1#include "network_backends.h" 2 3#if defined(USE_DARWIN_SENDFILE) 4 5#include "network.h" 6#include "log.h" 7 8#include <sys/types.h> 9#include <sys/socket.h> 10#include <sys/uio.h> 11 12#include <errno.h> 13#include <string.h> 14 15int network_write_file_chunk_sendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes) { 16 chunk* const c = cq->first; 17 off_t offset, written = 0; 18 off_t toSend; 19 int r; 20 21 force_assert(NULL != c); 22 force_assert(FILE_CHUNK == c->type); 23 force_assert(c->offset >= 0 && c->offset <= c->file.length); 24 25 offset = c->file.start + c->offset; 26 toSend = c->file.length - c->offset; 27 if (toSend > *p_max_bytes) toSend = *p_max_bytes; 28 29 if (0 == toSend) { 30 chunkqueue_remove_finished_chunks(cq); 31 return 0; 32 } 33 34 if (0 != network_open_file_chunk(srv, con, cq)) return -1; 35 36 /* Darwin sendfile() */ 37 written = toSend; 38 if (-1 == (r = sendfile(c->file.fd, fd, offset, &written, NULL, 0))) { 39 switch(errno) { 40 case EAGAIN: 41 case EINTR: 42 /* for EAGAIN/EINTR written still contains the sent bytes */ 43 break; /* try again later */ 44 case EPIPE: 45 case ENOTCONN: 46 return -2; 47 default: 48 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno); 49 return -1; 50 } 51 } 52 53 if (written >= 0) { 54 chunkqueue_mark_written(cq, written); 55 *p_max_bytes -= written; 56 } 57 58 return (r >= 0 && written == toSend) ? 0 : -3; 59} 60 61#endif /* USE_DARWIN_SENDFILE */ 62