You are viewing a plain text version of this content. The canonical link for it is here.
Posted to apreq-cvs@httpd.apache.org by jo...@apache.org on 2005/03/13 03:26:10 UTC

svn commit: r157308 - in httpd/apreq/branches/multi-env-unstable: include/apreq_util.h library/util.c

Author: joes
Date: Sat Mar 12 18:26:09 2005
New Revision: 157308

URL: http://svn.apache.org/viewcvs?view=rev&rev=157308
Log:
This patch includes two components:

  1) Max Kellermann's rewrite of apreq_fwrite
     which removes the recursion, and eliminates
     the possibility of a "successful zero-byte-write" 
     infinite loop.

  2) Define a copy method for SPOOL buckets.  It's
     clear from the perl glue's $upload->io() implementation 
     that on a copy, the original bucket stays a SPOOL
     while the copy becomes an ordinary file bucket.

Modified:
    httpd/apreq/branches/multi-env-unstable/include/apreq_util.h
    httpd/apreq/branches/multi-env-unstable/library/util.c

Modified: httpd/apreq/branches/multi-env-unstable/include/apreq_util.h
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/include/apreq_util.h?view=diff&r1=157307&r2=157308
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/include/apreq_util.h (original)
+++ httpd/apreq/branches/multi-env-unstable/include/apreq_util.h Sat Mar 12 18:26:09 2005
@@ -297,7 +297,7 @@
          e = APR_BUCKET_NEXT(e))
     {
         apr_bucket *c;
-        apr_bucket_copy(e, &c);
+        apr_bucket_copy(e, &c); /*XXX may fail! */
         APR_BRIGADE_INSERT_TAIL(d, c);
     }
 }

Modified: httpd/apreq/branches/multi-env-unstable/library/util.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/util.c?view=diff&r1=157307&r2=157308
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/util.c (original)
+++ httpd/apreq/branches/multi-env-unstable/library/util.c Sat Mar 12 18:26:09 2005
@@ -501,42 +501,50 @@
 static apr_status_t apreq_fwritev(apr_file_t *f, struct iovec *v, 
                                   int *nelts, apr_size_t *bytes_written)
 {
-    apr_size_t len, bytes_avail = 0;
-    int n = *nelts;
-    apr_status_t s = apr_file_writev(f, v, n, &len);
+    apr_size_t len;
+    int n;
+    apr_status_t s;
 
-    *bytes_written = len;
+    *bytes_written = 0;
 
-    if (s != APR_SUCCESS)
-        return s;
+    while (1) {
+        /* try to write */
+        s = apr_file_writev(f, v, *nelts, &len);
 
-    while (--n >= 0 && bytes_avail <= len)
-        bytes_avail += v[n].iov_len;
+        *bytes_written += len;
 
+        if (s != APR_SUCCESS)
+            return s;
 
-    if (bytes_avail > len) {
-        /* incomplete write: must shift v */
+        /* see how far we've come */
         n = 0;
-        while (v[n].iov_len <= len) {
-            len -= v[n].iov_len;
-            ++n;
+        while (n < *nelts && len >= v[n].iov_len)
+            len -= v[n++].iov_len;
+
+        if (n == *nelts) {
+            /* nothing left to write, report success */
+            *nelts = 0;
+            return APR_SUCCESS;
         }
+
+        /* incomplete write: must shift v */
         v[n].iov_len -= len;
         v[n].iov_base = (char *)(v[n].iov_base) + len;
 
         if (n > 0) {
+            /* we're satisfied for now if we can remove one iovec from
+               the "v" array */
             (*nelts) -= n;
             memmove(v, v + n, sizeof(*v) * *nelts);
+
+            return APR_SUCCESS;
         }
-        else {
-            s = apreq_fwritev(f, v, nelts, &len);
-            *bytes_written += len;
-        }
-    }
-    else
-        *nelts = 0;
 
-    return s;
+        /* we're still in the first iovec - check for endless loop,
+           and then try again */
+        if (len == 0)
+            return APREQ_ERROR_GENERAL;
+    }
 }
 
 
@@ -757,13 +765,21 @@
     return rv;
 }
 
+static
+apr_status_t spool_bucket_copy(apr_bucket *e, apr_bucket **c)
+{
+    apr_status_t rv = apr_bucket_shared_copy(e, c);
+    (*c)->type = &apr_bucket_type_file;
+    return rv;
+}
+
 static const apr_bucket_type_t spool_bucket_type = {
     "APREQ_SPOOL", 5, APR_BUCKET_DATA,
     spool_bucket_destroy,
     spool_bucket_read,
     spool_bucket_setaside,
     spool_bucket_split,
-    apr_bucket_copy_notimpl,
+    spool_bucket_copy,
 };
 
 APREQ_DECLARE(apr_file_t *)apreq_brigade_spoolfile(apr_bucket_brigade *bb)