Changeset 988 for vendor/current/source3/lib/sendfile.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/lib/sendfile.c
r740 r988 34 34 #endif 35 35 36 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_Toffset, size_t count)36 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count) 37 37 { 38 38 size_t total=0; … … 59 59 ssize_t nwritten; 60 60 do { 61 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)62 nwritten = sendfile64(tofd, fromfd, &offset, total);63 #else64 61 nwritten = sendfile(tofd, fromfd, &offset, total); 65 #endif66 #if defined(EWOULDBLOCK)67 62 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); 68 #else69 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN));70 #endif71 63 if (nwritten == -1) { 72 64 if (errno == ENOSYS || errno == EINVAL) { … … 94 86 } 95 87 96 #elif defined(LINUX_BROKEN_SENDFILE_API)97 98 /*99 * We must use explicit 32 bit types here. This code path means Linux100 * won't do proper 64-bit sendfile. JRA.101 */102 103 extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count);104 105 106 #ifndef MSG_MORE107 #define MSG_MORE 0x8000108 #endif109 110 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)111 {112 size_t total=0;113 ssize_t ret;114 ssize_t hdr_len = 0;115 uint32 small_total = 0;116 int32 small_offset;117 118 /*119 * Fix for broken Linux 2.4 systems with no working sendfile64().120 * If the offset+count > 2 GB then pretend we don't have the121 * system call sendfile at all. The upper layer catches this122 * and uses a normal read. JRA.123 */124 125 if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) {126 errno = ENOSYS;127 return -1;128 }129 130 /*131 * Send the header first.132 * Use MSG_MORE to cork the TCP output until sendfile is called.133 */134 135 if (header) {136 hdr_len = header->length;137 while (total < hdr_len) {138 ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);139 if (ret == -1)140 return -1;141 total += ret;142 }143 }144 145 small_total = (uint32)count;146 small_offset = (int32)offset;147 148 while (small_total) {149 int32 nwritten;150 do {151 nwritten = sendfile(tofd, fromfd, &small_offset, small_total);152 #if defined(EWOULDBLOCK)153 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));154 #else155 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN));156 #endif157 if (nwritten == -1) {158 if (errno == ENOSYS || errno == EINVAL) {159 /* Ok - we're in a world of pain here. We just sent160 * the header, but the sendfile failed. We have to161 * emulate the sendfile at an upper layer before we162 * disable it's use. So we do something really ugly.163 * We set the errno to a strange value so we can detect164 * this at the upper level and take care of it without165 * layer violation. JRA.166 */167 errno = EINTR; /* Normally we can never return this. */168 }169 return -1;170 }171 if (nwritten == 0) {172 /*173 * EOF, return a short read174 */175 return hdr_len + (((uint32)count) - small_total);176 }177 small_total -= nwritten;178 }179 return count + hdr_len;180 }181 182 183 88 #elif defined(SOLARIS_SENDFILE_API) 184 89 … … 189 94 #include <sys/sendfile.h> 190 95 191 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_Toffset, size_t count)96 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count) 192 97 { 193 98 int sfvcnt; … … 230 135 xferred = 0; 231 136 232 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64)233 nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred);234 #else235 137 nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); 236 #endif237 #if defined(EWOULDBLOCK)238 138 if (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) { 239 #else240 if (nwritten == -1 && (errno == EINTR || errno == EAGAIN)) {241 #endif242 139 if (xferred == 0) 243 140 continue; /* Nothing written yet. */ … … 279 176 #include <sys/uio.h> 280 177 281 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_Toffset, size_t count)178 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count) 282 179 { 283 180 size_t total=0; … … 308 205 309 206 do { 310 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)311 nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0);312 #else313 207 nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0); 314 #endif315 #if defined(EWOULDBLOCK)316 208 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); 317 #else318 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN));319 #endif320 209 if (nwritten == -1) 321 210 return -1; … … 348 237 } 349 238 350 #elif defined(FREEBSD_SENDFILE_API) 239 #elif defined(FREEBSD_SENDFILE_API) || defined(DARWIN_SENDFILE_API) 351 240 352 241 #include <sys/types.h> … … 354 243 #include <sys/uio.h> 355 244 356 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) 357 { 358 size_t total=0; 359 struct sf_hdtr hdr; 360 struct iovec hdtrl; 361 size_t hdr_len = 0; 362 363 hdr.headers = &hdtrl; 364 hdr.hdr_cnt = 1; 365 hdr.trailers = NULL; 366 hdr.trl_cnt = 0; 367 368 /* Set up the header iovec. */ 369 if (header) { 370 hdtrl.iov_base = (void *)header->data; 371 hdtrl.iov_len = hdr_len = header->length; 372 } else { 373 hdtrl.iov_base = NULL; 374 hdtrl.iov_len = 0; 375 } 376 377 total = count; 378 while (total + hdtrl.iov_len) { 379 SMB_OFF_T nwritten; 380 int ret; 381 382 /* 383 * FreeBSD sendfile returns 0 on success, -1 on error. 384 * Remember, the tofd and fromfd are reversed..... :-). 385 * nwritten includes the header data sent. 386 */ 387 388 do { 389 ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0); 390 #if defined(EWOULDBLOCK) 391 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); 245 ssize_t sys_sendfile(int tofd, int fromfd, 246 const DATA_BLOB *header, off_t offset, size_t count) 247 { 248 struct sf_hdtr sf_header = {0}; 249 struct iovec io_header = {0}; 250 251 off_t nwritten; 252 int ret; 253 254 if (header) { 255 sf_header.headers = &io_header; 256 sf_header.hdr_cnt = 1; 257 io_header.iov_base = header->data; 258 io_header.iov_len = header->length; 259 sf_header.trailers = NULL; 260 sf_header.trl_cnt = 0; 261 } 262 263 while (count != 0) { 264 265 nwritten = count; 266 #if defined(DARWIN_SENDFILE_API) 267 /* Darwin recycles nwritten as a value-result parameter, apart from that this 268 sendfile implementation is quite the same as the FreeBSD one */ 269 ret = sendfile(fromfd, tofd, offset, &nwritten, &sf_header, 0); 392 270 #else 393 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));271 ret = sendfile(fromfd, tofd, offset, count, &sf_header, &nwritten, 0); 394 272 #endif 395 if (ret == -1) 396 return -1; 397 398 if (nwritten == 0) 399 return -1; /* I think we're at EOF here... */ 400 401 /* 402 * If this was a short (signal interrupted) write we may need 403 * to subtract it from the header data, or null out the header 404 * data altogether if we wrote more than hdtrl.iov_len bytes. 405 * We change nwritten to be the number of file bytes written. 406 */ 407 408 if (hdtrl.iov_base && hdtrl.iov_len) { 409 if (nwritten >= hdtrl.iov_len) { 410 nwritten -= hdtrl.iov_len; 411 hdtrl.iov_base = NULL; 412 hdtrl.iov_len = 0; 273 if (ret == -1 && errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { 274 /* Send failed, we are toast. */ 275 return -1; 276 } 277 278 if (nwritten == 0) { 279 /* EOF of offset is after EOF. */ 280 break; 281 } 282 283 if (sf_header.hdr_cnt) { 284 if (io_header.iov_len <= nwritten) { 285 /* Entire header was sent. */ 286 sf_header.headers = NULL; 287 sf_header.hdr_cnt = 0; 288 nwritten -= io_header.iov_len; 413 289 } else { 414 hdtrl.iov_base = 415 (void *)((caddr_t)hdtrl.iov_base + nwritten); 416 hdtrl.iov_len -= nwritten; 290 /* Partial header was sent. */ 291 io_header.iov_len -= nwritten; 292 io_header.iov_base = 293 ((uint8_t *)io_header.iov_base) + nwritten; 417 294 nwritten = 0; 418 295 } 419 296 } 420 total -= nwritten; 297 421 298 offset += nwritten; 422 } 423 return count + hdr_len; 299 count -= nwritten; 300 } 301 302 return nwritten; 424 303 } 425 304 … … 431 310 #include <sys/socket.h> 432 311 433 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_Toffset, size_t count)312 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count) 434 313 { 435 314 struct sf_parms hdtrl; … … 470 349 do { 471 350 ret = send_file(&tofd, &hdtrl, 0); 472 #if defined(EWOULDBLOCK)473 351 } while ((ret == 1) || (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))); 474 #else475 } while ((ret == 1) || (ret == -1 && (errno == EINTR || errno == EAGAIN)));476 #endif477 352 if ( ret == -1 ) 478 353 return -1; … … 485 360 #else /* No sendfile implementation. Return error. */ 486 361 487 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_Toffset, size_t count)362 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count) 488 363 { 489 364 /* No sendfile syscall. */
Note:
See TracChangeset
for help on using the changeset viewer.