From de6fc7a06ae7ffe65cdbe8885c8be50d6147fce2 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 31 Oct 2007 16:12:01 +0000 Subject: [PATCH] small fix to apr for OS X 10.5 for sendfile git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6096 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/apr/network_io/unix/sendrecv.c | 118 +++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/libs/apr/network_io/unix/sendrecv.c b/libs/apr/network_io/unix/sendrecv.c index 8da404921b..eedf481c15 100644 --- a/libs/apr/network_io/unix/sendrecv.c +++ b/libs/apr/network_io/unix/sendrecv.c @@ -148,6 +148,8 @@ apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, apr_size_t *len) { apr_ssize_t rv; + + from->salen = sizeof(from->sa); do { rv = recvfrom(sock->socketdes, buf, (*len), flags, @@ -172,6 +174,8 @@ apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, return errno; } + apr_sockaddr_vars_set(from, from->sa.sin.sin_family, ntohs(from->sa.sin.sin_port)); + (*len) = rv; if (rv == 0 && sock->type == SOCK_STREAM) { return APR_EOF; @@ -399,6 +403,109 @@ do_select: return rv < 0 ? errno : APR_SUCCESS; } +#elif defined(DARWIN) + +/* OS/X Release 10.5 or greater */ +apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file, + apr_hdtr_t * hdtr, apr_off_t * offset, + apr_size_t * len, apr_int32_t flags) +{ + apr_off_t nbytes = *len; + int rv; + struct sf_hdtr headerstruct; + + /* Ignore flags for now. */ + flags = 0; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + headerstruct.headers = hdtr->headers; + headerstruct.hdr_cnt = hdtr->numheaders; + headerstruct.trailers = hdtr->trailers; + headerstruct.trl_cnt = hdtr->numtrailers; + + /* BSD can send the headers/footers as part of the system call */ + do { + if (sock->options & APR_INCOMPLETE_WRITE) { + apr_status_t arv; + sock->options &= ~APR_INCOMPLETE_WRITE; + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + if (nbytes) { + /* We won't dare call sendfile() if we don't have + * header or file bytes to send because nbytes == 0 + * means send the remaining file to EOF. + */ + rv = sendfile(file->filedes, /* file to be sent */ + sock->socketdes, /* socket */ + *offset, /* where in the file to start */ + &nbytes, /* number of bytes to write/written */ + &headerstruct, /* Headers/footers */ + flags); /* undefined, set to 0 */ + + if (rv == -1) { + if (errno == EAGAIN) { + if (sock->timeout > 0) { + sock->options |= APR_INCOMPLETE_WRITE; + } + /* BSD's sendfile can return -1/EAGAIN even if it + * sent bytes. Sanitize the result so we get normal EAGAIN + * semantics w.r.t. bytes sent. + */ + if (nbytes) { + /* normal exit for a big file & non-blocking io */ + (*len) = nbytes; + return APR_SUCCESS; + } + } + } + else { /* rv == 0 (or the kernel is broken) */ + if (nbytes == 0) { + /* Most likely the file got smaller after the stat. + * Return an error so the caller can do the Right Thing. + */ + (*len) = nbytes; + return APR_EOF; + } + } + } + else { + /* just trailer bytes... use writev() + */ + rv = writev(sock->socketdes, + hdtr->trailers, + hdtr->numtrailers); + if (rv > 0) { + nbytes = rv; + rv = 0; + } + else { + nbytes = 0; + } + } + if ((rv == -1) && (errno == EAGAIN) + && (sock->timeout > 0)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + } while (rv == -1 && (errno == EINTR || errno == EAGAIN)); + + (*len) = nbytes; + if (rv == -1) { + return errno; + } + return APR_SUCCESS; +} + #elif defined(__FreeBSD__) || defined(__DragonFly__) /* Release 3.1 or greater */ @@ -407,7 +514,10 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file, apr_size_t * len, apr_int32_t flags) { off_t nbytes = 0; - int rv, i; + int rv; +#if defined(__FreeBSD_version) && __FreeBSD_version < 460001 + int i; +#endif struct sf_hdtr headerstruct; apr_size_t bytes_to_send = *len; @@ -872,7 +982,9 @@ apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, for (i = 0; i < hdtr->numheaders; i++, curvec++) { sfv[curvec].sfv_fd = SFV_FD_SELF; sfv[curvec].sfv_flag = 0; - sfv[curvec].sfv_off = (apr_off_t)hdtr->headers[i].iov_base; + /* Cast to unsigned long to prevent sign extension of the + * pointer value for the LFS case; see PR 39463. */ + sfv[curvec].sfv_off = (unsigned long)hdtr->headers[i].iov_base; sfv[curvec].sfv_len = hdtr->headers[i].iov_len; requested_len += sfv[curvec].sfv_len; } @@ -896,7 +1008,7 @@ apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, for (i = 0; i < hdtr->numtrailers; i++, curvec++) { sfv[curvec].sfv_fd = SFV_FD_SELF; sfv[curvec].sfv_flag = 0; - sfv[curvec].sfv_off = (apr_off_t)hdtr->trailers[i].iov_base; + sfv[curvec].sfv_off = (unsigned long)hdtr->trailers[i].iov_base; sfv[curvec].sfv_len = hdtr->trailers[i].iov_len; requested_len += sfv[curvec].sfv_len; }