📄 lock.c
字号:
int force, dav_lockdb **lockdb){ const char *svn_client_options, *version_name; dav_lockdb *db = apr_pcalloc(r->pool, sizeof(*db)); dav_lockdb_private *info = apr_pcalloc(r->pool, sizeof(*info)); info->r = r; /* Is this an svn client? */ /* Check to see if an svn client sent any custom X-SVN-* headers in the request. */ svn_client_options = apr_table_get(r->headers_in, SVN_DAV_OPTIONS_HEADER); if (svn_client_options) { /* 'svn [lock | unlock] --force' */ if (ap_strstr_c(svn_client_options, SVN_DAV_OPTION_LOCK_BREAK)) info->lock_break = TRUE; if (ap_strstr_c(svn_client_options, SVN_DAV_OPTION_LOCK_STEAL)) info->lock_steal = TRUE; if (ap_strstr_c(svn_client_options, SVN_DAV_OPTION_KEEP_LOCKS)) info->keep_locks = TRUE; } /* 'svn lock' wants to make svn_fs_lock() do an out-of-dateness check. */ version_name = apr_table_get(r->headers_in, SVN_DAV_VERSION_NAME_HEADER); info->working_revnum = version_name ? SVN_STR_TO_REV(version_name): SVN_INVALID_REVNUM; /* The generic lockdb structure. */ db->hooks = &dav_svn_hooks_locks; db->ro = ro; db->info = info; *lockdb = db; return 0;}/* Indicates completion of locking operations */static voiddav_svn_close_lockdb(dav_lockdb *lockdb){ /* nothing to do here. */ return;}/* Take a resource out of the lock-null state. */static dav_error *dav_svn_remove_locknull_state(dav_lockdb *lockdb, const dav_resource *resource){ /* mod_dav_svn supports RFC2518bis which does not actually require the server to create lock-null resources. Instead, we create zero byte files when a lock comes in on a non-existent path. mod_dav_svn never creates any lock-null resources, so this function is never called by mod_dav. */ return 0; /* Just to suppress compiler warnings. */}/*** Create a (direct) lock structure for the given resource. A locktoken** will be created.**** The lock provider may store private information into lock->info.*/static dav_error *dav_svn_create_lock(dav_lockdb *lockdb, const dav_resource *resource, dav_lock **lock){ svn_error_t *serr; dav_locktoken *token = apr_pcalloc(resource->pool, sizeof(*token)); dav_lock *dlock = apr_pcalloc(resource->pool, sizeof(*dlock)); dlock->rectype = DAV_LOCKREC_DIRECT; dlock->is_locknull = resource->exists; dlock->scope = DAV_LOCKSCOPE_UNKNOWN; dlock->type = DAV_LOCKTYPE_UNKNOWN; dlock->depth = 0; serr = svn_fs_generate_lock_token(&(token->uuid_str), resource->info->repos->fs, resource->pool); if (serr) return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to generate a lock token.", resource->pool); dlock->locktoken = token; /* allowing mod_dav to fill in dlock->timeout, owner, auth_user. */ /* dlock->info and dlock->next are NULL by default. */ *lock = dlock; return 0; }/*** Get the locks associated with the specified resource.**** If resolve_locks is true (non-zero), then any indirect locks are** resolved to their actual, direct lock (i.e. the reference to followed** to the original lock).**** The locks, if any, are returned as a linked list in no particular** order. If no locks are present, then *locks will be NULL.**** #define DAV_GETLOCKS_RESOLVED 0 -- resolve indirects to directs ** #define DAV_GETLOCKS_PARTIAL 1 -- leave indirects partially filled ** #define DAV_GETLOCKS_COMPLETE 2 -- fill out indirect locks*/static dav_error *dav_svn_get_locks(dav_lockdb *lockdb, const dav_resource *resource, int calltype, dav_lock **locks){ dav_lockdb_private *info = lockdb->info; svn_error_t *serr; dav_error *derr; svn_lock_t *slock; svn_boolean_t readable = FALSE; dav_lock *lock = NULL; /* We only support exclusive locks, not shared ones. So this function always returns a "list" of exactly one lock, or just a NULL list. The 'calltype' arg is also meaningless, since we don't support locks on collections. */ /* Sanity check: if the resource has no associated path in the fs, then there's nothing to do. */ if (! resource->info->repos_path) { *locks = NULL; return 0; } /* The Big Lie: if the client ran 'svn lock', then we have to pretend that there's no existing lock. Otherwise mod_dav will throw '403 Locked' without even attempting to create a new lock. For the --force case, this is required and for the non-force case, we allow the filesystem to produce a better error for svn clients. */ if (info->r->method_number == M_LOCK) { *locks = NULL; return 0; } /* If the resource's fs path is unreadable, we don't want to say anything about locks attached to it.*/ derr = check_readability(&readable, resource->info->r, resource->info->repos, resource->info->repos_path, resource->pool); if (derr) return derr; if (! readable) return dav_new_error(resource->pool, HTTP_FORBIDDEN, DAV_ERR_LOCK_SAVE_LOCK, "Path is not accessible."); serr = svn_fs_get_lock(&slock, resource->info->repos->fs, resource->info->repos_path, resource->pool); if (serr) return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to check path for a lock.", resource->pool); if (slock != NULL) { svn_lock_to_dav_lock(&lock, slock, info->lock_break, resource->exists, resource->pool); /* Let svn clients know the creationdate of the slock. */ apr_table_setn(info->r->headers_out, SVN_DAV_CREATIONDATE_HEADER, svn_time_to_cstring(slock->creation_date, resource->pool)); /* Let svn clients know who "owns" the slock. */ apr_table_setn(info->r->headers_out, SVN_DAV_LOCK_OWNER_HEADER, slock->owner); } *locks = lock; return 0; }/*** Find a particular lock on a resource (specified by its locktoken).**** *lock will be set to NULL if the lock is not found.**** Note that the provider can optimize the unmarshalling -- only one** lock (or none) must be constructed and returned.**** If partial_ok is true (non-zero), then an indirect lock can be** partially filled in. Otherwise, another lookup is done and the** lock structure will be filled out as a DAV_LOCKREC_INDIRECT.*/static dav_error *dav_svn_find_lock(dav_lockdb *lockdb, const dav_resource *resource, const dav_locktoken *locktoken, int partial_ok, dav_lock **lock){ dav_lockdb_private *info = lockdb->info; svn_error_t *serr; dav_error *derr; svn_lock_t *slock; dav_lock *dlock = NULL; svn_boolean_t readable = FALSE; /* If the resource's fs path is unreadable, we don't want to say anything about locks attached to it.*/ derr = check_readability(&readable, resource->info->r, resource->info->repos, resource->info->repos_path, resource->pool); if (derr) return derr; if (! readable) return dav_new_error(resource->pool, HTTP_FORBIDDEN, DAV_ERR_LOCK_SAVE_LOCK, "Path is not accessible."); serr = svn_fs_get_lock(&slock, resource->info->repos->fs, resource->info->repos_path, resource->pool); if (serr) return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to look up lock by path.", resource->pool); if (slock != NULL) { /* Sanity check. */ if (strcmp(locktoken->uuid_str, slock->token) != 0) return dav_new_error(resource->pool, HTTP_BAD_REQUEST, DAV_ERR_LOCK_SAVE_LOCK, "Incoming token doesn't match existing lock."); svn_lock_to_dav_lock(&dlock, slock, FALSE, resource->exists, resource->pool); /* Let svn clients know the creationdate of the slock. */ apr_table_setn(info->r->headers_out, SVN_DAV_CREATIONDATE_HEADER, svn_time_to_cstring(slock->creation_date, resource->pool)); /* Let svn clients know the 'owner' of the slock. */ apr_table_setn(info->r->headers_out, SVN_DAV_LOCK_OWNER_HEADER, slock->owner); } *lock = dlock; return 0; }/*** Quick test to see if the resource has *any* locks on it.**** This is typically used to determine if a non-existent resource** has a lock and is (therefore) a locknull resource.**** WARNING: this function may return TRUE even when timed-out locks** exist (i.e. it may not perform timeout checks).*/static dav_error *dav_svn_has_locks(dav_lockdb *lockdb, const dav_resource *resource, int *locks_present){ dav_lockdb_private *info = lockdb->info; svn_error_t *serr; dav_error *derr; svn_lock_t *slock; svn_boolean_t readable = FALSE; /* Sanity check: if the resource has no associated path in the fs, then there's nothing to do. */ if (! resource->info->repos_path) { *locks_present = 0; return 0; } /* The Big Lie: if the client ran 'svn lock', then we have to pretend that there's no existing lock. Otherwise mod_dav will throw '403 Locked' without even attempting to create a new lock. For the --force case, this is required and for the non-force case, we allow the filesystem to produce a better error for svn clients. */ if (info->r->method_number == M_LOCK) { *locks_present = 0; return 0; } /* If the resource's fs path is unreadable, we don't want to say anything about locks attached to it.*/ derr = check_readability(&readable, resource->info->r, resource->info->repos, resource->info->repos_path, resource->pool); if (derr) return derr; if (! readable) return dav_new_error(resource->pool, HTTP_FORBIDDEN, DAV_ERR_LOCK_SAVE_LOCK, "Path is not accessible."); serr = svn_fs_get_lock(&slock, resource->info->repos->fs, resource->info->repos_path, resource->pool); if (serr) return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to check path for a lock.", resource->pool); *locks_present = slock ? 1 : 0; return 0;}/*** Append the specified lock(s) to the set of locks on this resource.**** If "make_indirect" is true (non-zero), then the specified lock(s)** should be converted to an indirect lock (if it is a direct lock)** before appending. Note that the conversion to an indirect lock does** not alter the passed-in lock -- the change is internal the** append_locks function.**** Multiple locks are specified using the lock->next links.*/static dav_error *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -