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

📄 lock.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * lock.c: mod_dav_svn locking provider functions * * ==================================================================== * Copyright (c) 2000-2006 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <httpd.h>#include <http_log.h>#include <mod_dav.h>#include <apr_uuid.h>#include <apr_time.h>#include "svn_fs.h"#include "svn_repos.h"#include "svn_dav.h"#include "svn_time.h"#include "svn_pools.h"#include "dav_svn.h"struct dav_lockdb_private{  /* These represent 'custom' request hearders only sent by svn clients: */  svn_boolean_t lock_steal;  svn_boolean_t lock_break;  svn_boolean_t keep_locks;  svn_revnum_t working_revnum;  /* The original request, so we can set 'custom' output headers. */  request_rec *r;};/* Helper func:  convert an svn_lock_t to a dav_lock, allocated in   pool.  EXISTS_P indicates whether slock->path actually exists or not.   If HIDE_AUTH_USER is set, then do not return the svn lock's 'owner'   as dlock->auth_user. */static voidsvn_lock_to_dav_lock(dav_lock **dlock,                     const svn_lock_t *slock,                     svn_boolean_t hide_auth_user,                     svn_boolean_t exists_p,                     apr_pool_t *pool){  dav_lock *lock = apr_pcalloc(pool, sizeof(*lock));  dav_locktoken *token = apr_pcalloc(pool, sizeof(*token));  lock->rectype = DAV_LOCKREC_DIRECT;  lock->scope = DAV_LOCKSCOPE_EXCLUSIVE;  lock->type = DAV_LOCKTYPE_WRITE;  lock->depth = 0;  lock->is_locknull = exists_p;  token->uuid_str = apr_pstrdup(pool, slock->token);  lock->locktoken = token;  /* the svn_lock_t 'comment' field maps to the 'DAV:owner' field. */  if (slock->comment)    {      if (! slock->is_dav_comment)        {          /* This comment was originally given to us by an svn client,             so, we need to wrap the naked comment with <DAV:owner>,             and xml-escape it for safe transport, lest we send back             an invalid http response.  (mod_dav won't do it for us,             because it assumes that it personally created every lock             in the repository.) */          lock->owner = apr_pstrcat(pool,                                    "<D:owner xmlns:D=\"DAV:\">",                                    apr_xml_quote_string(pool,                                                         slock->comment, 1),                                    "</D:owner>", NULL);        }      else        {          lock->owner = apr_pstrdup(pool, slock->comment);        }    }  else    lock->owner = NULL;  /* the svn_lock_t 'owner' is the actual authenticated owner of the     lock, and maps to the 'auth_user' field in the mod_dav lock. */  /* (If the client ran 'svn unlock --force', then we don't want to     return lock->auth_user.  Otherwise mod_dav will throw an error     when lock->auth_user and r->user don't match.) */  if (! hide_auth_user)    lock->auth_user = apr_pstrdup(pool, slock->owner);  /* This is absurd.  apr_time.h has an apr_time_t->time_t func,     but not the reverse?? */  if (slock->expiration_date)    lock->timeout = (time_t) (slock->expiration_date / APR_USEC_PER_SEC);  else    lock->timeout = DAV_TIMEOUT_INFINITE;  *dlock = lock;}/* Helper func for dav_lock_to_svn_lock:  take an incoming    "<D:owner>&lt;foo&gt;</D:owner>" tag and convert it to   "<foo>". */static dav_error *unescape_xml(const char **output,             const char *input,             apr_pool_t *pool){  apr_xml_parser *xml_parser = apr_xml_parser_create(pool);  apr_xml_doc *xml_doc;  apr_status_t apr_err;  const char *xml_input = apr_pstrcat     (pool, "<?xml version=\"1.0\" encoding=\"utf-8\"?>", input, NULL);  apr_err = apr_xml_parser_feed(xml_parser, xml_input, strlen(xml_input));  if (!apr_err)    apr_err = apr_xml_parser_done(xml_parser, &xml_doc);  if (apr_err)    {      char errbuf[1024];      (void)apr_xml_parser_geterror(xml_parser, errbuf, sizeof(errbuf));      return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR,                           DAV_ERR_LOCK_SAVE_LOCK, errbuf);    }  apr_xml_to_text(pool, xml_doc->root, APR_XML_X2T_INNER,                  xml_doc->namespaces, NULL, output, NULL);  return SVN_NO_ERROR;}/* Helper func:  convert a dav_lock to an svn_lock_t, allocated in pool. */static dav_error *dav_lock_to_svn_lock(svn_lock_t **slock,                     const dav_lock *dlock,                     const char *path,                     dav_lockdb_private *info,                     svn_boolean_t is_svn_client,                     apr_pool_t *pool){  svn_lock_t *lock;  /* Sanity checks */  if (dlock->type != DAV_LOCKTYPE_WRITE)    return dav_new_error(pool, HTTP_BAD_REQUEST,                         DAV_ERR_LOCK_SAVE_LOCK,                         "Only 'write' locks are supported.");  if (dlock->scope != DAV_LOCKSCOPE_EXCLUSIVE)    return dav_new_error(pool, HTTP_BAD_REQUEST,                         DAV_ERR_LOCK_SAVE_LOCK,                         "Only exclusive locks are supported.");  lock = svn_lock_create(pool);  lock->path = apr_pstrdup(pool, path);  lock->token = apr_pstrdup(pool, dlock->locktoken->uuid_str);  /* DAV has no concept of lock creationdate, so assume 'now' */  lock->creation_date = apr_time_now();  if (dlock->auth_user)    lock->owner = apr_pstrdup(pool, dlock->auth_user);    /* We need to be very careful about stripping the <D:owner> tag away     from the cdata.  It's okay to do for svn clients, but not other     DAV clients! */  if (dlock->owner)    {      if (is_svn_client)        {          /* mod_dav has forcibly xml-escaped the comment before             handing it to us; we need to xml-unescape it (and remove             the <D:owner> wrapper) when storing in the repository, so             it looks reasonable to the rest of svn. */          dav_error *derr;          lock->is_dav_comment = 0;  /* comment is NOT xml-wrapped. */          derr = unescape_xml(&(lock->comment), dlock->owner, pool);          if (derr)            return derr;        }      else        {           /* The comment comes from a non-svn client;  don't touch             this data at all. */          lock->comment = apr_pstrdup(pool, dlock->owner);          lock->is_dav_comment = 1; /* comment IS xml-wrapped. */        }    }  if (dlock->timeout == DAV_TIMEOUT_INFINITE)    lock->expiration_date = 0; /* never expires */  else    lock->expiration_date = ((apr_time_t)dlock->timeout) * APR_USEC_PER_SEC;  *slock = lock;  return 0;}/* Helper func:  invoke mod_dav_svn's authz_read callback on   PATH in HEAD revision, return the readability result in *READABLE. */static dav_error *check_readability(svn_boolean_t *readable,                  request_rec *r,                  const dav_svn_repos *repos,                  const char *path,                  apr_pool_t *pool){  svn_error_t *serr;  svn_fs_root_t *headroot;  svn_revnum_t headrev;  dav_svn_authz_read_baton arb;  arb.r = r;  arb.repos = repos;  serr = svn_fs_youngest_rev(&headrev, repos->fs, pool);  if (serr)    return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,                               "Failed to get youngest filesystem revision.",                               pool);  serr = svn_fs_revision_root(&headroot, repos->fs, headrev, pool);  if (serr)    return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,                               "Failed to open revision root for HEAD.",                               pool);  serr = dav_svn_authz_read(readable, headroot, path, &arb, pool);  if (serr)    return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,                               "Failed to check readability of a path.",                               pool);  return 0;}/* ---------------------------------------------------------------- *//* mod_dav locking vtable starts here: *//* Return the supportedlock property for a resource */static const char *dav_svn_get_supportedlock(const dav_resource *resource){  /* This is imitating what mod_dav_fs is doing.  Note that unlike     mod_dav_fs, however, we don't support "shared" locks, only     "exclusive" ones.  Nor do we support locks on collections. */  static const char supported[] = DEBUG_CR    "<D:lockentry>" DEBUG_CR    "<D:lockscope><D:exclusive/></D:lockscope>" DEBUG_CR    "<D:locktype><D:write/></D:locktype>" DEBUG_CR    "</D:lockentry>" DEBUG_CR;  if (resource->collection)    return NULL;  else    return supported;}/* Parse a lock token URI, returning a lock token object allocated * in the given pool. */static dav_error *dav_svn_parse_locktoken(apr_pool_t *pool,                        const char *char_token,                        dav_locktoken **locktoken_p){  dav_locktoken *token = apr_pcalloc(pool, sizeof(*token));  /* libsvn_fs already produces a valid locktoken URI. */  token->uuid_str = apr_pstrdup(pool, char_token);    *locktoken_p = token;  return 0;}/* Format a lock token object into a URI string, allocated in * the given pool. * * Always returns non-NULL. */static const char *dav_svn_format_locktoken(apr_pool_t *p,                         const dav_locktoken *locktoken){  /* libsvn_fs already produces a valid locktoken URI. */  return apr_pstrdup(p, locktoken->uuid_str);}/* Compare two lock tokens. * * Result < 0  => lt1 < lt2 * Result == 0 => lt1 == lt2 * Result > 0  => lt1 > lt2 */static intdav_svn_compare_locktoken(const dav_locktoken *lt1,                          const dav_locktoken *lt2){  return strcmp(lt1->uuid_str, lt2->uuid_str);}/* Open the provider's lock database. * * The provider may or may not use a "real" database for locks * (a lock could be an attribute on a resource, for example). * * The provider may choose to use the value of the DAVLockDB directive * (as returned by dav_get_lockdb_path()) to decide where to place * any storage it may need. * * The request storage pool should be associated with the lockdb, * so it can be used in subsequent operations. * * If ro != 0, only readonly operations will be performed. * If force == 0, the open can be "lazy"; no subsequent locking operations * may occur. * If force != 0, locking operations will definitely occur. */static dav_error *dav_svn_open_lockdb(request_rec *r,                    int ro,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -