From: Frank Lahm Date: Fri, 15 Mar 2013 08:19:40 +0000 (+0100) Subject: Use FreeBSD sendfile() capability to send protocol header X-Git-Url: https://arthur.barton.de/gitweb/?p=netatalk.git;a=commitdiff_plain;h=fa5fcf44a4a5498a3083a24985c98ffb42fbce9c Use FreeBSD sendfile() capability to send protocol header When transmitting file contents to a client with sendfile(), on every platform other then Solaris (where we use sendfilev()), we send the AFP the protocol header with an additional send with MSG_MORE before calling sendfile(). FreeBSD sendfile() supports sending protocol header (and trailer) data similarly to Solaris sendfilev(). --- diff --git a/NEWS b/NEWS index 5456a411..3fe240b2 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,8 @@ Changes in 3.0.3 * FIX: Permissions of ._ AppleDouble ressource fork after conversion from v2 to ea. Fixes bug #505. +* UPD: Use FreeBSD sendfile() capability to send protocol header. + From FR #75. Changes in 3.0.2 ================ diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 7f5487ee..577cd471 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -798,7 +798,7 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si "afp_read(fork: %" PRIu16 " [%s], off: %" PRIu64 ", len: %" PRIu64 ", size: %" PRIu64 ")", ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "reso", offset, reqcount, size); - if (offset > size) { + if (offset >= size) { err = AFPERR_EOF; goto afp_read_err; } diff --git a/libatalk/dsi/dsi_stream.c b/libatalk/dsi/dsi_stream.c index da58f87c..7579e252 100644 --- a/libatalk/dsi/dsi_stream.c +++ b/libatalk/dsi/dsi_stream.c @@ -344,6 +344,16 @@ ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const siz int sfvcnt; struct sendfilevec vec[2]; ssize_t nwritten; +#elif defined(FREEBSD) + ssize_t nwritten; + void *hdrp; + struct sf_hdtr hdr; + struct iovec iovec; + hdr.headers = &iovec; + hdr.hdr_cnt = 1; + hdr.trailers = NULL; + hdr.trl_cnt = 0; + hdrp = &hdr; #endif LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file(off: %jd, len: %zu)", (intmax_t)offset, length); @@ -372,6 +382,9 @@ ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const siz vec[1].sfv_flag = 0; vec[1].sfv_off = offset; vec[1].sfv_len = length; +#elif defined(FREEBSD) + iovec.iov_base = block; + iovec.iov_len = DSI_BLOCKSIZ; #else dsi_stream_write(dsi, block, sizeof(block), DSI_MSG_MORE); #endif @@ -380,6 +393,10 @@ ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const siz #ifdef HAVE_SENDFILEV nwritten = 0; len = sendfilev(dsi->socket, vec, sfvcnt, &nwritten); +#elif defined(FREEBSD) + len = sendfile(fromfd, dsi->socket, pos, total - written, hdrp, &nwritten, 0); + if (len == 0) + len = nwritten; #else len = sys_sendfile(dsi->socket, fromfd, &pos, total - written); #endif @@ -388,16 +405,14 @@ ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const siz case EINTR: case EAGAIN: len = 0; -#ifdef HAVE_SENDFILEV +#if defined(HAVE_SENDFILEV) || defined(FREEBSD) len = (size_t)nwritten; -#else -#if defined(SOLARIS) || defined(FREEBSD) +#elif defined(SOLARIS) if (pos > offset) { /* we actually have sent sth., adjust counters and keep trying */ len = pos - offset; offset = pos; } -#endif /* defined(SOLARIS) || defined(FREEBSD) */ #endif /* HAVE_SENDFILEV */ if (dsi_peek(dsi) != 0) { @@ -426,6 +441,18 @@ ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const siz vec[0].sfv_off += len; vec[0].sfv_len -= len; } +#elif defined(FREEBSD) + if (hdrp) { + if (len >= iovec.iov_len) { + hdrp = NULL; + len -= iovec.iov_len; /* len now contains how much sendfile() actually sent from the file */ + } else { + iovec.iov_len -= len; + iovec.iov_base += len; + len = 0; + } + } + pos += len; #endif /* HAVE_SENDFILEV */ LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: wrote: %zd", len); written += len;