--- httpd-2.2.21.orig/modules/dav/fs/repos.c 2012-01-30 15:12:09.000000000 +0100 +++ httpd-2.2.21.orig/modules/dav/fs/repos.c 2012-01-30 15:29:29.000000000 +0100 @@ -81,6 +81,9 @@ typedef struct { const dav_resource *root; apr_pool_t *pool; + /* scratch pool, cleared for each element in the walk */ + apr_pool_t *scratchpool; + } dav_fs_copymove_walk_ctx; /* an internal WALKTYPE to walk hidden files (the .DAV directory) */ @@ -309,10 +312,12 @@ static void dav_format_time(int style, a /* Copy or move src to dst; src_finfo is used to propagate permissions * bits across if non-NULL; dst_finfo must be non-NULL iff dst already - * exists. */ + * exists. The pool *sp is a scratch pool cleaned after each call to this + * function while *rp is a pool that lives as much as the request. */ static dav_error * dav_fs_copymove_file( int is_move, - apr_pool_t * p, + apr_pool_t * sp, + apr_pool_t * rp, const char *src, const char *dst, const apr_finfo_t *src_finfo, @@ -320,13 +325,18 @@ static dav_error * dav_fs_copymove_file( dav_buffer *pbuf) { dav_buffer work_buf = { 0 }; + apr_pool_t *bp; apr_file_t *inf = NULL; apr_file_t *outf = NULL; apr_status_t status; apr_fileperms_t perms; - if (pbuf == NULL) + if (pbuf == NULL) { pbuf = &work_buf; + bp = sp; + } else { + bp = rp; + } /* Determine permissions to use for destination */ if (src_finfo && src_finfo->valid & APR_FINFO_PROT @@ -336,7 +346,7 @@ static dav_error * dav_fs_copymove_file( if (dst_finfo != NULL) { /* chmod it if it already exist */ if (apr_file_perms_set(dst, perms)) { - return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + return dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not set permissions on destination"); } } @@ -345,22 +355,22 @@ static dav_error * dav_fs_copymove_file( perms = APR_OS_DEFAULT; } - dav_set_bufsize(p, pbuf, DAV_FS_COPY_BLOCKSIZE); + dav_set_bufsize(bp, pbuf, DAV_FS_COPY_BLOCKSIZE); - if ((apr_file_open(&inf, src, APR_READ | APR_BINARY, APR_OS_DEFAULT, p)) + if ((apr_file_open(&inf, src, APR_READ | APR_BINARY, APR_OS_DEFAULT, sp)) != APR_SUCCESS) { /* ### use something besides 500? */ - return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + return dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not open file for reading"); } /* ### do we need to deal with the umask? */ status = apr_file_open(&outf, dst, APR_WRITE | APR_CREATE | APR_TRUNCATE - | APR_BINARY, perms, p); + | APR_BINARY, perms, sp); if (status != APR_SUCCESS) { apr_file_close(inf); - return dav_new_error(p, MAP_IO2HTTP(status), 0, + return dav_new_error(rp, MAP_IO2HTTP(status), 0, "Could not open file for writing"); } @@ -372,18 +382,18 @@ static dav_error * dav_fs_copymove_file( apr_file_close(inf); apr_file_close(outf); - if (apr_file_remove(dst, p) != APR_SUCCESS) { + if (apr_file_remove(dst, sp) != APR_SUCCESS) { /* ### ACK! Inconsistent state... */ /* ### use something besides 500? */ - return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + return dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not delete output after read " "failure. Server is now in an " "inconsistent state."); } /* ### use something besides 500? */ - return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + return dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not read input file"); } @@ -396,17 +406,17 @@ static dav_error * dav_fs_copymove_file( apr_file_close(inf); apr_file_close(outf); - if (apr_file_remove(dst, p) != APR_SUCCESS) { + if (apr_file_remove(dst, sp) != APR_SUCCESS) { /* ### ACK! Inconsistent state... */ /* ### use something besides 500? */ - return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + return dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not delete output after write " "failure. Server is now in an " "inconsistent state."); } - return dav_new_error(p, MAP_IO2HTTP(status), 0, + return dav_new_error(rp, MAP_IO2HTTP(status), 0, "Could not write output file"); } } @@ -414,23 +424,23 @@ static dav_error * dav_fs_copymove_file( apr_file_close(inf); apr_file_close(outf); - if (is_move && apr_file_remove(src, p) != APR_SUCCESS) { + if (is_move && apr_file_remove(src, sp) != 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_file_remove(dst, sp) != APR_SUCCESS) { /* ### ACK. this creates an inconsistency. do more!? */ /* ### use something besides 500? */ /* Note that we use the latest errno */ - return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + return dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not remove source or destination " "file. Server is now in an inconsistent " "state."); } /* ### use something besides 500? */ - err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, + err = dav_new_error(rp, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not remove source file after move. " "Destination was removed to ensure consistency."); err->save_errno = save_errno; @@ -511,7 +521,7 @@ static dav_error * dav_fs_copymove_state else { /* gotta copy (and delete) */ - return dav_fs_copymove_file(is_move, p, src, dst, NULL, NULL, pbuf); + return dav_fs_copymove_file(is_move, p, p, src, dst, NULL, NULL, pbuf); } return NULL; @@ -1047,18 +1057,20 @@ static dav_error * dav_fs_copymove_walke dav_resource_private *dstinfo = ctx->res_dst->info; dav_error *err = NULL; + apr_pool_clear(ctx->scratchpool); + if (wres->resource->collection) { if (calltype == DAV_CALLTYPE_POSTFIX) { /* Postfix call for MOVE. delete the source dir. * Note: when copying, we do not enable the postfix-traversal. */ /* ### we are ignoring any error here; what should we do? */ - (void) apr_dir_remove(srcinfo->pathname, ctx->pool); + (void) apr_dir_remove(srcinfo->pathname, ctx->scratchpool); } else { /* copy/move of a collection. Create the new, target collection */ if (apr_dir_make(dstinfo->pathname, APR_OS_DEFAULT, - ctx->pool) != APR_SUCCESS) { + ctx->scratchpool) != APR_SUCCESS) { /* ### assume it was a permissions problem */ /* ### need a description here */ err = dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0, NULL); @@ -1066,7 +1078,7 @@ static dav_error * dav_fs_copymove_walke } } else { - err = dav_fs_copymove_file(ctx->is_move, ctx->pool, + err = dav_fs_copymove_file(ctx->is_move, ctx->scratchpool, ctx->pool, srcinfo->pathname, dstinfo->pathname, &srcinfo->finfo, ctx->res_dst->exists ? &dstinfo->finfo : NULL, @@ -1149,7 +1161,7 @@ static dav_error *dav_fs_copymove_resour } /* not a collection */ - if ((err = dav_fs_copymove_file(is_move, src->info->pool, + if ((err = dav_fs_copymove_file(is_move, src->info->pool, src->info->pool, src->info->pathname, dst->info->pathname, &src->info->finfo, dst->exists ? &dst->info->finfo : NULL, @@ -1730,6 +1742,7 @@ static dav_error * dav_fs_internal_walk( cm_ctx.res_dst = &fsctx.res2; cm_ctx.root = params->root; cm_ctx.pool = params->pool; + apr_pool_create(&cm_ctx.scratchpool, cm_ctx.pool); fsctx.res2 = *root_dst; fsctx.res2.exists = 0;