📄 repos.c
字号:
} /* ### 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, "\"%" APR_UINT64_T_HEX_FMT "-%" APR_UINT64_T_HEX_FMT "-%" APR_UINT64_T_HEX_FMT "\"", (apr_uint64_t) ctx->finfo.inode, (apr_uint64_t) ctx->finfo.size, (apr_uint64_t) ctx->finfo.mtime); } return apr_psprintf(ctx->pool, "\"%" APR_UINT64_T_HEX_FMT "\"", (apr_uint64_t) 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, "<D:supported-live-property D:name=\"%s\" " "D:namespace=\"%s\"/>" DEBUG_CR, info->name, dav_fs_namespace_uris[info->ns]); } apr_text_append(p, phdr, s); /* we inserted what was asked for */ return what;}static int dav_fs_is_writable(const dav_resource *resource, int propid){ const dav_liveprop_spec *info;#ifdef DAV_FS_HAS_EXECUTABLE /* if we have the executable property, and this isn't a collection, then the property is writable. */ if (propid == DAV_PROPID_FS_executable && !resource->collection) return 1;#endif (void) dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info); return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -