diff --git a/include/lighttpd/network.h b/include/lighttpd/network.h index 5543e94..5de59ea 100644 --- a/include/lighttpd/network.h +++ b/include/lighttpd/network.h @@ -5,7 +5,7 @@ #error Please include instead of this file #endif -#if defined(USE_LINUX_SENDFILE) || defined(USE_FREEBSD_SENDFILE) || defined(USE_SOLARIS_SENDFILEV) +#if defined(USE_LINUX_SENDFILE) || defined(USE_FREEBSD_SENDFILE) || defined(USE_SOLARIS_SENDFILEV) || defined(USE_OSX_SENDFILE) # define USE_SENDFILE #endif diff --git a/src/network_sendfile.c b/src/network_sendfile.c index 9ab77b8..a912925 100644 --- a/src/network_sendfile.c +++ b/src/network_sendfile.c @@ -47,17 +47,24 @@ static network_sendfile_result lighty_sendfile(vrequest *vr, int fd, int filefd, #elif defined(USE_FREEBSD_SENDFILE) static network_sendfile_result lighty_sendfile(vrequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote) { - off_t file_offset = offset; off_t r = 0; - while (-1 == sendfile(filefd, fd, file_offset, len, NULL, &r, 0)) { + while (-1 == sendfile(filefd, fd, offset, len, NULL, &r, 0)) { switch (errno) { case EAGAIN: + if (r) { + *wrote = r; + return NSR_SUCCSES; + } return NSR_WAIT_FOR_EVENT; case ENOTCONN: case EPIPE: return NSR_CLOSE; case EINTR: + if (r) { + *wrote = r; + return NSR_SUCCSES; + } break; /* try again */ case EINVAL: case EOPNOTSUPP: @@ -103,6 +110,42 @@ static network_sendfile_result lighty_sendfile(vrequest *vr, int fd, int filefd, return NSR_SUCCESS; } +#elif defined(USE_OSX_SENDFILE) + +static network_sendfile_result lighty_sendfile(vrequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote) { + off_t bytes = len; + + while (-1 == sendfile(filefd, fd, offset, &bytes, NULL, 0)) { + switch (errno) { + case EAGAIN: + if (bytes) { + *wrote = bytes; + return NSR_SUCCSES; + } + return NSR_WAIT_FOR_EVENT; + case ENOTCONN: + case EPIPE: + return NSR_CLOSE; + case EINTR: + if (bytes) { + *wrote = bytes; + return NSR_SUCCSES; + } + break; /* try again */ + case ENOTSUP: + case EOPNOTSUPP: + case ENOTSOCK: + /* TODO: print a warning? */ + return NSR_FALLBACK; + default: + VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno)); + return NSR_FATAL_ERROR; + } + } + *wrote = bytes; + return NSR_SUCCESS; +} + #endif