trawick 01/02/16 13:34:07
Modified: . CHANGES
network_io/unix sendrecv.c
Log:
Get apr_sendfile() working on HP-UX. This gets APR to build on
HP-UX without having to turn off APR_HAS_SENDFILE.
Revision Changes Path
1.61 +3 -0 apr/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr/CHANGES,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -r1.60 -r1.61
--- CHANGES 2001/02/16 05:50:49 1.60
+++ CHANGES 2001/02/16 21:34:02 1.61
@@ -1,5 +1,8 @@
Changes with APR b1
+ *) Get apr_sendfile() working on HP-UX. This gets APR to build on
+ HP-UX without having to turn off APR_HAS_SENDFILE. [Jeff Trawick]
+
*) Force FreeBSD to compile without threads by default. To enable
threads, use --enable-threads on the configure line.
[Ryan Bloom]
1.58 +97 -63 apr/network_io/unix/sendrecv.c
Index: sendrecv.c
===================================================================
RCS file: /home/cvs/apr/network_io/unix/sendrecv.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- sendrecv.c 2001/02/16 04:16:02 1.57
+++ sendrecv.c 2001/02/16 21:34:05 1.58
@@ -469,20 +469,30 @@
return APR_SUCCESS;
}
-#elif defined(__HPUX__)
+#elif defined(__hpux) || defined(__hpux__)
-#error "there's no way this apr_sendfile implementation works -djg"
+/* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */
-/* HP-UX Version 10.30 or greater */
-apr_status_t apr_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)
+/* HP-UX Version 10.30 or greater
+ * (no worries, because we only get here if autoconfiguration found sendfile)
+ */
+
+/* ssize_t sendfile(int s, int fd, off_t offset, size_t nbytes,
+ * const struct iovec *hdtrl, int flags);
+ *
+ * nbytes is the number of bytes to send just from the file; as with
FreeBSD,
+ * if nbytes == 0, the rest of the file (from offset) is sent
+ */
+
+apr_status_t apr_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)
{
- int i, ptr = 0;
- size_t nbytes = 0, headerlen = 0, trailerlen = 0;
- struct sf_hdtr headerstruct;
+ int i;
+ ssize_t rc;
+ size_t nbytes = *len, headerlen, trailerlen;
struct iovec hdtrarray[2];
- void *headerbuf, *trailerbuf;
+ char *headerbuf, *trailerbuf;
if (!hdtr) {
hdtr = &no_hdtr;
@@ -491,83 +501,107 @@
/* Ignore flags for now. */
flags = 0;
- /* HP-UX can only send one header iovec and one footer iovec */
-
- for (i = 0; i < hdtr->numheaders; i++) {
- headerlen += hdtr->headers[i].iov_len;
- }
-
- /* XXX: BUHHH? wow, what a memory leak! */
- headerbuf = apr_palloc(sock->cntxt, headerlen);
-
- for (i = 0; i < hdtr->numheaders; i++) {
- memcpy(headerbuf + ptr, hdtr->headers[i].iov_base,
- hdtr->headers[i].iov_len);
- ptr += hdtr->headers[i].iov_len;
- }
-
- for (i = 0; i < hdtr->numtrailers; i++) {
- trailerlen += hdtr->headers[i].iov_len;
+ /* HP-UX can only send one header iovec and one footer iovec; try to
+ * only allocate storage to combine input iovecs when we really have to
+ */
+
+ switch(hdtr->numheaders) {
+ case 0:
+ hdtrarray[0].iov_base = NULL;
+ hdtrarray[0].iov_len = 0;
+ break;
+ case 1:
+ hdtrarray[0] = hdtr->headers[0];
+ break;
+ default:
+ headerlen = 0;
+ for (i = 0; i < hdtr->numheaders; i++) {
+ headerlen += hdtr->headers[i].iov_len;
+ }
+
+ /* XXX: BUHHH? wow, what a memory leak! */
+ headerbuf = hdtrarray[0].iov_base = apr_palloc(sock->cntxt,
headerlen);
+ hdtrarray[0].iov_len = headerlen;
+
+ for (i = 0; i < hdtr->numheaders; i++) {
+ memcpy(headerbuf, hdtr->headers[i].iov_base,
+ hdtr->headers[i].iov_len);
+ headerbuf += hdtr->headers[i].iov_len;
+ }
}
- /* XXX: BUHHH? wow, what a memory leak! */
- trailerbuf = apr_palloc(sock->cntxt, trailerlen);
+ switch(hdtr->numtrailers) {
+ case 0:
+ hdtrarray[1].iov_base = NULL;
+ hdtrarray[1].iov_len = 0;
+ break;
+ case 1:
+ hdtrarray[1] = hdtr->trailers[0];
+ break;
+ default:
+ trailerlen = 0;
+ for (i = 0; i < hdtr->numtrailers; i++) {
+ trailerlen += hdtr->trailers[i].iov_len;
+ }
- for (i = 0; i < hdtr->numtrailers; i++) {
- memcpy(trailerbuf + ptr, hdtr->trailers[i].iov_base,
- hdtr->trailers[i].iov_len);
- ptr += hdtr->trailers[i].iov_len;
+ /* XXX: BUHHH? wow, what a memory leak! */
+ trailerbuf = hdtrarray[1].iov_base = apr_palloc(sock->cntxt,
trailerlen);
+ hdtrarray[1].iov_len = trailerlen;
+
+ for (i = 0; i < hdtr->numtrailers; i++) {
+ memcpy(trailerbuf, hdtr->trailers[i].iov_base,
+ hdtr->trailers[i].iov_len);
+ trailerbuf += hdtr->trailers[i].iov_len;
+ }
}
- hdtrarray[0].iov_base = headerbuf;
- hdtrarray[0].iov_len = headerlen;
- hdtrarray[1].iov_base = trailerbuf;
- hdtrarray[1].iov_len = trailerlen;
-
do {
- rv = sendfile(sock->socketdes, /* socket */
- file->filedes, /* file descriptor to send */
- *offset, /* where in the file to start */
- /* XXX: as far as i can see, nbytes == 0 always here -djg
*/
- nbytes, /* number of bytes to send */
- hdtrarray, /* Headers/footers */
- flags /* undefined, set to 0 */
- );
- } while (rv == -1 && errno == EINTR);
+ if (nbytes) { /* any bytes to send from the file? */
+ rc = sendfile(sock->socketdes, /* socket */
+ file->filedes, /* file descriptor to send */
+ *offset, /* where in the file to
start */
+ nbytes, /* number of bytes to send
from file */
+ hdtrarray, /* Headers/footers */
+ flags); /* undefined, set to 0 */
+ }
+ else { /* we can't call sendfile() for trailers only */
+ rc = write(sock->socketdes, hdtrarray[1].iov_base,
hdtrarray[1].iov_len);
+ }
+ } while (rc == -1 && errno == EINTR);
- if (rv == -1 &&
+ if (rc == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout > 0) {
apr_status_t arv = wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
- /* jlt: not tested, but this matches other sendfile logic */
- (*len) = 0;
+ *len = 0;
return arv;
}
else {
do {
- rv = sendfile(sock->socketdes, /* socket */
- file->filedes, /* file descriptor to send */
- *offset, /* where in the file to start */
- /* XXX: as far as i can see, nbytes == 0 always
here -djg */
- nbytes, /* number of bytes to send */
- hdtrarray, /* Headers/footers */
- flags /* undefined, set to 0 */
- );
- } while (rv == -1 && errno == EINTR);
+ if (nbytes) {
+ rc = sendfile(sock->socketdes, /* socket */
+ file->filedes, /* file descriptor to
send */
+ *offset, /* where in the file
to start */
+ nbytes, /* number of bytes to
send from file */
+ hdtrarray, /* Headers/footers */
+ flags); /* undefined, set to 0
*/
+ }
+ else { /* we can't call sendfile() for trailers only */
+ rc = write(sock->socketdes, hdtrarray[1].iov_base,
hdtrarray[1].iov_len);
+ }
+ } while (rc == -1 && errno == EINTR);
}
}
-
- if (rv == -1) {
+ if (rc == -1) {
*len = 0;
return errno;
}
-
/* Set len to the number of bytes written */
- (*len) = rv;
+ *len = rc;
return APR_SUCCESS;
}
#elif defined(_AIX) || defined(__MVS__)