ALT Linux repositórios
S: | 1.7.0-alt4 |
D: | 1.2.12-alt2.1 |
5.0: | 1.4.6-alt0.M51.1 |
4.1: | 1.2.12-alt2 |
4.0: | 1.2.8-alt1.2 |
+updates: | 1.2.8-alt1.2 |
Group :: Sistema/Bibliotecas
RPM: apr1
Main Changelog Spec Patches Sources Download Gear Bugs e FR Repocop
Patch: apr-1.4.4-alt-015_sendfile_lfs.dpatch
Download
Download
network_io/unix/sendrecv.c | 96 +++++++++++++++++++++++++++++--------------
1 files changed, 65 insertions(+), 31 deletions(-)
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c
index c133a26..d15ed69 100644
--- a/network_io/unix/sendrecv.c
+++ b/network_io/unix/sendrecv.c
@@ -247,39 +247,77 @@ static apr_hdtr_t no_hdtr;
#if defined(__linux__) && defined(HAVE_WRITEV)
-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)
+/* Helper function for apr_socket_sendfile.
+ * Takes care of sendfile vs. sendfile64 (must be detected at runtime),
+ * EINTR restarting, and other details. NOTE: does not necessarily
+ * update 'off', as callers don't need this.
+ */
+static
+ssize_t do_sendfile(int out, int in, apr_off_t *off, apr_size_t len)
{
- int rv, nbytes = 0, total_hdrbytes, i;
- apr_status_t arv;
+#if !APR_HAS_LARGE_FILES
+ ssize_t ret;
+ do
+ ret = sendfile(out, in, off, len);
+ while (ret == -1 && errno == EINTR);
+ return ret;
+#else
-#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64)
- apr_off_t off = *offset;
-#define sendfile sendfile64
+#ifdef HAVE_SENDFILE64
+ static int sendfile64_enosys; /* sendfile64() syscall not found */
+#endif
+ off_t offtmp;
+ ssize_t ret;
-#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
- /* 64-bit apr_off_t but no sendfile64(): fail if trying to send
- * past the 2Gb limit. */
- off_t off;
-
- if ((apr_int64_t)*offset + *len > INT_MAX) {
- return EINVAL;
+ /* Multiple reports have shown sendfile failing with EINVAL if
+ * passed a >=2Gb count value on some 64-bit kernels. It won't
+ * noticably hurt performance to limit each call to <2Gb at a time,
+ * so avoid that issue here. (Round down to a common page size.) */
+ if (sizeof(off_t) == 8 && len > INT_MAX)
+ len = INT_MAX - 8191;
+
+ /* The simple and common case: we don't cross the LFS barrier */
+ if (sizeof(off_t) == 8 || (apr_int64_t)*off + len <= INT_MAX) {
+ offtmp = *off;
+ do
+ ret = sendfile(out, in, &offtmp, len);
+ while (ret == -1 && errno == EINTR);
+ return ret;
}
-
- off = *offset;
-#else
- off_t off = *offset;
+ /* From here down we know it's a 32-bit runtime */
+#ifdef HAVE_SENDFILE64
+ if (!sendfile64_enosys) {
+ do
+ ret = sendfile64(out, in, off, len);
+ while (ret == -1 && errno == EINTR);
- /* Multiple reports have shown sendfile failing with EINVAL if
- * passed a >=2Gb count value on some 64-bit kernels. It won't
- * noticably hurt performance to limit each call to <2Gb at a
- * time, so avoid that issue here: */
- if (sizeof(off_t) == 8 && *len > INT_MAX) {
- *len = INT_MAX;
+ if (ret != -1 || errno != ENOSYS)
+ return ret;
+
+ sendfile64_enosys = 1;
}
#endif
+ if (*off > INT_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+ offtmp = *off;
+ do
+ ret = sendfile(out, in, &offtmp, len);
+ while (ret == -1 && errno == EINTR);
+ return ret;
+#endif /* APR_HAS_LARGE_FILES */
+}
+
+
+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)
+{
+ int rv, nbytes = 0, total_hdrbytes, i;
+ apr_status_t arv;
+ apr_off_t off = *offset;
if (!hdtr) {
hdtr = &no_hdtr;
@@ -325,12 +363,10 @@ apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
goto do_select;
}
- do {
- rv = sendfile(sock->socketdes, /* socket */
+ rv = do_sendfile(sock->socketdes, /* socket */
file->filedes, /* open file descriptor of the file to be sent */
&off, /* where in the file to start */
*len); /* number of bytes to send */
- } while (rv == -1 && errno == EINTR);
while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
&& (sock->timeout > 0)) {
@@ -341,12 +377,10 @@ do_select:
return arv;
}
else {
- do {
- rv = sendfile(sock->socketdes, /* socket */
+ rv = do_sendfile(sock->socketdes, /* socket */
file->filedes, /* open file descriptor of the file to be sent */
&off, /* where in the file to start */
*len); /* number of bytes to send */
- } while (rv == -1 && errno == EINTR);
}
}