2 * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice(s), this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified other than the possible
11 * addition of one or more copyright notices.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice(s), this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/fcntl.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
38 #include "pthread_private.h"
40 __weak_reference(_sendfile, sendfile);
43 _sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr,
44 off_t *sbytes, int flags)
46 struct pthread *curthread = _get_curthread();
49 ssize_t wvret, num = 0;
50 off_t n, nwritten = 0;
53 * Write the headers if any.
54 * If some data is written but not all we must return here.
56 if ((hdtr != NULL) && (hdtr->headers != NULL)) {
57 if ((wvret = writev(s, hdtr->headers, hdtr->hdr_cnt)) == -1) {
66 for (i = 0, hdrtot = 0; i < hdtr->hdr_cnt; i++)
67 hdrtot += hdtr->headers[i].iov_len;
73 /* Lock the descriptors. */
74 if ((ret = _FD_LOCK(fd, FD_READ, NULL)) != 0) {
79 if ((ret = _FD_LOCK(s, FD_WRITE, NULL)) != 0) {
85 /* Check the descriptor access modes. */
86 type = _thread_fd_getflags(fd) & O_ACCMODE;
87 if (type != O_RDONLY && type != O_RDWR) {
88 /* File is not open for read. */
93 type = _thread_fd_getflags(s) & O_ACCMODE;
94 if (type != O_WRONLY && type != O_RDWR) {
95 /* File is not open for write. */
101 /* Check if file operations are to block */
102 blocking = ((_thread_fd_getflags(s) & O_NONBLOCK) == 0);
105 * Loop while no error occurs and until the expected number of bytes are
109 /* Perform a non-blocking sendfile syscall. */
110 ret = __sys_sendfile(fd, s, offset + num, nbytes - num,
114 * We have to handle the sideways return path of sendfile.
116 * If the result is 0, we're done.
117 * If the result is anything else check the errno.
118 * If the errno is not EGAIN return the error.
119 * Otherwise, take into account how much
120 * sendfile may have written for us because sendfile can
121 * return EAGAIN even though it has written data.
123 * We don't clear 'ret' because the sendfile(2) syscall
124 * would not have either.
127 /* Writing completed. */
130 } else if ((ret == -1) && (errno == EAGAIN)) {
132 * Some bytes were written but there are still more to
136 /* Update the count of bytes written. */
140 * If we're not blocking then return.
143 _FD_UNLOCK(s, FD_WRITE);
144 _FD_UNLOCK(fd, FD_READ);
149 * Otherwise wait on the fd.
151 curthread->data.fd.fd = fd;
152 _thread_kern_set_timeout(NULL);
154 /* Reset the interrupted operation flag. */
155 curthread->interrupted = 0;
157 _thread_kern_sched_state(PS_FDW_WAIT, __FILE__,
160 if (curthread->interrupted) {
161 /* Interrupted by a signal. Return an error. */
165 /* Incomplete non-blocking syscall, or error. */
171 _FD_UNLOCK(s, FD_WRITE);
173 _FD_UNLOCK(fd, FD_READ);
176 /* Write the trailers, if any. */
177 if ((hdtr != NULL) && (hdtr->trailers != NULL)) {
178 if ((wvret = writev(s, hdtr->trailers, hdtr->trl_cnt))
186 if (sbytes != NULL) {
188 * Number of bytes written in headers/trailers, plus in the main
191 *sbytes = nwritten + num;