📄 repos.c
字号:
break;
}
/* put the various information back */
fsctx->path1.cur_len = save_path_len;
fsctx->path2.cur_len = save_path2_len;
fsctx->uri_buf.cur_len = save_uri_len;
fsctx->res1.collection = 0;
fsctx->res2.collection = 0;
/* assert: res1.exists == 1 */
}
}
/* ### check the return value of this? */
apr_dir_close(dirp);
if (err != NULL)
return err;
if (params->walk_type & DAV_WALKTYPE_LOCKNULL) {
apr_size_t offset = 0;
/* null terminate the directory name */
fsctx->path1.buf[fsctx->path1.cur_len - 1] = '\0';
/* Include any lock null resources found in this collection */
fsctx->res1.collection = 1;
if ((err = dav_fs_get_locknull_members(&fsctx->res1,
&fsctx->locknull_buf)) != NULL) {
/* ### maybe add a higher-level description? */
return err;
}
/* put a slash back on the end of the directory */
fsctx->path1.buf[fsctx->path1.cur_len - 1] = '/';
/* these are all non-existant (files) */
fsctx->res1.exists = 0;
fsctx->res1.collection = 0;
memset(&fsctx->info1.finfo, 0, sizeof(fsctx->info1.finfo));
while (offset < fsctx->locknull_buf.cur_len) {
apr_size_t len = strlen(fsctx->locknull_buf.buf + offset);
dav_lock *locks = NULL;
/*
** Append the locknull file to the paths and the URI. Note that
** we don't have to pad the URI for a slash since a locknull
** resource is not a collection.
*/
dav_buffer_place_mem(pool, &fsctx->path1,
fsctx->locknull_buf.buf + offset, len + 1, 0);
dav_buffer_place_mem(pool, &fsctx->uri_buf,
fsctx->locknull_buf.buf + offset, len + 1, 0);
if (fsctx->path2.buf != NULL) {
dav_buffer_place_mem(pool, &fsctx->path2,
fsctx->locknull_buf.buf + offset,
len + 1, 0);
}
/* set up the (internal) pathnames for the two resources */
fsctx->info1.pathname = fsctx->path1.buf;
fsctx->info2.pathname = fsctx->path2.buf;
/* set up the URI for the current resource */
fsctx->res1.uri = fsctx->uri_buf.buf;
/*
** To prevent a PROPFIND showing an expired locknull
** resource, query the lock database to force removal
** of both the lock entry and .locknull, if necessary..
** Sure, the query in PROPFIND would do this.. after
** the locknull resource was already included in the
** return.
**
** NOTE: we assume the caller has opened the lock database
** if they have provided DAV_WALKTYPE_LOCKNULL.
*/
/* ### we should also look into opening it read-only and
### eliding timed-out items from the walk, yet leaving
### them in the locknull database until somebody opens
### the thing writable.
*/
/* ### probably ought to use has_locks. note the problem
### mentioned above, though... we would traverse this as
### a locknull, but then a PROPFIND would load the lock
### info, causing a timeout and the locks would not be
### reported. Therefore, a null resource would be returned
### in the PROPFIND.
###
### alternative: just load unresolved locks. any direct
### locks will be timed out (correct). any indirect will
### not (correct; consider if a parent timed out -- the
### timeout routines do not walk and remove indirects;
### even the resolve func would probably fail when it
### tried to find a timed-out direct lock).
*/
if ((err = dav_lock_query(params->lockdb, &fsctx->res1,
&locks)) != NULL) {
/* ### maybe add a higher-level description? */
return err;
}
/* call the function for the specified dir + file */
if (locks != NULL &&
(err = (*params->func)(&fsctx->wres,
DAV_CALLTYPE_LOCKNULL)) != NULL) {
/* ### maybe add a higher-level description? */
return err;
}
offset += len + 1;
}
/* reset the exists flag */
fsctx->res1.exists = 1;
}
if (params->walk_type & DAV_WALKTYPE_POSTFIX) {
/* replace the dirs' trailing slashes with null terms */
fsctx->path1.buf[--fsctx->path1.cur_len] = '\0';
fsctx->uri_buf.buf[--fsctx->uri_buf.cur_len] = '\0';
if (fsctx->path2.buf != NULL) {
fsctx->path2.buf[--fsctx->path2.cur_len] = '\0';
}
/* this is a collection which exists */
fsctx->res1.collection = 1;
return (*params->func)(&fsctx->wres, DAV_CALLTYPE_POSTFIX);
}
return NULL;
}
static dav_error * dav_fs_internal_walk(const dav_walk_params *params,
int depth, int is_move,
const dav_resource *root_dst,
dav_response **response)
{
dav_fs_walker_context fsctx = { 0 };
dav_error *err;
dav_fs_copymove_walk_ctx cm_ctx = { 0 };
#if DAV_DEBUG
if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
&& params->lockdb == NULL) {
return dav_new_error(params->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
"DESIGN ERROR: walker called to walk locknull "
"resources, but a lockdb was not provided.");
}
#endif
fsctx.params = params;
fsctx.wres.walk_ctx = params->walk_ctx;
fsctx.wres.pool = params->pool;
/* ### zero out versioned, working, baselined? */
fsctx.res1 = *params->root;
fsctx.res1.pool = params->pool;
fsctx.res1.info = &fsctx.info1;
fsctx.info1 = *params->root->info;
/* the pathname is stored in the path1 buffer */
dav_buffer_init(params->pool, &fsctx.path1, fsctx.info1.pathname);
fsctx.info1.pathname = fsctx.path1.buf;
if (root_dst != NULL) {
/* internal call from the COPY/MOVE code. set it up. */
fsctx.wres.walk_ctx = &cm_ctx;
cm_ctx.is_move = is_move;
cm_ctx.res_dst = &fsctx.res2;
cm_ctx.root = params->root;
cm_ctx.pool = params->pool;
fsctx.res2 = *root_dst;
fsctx.res2.exists = 0;
fsctx.res2.collection = 0;
fsctx.res2.uri = NULL; /* we don't track this */
fsctx.res2.pool = params->pool;
fsctx.res2.info = &fsctx.info2;
fsctx.info2 = *root_dst->info;
/* res2 does not exist -- clear its finfo structure */
memset(&fsctx.info2.finfo, 0, sizeof(fsctx.info2.finfo));
/* the pathname is stored in the path2 buffer */
dav_buffer_init(params->pool, &fsctx.path2, fsctx.info2.pathname);
fsctx.info2.pathname = fsctx.path2.buf;
}
/* prep the URI buffer */
dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);
/* if we have a directory, then ensure the URI has a trailing "/" */
if (fsctx.res1.collection
&& fsctx.uri_buf.buf[fsctx.uri_buf.cur_len - 1] != '/') {
/* this will fall into the pad area */
fsctx.uri_buf.buf[fsctx.uri_buf.cur_len++] = '/';
fsctx.uri_buf.buf[fsctx.uri_buf.cur_len] = '\0';
}
/* the current resource's URI is stored in the uri_buf buffer */
fsctx.res1.uri = fsctx.uri_buf.buf;
/* point the callback's resource at our structure */
fsctx.wres.resource = &fsctx.res1;
/* always return the error, and any/all multistatus responses */
err = dav_fs_walker(&fsctx, depth);
*response = fsctx.wres.response;
return err;
}
static dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
dav_response **response)
{
/* always return the error, and any/all multistatus responses */
return dav_fs_internal_walk(params, depth, 0, NULL, response);
}
/* dav_fs_etag: Stolen from ap_make_etag. Creates a strong etag
* for file path.
* ### do we need to return weak tags sometimes?
*/
static const char *dav_fs_getetag(const dav_resource *resource)
{
dav_resource_private *ctx = resource->info;
if (!resource->exists)
return apr_pstrdup(ctx->pool, "");
if (ctx->finfo.filetype != 0) {
return apr_psprintf(ctx->pool, "\"%lx-%lx-%lx\"",
(unsigned long) ctx->finfo.inode,
(unsigned long) ctx->finfo.size,
(unsigned long) ctx->finfo.mtime);
}
return apr_psprintf(ctx->pool, "\"%lx\"", (unsigned long) ctx->finfo.mtime);
}
static const dav_hooks_repository dav_hooks_repository_fs =
{
DEBUG_GET_HANDLER, /* normally: special GET handling not required */
dav_fs_get_resource,
dav_fs_get_parent_resource,
dav_fs_is_same_resource,
dav_fs_is_parent_resource,
dav_fs_open_stream,
dav_fs_close_stream,
dav_fs_write_stream,
dav_fs_seek_stream,
#if DEBUG_GET_HANDLER
dav_fs_set_headers,
dav_fs_deliver,
#else
NULL,
NULL,
#endif
dav_fs_create_collection,
dav_fs_copy_resource,
dav_fs_move_resource,
dav_fs_remove_resource,
dav_fs_walk,
dav_fs_getetag,
};
static dav_prop_insert dav_fs_insert_prop(const dav_resource *resource,
int propid, dav_prop_insert what,
apr_text_header *phdr)
{
const char *value;
const char *s;
apr_pool_t *p = resource->info->pool;
const dav_liveprop_spec *info;
int global_ns;
/* an HTTP-date can be 29 chars plus a null term */
/* a 64-bit size can be 20 chars plus a null term */
char buf[DAV_TIMEBUF_SIZE];
/*
** None of FS provider properties are defined if the resource does not
** exist. Just bail for this case.
**
** Even though we state that the FS properties are not defined, the
** client cannot store dead values -- we deny that thru the is_writable
** hook function.
*/
if (!resource->exists)
return DAV_PROP_INSERT_NOTDEF;
switch (propid) {
case DAV_PROPID_creationdate:
/*
** Closest thing to a creation date. since we don't actually
** perform the operations that would modify ctime (after we
** create the file), then we should be pretty safe here.
*/
dav_format_time(DAV_STYLE_ISO8601,
resource->info->finfo.ctime,
buf);
value = buf;
break;
case DAV_PROPID_getcontentlength:
/* our property, but not defined on collection resources */
if (resource->collection)
return DAV_PROP_INSERT_NOTDEF;
(void) sprintf(buf, "%" APR_OFF_T_FMT, resource->info->finfo.size);
value = buf;
break;
case DAV_PROPID_getetag:
value = dav_fs_getetag(resource);
break;
case DAV_PROPID_getlastmodified:
dav_format_time(DAV_STYLE_RFC822,
resource->info->finfo.mtime,
buf);
value = buf;
break;
case DAV_PROPID_FS_executable:
/* our property, but not defined on collection resources */
if (resource->collection)
return DAV_PROP_INSERT_NOTDEF;
/* our property, but not defined on this platform */
if (!(resource->info->finfo.valid & APR_FINFO_UPROT))
return DAV_PROP_INSERT_NOTDEF;
/* the files are "ours" so we only need to check owner exec privs */
if (resource->info->finfo.protection & APR_UEXECUTE)
value = "T";
else
value = "F";
break;
default:
/* ### what the heck was this property? */
return DAV_PROP_INSERT_NOTDEF;
}
/* assert: value != NULL */
/* get the information and global NS index for the property */
global_ns = dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
/* assert: info != NULL && info->name != NULL */
/* DBG3("FS: inserting lp%d:%s (local %d)", ns, scan->name, scan->ns); */
if (what == DAV_PROP_INSERT_VALUE) {
s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
global_ns, info->name, value, global_ns, info->name);
}
else if (what == DAV_PROP_INSERT_NAME) {
s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name);
}
else {
/* assert: what == DAV_PROP_INSERT_SUPPORTED */
s = apr_psprintf(p,
"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -