📄 repos.c
字号:
if (apr_file_remove(dst, p) != APR_SUCCESS) { /* ### ACK! Inconsistent state... */ /* ### use something besides 500? */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not delete output after write " "failure. Server is now in an " "inconsistent state."); } return dav_new_error(p, MAP_IO2HTTP(status), 0, "Could not write output file"); } } apr_file_close(inf); apr_file_close(outf); if (is_move && apr_file_remove(src, p) != APR_SUCCESS) { dav_error *err; int save_errno = errno; /* save the errno that got us here */ if (apr_file_remove(dst, p) != APR_SUCCESS) { /* ### ACK. this creates an inconsistency. do more!? */ /* ### use something besides 500? */ /* Note that we use the latest errno */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not remove source or destination " "file. Server is now in an inconsistent " "state."); } /* ### use something besides 500? */ err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not remove source file after move. " "Destination was removed to ensure consistency."); err->save_errno = save_errno; return err; } return NULL;}/* copy/move a file from within a state dir to another state dir *//* ### need more buffers to replace the pool argument */static dav_error * dav_fs_copymove_state( int is_move, apr_pool_t * p, const char *src_dir, const char *src_file, const char *dst_dir, const char *dst_file, dav_buffer *pbuf){ apr_finfo_t src_finfo; /* finfo for source file */ apr_finfo_t dst_state_finfo; /* finfo for STATE directory */ apr_status_t rv; const char *src; const char *dst; /* build the propset pathname for the source file */ src = apr_pstrcat(p, src_dir, "/" DAV_FS_STATE_DIR "/", src_file, NULL); /* the source file doesn't exist */ rv = apr_stat(&src_finfo, src, APR_FINFO_NORM, p); if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) { return NULL; } /* build the pathname for the destination state dir */ dst = apr_pstrcat(p, dst_dir, "/" DAV_FS_STATE_DIR, NULL); /* ### do we need to deal with the umask? */ /* ensure that it exists */ rv = apr_dir_make(dst, APR_OS_DEFAULT, p); if (rv != APR_SUCCESS) { if (!APR_STATUS_IS_EEXIST(rv)) { /* ### use something besides 500? */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not create internal state directory"); } } /* get info about the state directory */ rv = apr_stat(&dst_state_finfo, dst, APR_FINFO_NORM, p); if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) { /* Ack! Where'd it go? */ /* ### use something besides 500? */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "State directory disappeared"); } /* The mkdir() may have failed because a *file* exists there already */ if (dst_state_finfo.filetype != APR_DIR) { /* ### try to recover by deleting this file? (and mkdir again) */ /* ### use something besides 500? */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "State directory is actually a file"); } /* append the target file to the state directory pathname */ dst = apr_pstrcat(p, dst, "/", dst_file, NULL); /* copy/move the file now */ if (is_move && src_finfo.device == dst_state_finfo.device) { /* simple rename is possible since it is on the same device */ if (apr_file_rename(src, dst, p) != APR_SUCCESS) { /* ### use something besides 500? */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not move state file."); } } else { /* gotta copy (and delete) */ return dav_fs_copymove_file(is_move, p, src, dst, NULL, NULL, pbuf); } return NULL;}static dav_error *dav_fs_copymoveset(int is_move, apr_pool_t *p, const dav_resource *src, const dav_resource *dst, dav_buffer *pbuf){ const char *src_dir; const char *src_file; const char *src_state1; const char *src_state2; const char *dst_dir; const char *dst_file; const char *dst_state1; const char *dst_state2; dav_error *err; /* Get directory and filename for resources */ /* ### should test these result values... */ (void) dav_fs_dir_file_name(src, &src_dir, &src_file); (void) dav_fs_dir_file_name(dst, &dst_dir, &dst_file); /* Get the corresponding state files for each resource */ dav_dbm_get_statefiles(p, src_file, &src_state1, &src_state2); dav_dbm_get_statefiles(p, dst_file, &dst_state1, &dst_state2);#if DAV_DEBUG if ((src_state2 != NULL && dst_state2 == NULL) || (src_state2 == NULL && dst_state2 != NULL)) { return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "DESIGN ERROR: dav_dbm_get_statefiles() " "returned inconsistent results."); }#endif err = dav_fs_copymove_state(is_move, p, src_dir, src_state1, dst_dir, dst_state1, pbuf); if (err == NULL && src_state2 != NULL) { err = dav_fs_copymove_state(is_move, p, src_dir, src_state2, dst_dir, dst_state2, pbuf); if (err != NULL) { /* ### CRAP. inconsistency. */ /* ### should perform some cleanup at the target if we still ### have the original files */ /* Change the error to reflect the bad server state. */ err->status = HTTP_INTERNAL_SERVER_ERROR; err->desc = "Could not fully copy/move the properties. " "The server is now in an inconsistent state."; } } return err;}static dav_error *dav_fs_deleteset(apr_pool_t *p, const dav_resource *resource){ const char *dirpath; const char *fname; const char *state1; const char *state2; const char *pathname; apr_status_t status; /* Get directory, filename, and state-file names for the resource */ /* ### should test this result value... */ (void) dav_fs_dir_file_name(resource, &dirpath, &fname); dav_dbm_get_statefiles(p, fname, &state1, &state2); /* build the propset pathname for the file */ pathname = apr_pstrcat(p, dirpath, "/" DAV_FS_STATE_DIR "/", state1, NULL); /* note: we may get ENOENT if the state dir is not present */ if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS && !APR_STATUS_IS_ENOENT(status)) { return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not remove properties."); } if (state2 != NULL) { /* build the propset pathname for the file */ pathname = apr_pstrcat(p, dirpath, "/" DAV_FS_STATE_DIR "/", state2, NULL); if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS && !APR_STATUS_IS_ENOENT(status)) { /* ### CRAP. only removed half. */ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not fully remove properties. " "The server is now in an inconsistent " "state."); } } return NULL;}/* --------------------------------------------------------------------**** REPOSITORY HOOK FUNCTIONS*/static dav_error * dav_fs_get_resource( request_rec *r, const char *root_dir, const char *label, int use_checked_in, dav_resource **result_resource){ dav_resource_private *ctx; dav_resource *resource; char *s; char *filename; apr_size_t len; /* ### optimize this into a single allocation! */ /* Create private resource context descriptor */ ctx = apr_pcalloc(r->pool, sizeof(*ctx)); ctx->finfo = r->finfo; /* ### this should go away */ ctx->pool = r->pool; /* Preserve case on OSes which fold canonical filenames */#if 0 /* ### not available in Apache 2.0 yet */ filename = r->case_preserved_filename;#else filename = r->filename;#endif /* ** If there is anything in the path_info, then this indicates that the ** entire path was not used to specify the file/dir. We want to append ** it onto the filename so that we get a "valid" pathname for null ** resources. */ s = apr_pstrcat(r->pool, filename, r->path_info, NULL); /* make sure the pathname does not have a trailing "/" */ len = strlen(s); if (len > 1 && s[len - 1] == '/') { s[len - 1] = '\0'; } ctx->pathname = s; /* Create resource descriptor */ resource = apr_pcalloc(r->pool, sizeof(*resource)); resource->type = DAV_RESOURCE_TYPE_REGULAR; resource->info = ctx; resource->hooks = &dav_hooks_repository_fs; resource->pool = r->pool; /* make sure the URI does not have a trailing "/" */ len = strlen(r->uri); if (len > 1 && r->uri[len - 1] == '/') { s = apr_pstrdup(r->pool, r->uri); s[len - 1] = '\0'; resource->uri = s; } else { resource->uri = r->uri; } if (r->finfo.filetype != 0) { resource->exists = 1; resource->collection = r->finfo.filetype == APR_DIR; /* unused info in the URL will indicate a null resource */ if (r->path_info != NULL && *r->path_info != '\0') { if (resource->collection) { /* only a trailing "/" is allowed */ if (*r->path_info != '/' || r->path_info[1] != '\0') { /* ** This URL/filename represents a locknull resource or ** possibly a destination of a MOVE/COPY */ resource->exists = 0; resource->collection = 0; } } else { /* ** The base of the path refers to a file -- nothing should ** be in path_info. The resource is simply an error: it ** can't be a null or a locknull resource. */ return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "The URL contains extraneous path " "components. The resource could not " "be identified."); } /* retain proper integrity across the structures */ if (!resource->exists) { ctx->finfo.filetype = 0; } } } *result_resource = resource; return NULL;}static dav_error * dav_fs_get_parent_resource(const dav_resource *resource, dav_resource **result_parent){ dav_resource_private *ctx = resource->info; dav_resource_private *parent_ctx; dav_resource *parent_resource; apr_status_t rv; char *dirpath; const char *testroot; const char *testpath; /* If we're at the root of the URL space, then there is no parent. */ if (strcmp(resource->uri, "/") == 0) { *result_parent = NULL; return NULL; } /* If given resource is root, then there is no parent. * Unless we can retrieve the filepath root, this is * intendend to fail. If we split the root and * no path info remains, then we also fail. */ testpath = ctx->pathname; rv = apr_filepath_root(&testroot, &testpath, 0, ctx->pool); if ((rv != APR_SUCCESS && rv != APR_ERELATIVE) || !testpath || !*testpath) { *result_parent = NULL; return NULL; } /* ### optimize this into a single allocation! */ /* Create private resource context descriptor */ parent_ctx = apr_pcalloc(ctx->pool, sizeof(*parent_ctx)); /* ### this should go away */ parent_ctx->pool = ctx->pool; dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname); if (strlen(dirpath) > 1 && dirpath[strlen(dirpath) - 1] == '/') dirpath[strlen(dirpath) - 1] = '\0'; parent_ctx->pathname = dirpath; parent_resource = apr_pcalloc(ctx->pool, sizeof(*parent_resource)); parent_resource->info = parent_ctx; parent_resource->collection = 1; parent_resource->hooks = &dav_hooks_repository_fs; parent_resource->pool = resource->pool;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -