⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lock.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* ### 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 + -