00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029 #if defined(LINUX_SENDFILE_API)
00030
00031 #include <sys/sendfile.h>
00032
00033 #ifndef MSG_MORE
00034 #define MSG_MORE 0x8000
00035 #endif
00036
00037 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00038 {
00039 size_t total=0;
00040 ssize_t ret;
00041 size_t hdr_len = 0;
00042
00043
00044
00045
00046
00047
00048 if (header) {
00049 hdr_len = header->length;
00050 while (total < hdr_len) {
00051 ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
00052 if (ret == -1)
00053 return -1;
00054 total += ret;
00055 }
00056 }
00057
00058 total = count;
00059 while (total) {
00060 ssize_t nwritten;
00061 do {
00062 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
00063 nwritten = sendfile64(tofd, fromfd, &offset, total);
00064 #else
00065 nwritten = sendfile(tofd, fromfd, &offset, total);
00066 #endif
00067 } while (nwritten == -1 && errno == EINTR);
00068 if (nwritten == -1) {
00069 if (errno == ENOSYS) {
00070
00071
00072
00073
00074
00075
00076
00077
00078 errno = EINTR;
00079 }
00080 return -1;
00081 }
00082 if (nwritten == 0)
00083 return -1;
00084 total -= nwritten;
00085 }
00086 return count + hdr_len;
00087 }
00088
00089 #elif defined(LINUX_BROKEN_SENDFILE_API)
00090
00091
00092
00093
00094
00095
00096 extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count);
00097
00098
00099 #ifndef MSG_MORE
00100 #define MSG_MORE 0x8000
00101 #endif
00102
00103 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00104 {
00105 size_t total=0;
00106 ssize_t ret;
00107 ssize_t hdr_len = 0;
00108 uint32 small_total = 0;
00109 int32 small_offset;
00110
00111
00112
00113
00114
00115
00116
00117
00118 if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) {
00119 errno = ENOSYS;
00120 return -1;
00121 }
00122
00123
00124
00125
00126
00127
00128 if (header) {
00129 hdr_len = header->length;
00130 while (total < hdr_len) {
00131 ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
00132 if (ret == -1)
00133 return -1;
00134 total += ret;
00135 }
00136 }
00137
00138 small_total = (uint32)count;
00139 small_offset = (int32)offset;
00140
00141 while (small_total) {
00142 int32 nwritten;
00143 do {
00144 nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
00145 } while (nwritten == -1 && errno == EINTR);
00146 if (nwritten == -1) {
00147 if (errno == ENOSYS) {
00148
00149
00150
00151
00152
00153
00154
00155
00156 errno = EINTR;
00157 }
00158 return -1;
00159 }
00160 if (nwritten == 0)
00161 return -1;
00162 small_total -= nwritten;
00163 }
00164 return count + hdr_len;
00165 }
00166
00167
00168 #elif defined(SOLARIS_SENDFILE_API)
00169
00170
00171
00172
00173
00174 #include <sys/sendfile.h>
00175
00176 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00177 {
00178 int sfvcnt;
00179 size_t total, xferred;
00180 struct sendfilevec vec[2];
00181 ssize_t hdr_len = 0;
00182
00183 if (header) {
00184 sfvcnt = 2;
00185
00186 vec[0].sfv_fd = SFV_FD_SELF;
00187 vec[0].sfv_flag = 0;
00188 vec[0].sfv_off = (off_t)header->data;
00189 vec[0].sfv_len = hdr_len = header->length;
00190
00191 vec[1].sfv_fd = fromfd;
00192 vec[1].sfv_flag = 0;
00193 vec[1].sfv_off = offset;
00194 vec[1].sfv_len = count;
00195
00196 } else {
00197 sfvcnt = 1;
00198
00199 vec[0].sfv_fd = fromfd;
00200 vec[0].sfv_flag = 0;
00201 vec[0].sfv_off = offset;
00202 vec[0].sfv_len = count;
00203 }
00204
00205 total = count + hdr_len;
00206
00207 while (total) {
00208 ssize_t nwritten;
00209
00210
00211
00212
00213
00214
00215 xferred = 0;
00216
00217 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64)
00218 nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred);
00219 #else
00220 nwritten = sendfilev(tofd, vec, sfvcnt, &xferred);
00221 #endif
00222 if (nwritten == -1 && errno == EINTR) {
00223 if (xferred == 0)
00224 continue;
00225 else
00226 nwritten = xferred;
00227 }
00228
00229 if (nwritten == -1)
00230 return -1;
00231 if (nwritten == 0)
00232 return -1;
00233
00234
00235
00236
00237
00238
00239
00240
00241 if (sfvcnt == 2 && nwritten >= vec[0].sfv_len) {
00242 vec[1].sfv_off += nwritten - vec[0].sfv_len;
00243 vec[1].sfv_len -= nwritten - vec[0].sfv_len;
00244
00245
00246 vec[0] = vec[1];
00247 sfvcnt = 1;
00248 } else {
00249 vec[0].sfv_off += nwritten;
00250 vec[0].sfv_len -= nwritten;
00251 }
00252 total -= nwritten;
00253 }
00254 return count + hdr_len;
00255 }
00256
00257 #elif defined(HPUX_SENDFILE_API)
00258
00259 #include <sys/socket.h>
00260 #include <sys/uio.h>
00261
00262 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00263 {
00264 size_t total=0;
00265 struct iovec hdtrl[2];
00266 size_t hdr_len = 0;
00267
00268 if (header) {
00269
00270 hdtrl[0].iov_base = header->data;
00271 hdtrl[0].iov_len = hdr_len = header->length;
00272 } else {
00273 hdtrl[0].iov_base = NULL;
00274 hdtrl[0].iov_len = hdr_len = 0;
00275 }
00276 hdtrl[1].iov_base = NULL;
00277 hdtrl[1].iov_len = 0;
00278
00279 total = count;
00280 while (total + hdtrl[0].iov_len) {
00281 ssize_t nwritten;
00282
00283
00284
00285
00286
00287
00288
00289
00290 do {
00291 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
00292 nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0);
00293 #else
00294 nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0);
00295 #endif
00296 } while (nwritten == -1 && errno == EINTR);
00297 if (nwritten == -1)
00298 return -1;
00299 if (nwritten == 0)
00300 return -1;
00301
00302
00303
00304
00305
00306
00307
00308
00309 if (hdtrl[0].iov_base && hdtrl[0].iov_len) {
00310 if (nwritten >= hdtrl[0].iov_len) {
00311 nwritten -= hdtrl[0].iov_len;
00312 hdtrl[0].iov_base = NULL;
00313 hdtrl[0].iov_len = 0;
00314 } else {
00315
00316 hdtrl[0].iov_base = ((char *)hdtrl[0].iov_base) + nwritten;
00317 hdtrl[0].iov_len -= nwritten;
00318 nwritten = 0;
00319 }
00320 }
00321 total -= nwritten;
00322 offset += nwritten;
00323 }
00324 return count + hdr_len;
00325 }
00326
00327 #elif defined(FREEBSD_SENDFILE_API)
00328
00329 #include <sys/types.h>
00330 #include <sys/socket.h>
00331 #include <sys/uio.h>
00332
00333 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00334 {
00335 size_t total=0;
00336 struct sf_hdtr hdr;
00337 struct iovec hdtrl;
00338 size_t hdr_len = 0;
00339
00340 hdr.headers = &hdtrl;
00341 hdr.hdr_cnt = 1;
00342 hdr.trailers = NULL;
00343 hdr.trl_cnt = 0;
00344
00345
00346 if (header) {
00347 hdtrl.iov_base = header->data;
00348 hdtrl.iov_len = hdr_len = header->length;
00349 } else {
00350 hdtrl.iov_base = NULL;
00351 hdtrl.iov_len = 0;
00352 }
00353
00354 total = count;
00355 while (total + hdtrl.iov_len) {
00356 SMB_OFF_T nwritten;
00357 int ret;
00358
00359
00360
00361
00362
00363
00364
00365 do {
00366 ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0);
00367 } while (ret == -1 && errno == EINTR);
00368 if (ret == -1)
00369 return -1;
00370
00371 if (nwritten == 0)
00372 return -1;
00373
00374
00375
00376
00377
00378
00379
00380
00381 if (hdtrl.iov_base && hdtrl.iov_len) {
00382 if (nwritten >= hdtrl.iov_len) {
00383 nwritten -= hdtrl.iov_len;
00384 hdtrl.iov_base = NULL;
00385 hdtrl.iov_len = 0;
00386 } else {
00387 hdtrl.iov_base += nwritten;
00388 hdtrl.iov_len -= nwritten;
00389 nwritten = 0;
00390 }
00391 }
00392 total -= nwritten;
00393 offset += nwritten;
00394 }
00395 return count + hdr_len;
00396 }
00397
00398 #elif defined(AIX_SENDFILE_API)
00399
00400
00401
00402
00403 #include <sys/socket.h>
00404
00405 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00406 {
00407 struct sf_parms hdtrl;
00408
00409
00410 if (header) {
00411 hdtrl.header_data = header->data;
00412 hdtrl.header_length = header->length;
00413 } else {
00414 hdtrl.header_data = NULL;
00415 hdtrl.header_length = 0;
00416 }
00417 hdtrl.trailer_data = NULL;
00418 hdtrl.trailer_length = 0;
00419
00420 hdtrl.file_descriptor = fromfd;
00421 hdtrl.file_offset = offset;
00422 hdtrl.file_bytes = count;
00423
00424 while ( hdtrl.file_bytes + hdtrl.header_length ) {
00425 ssize_t ret;
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 do {
00443 ret = send_file(&tofd, &hdtrl, 0);
00444 } while ( (ret == 1) || (ret == -1 && errno == EINTR) );
00445 if ( ret == -1 )
00446 return -1;
00447 }
00448
00449 return count + header->length;
00450 }
00451
00452
00453 #else
00454
00455 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
00456 {
00457
00458 errno = ENOSYS;
00459 return -1;
00460 }
00461 #endif