- while (written < length) {
- len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
-
- if (len < 0) {
- if (errno == EINTR)
- continue;
- if (errno == EINVAL || errno == ENOSYS)
- return -1;
-
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- if (dsi_peek(dsi)) {
- /* can't go back to blocking mode, exit, the next read
- will return with an error and afpd will die.
- */
- break;
- }
- continue;
- }
- LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno));
- break;
- }
- else if (!len) {
- /* afpd is going to exit */
- errno = EIO;
- return -1; /* I think we're at EOF here... */
- }
- else
+ while (written < total) {
+#ifdef HAVE_SENDFILEV
+ nwritten = 0;
+ len = sendfilev(dsi->socket, vec, sfvcnt, &nwritten);
+#else
+ len = sys_sendfile(dsi->socket, fromfd, &pos, total - written);
+#endif
+ if (len < 0) {
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+ len = 0;
+#ifdef HAVE_SENDFILEV
+ len = (size_t)nwritten;
+#else
+#if defined(SOLARIS) || defined(FREEBSD)
+ 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) {
+ ret = -1;
+ goto exit;
+ }
+ break;
+ default:
+ LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+ } else if (len == 0) {
+ /* afpd is going to exit */
+ ret = -1;
+ goto exit;
+ }
+#ifdef HAVE_SENDFILEV
+ if (sfvcnt == 2 && len >= vec[0].sfv_len) {
+ vec[1].sfv_off += len - vec[0].sfv_len;
+ vec[1].sfv_len -= len - vec[0].sfv_len;
+
+ vec[0] = vec[1];
+ sfvcnt = 1;
+ } else {
+ vec[0].sfv_off += len;
+ vec[0].sfv_len -= len;
+ }
+#endif /* HAVE_SENDFILEV */
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: wrote: %zd", len);