📄 lock.c
字号:
/* ### add a higher-level description? */
return err;
}
{
dav_lock_discovery *ld;
dav_lock_indirect *id;
apr_datum_t key;
/*
** Fetch the lock(s) that made the resource lock-null. Remove
** them under the filename key. Obtain the new inode key, and
** save the same lock information under it.
*/
key = dav_fs_build_fname_key(p, pathname);
if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
&ld, &id)) != NULL) {
/* ### insert a higher-level error description */
return err;
}
if ((err = dav_fs_save_lock_record(lockdb, key, NULL, NULL)) != NULL) {
/* ### insert a higher-level error description */
return err;
}
key = dav_fs_build_key(p, resource);
if ((err = dav_fs_save_lock_record(lockdb, key, ld, id)) != NULL) {
/* ### insert a higher-level error description */
return err;
}
}
return NULL;
}
static dav_error * dav_fs_create_lock(dav_lockdb *lockdb,
const dav_resource *resource,
dav_lock **lock)
{
apr_datum_t key;
key = dav_fs_build_key(lockdb->info->pool, resource);
*lock = dav_fs_alloc_lock(lockdb,
key,
NULL);
(*lock)->is_locknull = !resource->exists;
return NULL;
}
static dav_error * dav_fs_get_locks(dav_lockdb *lockdb,
const dav_resource *resource,
int calltype,
dav_lock **locks)
{
apr_pool_t *p = lockdb->info->pool;
apr_datum_t key;
dav_error *err;
dav_lock *lock = NULL;
dav_lock *newlock;
dav_lock_discovery *dp;
dav_lock_indirect *ip;
#if DAV_DEBUG
if (calltype == DAV_GETLOCKS_COMPLETE) {
return dav_new_error(lockdb->info->pool,
HTTP_INTERNAL_SERVER_ERROR, 0,
"INTERNAL DESIGN ERROR: DAV_GETLOCKS_COMPLETE "
"is not yet supported");
}
#endif
key = dav_fs_build_key(p, resource);
if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
&dp, &ip)) != NULL) {
/* ### push a higher-level desc? */
return err;
}
/* copy all direct locks to the result list */
for (; dp != NULL; dp = dp->next) {
newlock = dav_fs_alloc_lock(lockdb, key, dp->locktoken);
newlock->is_locknull = !resource->exists;
newlock->scope = dp->f.scope;
newlock->type = dp->f.type;
newlock->depth = dp->f.depth;
newlock->timeout = dp->f.timeout;
newlock->owner = dp->owner;
newlock->auth_user = dp->auth_user;
/* hook into the result list */
newlock->next = lock;
lock = newlock;
}
/* copy all the indirect locks to the result list. resolve as needed. */
for (; ip != NULL; ip = ip->next) {
newlock = dav_fs_alloc_lock(lockdb, ip->key, ip->locktoken);
newlock->is_locknull = !resource->exists;
if (calltype == DAV_GETLOCKS_RESOLVED) {
if ((err = dav_fs_resolve(lockdb, ip, &dp, NULL, NULL)) != NULL) {
/* ### push a higher-level desc? */
return err;
}
newlock->scope = dp->f.scope;
newlock->type = dp->f.type;
newlock->depth = dp->f.depth;
newlock->timeout = dp->f.timeout;
newlock->owner = dp->owner;
newlock->auth_user = dp->auth_user;
}
else {
/* DAV_GETLOCKS_PARTIAL */
newlock->rectype = DAV_LOCKREC_INDIRECT_PARTIAL;
}
/* hook into the result list */
newlock->next = lock;
lock = newlock;
}
*locks = lock;
return NULL;
}
static dav_error * dav_fs_find_lock(dav_lockdb *lockdb,
const dav_resource *resource,
const dav_locktoken *locktoken,
int partial_ok,
dav_lock **lock)
{
dav_error *err;
apr_datum_t key;
dav_lock_discovery *dp;
dav_lock_indirect *ip;
*lock = NULL;
key = dav_fs_build_key(lockdb->info->pool, resource);
if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
&dp, &ip)) != NULL) {
/* ### push a higher-level desc? */
return err;
}
for (; dp != NULL; dp = dp->next) {
if (!dav_compare_locktoken(locktoken, dp->locktoken)) {
*lock = dav_fs_alloc_lock(lockdb, key, locktoken);
(*lock)->is_locknull = !resource->exists;
(*lock)->scope = dp->f.scope;
(*lock)->type = dp->f.type;
(*lock)->depth = dp->f.depth;
(*lock)->timeout = dp->f.timeout;
(*lock)->owner = dp->owner;
(*lock)->auth_user = dp->auth_user;
return NULL;
}
}
for (; ip != NULL; ip = ip->next) {
if (!dav_compare_locktoken(locktoken, ip->locktoken)) {
*lock = dav_fs_alloc_lock(lockdb, ip->key, locktoken);
(*lock)->is_locknull = !resource->exists;
/* ### nobody uses the resolving right now! */
if (partial_ok) {
(*lock)->rectype = DAV_LOCKREC_INDIRECT_PARTIAL;
}
else {
(*lock)->rectype = DAV_LOCKREC_INDIRECT;
if ((err = dav_fs_resolve(lockdb, ip, &dp,
NULL, NULL)) != NULL) {
/* ### push a higher-level desc? */
return err;
}
(*lock)->scope = dp->f.scope;
(*lock)->type = dp->f.type;
(*lock)->depth = dp->f.depth;
(*lock)->timeout = dp->f.timeout;
(*lock)->owner = dp->owner;
(*lock)->auth_user = dp->auth_user;
}
return NULL;
}
}
return NULL;
}
static dav_error * dav_fs_has_locks(dav_lockdb *lockdb,
const dav_resource *resource,
int *locks_present)
{
dav_error *err;
apr_datum_t key;
*locks_present = 0;
if ((err = dav_fs_really_open_lockdb(lockdb)) != NULL) {
/* ### insert a higher-level error description */
return err;
}
/*
** If we opened readonly and the db wasn't there, then there are no
** locks for this resource. Just exit.
*/
if (lockdb->info->db == NULL)
return NULL;
key = dav_fs_build_key(lockdb->info->pool, resource);
*locks_present = dav_dbm_exists(lockdb->info->db, key);
return NULL;
}
static dav_error * dav_fs_append_locks(dav_lockdb *lockdb,
const dav_resource *resource,
int make_indirect,
const dav_lock *lock)
{
apr_pool_t *p = lockdb->info->pool;
dav_error *err;
dav_lock_indirect *ip;
dav_lock_discovery *dp;
apr_datum_t key;
key = dav_fs_build_key(lockdb->info->pool, resource);
if ((err = dav_fs_load_lock_record(lockdb, key, 0, &dp, &ip)) != NULL) {
/* ### maybe add in a higher-level description */
return err;
}
/*
** ### when we store the lock more directly, we need to update
** ### lock->rectype and lock->is_locknull
*/
if (make_indirect) {
for (; lock != NULL; lock = lock->next) {
/* ### this works for any <lock> rectype */
dav_lock_indirect *newi = apr_pcalloc(p, sizeof(*newi));
/* ### shut off the const warning for now */
newi->locktoken = (dav_locktoken *)lock->locktoken;
newi->timeout = lock->timeout;
newi->key = lock->info->key;
newi->next = ip;
ip = newi;
}
}
else {
for (; lock != NULL; lock = lock->next) {
/* create and link in the right kind of lock */
if (lock->rectype == DAV_LOCKREC_DIRECT) {
dav_lock_discovery *newd = apr_pcalloc(p, sizeof(*newd));
newd->f.scope = lock->scope;
newd->f.type = lock->type;
newd->f.depth = lock->depth;
newd->f.timeout = lock->timeout;
/* ### shut off the const warning for now */
newd->locktoken = (dav_locktoken *)lock->locktoken;
newd->owner = lock->owner;
newd->auth_user = lock->auth_user;
newd->next = dp;
dp = newd;
}
else {
/* DAV_LOCKREC_INDIRECT(_PARTIAL) */
dav_lock_indirect *newi = apr_pcalloc(p, sizeof(*newi));
/* ### shut off the const warning for now */
newi->locktoken = (dav_locktoken *)lock->locktoken;
newi->key = lock->info->key;
newi->next = ip;
ip = newi;
}
}
}
if ((err = dav_fs_save_lock_record(lockdb, key, dp, ip)) != NULL) {
/* ### maybe add a higher-level description */
return err;
}
/* we have a special list for recording locknull resources */
/* ### ack! this can add two copies to the locknull list */
if (!resource->exists
&& (err = dav_fs_add_locknull_state(lockdb, resource)) != NULL) {
/* ### maybe add a higher-level description */
return err;
}
return NULL;
}
static dav_error * dav_fs_remove_lock(dav_lockdb *lockdb,
const dav_resource *resource,
const dav_locktoken *locktoken)
{
dav_error *err;
dav_buffer buf = { 0 };
dav_lock_discovery *dh = NULL;
dav_lock_indirect *ih = NULL;
apr_datum_t key;
key = dav_fs_build_key(lockdb->info->pool, resource);
if (locktoken != NULL) {
dav_lock_discovery *dp;
dav_lock_discovery *dprev = NULL;
dav_lock_indirect *ip;
dav_lock_indirect *iprev = NULL;
if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
&dh, &ih)) != NULL) {
/* ### maybe add a higher-level description */
return err;
}
for (dp = dh; dp != NULL; dp = dp->next) {
if (dav_compare_locktoken(locktoken, dp->locktoken) == 0) {
if (dprev)
dprev->next = dp->next;
else
dh = dh->next;
}
dprev = dp;
}
for (ip = ih; ip != NULL; ip = ip->next) {
if (dav_compare_locktoken(locktoken, ip->locktoken) == 0) {
if (iprev)
iprev->next = ip->next;
else
ih = ih->next;
}
iprev = ip;
}
}
/* save the modified locks, or remove all locks (dh=ih=NULL). */
if ((err = dav_fs_save_lock_record(lockdb, key, dh, ih)) != NULL) {
/* ### maybe add a higher-level description */
return err;
}
/*
** If this resource is a locknull resource AND no more locks exist,
** then remove the locknull member.
**
** Note: remove_locknull_state() attempts to convert a locknull member
** to a real member. In this case, all locks are gone, so the
** locknull resource returns to the null state (ie. doesn't exist),
** so there is no need to update the lockdb (and it won't find
** any because a precondition is that none exist).
*/
if (!resource->exists && dh == NULL && ih == NULL
&& (err = dav_fs_remove_locknull_member(lockdb->info->pool,
dav_fs_pathname(resource),
&buf)) != NULL) {
/* ### maybe add a higher-level description */
return err;
}
return NULL;
}
static int dav_fs_do_refresh(dav_lock_discovery *dp,
const dav_locktoken_list *ltl,
time_t new_time)
{
int dirty = 0;
for (; ltl != NULL; ltl = ltl->next) {
if (dav_compare_locktoken(dp->locktoken, ltl->locktoken) == 0)
{
dp->f.timeout = new_time;
dirty = 1;
}
}
return dirty;
}
static dav_error * dav_fs_refresh_locks(dav_lockdb *lockdb,
const dav_resource *resource,
const dav_locktoken_list *ltl,
time_t new_time,
dav_lock **locks)
{
dav_error *err;
apr_datum_t key;
dav_lock_discovery *dp;
dav_lock_discovery *dp_scan;
dav_lock_indirect *ip;
int dirty = 0;
dav_lock *newlock;
*locks = NULL;
key = dav_fs_build_key(lockdb->info->pool, resource);
if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
&dp, &ip)) != NULL) {
/* ### maybe add in a higher-level description */
return err;
}
/* ### we should be refreshing direct AND (resolved) indirect locks! */
/* refresh all of the direct locks on this resource */
for (dp_scan = dp; dp_scan != NULL; dp_scan = dp_scan->next) {
if (dav_fs_do_refresh(dp_scan, ltl, new_time)) {
/* the lock was refreshed. return the lock. */
newlock = dav_fs_alloc_lock(lockdb, key, dp_scan->locktoken);
newlock->is_locknull = !resource->exists;
newlock->scope = dp_scan->f.scope;
newlock->type = dp_scan->f.type;
newlock->depth = dp_scan->f.depth;
newlock->timeout = dp_scan->f.timeout;
newlock->owner = dp_scan->owner;
newlock->auth_user = dp_scan->auth_user;
newlock->next = *locks;
*locks = newlock;
dirty = 1;
}
}
/* if we refreshed any locks, then save them back. */
if (dirty
&& (err = dav_fs_save_lock_record(lockdb, key, dp, ip)) != NULL) {
/* ### maybe add in a higher-level description */
return err;
}
/* for each indirect lock, find its direct lock and refresh it. */
for (; ip != NULL; ip = ip->next) {
dav_lock_discovery *ref_dp;
dav_lock_indirect *ref_ip;
if ((err = dav_fs_resolve(lockdb, ip, &dp_scan,
&ref_dp, &ref_ip)) != NULL) {
/* ### push a higher-level desc? */
return err;
}
if (dav_fs_do_refresh(dp_scan, ltl, new_time)) {
/* the lock was refreshed. return the lock. */
newlock = dav_fs_alloc_lock(lockdb, ip->key, dp_scan->locktoken);
newlock->is_locknull = !resource->exists;
newlock->scope = dp_scan->f.scope;
newlock->type = dp_scan->f.type;
newlock->depth = dp_scan->f.depth;
newlock->timeout = dp_scan->f.timeout;
newlock->owner = dp_scan->owner;
newlock->auth_user = dp_scan->auth_user;
newlock->next = *locks;
*locks = newlock;
/* save the (resolved) direct lock back */
if ((err = dav_fs_save_lock_record(lockdb, ip->key, ref_dp,
ref_ip)) != NULL) {
/* ### push a higher-level desc? */
return err;
}
}
}
return NULL;
}
const dav_hooks_locks dav_hooks_locks_fs =
{
dav_fs_get_supportedlock,
dav_fs_parse_locktoken,
dav_fs_format_locktoken,
dav_fs_compare_locktoken,
dav_fs_open_lockdb,
dav_fs_close_lockdb,
dav_fs_remove_locknull_state,
dav_fs_create_lock,
dav_fs_get_locks,
dav_fs_find_lock,
dav_fs_has_locks,
dav_fs_append_locks,
dav_fs_remove_lock,
dav_fs_refresh_locks,
NULL, /* lookup_resource */
NULL /* ctx */
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -