repos.c revision 0c9166d0186cf0e1ad397025f730ae6967f44ce6
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Copyright 2000-2006 The Apache Software Foundation or its licensors, as
842ae4bd224140319ae7feec1872b93dfd491143fielding * applicable.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Licensed under the Apache License, Version 2.0 (the "License");
842ae4bd224140319ae7feec1872b93dfd491143fielding * you may not use this file except in compliance with the License.
842ae4bd224140319ae7feec1872b93dfd491143fielding * You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * http://www.apache.org/licenses/LICENSE-2.0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** DAV filesystem-based repository provider
e8f95a682820a599fe41b22977010636be5c2717jim*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim#include "apr.h"
1747d30b98aa1bdbc43994c02cd46ab4cb9319e4fielding#include "apr_file_io.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_strings.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_buckets.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#if APR_HAVE_STDIO_H
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include <stdio.h> /* for sprintf() */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "httpd.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_log.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_protocol.h" /* for ap_set_* (in dav_fs_set_headers) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_request.h" /* for ap_update_mtime() */
5c0419d51818eb02045cf923a9fe456127a44c60wrowe
5c0419d51818eb02045cf923a9fe456127a44c60wrowe#include "mod_dav.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "repos.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* to assist in debugging mod_dav's GET handling */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define DEBUG_GET_HANDLER 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton#define DAV_FS_COPY_BLOCKSIZE 16384 /* copy 16k at a time */
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton/* context needed to identify a resource */
d266c3777146d36a4c23c17aad6f153aebea1bf4jortonstruct dav_resource_private {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_t *pool; /* memory storage pool associated with request */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *pathname; /* full pathname to resource */
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes apr_finfo_t finfo; /* filesystem info */
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes};
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes/* private context for doing a filesystem walk */
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholestypedef struct {
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes /* the input walk parameters */
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes const dav_walk_params *params;
cd3bbd6d2df78d6c75e5d159a81ef8bdd5f70df9trawick
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* reused as we walk */
0f60998368b493f90120180a93fc2e1e74490872covener dav_walk_resource wres;
0f60998368b493f90120180a93fc2e1e74490872covener
0f60998368b493f90120180a93fc2e1e74490872covener dav_resource res1;
0f60998368b493f90120180a93fc2e1e74490872covener dav_resource_private info1;
0f60998368b493f90120180a93fc2e1e74490872covener dav_buffer path1;
0f60998368b493f90120180a93fc2e1e74490872covener dav_buffer uri_buf;
0f60998368b493f90120180a93fc2e1e74490872covener
0f60998368b493f90120180a93fc2e1e74490872covener /* MOVE/COPY need a secondary path */
87587593f1a53030e840acc0dec6cc881022ea40covener dav_resource res2;
87587593f1a53030e840acc0dec6cc881022ea40covener dav_resource_private info2;
87587593f1a53030e840acc0dec6cc881022ea40covener dav_buffer path2;
87587593f1a53030e840acc0dec6cc881022ea40covener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer locknull_buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
0568280364eb026393be492ebc732795c4934643jorton} dav_fs_walker_context;
0568280364eb026393be492ebc732795c4934643jorton
0568280364eb026393be492ebc732795c4934643jortontypedef struct {
0568280364eb026393be492ebc732795c4934643jorton int is_move; /* is this a MOVE? */
0568280364eb026393be492ebc732795c4934643jorton dav_buffer work_buf; /* handy buffer for copymove_file() */
0568280364eb026393be492ebc732795c4934643jorton
0568280364eb026393be492ebc732795c4934643jorton /* CALLBACK: this is a secondary resource managed specially for us */
0568280364eb026393be492ebc732795c4934643jorton const dav_resource *res_dst;
0568280364eb026393be492ebc732795c4934643jorton
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* copied from dav_walk_params (they are invariant across the walk) */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener const dav_resource *root;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_pool_t *pool;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes} dav_fs_copymove_walk_ctx;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* an internal WALKTYPE to walk hidden files (the .DAV directory) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define DAV_WALKTYPE_HIDDEN 0x4000
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* an internal WALKTYPE to call collections (again) after their contents */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define DAV_WALKTYPE_POSTFIX 0x8000
796e4a7141265d8ed7036e4628161c6eafb2a789jorton
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define DAV_CALLTYPE_POSTFIX 1000 /* a private call type */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* pull this in from the other source file */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesextern const dav_hooks_locks dav_hooks_locks_fs;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* forward-declare the hook structures */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const dav_hooks_repository dav_hooks_repository_fs;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const dav_hooks_liveprop dav_hooks_liveprop_fs;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The namespace URIs that we use. This list and the enumeration must
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** stay in sync.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char * const dav_fs_namespace_uris[] =
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "DAV:",
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe "http://apache.org/dav/props/",
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe NULL /* sentinel */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesenum {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_FS_URI_DAV, /* the DAV: namespace URI */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_FS_URI_MYPROPS /* the namespace URI for our custom props */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** Does this platform support an executable flag?
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
a1790fb35c4b352dab721370985c623a9f8f5062rpluem** ### need a way to portably abstract this query
713a2b68bac4aeb1e9c48785006c0732451039depquerna*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#ifndef WIN32
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define DAV_FS_HAS_EXECUTABLE
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe** The single property that we define (in the DAV_FS_URI_MYPROPS namespace)
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define DAV_PROPID_FS_executable 1
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const dav_liveprop_spec dav_fs_props[] =
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* standard DAV properties */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_FS_URI_DAV,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "creationdate",
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener DAV_PROPID_creationdate,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes },
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_FS_URI_DAV,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "getcontentlength",
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe DAV_PROPID_getcontentlength,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes },
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_FS_URI_DAV,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "getetag",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_PROPID_getetag,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes },
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_FS_URI_DAV,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "getlastmodified",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_PROPID_getlastmodified,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes 0
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener },
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* our custom properties */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener DAV_FS_URI_MYPROPS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "executable",
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener DAV_PROPID_FS_executable,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes 0 /* handled special in dav_fs_is_writable */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener },
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes { 0 } /* sentinel */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const dav_liveprop_group dav_fs_liveprop_group =
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener dav_fs_props,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_fs_namespace_uris,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe &dav_hooks_liveprop_fs
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* define the dav_stream structure for our use */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstruct dav_stream {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_t *p;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_file_t *f;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *pathname; /* we may need to remove it at close time */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* returns an appropriate HTTP status code given an APR status code for a
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * failed I/O operation. ### use something besides 500? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define MAP_IO2HTTP(e) (APR_STATUS_IS_ENOSPC(e) ? HTTP_INSUFFICIENT_STORAGE : \
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes HTTP_INTERNAL_SERVER_ERROR)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* forward declaration for internal treewalkers */
1f299703465bd9975d94e9f229f76af807442de2covenerstatic dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener dav_response **response);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic dav_error * dav_fs_internal_walk(const dav_walk_params *params,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener int depth, int is_move,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_resource *root_dst,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe dav_response **response);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* --------------------------------------------------------------------
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** PRIVATE REPOSITORY FUNCTIONS
9ad7b260be233be7d7b5576979825cac72e15498rederpj*/
9ad7b260be233be7d7b5576979825cac72e15498rederpjapr_pool_t *dav_fs_pool(const dav_resource *resource)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return resource->info->pool;
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesconst char *dav_fs_pathname(const dav_resource *resource)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return resource->info->pathname;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesdav_error * dav_fs_dir_file_name(
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_resource *resource,
3e6d7277b90d3011db832139afc20efb5f17e203rederpj const char **dirpath_p,
3e6d7277b90d3011db832139afc20efb5f17e203rederpj const char **fname_p)
3e6d7277b90d3011db832139afc20efb5f17e203rederpj{
3e6d7277b90d3011db832139afc20efb5f17e203rederpj dav_resource_private *ctx = resource->info;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes if (resource->collection) {
e8f95a682820a599fe41b22977010636be5c2717jim *dirpath_p = ctx->pathname;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (fname_p != NULL)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener *fname_p = NULL;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener else {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener const char *testpath, *rootpath;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener char *dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_size_t dirlen = strlen(dirpath);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_status_t rv = APR_SUCCESS;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener testpath = dirpath;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (dirlen > 0) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener rv = apr_filepath_root(&rootpath, &testpath, 0, ctx->pool);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* remove trailing slash from dirpath, unless it's a root path
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if ((rv == APR_SUCCESS && testpath && *testpath)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener || rv == APR_ERELATIVE) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (dirpath[dirlen - 1] == '/') {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener dirpath[dirlen - 1] = '\0';
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* ###: Looks like a response could be appropriate
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener *
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * APR_SUCCESS here tells us the dir is a root
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * APR_ERELATIVE told us we had no root (ok)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * APR_EINCOMPLETE an incomplete testpath told us
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * there was no -file- name here!
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * APR_EBADPATH or other errors tell us this file
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * path is undecipherable
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (rv == APR_SUCCESS || rv == APR_ERELATIVE) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener *dirpath_p = dirpath;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (fname_p != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *fname_p = ctx->pathname + dirlen;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener else {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener return dav_new_error(ctx->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener "An incomplete/bad path was found in "
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener "dav_fs_dir_file_name.");
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener return NULL;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener}
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/* Note: picked up from ap_gm_timestr_822() */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/* NOTE: buf must be at least DAV_TIMEBUF_SIZE chars in size */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic void dav_format_time(int style, apr_time_t sec, char *buf)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener{
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_time_exp_t tms;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* ### what to do if fails? */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener (void) apr_time_exp_gmt(&tms, sec);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (style == DAV_STYLE_ISO8601) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### should we use "-00:00" instead of "Z" ?? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* 20 chars plus null term */
0e05808dc59a321566303084c84b9826a4353cefrederpj sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
b08925593f214f621161742925dcf074a8047e0acovener tms.tm_hour, tms.tm_min, tms.tm_sec);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes /* RFC 822 date format; as strftime '%a, %d %b %Y %T GMT' */
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj
e8f95a682820a599fe41b22977010636be5c2717jim /* 29 chars plus null term */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes sprintf(buf,
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes "%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
54d22ed1c429b903b029bbd62621f11a9e286137minfrin apr_day_snames[tms.tm_wday],
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes tms.tm_mday, apr_month_snames[tms.tm_mon],
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes tms.tm_year + 1900,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes tms.tm_hour, tms.tm_min, tms.tm_sec);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/* Copy or move src to dst; src_finfo is used to propagate permissions
ebe5305f8b22507374358f32b74d12fb50c05a25covener * bits across if non-NULL; dst_finfo must be non-NULL iff dst already
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * exists. */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic dav_error * dav_fs_copymove_file(
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes int is_move,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_pool_t * p,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *src,
513b324e774c559b579896df131fd7c8471ed529rederpj const char *dst,
513b324e774c559b579896df131fd7c8471ed529rederpj const apr_finfo_t *src_finfo,
513b324e774c559b579896df131fd7c8471ed529rederpj const apr_finfo_t *dst_finfo,
513b324e774c559b579896df131fd7c8471ed529rederpj dav_buffer *pbuf)
513b324e774c559b579896df131fd7c8471ed529rederpj{
513b324e774c559b579896df131fd7c8471ed529rederpj dav_buffer work_buf = { 0 };
513b324e774c559b579896df131fd7c8471ed529rederpj apr_file_t *inf = NULL;
513b324e774c559b579896df131fd7c8471ed529rederpj apr_file_t *outf = NULL;
513b324e774c559b579896df131fd7c8471ed529rederpj apr_status_t status;
513b324e774c559b579896df131fd7c8471ed529rederpj apr_fileperms_t perms;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (pbuf == NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pbuf = &work_buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Determine permissions to use for destination */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (src_finfo && src_finfo->valid & APR_FINFO_PROT
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes && src_finfo->protection & APR_UEXECUTE) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes perms = src_finfo->protection;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (dst_finfo != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* chmod it if it already exist */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_file_perms_set(dst, perms)) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "Could not set permissions on destination");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj else {
9ad7b260be233be7d7b5576979825cac72e15498rederpj perms = APR_OS_DEFAULT;
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj dav_set_bufsize(p, pbuf, DAV_FS_COPY_BLOCKSIZE);
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj if ((apr_file_open(&inf, src, APR_READ | APR_BINARY, APR_OS_DEFAULT, p))
9ad7b260be233be7d7b5576979825cac72e15498rederpj != APR_SUCCESS) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### use something besides 500? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "Could not open file for reading");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
ebe5305f8b22507374358f32b74d12fb50c05a25covener /* ### do we need to deal with the umask? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes status = apr_file_open(&outf, dst, APR_WRITE | APR_CREATE | APR_TRUNCATE
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes | APR_BINARY, perms, p);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (status != APR_SUCCESS) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_file_close(inf);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return dav_new_error(p, MAP_IO2HTTP(status), 0,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "Could not open file for writing");
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes while (1) {
ebe5305f8b22507374358f32b74d12fb50c05a25covener apr_size_t len = DAV_FS_COPY_BLOCKSIZE;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes status = apr_file_read(inf, pbuf->buf, &len);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (status != APR_SUCCESS && status != APR_EOF) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_file_close(inf);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_file_close(outf);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (apr_file_remove(dst, p) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### ACK! Inconsistent state... */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
b08925593f214f621161742925dcf074a8047e0acovener /* ### use something besides 500? */
b08925593f214f621161742925dcf074a8047e0acovener return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not delete output after read "
9ad7b260be233be7d7b5576979825cac72e15498rederpj "failure. Server is now in an "
9ad7b260be233be7d7b5576979825cac72e15498rederpj "inconsistent state.");
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
128a5d93141a86e3afa151e921035a07297c9833rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* ### use something besides 500? */
9ad7b260be233be7d7b5576979825cac72e15498rederpj return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
128a5d93141a86e3afa151e921035a07297c9833rederpj "Could not read input file");
128a5d93141a86e3afa151e921035a07297c9833rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (status == APR_EOF)
9ad7b260be233be7d7b5576979825cac72e15498rederpj break;
9ad7b260be233be7d7b5576979825cac72e15498rederpj
128a5d93141a86e3afa151e921035a07297c9833rederpj /* write any bytes that were read */
9ad7b260be233be7d7b5576979825cac72e15498rederpj status = apr_file_write_full(outf, pbuf->buf, len, NULL);
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (status != APR_SUCCESS) {
9ab21648975dff7e1b680daf8aea627227ba28f7trawick apr_file_close(inf);
9ad7b260be233be7d7b5576979825cac72e15498rederpj apr_file_close(outf);
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (apr_file_remove(dst, p) != APR_SUCCESS) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* ### ACK! Inconsistent state... */
87587593f1a53030e840acc0dec6cc881022ea40covener
87587593f1a53030e840acc0dec6cc881022ea40covener /* ### use something besides 500? */
9ad7b260be233be7d7b5576979825cac72e15498rederpj return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
9ad7b260be233be7d7b5576979825cac72e15498rederpj "Could not delete output after write "
9ad7b260be233be7d7b5576979825cac72e15498rederpj "failure. Server is now in an "
9ad7b260be233be7d7b5576979825cac72e15498rederpj "inconsistent state.");
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj return dav_new_error(p, MAP_IO2HTTP(status), 0,
9ad7b260be233be7d7b5576979825cac72e15498rederpj "Could not write output file");
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj apr_file_close(inf);
9ad7b260be233be7d7b5576979825cac72e15498rederpj apr_file_close(outf);
9ab21648975dff7e1b680daf8aea627227ba28f7trawick
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (is_move && apr_file_remove(src, p) != APR_SUCCESS) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj dav_error *err;
9ad7b260be233be7d7b5576979825cac72e15498rederpj int save_errno = errno; /* save the errno that got us here */
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (apr_file_remove(dst, p) != APR_SUCCESS) {
7add8f7fb048534390571801b7794f71cd9e127abnicholes /* ### ACK. this creates an inconsistency. do more!? */
7add8f7fb048534390571801b7794f71cd9e127abnicholes
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### use something besides 500? */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Note that we use the latest errno */
7add8f7fb048534390571801b7794f71cd9e127abnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
7add8f7fb048534390571801b7794f71cd9e127abnicholes "Could not remove source or destination "
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "file. Server is now in an inconsistent "
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "state.");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### use something besides 500? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
7add8f7fb048534390571801b7794f71cd9e127abnicholes "Could not remove source file after move. "
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "Destination was removed to ensure consistency.");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes err->save_errno = save_errno;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return err;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return NULL;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/* copy/move a file from within a state dir to another state dir */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/* ### need more buffers to replace the pool argument */
7add8f7fb048534390571801b7794f71cd9e127abnicholesstatic dav_error * dav_fs_copymove_state(
7add8f7fb048534390571801b7794f71cd9e127abnicholes int is_move,
141e1368614dc7564e1627671361b01b4869b491bnicholes apr_pool_t * p,
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes const char *src_dir, const char *src_file,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *dst_dir, const char *dst_file,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_buffer *pbuf)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
e8f95a682820a599fe41b22977010636be5c2717jim apr_finfo_t src_finfo; /* finfo for source file */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_finfo_t dst_state_finfo; /* finfo for STATE directory */
ebe5305f8b22507374358f32b74d12fb50c05a25covener apr_status_t rv;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *src;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *dst;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* build the propset pathname for the source file */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes src = apr_pstrcat(p, src_dir, "/" DAV_FS_STATE_DIR "/", src_file, NULL);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes /* the source file doesn't exist */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes rv = apr_stat(&src_finfo, src, APR_FINFO_NORM, p);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return NULL;
e8f95a682820a599fe41b22977010636be5c2717jim }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* build the pathname for the destination state dir */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dst = apr_pstrcat(p, dst_dir, "/" DAV_FS_STATE_DIR, NULL);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### do we need to deal with the umask? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ensure that it exists */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes rv = apr_dir_make(dst, APR_OS_DEFAULT, p);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (rv != APR_SUCCESS) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (!APR_STATUS_IS_EEXIST(rv)) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### use something besides 500? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "Could not create internal state directory");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* get info about the state directory */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes rv = apr_stat(&dst_state_finfo, dst, APR_FINFO_NORM, p);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* Ack! Where'd it go? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### use something besides 500? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "State directory disappeared");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* The mkdir() may have failed because a *file* exists there already */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (dst_state_finfo.filetype != APR_DIR) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### try to recover by deleting this file? (and mkdir again) */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* ### use something besides 500? */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "State directory is actually a file");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* append the target file to the state directory pathname */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dst = apr_pstrcat(p, dst, "/", dst_file, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* copy/move the file now */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (is_move && src_finfo.device == dst_state_finfo.device) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* simple rename is possible since it is on the same device */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_file_rename(src, dst, p) != APR_SUCCESS) {
e8f95a682820a599fe41b22977010636be5c2717jim /* ### use something besides 500? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not move state file.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* gotta copy (and delete) */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return dav_fs_copymove_file(is_move, p, src, dst, NULL, NULL, pbuf);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
6733d943c9e8d0f27dd077a04037e8c49eb090ffcovener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic dav_error *dav_fs_copymoveset(int is_move, apr_pool_t *p,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const dav_resource *src,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const dav_resource *dst,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_buffer *pbuf)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *src_dir;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *src_file;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *src_state1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *src_state2;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *dst_dir;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *dst_file;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin const char *dst_state1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *dst_state2;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_error *err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Get directory and filename for resources */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### should test these result values... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (void) dav_fs_dir_file_name(src, &src_dir, &src_file);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (void) dav_fs_dir_file_name(dst, &dst_dir, &dst_file);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Get the corresponding state files for each resource */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_dbm_get_statefiles(p, src_file, &src_state1, &src_state2);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_dbm_get_statefiles(p, dst_file, &dst_state1, &dst_state2);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#if DAV_DEBUG
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if ((src_state2 != NULL && dst_state2 == NULL) ||
54d22ed1c429b903b029bbd62621f11a9e286137minfrin (src_state2 == NULL && dst_state2 != NULL)) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "DESIGN ERROR: dav_dbm_get_statefiles() "
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "returned inconsistent results.");
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
e8f95a682820a599fe41b22977010636be5c2717jim#endif
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
8a03cd420b800a2428f49f4617293de9b2387b20jorton err = dav_fs_copymove_state(is_move, p,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin src_dir, src_state1,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dst_dir, dst_state1,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin pbuf);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (err == NULL && src_state2 != NULL) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin err = dav_fs_copymove_state(is_move, p,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin src_dir, src_state2,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dst_dir, dst_state2,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin pbuf);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (err != NULL) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* ### CRAP. inconsistency. */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* ### should perform some cleanup at the target if we still
54d22ed1c429b903b029bbd62621f11a9e286137minfrin ### have the original files */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* Change the error to reflect the bad server state. */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin err->status = HTTP_INTERNAL_SERVER_ERROR;
edc346c3223efd41e6a2057c37cea69744b73dccwrowe err->desc =
edc346c3223efd41e6a2057c37cea69744b73dccwrowe "Could not fully copy/move the properties. "
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "The server is now in an inconsistent state.";
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return err;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic dav_error *dav_fs_deleteset(apr_pool_t *p, const dav_resource *resource)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *dirpath;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *fname;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *state1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *state2;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *pathname;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t status;
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim /* Get directory, filename, and state-file names for the resource */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* ### should test this result value... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (void) dav_fs_dir_file_name(resource, &dirpath, &fname);
e8f95a682820a599fe41b22977010636be5c2717jim dav_dbm_get_statefiles(p, fname, &state1, &state2);
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe /* build the propset pathname for the file */
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe pathname = apr_pstrcat(p,
f0f6f1b90ab582896f8a7d56d85bd62a55e57d90covener dirpath,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe "/" DAV_FS_STATE_DIR "/",
54d22ed1c429b903b029bbd62621f11a9e286137minfrin state1,
560fd0658902ab57754616c172d8953e69fc4722bnicholes NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /* note: we may get ENOENT if the state dir is not present */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && !APR_STATUS_IS_ENOENT(status)) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
9ad7b260be233be7d7b5576979825cac72e15498rederpj "Could not remove properties.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (state2 != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* build the propset pathname for the file */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pathname = apr_pstrcat(p,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dirpath,
560fd0658902ab57754616c172d8953e69fc4722bnicholes "/" DAV_FS_STATE_DIR "/",
560fd0658902ab57754616c172d8953e69fc4722bnicholes state2,
560fd0658902ab57754616c172d8953e69fc4722bnicholes NULL);
560fd0658902ab57754616c172d8953e69fc4722bnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && !APR_STATUS_IS_ENOENT(status)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### CRAP. only removed half. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not fully remove properties. "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "The server is now in an inconsistent "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "state.");
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim return NULL;
e8f95a682820a599fe41b22977010636be5c2717jim}
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim/* --------------------------------------------------------------------
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** REPOSITORY HOOK FUNCTIONS
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_get_resource(
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes request_rec *r,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *root_dir,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *label,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int use_checked_in,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource **result_resource)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource_private *ctx;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource *resource;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *filename;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### optimize this into a single allocation! */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Create private resource context descriptor */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx = apr_pcalloc(r->pool, sizeof(*ctx));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->finfo = r->finfo;
e8f95a682820a599fe41b22977010636be5c2717jim
560fd0658902ab57754616c172d8953e69fc4722bnicholes /* ### this should go away */
e8f95a682820a599fe41b22977010636be5c2717jim ctx->pool = r->pool;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Preserve case on OSes which fold canonical filenames */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#if 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### not available in Apache 2.0 yet */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filename = r->case_preserved_filename;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#else
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filename = r->filename;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** If there is anything in the path_info, then this indicates that the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** entire path was not used to specify the file/dir. We want to append
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** it onto the filename so that we get a "valid" pathname for null
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** resources.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = apr_pstrcat(r->pool, filename, r->path_info, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* make sure the pathname does not have a trailing "/" */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes len = strlen(s);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (len > 1 && s[len - 1] == '/') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s[len - 1] = '\0';
0e05808dc59a321566303084c84b9826a4353cefrederpj }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->pathname = s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Create resource descriptor */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener resource = apr_pcalloc(r->pool, sizeof(*resource));
0e05808dc59a321566303084c84b9826a4353cefrederpj resource->type = DAV_RESOURCE_TYPE_REGULAR;
ebe5305f8b22507374358f32b74d12fb50c05a25covener resource->info = ctx;
ebe5305f8b22507374358f32b74d12fb50c05a25covener resource->hooks = &dav_hooks_repository_fs;
ebe5305f8b22507374358f32b74d12fb50c05a25covener resource->pool = r->pool;
ebe5305f8b22507374358f32b74d12fb50c05a25covener
ebe5305f8b22507374358f32b74d12fb50c05a25covener /* make sure the URI does not have a trailing "/" */
ebe5305f8b22507374358f32b74d12fb50c05a25covener len = strlen(r->uri);
ebe5305f8b22507374358f32b74d12fb50c05a25covener if (len > 1 && r->uri[len - 1] == '/') {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener s = apr_pstrdup(r->pool, r->uri);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener s[len - 1] = '\0';
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener resource->uri = s;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener else {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener resource->uri = r->uri;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (r->finfo.filetype != 0) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener resource->exists = 1;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener resource->collection = r->finfo.filetype == APR_DIR;
0e05808dc59a321566303084c84b9826a4353cefrederpj
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* unused info in the URL will indicate a null resource */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (r->path_info != NULL && *r->path_info != '\0') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (resource->collection) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* only a trailing "/" is allowed */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (*r->path_info != '/' || r->path_info[1] != '\0') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** This URL/filename represents a locknull resource or
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** possibly a destination of a MOVE/COPY
9ad7b260be233be7d7b5576979825cac72e15498rederpj */
9ad7b260be233be7d7b5576979825cac72e15498rederpj resource->exists = 0;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin resource->collection = 0;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else
54d22ed1c429b903b029bbd62621f11a9e286137minfrin {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /*
560fd0658902ab57754616c172d8953e69fc4722bnicholes ** The base of the path refers to a file -- nothing should
54d22ed1c429b903b029bbd62621f11a9e286137minfrin ** be in path_info. The resource is simply an error: it
54d22ed1c429b903b029bbd62621f11a9e286137minfrin ** can't be a null or a locknull resource.
54d22ed1c429b903b029bbd62621f11a9e286137minfrin */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener "The URL contains extraneous path "
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener "components. The resource could not "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "be identified.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* retain proper integrity across the structures */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!resource->exists) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->finfo.filetype = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *result_resource = resource;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_get_parent_resource(const dav_resource *resource,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource **result_parent)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe dav_resource_private *ctx = resource->info;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe dav_resource_private *parent_ctx;
e8f95a682820a599fe41b22977010636be5c2717jim dav_resource *parent_resource;
e8f95a682820a599fe41b22977010636be5c2717jim apr_status_t rv;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe char *dirpath;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *testroot;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *testpath;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /* If we're at the root of the URL space, then there is no parent. */
e8f95a682820a599fe41b22977010636be5c2717jim if (strcmp(resource->uri, "/") == 0) {
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe *result_parent = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* If given resource is root, then there is no parent.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless we can retrieve the filepath root, this is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * intendend to fail. If we split the root and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * no path info remains, then we also fail.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes testpath = ctx->pathname;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_filepath_root(&testroot, &testpath, 0, ctx->pool);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if ((rv != APR_SUCCESS && rv != APR_ERELATIVE)
e8f95a682820a599fe41b22977010636be5c2717jim || !testpath || !*testpath) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe *result_parent = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### optimize this into a single allocation! */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Create private resource context descriptor */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_ctx = apr_pcalloc(ctx->pool, sizeof(*parent_ctx));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### this should go away */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_ctx->pool = ctx->pool;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (strlen(dirpath) > 1 && dirpath[strlen(dirpath) - 1] == '/')
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dirpath[strlen(dirpath) - 1] = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_ctx->pathname = dirpath;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource = apr_pcalloc(ctx->pool, sizeof(*parent_resource));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource->info = parent_ctx;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource->collection = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource->hooks = &dav_hooks_repository_fs;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource->pool = resource->pool;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (resource->uri != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *uri = ap_make_dirstr_parent(ctx->pool, resource->uri);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (strlen(uri) > 1 && uri[strlen(uri) - 1] == '/')
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes uri[strlen(uri) - 1] = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource->uri = uri;
e8f95a682820a599fe41b22977010636be5c2717jim }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_stat(&parent_ctx->finfo, parent_ctx->pathname,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_FINFO_NORM, ctx->pool);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (rv == APR_SUCCESS || rv == APR_INCOMPLETE) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parent_resource->exists = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *result_parent = parent_resource;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int dav_fs_is_same_resource(
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_resource *res1,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_resource *res2)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource_private *ctx1 = res1->info;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource_private *ctx2 = res2->info;
43c3e6a4b559b76b750c245ee95e2782c15b4296jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (res1->hooks != res2->hooks)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((ctx1->finfo.filetype != 0) && (ctx2->finfo.filetype != 0)
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes && (ctx1->finfo.valid & ctx2->finfo.valid & APR_FINFO_INODE)) {
43c3e6a4b559b76b750c245ee95e2782c15b4296jim return ctx1->finfo.inode == ctx2->finfo.inode;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return strcmp(ctx1->pathname, ctx2->pathname) == 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener}
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener
37af4b0cf648275b68ff41c866c665b4ccf4667dcovenerstatic int dav_fs_is_parent_resource(
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener const dav_resource *res1,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe const dav_resource *res2)
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe{
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe dav_resource_private *ctx1 = res1->info;
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes dav_resource_private *ctx2 = res2->info;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t len1 = strlen(ctx1->pathname);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t len2;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (res1->hooks != res2->hooks)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* it is safe to use ctx2 now */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes len2 = strlen(ctx2->pathname);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return (len2 > len1
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && memcmp(ctx1->pathname, ctx2->pathname, len1) == 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && ctx2->pathname[len1] == '/');
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_open_stream(const dav_resource *resource,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_stream_mode mode,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_stream **stream)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_t *p = resource->info->pool;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_stream *ds = apr_pcalloc(p, sizeof(*ds));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_int32_t flags;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t rv;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim switch (mode) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes default:
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe flags = APR_READ | APR_BINARY;
e8f95a682820a599fe41b22977010636be5c2717jim break;
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe case DAV_MODE_WRITE_TRUNC:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes flags = APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case DAV_MODE_WRITE_SEEKABLE:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes flags = APR_WRITE | APR_CREATE | APR_BINARY;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ds->p = p;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ds->pathname = resource->info->pathname;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT, ds->p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (rv != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(p, MAP_IO2HTTP(rv), 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "An error occurred while opening a resource.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* (APR registers cleanups for the fd with the pool) */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem *stream = ds;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
8113dac419143273351446c3ad653f3fe5ba5cfdwrowestatic dav_error * dav_fs_close_stream(dav_stream *stream, int commit)
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_file_close(stream->f);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim if (!commit) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_file_remove(stream->pathname, stream->p) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### use a better description? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "There was a problem removing (rolling "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "back) the resource "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "when it was being closed.");
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_write_stream(dav_stream *stream,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const void *buf, apr_size_t bufsize)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t status;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes status = apr_file_write_full(stream->f, buf, bufsize, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (APR_STATUS_IS_ENOSPC(status)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(stream->p, HTTP_INSUFFICIENT_STORAGE, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "There is not enough storage to write to "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "this resource.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim else if (status != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### use something besides 500? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "An error occurred while writing to a "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "resource.");
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return NULL;
e8f95a682820a599fe41b22977010636be5c2717jim}
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowestatic dav_error * dav_fs_seek_stream(dav_stream *stream, apr_off_t abs_pos)
e8f95a682820a599fe41b22977010636be5c2717jim{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_file_seek(stream->f, APR_SET, &abs_pos) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### should check whether apr_file_seek set abs_pos was set to the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * correct position? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### use something besides 500? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not seek to specified position in the "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "resource.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#if DEBUG_GET_HANDLER
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* only define set_headers() and deliver() for debug purposes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_set_headers(request_rec *r,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_resource *resource)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* ### this function isn't really used since we have a get_pathname */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (!resource->exists)
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return NULL;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* make sure the proper mtime is in the request record */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_update_mtime(r, resource->info->finfo.mtime);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### note that these use r->filename rather than <resource> */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_set_last_modified(r);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_set_etag(r);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* we accept byte-ranges */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_setn(r->headers_out, "Accept-Ranges", "bytes");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* set up the Content-Length header */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_set_content_length(r, resource->info->finfo.size);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* ### how to set the content type? */
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes /* ### until this is resolved, the Content-Type header is busted */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
37af4b0cf648275b68ff41c866c665b4ccf4667dcovenerstatic dav_error * dav_fs_deliver(const dav_resource *resource,
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener ap_filter_t *output)
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener{
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener apr_pool_t *pool = resource->pool;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener apr_bucket_brigade *bb;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_file_t *fd;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t status;
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes apr_bucket *bkt;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Check resource type */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (resource->type != DAV_RESOURCE_TYPE_REGULAR
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && resource->type != DAV_RESOURCE_TYPE_VERSION
e8f95a682820a599fe41b22977010636be5c2717jim && resource->type != DAV_RESOURCE_TYPE_WORKING) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(pool, HTTP_CONFLICT, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Cannot GET this type of resource.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (resource->collection) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(pool, HTTP_CONFLICT, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "There is no default response to GET for a "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "collection.");
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((status = apr_file_open(&fd, resource->info->pathname,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe APR_READ | APR_BINARY, 0,
e8f95a682820a599fe41b22977010636be5c2717jim pool)) != APR_SUCCESS) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe return dav_new_error(pool, HTTP_FORBIDDEN, 0,
e8f95a682820a599fe41b22977010636be5c2717jim "File permissions deny server access.");
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim bb = apr_brigade_create(pool, output->c->bucket_alloc);
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe apr_brigade_insert_file(bb, fd, 0, resource->info->finfo.size, pool);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj bkt = apr_bucket_eos_create(output->c->bucket_alloc);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj APR_BRIGADE_INSERT_TAIL(bb, bkt);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return dav_new_error(pool, HTTP_FORBIDDEN, 0,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Could not write contents to filter.");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif /* DEBUG_GET_HANDLER */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_create_collection(dav_resource *resource)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource_private *ctx = resource->info;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t status;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes status = apr_dir_make(ctx->pathname, APR_OS_DEFAULT, ctx->pool);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (APR_STATUS_IS_ENOSPC(status)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(ctx->pool, HTTP_INSUFFICIENT_STORAGE, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "There is not enough storage to create "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "this collection.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (APR_STATUS_IS_ENOENT(status)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(ctx->pool, HTTP_CONFLICT, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Cannot create collection; intermediate "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "collection does not exist.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (status != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### refine this error message? */
8869662bb1a4078297020e94ae5e928626d877c6rederpj return dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Unable to create collection.");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* update resource state to show it exists as a collection */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem resource->exists = 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem resource->collection = 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8869662bb1a4078297020e94ae5e928626d877c6rederpj return NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj}
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic dav_error * dav_fs_copymove_walker(dav_walk_resource *wres,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int calltype)
8869662bb1a4078297020e94ae5e928626d877c6rederpj{
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_fs_copymove_walk_ctx *ctx = wres->walk_ctx;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_resource_private *srcinfo = wres->resource->info;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_resource_private *dstinfo = ctx->res_dst->info;
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_error *err = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (wres->resource->collection) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (calltype == DAV_CALLTYPE_POSTFIX) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* Postfix call for MOVE. delete the source dir.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * Note: when copying, we do not enable the postfix-traversal.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### we are ignoring any error here; what should we do? */
8869662bb1a4078297020e94ae5e928626d877c6rederpj (void) apr_dir_remove(srcinfo->pathname, ctx->pool);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj else {
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* copy/move of a collection. Create the new, target collection */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (apr_dir_make(dstinfo->pathname, APR_OS_DEFAULT,
8869662bb1a4078297020e94ae5e928626d877c6rederpj ctx->pool) != APR_SUCCESS) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### assume it was a permissions problem */
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### need a description here */
8869662bb1a4078297020e94ae5e928626d877c6rederpj err = dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0, NULL);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj else {
8869662bb1a4078297020e94ae5e928626d877c6rederpj err = dav_fs_copymove_file(ctx->is_move, ctx->pool,
6733d943c9e8d0f27dd077a04037e8c49eb090ffcovener srcinfo->pathname, dstinfo->pathname,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem &srcinfo->finfo,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ctx->res_dst->exists ? &dstinfo->finfo : NULL,
8869662bb1a4078297020e94ae5e928626d877c6rederpj &ctx->work_buf);
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### push a higher-level description? */
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /*
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** If we have a "not so bad" error, then it might need to go into a
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** multistatus response.
8869662bb1a4078297020e94ae5e928626d877c6rederpj **
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** For a MOVE, it will always go into the multistatus. It could be
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** that everything has been moved *except* for the root. Using a
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** multistatus (with no errors for the other resources) will signify
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** this condition.
8869662bb1a4078297020e94ae5e928626d877c6rederpj **
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** For a COPY, we are traversing in a prefix fashion. If the root fails,
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** then we can just bail out now.
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (err != NULL
8869662bb1a4078297020e94ae5e928626d877c6rederpj && !ap_is_HTTP_SERVER_ERROR(err->status)
8869662bb1a4078297020e94ae5e928626d877c6rederpj && (ctx->is_move
8869662bb1a4078297020e94ae5e928626d877c6rederpj || !dav_fs_is_same_resource(wres->resource, ctx->root))) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### use errno to generate DAV:responsedescription? */
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_add_response(wres, err->status, NULL);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* the error is in the multistatus now. do not stop the traversal. */
8869662bb1a4078297020e94ae5e928626d877c6rederpj return NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj return err;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic dav_error *dav_fs_copymove_resource(
8869662bb1a4078297020e94ae5e928626d877c6rederpj int is_move,
8869662bb1a4078297020e94ae5e928626d877c6rederpj const dav_resource *src,
8869662bb1a4078297020e94ae5e928626d877c6rederpj const dav_resource *dst,
8869662bb1a4078297020e94ae5e928626d877c6rederpj int depth,
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_response **response)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_error *err = NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_buffer work_buf = { 0 };
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem *response = NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* if a collection, recursively copy/move it and its children,
8869662bb1a4078297020e94ae5e928626d877c6rederpj * including the state dirs
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (src->collection) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_walk_params params = { 0 };
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_response *multi_status;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj params.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_HIDDEN;
8869662bb1a4078297020e94ae5e928626d877c6rederpj params.func = dav_fs_copymove_walker;
8869662bb1a4078297020e94ae5e928626d877c6rederpj params.pool = src->info->pool;
8869662bb1a4078297020e94ae5e928626d877c6rederpj params.root = src;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* params.walk_ctx is managed by dav_fs_internal_walk() */
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* postfix is needed for MOVE to delete source dirs */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (is_move)
8869662bb1a4078297020e94ae5e928626d877c6rederpj params.walk_type |= DAV_WALKTYPE_POSTFIX;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* note that we return the error OR the multistatus. never both */
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj if ((err = dav_fs_internal_walk(&params, depth, is_move, dst,
8869662bb1a4078297020e94ae5e928626d877c6rederpj &multi_status)) != NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* on a "real" error, then just punt. nothing else to do. */
8869662bb1a4078297020e94ae5e928626d877c6rederpj return err;
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((*response = multi_status) != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* some multistatus responses exist. wrap them in a 207 */
8869662bb1a4078297020e94ae5e928626d877c6rederpj return dav_new_error(src->info->pool, HTTP_MULTI_STATUS, 0,
8869662bb1a4078297020e94ae5e928626d877c6rederpj "Error(s) occurred on some resources during "
8869662bb1a4078297020e94ae5e928626d877c6rederpj "the COPY/MOVE process.");
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj return NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* not a collection */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if ((err = dav_fs_copymove_file(is_move, src->info->pool,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj src->info->pathname, dst->info->pathname,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem &src->info->finfo,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dst->exists ? &dst->info->finfo : NULL,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem &work_buf)) != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### push a higher-level description? */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return err;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* copy/move properties as well */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return dav_fs_copymoveset(is_move, src->info->pool, src, dst, &work_buf);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic dav_error * dav_fs_copy_resource(
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const dav_resource *src,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_resource *dst,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int depth,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_response **response)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_error *err;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem#if DAV_DEBUG
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (src->hooks != dst->hooks) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /*
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** ### strictly speaking, this is a design error; we should not
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** ### have reached this point.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return dav_new_error(src->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "DESIGN ERROR: a mix of repositories "
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "was passed to copy_resource.");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem#endif
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((err = dav_fs_copymove_resource(0, src, dst, depth,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem response)) == NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* update state of destination resource to show it exists */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dst->exists = 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dst->collection = src->collection;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return err;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
11ca38a20ab9b2d00258f745620e2724838e7e21rederpjstatic dav_error * dav_fs_move_resource(
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_resource *src,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_resource *dst,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_response **response)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj dav_resource_private *srcinfo = src->info;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj dav_resource_private *dstinfo = dst->info;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj dav_error *err;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj int can_rename = 0;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj#if DAV_DEBUG
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj if (src->hooks != dst->hooks) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /*
a9c4332dc6241dc11dd104826bd179d42ccc0f12fuankg ** ### strictly speaking, this is a design error; we should not
a9c4332dc6241dc11dd104826bd179d42ccc0f12fuankg ** ### have reached this point.
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj */
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj return dav_new_error(src->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj "DESIGN ERROR: a mix of repositories "
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj "was passed to move_resource.");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem#endif
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* determine whether a simple rename will work.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * Assume source exists, else we wouldn't get called.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (dstinfo->finfo.filetype != 0) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (dstinfo->finfo.device == srcinfo->finfo.device) {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj /* target exists and is on the same device. */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj can_rename = 1;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj else {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const char *dirpath;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_finfo_t finfo;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_status_t rv;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* destination does not exist, but the parent directory should,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * so try it
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dirpath = ap_make_dirstr_parent(dstinfo->pool, dstinfo->pathname);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /*
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * XXX: If missing dev ... then what test?
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj * Really need a try and failover for those platforms.
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj *
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj rv = apr_stat(&finfo, dirpath, APR_FINFO_DEV, dstinfo->pool);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if ((rv == APR_SUCCESS || rv == APR_INCOMPLETE)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj && (finfo.valid & srcinfo->finfo.valid & APR_FINFO_DEV)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj && (finfo.device == srcinfo->finfo.device)) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj can_rename = 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* if we can't simply rename, then do it the hard way... */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (!can_rename) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if ((err = dav_fs_copymove_resource(1, src, dst, DAV_INFINITY,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj response)) == NULL) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* update resource states */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj dst->exists = 1;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj dst->collection = src->collection;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj src->exists = 0;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj src->collection = 0;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return err;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* a rename should work. do it, and move properties as well */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* no multistatus response */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem *response = NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* ### APR has no rename? */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (apr_file_rename(srcinfo->pathname, dstinfo->pathname,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem srcinfo->pool) != APR_SUCCESS) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### should have a better error than this. */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return dav_new_error(srcinfo->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Could not rename resource.");
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* update resource states */
0e05808dc59a321566303084c84b9826a4353cefrederpj dst->exists = 1;
0e05808dc59a321566303084c84b9826a4353cefrederpj dst->collection = src->collection;
0e05808dc59a321566303084c84b9826a4353cefrederpj src->exists = 0;
0e05808dc59a321566303084c84b9826a4353cefrederpj src->collection = 0;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((err = dav_fs_copymoveset(1, src->info->pool,
0e05808dc59a321566303084c84b9826a4353cefrederpj src, dst, NULL)) == NULL) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* no error. we're done. go ahead and return now. */
0e05808dc59a321566303084c84b9826a4353cefrederpj return NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* error occurred during properties move; try to put resource back */
0e05808dc59a321566303084c84b9826a4353cefrederpj if (apr_file_rename(dstinfo->pathname, srcinfo->pathname,
0e05808dc59a321566303084c84b9826a4353cefrederpj srcinfo->pool) != APR_SUCCESS) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* couldn't put it back! */
0e05808dc59a321566303084c84b9826a4353cefrederpj return dav_push_error(srcinfo->pool,
0e05808dc59a321566303084c84b9826a4353cefrederpj HTTP_INTERNAL_SERVER_ERROR, 0,
0e05808dc59a321566303084c84b9826a4353cefrederpj "The resource was moved, but a failure "
0e05808dc59a321566303084c84b9826a4353cefrederpj "occurred during the move of its "
0e05808dc59a321566303084c84b9826a4353cefrederpj "properties. The resource could not be "
0e05808dc59a321566303084c84b9826a4353cefrederpj "restored to its original location. The "
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "server is now in an inconsistent state.",
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj err);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* update resource states again */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj src->exists = 1;
0e05808dc59a321566303084c84b9826a4353cefrederpj src->collection = dst->collection;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj dst->exists = 0;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dst->collection = 0;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* resource moved back, but properties may be inconsistent */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return dav_push_error(srcinfo->pool,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem HTTP_INTERNAL_SERVER_ERROR, 0,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "The resource was moved, but a failure "
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "occurred during the move of its properties. "
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "The resource was moved back to its original "
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "location, but its properties may have been "
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "partially moved. The server may be in an "
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "inconsistent state.",
0e05808dc59a321566303084c84b9826a4353cefrederpj err);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic dav_error * dav_fs_delete_walker(dav_walk_resource *wres, int calltype)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj{
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj dav_resource_private *info = wres->resource->info;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* do not attempt to remove a null resource,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * or a collection with children
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (wres->resource->exists &&
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj (!wres->resource->collection || calltype == DAV_CALLTYPE_POSTFIX)) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* try to remove the resource */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_status_t result;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj result = wres->resource->collection
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj ? apr_dir_remove(info->pathname, wres->pool)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem : apr_file_remove(info->pathname, wres->pool);
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /*
0e05808dc59a321566303084c84b9826a4353cefrederpj ** If an error occurred, then add it to multistatus response.
0e05808dc59a321566303084c84b9826a4353cefrederpj ** Note that we add it for the root resource, too. It is quite
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** possible to delete the whole darn tree, yet fail on the root.
0e05808dc59a321566303084c84b9826a4353cefrederpj **
0e05808dc59a321566303084c84b9826a4353cefrederpj ** (also: remember we are deleting via a postfix traversal)
0e05808dc59a321566303084c84b9826a4353cefrederpj */
0e05808dc59a321566303084c84b9826a4353cefrederpj if (result != APR_SUCCESS) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* ### assume there is a permissions problem */
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* ### use errno to generate DAV:responsedescription? */
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_add_response(wres, HTTP_FORBIDDEN, NULL);
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj return NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj}
0e05808dc59a321566303084c84b9826a4353cefrederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpjstatic dav_error * dav_fs_remove_resource(dav_resource *resource,
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_response **response)
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem{
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_resource_private *info = resource->info;
0e05808dc59a321566303084c84b9826a4353cefrederpj
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem *response = NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* if a collection, recursively remove it and its children,
0e05808dc59a321566303084c84b9826a4353cefrederpj * including the state dirs
0e05808dc59a321566303084c84b9826a4353cefrederpj */
0e05808dc59a321566303084c84b9826a4353cefrederpj if (resource->collection) {
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_walk_params params = { 0 };
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_error *err = NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_response *multi_status;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj params.walk_type = (DAV_WALKTYPE_NORMAL
0e05808dc59a321566303084c84b9826a4353cefrederpj | DAV_WALKTYPE_HIDDEN
0e05808dc59a321566303084c84b9826a4353cefrederpj | DAV_WALKTYPE_POSTFIX);
0e05808dc59a321566303084c84b9826a4353cefrederpj params.func = dav_fs_delete_walker;
0e05808dc59a321566303084c84b9826a4353cefrederpj params.pool = info->pool;
0e05808dc59a321566303084c84b9826a4353cefrederpj params.root = resource;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((err = dav_fs_walk(&params, DAV_INFINITY,
0e05808dc59a321566303084c84b9826a4353cefrederpj &multi_status)) != NULL) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* on a "real" error, then just punt. nothing else to do. */
0e05808dc59a321566303084c84b9826a4353cefrederpj return err;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((*response = multi_status) != NULL) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* some multistatus responses exist. wrap them in a 207 */
0e05808dc59a321566303084c84b9826a4353cefrederpj return dav_new_error(info->pool, HTTP_MULTI_STATUS, 0,
0e05808dc59a321566303084c84b9826a4353cefrederpj "Error(s) occurred on some resources during "
0e05808dc59a321566303084c84b9826a4353cefrederpj "the deletion process.");
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* no errors... update resource state */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj resource->exists = 0;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj resource->collection = 0;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* not a collection; remove the file and its properties */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (apr_file_remove(info->pathname, info->pool) != APR_SUCCESS) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* ### put a description in here */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return dav_new_error(info->pool, HTTP_FORBIDDEN, 0, NULL);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* update resource state */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj resource->exists = 0;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj resource->collection = 0;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* remove properties and return its result */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return dav_fs_deleteset(info->pool, resource);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj/* ### move this to dav_util? */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem/* Walk recursively down through directories, *
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * including lock-null resources as we go. */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const dav_walk_params *params = fsctx->params;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_pool_t *pool = params->pool;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_error *err = NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int isdir = fsctx->res1.collection;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj apr_finfo_t dirent;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj apr_dir_t *dirp;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ensure the context is prepared properly, then call the func */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem err = (*params->func)(&fsctx->wres,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem isdir
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ? DAV_CALLTYPE_COLLECTION
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem : DAV_CALLTYPE_MEMBER);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (err != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return err;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (depth == 0 || !isdir) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* put a trailing slash onto the directory, in preparation for appending
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj * files to it as we discovery them within the directory */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj dav_check_bufsize(pool, &fsctx->path1, DAV_BUFFER_PAD);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj fsctx->path1.buf[fsctx->path1.cur_len++] = '/';
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj fsctx->path1.buf[fsctx->path1.cur_len] = '\0'; /* in pad area */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* if a secondary path is present, then do that, too */
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe if (fsctx->path2.buf != NULL) {
e8f95a682820a599fe41b22977010636be5c2717jim dav_check_bufsize(pool, &fsctx->path2, DAV_BUFFER_PAD);
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe fsctx->path2.buf[fsctx->path2.cur_len++] = '/';
e8f95a682820a599fe41b22977010636be5c2717jim fsctx->path2.buf[fsctx->path2.cur_len] = '\0'; /* in pad area */
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Note: the URI should ALREADY have a trailing "/" */
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* for this first pass of files, all resources exist */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.exists = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* a file is the default; we'll adjust if we hit a directory */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.collection = 0;
f05787953018140838ad51456c86c965d6a86267jim fsctx->res2.collection = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
f05787953018140838ad51456c86c965d6a86267jim /* open and scan the directory */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((apr_dir_open(&dirp, fsctx->path1.buf, pool)) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### need a better error */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
e8f95a682820a599fe41b22977010636be5c2717jim }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t status;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes len = strlen(dirent.name);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /* avoid recursing into our current, parent, or state directories */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if (dirent.name[0] == '.'
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && (len == 1 || (dirent.name[1] == '.' && len == 2))) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes continue;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (params->walk_type & DAV_WALKTYPE_AUTH) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### need to authorize each file */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### example: .htaccess is normally configured to fail auth */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /* stuff in the state directory is never authorized! */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if (!strcmp(dirent.name, DAV_FS_STATE_DIR)) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes continue;
e8f95a682820a599fe41b22977010636be5c2717jim }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* skip the state dir unless a HIDDEN is performed */
e8f95a682820a599fe41b22977010636be5c2717jim if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && !strcmp(dirent.name, DAV_FS_STATE_DIR)) {
e8f95a682820a599fe41b22977010636be5c2717jim continue;
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* append this file onto the path buffer (copy null term) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer_place_mem(pool, &fsctx->path1, dirent.name, len + 1, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### Optimize me, dirent can give us what we need! */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes status = apr_stat(&fsctx->info1.finfo, fsctx->path1.buf,
e8f95a682820a599fe41b22977010636be5c2717jim APR_FINFO_NORM | APR_FINFO_LINK, pool);
e8f95a682820a599fe41b22977010636be5c2717jim if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
e8f95a682820a599fe41b22977010636be5c2717jim /* woah! where'd it go? */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* ### should have a better error here */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes err = dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener break;
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener }
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener /* copy the file to the URI, too. NOTE: we will pad an extra byte
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener for the trailing slash later. */
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener /* if there is a secondary path, then do that, too */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (fsctx->path2.buf != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer_place_mem(pool, &fsctx->path2, dirent.name, len + 1, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* set up the (internal) pathnames for the two resources */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->info1.pathname = fsctx->path1.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->info2.pathname = fsctx->path2.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* set up the URI for the current resource */
e8f95a682820a599fe41b22977010636be5c2717jim fsctx->res1.uri = fsctx->uri_buf.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### for now, only process regular files (e.g. skip symlinks) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (fsctx->info1.finfo.filetype == APR_REG) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* call the function for the specified dir + file */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if ((err = (*params->func)(&fsctx->wres,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_CALLTYPE_MEMBER)) != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### maybe add a higher-level description? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes else if (fsctx->info1.finfo.filetype == APR_DIR) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t save_path_len = fsctx->path1.cur_len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t save_uri_len = fsctx->uri_buf.cur_len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t save_path2_len = fsctx->path2.cur_len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener /* adjust length to incorporate the subdir name */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener fsctx->path1.cur_len += len;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener fsctx->path2.cur_len += len;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener /* adjust URI length to incorporate subdir and a slash */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe fsctx->uri_buf.cur_len += len + 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* switch over to a collection */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.collection = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res2.collection = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* recurse on the subdir */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### don't always want to quit on error from single child */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((err = dav_fs_walker(fsctx, depth - 1)) != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### maybe add a higher-level description? */
e8f95a682820a599fe41b22977010636be5c2717jim break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* put the various information back */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->path1.cur_len = save_path_len;
e8f95a682820a599fe41b22977010636be5c2717jim fsctx->path2.cur_len = save_path2_len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->uri_buf.cur_len = save_uri_len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.collection = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res2.collection = 0;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* assert: res1.exists == 1 */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### check the return value of this? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_dir_close(dirp);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (err != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (params->walk_type & DAV_WALKTYPE_LOCKNULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t offset = 0;
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* null terminate the directory name */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->path1.buf[fsctx->path1.cur_len - 1] = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Include any lock null resources found in this collection */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.collection = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((err = dav_fs_get_locknull_members(&fsctx->res1,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes &fsctx->locknull_buf)) != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### maybe add a higher-level description? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* put a slash back on the end of the directory */
e8f95a682820a599fe41b22977010636be5c2717jim fsctx->path1.buf[fsctx->path1.cur_len - 1] = '/';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* these are all non-existant (files) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.exists = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.collection = 0;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener memset(&fsctx->info1.finfo, 0, sizeof(fsctx->info1.finfo));
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener while (offset < fsctx->locknull_buf.cur_len) {
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener apr_size_t len = strlen(fsctx->locknull_buf.buf + offset);
bb07ee33bce1a448bcc60ca43720b1ab1c413f87minfrin dav_lock *locks = NULL;
bb07ee33bce1a448bcc60ca43720b1ab1c413f87minfrin
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes ** Append the locknull file to the paths and the URI. Note that
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** we don't have to pad the URI for a slash since a locknull
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** resource is not a collection.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer_place_mem(pool, &fsctx->path1,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->locknull_buf.buf + offset, len + 1, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer_place_mem(pool, &fsctx->uri_buf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->locknull_buf.buf + offset, len + 1, 0);
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes if (fsctx->path2.buf != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer_place_mem(pool, &fsctx->path2,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->locknull_buf.buf + offset,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes len + 1, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* set up the (internal) pathnames for the two resources */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->info1.pathname = fsctx->path1.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->info2.pathname = fsctx->path2.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* set up the URI for the current resource */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.uri = fsctx->uri_buf.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** To prevent a PROPFIND showing an expired locknull
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** resource, query the lock database to force removal
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** of both the lock entry and .locknull, if necessary..
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** Sure, the query in PROPFIND would do this.. after
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** the locknull resource was already included in the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** return.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes **
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes ** NOTE: we assume the caller has opened the lock database
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** if they have provided DAV_WALKTYPE_LOCKNULL.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### we should also look into opening it read-only and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### eliding timed-out items from the walk, yet leaving
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### them in the locknull database until somebody opens
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### the thing writable.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
e8f95a682820a599fe41b22977010636be5c2717jim /* ### probably ought to use has_locks. note the problem
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe ### mentioned above, though... we would traverse this as
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### a locknull, but then a PROPFIND would load the lock
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### info, causing a timeout and the locks would not be
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### reported. Therefore, a null resource would be returned
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### in the PROPFIND.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ###
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### alternative: just load unresolved locks. any direct
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### locks will be timed out (correct). any indirect will
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### not (correct; consider if a parent timed out -- the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### timeout routines do not walk and remove indirects;
e8f95a682820a599fe41b22977010636be5c2717jim ### even the resolve func would probably fail when it
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ### tried to find a timed-out direct lock).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((err = dav_lock_query(params->lockdb, &fsctx->res1,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes &locks)) != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### maybe add a higher-level description? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* call the function for the specified dir + file */
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes if (locks != NULL &&
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (err = (*params->func)(&fsctx->wres,
e8f95a682820a599fe41b22977010636be5c2717jim DAV_CALLTYPE_LOCKNULL)) != NULL) {
e8f95a682820a599fe41b22977010636be5c2717jim /* ### maybe add a higher-level description? */
e8f95a682820a599fe41b22977010636be5c2717jim return err;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe offset += len + 1;
e8f95a682820a599fe41b22977010636be5c2717jim }
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* reset the exists flag */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx->res1.exists = 1;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes }
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if (params->walk_type & DAV_WALKTYPE_POSTFIX) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* replace the dirs' trailing slashes with null terms */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->path1.buf[--fsctx->path1.cur_len] = '\0';
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx->uri_buf.buf[--fsctx->uri_buf.cur_len] = '\0';
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if (fsctx->path2.buf != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->path2.buf[--fsctx->path2.cur_len] = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* this is a collection which exists */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fsctx->res1.collection = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return (*params->func)(&fsctx->wres, DAV_CALLTYPE_POSTFIX);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error * dav_fs_internal_walk(const dav_walk_params *params,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int depth, int is_move,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe const dav_resource *root_dst,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_response **response)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes{
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_walker_context fsctx = { 0 };
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes dav_error *err;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_copymove_walk_ctx cm_ctx = { 0 };
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe#if DAV_DEBUG
e8f95a682820a599fe41b22977010636be5c2717jim if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
e8f95a682820a599fe41b22977010636be5c2717jim && params->lockdb == NULL) {
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe return dav_new_error(params->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "DESIGN ERROR: walker called to walk locknull "
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "resources, but a lockdb was not provided.");
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes }
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#endif
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.params = params;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.wres.walk_ctx = params->walk_ctx;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.wres.pool = params->pool;
f05787953018140838ad51456c86c965d6a86267jim
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* ### zero out versioned, working, baselined? */
f05787953018140838ad51456c86c965d6a86267jim
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.res1 = *params->root;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.res1.pool = params->pool;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
e8f95a682820a599fe41b22977010636be5c2717jim fsctx.res1.info = &fsctx.info1;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.info1 = *params->root->info;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* the pathname is stored in the path1 buffer */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_buffer_init(params->pool, &fsctx.path1, fsctx.info1.pathname);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.info1.pathname = fsctx.path1.buf;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
e8f95a682820a599fe41b22977010636be5c2717jim if (root_dst != NULL) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* internal call from the COPY/MOVE code. set it up. */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.wres.walk_ctx = &cm_ctx;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes cm_ctx.is_move = is_move;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes cm_ctx.res_dst = &fsctx.res2;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes cm_ctx.root = params->root;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes cm_ctx.pool = params->pool;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.res2 = *root_dst;
e8f95a682820a599fe41b22977010636be5c2717jim fsctx.res2.exists = 0;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe fsctx.res2.collection = 0;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.res2.uri = NULL; /* we don't track this */
e8f95a682820a599fe41b22977010636be5c2717jim fsctx.res2.pool = params->pool;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.res2.info = &fsctx.info2;
e8f95a682820a599fe41b22977010636be5c2717jim fsctx.info2 = *root_dst->info;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* res2 does not exist -- clear its finfo structure */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes memset(&fsctx.info2.finfo, 0, sizeof(fsctx.info2.finfo));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* the pathname is stored in the path2 buffer */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_buffer_init(params->pool, &fsctx.path2, fsctx.info2.pathname);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.info2.pathname = fsctx.path2.buf;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes }
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener /* prep the URI buffer */
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener /* if we have a directory, then ensure the URI has a trailing "/" */
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener if (fsctx.res1.collection
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener && fsctx.uri_buf.buf[fsctx.uri_buf.cur_len - 1] != '/') {
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener /* this will fall into the pad area */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.uri_buf.buf[fsctx.uri_buf.cur_len++] = '/';
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.uri_buf.buf[fsctx.uri_buf.cur_len] = '\0';
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes }
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* the current resource's URI is stored in the uri_buf buffer */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.res1.uri = fsctx.uri_buf.buf;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* point the callback's resource at our structure */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes fsctx.wres.resource = &fsctx.res1;
e8f95a682820a599fe41b22977010636be5c2717jim
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* always return the error, and any/all multistatus responses */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes err = dav_fs_walker(&fsctx, depth);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes *response = fsctx.wres.response;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes return err;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe}
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholesstatic dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_response **response)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes{
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* always return the error, and any/all multistatus responses */
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes return dav_fs_internal_walk(params, depth, 0, NULL, response);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes}
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes/* dav_fs_etag: Stolen from ap_make_etag. Creates a strong etag
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes * for file path.
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener * ### do we need to return weak tags sometimes?
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovenerstatic const char *dav_fs_getetag(const dav_resource *resource)
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener{
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener dav_resource_private *ctx = resource->info;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if (!resource->exists)
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes return apr_pstrdup(ctx->pool, "");
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if (ctx->finfo.filetype != 0) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes return apr_psprintf(ctx->pool, "\"%lx-%lx-%lx\"",
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes (unsigned long) ctx->finfo.inode,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes (unsigned long) ctx->finfo.size,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes (unsigned long) ctx->finfo.mtime);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes }
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes return apr_psprintf(ctx->pool, "\"%lx\"", (unsigned long) ctx->finfo.mtime);
e8f95a682820a599fe41b22977010636be5c2717jim}
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholesstatic const dav_hooks_repository dav_hooks_repository_fs =
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes{
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes DEBUG_GET_HANDLER, /* normally: special GET handling not required */
e8f95a682820a599fe41b22977010636be5c2717jim dav_fs_get_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_get_parent_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_is_same_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_is_parent_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_open_stream,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe dav_fs_close_stream,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe dav_fs_write_stream,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_seek_stream,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#if DEBUG_GET_HANDLER
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_set_headers,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_deliver,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#else
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes NULL,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes NULL,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#endif
490046d2a164ad86cc63bd789f32eaed663d239abnicholes dav_fs_create_collection,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_copy_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_move_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_remove_resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_walk,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_fs_getetag,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes};
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholesstatic dav_prop_insert dav_fs_insert_prop(const dav_resource *resource,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes int propid, dav_prop_insert what,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_text_header *phdr)
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes{
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes const char *value;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes const char *s;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_pool_t *p = resource->info->pool;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes const dav_liveprop_spec *info;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes int global_ns;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* an HTTP-date can be 29 chars plus a null term */
e8f95a682820a599fe41b22977010636be5c2717jim /* a 64-bit size can be 20 chars plus a null term */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe char buf[DAV_TIMEBUF_SIZE];
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /*
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** None of FS provider properties are defined if the resource does not
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** exist. Just bail for this case.
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes **
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** Even though we state that the FS properties are not defined, the
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** client cannot store dead values -- we deny that thru the is_writable
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** hook function.
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes */
e8f95a682820a599fe41b22977010636be5c2717jim if (!resource->exists)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes return DAV_PROP_INSERT_NOTDEF;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes switch (propid) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes case DAV_PROPID_creationdate:
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /*
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** Closest thing to a creation date. since we don't actually
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** perform the operations that would modify ctime (after we
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ** create the file), then we should be pretty safe here.
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes */
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes dav_format_time(DAV_STYLE_ISO8601,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes resource->info->finfo.ctime,
e8f95a682820a599fe41b22977010636be5c2717jim buf);
e8f95a682820a599fe41b22977010636be5c2717jim value = buf;
e8f95a682820a599fe41b22977010636be5c2717jim break;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe case DAV_PROPID_getcontentlength:
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* our property, but not defined on collection resources */
e8f95a682820a599fe41b22977010636be5c2717jim if (resource->collection)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes return DAV_PROP_INSERT_NOTDEF;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes (void) sprintf(buf, "%" APR_OFF_T_FMT, resource->info->finfo.size);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes value = buf;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes break;
0c8aa496e9d7676ff8101783398f17c0da1900f7bnicholes
0c8aa496e9d7676ff8101783398f17c0da1900f7bnicholes case DAV_PROPID_getetag:
0c8aa496e9d7676ff8101783398f17c0da1900f7bnicholes value = dav_fs_getetag(resource);
0c8aa496e9d7676ff8101783398f17c0da1900f7bnicholes break;
0c8aa496e9d7676ff8101783398f17c0da1900f7bnicholes
0c8aa496e9d7676ff8101783398f17c0da1900f7bnicholes case DAV_PROPID_getlastmodified:
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes dav_format_time(DAV_STYLE_RFC822,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes resource->info->finfo.mtime,
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes buf);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes value = buf;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes break;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes case DAV_PROPID_FS_executable:
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes /* our property, but not defined on collection resources */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if (resource->collection)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes return DAV_PROP_INSERT_NOTDEF;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* our property, but not defined on this platform */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!(resource->info->finfo.valid & APR_FINFO_UPROT))
e8f95a682820a599fe41b22977010636be5c2717jim return DAV_PROP_INSERT_NOTDEF;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* the files are "ours" so we only need to check owner exec privs */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (resource->info->finfo.protection & APR_UEXECUTE)
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe value = "T";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes value = "F";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin default:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### what the heck was this property? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return DAV_PROP_INSERT_NOTDEF;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* assert: value != NULL */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* get the information and global NS index for the property */
e8f95a682820a599fe41b22977010636be5c2717jim global_ns = dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* assert: info != NULL && info->name != NULL */
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim /* DBG3("FS: inserting lp%d:%s (local %d)", ns, scan->name, scan->ns); */
43c3e6a4b559b76b750c245ee95e2782c15b4296jim
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes if (what == DAV_PROP_INSERT_VALUE) {
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes global_ns, info->name, value, global_ns, info->name);
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes }
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes else if (what == DAV_PROP_INSERT_NAME) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
e8f95a682820a599fe41b22977010636be5c2717jim /* assert: what == DAV_PROP_INSERT_SUPPORTED */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = apr_psprintf(p,
e8f95a682820a599fe41b22977010636be5c2717jim "<D:supported-live-property D:name=\"%s\" "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "D:namespace=\"%s\"/>" DEBUG_CR,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes info->name, dav_fs_namespace_uris[info->ns]);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_text_append(p, phdr, s);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /* we inserted what was asked for */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe return what;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jimstatic int dav_fs_is_writable(const dav_resource *resource, int propid)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes const dav_liveprop_spec *info;
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes#ifdef DAV_FS_HAS_EXECUTABLE
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes /* if we have the executable property, and this isn't a collection,
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes then the property is writable. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (propid == DAV_PROPID_FS_executable && !resource->collection)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (void) dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return info->is_writable;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jimstatic dav_error *dav_fs_patch_validate(const dav_resource *resource,
e8f95a682820a599fe41b22977010636be5c2717jim const apr_xml_elem *elem,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int operation,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes void **context,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int *defer_to_dead)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const apr_text *cdata;
e8f95a682820a599fe41b22977010636be5c2717jim const apr_text *f_cdata;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe char value;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_elem_private *priv = elem->priv;
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim if (priv->propid != DAV_PROPID_FS_executable) {
43c3e6a4b559b76b750c245ee95e2782c15b4296jim *defer_to_dead = 1;
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes return NULL;
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes }
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes if (operation == DAV_PROP_OP_DELETE) {
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "The 'executable' property cannot be removed.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim cdata = elem->first_cdata.first;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### hmm. this isn't actually looking at all the possible text items */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes f_cdata = elem->first_child == NULL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ? NULL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes : elem->first_child->following_cdata.first;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /* DBG3("name=%s cdata=%s f_cdata=%s",elem->name,cdata ? cdata->text : "[null]",f_cdata ? f_cdata->text : "[null]"); */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (cdata == NULL) {
e8f95a682820a599fe41b22977010636be5c2717jim if (f_cdata == NULL) {
e8f95a682820a599fe41b22977010636be5c2717jim return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
43c3e6a4b559b76b750c245ee95e2782c15b4296jim "The 'executable' property expects a single "
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes "character, valued 'T' or 'F'. There was no "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "value submitted.");
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes }
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes cdata = f_cdata;
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (f_cdata != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes goto too_long;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (cdata->next != NULL || strlen(cdata->text) != 1)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes goto too_long;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim value = cdata->text[0];
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (value != 'T' && value != 'F') {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "The 'executable' property expects a single "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "character, valued 'T' or 'F'. The value "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "submitted is invalid.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe *context = (void *)((long)(value == 'T'));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim return NULL;
e8f95a682820a599fe41b22977010636be5c2717jim
43c3e6a4b559b76b750c245ee95e2782c15b4296jim too_long:
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes "The 'executable' property expects a single "
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes "character, valued 'T' or 'F'. The value submitted "
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes "has too many characters.");
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error *dav_fs_patch_exec(const dav_resource *resource,
e8f95a682820a599fe41b22977010636be5c2717jim const apr_xml_elem *elem,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int operation,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem void *context,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_liveprop_rollback **rollback_ctx)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes long value = context != NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_fileperms_t perms = resource->info->finfo.protection;
e8f95a682820a599fe41b22977010636be5c2717jim long old_value = (perms & APR_UEXECUTE) != 0;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* assert: prop == executable. operation == SET. */
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim /* don't do anything if there is no change. no rollback info either. */
43c3e6a4b559b76b750c245ee95e2782c15b4296jim /* DBG2("new value=%d (old=%d)", value, old_value); */
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes if (value == old_value)
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes return NULL;
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes perms &= ~APR_UEXECUTE;
3effb85eb3124c6f02cd89e22ffed0fc9afaddb9bnicholes if (value)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes perms |= APR_UEXECUTE;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_file_perms_set(resource->info->pathname, perms) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(resource->info->pool,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not set the executable flag of the "
e8f95a682820a599fe41b22977010636be5c2717jim "target resource.");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* update the resource and set up the rollback context */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes resource->info->finfo.protection = perms;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *rollback_ctx = (dav_liveprop_rollback *)old_value;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return NULL;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic void dav_fs_patch_commit(const dav_resource *resource,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin int operation,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin void *context,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_liveprop_rollback *rollback_ctx)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* nothing to do */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
88adce5ec0da39b41450ce1d5a77659168097e0cjorton
88adce5ec0da39b41450ce1d5a77659168097e0cjortonstatic dav_error *dav_fs_patch_rollback(const dav_resource *resource,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin int operation,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin void *context,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_liveprop_rollback *rollback_ctx)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin apr_fileperms_t perms = resource->info->finfo.protection & ~APR_UEXECUTE;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin int value = rollback_ctx != NULL;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* assert: prop == executable. operation == SET. */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* restore the executable bit */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (value)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin perms |= APR_UEXECUTE;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (apr_file_perms_set(resource->info->pathname, perms) != APR_SUCCESS) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return dav_new_error(resource->info->pool,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin HTTP_INTERNAL_SERVER_ERROR, 0,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "After a failure occurred, the resource's "
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "executable flag could not be restored.");
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* restore the resource's state */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin resource->info->finfo.protection = perms;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return NULL;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic const dav_hooks_liveprop dav_hooks_liveprop_fs =
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_fs_insert_prop,
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes dav_fs_is_writable,
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes dav_fs_namespace_uris,
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes dav_fs_patch_validate,
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes dav_fs_patch_exec,
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes dav_fs_patch_commit,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_fs_patch_rollback
54d22ed1c429b903b029bbd62621f11a9e286137minfrin};
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic const dav_provider dav_fs_provider =
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin &dav_hooks_repository_fs,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin &dav_hooks_db_dbm,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin &dav_hooks_locks_fs,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin NULL, /* vsn */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin NULL, /* binding */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin NULL, /* search */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin NULL /* ctx */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin};
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinvoid dav_fs_gather_propsets(apr_array_header_t *uris)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#ifdef DAV_FS_HAS_EXECUTABLE
54d22ed1c429b903b029bbd62621f11a9e286137minfrin *(const char **)apr_array_push(uris) =
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "<http://apache.org/dav/propset/fs/1>";
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes#endif
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes}
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholesint dav_fs_find_liveprop(const dav_resource *resource,
09338db7fdcf82ecc189195347da3a3ed5d0287abnicholes const char *ns_uri, const char *name,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin const dav_hooks_liveprop **hooks)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* don't try to find any liveprops if this isn't "our" resource */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (resource->hooks != &dav_hooks_repository_fs)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return 0;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return dav_do_find_liveprop(ns_uri, name, &dav_fs_liveprop_group, hooks);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinvoid dav_fs_insert_all_liveprops(request_rec *r, const dav_resource *resource,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_prop_insert what, apr_text_header *phdr)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* don't insert any liveprops if this isn't "our" resource */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (resource->hooks != &dav_hooks_repository_fs)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (!resource->exists) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* a lock-null resource */
e8f95a682820a599fe41b22977010636be5c2717jim /*
e8f95a682820a599fe41b22977010636be5c2717jim ** ### technically, we should insert empty properties. dunno offhand
e8f95a682820a599fe41b22977010636be5c2717jim ** ### what part of the spec said this, but it was essentially thus:
e8f95a682820a599fe41b22977010636be5c2717jim ** ### "the properties should be defined, but may have no value".
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin (void) dav_fs_insert_prop(resource, DAV_PROPID_creationdate,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes what, phdr);
5aa455d45abacfa675c88d4ff53fbe97c44ce545bnicholes (void) dav_fs_insert_prop(resource, DAV_PROPID_getcontentlength,
1223ef8a85a044b5e3a8df29391a66530153aefcbnicholes what, phdr);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin (void) dav_fs_insert_prop(resource, DAV_PROPID_getlastmodified,
d5cff0d8e871bf2528aadd8736fb50dc044b1e6dbnicholes what, phdr);
5aa455d45abacfa675c88d4ff53fbe97c44ce545bnicholes (void) dav_fs_insert_prop(resource, DAV_PROPID_getetag,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes what, phdr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#ifdef DAV_FS_HAS_EXECUTABLE
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Only insert this property if it is defined for this platform. */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin (void) dav_fs_insert_prop(resource, DAV_PROPID_FS_executable,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin what, phdr);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#endif
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* ### we know the others aren't defined as liveprops */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinvoid dav_fs_register(apr_pool_t *p)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* register the namespace URIs */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_register_liveprop_group(p, &dav_fs_liveprop_group);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* register the repository provider */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_register_provider(p, "filesystem", &dav_fs_provider);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin