📄 util_lock.c
字号:
/* ### should we stop or return a multistatus? looks like STOP */ /* ### add a higher-level description? */ return err; } return NULL;}/*** dav_get_direct_resource:**** Find a lock on the specified resource, then return the resource the** lock was applied to (in other words, given a (possibly) indirect lock,** return the direct lock's corresponding resource).**** If the lock is an indirect lock, this usually means traversing up the** namespace [repository] hierarchy. Note that some lock providers may be** able to return this information with a traversal.*/static dav_error * dav_get_direct_resource(apr_pool_t *p, dav_lockdb *lockdb, const dav_locktoken *locktoken, const dav_resource *resource, const dav_resource **direct_resource){ if (lockdb->hooks->lookup_resource != NULL) { return (*lockdb->hooks->lookup_resource)(lockdb, locktoken, resource, direct_resource); } *direct_resource = NULL; /* Find the top of this lock- * If r->filename's direct locks include locktoken, use r->filename. * If r->filename's indirect locks include locktoken, retry r->filename/.. * Else fail. */ while (resource != NULL) { dav_error *err; dav_lock *lock; dav_resource *parent; /* ** Find the lock specified by <locktoken> on <resource>. If it is ** an indirect lock, then partial results are okay. We're just ** trying to find the thing and know whether it is a direct or ** an indirect lock. */ if ((err = (*lockdb->hooks->find_lock)(lockdb, resource, locktoken, 1, &lock)) != NULL) { /* ### add a higher-level desc? */ return err; } /* not found! that's an error. */ if (lock == NULL) { return dav_new_error(p, HTTP_BAD_REQUEST, 0, "The specified locktoken does not correspond " "to an existing lock on this resource."); } if (lock->rectype == DAV_LOCKREC_DIRECT) { /* we found the direct lock. return this resource. */ *direct_resource = resource; return NULL; } /* the lock was indirect. move up a level in the URL namespace */ if ((err = (*resource->hooks->get_parent_resource)(resource, &parent)) != NULL) { /* ### add a higher-level desc? */ return err; } resource = parent; } return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "The lock database is corrupt. A direct lock could " "not be found for the corresponding indirect lock " "on this resource.");}/*** dav_unlock: Removes all direct and indirect locks for r->filename,** with given locktoken. If locktoken == null_locktoken, all locks** are removed. If r->filename represents an indirect lock,** we must unlock the appropriate direct lock.** Returns OK or appropriate HTTP_* response and logs any errors.**** ### We've already crawled the tree to ensure everything was locked** by us; there should be no need to incorporate a rollback.*/DAV_DECLARE(int) dav_unlock(request_rec *r, const dav_resource *resource, const dav_locktoken *locktoken){ int result; dav_lockdb *lockdb; const dav_resource *lock_resource = resource; const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r); const dav_hooks_repository *repos_hooks = resource->hooks; dav_walker_ctx ctx = { { 0 } }; dav_response *multi_status; dav_error *err; /* If no locks provider, then there is nothing to unlock. */ if (hooks == NULL) { return OK; } /* 2518 requires the entire lock to be removed if resource/locktoken * point to an indirect lock. We need resource of the _direct_ * lock in order to walk down the tree and remove the locks. So, * If locktoken != null_locktoken, * Walk up the resource hierarchy until we see a direct lock. * Or, we could get the direct lock's db/key, pick out the URL * and do a subrequest. I think walking up is faster and will work * all the time. * Else * Just start removing all locks at and below resource. */ if ((err = (*hooks->open_lockdb)(r, 0, 1, &lockdb)) != NULL) { /* ### return err! maybe add a higher-level desc */ /* ### map result to something nice; log an error */ return HTTP_INTERNAL_SERVER_ERROR; } if (locktoken != NULL && (err = dav_get_direct_resource(r->pool, lockdb, locktoken, resource, &lock_resource)) != NULL) { /* ### add a higher-level desc? */ /* ### should return err! */ return err->status; } /* At this point, lock_resource/locktoken refers to a direct lock (key), ie * the root of a depth > 0 lock, or locktoken is null. */ ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL; ctx.w.func = dav_unlock_walker; ctx.w.walk_ctx = &ctx; ctx.w.pool = r->pool; ctx.w.root = lock_resource; ctx.w.lockdb = lockdb; ctx.r = r; ctx.locktoken = locktoken; err = (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status); /* ### fix this! */ /* ### do something with multi_status */ result = err == NULL ? OK : err->status; (*hooks->close_lockdb)(lockdb); return result;}/* dav_inherit_walker: Walker callback function to inherit locks */static dav_error * dav_inherit_walker(dav_walk_resource *wres, int calltype){ dav_walker_ctx *ctx = wres->walk_ctx; if (ctx->skip_root && (*wres->resource->hooks->is_same_resource)(wres->resource, ctx->w.root)) { return NULL; } /* ### maybe add a higher-level desc */ return (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb, wres->resource, 1, ctx->lock);}/*** dav_inherit_locks: When a resource or collection is added to a collection,** locks on the collection should be inherited to the resource/collection.** (MOVE, MKCOL, etc) Here we propagate any direct or indirect locks from** parent of resource to resource and below.*/static dav_error * dav_inherit_locks(request_rec *r, dav_lockdb *lockdb, const dav_resource *resource, int use_parent){ dav_error *err; const dav_resource *which_resource; dav_lock *locks; dav_lock *scan; dav_lock *prev; dav_walker_ctx ctx = { { 0 } }; const dav_hooks_repository *repos_hooks = resource->hooks; dav_response *multi_status; if (use_parent) { dav_resource *parent; if ((err = (*repos_hooks->get_parent_resource)(resource, &parent)) != NULL) { /* ### add a higher-level desc? */ return err; } if (parent == NULL) { /* ### map result to something nice; log an error */ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not fetch parent resource. Unable to " "inherit locks from the parent and apply " "them to this resource."); } which_resource = parent; } else { which_resource = resource; } if ((err = (*lockdb->hooks->get_locks)(lockdb, which_resource, DAV_GETLOCKS_PARTIAL, &locks)) != NULL) { /* ### maybe add a higher-level desc */ return err; } if (locks == NULL) { /* No locks to propagate, just return */ return NULL; } /* ** (1) Copy all indirect locks from our parent; ** (2) Create indirect locks for the depth infinity, direct locks ** in our parent. ** ** The append_locks call in the walker callback will do the indirect ** conversion, but we need to remove any direct locks that are NOT ** depth "infinity". */ for (scan = locks, prev = NULL; scan != NULL; prev = scan, scan = scan->next) { if (scan->rectype == DAV_LOCKREC_DIRECT && scan->depth != DAV_INFINITY) { if (prev == NULL) locks = scan->next; else prev->next = scan->next; } } /* <locks> has all our new locks. Walk down and propagate them. */ ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL; ctx.w.func = dav_inherit_walker; ctx.w.walk_ctx = &ctx; ctx.w.pool = r->pool; ctx.w.root = resource; ctx.w.lockdb = lockdb; ctx.r = r; ctx.lock = locks; ctx.skip_root = !use_parent; /* ### do something with multi_status */ return (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);}/* ---------------------------------------------------------------**** Functions dealing with lock-null resources***//*** dav_get_resource_state: Returns the state of the resource** r->filename: DAV_RESOURCE_NULL, DAV_RESOURCE_LOCK_NULL,** or DAV_RESOURCE_EXIST.**** Returns DAV_RESOURCE_ERROR if an error occurs.*/DAV_DECLARE(int) dav_get_resource_state(request_rec *r, const dav_resource *resource){ const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r); if (resource->exists) return DAV_RESOURCE_EXISTS; if (hooks != NULL) { dav_error *err; dav_lockdb *lockdb; int locks_present; /* ** A locknull resource has the form: ** ** known-dir "/" locknull-file ** ** It would be nice to look into <resource> to verify this form, ** but it does not have enough information for us. Instead, we ** can look at the path_info. If the form does not match, then ** there is no way we could have a locknull resource -- it must ** be a plain, null resource. ** ** Apache sets r->filename to known-dir/unknown-file and r->path_info ** to "" for the "proper" case. If anything is in path_info, then ** it can't be a locknull resource. ** ** ### I bet this path_info hack doesn't work for repositories. ** ### Need input from repository implementors! What kind of ** ### restructure do we need? New provider APIs? */ if (r->path_info != NULL && *r->path_info != '\0') { return DAV_RESOURCE_NULL; } if ((err = (*hooks->open_lockdb)(r, 1, 1, &lockdb)) == NULL) { /* note that we might see some expired locks... *shrug* */ err = (*hooks->has_locks)(lockdb, resource, &locks_present); (*hooks->close_lockdb)(lockdb); } if (err != NULL) { /* ### don't log an error. return err. add higher-level desc. */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Failed to query lock-null status for %s", r->filename); return DAV_RESOURCE_ERROR; } if (locks_present) return DAV_RESOURCE_LOCK_NULL; } return DAV_RESOURCE_NULL;}DAV_DECLARE(dav_error *) dav_notify_created(request_rec *r, dav_lockdb *lockdb, const dav_resource *resource, int resource_state, int depth){ dav_error *err; if (resource_state == DAV_RESOURCE_LOCK_NULL) { /* ** The resource is no longer a locknull resource. This will remove ** the special marker. ** ** Note that a locknull resource has already inherited all of the ** locks from the parent. We do not need to call dav_inherit_locks. ** ** NOTE: some lock providers record locks for locknull resources using ** a different key than for regular resources. this will shift ** the lock information between the two key types. */ (void)(*lockdb->hooks->remove_locknull_state)(lockdb, resource); /* ** There are resources under this one, which are new. We must ** propagate the locks down to the new resources. */ if (depth > 0 && (err = dav_inherit_locks(r, lockdb, resource, 0)) != NULL) { /* ### add a higher level desc? */ return err; } } else if (resource_state == DAV_RESOURCE_NULL) { /* ### should pass depth to dav_inherit_locks so that it can ** ### optimize for the depth==0 case. */ /* this resource should inherit locks from its parent */ if ((err = dav_inherit_locks(r, lockdb, resource, 1)) != NULL) { err = dav_push_error(r->pool, err->status, 0, "The resource was created successfully, but " "there was a problem inheriting locks from " "the parent resource.", err); return err; } } /* else the resource already exists and its locks are correct. */ return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -