subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1776832 [3/4] - in /subversion/trunk: ./ subversion/include/ subversion/include/private/ subversion/libsvn_fs_x/ subversion/libsvn_repos/ subversion/libsvn_subr/ subversion/mod_authz_svn/ subversion/mod_dav_svn/ subversion/svnserve/ subver...
Date Sun, 01 Jan 2017 10:43:41 GMT
Modified: subversion/trunk/subversion/libsvn_repos/config_pool.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/config_pool.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/config_pool.c (original)
+++ subversion/trunk/subversion/libsvn_repos/config_pool.c Sun Jan  1 10:43:40 2017
@@ -25,110 +25,17 @@
 
 
 #include "svn_checksum.h"
-#include "svn_config.h"
-#include "svn_error.h"
-#include "svn_hash.h"
 #include "svn_path.h"
 #include "svn_pools.h"
-#include "svn_repos.h"
 
-#include "private/svn_dep_compat.h"
-#include "private/svn_mutex.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_repos_private.h"
-#include "private/svn_object_pool.h"
 
 #include "svn_private_config.h"
 
-
-/* Our wrapper structure for parsed svn_config_t* instances.  All data in
- * CS_CFG and CI_CFG is expanded (to make it thread-safe) and considered
- * read-only.
- */
-typedef struct config_object_t
-{
-  /* UUID of the configuration contents.
-   * This is a SHA1 checksum of the parsed textual representation of CFG. */
-  svn_checksum_t *key;
-
-  /* Parsed and expanded configuration.  At least one of the following
-   * must not be NULL. */
-
-  /* Case-sensitive config. May be NULL */
-  svn_config_t *cs_cfg;
-
-  /* Case-insensitive config. May be NULL */
-  svn_config_t *ci_cfg;
-} config_object_t;
-
-
-/* Data structure used to short-circuit the repository access for configs
- * read via URL.  After reading such a config successfully, we store key
- * repository information here and will validate it without actually opening
- * the repository.
- *
- * As this is only an optimization and may create many entries in
- * svn_repos__config_pool_t's IN_REPO_HASH_POOL index, we clean them up
- * once in a while.
- */
-typedef struct in_repo_config_t
-{
-  /* URL used to open the configuration */
-  const char *url;
-
-  /* Path of the repository that contained URL */
-  const char *repo_root;
-
-  /* Head revision of that repository when last read */
-  svn_revnum_t revision;
-
-  /* Contents checksum of the file stored under URL@REVISION */
-  svn_checksum_t *key;
-} in_repo_config_t;
-
-
-/* Core data structure extending the encapsulated OBJECT_POOL.  All access
- * to it must be serialized using the OBJECT_POOL->MUTEX.
- *
- * To speed up URL@HEAD lookups, we maintain IN_REPO_CONFIGS as a secondary
- * hash index.  It maps URLs as provided by the caller onto in_repo_config_t
- * instances.  If that is still up-to-date, a further lookup into CONFIG
- * may yield the desired configuration without the need to actually open
- * the respective repository.
- *
- * Unused configurations that are kept in the IN_REPO_CONFIGS hash and may
- * be cleaned up when the hash is about to grow.
- */
-struct svn_repos__config_pool_t
-{
-  svn_object_pool__t *object_pool;
-
-  /* URL -> in_repo_config_t* mapping.
-   * This is only a partial index and will get cleared regularly. */
-  apr_hash_t *in_repo_configs;
-
-  /* allocate the IN_REPO_CONFIGS index and in_repo_config_t here */
-  apr_pool_t *in_repo_hash_pool;
-};
+#include "config_file.h"
 
 
-/* Return an automatic reference to the CFG member in CONFIG that will be
- * released when POOL gets cleaned up.  The case sensitivity flag in *BATON
- * selects the desired option and section name matching mode.
- */
-static void *
-getter(void *object,
-       void *baton,
-       apr_pool_t *pool)
-{
-  config_object_t *wrapper = object;
-  svn_boolean_t *case_sensitive = baton;
-  svn_config_t *config = *case_sensitive ? wrapper->cs_cfg : wrapper->ci_cfg;
-
-  /* we need to duplicate the root structure as it contains temp. buffers */
-  return config ? svn_config__shallow_copy(config, pool) : NULL;
-}
-
 /* Return a memory buffer structure allocated in POOL and containing the
  * data from CHECKSUM.
  */
@@ -146,286 +53,43 @@ checksum_as_key(svn_checksum_t *checksum
   return result;
 }
 
-/* Copy the configuration from the wrapper in SOURCE to the wrapper in
- * *TARGET with the case sensitivity flag in *BATON selecting the config
- * to copy.  This is usually done to add the missing case-(in)-sensitive
- * variant.  Since we must hold all data in *TARGET from the same POOL,
- * a deep copy is required.
- */
-static svn_error_t *
-setter(void **target,
-       void *source,
-       void *baton,
-       apr_pool_t *pool)
-{
-  svn_boolean_t *case_sensitive = baton;
-  config_object_t *target_cfg = *(config_object_t **)target;
-  config_object_t *source_cfg = source;
-
-  /* Maybe, we created a variant with different case sensitivity? */
-  if (*case_sensitive && target_cfg->cs_cfg == NULL)
-    {
-      SVN_ERR(svn_config_dup(&target_cfg->cs_cfg, source_cfg->cs_cfg, pool));
-      svn_config__set_read_only(target_cfg->cs_cfg, pool);
-    }
-  else if (!*case_sensitive && target_cfg->ci_cfg == NULL)
-    {
-      SVN_ERR(svn_config_dup(&target_cfg->ci_cfg, source_cfg->ci_cfg, pool));
-      svn_config__set_read_only(target_cfg->ci_cfg, pool);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Set *CFG to the configuration passed in as text in CONTENTS and *KEY to
- * the corresponding object pool key.  If no such configuration exists in
- * CONFIG_POOL, yet, parse CONTENTS and cache the result.  CASE_SENSITIVE
- * controls option and section name matching.
+/* Set *CFG to the configuration serialized in STREAM and cache it in
+ * CONFIG_POOL under CHECKSUM.  The configuration will only be parsed if
+ * we can't find it the CONFIG_POOL already.
  *
  * RESULT_POOL determines the lifetime of the returned reference and
  * SCRATCH_POOL is being used for temporary allocations.
  */
 static svn_error_t *
-auto_parse(svn_config_t **cfg,
-           svn_membuf_t **key,
-           svn_repos__config_pool_t *config_pool,
-           svn_stringbuf_t *contents,
-           svn_boolean_t case_sensitive,
-           apr_pool_t *result_pool,
-           apr_pool_t *scratch_pool)
-{
-  svn_checksum_t *checksum;
-  config_object_t *config_object;
-  apr_pool_t *cfg_pool;
-
-  /* calculate SHA1 over the whole file contents */
-  SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
-                       contents->data, contents->len, scratch_pool));
-
-  /* return reference to suitable config object if that already exists */
-  *key = checksum_as_key(checksum, result_pool);
-  SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool,
-                                  *key, &case_sensitive, result_pool));
-  if (*cfg)
-    return SVN_NO_ERROR;
-
-  /* create a pool for the new config object and parse the data into it  */
-  cfg_pool = svn_object_pool__new_wrapper_pool(config_pool->object_pool);
-
-  config_object = apr_pcalloc(cfg_pool, sizeof(*config_object));
-
-  SVN_ERR(svn_config_parse(case_sensitive ? &config_object->cs_cfg
-                                          : &config_object->ci_cfg,
-                           svn_stream_from_stringbuf(contents, scratch_pool),
-                           case_sensitive, case_sensitive, cfg_pool));
-
-  /* switch config data to r/o mode to guarantee thread-safe access */
-  svn_config__set_read_only(case_sensitive ? config_object->cs_cfg
-                                           : config_object->ci_cfg,
-                            cfg_pool);
-
-  /* add config in pool, handle loads races and return the right config */
-  SVN_ERR(svn_object_pool__insert((void **)cfg, config_pool->object_pool,
-                                  *key, config_object, &case_sensitive,
-                                  cfg_pool, result_pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* Store a URL@REVISION to CHECKSUM, REPOS_ROOT in CONFIG_POOL.
- */
-static svn_error_t *
-add_checksum(svn_repos__config_pool_t *config_pool,
-             const char *url,
-             const char *repos_root,
-             svn_revnum_t revision,
-             svn_checksum_t *checksum)
-{
-  apr_size_t path_len = strlen(url);
-  apr_pool_t *pool = config_pool->in_repo_hash_pool;
-  in_repo_config_t *config = apr_hash_get(config_pool->in_repo_configs,
-                                          url, path_len);
-  if (config)
-    {
-      /* update the existing entry */
-      memcpy((void *)config->key->digest, checksum->digest,
-             svn_checksum_size(checksum));
-      config->revision = revision;
-
-      /* duplicate the string only if necessary */
-      if (strcmp(config->repo_root, repos_root))
-        config->repo_root = apr_pstrdup(pool, repos_root);
-    }
-  else
-    {
-      /* insert a new entry.
-       * Limit memory consumption by cyclically clearing pool and hash. */
-      if (2 * svn_object_pool__count(config_pool->object_pool)
-          < apr_hash_count(config_pool->in_repo_configs))
-        {
-          svn_pool_clear(pool);
-          config_pool->in_repo_configs = svn_hash__make(pool);
-        }
-
-      /* construct the new entry */
-      config = apr_pcalloc(pool, sizeof(*config));
-      config->key = svn_checksum_dup(checksum, pool);
-      config->url = apr_pstrmemdup(pool, url, path_len);
-      config->repo_root = apr_pstrdup(pool, repos_root);
-      config->revision = revision;
+find_config(svn_config_t **cfg,
+            svn_repos__config_pool_t *config_pool,
+            svn_stream_t *stream,
+            svn_checksum_t *checksum,
+            apr_pool_t *result_pool,
+            apr_pool_t *scratch_pool)
+{
+  /* First, attempt the cache lookup. */
+  svn_membuf_t *key = checksum_as_key(checksum, scratch_pool);
+  SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool, key,
+                                  result_pool));
 
-      /* add to index */
-      apr_hash_set(config_pool->in_repo_configs, url, path_len, config);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Set *CFG to the configuration stored in URL@HEAD and cache it in
- * CONFIG_POOL.  CASE_SENSITIVE controls
- * option and section name matching.  If PREFERRED_REPOS is given,
- * use that if it also matches URL.
- *
- * RESULT_POOL determines the lifetime of the returned reference and
- * SCRATCH_POOL is being used for temporary allocations.
- */
-static svn_error_t *
-find_repos_config(svn_config_t **cfg,
-                  svn_membuf_t **key,
-                  svn_repos__config_pool_t *config_pool,
-                  const char *url,
-                  svn_boolean_t case_sensitive,
-                  svn_repos_t *preferred_repos,
-                  apr_pool_t *result_pool,
-                  apr_pool_t *scratch_pool)
-{
-  svn_repos_t *repos = NULL;
-  svn_fs_t *fs;
-  svn_fs_root_t *root;
-  svn_revnum_t youngest_rev;
-  svn_node_kind_t node_kind;
-  const char *dirent;
-  svn_stream_t *stream;
-  const char *fs_path;
-  const char *repos_root_dirent;
-  svn_checksum_t *checksum;
-  svn_stringbuf_t *contents;
-
-  *cfg = NULL;
-  SVN_ERR(svn_uri_get_dirent_from_file_url(&dirent, url, scratch_pool));
-
-  /* maybe we can use the preferred repos instance instead of creating a
-   * new one */
-  if (preferred_repos)
-    {
-      repos_root_dirent = svn_repos_path(preferred_repos, scratch_pool);
-      if (!svn_dirent_is_absolute(repos_root_dirent))
-        SVN_ERR(svn_dirent_get_absolute(&repos_root_dirent,
-                                        repos_root_dirent,
-                                        scratch_pool));
-
-      if (svn_dirent_is_ancestor(repos_root_dirent, dirent))
-        repos = preferred_repos;
-    }
-
-  /* open repos if no suitable preferred repos was provided. */
-  if (!repos)
-    {
-      /* Search for a repository in the full path. */
-      repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
-
-      /* 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)];
-
-  /* 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));
-
-  /* Fetch checksum and see whether we already have a matching config */
-  SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root, fs_path,
-                               FALSE, scratch_pool));
-  if (checksum)
-    {
-      *key = checksum_as_key(checksum, scratch_pool);
-      SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool,
-                                      *key, &case_sensitive, result_pool));
-    }
-
-  /* not parsed, yet? */
+  /* Not found? => parse and cache */
   if (!*cfg)
     {
-      svn_filesize_t length;
+      svn_config_t *config;
 
-      /* fetch the file contents */
-      SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool));
-      if (node_kind != svn_node_file)
-        return SVN_NO_ERROR;
-
-      SVN_ERR(svn_fs_file_length(&length, root, fs_path, scratch_pool));
-      SVN_ERR(svn_fs_file_contents(&stream, root, fs_path, scratch_pool));
-      SVN_ERR(svn_stringbuf_from_stream(&contents, stream,
-                                        (apr_size_t)length, scratch_pool));
-
-      /* handle it like ordinary file contents and cache it */
-      SVN_ERR(auto_parse(cfg, key, config_pool, contents, case_sensitive,
-                         result_pool, scratch_pool));
+      /* create a pool for the new config object and parse the data into it */
+      apr_pool_t *cfg_pool = svn_object_pool__new_item_pool(config_pool);
+      SVN_ERR(svn_config_parse(&config, stream, FALSE, FALSE, cfg_pool));
+
+      /* switch config data to r/o mode to guarantee thread-safe access */
+      svn_config__set_read_only(config, cfg_pool);
+
+      /* add config in pool, handle loads races and return the right config */
+      SVN_ERR(svn_object_pool__insert((void **)cfg, config_pool, key,
+                                      config, cfg_pool, result_pool));
     }
 
-  /* store the (path,rev) -> checksum mapping as well */
-  if (*cfg && checksum)
-    SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool),
-                         add_checksum(config_pool, url, repos_root_dirent,
-                                      youngest_rev, checksum));
-
-  return SVN_NO_ERROR;
-}
-
-/* Given the URL, search the CONFIG_POOL for an entry that maps it URL to
- * a content checksum and is still up-to-date.  If this could be found,
- * return the object's *KEY.  Use POOL for allocations.
- *
- * Requires external serialization on CONFIG_POOL.
- *
- * Note that this is only the URL(+rev) -> Checksum lookup and does not
- * guarantee that there is actually a config object available for *KEY.
- */
-static svn_error_t *
-key_by_url(svn_membuf_t **key,
-           svn_repos__config_pool_t *config_pool,
-           const char *url,
-           apr_pool_t *pool)
-{
-  svn_error_t *err;
-  svn_stringbuf_t *contents;
-  apr_int64_t current;
-
-  /* hash lookup url -> sha1 -> config */
-  in_repo_config_t *config = svn_hash_gets(config_pool->in_repo_configs, url);
-  *key = NULL;
-  if (!config)
-    return SVN_NO_ERROR;
-
-  /* found *some* reference to a configuration.
-   * Verify that it is still current.  Will fail for BDB repos. */
-  err = svn_stringbuf_from_file2(&contents,
-                                 svn_dirent_join(config->repo_root,
-                                                 "db/current", pool),
-                                 pool);
-  if (!err)
-    err = svn_cstring_atoi64(&current, contents->data);
-
-  if (err)
-    svn_error_clear(err);
-  else if (current == config->revision)
-    *key = checksum_as_key(config->key, pool);
-
   return SVN_NO_ERROR;
 }
 
@@ -436,94 +100,49 @@ svn_repos__config_pool_create(svn_repos_
                               svn_boolean_t thread_safe,
                               apr_pool_t *pool)
 {
-  svn_repos__config_pool_t *result;
-  svn_object_pool__t *object_pool;
-
-  SVN_ERR(svn_object_pool__create(&object_pool, getter, setter,
-                                  thread_safe, pool));
-
-  /* construct the config pool in our private ROOT_POOL to survive POOL
-   * cleanup and to prevent threading issues with the allocator */
-  result = apr_pcalloc(pool, sizeof(*result));
-
-  result->object_pool = object_pool;
-  result->in_repo_hash_pool = svn_pool_create(pool);
-  result->in_repo_configs = svn_hash__make(result->in_repo_hash_pool);
-
-  *config_pool = result;
-  return SVN_NO_ERROR;
+  return svn_error_trace(svn_object_pool__create(config_pool,
+                                                 thread_safe, pool));
 }
 
 svn_error_t *
 svn_repos__config_pool_get(svn_config_t **cfg,
-                           svn_membuf_t **key,
                            svn_repos__config_pool_t *config_pool,
                            const char *path,
                            svn_boolean_t must_exist,
-                           svn_boolean_t case_sensitive,
                            svn_repos_t *preferred_repos,
                            apr_pool_t *pool)
 {
   svn_error_t *err = SVN_NO_ERROR;
   apr_pool_t *scratch_pool = svn_pool_create(pool);
+  config_access_t *access = svn_repos__create_config_access(preferred_repos,
+                                                            scratch_pool);
+  svn_stream_t *stream;
+  svn_checksum_t *checksum;
 
-  /* make sure we always have a *KEY object */
-  svn_membuf_t *local_key = NULL;
-  if (key == NULL)
-    key = &local_key;
-  else
-    *key = NULL;
+  *cfg = NULL;
+  err = svn_repos__get_config(&stream, &checksum, access, path, must_exist,
+                              scratch_pool);
+  if (!err)
+    err = svn_error_quick_wrapf(find_config(cfg, config_pool, stream,
+                                            checksum, pool, scratch_pool),
+                                "Error while parsing config file: '%s':",
+                                path);
 
-  if (svn_path_is_url(path))
-    {
-      /* Read config file from repository.
-       * Attempt a quick lookup first. */
-      SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool),
-                           key_by_url(key, config_pool, path, pool));
-      if (*key)
-        {
-          SVN_ERR(svn_object_pool__lookup((void **)cfg,
-                                          config_pool->object_pool,
-                                          *key, &case_sensitive, pool));
-          if (*cfg)
-            {
-              svn_pool_destroy(scratch_pool);
-              return SVN_NO_ERROR;
-            }
-        }
-
-      /* Read and cache the configuration.  This may fail. */
-      err = find_repos_config(cfg, key, config_pool, path, case_sensitive,
-                              preferred_repos, pool, scratch_pool);
-      if (err || !*cfg)
-        {
-          /* let the standard implementation handle all the difficult cases */
-          svn_error_clear(err);
-          err = svn_repos__retrieve_config(cfg, path, must_exist,
-                                           case_sensitive, pool);
-        }
-    }
-  else
+  /* Let the standard implementation handle all the difficult cases.
+   * Note that for in-repo configs, there are no further special cases to
+   * check for and deal with. */
+  if (!*cfg && !svn_path_is_url(path))
     {
-      /* Outside of repo file.  Read it. */
-      svn_stringbuf_t *contents;
-      err = svn_stringbuf_from_file2(&contents, path, scratch_pool);
-      if (err)
-        {
-          /* let the standard implementation handle all the difficult cases */
-          svn_error_clear(err);
-          err = svn_config_read3(cfg, path, must_exist, case_sensitive,
-                                 case_sensitive, pool);
-        }
-      else
-        {
-          /* parsing and caching will always succeed */
-          err = auto_parse(cfg, key, config_pool, contents, case_sensitive,
-                           pool, scratch_pool);
-        }
+      svn_error_clear(err);
+      err = svn_config_read3(cfg, path, must_exist, FALSE, FALSE, pool);
     }
 
+  svn_repos__destroy_config_access(access);
   svn_pool_destroy(scratch_pool);
 
-  return err;
+  /* we need to duplicate the root structure as it contains temp. buffers */
+  if (*cfg)
+    *cfg = svn_config__shallow_copy(*cfg, pool);
+
+  return svn_error_trace(err);
 }

Modified: subversion/trunk/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/deprecated.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_repos/deprecated.c Sun Jan  1 10:43:40 2017
@@ -29,7 +29,9 @@
 #include "svn_repos.h"
 #include "svn_compat.h"
 #include "svn_hash.h"
+#include "svn_path.h"
 #include "svn_props.h"
+#include "svn_pools.h"
 
 #include "svn_private_config.h"
 
@@ -1171,9 +1173,30 @@ svn_repos_fs_begin_txn_for_update(svn_fs
 /*** From authz.c ***/
 
 svn_error_t *
+svn_repos_authz_read2(svn_authz_t **authz_p,
+                      const char *path,
+                      const char *groups_path,
+                      svn_boolean_t must_exist,
+                      apr_pool_t *pool)
+{
+  apr_pool_t *scratch_pool = svn_pool_create(pool);
+  svn_error_t *err = svn_repos_authz_read3(authz_p, path, groups_path,
+                                           must_exist, NULL,
+                                           pool, scratch_pool);
+  svn_pool_destroy(scratch_pool);
+
+  return svn_error_trace(err);
+}
+
+svn_error_t *
 svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
                      svn_boolean_t must_exist, apr_pool_t *pool)
 {
-  return svn_repos__authz_read(authz_p, file, NULL, must_exist,
-                               FALSE, pool);
+  /* Prevent accidental new features in existing API. */
+  if (svn_path_is_url(file))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             "'%s' is not a file name", file);
+
+  return svn_error_trace(svn_repos_authz_read2(authz_p, file, NULL,
+                                               must_exist, pool));
 }

Modified: subversion/trunk/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/repos.h?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/repos.h (original)
+++ subversion/trunk/subversion/libsvn_repos/repos.h Sun Jan  1 10:43:40 2017
@@ -27,6 +27,7 @@
 #include <apr_hash.h>
 
 #include "svn_fs.h"
+#include "svn_config.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -362,32 +363,6 @@ svn_repos__hooks_post_unlock(svn_repos_t
                              apr_pool_t *pool);
 
 
-/*** Authz Functions ***/
-
-/* Read authz configuration data from PATH into *AUTHZ_P, allocated
-   in POOL.  If GROUPS_PATH is set, use the global groups parsed from it.
-
-   PATH and GROUPS_PATH may be a dirent or a registry path and iff ACCEPT_URLS
-   is set it may also be an absolute file url.
-
-   If PATH or GROUPS_PATH is not a valid authz rule file, then return
-   SVN_AUTHZ_INVALID_CONFIG.  The contents of *AUTHZ_P is then
-   undefined.  If MUST_EXIST is TRUE, a missing authz or global groups file
-   is also an error. */
-svn_error_t *
-svn_repos__authz_read(svn_authz_t **authz_p,
-                      const char *path,
-                      const char *groups_path,
-                      svn_boolean_t must_exist,
-                      svn_boolean_t accept_urls,
-                      apr_pool_t *pool);
-
-/* Walk the configuration in AUTHZ looking for any errors. */
-svn_error_t *
-svn_repos__authz_validate(svn_authz_t *authz,
-                          apr_pool_t *pool);
-
-
 /*** Utility Functions ***/
 
 /* Set *PREV_PATH and *PREV_REV to the path and revision which

Modified: subversion/trunk/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/config.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/config.c (original)
+++ subversion/trunk/subversion/libsvn_subr/config.c Sun Jan  1 10:43:40 2017
@@ -33,12 +33,15 @@
 #include <apr_lib.h>
 #include "svn_hash.h"
 #include "svn_error.h"
+#include "svn_string.h"
 #include "svn_pools.h"
 #include "config_impl.h"
 
-#include "svn_private_config.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_subr_private.h"
+#include "private/svn_config_private.h"
+
+#include "svn_private_config.h"
 
 
 
@@ -108,7 +111,7 @@ svn_config_create2(svn_config_t **cfgp,
 {
   svn_config_t *cfg = apr_palloc(result_pool, sizeof(*cfg));
 
-  cfg->sections = apr_hash_make(result_pool);
+  cfg->sections = svn_hash__make(result_pool);
   cfg->pool = result_pool;
   cfg->x_pool = svn_pool_create(result_pool);
   cfg->x_values = FALSE;
@@ -159,6 +162,18 @@ svn_config_read3(svn_config_t **cfgp, co
 }
 
 svn_error_t *
+svn_config__default_add_value_fn(void *baton,
+                                 svn_stringbuf_t *section,
+                                 svn_stringbuf_t *option,
+                                 svn_stringbuf_t *value)
+{
+  /* FIXME: We may as well propagate the known string sizes here. */
+  svn_config_set((svn_config_t *)baton, section->data,
+                 option->data, value->data);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_config_parse(svn_config_t **cfgp, svn_stream_t *stream,
                  svn_boolean_t section_names_case_sensitive,
                  svn_boolean_t option_names_case_sensitive,
@@ -174,7 +189,12 @@ svn_config_parse(svn_config_t **cfgp, sv
                            result_pool);
 
   if (err == SVN_NO_ERROR)
-    err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
+    err = svn_config__parse_stream(stream,
+                                   svn_config__constructor_create(
+                                       NULL, NULL,
+                                       svn_config__default_add_value_fn,
+                                       scratch_pool),
+                                   cfg, scratch_pool);
 
   if (err == SVN_NO_ERROR)
     *cfgp = cfg;
@@ -315,7 +335,7 @@ svn_config_get_config(apr_hash_t **cfg_h
                       apr_pool_t *pool)
 {
   svn_config_t *cfg;
-  *cfg_hash = apr_hash_make(pool);
+  *cfg_hash = svn_hash__make(pool);
 
   SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS,
                               pool));
@@ -333,7 +353,7 @@ svn_config__get_default_config(apr_hash_
                                apr_pool_t *pool)
 {
   svn_config_t *empty_cfg;
-  *cfg_hash = apr_hash_make(pool);
+  *cfg_hash = svn_hash__make(pool);
 
   SVN_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
   svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, empty_cfg);
@@ -690,7 +710,8 @@ svn_config_addsection(svn_config_t *cfg,
     hash_key = s->name;
   else
     hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
-  s->options = apr_hash_make(cfg->pool);
+  s->options = svn_hash__make(cfg->pool);
+
   svn_hash_sets(cfg->sections, hash_key, s);
 
   return s;
@@ -1234,7 +1255,7 @@ svn_config_copy_config(apr_hash_t **cfg_
 {
   apr_hash_index_t *cidx;
 
-  *cfg_hash = apr_hash_make(pool);
+  *cfg_hash = svn_hash__make(pool);
   for (cidx = apr_hash_first(pool, src_hash);
        cidx != NULL;
        cidx = apr_hash_next(cidx))
@@ -1311,3 +1332,40 @@ svn_config_has_section(svn_config_t *cfg
   return NULL != get_hash_value(cfg->sections, cfg->tmp_key, section,
                                 cfg->section_names_case_sensitive);
 }
+
+svn_error_t *
+svn_config__write(svn_stream_t *stream,
+                  const struct svn_config_t *cfg,
+                  apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *section_i;
+  apr_hash_index_t *options_i;
+  apr_pool_t *section_pool = svn_pool_create(scratch_pool);
+  apr_pool_t *options_pool = svn_pool_create(scratch_pool);
+
+  for (section_i = apr_hash_first(scratch_pool, cfg->sections);
+       section_i != NULL;
+       section_i = apr_hash_next(section_i))
+    {
+      cfg_section_t *section = apr_hash_this_val(section_i);
+      svn_pool_clear(section_pool);
+      SVN_ERR(svn_stream_printf(stream, section_pool, "\n[%s]\n",
+                                section->name));
+
+      for (options_i = apr_hash_first(section_pool, section->options);
+           options_i != NULL;
+           options_i = apr_hash_next(options_i))
+        {
+          cfg_option_t *option = apr_hash_this_val(options_i);
+          svn_pool_clear(options_pool);
+          SVN_ERR(svn_stream_printf(stream, options_pool, "%s=%s\n",
+                                    option->name, option->value));
+        }
+    }
+
+  svn_pool_destroy(section_pool);
+  svn_pool_destroy(options_pool);
+
+  return SVN_NO_ERROR;
+}
+

Modified: subversion/trunk/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/config_file.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/config_file.c (original)
+++ subversion/trunk/subversion/libsvn_subr/config_file.c Sun Jan  1 10:43:40 2017
@@ -25,6 +25,8 @@
 
 #include <apr_lib.h>
 #include <apr_env.h>
+#include <apr_tables.h>
+
 #include "config_impl.h"
 #include "svn_io.h"
 #include "svn_types.h"
@@ -37,8 +39,9 @@
 #include "svn_user.h"
 #include "svn_ctype.h"
 
-#include "svn_private_config.h"
+#include "private/svn_config_private.h"
 #include "private/svn_subr_private.h"
+#include "svn_private_config.h"
 
 #ifdef __HAIKU__
 #  include <FindDirectory.h>
@@ -52,8 +55,9 @@
 /* File parsing context */
 typedef struct parse_context_t
 {
-  /* This config struct */
-  svn_config_t *cfg;
+  /* The configuration constructor. */
+  svn_config__constructor_t *constructor;
+  void *constructor_baton;
 
   /* The stream struct */
   svn_stream_t *stream;
@@ -64,10 +68,14 @@ typedef struct parse_context_t
   /* Emulate an ungetc */
   int ungotten_char;
 
+  /* We're currently parsing a section */
+  svn_boolean_t in_section;
+
   /* Temporary strings */
   svn_stringbuf_t *section;
   svn_stringbuf_t *option;
   svn_stringbuf_t *value;
+  svn_stringbuf_t *line_read;
 
   /* Parser buffer for getc() to avoid call overhead into several libraries
      for every character */
@@ -80,6 +88,109 @@ typedef struct parse_context_t
 } parse_context_t;
 
 
+/* Config representation constructor */
+struct svn_config__constructor_t
+{
+  /* Constructor callbacks; see docs for svn_config__constructor_create. */
+  svn_config__open_section_fn open_section;
+  svn_config__close_section_fn close_section;
+  svn_config__add_value_fn add_value;
+};
+
+svn_config__constructor_t *
+svn_config__constructor_create(
+    svn_config__open_section_fn open_section_callback,
+    svn_config__close_section_fn close_section_callback,
+    svn_config__add_value_fn add_value_callback,
+    apr_pool_t *result_pool)
+{
+  svn_config__constructor_t *ctor = apr_palloc(result_pool, sizeof(*ctor));
+  ctor->open_section = open_section_callback;
+  ctor->close_section = close_section_callback;
+  ctor->add_value = add_value_callback;
+  return ctor;
+}
+
+/* Called after we've parsed a section name and before we start
+   parsing any options within that section. */
+static APR_INLINE svn_error_t *
+open_section(parse_context_t *ctx, svn_boolean_t *stop)
+{
+  if (ctx->constructor->open_section)
+    {
+      svn_error_t *err = ctx->constructor->open_section(
+          ctx->constructor_baton, ctx->section);
+      if (err)
+        {
+          if (err->apr_err == SVN_ERR_CEASE_INVOCATION)
+            {
+              *stop = TRUE;
+              svn_error_clear(err);
+              return SVN_NO_ERROR;
+            }
+          else
+            return svn_error_trace(err);
+        }
+    }
+
+  *stop = FALSE;
+  ctx->in_section = TRUE;
+  return SVN_NO_ERROR;
+}
+
+/* Called after we've parsed all options within a section and before
+   we start parsing the next section. */
+static APR_INLINE svn_error_t *
+close_section(parse_context_t *ctx, svn_boolean_t *stop)
+{
+  ctx->in_section = FALSE;
+  if (ctx->constructor->close_section)
+    {
+      svn_error_t *err = ctx->constructor->close_section(
+          ctx->constructor_baton, ctx->section);
+      if (err)
+        {
+          if (err->apr_err == SVN_ERR_CEASE_INVOCATION)
+            {
+              *stop = TRUE;
+              svn_error_clear(err);
+              return SVN_NO_ERROR;
+            }
+          else
+            return svn_error_trace(err);
+        }
+    }
+
+  *stop = FALSE;
+  return SVN_NO_ERROR;
+}
+
+/* Called every tyme we've parsed a complete (option, value) pair. */
+static APR_INLINE svn_error_t *
+add_value(parse_context_t *ctx, svn_boolean_t *stop)
+{
+  if (ctx->constructor->add_value)
+    {
+      svn_error_t *err =  ctx->constructor->add_value(
+          ctx->constructor_baton, ctx->section,
+          ctx->option, ctx->value);
+      if (err)
+        {
+          if (err->apr_err == SVN_ERR_CEASE_INVOCATION)
+            {
+              *stop = TRUE;
+              svn_error_clear(err);
+              return SVN_NO_ERROR;
+            }
+          else
+            return svn_error_trace(err);
+        }
+    }
+
+  *stop = FALSE;
+  return SVN_NO_ERROR;
+}
+
 
 /* Emulate getc() because streams don't support it.
  *
@@ -161,6 +272,57 @@ parser_ungetc(parse_context_t *ctx, int
   return SVN_NO_ERROR;
 }
 
+/* Read from CTX to the end of the line (or file) and write the data
+   into LINE.  Previous contents of *LINE will be overwritten.
+   Returns the char that ended the line in *C; the char is either
+   EOF or newline. */
+static svn_error_t *
+parser_get_line(parse_context_t *ctx, svn_stringbuf_t *line, int *c)
+{
+  int ch;
+  svn_stringbuf_setempty(line);
+
+  /* Loop until EOF of newline. There is one extra iteration per
+   * parser buffer refill.  The initial parser_getc() also ensures
+   * that the unget buffer is emptied. */
+  SVN_ERR(parser_getc(ctx, &ch));
+  while (ch != '\n' && ch != EOF)
+    {
+      const char *start, *newline;
+
+      /* Save the char we just read. */
+      svn_stringbuf_appendbyte(line, ch);
+
+      /* Scan the parser buffer for NL. */
+      start = ctx->parser_buffer + ctx->buffer_pos;
+      newline = memchr(start, '\n', ctx->buffer_size - ctx->buffer_pos);
+      if (newline)
+        {
+          /* NL found before the end of the of the buffer. */
+          svn_stringbuf_appendbytes(line, start, newline - start);
+          ch = '\n';
+          ctx->buffer_pos = newline - ctx->parser_buffer + 1;
+          break;
+        }
+      else
+        {
+          /* Hit the end of the buffer.  This may be either due to
+           * buffer size or EOF.  In any case, all (remaining) current
+           * buffer data is part of the line to read. */
+          const char *end = ctx->parser_buffer + ctx->buffer_size;
+          ctx->buffer_pos = ctx->buffer_size;
+
+          svn_stringbuf_appendbytes(line, start, end - start);
+        }
+
+      /* refill buffer, check for EOF */
+      SVN_ERR(parser_getc_plain(ctx, &ch));
+    }
+
+  *c = ch;
+  return SVN_NO_ERROR;
+}
+
 /* Eat chars from STREAM until encounter non-whitespace, newline, or EOF.
    Set *PCOUNT to the number of characters eaten, not counting the
    last one, and return the last char read (the one that caused the
@@ -245,23 +407,16 @@ skip_bom(parse_context_t *ctx)
   return SVN_NO_ERROR;
 }
 
-/* Parse a single option value */
+/* Parse continuation lines of single option value if they exist.  Append
+ * their contents, including *PCH, to CTX->VALUE.  Return the first char
+ * of the next line or EOF in *PCH. */
 static svn_error_t *
-parse_value(int *pch, parse_context_t *ctx)
+parse_value_continuation_lines(int *pch, parse_context_t *ctx)
 {
   svn_boolean_t end_of_val = FALSE;
-  int ch;
+  svn_boolean_t stop;
+  int ch = *pch;
 
-  /* Read the first line of the value */
-  svn_stringbuf_setempty(ctx->value);
-  SVN_ERR(parser_getc(ctx, &ch));
-  while (ch != EOF && ch != '\n')
-    /* last ch seen was ':' or '=' in parse_option. */
-    {
-      const char char_from_int = (char)ch;
-      svn_stringbuf_appendbyte(ctx->value, char_from_int);
-      SVN_ERR(parser_getc(ctx, &ch));
-    }
   /* Leading and trailing whitespace is ignored. */
   svn_stringbuf_strip_whitespace(ctx->value);
 
@@ -273,8 +428,9 @@ parse_value(int *pch, parse_context_t *c
         {
           /* At end of file. The value is complete, there can't be
              any continuation lines. */
-          svn_config_set(ctx->cfg, ctx->section->data,
-                         ctx->option->data, ctx->value->data);
+          SVN_ERR(add_value(ctx, &stop));
+          if (stop)
+            return SVN_NO_ERROR;
           break;
         }
       else
@@ -310,16 +466,14 @@ parse_value(int *pch, parse_context_t *c
               else
                 {
                   /* This is a continuation line. Read it. */
-                  svn_stringbuf_appendbyte(ctx->value, ' ');
+                  SVN_ERR(parser_get_line(ctx, ctx->line_read, &ch));
 
-                  while (ch != EOF && ch != '\n')
-                    {
-                      const char char_from_int = (char)ch;
-                      svn_stringbuf_appendbyte(ctx->value, char_from_int);
-                      SVN_ERR(parser_getc(ctx, &ch));
-                    }
                   /* Trailing whitespace is ignored. */
-                  svn_stringbuf_strip_whitespace(ctx->value);
+                  svn_stringbuf_strip_whitespace(ctx->line_read);
+
+                  svn_stringbuf_appendbyte(ctx->value, ' ');
+                  svn_stringbuf_appendbytes(ctx->value, ctx->line_read->data,
+                                            ctx->line_read->len);
                 }
             }
         }
@@ -336,17 +490,33 @@ parse_option(int *pch, parse_context_t *
 {
   svn_error_t *err = SVN_NO_ERROR;
   int ch;
+  char *equals, *separator;
+
+  /* Read the first line. */
+  parser_ungetc(ctx, *pch); /* Yes, the first char is relevant. */
+  SVN_ERR(parser_get_line(ctx, ctx->line_read, &ch));
+
+  /* Extract the option name from it. */
+  equals = strchr(ctx->line_read->data, '=');
+  if (equals)
+    {
+      /* Efficiently look for a colon separator prior to the equals sign.
+       * Since there is no strnchr, we limit the search by temporarily
+       * limiting the string. */
+      char *colon;
+      *equals = 0;
+      colon = strchr(ctx->line_read->data, ':');
+      *equals = '=';
 
-  svn_stringbuf_setempty(ctx->option);
-  ch = *pch;   /* Yes, the first char is relevant. */
-  while (ch != EOF && ch != ':' && ch != '=' && ch != '\n')
+      separator = colon ? colon : equals;
+    }
+  else
     {
-      const char char_from_int = (char)ch;
-      svn_stringbuf_appendbyte(ctx->option, char_from_int);
-      SVN_ERR(parser_getc(ctx, &ch));
+      /* No '=' separator so far.  Look for colon. */
+      separator = strchr(ctx->line_read->data, ':');
     }
 
-  if (ch != ':' && ch != '=')
+  if (!separator)
     {
       ch = EOF;
       err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
@@ -356,8 +526,22 @@ parse_option(int *pch, parse_context_t *
   else
     {
       /* Whitespace around the name separator is ignored. */
-      svn_stringbuf_strip_whitespace(ctx->option);
-      err = parse_value(&ch, ctx);
+      const char *end = separator;
+      while (svn_ctype_isspace(*--end))
+        ;
+      while (svn_ctype_isspace(*++separator))
+        ;
+
+      /* Extract the option.  It can't contain whitespace chars. */
+      svn_stringbuf_setempty(ctx->option);
+      svn_stringbuf_appendbytes(ctx->option, ctx->line_read->data,
+                                end + 1 - ctx->line_read->data);
+
+      /* Extract the first line of the value. */
+      end = ctx->line_read->data + ctx->line_read->len;
+      svn_stringbuf_setempty(ctx->value);
+      svn_stringbuf_appendbytes(ctx->value, separator, end - separator);
+      err = parse_value_continuation_lines(&ch, ctx);
     }
 
   *pch = ch;
@@ -379,17 +563,12 @@ parse_section_name(int *pch, parse_conte
 {
   svn_error_t *err = SVN_NO_ERROR;
   int ch;
+  char *terminal;
 
-  svn_stringbuf_setempty(ctx->section);
-  SVN_ERR(parser_getc(ctx, &ch));
-  while (ch != EOF && ch != ']' && ch != '\n')
-    {
-      const char char_from_int = (char)ch;
-      svn_stringbuf_appendbyte(ctx->section, char_from_int);
-      SVN_ERR(parser_getc(ctx, &ch));
-    }
+  SVN_ERR(parser_get_line(ctx, ctx->section, &ch));
+  terminal = strchr(ctx->section->data, ']');
 
-  if (ch != ']')
+  if (!terminal)
     {
       ch = EOF;
       err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
@@ -399,9 +578,8 @@ parse_section_name(int *pch, parse_conte
   else
     {
       /* Everything from the ']' to the end of the line is ignored. */
-      SVN_ERR(skip_to_eoln(ctx, &ch));
-      if (ch != EOF)
-        ++ctx->line;
+      *terminal = 0;
+      ctx->section->len = terminal - ctx->section->data;
     }
 
   *pch = ch;
@@ -531,6 +709,7 @@ svn_config__shallow_replace_section(svn_
 }
 
 
+
 svn_error_t *
 svn_config__parse_file(svn_config_t *cfg, const char *file,
                        svn_boolean_t must_exist, apr_pool_t *result_pool)
@@ -554,7 +733,12 @@ svn_config__parse_file(svn_config_t *cfg
     SVN_ERR(err);
 
   stream = svn_stream_from_aprfile2(apr_file, FALSE, scratch_pool);
-  err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
+  err = svn_config__parse_stream(stream,
+                                 svn_config__constructor_create(
+                                     NULL, NULL,
+                                     svn_config__default_add_value_fn,
+                                     scratch_pool),
+                                 cfg, scratch_pool);
 
   if (err != SVN_NO_ERROR)
     {
@@ -571,21 +755,27 @@ svn_config__parse_file(svn_config_t *cfg
 }
 
 svn_error_t *
-svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream,
-                         apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+svn_config__parse_stream(svn_stream_t *stream,
+                         svn_config__constructor_t *constructor,
+                         void *constructor_baton,
+                         apr_pool_t *scratch_pool)
 {
   parse_context_t *ctx;
+  svn_boolean_t stop;
   int ch, count;
 
   ctx = apr_palloc(scratch_pool, sizeof(*ctx));
 
-  ctx->cfg = cfg;
+  ctx->constructor = constructor;
+  ctx->constructor_baton = constructor_baton;
   ctx->stream = stream;
   ctx->line = 1;
   ctx->ungotten_char = EOF;
+  ctx->in_section = FALSE;
   ctx->section = svn_stringbuf_create_empty(scratch_pool);
   ctx->option = svn_stringbuf_create_empty(scratch_pool);
   ctx->value = svn_stringbuf_create_empty(scratch_pool);
+  ctx->line_read = svn_stringbuf_create_empty(scratch_pool);
   ctx->buffer_pos = 0;
   ctx->buffer_size = 0;
   ctx->hit_stream_eof = FALSE;
@@ -599,13 +789,23 @@ svn_config__parse_stream(svn_config_t *c
       switch (ch)
         {
         case '[':               /* Start of section header */
-          if (count == 0)
-            SVN_ERR(parse_section_name(&ch, ctx, scratch_pool));
-          else
+          if (count != 0)
             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
                                      _("line %d: Section header"
                                        " must start in the first column"),
                                      ctx->line);
+
+          /* Close the previous section before starting a new one. */
+          if (ctx->in_section)
+            {
+              SVN_ERR(close_section(ctx, &stop));
+              if (stop)
+                return SVN_NO_ERROR;
+            }
+          SVN_ERR(parse_section_name(&ch, ctx, scratch_pool));
+          SVN_ERR(open_section(ctx, &stop));
+          if (stop)
+            return SVN_NO_ERROR;
           break;
 
         case '#':               /* Comment */
@@ -644,6 +844,9 @@ svn_config__parse_stream(svn_config_t *c
     }
   while (ch != EOF);
 
+  /* Emit the last close-section call to wrap up. */
+  if (ctx->in_section)
+    SVN_ERR(close_section(ctx, &stop));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/config_impl.h?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/trunk/subversion/libsvn_subr/config_impl.h Sun Jan  1 10:43:40 2017
@@ -76,18 +76,18 @@ struct svn_config_t
   svn_boolean_t read_only;
 };
 
+/* The default add-value constructor callback, used by the default
+   config parser that populates an svn_config_t. */
+svn_error_t *svn_config__default_add_value_fn(
+    void *baton, svn_stringbuf_t *section,
+    svn_stringbuf_t *option, svn_stringbuf_t *value);
+
 /* Read sections and options from a file. */
 svn_error_t *svn_config__parse_file(svn_config_t *cfg,
                                     const char *file,
                                     svn_boolean_t must_exist,
                                     apr_pool_t *pool);
 
-/* Read sections and options from a stream. */
-svn_error_t *svn_config__parse_stream(svn_config_t *cfg,
-                                      svn_stream_t *stream,
-                                      apr_pool_t *result_pool,
-                                      apr_pool_t *scratch_pool);
-
 /* The name of the magic [DEFAULT] section. */
 #define SVN_CONFIG__DEFAULT_SECTION "DEFAULT"
 

Modified: subversion/trunk/subversion/libsvn_subr/object_pool.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/object_pool.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/object_pool.c (original)
+++ subversion/trunk/subversion/libsvn_subr/object_pool.c Sun Jan  1 10:43:40 2017
@@ -1,5 +1,5 @@
 /*
- * config_pool.c :  pool of configuration objects
+ * object_pool.c :  generic pool of reference-counted objects
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -49,7 +49,7 @@ typedef struct object_ref_t
   svn_membuf_t key;
 
   /* User provided object. Usually a wrapper. */
-  void *wrapper;
+  void *object;
 
   /* private pool. This instance and its other members got allocated in it.
    * Will be destroyed when this instance is cleaned up. */
@@ -85,10 +85,6 @@ struct svn_object_pool__t
 
   /* the root pool owning this structure */
   apr_pool_t *pool;
-
-  /* extractor and updater for the user object wrappers */
-  svn_object_pool__getter_t getter;
-  svn_object_pool__setter_t setter;
 };
 
 
@@ -189,7 +185,6 @@ static svn_error_t *
 lookup(void **object,
        svn_object_pool__t *object_pool,
        svn_membuf_t *key,
-       void *baton,
        apr_pool_t *result_pool)
 {
   object_ref_t *object_ref
@@ -197,7 +192,7 @@ lookup(void **object,
 
   if (object_ref)
     {
-      *object = object_pool->getter(object_ref->wrapper, baton, result_pool);
+      *object = object_ref->object;
       add_object_ref(object_ref, result_pool);
     }
   else
@@ -216,57 +211,28 @@ static svn_error_t *
 insert(void **object,
        svn_object_pool__t *object_pool,
        const svn_membuf_t *key,
-       void *wrapper,
-       void *baton,
-       apr_pool_t *wrapper_pool,
+       void *item,
+       apr_pool_t *item_pool,
        apr_pool_t *result_pool)
 {
   object_ref_t *object_ref
     = apr_hash_get(object_pool->objects, key->data, key->size);
   if (object_ref)
     {
-      /* entry already exists (e.g. race condition) */
-      svn_error_t *err = object_pool->setter(&object_ref->wrapper,
-                                             wrapper, baton,
-                                             object_ref->pool);
-      if (err)
-        {
-          /* if we had an issue in the setter, then OBJECT_REF is in an
-           * unknown state now.  Keep it around for the current users
-           * (i.e. don't clean the pool) but remove it from the list of
-           * available ones.
-           */
-          apr_hash_set(object_pool->objects, key->data, key->size, NULL);
-          svn_atomic_dec(&object_pool->object_count);
-
-          /* for the unlikely case that the object got created _and_
-           * already released since we last checked: */
-          if (svn_atomic_read(&object_ref->ref_count) == 0)
-            svn_atomic_dec(&object_pool->unused_count);
-
-          /* cleanup the new data as well because it's not safe to use
-           * either.
-           */
-          svn_pool_destroy(wrapper_pool);
-
-          /* propagate error */
-          return svn_error_trace(err);
-        }
-
       /* Destroy the new one and return a reference to the existing one
        * because the existing one may already have references on it.
        */
-      svn_pool_destroy(wrapper_pool);
+      svn_pool_destroy(item_pool);
     }
   else
     {
       /* add new index entry */
-      object_ref = apr_pcalloc(wrapper_pool, sizeof(*object_ref));
+      object_ref = apr_pcalloc(item_pool, sizeof(*object_ref));
       object_ref->object_pool = object_pool;
-      object_ref->wrapper = wrapper;
-      object_ref->pool = wrapper_pool;
+      object_ref->object = item;
+      object_ref->pool = item_pool;
 
-      svn_membuf__create(&object_ref->key, key->size, wrapper_pool);
+      svn_membuf__create(&object_ref->key, key->size, item_pool);
       object_ref->key.size = key->size;
       memcpy(object_ref->key.data, key->data, key->size);
 
@@ -281,7 +247,7 @@ insert(void **object,
     }
 
   /* return a reference to the object we just added */
-  *object = object_pool->getter(object_ref->wrapper, baton, result_pool);
+  *object = object_ref->object;
   add_object_ref(object_ref, result_pool);
 
   /* limit memory usage */
@@ -292,34 +258,11 @@ insert(void **object,
   return SVN_NO_ERROR;
 }
 
-/* Implement svn_object_pool__getter_t as no-op.
- */
-static void *
-default_getter(void *object,
-               void *baton,
-               apr_pool_t *pool)
-{
-  return object;
-}
-
-/* Implement svn_object_pool__setter_t as no-op.
- */
-static svn_error_t *
-default_setter(void **target,
-               void *source,
-               void *baton,
-               apr_pool_t *pool)
-{
-  return SVN_NO_ERROR;
-}
-
 
 /* API implementation */
 
 svn_error_t *
 svn_object_pool__create(svn_object_pool__t **object_pool,
-                        svn_object_pool__getter_t getter,
-                        svn_object_pool__setter_t setter,
                         svn_boolean_t thread_safe,
                         apr_pool_t *pool)
 {
@@ -333,8 +276,6 @@ svn_object_pool__create(svn_object_pool_
 
   result->pool = pool;
   result->objects = svn_hash__make(result->pool);
-  result->getter = getter ? getter : default_getter;
-  result->setter = setter ? setter : default_setter;
 
   /* make sure we clean up nicely.
    * We need two cleanup functions of which exactly one will be run
@@ -351,33 +292,20 @@ svn_object_pool__create(svn_object_pool_
 }
 
 apr_pool_t *
-svn_object_pool__new_wrapper_pool(svn_object_pool__t *object_pool)
+svn_object_pool__new_item_pool(svn_object_pool__t *object_pool)
 {
   return svn_pool_create(object_pool->pool);
 }
 
-svn_mutex__t *
-svn_object_pool__mutex(svn_object_pool__t *object_pool)
-{
-  return object_pool->mutex;
-}
-
-unsigned
-svn_object_pool__count(svn_object_pool__t *object_pool)
-{
-  return svn_atomic_read(&object_pool->object_count);
-}
-
 svn_error_t *
 svn_object_pool__lookup(void **object,
                         svn_object_pool__t *object_pool,
                         svn_membuf_t *key,
-                        void *baton,
                         apr_pool_t *result_pool)
 {
   *object = NULL;
   SVN_MUTEX__WITH_LOCK(object_pool->mutex,
-                       lookup(object, object_pool, key, baton, result_pool));
+                       lookup(object, object_pool, key, result_pool));
   return SVN_NO_ERROR;
 }
 
@@ -385,14 +313,13 @@ svn_error_t *
 svn_object_pool__insert(void **object,
                         svn_object_pool__t *object_pool,
                         const svn_membuf_t *key,
-                        void *wrapper,
-                        void *baton,
-                        apr_pool_t *wrapper_pool,
+                        void *item,
+                        apr_pool_t *item_pool,
                         apr_pool_t *result_pool)
 {
   *object = NULL;
   SVN_MUTEX__WITH_LOCK(object_pool->mutex,
-                       insert(object, object_pool, key, wrapper, baton,
-                              wrapper_pool, result_pool));
+                       insert(object, object_pool, key, item, 
+                              item_pool, result_pool));
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/string.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/string.c (original)
+++ subversion/trunk/subversion/libsvn_subr/string.c Sun Jan  1 10:43:40 2017
@@ -487,9 +487,7 @@ svn_stringbuf_set(svn_stringbuf_t *str,
 void
 svn_stringbuf_setempty(svn_stringbuf_t *str)
 {
-  if (str->len > 0)
-    str->data[0] = '\0';
-
+  str->data[0] = '\0';
   str->len = 0;
 }
 
@@ -505,6 +503,27 @@ svn_stringbuf_chop(svn_stringbuf_t *str,
   str->data[str->len] = '\0';
 }
 
+void
+svn_stringbuf_leftchop(svn_stringbuf_t *str, apr_size_t nbytes)
+{
+  if (str->len == 0)
+    return;
+
+  if (nbytes >= str->len)
+    {
+      str->len = 0;
+      *str->data = '\0';
+    }
+  else
+    {
+      /* Note: This will irretrievably waste nbytes of space in the
+         stringbuf's pool, but unlike the alternative of memmoving the
+         data, it's a constant-time operation. */
+      str->data += nbytes;
+      str->len -= nbytes;
+      str->blocksize -= nbytes;
+    }
+}
 
 svn_boolean_t
 svn_stringbuf_isempty(const svn_stringbuf_t *str)
@@ -723,6 +742,71 @@ svn_stringbuf_replace(svn_stringbuf_t *s
 }
 
 
+apr_size_t
+svn_stringbuf_replace_all(svn_stringbuf_t *str,
+                          const char *to_find,
+                          const char *replacement)
+{
+  apr_size_t replacements = 0;
+
+  apr_size_t current = 0;
+  apr_size_t original_length = str->len;
+
+  apr_size_t to_copy;
+  apr_size_t to_find_len;
+  apr_size_t replacement_len;
+  apr_size_t new_length;
+
+  /* Early exit. */
+  const char *pos = strstr(str->data, to_find);
+  if (pos == NULL)
+    return 0;
+
+  to_find_len = strlen(to_find);
+  replacement_len = strlen(replacement);
+
+  /* We will store the new contents behind the NUL terminator of the current
+   * data and track the total length in STR->LEN to make the reallocation
+   * code preserve both bits.  However, we need to keep the NUL between them
+   * to make strstr stop at that boundary. */
+  ++str->len;
+
+  /* Find all occurrences of TO_FIND, copy the bits in between to the target,
+   * separated by REPLACEMENT. */
+  for ( ; pos; pos = strstr(str->data + current, to_find), ++replacements)
+    {
+      to_copy = pos - str->data - current;
+      svn_stringbuf_ensure(str, str->len + to_copy + replacement_len);
+
+      if (to_copy)
+        memcpy(str->data + str->len, str->data + current, to_copy);
+      current += to_copy + to_find_len;
+
+      str->len += to_copy;
+      memcpy(str->data + str->len, replacement, replacement_len);
+      str->len += replacement_len;
+    }
+
+  /* Copy remainder. */
+  to_copy = original_length - current;
+  if (to_copy)
+    {
+      svn_stringbuf_ensure(str, str->len + to_copy);
+      memcpy(str->data + str->len, str->data + current, to_copy);
+      str->len += to_copy;
+    }
+
+  /* Move new contents to the start of the buffer and terminate it. */
+  new_length = str->len - original_length - 1;
+  memmove(str->data, str->data + original_length + 1, new_length);
+  str->len = new_length;
+  str->data[new_length] = 0;
+
+  /* Done. */
+  return replacements;
+}
+
+
 svn_stringbuf_t *
 svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool)
 {
@@ -751,13 +835,18 @@ svn_stringbuf_first_non_whitespace(const
 void
 svn_stringbuf_strip_whitespace(svn_stringbuf_t *str)
 {
-  /* Find first non-whitespace character */
-  apr_size_t offset = svn_stringbuf_first_non_whitespace(str);
-
-  /* Go ahead!  Waste some RAM, we've got pools! :)  */
-  str->data += offset;
-  str->len -= offset;
-  str->blocksize -= offset;
+  /* Skip (hide) whitespace at the beginning of the string. */
+  if (svn_ctype_isspace(str->data[0]))
+    {
+      /* Find first non-whitespace character */
+      apr_size_t offset = string_first_non_whitespace(str->data + 1,
+                                                      str->len - 1) + 1;
+
+      /* Go ahead!  Waste some RAM, we've got pools! :)  */
+      str->data += offset;
+      str->len -= offset;
+      str->blocksize -= offset;
+    }
 
   /* Now that we've trimmed the front, trim the end, wasting more RAM. */
   while ((str->len > 0) && svn_ctype_isspace(str->data[str->len - 1]))

Modified: subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c Sun Jan  1 10:43:40 2017
@@ -154,7 +154,7 @@ canonicalize_access_file(const char *acc
     }
 
   /* We don't canonicalize repos relative urls since they get
-   * canonicalized before calling svn_repos_authz_read2() when they
+   * canonicalized before calling svn_repos_authz_read3() when they
    * are resolved. */
 
   return access_file;
@@ -472,10 +472,10 @@ get_access_conf(request_rec *r, authz_sv
   access_conf = user_data;
   if (access_conf == NULL)
     {
-
-      svn_err = svn_repos_authz_read2(&access_conf, access_file,
-                                      groups_file, TRUE,
-                                      r->connection->pool);
+      svn_err = svn_repos_authz_read3(&access_conf, access_file,
+                                      groups_file, TRUE, NULL,
+                                      r->connection->pool,
+                                      scratch_pool);
 
       if (svn_err)
         {

Modified: subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c Sun Jan  1 10:43:40 2017
@@ -137,6 +137,15 @@ init(apr_pool_t *p, apr_pool_t *plog, ap
       return HTTP_INTERNAL_SERVER_ERROR;
     }
 
+  serr = svn_repos_authz_initialize(p);
+  if (serr)
+    {
+      ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err, p,
+               "mod_dav_svn: error calling svn_repos_authz_initialize: '%s'",
+                    serr->message ? serr->message : "(no more info)");
+      return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
   /* This returns void, so we can't check for error. */
   conf = ap_get_module_config(s->module_config, &dav_svn_module);
   svn_utf_initialize2(conf->use_utf8, p);

Modified: subversion/trunk/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/serve.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/serve.c (original)
+++ subversion/trunk/subversion/svnserve/serve.c Sun Jan  1 10:43:40 2017
@@ -226,8 +226,8 @@ load_pwdb_config(repository_t *repositor
       pwdb_path = svn_dirent_internal_style(pwdb_path, pool);
       pwdb_path = svn_dirent_join(repository->base, pwdb_path, pool);
 
-      err = svn_repos__config_pool_get(&repository->pwdb, NULL, config_pool,
-                                       pwdb_path, TRUE, FALSE,
+      err = svn_repos__config_pool_get(&repository->pwdb, config_pool,
+                                       pwdb_path, TRUE,
                                        repository->repos, pool);
       if (err)
         {
@@ -285,8 +285,8 @@ canonicalize_access_file(const char **ac
   return SVN_NO_ERROR;
 }
 
-/* Load the authz database for the listening server through AUTHZ_POOL
-   based on the entries in the SERVER struct.
+/* Load the authz database for the listening server based on the entries
+   in the SERVER struct.
 
    SERVER and CONN must not be NULL. The real errors will be logged with
    SERVER and CONN but return generic errors to the client. */
@@ -294,7 +294,6 @@ static svn_error_t *
 load_authz_config(repository_t *repository,
                   const char *repos_root,
                   svn_config_t *cfg,
-                  svn_repos__authz_pool_t *authz_pool,
                   apr_pool_t *pool)
 {
   const char *authzdb_path;
@@ -322,9 +321,9 @@ load_authz_config(repository_t *reposito
                                        repos_root, pool);
 
       if (!err)
-        err = svn_repos__authz_pool_get(&repository->authzdb, authz_pool,
-                                        authzdb_path, groupsdb_path, TRUE,
-                                        repository->repos, pool);
+        err = svn_repos_authz_read3(&repository->authzdb, authzdb_path,
+                                    groupsdb_path, TRUE, repository->repos,
+                                    pool, pool);
 
       if (err)
         return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL);
@@ -446,7 +445,7 @@ static svn_error_t *authz_check_access(s
      absolute path. Passing such a malformed path to the authz
      routines throws them into an infinite loop and makes them miss
      ACLs. */
-  if (path)
+  if (path && *path != '/')
     path = svn_fspath__canonicalize(path, pool);
 
   /* If we have a username, and we've not yet used it + any username
@@ -3739,8 +3738,7 @@ repos_path_valid(const char *path)
  * and fs_path fields of REPOSITORY.  VHOST and READ_ONLY flags are the
  * same as in the server baton.
  *
- * CONFIG_POOL and AUTHZ_POOL shall be used to load any object of the
- * respective type.
+ * CONFIG_POOL shall be used to load config objects.
  *
  * Use SCRATCH_POOL for temporary allocations.
  *
@@ -3753,7 +3751,6 @@ find_repos(const char *url,
            svn_config_t *cfg,
            repository_t *repository,
            svn_repos__config_pool_t *config_pool,
-           svn_repos__authz_pool_t *authz_pool,
            apr_hash_t *fs_config,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool)
@@ -3822,16 +3819,16 @@ find_repos(const char *url,
     {
       repository->base = svn_repos_conf_dir(repository->repos, result_pool);
 
-      SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+      SVN_ERR(svn_repos__config_pool_get(&cfg, config_pool,
                                          svn_repos_svnserve_conf
                                             (repository->repos, result_pool),
-                                         FALSE, FALSE, repository->repos,
+                                         FALSE, repository->repos,
                                          result_pool));
     }
 
   SVN_ERR(load_pwdb_config(repository, cfg, config_pool, result_pool));
   SVN_ERR(load_authz_config(repository, repository->repos_root, cfg,
-                            authz_pool, result_pool));
+                            result_pool));
 
 #ifdef SVN_HAVE_SASL
     {
@@ -4165,7 +4162,7 @@ construct_server_baton(server_baton_t **
   err = handle_config_error(find_repos(client_url, params->root, b->vhost,
                                        b->read_only, params->cfg,
                                        b->repository, params->config_pool,
-                                       params->authz_pool, params->fs_config,
+                                       params->fs_config,
                                        conn_pool, scratch_pool),
                             b);
   if (!err)

Modified: subversion/trunk/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/server.h?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/server.h (original)
+++ subversion/trunk/subversion/svnserve/server.h Sun Jan  1 10:43:40 2017
@@ -127,9 +127,6 @@ typedef struct serve_params_t {
   /* all configurations should be opened through this factory */
   svn_repos__config_pool_t *config_pool;
 
-  /* all authz data should be opened through this factory */
-  svn_repos__authz_pool_t *authz_pool;
-
   /* The FS configuration to be applied to all repositories.
      It mainly contains things like cache settings. */
   apr_hash_t *fs_config;

Modified: subversion/trunk/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/svnserve.c?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/svnserve.c (original)
+++ subversion/trunk/subversion/svnserve/svnserve.c Sun Jan  1 10:43:40 2017
@@ -752,6 +752,9 @@ sub_main(int *exit_code, int argc, const
   /* Initialize the FS library. */
   SVN_ERR(svn_fs_initialize(pool));
 
+  /* Initialize the efficient Authz support. */
+  SVN_ERR(svn_repos_authz_initialize(pool));
+
   SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
 
   params.root = "/";
@@ -763,7 +766,6 @@ sub_main(int *exit_code, int argc, const
   params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
   params.logger = NULL;
   params.config_pool = NULL;
-  params.authz_pool = NULL;
   params.fs_config = NULL;
   params.vhost = FALSE;
   params.username_case = CASE_ASIS;
@@ -1046,10 +1048,6 @@ sub_main(int *exit_code, int argc, const
   SVN_ERR(svn_repos__config_pool_create(&params.config_pool,
                                         is_multi_threaded,
                                         pool));
-  SVN_ERR(svn_repos__authz_pool_create(&params.authz_pool,
-                                       params.config_pool,
-                                       is_multi_threaded,
-                                       pool));
 
   /* If a configuration file is specified, load it and any referenced
    * password and authorization files. */
@@ -1057,11 +1055,10 @@ sub_main(int *exit_code, int argc, const
     {
       params.base = svn_dirent_dirname(config_filename, pool);
 
-      SVN_ERR(svn_repos__config_pool_get(&params.cfg, NULL,
+      SVN_ERR(svn_repos__config_pool_get(&params.cfg,
                                          params.config_pool,
                                          config_filename,
                                          TRUE, /* must_exist */
-                                         FALSE, /* names_case_sensitive */
                                          NULL,
                                          pool));
     }

Modified: subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py?rev=1776832&r1=1776831&r2=1776832&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py Sun Jan  1 10:43:40 2017
@@ -590,7 +590,7 @@ def svnauthz_accessof_is_file_test(sbox)
   svntest.main.file_append(authz_path, "x\n")
   # Check that --is returns 1 when the syntax is invalid with a file..
   expected_out = svntest.verify.RegexOutput(
-      ".*Error while parsing config file:",
+      ".*Error while parsing authz file:",
       match_all=False
   )
   svntest.actions.run_and_verify_svnauthz(None, expected_out, 1, False,



Mime
View raw message