コード例 #1
0
ファイル: dump.c プロジェクト: mommel/alien-svn
static svn_error_t *
verify_directory_entry(void *baton, const void *key, apr_ssize_t klen,
                       void *val, apr_pool_t *pool)
{
  struct dir_baton *db = baton;
  char *path = svn_relpath_join(db->path, (const char *)key, pool);
  svn_node_kind_t kind;
  apr_hash_t *dirents;
  svn_filesize_t len;

  SVN_ERR(svn_fs_check_path(&kind, db->edit_baton->fs_root, path, pool));
  switch (kind) {
  case svn_node_dir:
    /* Getting this directory's contents is enough to ensure that our
       link to it is correct. */
    SVN_ERR(svn_fs_dir_entries(&dirents, db->edit_baton->fs_root, path, pool));
    break;
  case svn_node_file:
    /* Getting this file's size is enough to ensure that our link to it
       is correct. */
    SVN_ERR(svn_fs_file_length(&len, db->edit_baton->fs_root, path, pool));
    break;
  default:
    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                             _("Unexpected node kind %d for '%s'"), kind, path);
  }

  return SVN_NO_ERROR;
}
コード例 #2
0
ファイル: commit.c プロジェクト: DJEX93/dsploit
static svn_error_t *
open_directory(const char *path,
               void *parent_baton,
               svn_revnum_t base_revision,
               apr_pool_t *pool,
               void **child_baton)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  svn_node_kind_t kind;
  const char *full_path;

  full_path = svn_fspath__join(eb->base_path,
                               svn_relpath_canonicalize(path, pool), pool);

  /* Check PATH in our transaction.  If it does not exist,
     return a 'Path not present' error. */
  SVN_ERR(svn_fs_check_path(&kind, eb->txn_root, full_path, pool));
  if (kind == svn_node_none)
    return svn_error_createf(SVN_ERR_FS_NOT_DIRECTORY, NULL,
                             _("Path '%s' not present"),
                             path);

  /* Build a new dir baton for this directory. */
  *child_baton = make_dir_baton(eb, pb, full_path, pb->was_copied,
                                base_revision, pool);
  return SVN_NO_ERROR;
}
コード例 #3
0
ファイル: node_tree.c プロジェクト: vocho/openqnx
static svn_error_t *
delete_entry(const char *path,
             svn_revnum_t revision,
             void *parent_baton,
             apr_pool_t *pool)
{
  struct node_baton *d = parent_baton;
  struct edit_baton *eb = d->edit_baton;
  svn_repos_node_t *node;
  const char *name;
  const char *base_path;
  svn_revnum_t base_rev;
  svn_fs_root_t *base_root;
  svn_node_kind_t kind;

  /* Get (or create) the change node and update it. */
  name = svn_path_basename(path, pool);
  node = find_child_by_name(d->node, name);
  if (! node)
    node = create_child_node(d->node, name, eb->node_pool);
  node->action = 'D';

  /* We need to look up this node's parents to see what its original
     path in the filesystem was.  Why?  Because if this deletion
     occurred underneath a copied path, the thing that was deleted
     probably lived at a different location (relative to the copy
     source). */
  find_real_base_location(&base_path, &base_rev, node, pool);
  if (! SVN_IS_VALID_REVNUM(base_rev))
    {
      /* No interesting base revision?  We'll just look for the path
         in our base root.  */
      base_root = eb->base_root;
    }
  else
    {
      /* Oh.  Perhaps some copy goodness happened somewhere? */
      SVN_ERR(svn_fs_revision_root(&base_root, eb->fs, base_rev, pool));
    }

  /* Now figure out if this thing was a file or a dir. */
  SVN_ERR(svn_fs_check_path(&kind, base_root, base_path, pool));
  if (kind == svn_node_none)
    return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
                             _("'%s' not found in filesystem"), path);
  node->kind = kind;

  return SVN_NO_ERROR;
}
コード例 #4
0
ファイル: svnauthz.c プロジェクト: lysine/wasp
/* Loads the fs FILENAME contents into *CONTENTS ensuring that the
   corresponding node is a file. Using POOL for allocations. */
static svn_error_t *
read_file_contents(svn_stream_t **contents, const char *filename,
                   svn_fs_root_t *root, apr_pool_t *pool)
{
  svn_node_kind_t node_kind;

  /* Make sure the path is a file */
  SVN_ERR(svn_fs_check_path(&node_kind, root, filename, pool));
  if (node_kind != svn_node_file)
    return svn_error_createf(SVN_ERR_FS_NOT_FILE, NULL,
                             "Path '%s' is not a file", filename);

  SVN_ERR(svn_fs_file_contents(contents, root, filename, pool));

  return SVN_NO_ERROR;
}
コード例 #5
0
ファイル: ra_plugin.c プロジェクト: aosm/subversion
static svn_error_t *
svn_ra_local__do_check_path(svn_ra_session_t *session,
                            const char *path,
                            svn_revnum_t revision,
                            svn_node_kind_t *kind,
                            apr_pool_t *pool)
{
  svn_ra_local__session_baton_t *sess = session->priv;
  svn_fs_root_t *root;
  const char *abs_path = svn_path_join(sess->fs_path->data, path, pool);

  if (! SVN_IS_VALID_REVNUM(revision))
    SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
  SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, pool));
  return svn_fs_check_path(kind, root, abs_path, pool);
}
コード例 #6
0
ファイル: editor.c プロジェクト: Ranga123/test1
/* Can we create a node at FSPATH in TXN_ROOT? If something already exists
   at that path, then the client MAY be out of date. We then have to see if
   the path was created/modified in this transaction. IOW, it is new and
   can be replaced without problem.

   Note: the editor protocol disallows double-modifications. This is to
   ensure somebody does not accidentally overwrite another file due to
   being out-of-date.  */
static svn_error_t *
can_create(svn_fs_root_t *txn_root,
           const char *fspath,
           apr_pool_t *scratch_pool)
{
    svn_node_kind_t kind;
    const char *cur_fspath;

    SVN_ERR(svn_fs_check_path(&kind, txn_root, fspath, scratch_pool));
    if (kind == svn_node_none)
        return SVN_NO_ERROR;

    /* ### I'm not sure if this works perfectly. We might have an ancestor
       ### that was modified as a result of a change on a cousin. We might
       ### misinterpret that as a *-here node which brought along this
       ### child. Need to write a test to verify. We may also be able to
       ### test the ancestor to determine if it has been *-here in this
       ### txn, or just a simple modification.  */

    /* Are any of the parents copied/moved/rotated-here?  */
    for (cur_fspath = fspath;
            strlen(cur_fspath) > 1;  /* not the root  */
            cur_fspath = svn_fspath__dirname(cur_fspath, scratch_pool))
    {
        svn_revnum_t created_rev;

        SVN_ERR(svn_fs_node_created_rev(&created_rev, txn_root, cur_fspath,
                                        scratch_pool));
        if (!SVN_IS_VALID_REVNUM(created_rev))
        {
            /* The node has no created revision, meaning it is uncommitted.
               Thus, it was created in this transaction, or it has already
               been modified in some way (implying it has already passed a
               modification check.  */
            /* ### verify the node has been *-here ??  */
            return SVN_NO_ERROR;
        }
    }

    return svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, NULL,
                             _("'%s' already exists, so may be out"
                               " of date; try updating"),
                             fspath);
}
コード例 #7
0
ファイル: commit.c プロジェクト: DJEX93/dsploit
static svn_error_t *
delete_entry(const char *path,
             svn_revnum_t revision,
             void *parent_baton,
             apr_pool_t *pool)
{
  struct dir_baton *parent = parent_baton;
  struct edit_baton *eb = parent->edit_baton;
  svn_node_kind_t kind;
  svn_revnum_t cr_rev;
  svn_repos_authz_access_t required = svn_authz_write;
  const char *full_path;

  full_path = svn_fspath__join(eb->base_path,
                               svn_relpath_canonicalize(path, pool), pool);

  /* Check PATH in our transaction.  */
  SVN_ERR(svn_fs_check_path(&kind, eb->txn_root, full_path, pool));

  /* Deletion requires a recursive write access, as well as write
     access to the parent directory. */
  if (kind == svn_node_dir)
    required |= svn_authz_recursive;
  SVN_ERR(check_authz(eb, full_path, eb->txn_root,
                      required, pool));
  SVN_ERR(check_authz(eb, parent->path, eb->txn_root,
                      svn_authz_write, pool));

  /* If PATH doesn't exist in the txn, the working copy is out of date. */
  if (kind == svn_node_none)
    return out_of_date(full_path, kind);

  /* Now, make sure we're deleting the node we *think* we're
     deleting, else return an out-of-dateness error. */
  SVN_ERR(svn_fs_node_created_rev(&cr_rev, eb->txn_root, full_path, pool));
  if (SVN_IS_VALID_REVNUM(revision) && (revision < cr_rev))
    return out_of_date(full_path, kind);

  /* This routine is a mindless wrapper.  We call svn_fs_delete()
     because that will delete files and recursively delete
     directories.  */
  return svn_fs_delete(eb->txn_root, full_path, pool);
}
コード例 #8
0
ファイル: commit.c プロジェクト: 2asoft/freebsd
static svn_error_t *
fetch_kind_func(svn_node_kind_t *kind,
                void *baton,
                const char *path,
                svn_revnum_t base_revision,
                apr_pool_t *scratch_pool)
{
  struct edit_baton *eb = baton;
  svn_fs_root_t *fs_root;

  if (!SVN_IS_VALID_REVNUM(base_revision))
    base_revision = svn_fs_txn_base_revision(eb->txn);

  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));

  SVN_ERR(svn_fs_check_path(kind, fs_root, path, scratch_pool));

  return SVN_NO_ERROR;
}
コード例 #9
0
ファイル: merge.c プロジェクト: matthewdpklanier/alien-svn
static svn_error_t *
do_resources(const dav_svn_repos *repos,
             svn_fs_root_t *root,
             svn_revnum_t revision,
             ap_filter_t *output,
             apr_bucket_brigade *bb,
             apr_pool_t *pool)
{
  apr_hash_t *changes;
  apr_hash_t *sent = apr_hash_make(pool);
  apr_hash_index_t *hi;
  apr_pool_t *subpool = svn_pool_create(pool);

  /* Fetch the paths changed in this revision.  This will contain
     everything except otherwise-unchanged parent directories of added
     and deleted things.  Also, note that deleted things don't merit
     responses of their own -- they are considered modifications to
     their parent.  */
  SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));

  for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      const char *path;
      svn_fs_path_change2_t *change;
      svn_boolean_t send_self;
      svn_boolean_t send_parent;

      svn_pool_clear(subpool);
      apr_hash_this(hi, &key, NULL, &val);
      path = key;
      change = val;

      /* Figure out who needs to get sent. */
      switch (change->change_kind)
        {
        case svn_fs_path_change_delete:
          send_self = FALSE;
          send_parent = TRUE;
          break;

        case svn_fs_path_change_add:
        case svn_fs_path_change_replace:
          send_self = TRUE;
          send_parent = TRUE;
          break;

        case svn_fs_path_change_modify:
        default:
          send_self = TRUE;
          send_parent = FALSE;
          break;
        }

      if (send_self)
        {
          /* If we haven't already sent this path, send it (and then
             remember that we sent it). */
          if (! apr_hash_get(sent, path, APR_HASH_KEY_STRING))
            {
              svn_node_kind_t kind;
              SVN_ERR(svn_fs_check_path(&kind, root, path, subpool));
              SVN_ERR(send_response(repos, root, path,
                                    kind == svn_node_dir,
                                    output, bb, subpool));
              apr_hash_set(sent, path, APR_HASH_KEY_STRING, (void *)1);
            }
        }
      if (send_parent)
        {
          /* If it hasn't already been sent, send the parent directory
             (and then remember that you sent it).  Allocate parent in
             pool, not subpool, because it stays in the sent hash
             afterwards. */
          const char *parent = svn_path_dirname(path, pool);
          if (! apr_hash_get(sent, parent, APR_HASH_KEY_STRING))
            {
              SVN_ERR(send_response(repos, root, parent,
                                    TRUE, output, bb, subpool));
              apr_hash_set(sent, parent, APR_HASH_KEY_STRING, (void *)1);
            }
        }
    }

  svn_pool_destroy(subpool);

  return SVN_NO_ERROR;
}
コード例 #10
0
ファイル: deadprops.c プロジェクト: DJEX93/dsploit
static dav_error *
db_first_name(dav_db *db, dav_prop_name *pname)
{
  /* for operational logging */
  const char *action = NULL;

  /* if we don't have a copy of the properties, then get one */
  if (db->props == NULL)
    {
      svn_error_t *serr;

      /* Working Baseline, Baseline, or (Working) Version resource */
      if (db->resource->baselined)
        {
          if (db->resource->type == DAV_RESOURCE_TYPE_WORKING)
            serr = svn_fs_txn_proplist(&db->props,
                                       db->resource->info->root.txn,
                                       db->p);
          else
            {
              action = svn_log__rev_proplist(db->resource->info->root.rev,
                                             db->resource->pool);
              serr = svn_repos_fs_revision_proplist
                (&db->props,
                 db->resource->info->repos->repos,
                 db->resource->info->root.rev,
                 db->authz_read_func,
                 db->authz_read_baton,
                 db->p);
            }
        }
      else
        {
          svn_node_kind_t kind;
          serr = svn_fs_node_proplist(&db->props,
                                      db->resource->info->root.root,
                                      get_repos_path(db->resource->info),
                                      db->p);
          if (! serr)
            serr = svn_fs_check_path(&kind, db->resource->info->root.root,
                                     get_repos_path(db->resource->info),
                                     db->p);

          if (! serr)
            {
              if (kind == svn_node_dir)
                action = svn_log__get_dir(db->resource->info->repos_path,
                                          db->resource->info->root.rev,
                                          FALSE, TRUE, 0, db->resource->pool);
              else
                action = svn_log__get_file(db->resource->info->repos_path,
                                           db->resource->info->root.rev,
                                           FALSE, TRUE, db->resource->pool);
            }
        }
      if (serr != NULL)
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "could not begin sequencing through "
                                    "properties",
                                    db->resource->pool);
    }

  /* begin the iteration over the hash */
  db->hi = apr_hash_first(db->p, db->props);

  /* fetch the first key */
  get_name(db, pname);

  /* If we have a high-level action to log, do so. */
  if (action != NULL)
    dav_svn__operational_log(db->resource->info, action);

  return NULL;
}
コード例 #11
0
ファイル: commit.c プロジェクト: DJEX93/dsploit
/* This function is the shared guts of add_file() and add_directory(),
   which see for the meanings of the parameters.  The only extra
   parameter here is IS_DIR, which is TRUE when adding a directory,
   and FALSE when adding a file.  */
static svn_error_t *
add_file_or_directory(const char *path,
                      void *parent_baton,
                      const char *copy_path,
                      svn_revnum_t copy_revision,
                      svn_boolean_t is_dir,
                      apr_pool_t *pool,
                      void **return_baton)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  apr_pool_t *subpool = svn_pool_create(pool);
  svn_boolean_t was_copied = FALSE;
  const char *full_path;

  full_path = svn_fspath__join(eb->base_path,
                               svn_relpath_canonicalize(path, pool), pool);

  /* Sanity check. */
  if (copy_path && (! SVN_IS_VALID_REVNUM(copy_revision)))
    return svn_error_createf
      (SVN_ERR_FS_GENERAL, NULL,
       _("Got source path but no source revision for '%s'"), full_path);

  if (copy_path)
    {
      const char *fs_path;
      svn_fs_root_t *copy_root;
      svn_node_kind_t kind;
      size_t repos_url_len;
      svn_repos_authz_access_t required;

      /* Copy requires recursive write access to the destination path
         and write access to the parent path. */
      required = svn_authz_write | (is_dir ? svn_authz_recursive : 0);
      SVN_ERR(check_authz(eb, full_path, eb->txn_root,
                          required, subpool));
      SVN_ERR(check_authz(eb, pb->path, eb->txn_root,
                          svn_authz_write, subpool));

      /* Check PATH in our transaction.  Make sure it does not exist
         unless its parent directory was copied (in which case, the
         thing might have been copied in as well), else return an
         out-of-dateness error. */
      SVN_ERR(svn_fs_check_path(&kind, eb->txn_root, full_path, subpool));
      if ((kind != svn_node_none) && (! pb->was_copied))
        return out_of_date(full_path, kind);

      /* For now, require that the url come from the same repository
         that this commit is operating on. */
      copy_path = svn_path_uri_decode(copy_path, subpool);
      repos_url_len = strlen(eb->repos_url);
      if (strncmp(copy_path, eb->repos_url, repos_url_len) != 0)
        return svn_error_createf
          (SVN_ERR_FS_GENERAL, NULL,
           _("Source url '%s' is from different repository"), copy_path);

      fs_path = apr_pstrdup(subpool, copy_path + repos_url_len);

      /* Now use the "fs_path" as an absolute path within the
         repository to make the copy from. */
      SVN_ERR(svn_fs_revision_root(&copy_root, eb->fs,
                                   copy_revision, subpool));

      /* Copy also requires (recursive) read access to the source */
      required = svn_authz_read | (is_dir ? svn_authz_recursive : 0);
      SVN_ERR(check_authz(eb, fs_path, copy_root, required, subpool));

      SVN_ERR(svn_fs_copy(copy_root, fs_path,
                          eb->txn_root, full_path, subpool));
      was_copied = TRUE;
    }
  else
    {
      /* No ancestry given, just make a new directory or empty file.
         Note that we don't perform an existence check here like the
         copy-from case does -- that's because svn_fs_make_*()
         already errors out if the file already exists.  Verify write
         access to the full path and to the parent. */
      SVN_ERR(check_authz(eb, full_path, eb->txn_root,
                          svn_authz_write, subpool));
      SVN_ERR(check_authz(eb, pb->path, eb->txn_root,
                          svn_authz_write, subpool));
      if (is_dir)
        SVN_ERR(svn_fs_make_dir(eb->txn_root, full_path, subpool));
      else
        SVN_ERR(svn_fs_make_file(eb->txn_root, full_path, subpool));
    }

  /* Cleanup our temporary subpool. */
  svn_pool_destroy(subpool);

  /* Build a new child baton. */
  if (is_dir)
    {
      *return_baton = make_dir_baton(eb, pb, full_path, was_copied,
                                     SVN_INVALID_REVNUM, pool);
    }
  else
    {
      struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb));
      new_fb->edit_baton = eb;
      new_fb->path = full_path;
      *return_baton = new_fb;
    }

  return SVN_NO_ERROR;
}
コード例 #12
0
static svn_error_t *
path_driver_cb_func(void **dir_baton,
                    void *parent_baton,
                    void *callback_baton,
                    const char *edit_path,
                    apr_pool_t *pool)
{
  struct path_driver_cb_baton *cb = callback_baton;
  const svn_delta_editor_t *editor = cb->editor;
  void *edit_baton = cb->edit_baton;
  svn_fs_root_t *root = cb->root;
  svn_fs_path_change2_t *change;
  svn_boolean_t do_add = FALSE, do_delete = FALSE;
  void *file_baton = NULL;
  svn_revnum_t copyfrom_rev;
  const char *copyfrom_path;
  svn_boolean_t src_readable = TRUE;
  svn_fs_root_t *source_root = cb->compare_root;
  const char *source_fspath = NULL;
  const char *base_path = cb->base_path;
  size_t base_path_len = cb->base_path_len;

  *dir_baton = NULL;

  /* Initialize SOURCE_FSPATH. */
  if (source_root)
    source_fspath = svn_fspath__canonicalize(edit_path, pool);

  /* First, flush the copies stack so it only contains ancestors of path. */
  while (cb->copies->nelts > 0
         && ! svn_dirent_is_ancestor(APR_ARRAY_IDX(cb->copies,
                                                   cb->copies->nelts - 1,
                                                   struct copy_info).path,
                                     edit_path))
    cb->copies->nelts--;

  change = apr_hash_get(cb->changed_paths, edit_path, APR_HASH_KEY_STRING);
  if (! change)
    {
      /* This can only happen if the path was removed from cb->changed_paths
         by an earlier call to add_subdir, which means the path was already
         handled and we should simply ignore it. */
      return SVN_NO_ERROR;
    }
  switch (change->change_kind)
    {
    case svn_fs_path_change_add:
      do_add = TRUE;
      break;

    case svn_fs_path_change_delete:
      do_delete = TRUE;
      break;

    case svn_fs_path_change_replace:
      do_add = TRUE;
      do_delete = TRUE;
      break;

    case svn_fs_path_change_modify:
    default:
      /* do nothing */
      break;
    }

  /* Handle any deletions. */
  if (do_delete)
    SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
                                 parent_baton, pool));

  /* Fetch the node kind if it makes sense to do so. */
  if (! do_delete || do_add)
    {
      if (change->node_kind == svn_node_unknown)
        SVN_ERR(svn_fs_check_path(&(change->node_kind), root, edit_path, pool));
      if ((change->node_kind != svn_node_dir) &&
          (change->node_kind != svn_node_file))
        return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
                                 _("Filesystem path '%s' is neither a file "
                                   "nor a directory"), edit_path);
    }

  /* Handle any adds/opens. */
  if (do_add)
    {
      svn_fs_root_t *copyfrom_root = NULL;
      /* Was this node copied? */
      if (! change->copyfrom_known)
        {
          SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
                                     &(change->copyfrom_path),
                                     root, edit_path, pool));
          change->copyfrom_known = TRUE;
        }
      copyfrom_rev = change->copyfrom_rev;
      copyfrom_path = change->copyfrom_path;

      if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev))
        {
          SVN_ERR(svn_fs_revision_root(&copyfrom_root,
                                       svn_fs_root_fs(root),
                                       copyfrom_rev, pool));

          if (cb->authz_read_func)
            {
              SVN_ERR(cb->authz_read_func(&src_readable, copyfrom_root,
                                          copyfrom_path,
                                          cb->authz_read_baton, pool));
            }
        }

      /* If we have a copyfrom path, and we can't read it or we're just
         ignoring it, or the copyfrom rev is prior to the low water mark
         then we just null them out and do a raw add with no history at
         all. */
      if (copyfrom_path
          && ((! src_readable)
              || (! is_within_base_path(copyfrom_path + 1, base_path,
                                        base_path_len))
              || (cb->low_water_mark > copyfrom_rev)))
        {
          copyfrom_path = NULL;
          copyfrom_rev = SVN_INVALID_REVNUM;
        }

      /* Do the right thing based on the path KIND. */
      if (change->node_kind == svn_node_dir)
        {
          /* If this is a copy, but we can't represent it as such,
             then we just do a recursive add of the source path
             contents. */
          if (change->copyfrom_path && ! copyfrom_path)
            {
              SVN_ERR(add_subdir(copyfrom_root, root, editor, edit_baton,
                                 edit_path, parent_baton, change->copyfrom_path,
                                 cb->authz_read_func, cb->authz_read_baton,
                                 cb->changed_paths, pool, dir_baton));
            }
          else
            {
              SVN_ERR(editor->add_directory(edit_path, parent_baton,
                                            copyfrom_path, copyfrom_rev,
                                            pool, dir_baton));
            }
        }
      else
        {
          SVN_ERR(editor->add_file(edit_path, parent_baton, copyfrom_path,
                                   copyfrom_rev, pool, &file_baton));
        }

      /* If we represent this as a copy... */
      if (copyfrom_path)
        {
          /* If it is a directory, make sure descendants get the correct
             delta source by remembering that we are operating inside a
             (possibly nested) copy operation. */
          if (change->node_kind == svn_node_dir)
            {
              struct copy_info *info = &APR_ARRAY_PUSH(cb->copies,
                                                       struct copy_info);
              info->path = apr_pstrdup(cb->pool, edit_path);
              info->copyfrom_path = apr_pstrdup(cb->pool, copyfrom_path);
              info->copyfrom_rev = copyfrom_rev;
            }

          /* Save the source so that we can use it later, when we
             need to generate text and prop deltas. */
          source_root = copyfrom_root;
          source_fspath = copyfrom_path;
        }
      else
        /* Else, we are an add without history... */
        {
          /* If an ancestor is added with history, we need to forget about
             that here, go on with life and repeat all the mistakes of our
             past... */
          if (change->node_kind == svn_node_dir && cb->copies->nelts > 0)
            {
              struct copy_info *info = &APR_ARRAY_PUSH(cb->copies,
                                                       struct copy_info);
              info->path = apr_pstrdup(cb->pool, edit_path);
              info->copyfrom_path = NULL;
              info->copyfrom_rev = SVN_INVALID_REVNUM;
            }
          source_root = NULL;
          source_fspath = NULL;
        }
    }
コード例 #13
0
ファイル: authz.c プロジェクト: 2asoft/freebsd
/* Retrieve the file at DIRENT (contained in a repo) then parse it as a config
 * file placing the result into CFG_P allocated in POOL.
 *
 * If DIRENT cannot be parsed as a config file then an error is returned.  The
 * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
 * authz file is also an error.  The CASE_SENSITIVE controls the lookup
 * behavior for section and option names alike.
 *
 * SCRATCH_POOL will be used for temporary allocations. */
static svn_error_t *
authz_retrieve_config_repo(svn_config_t **cfg_p,
                           const char *dirent,
                           svn_boolean_t must_exist,
                           svn_boolean_t case_sensitive,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
{
  svn_error_t *err;
  svn_repos_t *repos;
  const char *repos_root_dirent;
  const char *fs_path;
  svn_fs_t *fs;
  svn_fs_root_t *root;
  svn_revnum_t youngest_rev;
  svn_node_kind_t node_kind;
  svn_stream_t *contents;

  /* Search for a repository in the full path. */
  repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
  if (!repos_root_dirent)
    return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_NOT_FOUND, NULL,
                             "Unable to find repository at '%s'", dirent);

  /* Attempt to open a repository at repos_root_dirent. */
  SVN_ERR(svn_repos_open3(&repos, repos_root_dirent, NULL, scratch_pool,
                          scratch_pool));

  fs_path = &dirent[strlen(repos_root_dirent)];

  /* Root path is always a directory so no reason to go any further */
  if (*fs_path == '\0')
    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                             "'/' is not a file in repo '%s'",
                             repos_root_dirent);

  /* We skip some things that are non-important for how we're going to use
   * this repo connection.  We do not set any capabilities since none of
   * the current ones are important for what we're doing.  We also do not
   * setup the environment that repos hooks would run under since we won't
   * be triggering any. */

  /* Get the filesystem. */
  fs = svn_repos_fs(repos);

  /* Find HEAD and the revision root */
  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool));
  SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, scratch_pool));

  SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool));
  if (node_kind == svn_node_none)
    {
      if (!must_exist)
        {
          SVN_ERR(svn_config_create2(cfg_p, case_sensitive, case_sensitive,
                                     result_pool));
          return SVN_NO_ERROR;
        }
      else
        {
          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                   "'%s' path not found in repo '%s'", fs_path,
                                   repos_root_dirent);
        }
    }
  else if (node_kind != svn_node_file)
    {
      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                               "'%s' is not a file in repo '%s'", fs_path,
                               repos_root_dirent);
    }

  SVN_ERR(svn_fs_file_contents(&contents, root, fs_path, scratch_pool));
  err = svn_config_parse(cfg_p, contents, case_sensitive, case_sensitive,
                         result_pool);

  /* Add the URL to the error stack since the parser doesn't have it. */
  if (err != SVN_NO_ERROR)
    return svn_error_createf(err->apr_err, err,
                             "Error while parsing config file: '%s' in repo '%s':",
                             fs_path, repos_root_dirent);

  return SVN_NO_ERROR;
}
コード例 #14
0
ファイル: liveprops.c プロジェクト: Distrotech/subversion
static dav_prop_insert
insert_prop_internal(const dav_resource *resource,
                     int propid,
                     dav_prop_insert what,
                     apr_text_header *phdr,
                     apr_pool_t *scratch_pool,
                     apr_pool_t *result_pool)
{
  const char *value = NULL;
  const char *s;
  const dav_liveprop_spec *info;
  int global_ns;
  svn_error_t *serr;

  /*
  ** Almost none of the SVN provider properties are defined if the
  ** resource does not exist.  We do need to return the one VCC
  ** property and baseline-relative-path on lock-null resources,
  ** however, so that svn clients can run 'svn unlock' and 'svn info'
  ** on these things.
  **
  ** Even though we state that the SVN properties are not defined, the
  ** client cannot store dead values -- we deny that thru the is_writable
  ** hook function.
  */
  if ((! resource->exists)
      && (propid != DAV_PROPID_version_controlled_configuration)
      && (propid != SVN_PROPID_baseline_relative_path))
    return DAV_PROP_INSERT_NOTSUPP;

  /* ### we may want to respond to DAV_PROPID_resourcetype for PRIVATE
     ### resources. need to think on "proper" interaction with mod_dav */

  switch (propid)
    {
    case DAV_PROPID_getlastmodified:
    case DAV_PROPID_creationdate:
      {
        /* In subversion terms, the date attached to a file's CR is
           the true "last modified" time.  However, we're defining
           creationdate in the same way.  IMO, the "creationdate" is
           really the date attached to the revision in which the item
           *first* came into existence; this would found by tracing
           back through the log of the file -- probably via
           svn_fs_revisions_changed.  gstein, is it a bad thing that
           we're currently using 'creationdate' to mean the same thing
           as 'last modified date'?  */
        const char *datestring;
        apr_time_t timeval;
        enum time_format format;

        /* ### for now, our global VCC has no such property. */
        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && (resource->info->restype == DAV_SVN_RESTYPE_VCC
                || resource->info->restype == DAV_SVN_RESTYPE_ME))
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (propid == DAV_PROPID_creationdate)
          {
            /* Return an ISO8601 date; this is what the svn client
               expects, and rfc2518 demands it. */
            format = time_format_iso8601;
          }
        else /* propid == DAV_PROPID_getlastmodified */
          {
            format = time_format_rfc1123;
          }

        if (0 != get_last_modified_time(&datestring, &timeval,
                                        resource, format, scratch_pool))
          {
            return DAV_PROP_INSERT_NOTDEF;
          }

        value = apr_xml_quote_string(scratch_pool, datestring, 1);
        break;
      }

    case DAV_PROPID_creator_displayname:
      {
        svn_revnum_t committed_rev = SVN_INVALID_REVNUM;
        svn_string_t *last_author = NULL;

        /* ### for now, our global VCC has no such property. */
        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && (resource->info->restype == DAV_SVN_RESTYPE_VCC
                || resource->info->restype == DAV_SVN_RESTYPE_ME))
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (resource->baselined && resource->type == DAV_RESOURCE_TYPE_VERSION)
          {
            /* A baseline URI. */
            committed_rev = resource->info->root.rev;
          }
        else if (resource->type == DAV_RESOURCE_TYPE_REGULAR
                 || resource->type == DAV_RESOURCE_TYPE_WORKING
                 || resource->type == DAV_RESOURCE_TYPE_VERSION)
          {
            /* Get the CR field out of the node's skel.  Notice that the
               root object might be an ID root -or- a revision root. */
            serr = svn_fs_node_created_rev(&committed_rev,
                                           resource->info->root.root,
                                           resource->info->repos_path,
                                           scratch_pool);
            if (serr != NULL)
              {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                              resource->info->r,
                              "Can't get created-rev of '%s': "
                              "%s",
                              resource->info->repos_path,
                              serr->message);
                svn_error_clear(serr);
                value = "###error###";
                break;
              }
          }
        else
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        serr = get_path_revprop(&last_author,
                                resource,
                                committed_rev,
                                SVN_PROP_REVISION_AUTHOR,
                                scratch_pool);
        if (serr)
          {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                          resource->info->r,
                          "Can't get author of r%ld: "
                          "%s",
                          committed_rev,
                          serr->message);
            svn_error_clear(serr);
            value = "###error###";
            break;
          }

        if (last_author == NULL)
          return DAV_PROP_INSERT_NOTDEF;

        value = apr_xml_quote_string(scratch_pool, last_author->data, 1);
        break;
      }

    case DAV_PROPID_getcontentlanguage:
      /* ### need something here */
      return DAV_PROP_INSERT_NOTSUPP;
      break;

    case DAV_PROPID_getcontentlength:
      {
        svn_filesize_t len = 0;

        /* our property, but not defined on collection resources */
        if (resource->collection || resource->baselined)
          return DAV_PROP_INSERT_NOTSUPP;

        serr = svn_fs_file_length(&len, resource->info->root.root,
                                  resource->info->repos_path, scratch_pool);
        if (serr != NULL)
          {
            svn_error_clear(serr);
            value = "0";  /* ### what to do? */
            break;
          }

        value = apr_psprintf(scratch_pool, "%" SVN_FILESIZE_T_FMT, len);
        break;
      }

    case DAV_PROPID_getcontenttype:
      {
        /* The subversion client assumes that any file without an
           svn:mime-type property is of type text/plain.  So it seems
           safe (and consistent) to assume the same on the server.  */
        svn_string_t *pval;
        const char *mime_type = NULL;

        if (resource->baselined && resource->type == DAV_RESOURCE_TYPE_VERSION)
          return DAV_PROP_INSERT_NOTSUPP;

        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && (resource->info->restype == DAV_SVN_RESTYPE_VCC
                || resource->info->restype == DAV_SVN_RESTYPE_ME))
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (resource->collection) /* defaults for directories */
          {
            if (resource->info->repos->xslt_uri)
              mime_type = "text/xml";
            else
              mime_type = "text/html; charset=UTF-8";
          }
        else
          {
            if ((serr = svn_fs_node_prop(&pval, resource->info->root.root,
                                         resource->info->repos_path,
                                         SVN_PROP_MIME_TYPE, scratch_pool)))
              {
                svn_error_clear(serr);
                pval = NULL;
              }

            if (pval)
              mime_type = pval->data;
            else if ((! resource->info->repos->is_svn_client)
                     && resource->info->r->content_type)
              mime_type = resource->info->r->content_type;
            else
              mime_type = "text/plain";

            if ((serr = svn_mime_type_validate(mime_type, scratch_pool)))
              {
                /* Probably serr->apr == SVN_ERR_BAD_MIME_TYPE, but
                   there's no point even checking.  No matter what the
                   error is, we can't claim to have a mime type for
                   this resource. */
                svn_error_clear(serr);
                return DAV_PROP_INSERT_NOTDEF;
              }
          }

        value = mime_type;
        break;
      }

    case DAV_PROPID_getetag:
      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && (resource->info->restype == DAV_SVN_RESTYPE_VCC
              || resource->info->restype == DAV_SVN_RESTYPE_ME))
        {
          return DAV_PROP_INSERT_NOTSUPP;
        }

      value = dav_svn__getetag(resource, scratch_pool);
      break;

    case DAV_PROPID_auto_version:
      /* we only support one autoversioning behavior, and thus only
         return this one static value; someday when we support
         locking, there are other possible values/behaviors for this. */
      if (resource->info->repos->autoversioning)
        value = "DAV:checkout-checkin";
      else
        return DAV_PROP_INSERT_NOTDEF;
      break;

    case DAV_PROPID_baseline_collection:
      /* only defined for Baselines */
      /* ### whoops. also defined for a VCC. deal with it later. */
      if (resource->type != DAV_RESOURCE_TYPE_VERSION || !resource->baselined)
        return DAV_PROP_INSERT_NOTSUPP;
      value = dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_BC,
                                 resource->info->root.rev, NULL,
                                 1 /* add_href */, scratch_pool);
      break;

    case DAV_PROPID_checked_in:
      /* only defined for VCRs (in the public space and in a BC space) */
      /* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && (resource->info->restype == DAV_SVN_RESTYPE_VCC
              || resource->info->restype == DAV_SVN_RESTYPE_ME))
        {
          svn_revnum_t revnum;

          serr = svn_fs_youngest_rev(&revnum, resource->info->repos->fs,
                                     scratch_pool);
          if (serr != NULL)
            {
              ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                            resource->info->r,
                            "Can't get youngest revision in '%s': "
                            "%s",
                            svn_fs_path(resource->info->repos->fs,
                                        scratch_pool),
                            serr->message);
              svn_error_clear(serr);
              value = "###error###";
              break;
            }
          s = dav_svn__build_uri(resource->info->repos,
                                 DAV_SVN__BUILD_URI_BASELINE,
                                 revnum, NULL, 0 /* add_href */, scratch_pool);
          value = apr_psprintf(scratch_pool, "<D:href>%s</D:href>",
                               apr_xml_quote_string(scratch_pool, s, 1));
        }
      else if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        {
          /* not defined for this resource type */
          return DAV_PROP_INSERT_NOTSUPP;
        }
      else
        {
          svn_revnum_t rev_to_use =
            dav_svn__get_safe_cr(resource->info->root.root,
                                 resource->info->repos_path, scratch_pool);

          s = dav_svn__build_uri(resource->info->repos,
                                 DAV_SVN__BUILD_URI_VERSION,
                                 rev_to_use, resource->info->repos_path,
                                0 /* add_href */, scratch_pool);
          value = apr_psprintf(scratch_pool, "<D:href>%s</D:href>",
                               apr_xml_quote_string(scratch_pool, s, 1));
        }
      break;

    case DAV_PROPID_version_controlled_configuration:
      /* only defined for VCRs */
      /* ### VCRs within the BC should not have this property! */
      /* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
      if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        return DAV_PROP_INSERT_NOTSUPP;
      value = dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_VCC,
                                 SVN_IGNORED_REVNUM, NULL,
                                 1 /* add_href */, scratch_pool);
      break;

    case DAV_PROPID_version_name:
      /* only defined for Version Resources and Baselines */
      /* ### whoops. also defined for VCRs. deal with it later. */
      if ((resource->type != DAV_RESOURCE_TYPE_VERSION)
          && (! resource->versioned))
        return DAV_PROP_INSERT_NOTSUPP;

      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && (resource->info->restype == DAV_SVN_RESTYPE_VCC
              || resource->info->restype == DAV_SVN_RESTYPE_ME))
        {
          return DAV_PROP_INSERT_NOTSUPP;
        }

      if (resource->baselined)
        {
          /* just the revision number for baselines */
          value = apr_psprintf(scratch_pool, "%ld",
                               resource->info->root.rev);
        }
      else
        {
          svn_revnum_t committed_rev = SVN_INVALID_REVNUM;

          /* Get the CR field out of the node's skel.  Notice that the
             root object might be an ID root -or- a revision root. */
          serr = svn_fs_node_created_rev(&committed_rev,
                                         resource->info->root.root,
                                         resource->info->repos_path,
                                         scratch_pool);
          if (serr != NULL)
            {
              ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                            resource->info->r,
                            "Can't get created-rev of '%s': "
                            "%s",
                            resource->info->repos_path,
                            serr->message);
              svn_error_clear(serr);
              value = "###error###";
              break;
            }

          /* Convert the revision into a quoted string */
          s = apr_psprintf(scratch_pool, "%ld", committed_rev);
          value = apr_xml_quote_string(scratch_pool, s, 1);
        }
      break;

    case SVN_PROPID_baseline_relative_path:
      /* only defined for VCRs */
      /* ### VCRs within the BC should not have this property! */
      /* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
      if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        return DAV_PROP_INSERT_NOTSUPP;

      /* drop the leading slash, so it is relative */
      s = resource->info->repos_path + 1;
      value = apr_xml_quote_string(scratch_pool, s, 1);
      break;

    case SVN_PROPID_md5_checksum:
      if ((! resource->collection)
          && (! resource->baselined)
          && (resource->type == DAV_RESOURCE_TYPE_REGULAR
              || resource->type == DAV_RESOURCE_TYPE_WORKING
              || resource->type == DAV_RESOURCE_TYPE_VERSION))
        {
          svn_node_kind_t kind;
          svn_checksum_t *checksum;

          serr = svn_fs_check_path(&kind, resource->info->root.root,
                                   resource->info->repos_path, scratch_pool);
          if (!serr && kind == svn_node_file)
            serr = svn_fs_file_checksum(&checksum, svn_checksum_md5,
                                        resource->info->root.root,
                                        resource->info->repos_path, TRUE,
                                        scratch_pool);
          if (serr != NULL)
            {
              ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                            resource->info->r,
                            "Can't fetch or compute MD5 checksum of '%s': "
                            "%s",
                            resource->info->repos_path,
                            serr->message);
              svn_error_clear(serr);
              value = "###error###";
              break;
            }

          if (kind != svn_node_file)
            return DAV_PROP_INSERT_NOTSUPP;

          value = svn_checksum_to_cstring(checksum, scratch_pool);

          if (! value)
            return DAV_PROP_INSERT_NOTSUPP;
        }
      else
        return DAV_PROP_INSERT_NOTSUPP;

      break;

    case SVN_PROPID_repository_uuid:
      serr = svn_fs_get_uuid(resource->info->repos->fs, &value, scratch_pool);
      if (serr != NULL)
        {
          ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                        resource->info->r,
                        "Can't fetch UUID of '%s': "
                        "%s",
                        svn_fs_path(resource->info->repos->fs, scratch_pool),
                        serr->message);
          svn_error_clear(serr);
          value = "###error###";
          break;
        }
      break;

    case SVN_PROPID_deadprop_count:
      {
        unsigned int propcount;
        apr_hash_t *proplist;

        if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
          return DAV_PROP_INSERT_NOTSUPP;

        serr = svn_fs_node_proplist(&proplist,
                                    resource->info->root.root,
                                    resource->info->repos_path, scratch_pool);
        if (serr != NULL)
          {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, 
                          resource->info->r,
                          "Can't fetch proplist of '%s': "
                          "%s",
                          resource->info->repos_path,
                          serr->message);
            svn_error_clear(serr);
            value = "###error###";
            break;
          }

        propcount = apr_hash_count(proplist);
        value = apr_psprintf(scratch_pool, "%u", propcount);
        break;
      }

    default:
      /* ### what the heck was this property? */
      return DAV_PROP_INSERT_NOTDEF;
    }

  /* assert: value != NULL */

  /* get the information and global NS index for the property */
  global_ns = dav_get_liveprop_info(propid, &dav_svn__liveprop_group, &info);

  /* assert: info != NULL && info->name != NULL */

  if (what == DAV_PROP_INSERT_NAME
      || (what == DAV_PROP_INSERT_VALUE && *value == '\0')) {
    s = apr_psprintf(result_pool, "<lp%d:%s/>" DEBUG_CR, global_ns,
                     info->name);
  }
  else if (what == DAV_PROP_INSERT_VALUE) {
    s = apr_psprintf(result_pool, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
                     global_ns, info->name, value, global_ns, info->name);
  }
  else {
    /* assert: what == DAV_PROP_INSERT_SUPPORTED */
    s = apr_psprintf(result_pool,
                     "<D:supported-live-property D:name=\"%s\" "
                     "D:namespace=\"%s\"/>" DEBUG_CR,
                     info->name, namespace_uris[info->ns]);
  }
  apr_text_append(result_pool, phdr, s);

  /* we inserted whatever was asked for */
  return what;
}