[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