Exemplo n.º 1
0
static svn_error_t *
svn_ra_local__get_lock(svn_ra_session_t *session,
                       svn_lock_t **lock,
                       const char *path,
                       apr_pool_t *pool)
{
  svn_ra_local__session_baton_t *sess = session->priv;
  const char *abs_path = svn_path_join(sess->fs_path->data, path, pool);
  return svn_fs_get_lock(lock, sess->fs, abs_path, pool);
}
Exemplo n.º 2
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 *
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;
  svn_lock_t *slock;
  dav_lock *dlock = NULL;

  /* If the resource's fs path is unreadable, we don't want to say
     anything about locks attached to it.*/
  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
                                     resource->pool))
    return dav_svn__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_svn__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;
}
Exemplo n.º 3
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 *
has_locks(dav_lockdb *lockdb, const dav_resource *resource, int *locks_present)
{
  dav_lockdb_private *info = lockdb->info;
  svn_error_t *serr;
  svn_lock_t *slock;

  /* 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
      && resource->info->repos->is_svn_client)
    {
      *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.*/
  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
                                     resource->pool))
    return dav_svn__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;
}
Exemplo n.º 4
0
/*
** Refresh all locks, found on the specified resource, which has a
** locktoken in the provided list.
**
** If the lock is indirect, then the direct lock is referenced and
** refreshed.
**
** Each lock that is updated is returned in the <locks> argument.
** Note that the locks will be fully resolved.
*/
static dav_error *
refresh_locks(dav_lockdb *lockdb,
              const dav_resource *resource,
              const dav_locktoken_list *ltl,
              time_t new_time,
              dav_lock **locks)
{
  /* We're not looping over a list of locks, since we only support one
     lock per resource. */
  dav_locktoken *token = ltl->locktoken;
  svn_error_t *serr;
  svn_lock_t *slock;
  dav_lock *dlock;

  /* If the resource's fs path is unreadable, we don't want to say
     anything about locks attached to it.*/
  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
                                     resource->pool))
    return dav_svn__new_error(resource->pool, HTTP_FORBIDDEN,
                              DAV_ERR_LOCK_SAVE_LOCK,
                              "Path is not accessible.");

  /* Convert the path into an svn_lock_t. */
  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,
                                "Token doesn't point to a lock.",
                                resource->pool);

  /* Sanity check: does the incoming token actually represent the
     current lock on the incoming resource? */
  if ((! slock)
      || (strcmp(token->uuid_str, slock->token) != 0))
    return dav_svn__new_error(resource->pool, HTTP_UNAUTHORIZED,
                              DAV_ERR_LOCK_SAVE_LOCK,
                              "Lock refresh request doesn't match existing "
                              "lock.");

  /* Now use the tweaked svn_lock_t to 'refresh' the existing lock. */
  serr = svn_repos_fs_lock(&slock,
                           resource->info->repos->repos,
                           slock->path,
                           slock->token,
                           slock->comment,
                           slock->is_dav_comment,
                           (new_time == DAV_TIMEOUT_INFINITE)
                             ? 0 : (apr_time_t)new_time * APR_USEC_PER_SEC,
                           SVN_INVALID_REVNUM,
                           TRUE, /* forcibly steal existing lock */
                           resource->pool);

  if (serr && serr->apr_err == SVN_ERR_FS_NO_USER)
    {
      svn_error_clear(serr);
      return dav_svn__new_error(resource->pool, HTTP_UNAUTHORIZED,
                                DAV_ERR_LOCK_SAVE_LOCK,
                                "Anonymous lock refreshing is not allowed.");
    }
  else if (serr)
    return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                "Failed to refresh existing lock.",
                                resource->pool);

  /* Convert the refreshed lock into a dav_lock and return it. */
  svn_lock_to_dav_lock(&dlock, slock, FALSE, resource->exists, resource->pool);
  *locks = dlock;

  return 0;
}
Exemplo n.º 5
0
/*
** Remove any lock that has the specified locktoken.
**
** If locktoken == NULL, then ALL locks are removed.
*/
static dav_error *
remove_lock(dav_lockdb *lockdb,
            const dav_resource *resource,
            const dav_locktoken *locktoken)
{
  dav_lockdb_private *info = lockdb->info;
  svn_error_t *serr;
  svn_lock_t *slock;
  const char *token = NULL;

  /* Sanity check:  if the resource has no associated path in the fs,
     then there's nothing to do.  */
  if (! resource->info->repos_path)
    return 0;

  /* Another easy out: if an svn client sent a 'keep_locks' header
     (typically in a DELETE request, as part of 'svn commit
     --no-unlock'), then ignore dav_method_delete()'s attempt to
     unconditionally remove the lock.  */
  if (info->keep_locks)
    return 0;

  /* If the resource's fs path is unreadable, we don't allow a lock to
     be removed from it. */
  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
                                     resource->pool))
    return dav_svn__new_error(resource->pool, HTTP_FORBIDDEN,
                              DAV_ERR_LOCK_SAVE_LOCK,
                              "Path is not accessible.");

  if (locktoken == NULL)
    {
      /* Need to manually discover any lock on the resource. */
      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)
        token = slock->token;
    }
  else
    {
      token = locktoken->uuid_str;
    }

  if (token)
    {
      /* Notice that a generic DAV client is unable to forcibly
         'break' a lock, because info->lock_break will always be
         FALSE.  An svn client, however, can request a 'forced' break.*/
      serr = svn_repos_fs_unlock(resource->info->repos->repos,
                                 resource->info->repos_path,
                                 token,
                                 info->lock_break,
                                 resource->pool);

      if (serr && serr->apr_err == SVN_ERR_FS_NO_USER)
        {
          svn_error_clear(serr);
          return dav_svn__new_error(resource->pool, HTTP_UNAUTHORIZED,
                                    DAV_ERR_LOCK_SAVE_LOCK,
                                    "Anonymous lock removal is not allowed.");
        }
      else if (serr)
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "Failed to remove a lock.",
                                    resource->pool);

      /* Log the unlocking as a 'high-level' action. */
      dav_svn__operational_log(resource->info,
                               svn_log__unlock_one_path(
                                   resource->info->repos_path,
                                   info->lock_break,
                                   resource->info->r->pool));
    }

  return 0;
}
Exemplo n.º 6
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 *
get_locks(dav_lockdb *lockdb,
          const dav_resource *resource,
          int calltype,
          dav_lock **locks)
{
  dav_lockdb_private *info = lockdb->info;
  svn_error_t *serr;
  svn_lock_t *slock;
  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.*/
  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
                                     resource->pool))
    return dav_svn__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;
}