842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * http://www.apache.org/licenses/LICENSE-2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** DAV filesystem-based repository provider
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gstein
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein#include "apr.h"
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein#include "apr_file_io.h"
8a46775d163c06a8c51d1b0a3f2edfde945cb1d8stoddard#include "apr_strings.h"
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley#include "apr_buckets.h"
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf#if APR_HAVE_UNISTD_H
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf#include <unistd.h> /* for getpid() */
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf#endif
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "httpd.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_log.h"
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#include "http_protocol.h" /* for ap_set_* (in dav_fs_set_headers) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_request.h" /* for ap_update_mtime() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1a9d922232824a7cc008d4f74e48bd82adf5bdedgstein#include "mod_dav.h"
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein#include "repos.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* to assist in debugging mod_dav's GET handling */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define DEBUG_GET_HANDLER 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#define DAV_FS_COPY_BLOCKSIZE 16384 /* copy 16k at a time */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* context needed to identify a resource */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstruct dav_resource_private {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_t *pool; /* memory storage pool associated with request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *pathname; /* full pathname to resource */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_finfo_t finfo; /* filesystem info */
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin request_rec *r;
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* private context for doing a filesystem walk */
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef struct {
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein /* the input walk parameters */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein const dav_walk_params *params;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein /* reused as we walk */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_walk_resource wres;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource res1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private info1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_buffer path1;
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_buffer uri_buf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* MOVE/COPY need a secondary path */
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_resource res2;
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_resource_private info2;
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_buffer path2;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_buffer locknull_buf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein} dav_fs_walker_context;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gsteintypedef struct {
707ecf9559338ec06b24334bc9abcca670325cc4gstein int is_move; /* is this a MOVE? */
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_buffer work_buf; /* handy buffer for copymove_file() */
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* CALLBACK: this is a secondary resource managed specially for us */
707ecf9559338ec06b24334bc9abcca670325cc4gstein const dav_resource *res_dst;
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* copied from dav_walk_params (they are invariant across the walk) */
707ecf9559338ec06b24334bc9abcca670325cc4gstein const dav_resource *root;
707ecf9559338ec06b24334bc9abcca670325cc4gstein apr_pool_t *pool;
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein} dav_fs_copymove_walk_ctx;
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein/* an internal WALKTYPE to walk hidden files (the .DAV directory) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#define DAV_WALKTYPE_HIDDEN 0x4000
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein/* an internal WALKTYPE to call collections (again) after their contents */
707ecf9559338ec06b24334bc9abcca670325cc4gstein#define DAV_WALKTYPE_POSTFIX 0x8000
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein#define DAV_CALLTYPE_POSTFIX 1000 /* a private call type */
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* pull this in from the other source file */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinextern const dav_hooks_locks dav_hooks_locks_fs;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein/* forward-declare the hook structures */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const dav_hooks_repository dav_hooks_repository_fs;
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic const dav_hooks_liveprop dav_hooks_liveprop_fs;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** The namespace URIs that we use. This list and the enumeration must
f4c310fd2555c6faca1f980f00b161eadb089023gstein** stay in sync.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char * const dav_fs_namespace_uris[] =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein "DAV:",
f4c310fd2555c6faca1f980f00b161eadb089023gstein "http://apache.org/dav/props/",
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe NULL /* sentinel */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gsteinenum {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe DAV_FS_URI_DAV, /* the DAV: namespace URI */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe DAV_FS_URI_MYPROPS /* the namespace URI for our custom props */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein/*
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein** Does this platform support an executable flag?
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein**
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein** ### need a way to portably abstract this query
c70afa1853413eb72c4909354c2814d89e9b99f7jorton**
c70afa1853413eb72c4909354c2814d89e9b99f7jorton** DAV_FINFO_MASK gives the appropriate mask to use for the stat call
c70afa1853413eb72c4909354c2814d89e9b99f7jorton** used to get file attributes.
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein*/
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#ifndef WIN32
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#define DAV_FS_HAS_EXECUTABLE
c70afa1853413eb72c4909354c2814d89e9b99f7jorton#define DAV_FINFO_MASK (APR_FINFO_LINK | APR_FINFO_TYPE | APR_FINFO_INODE | \
c70afa1853413eb72c4909354c2814d89e9b99f7jorton APR_FINFO_SIZE | APR_FINFO_CTIME | APR_FINFO_MTIME | \
c70afa1853413eb72c4909354c2814d89e9b99f7jorton APR_FINFO_PROT)
c70afa1853413eb72c4909354c2814d89e9b99f7jorton#else
c70afa1853413eb72c4909354c2814d89e9b99f7jorton/* as above, but without APR_FINFO_PROT */
c70afa1853413eb72c4909354c2814d89e9b99f7jorton#define DAV_FINFO_MASK (APR_FINFO_LINK | APR_FINFO_TYPE | APR_FINFO_INODE | \
c70afa1853413eb72c4909354c2814d89e9b99f7jorton APR_FINFO_SIZE | APR_FINFO_CTIME | APR_FINFO_MTIME)
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#endif
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein** The single property that we define (in the DAV_FS_URI_MYPROPS namespace)
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein#define DAV_PROPID_FS_executable 1
f4c310fd2555c6faca1f980f00b161eadb089023gstein
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf/*
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf * prefix for temporary files
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim#define DAV_FS_TMP_PREFIX ".davfs.tmp"
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic const dav_liveprop_spec dav_fs_props[] =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein /* standard DAV properties */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_FS_URI_DAV,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein "creationdate",
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_PROPID_creationdate,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein 0
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein },
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_FS_URI_DAV,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein "getcontentlength",
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_PROPID_getcontentlength,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein 0
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein },
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_FS_URI_DAV,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein "getetag",
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_PROPID_getetag,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein 0
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein },
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_FS_URI_DAV,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein "getlastmodified",
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_PROPID_getlastmodified,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein 0
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein },
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein /* our custom properties */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_FS_URI_MYPROPS,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein "executable",
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein DAV_PROPID_FS_executable,
956f4b1551215610a57f3b52822dbac6f41a8aa9gstein 0 /* handled special in dav_fs_is_writable */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein },
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe { 0 } /* sentinel */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic const dav_liveprop_group dav_fs_liveprop_group =
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein{
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein dav_fs_props,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein dav_fs_namespace_uris,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein &dav_hooks_liveprop_fs
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein};
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* define the dav_stream structure for our use */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstruct dav_stream {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_t *p;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_file_t *f;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *pathname; /* we may need to remove it at close time */
c08cb1e24083b34387716ee770cc1a321de661a4sf char *temppath;
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf int unlink_on_error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
e8f95a682820a599fe41b22977010636be5c2717jim/* returns an appropriate HTTP status code given an APR status code for a
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton * failed I/O operation. ### use something besides 500? */
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton#define MAP_IO2HTTP(e) (APR_STATUS_IS_ENOSPC(e) ? HTTP_INSUFFICIENT_STORAGE : \
05c31d569e4171a72dea5fee28533ed23f6f1fb2sf APR_STATUS_IS_ENOENT(e) ? HTTP_CONFLICT : \
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton HTTP_INTERNAL_SERVER_ERROR)
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* forward declaration for internal treewalkers */
f94aab38f6ee899f463f0118ea395291f7c5b4cegsteinstatic dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_response **response);
707ecf9559338ec06b24334bc9abcca670325cc4gsteinstatic dav_error * dav_fs_internal_walk(const dav_walk_params *params,
707ecf9559338ec06b24334bc9abcca670325cc4gstein int depth, int is_move,
707ecf9559338ec06b24334bc9abcca670325cc4gstein const dav_resource *root_dst,
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_response **response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* --------------------------------------------------------------------
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** PRIVATE REPOSITORY FUNCTIONS
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
a0c5ae524801374f36b3769d33d32ea1cca5ade3fuankgstatic request_rec *dav_fs_get_request_rec(const dav_resource *resource)
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin{
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin return resource->info->r;
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin}
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmapr_pool_t *dav_fs_pool(const dav_resource *resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return resource->info->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinconst char *dav_fs_pathname(const dav_resource *resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return resource->info->pathname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
cc8241a7ee9815575a267e13eff62b6fddf1fe58gsteindav_error * dav_fs_dir_file_name(
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char **dirpath_p,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char **fname_p)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx = resource->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *dirpath_p = ctx->pathname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (fname_p != NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein *fname_p = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe const char *testpath, *rootpath;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
49bf4df23d9e5281abcd83005550bda818b17b08wrowe apr_size_t dirlen = strlen(dirpath);
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe apr_status_t rv = APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe testpath = dirpath;
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (dirlen > 0) {
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe rv = apr_filepath_root(&rootpath, &testpath, 0, ctx->pool);
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe }
e8f95a682820a599fe41b22977010636be5c2717jim
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe /* remove trailing slash from dirpath, unless it's a root path
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe */
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if ((rv == APR_SUCCESS && testpath && *testpath)
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe || rv == APR_ERELATIVE) {
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (dirpath[dirlen - 1] == '/') {
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe dirpath[dirlen - 1] = '\0';
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe }
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe }
e8f95a682820a599fe41b22977010636be5c2717jim
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe /* ###: Looks like a response could be appropriate
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe *
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe * APR_SUCCESS here tells us the dir is a root
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe * APR_ERELATIVE told us we had no root (ok)
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe * APR_EINCOMPLETE an incomplete testpath told us
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe * there was no -file- name here!
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe * APR_EBADPATH or other errors tell us this file
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe * path is undecipherable
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe */
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (rv == APR_SUCCESS || rv == APR_ERELATIVE) {
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe *dirpath_p = dirpath;
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (fname_p != NULL)
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe *fname_p = ctx->pathname + dirlen;
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe }
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe else {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(ctx->pool, HTTP_INTERNAL_SERVER_ERROR, 0, rv,
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein "An incomplete/bad path was found in "
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein "dav_fs_dir_file_name.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Note: picked up from ap_gm_timestr_822() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* NOTE: buf must be at least DAV_TIMEBUF_SIZE chars in size */
dc52cac281d8b311dc47d115ed979f923b667679rjungstatic void dav_format_time(int style, apr_time_t sec, char *buf, apr_size_t buflen)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh apr_time_exp_t tms;
e8f95a682820a599fe41b22977010636be5c2717jim
f71d4ec448449837beefe21cf7c9f8d9b6bd4654gstein /* ### what to do if fails? */
93ef028b3ac7dc86ec72204233b9d99c69587c54striker (void) apr_time_exp_gmt(&tms, sec);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (style == DAV_STYLE_ISO8601) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### should we use "-00:00" instead of "Z" ?? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* 20 chars plus null term */
dc52cac281d8b311dc47d115ed979f923b667679rjung apr_snprintf(buf, buflen, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ",
6a027960e59525210409d4b4501cecf1c454f0f9wrowe tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
6a027960e59525210409d4b4501cecf1c454f0f9wrowe tms.tm_hour, tms.tm_min, tms.tm_sec);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* RFC 822 date format; as strftime '%a, %d %b %Y %T GMT' */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* 29 chars plus null term */
dc52cac281d8b311dc47d115ed979f923b667679rjung apr_snprintf(buf, buflen, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
dc52cac281d8b311dc47d115ed979f923b667679rjung apr_day_snames[tms.tm_wday],
dc52cac281d8b311dc47d115ed979f923b667679rjung tms.tm_mday, apr_month_snames[tms.tm_mon],
dc52cac281d8b311dc47d115ed979f923b667679rjung tms.tm_year + 1900,
dc52cac281d8b311dc47d115ed979f923b667679rjung tms.tm_hour, tms.tm_min, tms.tm_sec);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7f69a90d847f08a86f9909c2c5129408697a9600jorton/* Copy or move src to dst; src_finfo is used to propagate permissions
7f69a90d847f08a86f9909c2c5129408697a9600jorton * bits across if non-NULL; dst_finfo must be non-NULL iff dst already
7f69a90d847f08a86f9909c2c5129408697a9600jorton * exists. */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_copymove_file(
f4c310fd2555c6faca1f980f00b161eadb089023gstein int is_move,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_t * p,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst,
7f69a90d847f08a86f9909c2c5129408697a9600jorton const apr_finfo_t *src_finfo,
7f69a90d847f08a86f9909c2c5129408697a9600jorton const apr_finfo_t *dst_finfo,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_buffer *pbuf)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_buffer work_buf = { 0 };
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_file_t *inf = NULL;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_file_t *outf = NULL;
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton apr_status_t status;
7f69a90d847f08a86f9909c2c5129408697a9600jorton apr_fileperms_t perms;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pbuf == NULL)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pbuf = &work_buf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7f69a90d847f08a86f9909c2c5129408697a9600jorton /* Determine permissions to use for destination */
7f69a90d847f08a86f9909c2c5129408697a9600jorton if (src_finfo && src_finfo->valid & APR_FINFO_PROT
7f69a90d847f08a86f9909c2c5129408697a9600jorton && src_finfo->protection & APR_UEXECUTE) {
ebf7895684796436b808025426cbfab96d57910dnd perms = src_finfo->protection;
ebf7895684796436b808025426cbfab96d57910dnd
7f69a90d847f08a86f9909c2c5129408697a9600jorton if (dst_finfo != NULL) {
7f69a90d847f08a86f9909c2c5129408697a9600jorton /* chmod it if it already exist */
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_file_perms_set(dst, perms)) != APR_SUCCESS) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
7f69a90d847f08a86f9909c2c5129408697a9600jorton "Could not set permissions on destination");
7f69a90d847f08a86f9909c2c5129408697a9600jorton }
7f69a90d847f08a86f9909c2c5129408697a9600jorton }
e8f95a682820a599fe41b22977010636be5c2717jim }
7f69a90d847f08a86f9909c2c5129408697a9600jorton else {
7f69a90d847f08a86f9909c2c5129408697a9600jorton perms = APR_OS_DEFAULT;
7f69a90d847f08a86f9909c2c5129408697a9600jorton }
7f69a90d847f08a86f9909c2c5129408697a9600jorton
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_set_bufsize(p, pbuf, DAV_FS_COPY_BLOCKSIZE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if ((status = apr_file_open(&inf, src, APR_READ | APR_BINARY,
99d46a23c6eac800f327b29f8009f7d7da986230trawick APR_OS_DEFAULT, p)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not open file for reading");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do we need to deal with the umask? */
e8f95a682820a599fe41b22977010636be5c2717jim status = apr_file_open(&outf, dst, APR_WRITE | APR_CREATE | APR_TRUNCATE
7f69a90d847f08a86f9909c2c5129408697a9600jorton | APR_BINARY, perms, p);
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton if (status != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_file_close(inf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, MAP_IO2HTTP(status), 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not open file for writing");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t len = DAV_FS_COPY_BLOCKSIZE;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe status = apr_file_read(inf, pbuf->buf, &len);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (status != APR_SUCCESS && status != APR_EOF) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t lcl_status;
99d46a23c6eac800f327b29f8009f7d7da986230trawick
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_file_close(inf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_file_close(outf);
e8f95a682820a599fe41b22977010636be5c2717jim
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((lcl_status = apr_file_remove(dst, p)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### ACK! Inconsistent state... */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
99d46a23c6eac800f327b29f8009f7d7da986230trawick lcl_status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not delete output after read "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "failure. Server is now in an "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "inconsistent state.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not read input file");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7ac747af0cf476c2276aaf9999425e1b52bf5f64jorton if (status == APR_EOF)
7ac747af0cf476c2276aaf9999425e1b52bf5f64jorton break;
7ac747af0cf476c2276aaf9999425e1b52bf5f64jorton
7ac747af0cf476c2276aaf9999425e1b52bf5f64jorton /* write any bytes that were read */
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton status = apr_file_write_full(outf, pbuf->buf, len, NULL);
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton if (status != APR_SUCCESS) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t lcl_status;
99d46a23c6eac800f327b29f8009f7d7da986230trawick
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_file_close(inf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_file_close(outf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((lcl_status = apr_file_remove(dst, p)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### ACK! Inconsistent state... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
99d46a23c6eac800f327b29f8009f7d7da986230trawick lcl_status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not delete output after write "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "failure. Server is now in an "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "inconsistent state.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, MAP_IO2HTTP(status), 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not write output file");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
066877f1a045103acfdd376d48cdd473c33f409bdougm apr_file_close(inf);
066877f1a045103acfdd376d48cdd473c33f409bdougm apr_file_close(outf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf if (is_move && (status = apr_file_remove(src, p)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_error *err;
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t lcl_status;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf if (APR_STATUS_IS_ENOENT(status)) {
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf /*
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf * Something is wrong here but the result is what we wanted.
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf * We definitely should not remove the destination file.
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf */
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf apr_psprintf(p, "Could not remove source "
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf "file %s after move to %s. The "
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf "server may be in an "
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf "inconsistent state.", src, dst));
4dcb341a20cfcfdfa7dbe1faad88ce8de6a413f0sf return err;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim }
99d46a23c6eac800f327b29f8009f7d7da986230trawick else if ((lcl_status = apr_file_remove(dst, p)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### ACK. this creates an inconsistency. do more!? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, lcl_status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not remove source or destination "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "file. Server is now in an inconsistent "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "state.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not remove source file after move. "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Destination was removed to ensure consistency.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* copy/move a file from within a state dir to another state dir */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* ### need more buffers to replace the pool argument */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_copymove_state(
f4c310fd2555c6faca1f980f00b161eadb089023gstein int is_move,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_t * p,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src_dir, const char *src_file,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst_dir, const char *dst_file,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_buffer *pbuf)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_finfo_t src_finfo; /* finfo for source file */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_finfo_t dst_state_finfo; /* finfo for STATE directory */
4c449c30215bd5e8bad122a4118f5a7b0e995472wrowe apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* build the propset pathname for the source file */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm src = apr_pstrcat(p, src_dir, "/" DAV_FS_STATE_DIR "/", src_file, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the source file doesn't exist */
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe rv = apr_stat(&src_finfo, src, APR_FINFO_NORM, p);
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* build the pathname for the destination state dir */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dst = apr_pstrcat(p, dst_dir, "/" DAV_FS_STATE_DIR, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do we need to deal with the umask? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ensure that it exists */
066877f1a045103acfdd376d48cdd473c33f409bdougm rv = apr_dir_make(dst, APR_OS_DEFAULT, p);
4c449c30215bd5e8bad122a4118f5a7b0e995472wrowe if (rv != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!APR_STATUS_IS_EEXIST(rv)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not create internal state directory");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* get info about the state directory */
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe rv = apr_stat(&dst_state_finfo, dst, APR_FINFO_NORM, p);
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Ack! Where'd it go? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "State directory disappeared");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The mkdir() may have failed because a *file* exists there already */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein if (dst_state_finfo.filetype != APR_DIR) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### try to recover by deleting this file? (and mkdir again) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "State directory is actually a file");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* append the target file to the state directory pathname */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dst = apr_pstrcat(p, dst, "/", dst_file, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* copy/move the file now */
490062b5568680531b35102c60228d1802fcdb23sf if (is_move) {
490062b5568680531b35102c60228d1802fcdb23sf /* try simple rename first */
490062b5568680531b35102c60228d1802fcdb23sf rv = apr_file_rename(src, dst, p);
490062b5568680531b35102c60228d1802fcdb23sf if (APR_STATUS_IS_EXDEV(rv)) {
490062b5568680531b35102c60228d1802fcdb23sf return dav_fs_copymove_file(is_move, p, src, dst, NULL, NULL, pbuf);
490062b5568680531b35102c60228d1802fcdb23sf }
490062b5568680531b35102c60228d1802fcdb23sf if (rv != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not move state file.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein else
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* gotta copy (and delete) */
7f69a90d847f08a86f9909c2c5129408697a9600jorton return dav_fs_copymove_file(is_move, p, src, dst, NULL, NULL, pbuf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic dav_error *dav_fs_copymoveset(int is_move, apr_pool_t *p,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const dav_resource *src,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const dav_resource *dst,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_buffer *pbuf)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src_dir;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src_file;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src_state1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *src_state2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst_dir;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst_file;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst_state1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dst_state2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Get directory and filename for resources */
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein /* ### should test these result values... */
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein (void) dav_fs_dir_file_name(src, &src_dir, &src_file);
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein (void) dav_fs_dir_file_name(dst, &dst_dir, &dst_file);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Get the corresponding state files for each resource */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dbm_get_statefiles(p, src_file, &src_state1, &src_state2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dbm_get_statefiles(p, dst_file, &dst_state1, &dst_state2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if DAV_DEBUG
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((src_state2 != NULL && dst_state2 == NULL) ||
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (src_state2 == NULL && dst_state2 != NULL)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "DESIGN ERROR: dav_dbm_get_statefiles() "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "returned inconsistent results.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_fs_copymove_state(is_move, p,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe src_dir, src_state1,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dst_dir, dst_state1,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pbuf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL && src_state2 != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe err = dav_fs_copymove_state(is_move, p,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe src_dir, src_state2,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dst_dir, dst_state2,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pbuf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (err != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### CRAP. inconsistency. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### should perform some cleanup at the target if we still
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### have the original files */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Change the error to reflect the bad server state. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe err->status = HTTP_INTERNAL_SERVER_ERROR;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe err->desc =
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not fully copy/move the properties. "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The server is now in an inconsistent state.";
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic dav_error *dav_fs_deleteset(apr_pool_t *p, const dav_resource *resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dirpath;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *fname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *state1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *state2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *pathname;
da9adab0554faf94f8cc2705c2363aceacf75c46gstein apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Get directory, filename, and state-file names for the resource */
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein /* ### should test this result value... */
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein (void) dav_fs_dir_file_name(resource, &dirpath, &fname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dbm_get_statefiles(p, fname, &state1, &state2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* build the propset pathname for the file */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm pathname = apr_pstrcat(p,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dirpath,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "/" DAV_FS_STATE_DIR "/",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe state1,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: we may get ENOENT if the state dir is not present */
da9adab0554faf94f8cc2705c2363aceacf75c46gstein if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
da9adab0554faf94f8cc2705c2363aceacf75c46gstein && !APR_STATUS_IS_ENOENT(status)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not remove properties.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (state2 != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* build the propset pathname for the file */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pathname = apr_pstrcat(p,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dirpath,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "/" DAV_FS_STATE_DIR "/",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe state2,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
da9adab0554faf94f8cc2705c2363aceacf75c46gstein if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
da9adab0554faf94f8cc2705c2363aceacf75c46gstein && !APR_STATUS_IS_ENOENT(status)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### CRAP. only removed half. */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not fully remove properties. "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The server is now in an inconsistent "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "state.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* --------------------------------------------------------------------
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** REPOSITORY HOOK FUNCTIONS
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gstein
866b521be8a30b2798ad3c3b73de5e965edd7c2fgsteinstatic dav_error * dav_fs_get_resource(
f4c310fd2555c6faca1f980f00b161eadb089023gstein request_rec *r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *root_dir,
f39230a531b23d94f86a087963299bbe2e431a4agstein const char *label,
f39230a531b23d94f86a087963299bbe2e431a4agstein int use_checked_in,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein dav_resource **result_resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *filename;
49bf4df23d9e5281abcd83005550bda818b17b08wrowe apr_size_t len;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### optimize this into a single allocation! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create private resource context descriptor */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ctx = apr_pcalloc(r->pool, sizeof(*ctx));
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->finfo = r->finfo;
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin ctx->r = r;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein /* ### this should go away */
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein ctx->pool = r->pool;
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Preserve case on OSes which fold canonical filenames */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein#if 0
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein /* ### not available in Apache 2.0 yet */
f4c310fd2555c6faca1f980f00b161eadb089023gstein filename = r->case_preserved_filename;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein filename = r->filename;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If there is anything in the path_info, then this indicates that the
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** entire path was not used to specify the file/dir. We want to append
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** it onto the filename so that we get a "valid" pathname for null
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** resources.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm s = apr_pstrcat(r->pool, filename, r->path_info, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the pathname does not have a trailing "/" */
f4c310fd2555c6faca1f980f00b161eadb089023gstein len = strlen(s);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (len > 1 && s[len - 1] == '/') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe s[len - 1] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->pathname = s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create resource descriptor */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm resource = apr_pcalloc(r->pool, sizeof(*resource));
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->type = DAV_RESOURCE_TYPE_REGULAR;
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->info = ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->hooks = &dav_hooks_repository_fs;
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein resource->pool = r->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the URI does not have a trailing "/" */
4f01ee597f569d80e2e81f912e425a572002328cbreser len = strlen(r->uri);
4f01ee597f569d80e2e81f912e425a572002328cbreser if (len > 1 && r->uri[len - 1] == '/') {
4f01ee597f569d80e2e81f912e425a572002328cbreser s = apr_pstrmemdup(r->pool, r->uri, len-1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe resource->uri = s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
4f01ee597f569d80e2e81f912e425a572002328cbreser resource->uri = r->uri;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
2d4ea77e21ef7f3707d2c27f6117cc0a36e99b83trawick if (r->finfo.filetype != APR_NOFILE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->exists = 1;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein resource->collection = r->finfo.filetype == APR_DIR;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* unused info in the URL will indicate a null resource */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (r->path_info != NULL && *r->path_info != '\0') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (resource->collection) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* only a trailing "/" is allowed */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*r->path_info != '/' || r->path_info[1] != '\0') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** This URL/filename represents a locknull resource or
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** possibly a destination of a MOVE/COPY
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe resource->exists = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe resource->collection = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** The base of the path refers to a file -- nothing should
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** be in path_info. The resource is simply an error: it
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** can't be a null or a locknull resource.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, 0,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "The URL contains extraneous path "
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "components. The resource could not "
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "be identified.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* retain proper integrity across the structures */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!resource->exists) {
2d4ea77e21ef7f3707d2c27f6117cc0a36e99b83trawick ctx->finfo.filetype = APR_NOFILE;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein *result_resource = resource;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
866b521be8a30b2798ad3c3b73de5e965edd7c2fgsteinstatic dav_error * dav_fs_get_parent_resource(const dav_resource *resource,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein dav_resource **result_parent)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx = resource->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *parent_ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *parent_resource;
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *dirpath;
e2c92fb4350c626885aff64d3f92690a1892ca50wrowe const char *testroot;
e2c92fb4350c626885aff64d3f92690a1892ca50wrowe const char *testpath;
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein /* If we're at the root of the URL space, then there is no parent. */
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein if (strcmp(resource->uri, "/") == 0) {
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein *result_parent = NULL;
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein return NULL;
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein }
cc8241a7ee9815575a267e13eff62b6fddf1fe58gstein
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe /* If given resource is root, then there is no parent.
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe * Unless we can retrieve the filepath root, this is
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe * intendend to fail. If we split the root and
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe * no path info remains, then we also fail.
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe */
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe testpath = ctx->pathname;
e2c92fb4350c626885aff64d3f92690a1892ca50wrowe rv = apr_filepath_root(&testroot, &testpath, 0, ctx->pool);
e8f95a682820a599fe41b22977010636be5c2717jim if ((rv != APR_SUCCESS && rv != APR_ERELATIVE)
8fbfbe227895f4752c9bfd99b89f303f508610f4wrowe || !testpath || !*testpath) {
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein *result_parent = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### optimize this into a single allocation! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create private resource context descriptor */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm parent_ctx = apr_pcalloc(ctx->pool, sizeof(*parent_ctx));
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein /* ### this should go away */
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_ctx->pool = ctx->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
e8f95a682820a599fe41b22977010636be5c2717jim if (strlen(dirpath) > 1 && dirpath[strlen(dirpath) - 1] == '/')
f4c310fd2555c6faca1f980f00b161eadb089023gstein dirpath[strlen(dirpath) - 1] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_ctx->pathname = dirpath;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm parent_resource = apr_pcalloc(ctx->pool, sizeof(*parent_resource));
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_resource->info = parent_ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_resource->collection = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_resource->hooks = &dav_hooks_repository_fs;
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein parent_resource->pool = resource->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->uri != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *uri = ap_make_dirstr_parent(ctx->pool, resource->uri);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (strlen(uri) > 1 && uri[strlen(uri) - 1] == '/')
f4c310fd2555c6faca1f980f00b161eadb089023gstein uri[strlen(uri) - 1] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe parent_resource->uri = uri;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
e8f95a682820a599fe41b22977010636be5c2717jim rv = apr_stat(&parent_ctx->finfo, parent_ctx->pathname,
2dc8d653749bc319011afe9b02434c80a815d175trawick APR_FINFO_NORM, ctx->pool);
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe if (rv == APR_SUCCESS || rv == APR_INCOMPLETE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_resource->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein *result_parent = parent_resource;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_fs_is_same_resource(
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *res1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *res2)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx1 = res1->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx2 = res2->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (res1->hooks != res2->hooks)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
2d4ea77e21ef7f3707d2c27f6117cc0a36e99b83trawick if ((ctx1->finfo.filetype != APR_NOFILE) && (ctx2->finfo.filetype != APR_NOFILE)
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe && (ctx1->finfo.valid & ctx2->finfo.valid & APR_FINFO_INODE)) {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein return ctx1->finfo.inode == ctx2->finfo.inode;
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe }
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return strcmp(ctx1->pathname, ctx2->pathname) == 0;
2f40d5ac42ba2e7a8043eca56b5f5d8dce101f94wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_fs_is_parent_resource(
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *res1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *res2)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx1 = res1->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx2 = res2->info;
49bf4df23d9e5281abcd83005550bda818b17b08wrowe apr_size_t len1 = strlen(ctx1->pathname);
49bf4df23d9e5281abcd83005550bda818b17b08wrowe apr_size_t len2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (res1->hooks != res2->hooks)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* it is safe to use ctx2 now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein len2 = strlen(ctx2->pathname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (len2 > len1
f4c310fd2555c6faca1f980f00b161eadb089023gstein && memcmp(ctx1->pathname, ctx2->pathname, len1) == 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein && ctx2->pathname[len1] == '/');
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletcstatic apr_status_t tmpfile_cleanup(void *data)
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletc{
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletc dav_stream *ds = data;
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletc if (ds->temppath) {
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletc apr_file_remove(ds->temppath, ds->p);
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletc }
eb29b973bd3cd6336104f3ba413f6729a41623b1jailletc return APR_SUCCESS;
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf}
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf/* custom mktemp that creates the file with APR_OS_DEFAULT permissions */
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsfstatic apr_status_t dav_fs_mktemp(apr_file_t **fp, char *templ, apr_pool_t *p)
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf{
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf apr_status_t rv;
a9cb1e4a5aa12b156a3645d5be1dc2095759aa88rpluem int num = ((getpid() << 7) + (apr_uintptr_t)templ % (1 << 16) ) %
a9cb1e4a5aa12b156a3645d5be1dc2095759aa88rpluem ( 1 << 23 ) ;
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf char *numstr = templ + strlen(templ) - 6;
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf ap_assert(numstr >= templ);
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf do {
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf num = (num + 1) % ( 1 << 23 );
6a027960e59525210409d4b4501cecf1c454f0f9wrowe apr_snprintf(numstr, 7, "%06x", num);
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf rv = apr_file_open(fp, templ,
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf APR_WRITE | APR_CREATE | APR_BINARY | APR_EXCL,
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf APR_OS_DEFAULT, p);
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf } while (APR_STATUS_IS_EEXIST(rv));
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf return rv;
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf}
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_open_stream(const dav_resource *resource,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_stream_mode mode,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_stream **stream)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_t *p = resource->info->pool;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dav_stream *ds = apr_pcalloc(p, sizeof(*ds));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_int32_t flags;
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (mode) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein default:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe flags = APR_READ | APR_BINARY;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_MODE_WRITE_TRUNC:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe flags = APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_MODE_WRITE_SEEKABLE:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe flags = APR_WRITE | APR_CREATE | APR_BINARY;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ds->p = p;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ds->pathname = resource->info->pathname;
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf ds->temppath = NULL;
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf ds->unlink_on_error = 0;
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf if (mode == DAV_MODE_WRITE_TRUNC) {
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf ds->temppath = apr_pstrcat(p, ap_make_dirstr_parent(p, ds->pathname),
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf DAV_FS_TMP_PREFIX "XXXXXX", NULL);
9e7795ba458e905b76861ed4ee13fa11bacd4d2dsf rv = dav_fs_mktemp(&ds->f, ds->temppath, ds->p);
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf apr_pool_cleanup_register(p, ds, tmpfile_cleanup,
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf apr_pool_cleanup_null);
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf }
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf else if (mode == DAV_MODE_WRITE_SEEKABLE) {
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf rv = apr_file_open(&ds->f, ds->pathname, flags | APR_FOPEN_EXCL,
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf APR_OS_DEFAULT, ds->p);
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf if (rv == APR_SUCCESS) {
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf /* we have created a new file */
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf ds->unlink_on_error = 1;
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf }
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf else if (APR_STATUS_IS_EEXIST(rv)) {
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT,
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf ds->p);
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf }
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf else {
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT, ds->p);
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton if (rv != APR_SUCCESS) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(p, MAP_IO2HTTP(rv), 0, rv,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "An error occurred while opening a resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein /* (APR registers cleanups for the fd with the pool) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein *stream = ds;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_close_stream(dav_stream *stream, int commit)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf apr_status_t rv;
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf
066877f1a045103acfdd376d48cdd473c33f409bdougm apr_file_close(stream->f);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!commit) {
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf if (stream->temppath) {
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf apr_pool_cleanup_run(stream->p, stream, tmpfile_cleanup);
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf }
17d64c884a44f5ca72f6901afd3e50991bfc1c63sf else if (stream->unlink_on_error) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((rv = apr_file_remove(stream->pathname, stream->p))
99d46a23c6eac800f327b29f8009f7d7da986230trawick != APR_SUCCESS) {
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf /* ### use a better description? */
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
99d46a23c6eac800f327b29f8009f7d7da986230trawick rv,
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf "There was a problem removing (rolling "
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf "back) the resource "
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf "when it was being closed.");
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf else if (stream->temppath) {
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf rv = apr_file_rename(stream->temppath, stream->pathname, stream->p);
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf if (rv) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0, rv,
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf "There was a problem writing the file "
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf "atomically after writes.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf apr_pool_cleanup_kill(stream->p, stream, tmpfile_cleanup);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_write_stream(dav_stream *stream,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const void *buf, apr_size_t bufsize)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
066877f1a045103acfdd376d48cdd473c33f409bdougm status = apr_file_write_full(stream->f, buf, bufsize, NULL);
07648ef03a5547fc4ed4410054d4161c142add50wrowe if (APR_STATUS_IS_ENOSPC(status)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(stream->p, HTTP_INSUFFICIENT_STORAGE, 0, status,
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein "There is not enough storage to write to "
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein "this resource.");
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein }
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein else if (status != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "An error occurred while writing to a "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic dav_error * dav_fs_seek_stream(dav_stream *stream, apr_off_t abs_pos)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t status;
99d46a23c6eac800f327b29f8009f7d7da986230trawick
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_file_seek(stream->f, APR_SET, &abs_pos))
99d46a23c6eac800f327b29f8009f7d7da986230trawick != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### should check whether apr_file_seek set abs_pos was set to the
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * correct position? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use something besides 500? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not seek to specified position in the "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein#if DEBUG_GET_HANDLER
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein/* only define set_headers() and deliver() for debug purposes */
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_set_headers(request_rec *r,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const dav_resource *resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this function isn't really used since we have a get_pathname */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the proper mtime is in the request record */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_update_mtime(r, resource->info->finfo.mtime);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### note that these use r->filename rather than <resource> */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_set_last_modified(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_set_etag(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we accept byte-ranges */
af7cd2711a9737c0a2aa1b8475455a7dd8ce6113covener ap_set_accept_ranges(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* set up the Content-Length header */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_set_content_length(r, resource->info->finfo.size);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### how to set the content type? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### until this is resolved, the Content-Type header is busted */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egsteinstatic dav_error * dav_fs_deliver(const dav_resource *resource,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein ap_filter_t *output)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein apr_pool_t *pool = resource->pool;
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein apr_bucket_brigade *bb;
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein apr_file_t *fd;
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein apr_status_t status;
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein apr_bucket *bkt;
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein /* Check resource type */
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein && resource->type != DAV_RESOURCE_TYPE_VERSION
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein && resource->type != DAV_RESOURCE_TYPE_WORKING) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(pool, HTTP_CONFLICT, 0, 0,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "Cannot GET this type of resource.");
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein }
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if (resource->collection) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(pool, HTTP_CONFLICT, 0, 0,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "There is no default response to GET for a "
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "collection.");
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if ((status = apr_file_open(&fd, resource->info->pathname,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein APR_READ | APR_BINARY, 0,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein pool)) != APR_SUCCESS) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(pool, HTTP_FORBIDDEN, 0, status,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "File permissions deny server access.");
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein }
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley bb = apr_brigade_create(pool, output->c->bucket_alloc);
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
0c9166d0186cf0e1ad397025f730ae6967f44ce6jorton apr_brigade_insert_file(bb, fd, 0, resource->info->finfo.size, pool);
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley bkt = apr_bucket_eos_create(output->c->bucket_alloc);
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein APR_BRIGADE_INSERT_TAIL(bb, bkt);
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS) {
1715880355ef7f574cae2e8f973411b51acededeylavic return dav_new_error(pool, AP_FILTER_ERROR, 0, status,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "Could not write contents to filter.");
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein }
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein#endif /* DEBUG_GET_HANDLER */
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein
33397e35239f202a595837571561468f02b2e806gsteinstatic dav_error * dav_fs_create_collection(dav_resource *resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx = resource->info;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
066877f1a045103acfdd376d48cdd473c33f409bdougm status = apr_dir_make(ctx->pathname, APR_OS_DEFAULT, ctx->pool);
9ec6440fdeb81f04905959293b381ebbfa3114c2jorton if (APR_STATUS_IS_ENOSPC(status)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(ctx->pool, HTTP_INSUFFICIENT_STORAGE, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "There is not enough storage to create "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "this collection.");
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein }
51a61c00a9edcd1d249b9d912681c0c10b8be409jorton else if (APR_STATUS_IS_ENOENT(status)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(ctx->pool, HTTP_CONFLICT, 0, status,
51a61c00a9edcd1d249b9d912681c0c10b8be409jorton "Cannot create collection; intermediate "
51a61c00a9edcd1d249b9d912681c0c10b8be409jorton "collection does not exist.");
51a61c00a9edcd1d249b9d912681c0c10b8be409jorton }
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein else if (status != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### refine this error message? */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0, status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Unable to create collection.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* update resource state to show it exists as a collection */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->collection = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gsteinstatic dav_error * dav_fs_copymove_walker(dav_walk_resource *wres,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein int calltype)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t status;
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_fs_copymove_walk_ctx *ctx = wres->walk_ctx;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_resource_private *srcinfo = wres->resource->info;
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_resource_private *dstinfo = ctx->res_dst->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (wres->resource->collection) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (calltype == DAV_CALLTYPE_POSTFIX) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Postfix call for MOVE. delete the source dir.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Note: when copying, we do not enable the postfix-traversal.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### we are ignoring any error here; what should we do? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (void) apr_dir_remove(srcinfo->pathname, ctx->pool);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* copy/move of a collection. Create the new, target collection */
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_dir_make(dstinfo->pathname, APR_OS_DEFAULT,
99d46a23c6eac800f327b29f8009f7d7da986230trawick ctx->pool)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### assume it was a permissions problem */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### need a description here */
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0, status, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
e8f95a682820a599fe41b22977010636be5c2717jim err = dav_fs_copymove_file(ctx->is_move, ctx->pool,
e8f95a682820a599fe41b22977010636be5c2717jim srcinfo->pathname, dstinfo->pathname,
e8f95a682820a599fe41b22977010636be5c2717jim &srcinfo->finfo,
7f69a90d847f08a86f9909c2c5129408697a9600jorton ctx->res_dst->exists ? &dstinfo->finfo : NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe &ctx->work_buf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### push a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If we have a "not so bad" error, then it might need to go into a
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** multistatus response.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** For a MOVE, it will always go into the multistatus. It could be
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** that everything has been moved *except* for the root. Using a
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** multistatus (with no errors for the other resources) will signify
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** this condition.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** For a COPY, we are traversing in a prefix fashion. If the root fails,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** then we can just bail out now.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL
f4c310fd2555c6faca1f980f00b161eadb089023gstein && !ap_is_HTTP_SERVER_ERROR(err->status)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe && (ctx->is_move
707ecf9559338ec06b24334bc9abcca670325cc4gstein || !dav_fs_is_same_resource(wres->resource, ctx->root))) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### use errno to generate DAV:responsedescription? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_add_response(wres, err->status, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the error is in the multistatus now. do not stop the traversal. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error *dav_fs_copymove_resource(
f4c310fd2555c6faca1f980f00b161eadb089023gstein int is_move,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *src,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *dst,
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response **response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_buffer work_buf = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein *response = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if a collection, recursively copy/move it and its children,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * including the state dirs
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (src->collection) {
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_walk_params params = { 0 };
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_response *multi_status;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_HIDDEN;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.func = dav_fs_copymove_walker;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.pool = src->info->pool;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.root = src;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* params.walk_ctx is managed by dav_fs_internal_walk() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* postfix is needed for MOVE to delete source dirs */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (is_move)
707ecf9559338ec06b24334bc9abcca670325cc4gstein params.walk_type |= DAV_WALKTYPE_POSTFIX;
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* note that we return the error OR the multistatus. never both */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((err = dav_fs_internal_walk(&params, depth, is_move, dst,
707ecf9559338ec06b24334bc9abcca670325cc4gstein &multi_status)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* on a "real" error, then just punt. nothing else to do. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein if ((*response = multi_status) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* some multistatus responses exist. wrap them in a 207 */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(src->info->pool, HTTP_MULTI_STATUS, 0, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Error(s) occurred on some resources during "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "the COPY/MOVE process.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* not a collection */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_fs_copymove_file(is_move, src->info->pool,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe src->info->pathname, dst->info->pathname,
e8f95a682820a599fe41b22977010636be5c2717jim &src->info->finfo,
7f69a90d847f08a86f9909c2c5129408697a9600jorton dst->exists ? &dst->info->finfo : NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe &work_buf)) != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### push a higher-level description? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
e8f95a682820a599fe41b22977010636be5c2717jim
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* copy/move properties as well */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_fs_copymoveset(is_move, src->info->pool, src, dst, &work_buf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_copy_resource(
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_resource *src,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *dst,
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response **response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if DAV_DEBUG
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (src->hooks != dst->hooks) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### strictly speaking, this is a design error; we should not
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### have reached this point.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(src->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "DESIGN ERROR: a mix of repositories "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "was passed to copy_resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_fs_copymove_resource(0, src, dst, depth,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe response)) == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* update state of destination resource to show it exists */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->collection = src->collection;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_move_resource(
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *src,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *dst,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response **response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *srcinfo = src->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *dstinfo = dst->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
490062b5568680531b35102c60228d1802fcdb23sf apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if DAV_DEBUG
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (src->hooks != dst->hooks) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### strictly speaking, this is a design error; we should not
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### have reached this point.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(src->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "DESIGN ERROR: a mix of repositories "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "was passed to move_resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
490062b5568680531b35102c60228d1802fcdb23sf /* try rename first */
490062b5568680531b35102c60228d1802fcdb23sf rv = apr_file_rename(srcinfo->pathname, dstinfo->pathname, srcinfo->pool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5646ba89a25a695006edae46de226fb57a2e6270gstein /* if we can't simply rename, then do it the hard way... */
490062b5568680531b35102c60228d1802fcdb23sf if (APR_STATUS_IS_EXDEV(rv)) {
5646ba89a25a695006edae46de226fb57a2e6270gstein if ((err = dav_fs_copymove_resource(1, src, dst, DAV_INFINITY,
5646ba89a25a695006edae46de226fb57a2e6270gstein response)) == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* update resource states */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->collection = src->collection;
f4c310fd2555c6faca1f980f00b161eadb089023gstein src->exists = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein src->collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no multistatus response */
f4c310fd2555c6faca1f980f00b161eadb089023gstein *response = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
490062b5568680531b35102c60228d1802fcdb23sf if (rv != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### should have a better error than this. */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(srcinfo->pool, HTTP_INTERNAL_SERVER_ERROR, 0, rv,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not rename resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
490062b5568680531b35102c60228d1802fcdb23sf /* Rename did work. Update resource states and move properties as well */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->collection = src->collection;
f4c310fd2555c6faca1f980f00b161eadb089023gstein src->exists = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein src->collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_fs_copymoveset(1, src->info->pool,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe src, dst, NULL)) == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* no error. we're done. go ahead and return now. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* error occurred during properties move; try to put resource back */
066877f1a045103acfdd376d48cdd473c33f409bdougm if (apr_file_rename(dstinfo->pathname, srcinfo->pathname,
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein srcinfo->pool) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* couldn't put it back! */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return dav_push_error(srcinfo->pool,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe HTTP_INTERNAL_SERVER_ERROR, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The resource was moved, but a failure "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "occurred during the move of its "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "properties. The resource could not be "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "restored to its original location. The "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "server is now in an inconsistent state.",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* update resource states again */
f4c310fd2555c6faca1f980f00b161eadb089023gstein src->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein src->collection = dst->collection;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->exists = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dst->collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resource moved back, but properties may be inconsistent */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_push_error(srcinfo->pool,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe HTTP_INTERNAL_SERVER_ERROR, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The resource was moved, but a failure "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "occurred during the move of its properties. "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The resource was moved back to its original "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "location, but its properties may have been "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "partially moved. The server may be in an "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "inconsistent state.",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gsteinstatic dav_error * dav_fs_delete_walker(dav_walk_resource *wres, int calltype)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_resource_private *info = wres->resource->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* do not attempt to remove a null resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * or a collection with children
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (wres->resource->exists &&
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein (!wres->resource->collection || calltype == DAV_CALLTYPE_POSTFIX)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* try to remove the resource */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe result = wres->resource->collection
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ? apr_dir_remove(info->pathname, wres->pool)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe : apr_file_remove(info->pathname, wres->pool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If an error occurred, then add it to multistatus response.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note that we add it for the root resource, too. It is quite
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** possible to delete the whole darn tree, yet fail on the root.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** (also: remember we are deleting via a postfix traversal)
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (result != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### assume there is a permissions problem */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### use errno to generate DAV:responsedescription? */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_add_response(wres, HTTP_FORBIDDEN, NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_fs_remove_resource(dav_resource *resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response **response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *info = resource->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein *response = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if a collection, recursively remove it and its children,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * including the state dirs
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection) {
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_walk_params params = { 0 };
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_error *err = NULL;
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_response *multi_status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.walk_type = (DAV_WALKTYPE_NORMAL
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein | DAV_WALKTYPE_HIDDEN
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein | DAV_WALKTYPE_POSTFIX);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.func = dav_fs_delete_walker;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.pool = info->pool;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe params.root = resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((err = dav_fs_walk(&params, DAV_INFINITY,
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein &multi_status)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* on a "real" error, then just punt. nothing else to do. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein if ((*response = multi_status) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* some multistatus responses exist. wrap them in a 207 */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(info->pool, HTTP_MULTI_STATUS, 0, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Error(s) occurred on some resources during "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "the deletion process.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no errors... update resource state */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->exists = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* not a collection; remove the file and its properties */
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_file_remove(info->pathname, info->pool)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### put a description in here */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(info->pool, HTTP_FORBIDDEN, 0, status, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* update resource state */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->exists = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* remove properties and return its result */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_fs_deleteset(info->pool, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* ### move this to dav_util? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Walk recursively down through directories, *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * including lock-null resources as we go. */
26250b0077972bf21b6d8a8d23772a4cf53f9477gsteinstatic dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein const dav_walk_params *params = fsctx->params;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein apr_pool_t *pool = params->pool;
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err = NULL;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein int isdir = fsctx->res1.collection;
ac65d432dabe462e98489f8e3946b2537ca9ecf6wrowe apr_finfo_t dirent;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_dir_t *dirp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ensure the context is prepared properly, then call the func */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein err = (*params->func)(&fsctx->wres,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein isdir
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ? DAV_CALLTYPE_COLLECTION
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein : DAV_CALLTYPE_MEMBER);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth == 0 || !isdir) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* put a trailing slash onto the directory, in preparation for appending
f4c310fd2555c6faca1f980f00b161eadb089023gstein * files to it as we discovery them within the directory */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_check_bufsize(pool, &fsctx->path1, DAV_BUFFER_PAD);
f4c310fd2555c6faca1f980f00b161eadb089023gstein fsctx->path1.buf[fsctx->path1.cur_len++] = '/';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path1.buf[fsctx->path1.cur_len] = '\0'; /* in pad area */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if a secondary path is present, then do that, too */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (fsctx->path2.buf != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_check_bufsize(pool, &fsctx->path2, DAV_BUFFER_PAD);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path2.buf[fsctx->path2.cur_len++] = '/';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path2.buf[fsctx->path2.cur_len] = '\0'; /* in pad area */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Note: the URI should ALREADY have a trailing "/" */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* for this first pass of files, all resources exist */
f4c310fd2555c6faca1f980f00b161eadb089023gstein fsctx->res1.exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* a file is the default; we'll adjust if we hit a directory */
f4c310fd2555c6faca1f980f00b161eadb089023gstein fsctx->res1.collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein fsctx->res2.collection = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* open and scan the directory */
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_dir_open(&dirp, fsctx->path1.buf, pool)) != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### need a better error */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(pool, HTTP_NOT_FOUND, 0, status, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
ac65d432dabe462e98489f8e3946b2537ca9ecf6wrowe while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t len;
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe len = strlen(dirent.name);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* avoid recursing into our current, parent, or state directories */
e8f95a682820a599fe41b22977010636be5c2717jim if (dirent.name[0] == '.'
ac65d432dabe462e98489f8e3946b2537ca9ecf6wrowe && (len == 1 || (dirent.name[1] == '.' && len == 2))) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (params->walk_type & DAV_WALKTYPE_AUTH) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### need to authorize each file */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### example: .htaccess is normally configured to fail auth */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf /* stuff in the state directory and temp files are never authorized! */
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf if (!strcmp(dirent.name, DAV_FS_STATE_DIR) ||
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf !strncmp(dirent.name, DAV_FS_TMP_PREFIX,
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf strlen(DAV_FS_TMP_PREFIX))) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf /* skip the state dir and temp files unless a HIDDEN is performed */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf && (!strcmp(dirent.name, DAV_FS_STATE_DIR) ||
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf !strncmp(dirent.name, DAV_FS_TMP_PREFIX,
a6e4caaa97e433cc2ef78d957bc32756d9c49f79sf strlen(DAV_FS_TMP_PREFIX)))) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* append this file onto the path buffer (copy null term) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_buffer_place_mem(pool, &fsctx->path1, dirent.name, len + 1, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
e8f95a682820a599fe41b22977010636be5c2717jim status = apr_stat(&fsctx->info1.finfo, fsctx->path1.buf,
c70afa1853413eb72c4909354c2814d89e9b99f7jorton DAV_FINFO_MASK, pool);
b6126f9c87296cf2cd10b0a39f7330a9d50e68d7gstein if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* woah! where'd it go? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### should have a better error here */
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(pool, HTTP_NOT_FOUND, 0, status, NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* copy the file to the URI, too. NOTE: we will pad an extra byte
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for the trailing slash later. */
4f01ee597f569d80e2e81f912e425a572002328cbreser dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* if there is a secondary path, then do that, too */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (fsctx->path2.buf != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_buffer_place_mem(pool, &fsctx->path2, dirent.name, len + 1, 0);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* set up the (internal) pathnames for the two resources */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->info1.pathname = fsctx->path1.buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->info2.pathname = fsctx->path2.buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* set up the URI for the current resource */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.uri = fsctx->uri_buf.buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### for now, only process regular files (e.g. skip symlinks) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (fsctx->info1.finfo.filetype == APR_REG) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* call the function for the specified dir + file */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((err = (*params->func)(&fsctx->wres,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein DAV_CALLTYPE_MEMBER)) != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### maybe add a higher-level description? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (fsctx->info1.finfo.filetype == APR_DIR) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t save_path_len = fsctx->path1.cur_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t save_uri_len = fsctx->uri_buf.cur_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t save_path2_len = fsctx->path2.cur_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* adjust length to incorporate the subdir name */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path1.cur_len += len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path2.cur_len += len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* adjust URI length to incorporate subdir and a slash */
4f01ee597f569d80e2e81f912e425a572002328cbreser fsctx->uri_buf.cur_len += len + 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* switch over to a collection */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.collection = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res2.collection = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* recurse on the subdir */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### don't always want to quit on error from single child */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((err = dav_fs_walker(fsctx, depth - 1)) != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### maybe add a higher-level description? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* put the various information back */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path1.cur_len = save_path_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path2.cur_len = save_path2_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->uri_buf.cur_len = save_uri_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.collection = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res2.collection = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* assert: res1.exists == 1 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### check the return value of this? */
ac65d432dabe462e98489f8e3946b2537ca9ecf6wrowe apr_dir_close(dirp);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (params->walk_type & DAV_WALKTYPE_LOCKNULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t offset = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* null terminate the directory name */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path1.buf[fsctx->path1.cur_len - 1] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Include any lock null resources found in this collection */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.collection = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((err = dav_fs_get_locknull_members(&fsctx->res1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &fsctx->locknull_buf)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### maybe add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* put a slash back on the end of the directory */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path1.buf[fsctx->path1.cur_len - 1] = '/';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* these are all non-existant (files) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.exists = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.collection = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe memset(&fsctx->info1.finfo, 0, sizeof(fsctx->info1.finfo));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (offset < fsctx->locknull_buf.cur_len) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t len = strlen(fsctx->locknull_buf.buf + offset);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_lock *locks = NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** Append the locknull file to the paths and the URI. Note that
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** we don't have to pad the URI for a slash since a locknull
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** resource is not a collection.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_buffer_place_mem(pool, &fsctx->path1,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->locknull_buf.buf + offset, len + 1, 0);
4f01ee597f569d80e2e81f912e425a572002328cbreser dav_buffer_place_mem(pool, &fsctx->uri_buf,
4f01ee597f569d80e2e81f912e425a572002328cbreser fsctx->locknull_buf.buf + offset, len + 1, 0);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (fsctx->path2.buf != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_buffer_place_mem(pool, &fsctx->path2,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->locknull_buf.buf + offset,
f4c310fd2555c6faca1f980f00b161eadb089023gstein len + 1, 0);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* set up the (internal) pathnames for the two resources */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->info1.pathname = fsctx->path1.buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->info2.pathname = fsctx->path2.buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* set up the URI for the current resource */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.uri = fsctx->uri_buf.buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** To prevent a PROPFIND showing an expired locknull
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** resource, query the lock database to force removal
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** of both the lock entry and .locknull, if necessary..
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** Sure, the query in PROPFIND would do this.. after
e8f95a682820a599fe41b22977010636be5c2717jim ** the locknull resource was already included in the
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** return.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe **
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** NOTE: we assume the caller has opened the lock database
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** if they have provided DAV_WALKTYPE_LOCKNULL.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### we should also look into opening it read-only and
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### eliding timed-out items from the walk, yet leaving
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### them in the locknull database until somebody opens
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### the thing writable.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### probably ought to use has_locks. note the problem
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### mentioned above, though... we would traverse this as
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### a locknull, but then a PROPFIND would load the lock
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### info, causing a timeout and the locks would not be
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### reported. Therefore, a null resource would be returned
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### in the PROPFIND.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ###
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### alternative: just load unresolved locks. any direct
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### locks will be timed out (correct). any indirect will
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### not (correct; consider if a parent timed out -- the
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### timeout routines do not walk and remove indirects;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### even the resolve func would probably fail when it
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ### tried to find a timed-out direct lock).
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((err = dav_lock_query(params->lockdb, &fsctx->res1,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein &locks)) != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### maybe add a higher-level description? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* call the function for the specified dir + file */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (locks != NULL &&
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (err = (*params->func)(&fsctx->wres,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein DAV_CALLTYPE_LOCKNULL)) != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* ### maybe add a higher-level description? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe offset += len + 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* reset the exists flag */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (params->walk_type & DAV_WALKTYPE_POSTFIX) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* replace the dirs' trailing slashes with null terms */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path1.buf[--fsctx->path1.cur_len] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->uri_buf.buf[--fsctx->uri_buf.cur_len] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (fsctx->path2.buf != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->path2.buf[--fsctx->path2.cur_len] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* this is a collection which exists */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx->res1.collection = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (*params->func)(&fsctx->wres, DAV_CALLTYPE_POSTFIX);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gsteinstatic dav_error * dav_fs_internal_walk(const dav_walk_params *params,
707ecf9559338ec06b24334bc9abcca670325cc4gstein int depth, int is_move,
707ecf9559338ec06b24334bc9abcca670325cc4gstein const dav_resource *root_dst,
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_response **response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_walker_context fsctx = { 0 };
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_error *err;
707ecf9559338ec06b24334bc9abcca670325cc4gstein dav_fs_copymove_walk_ctx cm_ctx = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if DAV_DEBUG
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe && params->lockdb == NULL) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(params->pool, HTTP_INTERNAL_SERVER_ERROR, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "DESIGN ERROR: walker called to walk locknull "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "resources, but a lockdb was not provided.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein fsctx.params = params;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein fsctx.wres.walk_ctx = params->walk_ctx;
00f73f5096966f34c7db15562e5d2e1233eb4571gstein fsctx.wres.pool = params->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### zero out versioned, working, baselined? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein fsctx.res1 = *params->root;
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein fsctx.res1.pool = params->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein fsctx.res1.info = &fsctx.info1;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein fsctx.info1 = *params->root->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* the pathname is stored in the path1 buffer */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_buffer_init(params->pool, &fsctx.path1, fsctx.info1.pathname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein fsctx.info1.pathname = fsctx.path1.buf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein if (root_dst != NULL) {
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* internal call from the COPY/MOVE code. set it up. */
707ecf9559338ec06b24334bc9abcca670325cc4gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein fsctx.wres.walk_ctx = &cm_ctx;
707ecf9559338ec06b24334bc9abcca670325cc4gstein cm_ctx.is_move = is_move;
707ecf9559338ec06b24334bc9abcca670325cc4gstein cm_ctx.res_dst = &fsctx.res2;
707ecf9559338ec06b24334bc9abcca670325cc4gstein cm_ctx.root = params->root;
707ecf9559338ec06b24334bc9abcca670325cc4gstein cm_ctx.pool = params->pool;
707ecf9559338ec06b24334bc9abcca670325cc4gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.res2 = *root_dst;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.res2.exists = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.res2.collection = 0;
707ecf9559338ec06b24334bc9abcca670325cc4gstein fsctx.res2.uri = NULL; /* we don't track this */
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein fsctx.res2.pool = params->pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.res2.info = &fsctx.info2;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.info2 = *root_dst->info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* res2 does not exist -- clear its finfo structure */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe memset(&fsctx.info2.finfo, 0, sizeof(fsctx.info2.finfo));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* the pathname is stored in the path2 buffer */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_buffer_init(params->pool, &fsctx.path2, fsctx.info2.pathname);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.info2.pathname = fsctx.path2.buf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein /* prep the URI buffer */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if we have a directory, then ensure the URI has a trailing "/" */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (fsctx.res1.collection
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe && fsctx.uri_buf.buf[fsctx.uri_buf.cur_len - 1] != '/') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* this will fall into the pad area */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.uri_buf.buf[fsctx.uri_buf.cur_len++] = '/';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe fsctx.uri_buf.buf[fsctx.uri_buf.cur_len] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* the current resource's URI is stored in the uri_buf buffer */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein fsctx.res1.uri = fsctx.uri_buf.buf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* point the callback's resource at our structure */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein fsctx.wres.resource = &fsctx.res1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* always return the error, and any/all multistatus responses */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein err = dav_fs_walker(&fsctx, depth);
707ecf9559338ec06b24334bc9abcca670325cc4gstein *response = fsctx.wres.response;
707ecf9559338ec06b24334bc9abcca670325cc4gstein return err;
707ecf9559338ec06b24334bc9abcca670325cc4gstein}
707ecf9559338ec06b24334bc9abcca670325cc4gstein
f94aab38f6ee899f463f0118ea395291f7c5b4cegsteinstatic dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_response **response)
707ecf9559338ec06b24334bc9abcca670325cc4gstein{
707ecf9559338ec06b24334bc9abcca670325cc4gstein /* always return the error, and any/all multistatus responses */
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein return dav_fs_internal_walk(params, depth, 0, NULL, response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* dav_fs_etag: Stolen from ap_make_etag. Creates a strong etag
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for file path.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### do we need to return weak tags sometimes?
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *dav_fs_getetag(const dav_resource *resource)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource_private *ctx = resource->info;
fec106c7688e279dfde4403bc3c935fec97c1d62sf /* XXX: This should really honor the FileETag setting */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
e8f95a682820a599fe41b22977010636be5c2717jim if (!resource->exists)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return apr_pstrdup(ctx->pool, "");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
2d4ea77e21ef7f3707d2c27f6117cc0a36e99b83trawick if (ctx->finfo.filetype != APR_NOFILE) {
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem return apr_psprintf(ctx->pool, "\"%" APR_UINT64_T_HEX_FMT "-%"
fec106c7688e279dfde4403bc3c935fec97c1d62sf APR_UINT64_T_HEX_FMT "\"",
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem (apr_uint64_t) ctx->finfo.size,
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem (apr_uint64_t) ctx->finfo.mtime);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem return apr_psprintf(ctx->pool, "\"%" APR_UINT64_T_HEX_FMT "\"",
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem (apr_uint64_t) ctx->finfo.mtime);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const dav_hooks_repository dav_hooks_repository_fs =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein DEBUG_GET_HANDLER, /* normally: special GET handling not required */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_get_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_get_parent_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_is_same_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_is_parent_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_open_stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_close_stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_write_stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_seek_stream,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein#if DEBUG_GET_HANDLER
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_set_headers,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein dav_fs_deliver,
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein NULL,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_create_collection,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_copy_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_move_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_remove_resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_walk,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_getetag,
a0c5ae524801374f36b3769d33d32ea1cca5ade3fuankg NULL,
f5119c5d7cfe8c6d53cb29d43f8746684068ed82minfrin dav_fs_get_request_rec,
a0c5ae524801374f36b3769d33d32ea1cca5ade3fuankg dav_fs_pathname
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_prop_insert dav_fs_insert_prop(const dav_resource *resource,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int propid, dav_prop_insert what,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_text_header *phdr)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *value;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *s;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_t *p = resource->info->pool;
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein const dav_liveprop_spec *info;
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein int global_ns;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* an HTTP-date can be 29 chars plus a null term */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* a 64-bit size can be 20 chars plus a null term */
f4c310fd2555c6faca1f980f00b161eadb089023gstein char buf[DAV_TIMEBUF_SIZE];
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** None of FS provider properties are defined if the resource does not
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** exist. Just bail for this case.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Even though we state that the FS properties are not defined, the
956f4b1551215610a57f3b52822dbac6f41a8aa9gstein ** client cannot store dead values -- we deny that thru the is_writable
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** hook function.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return DAV_PROP_INSERT_NOTDEF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (propid) {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein case DAV_PROPID_creationdate:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** Closest thing to a creation date. since we don't actually
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** perform the operations that would modify ctime (after we
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** create the file), then we should be pretty safe here.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_format_time(DAV_STYLE_ISO8601,
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein resource->info->finfo.ctime,
dc52cac281d8b311dc47d115ed979f923b667679rjung buf, sizeof(buf));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe value = buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein case DAV_PROPID_getcontentlength:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* our property, but not defined on collection resources */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (resource->collection)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return DAV_PROP_INSERT_NOTDEF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
dc52cac281d8b311dc47d115ed979f923b667679rjung apr_snprintf(buf, sizeof(buf), "%" APR_OFF_T_FMT, resource->info->finfo.size);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe value = buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein case DAV_PROPID_getetag:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe value = dav_fs_getetag(resource);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein case DAV_PROPID_getlastmodified:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_format_time(DAV_STYLE_RFC822,
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein resource->info->finfo.mtime,
dc52cac281d8b311dc47d115ed979f923b667679rjung buf, sizeof(buf));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe value = buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_PROPID_FS_executable:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* our property, but not defined on collection resources */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (resource->collection)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return DAV_PROP_INSERT_NOTDEF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f54da7877f9e092465df38bfda142f3e71dbb7aawrowe /* our property, but not defined on this platform */
f54da7877f9e092465df38bfda142f3e71dbb7aawrowe if (!(resource->info->finfo.valid & APR_FINFO_UPROT))
f54da7877f9e092465df38bfda142f3e71dbb7aawrowe return DAV_PROP_INSERT_NOTDEF;
f54da7877f9e092465df38bfda142f3e71dbb7aawrowe
f54da7877f9e092465df38bfda142f3e71dbb7aawrowe /* the files are "ours" so we only need to check owner exec privs */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (resource->info->finfo.protection & APR_UEXECUTE)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe value = "T";
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe value = "F";
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein default:
5fbee309625f7a631a42d7dc05bbfa0d45a926ccgstein /* ### what the heck was this property? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return DAV_PROP_INSERT_NOTDEF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* assert: value != NULL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein /* get the information and global NS index for the property */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein global_ns = dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein /* assert: info != NULL && info->name != NULL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* DBG3("FS: inserting lp%d:%s (local %d)", ns, scan->name, scan->ns); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (what == DAV_PROP_INSERT_VALUE) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein global_ns, info->name, value, global_ns, info->name);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (what == DAV_PROP_INSERT_NAME) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* assert: what == DAV_PROP_INSERT_SUPPORTED */
bbba27074551817d7c6a606c4362965c26a0777egstein s = apr_psprintf(p,
bbba27074551817d7c6a606c4362965c26a0777egstein "<D:supported-live-property D:name=\"%s\" "
bbba27074551817d7c6a606c4362965c26a0777egstein "D:namespace=\"%s\"/>" DEBUG_CR,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein info->name, dav_fs_namespace_uris[info->ns]);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
dd56b1dd453bd9032d97028bc3987f999c31280cwrowe apr_text_append(p, phdr, s);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* we inserted what was asked for */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return what;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
956f4b1551215610a57f3b52822dbac6f41a8aa9gsteinstatic int dav_fs_is_writable(const dav_resource *resource, int propid)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein const dav_liveprop_spec *info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#ifdef DAV_FS_HAS_EXECUTABLE
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein /* if we have the executable property, and this isn't a collection,
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein then the property is writable. */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein if (propid == DAV_PROPID_FS_executable && !resource->collection)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 1;
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (void) dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein return info->is_writable;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error *dav_fs_patch_validate(const dav_resource *resource,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const apr_xml_elem *elem,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int operation,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void **context,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int *defer_to_dead)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
dd56b1dd453bd9032d97028bc3987f999c31280cwrowe const apr_text *cdata;
dd56b1dd453bd9032d97028bc3987f999c31280cwrowe const apr_text *f_cdata;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char value;
872f3bdb13ca15077fbe3a1d560e3c18d7f2e4d1trawick dav_elem_private *priv = elem->priv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (priv->propid != DAV_PROPID_FS_executable) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *defer_to_dead = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (operation == DAV_PROP_OP_DELETE) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The 'executable' property cannot be removed.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein cdata = elem->first_cdata.first;
5646ba89a25a695006edae46de226fb57a2e6270gstein
5646ba89a25a695006edae46de226fb57a2e6270gstein /* ### hmm. this isn't actually looking at all the possible text items */
5646ba89a25a695006edae46de226fb57a2e6270gstein f_cdata = elem->first_child == NULL
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ? NULL
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe : elem->first_child->following_cdata.first;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein /* DBG3("name=%s cdata=%s f_cdata=%s",elem->name,cdata ? cdata->text : "[null]",f_cdata ? f_cdata->text : "[null]"); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cdata == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (f_cdata == NULL) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The 'executable' property expects a single "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "character, valued 'T' or 'F'. There was no "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "value submitted.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe cdata = f_cdata;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (f_cdata != NULL)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe goto too_long;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cdata->next != NULL || strlen(cdata->text) != 1)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe goto too_long;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein value = cdata->text[0];
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (value != 'T' && value != 'F') {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The 'executable' property expects a single "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "character, valued 'T' or 'F'. The value "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "submitted is invalid.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1448efd1befdbe16fe42532edbc379204279aadfasteinmetz *context = (void *)((long)(value == 'T'));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein too_long:
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "The 'executable' property expects a single "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "character, valued 'T' or 'F'. The value submitted "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "has too many characters.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
bbba27074551817d7c6a606c4362965c26a0777egsteinstatic dav_error *dav_fs_patch_exec(const dav_resource *resource,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const apr_xml_elem *elem,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int operation,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void *context,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_liveprop_rollback **rollback_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1448efd1befdbe16fe42532edbc379204279aadfasteinmetz long value = context != NULL;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_fileperms_t perms = resource->info->finfo.protection;
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t status;
1448efd1befdbe16fe42532edbc379204279aadfasteinmetz long old_value = (perms & APR_UEXECUTE) != 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* assert: prop == executable. operation == SET. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* don't do anything if there is no change. no rollback info either. */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein /* DBG2("new value=%d (old=%d)", value, old_value); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (value == old_value)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein perms &= ~APR_UEXECUTE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (value)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe perms |= APR_UEXECUTE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_file_perms_set(resource->info->pathname, perms))
99d46a23c6eac800f327b29f8009f7d7da986230trawick != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return dav_new_error(resource->info->pool,
99d46a23c6eac800f327b29f8009f7d7da986230trawick HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Could not set the executable flag of the "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "target resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* update the resource and set up the rollback context */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein resource->info->finfo.protection = perms;
f4c310fd2555c6faca1f980f00b161eadb089023gstein *rollback_ctx = (dav_liveprop_rollback *)old_value;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
bbba27074551817d7c6a606c4362965c26a0777egsteinstatic void dav_fs_patch_commit(const dav_resource *resource,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int operation,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void *context,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_liveprop_rollback *rollback_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* nothing to do */
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
bbba27074551817d7c6a606c4362965c26a0777egsteinstatic dav_error *dav_fs_patch_rollback(const dav_resource *resource,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int operation,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void *context,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe dav_liveprop_rollback *rollback_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_fileperms_t perms = resource->info->finfo.protection & ~APR_UEXECUTE;
99d46a23c6eac800f327b29f8009f7d7da986230trawick apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int value = rollback_ctx != NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* assert: prop == executable. operation == SET. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore the executable bit */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (value)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe perms |= APR_UEXECUTE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick if ((status = apr_file_perms_set(resource->info->pathname, perms))
99d46a23c6eac800f327b29f8009f7d7da986230trawick != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return dav_new_error(resource->info->pool,
99d46a23c6eac800f327b29f8009f7d7da986230trawick HTTP_INTERNAL_SERVER_ERROR, 0, status,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "After a failure occurred, the resource's "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "executable flag could not be restored.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore the resource's state */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein resource->info->finfo.protection = perms;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const dav_hooks_liveprop dav_hooks_liveprop_fs =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_insert_prop,
956f4b1551215610a57f3b52822dbac6f41a8aa9gstein dav_fs_is_writable,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_namespace_uris,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_patch_validate,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_patch_exec,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_fs_patch_commit,
e154725591e87e013bad80b6c9aac6f1b0441f7cgstein dav_fs_patch_rollback
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gsteinstatic const dav_provider dav_fs_provider =
709df1e1c2e1710570f8cb4209497e88662829c3gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein &dav_hooks_repository_fs,
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein &dav_hooks_db_dbm,
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein &dav_hooks_locks_fs,
02fed5190fb8d69dbb70fb2330526fff85af1c41gstein NULL, /* vsn */
67ec15681c83d4f5e119f0742618569017beb3fbstriker NULL, /* binding */
bf8de10e1e04cd6019ba4e23ebebcc1eaee5d4bagstein NULL, /* search */
bf8de10e1e04cd6019ba4e23ebebcc1eaee5d4bagstein
bf8de10e1e04cd6019ba4e23ebebcc1eaee5d4bagstein NULL /* ctx */
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein};
75ba48124689705b1eee2b4fe10fe24a2d2467cdgstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmvoid dav_fs_gather_propsets(apr_array_header_t *uris)
6b745319b1099edacf401e8911efa480440f999agstein{
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#ifdef DAV_FS_HAS_EXECUTABLE
066877f1a045103acfdd376d48cdd473c33f409bdougm *(const char **)apr_array_push(uris) =
6b745319b1099edacf401e8911efa480440f999agstein "<http://apache.org/dav/propset/fs/1>";
e2308c8c7aadbaa73ea513863b49848e34b99353wrowe#endif
6b745319b1099edacf401e8911efa480440f999agstein}
6b745319b1099edacf401e8911efa480440f999agstein
acdb373d92c698a2ac260e03da95816c8a091eb6gsteinint dav_fs_find_liveprop(const dav_resource *resource,
acdb373d92c698a2ac260e03da95816c8a091eb6gstein const char *ns_uri, const char *name,
6b745319b1099edacf401e8911efa480440f999agstein const dav_hooks_liveprop **hooks)
6b745319b1099edacf401e8911efa480440f999agstein{
acdb373d92c698a2ac260e03da95816c8a091eb6gstein /* don't try to find any liveprops if this isn't "our" resource */
acdb373d92c698a2ac260e03da95816c8a091eb6gstein if (resource->hooks != &dav_hooks_repository_fs)
acdb373d92c698a2ac260e03da95816c8a091eb6gstein return 0;
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein return dav_do_find_liveprop(ns_uri, name, &dav_fs_liveprop_group, hooks);
6b745319b1099edacf401e8911efa480440f999agstein}
6b745319b1099edacf401e8911efa480440f999agstein
6b745319b1099edacf401e8911efa480440f999agsteinvoid dav_fs_insert_all_liveprops(request_rec *r, const dav_resource *resource,
dd56b1dd453bd9032d97028bc3987f999c31280cwrowe dav_prop_insert what, apr_text_header *phdr)
6b745319b1099edacf401e8911efa480440f999agstein{
acdb373d92c698a2ac260e03da95816c8a091eb6gstein /* don't insert any liveprops if this isn't "our" resource */
acdb373d92c698a2ac260e03da95816c8a091eb6gstein if (resource->hooks != &dav_hooks_repository_fs)
acdb373d92c698a2ac260e03da95816c8a091eb6gstein return;
acdb373d92c698a2ac260e03da95816c8a091eb6gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein if (!resource->exists) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* a lock-null resource */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### technically, we should insert empty properties. dunno offhand
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### what part of the spec said this, but it was essentially thus:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ** ### "the properties should be defined, but may have no value".
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return;
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein }
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (void) dav_fs_insert_prop(resource, DAV_PROPID_creationdate,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe what, phdr);
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (void) dav_fs_insert_prop(resource, DAV_PROPID_getcontentlength,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe what, phdr);
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (void) dav_fs_insert_prop(resource, DAV_PROPID_getlastmodified,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe what, phdr);
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (void) dav_fs_insert_prop(resource, DAV_PROPID_getetag,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe what, phdr);
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein#ifdef DAV_FS_HAS_EXECUTABLE
0b1895a2cd5b4a9450709abdb7ae9974908f9382gstein /* Only insert this property if it is defined for this platform. */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (void) dav_fs_insert_prop(resource, DAV_PROPID_FS_executable,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe what, phdr);
e2308c8c7aadbaa73ea513863b49848e34b99353wrowe#endif
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein /* ### we know the others aren't defined as liveprops */
6b745319b1099edacf401e8911efa480440f999agstein}
6b745319b1099edacf401e8911efa480440f999agstein
5a47cad1aef57039cd47eb34ebbc2959c610f326gsteinvoid dav_fs_register(apr_pool_t *p)
75ba48124689705b1eee2b4fe10fe24a2d2467cdgstein{
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein /* register the namespace URIs */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein dav_register_liveprop_group(p, &dav_fs_liveprop_group);
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein /* register the repository provider */
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein dav_register_provider(p, "filesystem", &dav_fs_provider);
75ba48124689705b1eee2b4fe10fe24a2d2467cdgstein}