[Pkg-apache-commits] r1097 - in /trunk/apache2: apache2.2-common.postinst changelog patches/00list patches/073_mod_dav_trunk_fixes.dpatch

sf at alioth.debian.org sf at alioth.debian.org
Wed Nov 11 22:25:27 UTC 2009


Author: sf
Date: Wed Nov 11 22:25:27 2009
New Revision: 1097

URL: http://svn.debian.org/wsvn/pkg-apache/?sc=1&rev=1097
Log:
various DAV fixes from upstream trunk

Added:
    trunk/apache2/patches/073_mod_dav_trunk_fixes.dpatch
Modified:
    trunk/apache2/apache2.2-common.postinst
    trunk/apache2/changelog
    trunk/apache2/patches/00list

Modified: trunk/apache2/apache2.2-common.postinst
URL: http://svn.debian.org/wsvn/pkg-apache/trunk/apache2/apache2.2-common.postinst?rev=1097&op=diff
==============================================================================
--- trunk/apache2/apache2.2-common.postinst (original)
+++ trunk/apache2/apache2.2-common.postinst Wed Nov 11 22:25:27 2009
@@ -67,6 +67,11 @@
 	fi
 fi
 
+# DavLockDB format change
+if dpkg --compare-versions "$2" lt 2.2.14-3~; then
+	rm -f /var/lock/apache2/DAVLock.dir /var/lock/apache2/DAVLock.pag
+fi
+
 rm -f /etc/apache2/ports.conf.dpkg-apache2.2-common.old
 rm -f /etc/default/apache2.dpkg-apache2.2-common.old
 rm -f /etc/apache2/conf.d/charset.dpkg-apache2.2-common.old

Modified: trunk/apache2/changelog
URL: http://svn.debian.org/wsvn/pkg-apache/trunk/apache2/changelog?rev=1097&op=diff
==============================================================================
--- trunk/apache2/changelog (original)
+++ trunk/apache2/changelog Wed Nov 11 22:25:27 2009
@@ -1,5 +1,12 @@
-apache2 (2.2.14-4) UNRELEASED; urgency=low
-
+apache2 (2.2.14-3) UNRELEASED; urgency=low
+
+  * Backport various mod_dav/mod_dav_fs fixes from upstream trunk svn. This
+    includes:
+    - Make PUT replace files atomically (closes: #525137).
+    - Make MOVE not delete the destination if the source file disappeared in
+      the meantime (closes: #273476).
+    NOTE: The format of the DavLockDB has changed. The default DavLockDB will
+    be deleted on upgrade. Non-default DavLockDBs should be deleted manually.
   * Fix output of "/etc/init.d/apache2 status" (closes: #555687).
   * Set redirect-carefully for Konqueror/4.
 

Modified: trunk/apache2/patches/00list
URL: http://svn.debian.org/wsvn/pkg-apache/trunk/apache2/patches/00list?rev=1097&op=diff
==============================================================================
--- trunk/apache2/patches/00list (original)
+++ trunk/apache2/patches/00list Wed Nov 11 22:25:27 2009
@@ -22,6 +22,7 @@
 070_RemoveType_override_mime.types.dpatch
 071_fix_cacheenable.dpatch
 072_CVE-2009-3555.dpatch
+073_mod_dav_trunk_fixes.dpatch
 099_config_guess_sub_update
 200_cp_suexec.dpatch
 201_build_suexec-custom.dpatch

Added: trunk/apache2/patches/073_mod_dav_trunk_fixes.dpatch
URL: http://svn.debian.org/wsvn/pkg-apache/trunk/apache2/patches/073_mod_dav_trunk_fixes.dpatch?rev=1097&op=file
==============================================================================
--- trunk/apache2/patches/073_mod_dav_trunk_fixes.dpatch (added)
+++ trunk/apache2/patches/073_mod_dav_trunk_fixes.dpatch Wed Nov 11 22:25:27 2009
@@ -1,0 +1,492 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Various bug fixes for mod_dav/mod_dav_fs
+## DP: upstream svn revs 834018:835092 in modules/dav
+#
+# *) mod_dav: Include uri when logging a PUT error due to connection abort.
+#    PR 38149. [Stefan Fritsch]
+#
+# *) mod_dav: Return 409 instead of 500 for a LOCK request if the parent
+#    resource does not exist or is not a collection. PR 43465. [Stefan Fritsch]
+#
+# *) mod_dav_fs: Return 409 instead of 500 for Litmus test case copy_nodestcoll
+#    (a COPY request where the parent of the destination resource does not
+#    exist). PR 39299. [Stefan Fritsch]
+#
+# *) mod_dav_fs: Don't delete the whole file if a PUT with content-range failed.
+#    PR 42896. [Stefan Fritsch]
+#
+# *) mod_dav_fs: Make PUT create files atomically and no longer destroy the
+#    old file if the transfer aborted. PR 39815. [Paul Querna, Stefan Fritsch]
+#
+# *) mod_dav_fs: Remove inode keyed locking as this conflicts with atomically
+#    creating files. On systems with inode numbers, this is a format change of
+#    the DavLockDB. The old DavLockDB must be deleted on upgrade.
+#    [Stefan Fritsch]
+ at DPATCH@
+Index: a/modules/dav/main/mod_dav.c
+===================================================================
+--- a/modules/dav/main/mod_dav.c	(Revision 834018)
++++ a/modules/dav/main/mod_dav.c	(Revision 835089)
+@@ -982,7 +982,10 @@
+ 
+             if (rc != APR_SUCCESS) {
+                 err = dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
+-                                    "Could not get next bucket brigade");
++                                    apr_psprintf(r->pool,
++                                                 "Could not get next bucket "
++                                                 "brigade (URI: %s)",
++                                                 ap_escape_html(r->pool, r->uri)));
+                 break;
+             }
+ 
+@@ -1005,8 +1008,10 @@
+                 rc = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+                 if (rc != APR_SUCCESS) {
+                     err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
+-                                        "An error occurred while reading "
+-                                        "the request body.");
++                                        apr_psprintf(r->pool,
++                                                    "An error occurred while reading"
++                                                    " the request body (URI: %s)",
++                                                    ap_escape_html(r->pool, r->uri)));
+                     break;
+                 }
+ 
+@@ -2995,6 +3000,7 @@
+ {
+     dav_error *err;
+     dav_resource *resource;
++    dav_resource *parent;
+     const dav_hooks_locks *locks_hooks;
+     int result;
+     int depth;
+@@ -3026,6 +3032,20 @@
+     if (err != NULL)
+         return dav_handle_err(r, err, NULL);
+ 
++    /* Check if parent collection exists */
++    if ((err = resource->hooks->get_parent_resource(resource, &parent)) != NULL) {
++        /* ### add a higher-level description? */
++        return dav_handle_err(r, err, NULL);
++    }
++    if (parent && (!parent->exists || parent->collection != 1)) {
++        err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
++                           apr_psprintf(r->pool,
++                                        "The parent resource of %s does not "
++                                        "exist or is not a collection.", 
++                                        ap_escape_html(r->pool, r->uri)));
++        return dav_handle_err(r, err, NULL);
++    }
++
+     /*
+      * Open writable. Unless an error occurs, we'll be
+      * writing into the database.
+Index: a/modules/dav/fs/lock.c
+===================================================================
+--- a/modules/dav/fs/lock.c	(Revision 834018)
++++ a/modules/dav/fs/lock.c	(Revision 835089)
+@@ -48,9 +48,8 @@
+ **
+ ** KEY
+ **
+-** The database is keyed by a key_type unsigned char (DAV_TYPE_INODE or
+-** DAV_TYPE_FNAME) followed by inode and device number if possible,
+-** otherwise full path (in the case of Win32 or lock-null resources).
++** The database is keyed by a key_type unsigned char (DAV_TYPE_FNAME)
++** followed by the full path. The key_type DAV_TYPE_INODE is not used anymore.
+ **
+ ** VALUE
+ **
+@@ -82,7 +81,10 @@
+ #define DAV_LOCK_DIRECT         1
+ #define DAV_LOCK_INDIRECT       2
+ 
+-#define DAV_TYPE_INODE          10
++/*
++ * not used anymore
++ * #define DAV_TYPE_INODE          10
++ */
+ #define DAV_TYPE_FNAME          11
+ 
+ 
+@@ -372,12 +374,13 @@
+ }
+ 
+ /*
+-** dav_fs_build_fname_key
+-**
+-** Given a pathname, build a DAV_TYPE_FNAME lock database key.
++** dav_fs_build_key:  Given a resource, return a apr_datum_t key
++**    to look up lock information for this file.
+ */
+-static apr_datum_t dav_fs_build_fname_key(apr_pool_t *p, const char *pathname)
++static apr_datum_t dav_fs_build_key(apr_pool_t *p,
++                                    const dav_resource *resource)
+ {
++    const char *pathname = dav_fs_pathname(resource);
+     apr_datum_t key;
+ 
+     /* ### does this allocation have a proper lifetime? need to check */
+@@ -394,46 +397,6 @@
+ }
+ 
+ /*
+-** dav_fs_build_key:  Given a resource, return a apr_datum_t key
+-**    to look up lock information for this file.
+-**
+-**    (inode/dev not supported or file is lock-null):
+-**       apr_datum_t->dvalue = full path
+-**
+-**    (inode/dev supported and file exists ):
+-**       apr_datum_t->dvalue = inode, dev
+-*/
+-static apr_datum_t dav_fs_build_key(apr_pool_t *p,
+-                                    const dav_resource *resource)
+-{
+-    const char *file = dav_fs_pathname(resource);
+-    apr_datum_t key;
+-    apr_finfo_t finfo;
+-    apr_status_t rv;
+-
+-    /* ### use lstat() ?? */
+-    /*
+-     * XXX: What for platforms with no IDENT (dev/inode)?
+-     */
+-    rv = apr_stat(&finfo, file, APR_FINFO_IDENT, p);
+-    if ((rv == APR_SUCCESS || rv == APR_INCOMPLETE)
+-        && ((finfo.valid & APR_FINFO_IDENT) == APR_FINFO_IDENT))
+-    {
+-        /* ### can we use a buffer for this? */
+-        key.dsize = 1 + sizeof(finfo.inode) + sizeof(finfo.device);
+-        key.dptr = apr_palloc(p, key.dsize);
+-        *key.dptr = DAV_TYPE_INODE;
+-        memcpy(key.dptr + 1, &finfo.inode, sizeof(finfo.inode));
+-        memcpy(key.dptr + 1 + sizeof(finfo.inode), &finfo.device,
+-               sizeof(finfo.device));
+-
+-        return key;
+-    }
+-
+-    return dav_fs_build_fname_key(p, file);
+-}
+-
+-/*
+ ** dav_fs_lock_expired:  return 1 (true) if the given timeout is in the past
+ **    or present (the lock has expired), or 0 (false) if in the future
+ **    (the lock has not yet expired).
+@@ -989,13 +952,8 @@
+ 
+ /*
+ ** dav_fs_remove_locknull_state:  Given a request, check to see if r->filename
+-**    is/was a lock-null resource.  If so, return it to an existant state.
+-**
+-**    ### this function is broken... it doesn't check!
+-**
+-**    In this implementation, this involves two things:
+-**    (a) remove it from the list in the appropriate .DAV/locknull file
+-**    (b) on *nix, convert the key from a filename to an inode.
++**    is/was a lock-null resource.  If so, return it to an existant state, i.e.
++**    remove it from the list in the appropriate .DAV/locknull file.
+ */
+ static dav_error * dav_fs_remove_locknull_state(
+     dav_lockdb *lockdb,
+@@ -1011,35 +969,6 @@
+         return err;
+     }
+ 
+-    {
+-        dav_lock_discovery *ld;
+-        dav_lock_indirect  *id;
+-        apr_datum_t key;
+-
+-        /*
+-        ** Fetch the lock(s) that made the resource lock-null. Remove
+-        ** them under the filename key. Obtain the new inode key, and
+-        ** save the same lock information under it.
+-        */
+-        key = dav_fs_build_fname_key(p, pathname);
+-        if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
+-                                           &ld, &id)) != NULL) {
+-            /* ### insert a higher-level error description */
+-            return err;
+-        }
+-
+-        if ((err = dav_fs_save_lock_record(lockdb, key, NULL, NULL)) != NULL) {
+-            /* ### insert a higher-level error description */
+-            return err;
+-        }
+-
+-        key = dav_fs_build_key(p, resource);
+-        if ((err = dav_fs_save_lock_record(lockdb, key, ld, id)) != NULL) {
+-            /* ### insert a higher-level error description */
+-            return err;
+-        }
+-    }
+-
+     return NULL;
+ }
+ 
+Index: a/modules/dav/fs/repos.c
+===================================================================
+--- a/modules/dav/fs/repos.c	(Revision 834018)
++++ a/modules/dav/fs/repos.c	(Revision 835089)
+@@ -140,6 +140,11 @@
+ */
+ #define DAV_PROPID_FS_executable        1
+ 
++/*
++ * prefix for temporary files
++ */
++#define DAV_FS_TMP_PREFIX ".davfs." 
++
+ static const dav_liveprop_spec dav_fs_props[] =
+ {
+     /* standard DAV properties */
+@@ -192,11 +197,14 @@
+     apr_pool_t *p;
+     apr_file_t *f;
+     const char *pathname;       /* we may need to remove it at close time */
++    char *temppath;
++    int unlink_on_error;
+ };
+ 
+ /* returns an appropriate HTTP status code given an APR status code for a
+  * failed I/O operation.  ### use something besides 500? */
+ #define MAP_IO2HTTP(e) (APR_STATUS_IS_ENOSPC(e) ? HTTP_INSUFFICIENT_STORAGE : \
++                        APR_STATUS_IS_ENOENT(e) ? HTTP_CONFLICT : \
+                         HTTP_INTERNAL_SERVER_ERROR)
+ 
+ /* forward declaration for internal treewalkers */
+@@ -420,11 +428,24 @@
+     apr_file_close(inf);
+     apr_file_close(outf);
+ 
+-    if (is_move && apr_file_remove(src, p) != APR_SUCCESS) {
++    if (is_move && (status = apr_file_remove(src, p)) != APR_SUCCESS) {
+         dav_error *err;
+         int save_errno = errno;   /* save the errno that got us here */
+ 
+-        if (apr_file_remove(dst, p) != APR_SUCCESS) {
++        if (APR_STATUS_IS_ENOENT(status)) {
++            /*
++             * Something is wrong here but the result is what we wanted.
++             * We definitely should not remove the destination file.
++             */
++             err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
++                                 apr_psprintf(p, "Could not remove source "
++                                              "file %s after move to %s. The "
++                                              "server may be in an "
++                                              "inconsistent state.", src, dst));
++            err->save_errno = save_errno;
++            return err;
++        } 
++        else if (apr_file_remove(dst, p) != APR_SUCCESS) {
+             /* ### ACK. this creates an inconsistency. do more!? */
+ 
+             /* ### use something besides 500? */
+@@ -506,9 +527,13 @@
+     dst = apr_pstrcat(p, dst, "/", dst_file, NULL);
+ 
+     /* copy/move the file now */
+-    if (is_move && src_finfo.device == dst_state_finfo.device) {
+-        /* simple rename is possible since it is on the same device */
+-        if (apr_file_rename(src, dst, p) != APR_SUCCESS) {
++    if (is_move) {
++        /* try simple rename first */
++        rv = apr_file_rename(src, dst, p);
++        if (APR_STATUS_IS_EXDEV(rv)) {
++            return dav_fs_copymove_file(is_move, p, src, dst, NULL, NULL, pbuf);
++        }
++        if (rv != APR_SUCCESS) {
+             /* ### use something besides 500? */
+             return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
+                                  "Could not move state file.");
+@@ -848,6 +873,14 @@
+             && ctx2->pathname[len1] == '/');
+ }
+ 
++static apr_status_t tmpfile_cleanup(void *data) {
++        dav_stream *ds = data;
++        if (ds->temppath) {
++                apr_file_remove(ds->temppath, ds->p);
++        }
++        return APR_SUCCESS;
++}
++
+ static dav_error * dav_fs_open_stream(const dav_resource *resource,
+                                       dav_stream_mode mode,
+                                       dav_stream **stream)
+@@ -872,7 +905,32 @@
+ 
+     ds->p = p;
+     ds->pathname = resource->info->pathname;
+-    rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT, ds->p);
++    ds->temppath = NULL;
++    ds->unlink_on_error = 0;
++
++    if (mode == DAV_MODE_WRITE_TRUNC) {
++        ds->temppath = apr_pstrcat(p, ap_make_dirstr_parent(p, ds->pathname),
++                                   DAV_FS_TMP_PREFIX "XXXXXX", NULL);
++        rv = apr_file_mktemp(&ds->f, ds->temppath, flags, ds->p);
++        apr_pool_cleanup_register(p, ds, tmpfile_cleanup,
++                                  apr_pool_cleanup_null);
++    }
++    else if (mode == DAV_MODE_WRITE_SEEKABLE) {
++        rv = apr_file_open(&ds->f, ds->pathname, flags | APR_FOPEN_EXCL,
++                           APR_OS_DEFAULT, ds->p);
++        if (rv == APR_SUCCESS) {
++            /* we have created a new file */
++            ds->unlink_on_error = 1;
++        }
++        else if (APR_STATUS_IS_EEXIST(rv)) {
++            rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT,
++                               ds->p);
++        }
++    }
++    else {
++        rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT, ds->p);
++    }
++
+     if (rv != APR_SUCCESS) {
+         return dav_new_error(p, MAP_IO2HTTP(rv), 0,
+                              "An error occurred while opening a resource.");
+@@ -886,17 +944,33 @@
+ 
+ static dav_error * dav_fs_close_stream(dav_stream *stream, int commit)
+ {
++    apr_status_t rv;
++
+     apr_file_close(stream->f);
+ 
+     if (!commit) {
+-        if (apr_file_remove(stream->pathname, stream->p) != APR_SUCCESS) {
+-            /* ### use a better description? */
+-            return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
+-                                 "There was a problem removing (rolling "
+-                                 "back) the resource "
+-                                 "when it was being closed.");
++        if (stream->temppath) {
++            apr_pool_cleanup_run(stream->p, stream, tmpfile_cleanup);
+         }
++        else if (stream->unlink_on_error) {
++            if (apr_file_remove(stream->pathname, stream->p) != APR_SUCCESS) {
++                /* ### use a better description? */
++                return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
++                                     "There was a problem removing (rolling "
++                                     "back) the resource "
++                                     "when it was being closed.");
++            }
++        }
+     }
++    else if (stream->temppath) {
++        rv = apr_file_rename(stream->temppath, stream->pathname, stream->p);
++        if (rv) {
++            return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, rv,
++                                 "There was a problem writing the file "
++                                 "atomically after writes.");
++        }
++        apr_pool_cleanup_kill(stream->p, stream, tmpfile_cleanup);
++    }
+ 
+     return NULL;
+ }
+@@ -1204,7 +1278,7 @@
+     dav_resource_private *srcinfo = src->info;
+     dav_resource_private *dstinfo = dst->info;
+     dav_error *err;
+-    int can_rename = 0;
++    apr_status_t rv;
+ 
+ #if DAV_DEBUG
+     if (src->hooks != dst->hooks) {
+@@ -1218,39 +1292,12 @@
+     }
+ #endif
+ 
+-    /* determine whether a simple rename will work.
+-     * Assume source exists, else we wouldn't get called.
+-     */
+-    if (dstinfo->finfo.filetype != 0) {
+-        if (dstinfo->finfo.device == srcinfo->finfo.device) {
+-            /* target exists and is on the same device. */
+-            can_rename = 1;
+-        }
+-    }
+-    else {
+-        const char *dirpath;
+-        apr_finfo_t finfo;
+-        apr_status_t rv;
+ 
+-        /* destination does not exist, but the parent directory should,
+-         * so try it
+-         */
+-        dirpath = ap_make_dirstr_parent(dstinfo->pool, dstinfo->pathname);
+-        /*
+-         * XXX: If missing dev ... then what test?
+-         * Really need a try and failover for those platforms.
+-         *
+-         */
+-        rv = apr_stat(&finfo, dirpath, APR_FINFO_DEV, dstinfo->pool);
+-        if ((rv == APR_SUCCESS || rv == APR_INCOMPLETE)
+-            && (finfo.valid & srcinfo->finfo.valid & APR_FINFO_DEV)
+-            && (finfo.device == srcinfo->finfo.device)) {
+-            can_rename = 1;
+-        }
+-    }
++    /* try rename first */
++    rv = apr_file_rename(srcinfo->pathname, dstinfo->pathname, srcinfo->pool);
+ 
+     /* if we can't simply rename, then do it the hard way... */
+-    if (!can_rename) {
++    if (APR_STATUS_IS_EXDEV(rv)) {
+         if ((err = dav_fs_copymove_resource(1, src, dst, DAV_INFINITY,
+                                             response)) == NULL) {
+             /* update resource states */
+@@ -1263,20 +1310,16 @@
+         return err;
+     }
+ 
+-    /* a rename should work. do it, and move properties as well */
+-
+     /* no multistatus response */
+     *response = NULL;
+ 
+-    /* ### APR has no rename? */
+-    if (apr_file_rename(srcinfo->pathname, dstinfo->pathname,
+-                       srcinfo->pool) != APR_SUCCESS) {
++    if (rv != APR_SUCCESS) {
+         /* ### should have a better error than this. */
+         return dav_new_error(srcinfo->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
+                              "Could not rename resource.");
+     }
+ 
+-    /* update resource states */
++    /* Rename did work. Update resource states and move properties as well */
+     dst->exists = 1;
+     dst->collection = src->collection;
+     src->exists = 0;
+@@ -1478,14 +1521,18 @@
+             /* ### need to authorize each file */
+             /* ### example: .htaccess is normally configured to fail auth */
+ 
+-            /* stuff in the state directory is never authorized! */
+-            if (!strcmp(dirent.name, DAV_FS_STATE_DIR)) {
++            /* stuff in the state directory and temp files are never authorized! */
++            if (!strcmp(dirent.name, DAV_FS_STATE_DIR) ||
++                !strncmp(dirent.name, DAV_FS_TMP_PREFIX,
++                         strlen(DAV_FS_TMP_PREFIX))) {
+                 continue;
+             }
+         }
+-        /* skip the state dir unless a HIDDEN is performed */
++        /* skip the state dir and temp files unless a HIDDEN is performed */
+         if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
+-            && !strcmp(dirent.name, DAV_FS_STATE_DIR)) {
++            && (!strcmp(dirent.name, DAV_FS_STATE_DIR) ||
++                !strncmp(dirent.name, DAV_FS_TMP_PREFIX,
++                         strlen(DAV_FS_TMP_PREFIX)))) {
+             continue;
+         }
+ 




More information about the Pkg-apache-commits mailing list