You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/11/27 08:53:35 UTC
svn commit: r1545955 [6/15] - in /subversion/branches/fsfs-improvements: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/server-side/ contrib/server-side/svncutter/ notes/
subversion/bindings/javahl/native/ s...
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c Wed Nov 27 07:53:29 2013
@@ -24,45 +24,42 @@
-#include <assert.h>
-
#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_atomic.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"
-/* A reference counting wrapper around a parsed svn_config_t* instance. All
- * data in CFG is expanded (to make it thread-safe) and considered read-only.
+/* 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_ref_t
+typedef struct config_object_t
{
- /* reference to the parent container */
- svn_repos__config_pool_t *config_pool;
-
/* 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 */
- svn_config_t *cfg;
+ /* 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;
- /* private pool. This instance and its other members got allocated in it.
- * Will be destroyed when this instance is cleaned up. */
- apr_pool_t *pool;
-
- /* Number of references to this data struct */
- volatile svn_atomic_t ref_count;
-} config_ref_t;
+ /* 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
@@ -71,8 +68,8 @@ typedef struct config_ref_t
* the repository.
*
* As this is only an optimization and may create many entries in
- * svn_config_pool__t's IN_REPO_HASH_POOL index, we clean them up once in
- * a while.
+ * 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
{
@@ -90,10 +87,8 @@ typedef struct in_repo_config_t
} in_repo_config_t;
-/* Core data structure. All access to it must be serialized using MUTEX.
- *
- * CONFIGS maps a SHA1 checksum of the config text to the config_ref_t with
- * the parsed configuration in it.
+/* 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
@@ -102,240 +97,105 @@ typedef struct in_repo_config_t
* 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. We use various pools to
- * ensure that we can release unused memory for each data structure:
- *
- * - every config_ref_t uses its own pool
- * (gets destroyed when config is removed from cache)
- * - CONFIGS_HASH_POOL is used for configs only
- * - IN_REPO_HASH_POOL is used for IN_REPO_CONFIGS and the in_repo_config_t
- * structure in it
- *
- * References handed out to callers must remain valid until released. In
- * that case, cleaning up the config pool will only set READY_FOR_CLEANUP
- * and the last reference being returned will actually trigger the
- * destruction.
+ * be cleaned up when the hash is about to grow.
*/
struct svn_repos__config_pool_t
{
- /* serialization object for all non-atomic data in this struct */
- svn_mutex__t *mutex;
-
- /* set to TRUE when pool passed to svn_config_pool__create() gets cleaned
- * up. When set, the last config reference released must also destroy
- * this config pool object. */
- volatile svn_atomic_t ready_for_cleanup;
-
- /* SHA1 -> config_ref_t* mapping */
- apr_hash_t *configs;
-
- /* number of entries in CONFIGS with a reference count > 0 */
- volatile svn_atomic_t used_config_count;
+ 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;
- /* the root pool owning this structure */
- apr_pool_t *root_pool;
-
- /* allocate the CONFIGS index here */
- apr_pool_t *configs_hash_pool;
-
/* allocate the IN_REPO_CONFIGS index and in_repo_config_t here */
apr_pool_t *in_repo_hash_pool;
};
-/* Destructor function for the whole config pool.
+/* 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 apr_status_t
-destroy_config_pool(svn_repos__config_pool_t *config_pool)
+static void *
+getter(void *object,
+ void *baton,
+ apr_pool_t *pool)
{
- svn_mutex__lock(config_pool->mutex);
-
- /* there should be no outstanding references to any config in this pool */
- assert(svn_atomic_read(&config_pool->used_config_count) == 0);
-
- /* make future attempts to access this pool cause definitive segfaults */
- config_pool->configs = NULL;
- config_pool->in_repo_configs = NULL;
+ config_object_t *wrapper = object;
+ svn_boolean_t *case_sensitive = baton;
+ svn_config_t *config = *case_sensitive ? wrapper->cs_cfg : wrapper->ci_cfg;
- /* This is the actual point of destruction. */
- /* Destroying the pool will also release the lock. */
- svn_pool_destroy(config_pool->root_pool);
-
- return APR_SUCCESS;
+ /* we need to duplicate the root structure as it contains temp. buffers */
+ return config ? svn_config__shallow_copy(config, pool) : NULL;
}
-/* Pool cleanup function for the whole config pool. Actual destruction will
- * be deferred until no configurations are left in use.
+/* Return a memory buffer structure allocated in POOL and containing the
+ * data from CHECKSUM.
*/
-static apr_status_t
-config_pool_cleanup(void *baton)
+static svn_membuf_t *
+checksum_as_key(svn_checksum_t *checksum,
+ apr_pool_t *pool)
{
- svn_repos__config_pool_t *config_pool = baton;
+ svn_membuf_t *result = apr_pcalloc(pool, sizeof(*result));
+ apr_size_t size = svn_checksum_size(checksum);
- svn_atomic_set(&config_pool->ready_for_cleanup, TRUE);
- if (svn_atomic_read(&config_pool->used_config_count) == 0)
- {
- /* Attempts to get a configuration from a pool that whose cleanup has
- * already started is illegal.
- * So, used_config_count must not increase again.
- */
- destroy_config_pool(config_pool);
- }
+ svn_membuf__create(result, size, pool);
+ result->size = size; /* exact length is required! */
+ memcpy(result->data, checksum->digest, size);
- return APR_SUCCESS;
+ return result;
}
-/* Cleanup function called when a config_ref_t gets released.
- */
-static apr_status_t
-config_ref_cleanup(void *baton)
-{
- config_ref_t *config = baton;
- svn_repos__config_pool_t *config_pool = config->config_pool;
-
- /* Maintain reference counters and handle object cleanup */
- if ( svn_atomic_dec(&config->ref_count) == 1
- && svn_atomic_dec(&config_pool->used_config_count) == 1
- && svn_atomic_read(&config_pool->ready_for_cleanup) == TRUE)
- {
- /* There cannot be any future references to a config in this pool.
- * So, we are the last one and need to finally clean it up.
- */
- destroy_config_pool(config_pool);
- }
-
- return APR_SUCCESS;
-}
-
-/* Return an automatic reference to the CFG member in CONFIG that will be
- * released when POOL gets cleaned up.
- */
-static svn_config_t *
-return_config_ref(config_ref_t *config,
- apr_pool_t *pool)
-{
- if (svn_atomic_inc(&config->ref_count) == 0)
- svn_atomic_inc(&config->config_pool->used_config_count);
- apr_pool_cleanup_register(pool, config, config_ref_cleanup,
- apr_pool_cleanup_null);
- return config->cfg;
-}
-
-/* Set *CFG to the configuration with a parsed textual matching CHECKSUM.
- * Set *CFG to NULL if no such config can be found in CONFIG_POOL.
- *
- * RESULT_POOL determines the lifetime of the returned reference.
- *
- * Requires external serialization on CONFIG_POOL.
+/* 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 *
-config_by_checksum(svn_config_t **cfg,
- svn_repos__config_pool_t *config_pool,
- svn_checksum_t *checksum,
- apr_pool_t *result_pool)
-{
- config_ref_t *config_ref = apr_hash_get(config_pool->configs,
- checksum->digest,
- svn_checksum_size(checksum));
- *cfg = config_ref ? return_config_ref(config_ref, result_pool) : NULL;
-
- return SVN_NO_ERROR;
-}
+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;
-/* Re-allocate CONFIGS in CONFIG_POOL and remove all unused configurations
- * to minimize memory consumption.
- *
- * Requires external serialization on CONFIG_POOL.
- */
-static void
-remove_unused_configs(svn_repos__config_pool_t *config_pool)
-{
- apr_pool_t *new_pool = svn_pool_create(config_pool->root_pool);
- apr_hash_t *new_hash = svn_hash__make(new_pool);
-
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(config_pool->configs_hash_pool,
- config_pool->configs);
- hi != NULL;
- hi = apr_hash_next(hi))
+ /* Maybe, we created a variant with different case sensitivity? */
+ if (*case_sensitive && target_cfg->cs_cfg == NULL)
{
- config_ref_t *config_ref = svn__apr_hash_index_val(hi);
- if (config_ref->ref_count == 0)
- svn_pool_destroy(config_ref->pool);
- else
- apr_hash_set(new_hash, config_ref->key->digest,
- svn_checksum_size(config_ref->key), config_ref);
+ SVN_ERR(svn_config_dup(&target_cfg->cs_cfg, source_cfg->cs_cfg, pool));
+ svn_config__set_read_only(target_cfg->cs_cfg, pool);
}
-
- svn_pool_destroy(config_pool->configs_hash_pool);
- config_pool->configs = new_hash;
- config_pool->configs_hash_pool = new_pool;
-}
-
-/* Cache config_ref* in CONFIG_POOL and return a reference to it in *CFG.
- * RESULT_POOL determines the lifetime of that reference.
- *
- * Requires external serialization on CONFIG_POOL.
- */
-static svn_error_t *
-config_add(svn_config_t **cfg,
- svn_repos__config_pool_t *config_pool,
- config_ref_t *config_ref,
- apr_pool_t *result_pool)
-{
- config_ref_t *config = apr_hash_get(config_ref->config_pool->configs,
- config_ref->key->digest,
- svn_checksum_size(config_ref->key));
- if (config)
- {
- /* entry already exists (e.g. race condition)
- * 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(config_ref->pool);
- config_ref = config;
- }
- else
+ else if (!*case_sensitive && target_cfg->ci_cfg == NULL)
{
- /* Release unused configurations if there are relatively frequent. */
- if ( config_pool->used_config_count * 2 + 4
- < apr_hash_count(config_pool->configs))
- {
- remove_unused_configs(config_pool);
- }
-
- /* add new index entry */
- apr_hash_set(config_ref->config_pool->configs,
- config_ref->key->digest,
- svn_checksum_size(config_ref->key),
- config_ref);
+ SVN_ERR(svn_config_dup(&target_cfg->ci_cfg, source_cfg->ci_cfg, pool));
+ svn_config__set_read_only(target_cfg->ci_cfg, pool);
}
- *cfg = return_config_ref(config_ref, result_pool);
-
return SVN_NO_ERROR;
}
-/* Set *CFG to the configuration passed in as text in CONTENTS. If no such
- * configuration exists in CONFIG_POOL, yet, parse CONTENTS and cache the
- * result.
- *
+/* 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.
+ *
* 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_ref_t *config_ref;
+ config_object_t *config_object;
apr_pool_t *cfg_pool;
/* calculate SHA1 over the whole file contents */
@@ -345,46 +205,36 @@ auto_parse(svn_config_t **cfg,
&checksum, NULL, svn_checksum_sha1, TRUE, scratch_pool)));
/* return reference to suitable config object if that already exists */
- *cfg = NULL;
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_by_checksum(cfg, config_pool, checksum,
- result_pool));
-
+ *key = checksum_as_key(checksum, scratch_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_pool_create(svn_object_pool__pool(config_pool->object_pool));
- /* the following is thread-safe because the allocator is thread-safe */
- cfg_pool = svn_pool_create(config_pool->root_pool);
-
- config_ref = apr_pcalloc(cfg_pool, sizeof(*config_ref));
- config_ref->config_pool = config_pool;
- config_ref->key = svn_checksum_dup(checksum, cfg_pool);
- config_ref->pool = cfg_pool;
- config_ref->ref_count = 0;
+ config_object = apr_pcalloc(cfg_pool, sizeof(*config_object));
- SVN_ERR(svn_config_parse(&config_ref->cfg,
+ SVN_ERR(svn_config_parse(case_sensitive ? &config_object->cs_cfg
+ : &config_object->ci_cfg,
svn_stream_from_stringbuf(contents, scratch_pool),
- TRUE, TRUE, cfg_pool));
+ case_sensitive, case_sensitive, cfg_pool));
/* switch config data to r/o mode to guarantee thread-safe access */
- svn_config__set_read_only(config_ref->cfg, cfg_pool);
+ 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_MUTEX__WITH_LOCK(config_pool->mutex,
- config_add(cfg, config_pool, config_ref, result_pool));
+ 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;
}
-/* Set *CFG to the configuration stored in URL@HEAD and cache it in
- * CONFIG_POOL.
- *
- * RESULT_POOL determines the lifetime of the returned reference and
- * SCRATCH_POOL is being used for temporary allocations.
- *
- * Requires external serialization on CONFIG_POOL.
+/* Store a URL@REVISION to CHECKSUM, REPOS_ROOT in CONFIG_POOL.
*/
static svn_error_t *
add_checksum(svn_repos__config_pool_t *config_pool,
@@ -396,7 +246,7 @@ add_checksum(svn_repos__config_pool_t *c
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);
+ url, path_len);
if (config)
{
/* update the existing entry */
@@ -412,7 +262,7 @@ add_checksum(svn_repos__config_pool_t *c
{
/* insert a new entry.
* Limit memory consumption by cyclically clearing pool and hash. */
- if (2 * apr_hash_count(config_pool->configs)
+ if (2 * svn_object_pool__count(config_pool->object_pool)
< apr_hash_count(config_pool->in_repo_configs))
{
svn_pool_clear(pool);
@@ -434,19 +284,24 @@ add_checksum(svn_repos__config_pool_t *c
}
/* Set *CFG to the configuration stored in URL@HEAD and cache it in
- * CONFIG_POOL. ### Always returns a NULL CFG.
+ * 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;
+ svn_repos_t *repos = NULL;
svn_fs_t *fs;
svn_fs_root_t *root;
svn_revnum_t youngest_rev;
@@ -461,11 +316,29 @@ find_repos_config(svn_config_t **cfg,
*cfg = NULL;
SVN_ERR(svn_uri_get_dirent_from_file_url(&dirent, url, scratch_pool));
- /* Search for a repository in the full path. */
- repos_root_dirent = svn_repos_find_root_path(dirent, 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;
+ }
- /* Attempt to open a repository at repos_root_dirent. */
- SVN_ERR(svn_repos_open2(&repos, repos_root_dirent, NULL, scratch_pool));
+ /* 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_open2(&repos, repos_root_dirent, NULL, scratch_pool));
+ }
fs_path = &dirent[strlen(repos_root_dirent)];
@@ -480,9 +353,11 @@ find_repos_config(svn_config_t **cfg,
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root, fs_path,
FALSE, scratch_pool));
if (checksum)
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_by_checksum(cfg, config_pool, checksum,
- result_pool));
+ {
+ *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? */
if (!*cfg)
@@ -500,64 +375,57 @@ find_repos_config(svn_config_t **cfg,
(apr_size_t)length, scratch_pool));
/* handle it like ordinary file contents and cache it */
- SVN_ERR(auto_parse(cfg, config_pool, contents, result_pool,
- scratch_pool));
+ SVN_ERR(auto_parse(cfg, key, config_pool, contents, case_sensitive,
+ result_pool, scratch_pool));
}
/* store the (path,rev) -> checksum mapping as well */
if (*cfg)
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
+ 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;
}
-/* Set *CFG to the configuration cached in CONFIG_POOL for URL. If no
- * suitable config has been cached or if it is potentially outdated, set
- * *CFG to NULL.
- *
- * RESULT_POOL determines the lifetime of the returned reference and
- * SCRATCH_POOL is being used for temporary allocations.
+/* 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 *
-config_by_url(svn_config_t **cfg,
- svn_repos__config_pool_t *config_pool,
- const char *url,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+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;
- config_ref_t *config_ref = NULL;
svn_stringbuf_t *contents;
apr_int64_t current;
/* hash lookup url -> sha1 -> config */
- in_repo_config_t *config = apr_hash_get(config_pool->in_repo_configs,
- url, APR_HASH_KEY_STRING);
- *cfg = 0;
- if (config)
- config_ref = apr_hash_get(config_pool->configs,
- config->key->digest,
- svn_checksum_size(config->key));
- if (!config_ref)
+ in_repo_config_t *config = svn_hash_gets(config_pool->in_repo_configs, url);
+ *key = NULL;
+ if (!config)
return SVN_NO_ERROR;
- /* found *some* configuration.
+ /* 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", scratch_pool),
- scratch_pool);
+ "db/current", pool),
+ pool);
if (!err)
err = svn_cstring_atoi64(¤t, contents->data);
if (err)
svn_error_clear(err);
else if (current == config->revision)
- *cfg = return_config_ref(config_ref, result_pool);
+ *key = checksum_as_key(config->key, pool);
return SVN_NO_ERROR;
}
@@ -566,27 +434,25 @@ config_by_url(svn_config_t **cfg,
svn_error_t *
svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
+ svn_boolean_t thread_safe,
apr_pool_t *pool)
{
- /* our allocator must be thread-safe */
- apr_pool_t *root_pool
- = apr_allocator_owner_get(svn_pool_create_allocator(TRUE));
+ svn_repos__config_pool_t *result;
+ svn_object_pool__t *object_pool;
+ apr_pool_t *root_pool;
+
+ SVN_ERR(svn_object_pool__create(&object_pool, getter, setter,
+ 4, APR_UINT32_MAX, TRUE, thread_safe,
+ pool));
+ root_pool = svn_object_pool__pool(object_pool);
/* construct the config pool in our private ROOT_POOL to survive POOL
* cleanup and to prevent threading issues with the allocator */
- svn_repos__config_pool_t *result = apr_pcalloc(pool, sizeof(*result));
- SVN_ERR(svn_mutex__init(&result->mutex, TRUE, root_pool));
+ result = apr_pcalloc(root_pool, sizeof(*result));
- result->root_pool = root_pool;
- result->configs_hash_pool = svn_pool_create(root_pool);
+ result->object_pool = object_pool;
result->in_repo_hash_pool = svn_pool_create(root_pool);
- result->configs = svn_hash__make(result->configs_hash_pool);
result->in_repo_configs = svn_hash__make(result->in_repo_hash_pool);
- result->ready_for_cleanup = FALSE;
-
- /* make sure we clean up nicely */
- apr_pool_cleanup_register(pool, result, config_pool_cleanup,
- apr_pool_cleanup_null);
*config_pool = result;
return SVN_NO_ERROR;
@@ -594,30 +460,51 @@ svn_repos__config_pool_create(svn_repos_
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);
+ /* make sure we always have a *KEY object */
+ svn_membuf_t *local_key = NULL;
+ if (key == NULL)
+ key = &local_key;
+ else
+ *key = NULL;
+
if (svn_path_is_url(path))
{
/* Read config file from repository.
* Attempt a quick lookup first. */
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_by_url(cfg, config_pool, path, pool,
- scratch_pool));
- if (cfg)
- return SVN_NO_ERROR;
+ 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, config_pool, path, pool, scratch_pool);
+ 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, TRUE, pool);
+ err = svn_repos__retrieve_config(cfg, path, must_exist,
+ case_sensitive, pool);
}
}
else
@@ -629,12 +516,14 @@ svn_repos__config_pool_get(svn_config_t
{
/* let the standard implementation handle all the difficult cases */
svn_error_clear(err);
- err = svn_config_read3(cfg, path, TRUE, TRUE, TRUE, pool);
+ err = svn_config_read3(cfg, path, must_exist, case_sensitive,
+ case_sensitive, pool);
}
else
{
/* parsing and caching will always succeed */
- err = auto_parse(cfg, config_pool, contents, pool, scratch_pool);
+ err = auto_parse(cfg, key, config_pool, contents, case_sensitive,
+ pool, scratch_pool);
}
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c Wed Nov 27 07:53:29 2013
@@ -763,6 +763,7 @@ svn_repos_verify_fs2(svn_repos_t *repos,
start_rev,
end_rev,
FALSE,
+ FALSE,
notify_func,
notify_baton,
cancel_func,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c Wed Nov 27 07:53:29 2013
@@ -38,6 +38,7 @@
#include "private/svn_mergeinfo_private.h"
#include "private/svn_fs_private.h"
+#include "private/svn_utf_private.h"
#include "private/svn_cache.h"
#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
@@ -134,9 +135,9 @@ tracker_create(svn_revnum_t revision,
* we encounter a new tree change.
*/
static void
-tracker__trim(path_tracker_t *tracker,
- const char *path,
- svn_boolean_t allow_exact_match)
+tracker_trim(path_tracker_t *tracker,
+ const char *path,
+ svn_boolean_t allow_exact_match)
{
/* remove everything that is unrelated to PATH.
Note that TRACKER->STACK is depth-ordered,
@@ -176,7 +177,7 @@ tracker_lookup(const char **orig_path,
const char *path,
apr_pool_t *pool)
{
- tracker__trim(tracker, path, TRUE);
+ tracker_trim(tracker, path, TRUE);
if (tracker->depth == 0)
{
/* no tree changes -> paths are the same as in the previous rev. */
@@ -230,11 +231,11 @@ tracker_lookup(const char **orig_path,
will have undefined values.
*/
static path_tracker_entry_t *
-tracker__add_entry(path_tracker_t *tracker,
- const char *path)
+tracker_add_entry(path_tracker_t *tracker,
+ const char *path)
{
path_tracker_entry_t *entry;
- tracker__trim(tracker, path, FALSE);
+ tracker_trim(tracker, path, FALSE);
if (tracker->depth == tracker->stack->nelts)
{
@@ -263,7 +264,7 @@ tracker_path_copy(path_tracker_t *tracke
const char *copyfrom_path,
svn_revnum_t copyfrom_rev)
{
- path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+ path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
svn_stringbuf_set(entry->copyfrom_path, copyfrom_path);
entry->copyfrom_rev = copyfrom_rev;
@@ -276,7 +277,7 @@ static void
tracker_path_add(path_tracker_t *tracker,
const char *path)
{
- path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+ path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
svn_stringbuf_setempty(entry->copyfrom_path);
entry->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -301,7 +302,7 @@ static void
tracker_path_delete(path_tracker_t *tracker,
const char *path)
{
- path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+ path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
svn_stringbuf_setempty(entry->copyfrom_path);
entry->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -380,6 +381,9 @@ struct edit_baton
/* True if this "dump" is in fact a verify. */
svn_boolean_t verify;
+ /* True if checking UCS normalization during a verify. */
+ svn_boolean_t check_ucs_norm;
+
/* The first revision dumped in this dumpstream. */
svn_revnum_t oldest_dumped_rev;
@@ -434,6 +438,12 @@ struct dir_baton
really, they're all within this directory.) */
apr_hash_t *deleted_entries;
+ /* A flag indicating that new entries have been added to this
+ directory in this revision. Used to optimize detection of UCS
+ representation collisions; we will only check for that in
+ revisions where new names appear in the directory. */
+ svn_boolean_t check_name_collision;
+
/* pool to be used for deleting the hash items */
apr_pool_t *pool;
};
@@ -486,6 +496,7 @@ make_dir_baton(const char *path,
new_db->added = added;
new_db->written_out = FALSE;
new_db->deleted_entries = apr_hash_make(pool);
+ new_db->check_name_collision = FALSE;
new_db->pool = pool;
return new_db;
@@ -581,6 +592,104 @@ node_must_not_exist(struct edit_baton *e
return SVN_NO_ERROR;
}
+
+static svn_error_t *
+check_ucs_normalization(const char *path,
+ svn_node_kind_t kind,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ const char *const name = svn_relpath_basename(path, scratch_pool);
+ if (!svn_utf__is_normalized(name, scratch_pool))
+ {
+ svn_repos_notify_t *const notify =
+ svn_repos_notify_create(svn_repos_notify_warning, scratch_pool);
+ notify->warning = svn_repos_notify_warning_denormalized_name;
+ switch (kind)
+ {
+ case svn_node_dir:
+ notify->warning_str = apr_psprintf(
+ scratch_pool, _("Denormalized directory name '%s'"), path);
+ break;
+ case svn_node_file:
+ notify->warning_str = apr_psprintf(
+ scratch_pool, _("Denormalized file name '%s'"), path);
+ break;
+ default:
+ notify->warning_str = apr_psprintf(
+ scratch_pool, _("Denormalized entry name '%s'"), path);
+ }
+ notify_func(notify_baton, notify, scratch_pool);
+ }
+ return SVN_NO_ERROR;
+}
+
+
+/* Baton used by the check_mergeinfo_normalization hash iterator. */
+struct check_mergeinfo_normalization_baton
+{
+ const char* path;
+ apr_hash_t *normalized;
+ svn_membuf_t buffer;
+ svn_repos_notify_func_t notify_func;
+ void *notify_baton;
+};
+
+/* Hash iterator that verifies normalization and collision of paths in
+ an svn:mergeinfo property. */
+static svn_error_t *
+check_mergeinfo_normalization(void *baton, const void *key, apr_ssize_t klen,
+ void *val, apr_pool_t *pool)
+{
+ static const char unique[] = "unique";
+ static const char collision[] = "collision";
+
+ struct check_mergeinfo_normalization_baton *const check_baton = baton;
+
+ const char *const path = key;
+ const char *normpath;
+ const char *found;
+
+ SVN_ERR(svn_utf__normalize(&normpath, path, klen, &check_baton->buffer));
+
+ found = svn_hash_gets(check_baton->normalized, normpath);
+ if (!found)
+ {
+ if (0 != strcmp(path, normpath))
+ {
+ /* Report denormlized mergeinfo path */
+ svn_repos_notify_t *const notify =
+ svn_repos_notify_create(svn_repos_notify_warning, pool);
+ notify->warning = svn_repos_notify_warning_denormalized_mergeinfo;
+ notify->warning_str = apr_psprintf(
+ pool, _("Denormalized path '%s' in %s property of '%s'"),
+ path, SVN_PROP_MERGEINFO, check_baton->path);
+ check_baton->notify_func(check_baton->notify_baton, notify, pool);
+ }
+ svn_hash_sets(check_baton->normalized,
+ apr_pstrdup(pool, normpath), unique);
+ }
+ else if (found == collision)
+ /* Skip already reported collision */;
+ else
+ {
+ /* Report path collision in mergeinfo */
+ svn_repos_notify_t *const notify =
+ svn_repos_notify_create(svn_repos_notify_warning, pool);
+ notify->warning = svn_repos_notify_warning_mergeinfo_collision;
+ notify->warning_str = apr_psprintf(
+ pool, _("Duplicate representation of path '%s'"
+ " in %s property of '%s'"),
+ normpath, SVN_PROP_MERGEINFO, check_baton->path);
+ check_baton->notify_func(check_baton->notify_baton, notify, pool);
+ svn_hash_sets(check_baton->normalized,
+ apr_pstrdup(pool, normpath), collision);
+ }
+ return SVN_NO_ERROR;
+}
+
+
/* This helper is the main "meat" of the editor -- it does all the
work of writing a node record.
@@ -926,6 +1035,33 @@ dump_node(struct edit_baton *eb,
}
}
+ /* If we're checking UCS normalization, also parse any changed
+ mergeinfo and warn about denormalized paths and name
+ collisions there. */
+ if (eb->verify && eb->check_ucs_norm && eb->notify_func)
+ {
+ /* N.B.: This hash lookup happens only once; the conditions
+ for verifying historic mergeinfo references and checking
+ UCS normalization are mutually exclusive. */
+ svn_string_t *mergeinfo_str = svn_hash_gets(prophash,
+ SVN_PROP_MERGEINFO);
+ if (mergeinfo_str)
+ {
+ svn_mergeinfo_t mergeinfo;
+ struct check_mergeinfo_normalization_baton check_baton;
+ check_baton.path = path;
+ check_baton.normalized = apr_hash_make(pool);
+ svn_membuf__create(&check_baton.buffer, 0, pool);
+ check_baton.notify_func = eb->notify_func;
+ check_baton.notify_baton = eb->notify_baton;
+ SVN_ERR(svn_mergeinfo_parse(&mergeinfo,
+ mergeinfo_str->data, pool));
+ SVN_ERR(svn_iter_apr_hash(NULL, mergeinfo,
+ check_mergeinfo_normalization,
+ &check_baton, pool));
+ }
+ }
+
if (eb->use_deltas && compare_root)
{
/* Fetch the old property hash to diff against and output a header
@@ -1116,6 +1252,16 @@ add_directory(const char *path,
/* Delete the path, it's now been dumped. */
svn_hash_sets(pb->deleted_entries, path, NULL);
+ /* Check for UCS normalization and name clashes, but only if this is
+ actually a new name in the parent, not a replacement. */
+ if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
+ {
+ pb->check_name_collision = TRUE;
+ SVN_ERR(check_ucs_normalization(
+ path, svn_node_dir,
+ eb->notify_func, eb->notify_baton, pool));
+ }
+
new_db->written_out = TRUE;
*child_baton = new_db;
@@ -1215,6 +1361,16 @@ add_file(const char *path,
is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
pool));
+ /* Check for UCS normalization and name clashes, but only if this is
+ actually a new name in the parent, not a replacement. */
+ if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
+ {
+ pb->check_name_collision = TRUE;
+ SVN_ERR(check_ucs_normalization(
+ path, svn_node_file,
+ eb->notify_func, eb->notify_baton, pool));
+ }
+
if (val)
/* delete the path, it's now been dumped. */
svn_hash_sets(pb->deleted_entries, path, NULL);
@@ -1382,6 +1538,7 @@ get_dump_editor(const svn_delta_editor_t
svn_revnum_t oldest_dumped_rev,
svn_boolean_t use_deltas,
svn_boolean_t verify,
+ svn_boolean_t check_ucs_norm,
svn_cache__t *verified_dirents_cache,
apr_pool_t *pool)
{
@@ -1405,6 +1562,7 @@ get_dump_editor(const svn_delta_editor_t
eb->current_rev = to_rev;
eb->use_deltas = use_deltas;
eb->verify = verify;
+ eb->check_ucs_norm = check_ucs_norm;
eb->found_old_reference = found_old_reference;
eb->found_old_mergeinfo = found_old_mergeinfo;
eb->verified_dirents_cache = verified_dirents_cache;
@@ -1612,7 +1770,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
"", stream, &found_old_reference,
&found_old_mergeinfo, NULL,
notify_func, notify_baton,
- start_rev, use_deltas_for_rev, FALSE,
+ start_rev, use_deltas_for_rev, FALSE, FALSE,
NULL, subpool));
/* Drive the editor in one way or another. */
@@ -1790,9 +1948,59 @@ verify_directory_entry(void *baton, cons
return SVN_NO_ERROR;
}
+/* Baton used by the check_name_collision hash iterator. */
+struct check_name_collision_baton
+{
+ struct dir_baton *dir_baton;
+ apr_hash_t *normalized;
+ svn_membuf_t buffer;
+};
+
+/* Scan the directory and report all entry names that differ only in
+ Unicode character representaiton. */
+static svn_error_t *
+check_name_collision(void *baton, const void *key, apr_ssize_t klen,
+ void *val, apr_pool_t *pool)
+{
+ static const char unique[] = "unique";
+ static const char collision[] = "collision";
+
+ struct check_name_collision_baton *const check_baton = baton;
+ const char *name;
+ const char *found;
+
+ SVN_ERR(svn_utf__normalize(&name, key, klen, &check_baton->buffer));
+
+ found = svn_hash_gets(check_baton->normalized, name);
+ if (!found)
+ svn_hash_sets(check_baton->normalized,
+ apr_pstrdup(pool, name), unique);
+ else if (found == collision)
+ /* Skip already reported collision */;
+ else
+ {
+ struct dir_baton *const db = check_baton->dir_baton;
+ struct edit_baton *const eb = db->edit_baton;
+ svn_repos_notify_t *notify;
+ const char* normpath;
+
+ svn_hash_sets(check_baton->normalized,
+ apr_pstrdup(pool, name), collision);
+ SVN_ERR(svn_utf__normalize(
+ &normpath, svn_relpath_join(db->path, name, pool),
+ SVN_UTF__UNKNOWN_LENGTH, &check_baton->buffer));
+ notify = svn_repos_notify_create(svn_repos_notify_warning, pool);
+ notify->warning = svn_repos_notify_warning_name_collision;
+ notify->warning_str = apr_psprintf(
+ pool, _("Duplicate representation of path '%s'"), normpath);
+ eb->notify_func(eb->notify_baton, notify, pool);
+ }
+ return SVN_NO_ERROR;
+}
+
+
static svn_error_t *
-verify_close_directory(void *dir_baton,
- apr_pool_t *pool)
+verify_close_directory(void *dir_baton, apr_pool_t *pool)
{
struct dir_baton *db = dir_baton;
apr_hash_t *dirents;
@@ -1800,6 +2008,17 @@ verify_close_directory(void *dir_baton,
db->path, pool));
SVN_ERR(svn_iter_apr_hash(NULL, dirents, verify_directory_entry,
dir_baton, pool));
+
+ if (db->check_name_collision)
+ {
+ struct check_name_collision_baton check_baton;
+ check_baton.dir_baton = db;
+ check_baton.normalized = apr_hash_make(pool);
+ svn_membuf__create(&check_baton.buffer, 0, pool);
+ SVN_ERR(svn_iter_apr_hash(NULL, dirents, check_name_collision,
+ &check_baton, pool));
+ }
+
return close_directory(dir_baton, pool);
}
@@ -1828,6 +2047,7 @@ verify_one_revision(svn_fs_t *fs,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_revnum_t start_rev,
+ svn_boolean_t check_ucs_norm,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_cache__t *verified_dirents_cache,
@@ -1849,6 +2069,7 @@ verify_one_revision(svn_fs_t *fs,
notify_func, notify_baton,
start_rev,
FALSE, TRUE, /* use_deltas, verify */
+ check_ucs_norm,
verified_dirents_cache,
scratch_pool));
SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
@@ -1926,6 +2147,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
svn_boolean_t keep_going,
+ svn_boolean_t check_ucs_norm,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -2021,7 +2243,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
/* Wrapper function to catch the possible errors. */
err = verify_one_revision(fs, rev, notify_func, notify_baton,
- start_rev, cancel_func, cancel_baton,
+ start_rev, check_ucs_norm,
+ cancel_func, cancel_baton,
verified_dirents_cache, iterpool);
if (err)
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c Wed Nov 27 07:53:29 2013
@@ -417,17 +417,25 @@ svn_repos__parse_hooks_env(apr_hash_t **
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_config_t *cfg;
struct parse_hooks_env_section_baton b;
-
if (local_abspath)
{
- SVN_ERR(svn_config_read3(&cfg, local_abspath, FALSE,
- TRUE, TRUE, scratch_pool));
- b.cfg = cfg;
+ svn_node_kind_t kind;
+ SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+
b.hooks_env = apr_hash_make(result_pool);
- (void)svn_config_enumerate_sections2(cfg, parse_hooks_env_section, &b,
- scratch_pool);
+
+ if (kind != svn_node_none)
+ {
+ svn_config_t *cfg;
+ SVN_ERR(svn_config_read3(&cfg, local_abspath, FALSE,
+ TRUE, TRUE, scratch_pool));
+ b.cfg = cfg;
+
+ (void)svn_config_enumerate_sections2(cfg, parse_hooks_env_section,
+ &b, scratch_pool);
+ }
+
*hooks_env_p = b.hooks_env;
}
else
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c Wed Nov 27 07:53:29 2013
@@ -1796,6 +1796,11 @@ svn_repos_fs(svn_repos_t *repos)
return repos->fs;
}
+const char *
+svn_repos_fs_type(svn_repos_t *repos, apr_pool_t *pool)
+{
+ return apr_pstrdup(pool, repos->fs_type);
+}
/* For historical reasons, for the Berkeley DB backend, this code uses
* repository locking, which is motivated by the need to support the
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h Wed Nov 27 07:53:29 2013
@@ -382,6 +382,11 @@ svn_repos__authz_read(svn_authz_t **auth
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 ***/
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c Wed Nov 27 07:53:29 2013
@@ -177,14 +177,18 @@ svn_auth_set_parameter(svn_auth_baton_t
const char *name,
const void *value)
{
- svn_hash_sets(auth_baton->parameters, name, value);
+ if (auth_baton)
+ svn_hash_sets(auth_baton->parameters, name, value);
}
const void *
svn_auth_get_parameter(svn_auth_baton_t *auth_baton,
const char *name)
{
- return svn_hash_gets(auth_baton->parameters, name);
+ if (auth_baton)
+ return svn_hash_gets(auth_baton->parameters, name);
+ else
+ return NULL;
}
@@ -215,6 +219,10 @@ svn_auth_first_credentials(void **creden
svn_auth_iterstate_t *iterstate;
const char *cache_key;
+ if (! auth_baton)
+ return svn_error_create(SVN_ERR_AUTHN_NO_PROVIDER, NULL,
+ _("No authentication providers registered"));
+
/* Get the appropriate table of providers for CRED_KIND. */
table = svn_hash_gets(auth_baton->tables, cred_kind);
if (! table)
@@ -511,19 +519,19 @@ svn_auth_get_platform_specific_provider(
if (strcmp(provider_name, "gpg_agent") == 0 &&
strcmp(provider_type, "simple") == 0)
{
- svn_auth_get_gpg_agent_simple_provider(provider, pool);
+ svn_auth__get_gpg_agent_simple_provider(provider, pool);
}
#endif
#ifdef SVN_HAVE_KEYCHAIN_SERVICES
if (strcmp(provider_name, "keychain") == 0 &&
strcmp(provider_type, "simple") == 0)
{
- svn_auth_get_keychain_simple_provider(provider, pool);
+ svn_auth__get_keychain_simple_provider(provider, pool);
}
else if (strcmp(provider_name, "keychain") == 0 &&
strcmp(provider_type, "ssl_client_cert_pw") == 0)
{
- svn_auth_get_keychain_ssl_client_cert_pw_provider(provider, pool);
+ svn_auth__get_keychain_ssl_client_cert_pw_provider(provider, pool);
}
#endif
@@ -531,17 +539,17 @@ svn_auth_get_platform_specific_provider(
if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "simple") == 0)
{
- svn_auth_get_windows_simple_provider(provider, pool);
+ svn_auth__get_windows_simple_provider(provider, pool);
}
else if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "ssl_client_cert_pw") == 0)
{
- svn_auth_get_windows_ssl_client_cert_pw_provider(provider, pool);
+ svn_auth__get_windows_ssl_client_cert_pw_provider(provider, pool);
}
else if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "ssl_server_trust") == 0)
{
- svn_auth_get_windows_ssl_server_trust_provider(provider, pool);
+ svn_auth__get_windows_ssl_server_trust_provider(provider, pool);
}
else if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "ssl_server_authority") == 0)
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h Wed Nov 27 07:53:29 2013
@@ -41,6 +41,121 @@ svn_auth__file_path(const char **path,
const char *config_dir,
apr_pool_t *pool);
+#if (defined(WIN32) && !defined(__MINGW32__)) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory. Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_simple_provider(), except that, when
+ * running on Window 2000 or newer (or any other Windows version that
+ * includes the CryptoAPI), the provider encrypts the password before
+ * storing it to disk. On earlier versions of Windows, the provider
+ * does nothing.
+ *
+ * @note This function is only available on Windows.
+ *
+ * @note An administrative password reset may invalidate the account's
+ * secret key. This function will detect that situation and behave as
+ * if the password were not cached at all.
+ */
+void
+svn_auth__get_windows_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the
+ * user's ~/.subversion configuration directory. Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_ssl_client_cert_pw_file_provider(), except that
+ * when running on Window 2000 or newer, the provider encrypts the password
+ * before storing it to disk. On earlier versions of Windows, the provider
+ * does nothing.
+ *
+ * @note This function is only available on Windows.
+ *
+ * @note An administrative password reset may invalidate the account's
+ * secret key. This function will detect that situation and behave as
+ * if the password were not cached at all.
+ */
+void
+svn_auth__get_windows_ssl_client_cert_pw_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_ssl_server_trust_t, allocated in @a pool.
+ *
+ * This provider automatically validates ssl server certificates with
+ * the CryptoApi, like Internet Explorer and the Windows network API do.
+ * This allows the rollout of root certificates via Windows Domain
+ * policies, instead of Subversion specific configuration.
+ *
+ * @note This function is only available on Windows.
+ */
+void
+svn_auth__get_windows_ssl_server_trust_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+#endif /* WIN32 && !__MINGW32__ || DOXYGEN */
+
+#if defined(DARWIN) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory. Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_simple_provider(), except that the
+ * password is stored in the Mac OS KeyChain.
+ *
+ * @note This function is only available on Mac OS 10.2 and higher.
+ */
+void
+svn_auth__get_keychain_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the
+ * user's ~/.subversion configuration directory. Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_ssl_client_cert_pw_file_provider(), except
+ * that the password is stored in the Mac OS KeyChain.
+ *
+ * @note This function is only available on Mac OS 10.2 and higher.
+ */
+void
+svn_auth__get_keychain_ssl_client_cert_pw_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+#endif /* DARWIN || DOXYGEN */
+
+#if !defined(WIN32) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.
+ *
+ * This is like svn_client_get_simple_provider(), except that the
+ * password is obtained from gpg_agent, which will keep it in
+ * a memory cache.
+ *
+ * Allocate @a *provider in @a pool.
+ *
+ * @note This function actually works only on systems with
+ * GNU Privacy Guard installed.
+ */
+void
+svn_auth__get_gpg_agent_simple_provider
+ (svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+#endif /* !defined(WIN32) || defined(DOXYGEN) */
#ifdef __cplusplus
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c Wed Nov 27 07:53:29 2013
@@ -791,7 +791,7 @@ free_spare_group(svn_membuffer_t *cache,
{
assert(group->header.used == 0);
assert(group->header.previous != NO_INDEX);
- assert(group - cache->directory >= cache->group_count);
+ assert(group - cache->directory >= (apr_ssize_t)cache->group_count);
/* unchain */
cache->directory[group->header.previous].header.next = NO_INDEX;
@@ -1817,6 +1817,39 @@ entry_exists(svn_membuffer_t *cache,
return SVN_NO_ERROR;
}
+/* Given the SIZE and PRIORITY of a new item, return the cache level
+ (L1 or L2) in fragment CACHE that this item shall be inserted into.
+ If we can't find nor make enough room for the item, return NULL.
+ */
+static cache_level_t *
+select_level(svn_membuffer_t *cache,
+ apr_size_t size,
+ apr_uint32_t priority)
+{
+ if (cache->max_entry_size >= size)
+ {
+ /* Small items go into L1. */
+ return ensure_data_insertable_l1(cache, size)
+ ? &cache->l1
+ : NULL;
+ }
+ else if ( cache->l2.size >= size
+ && MAX_ITEM_SIZE >= size
+ && priority >= SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY)
+ {
+ /* Large and somewhat important items go into L2. */
+ entry_t dummy_entry = { { 0 } };
+ dummy_entry.priority = priority;
+ dummy_entry.size = size;
+
+ return ensure_data_insertable_l2(cache, &dummy_entry)
+ ? &cache->l2
+ : NULL;
+ }
+
+ /* Don't cache large, unimportant items. */
+ return NULL;
+}
/* Try to insert the serialized item given in BUFFER with SIZE into
* the group GROUP_INDEX of CACHE and uniquely identify it by hash
@@ -1840,6 +1873,8 @@ membuffer_cache_set_internal(svn_membuff
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
+ cache_level_t *level;
+
/* first, look for a previous entry for the given key */
entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
@@ -1869,9 +1904,8 @@ membuffer_cache_set_internal(svn_membuff
/* if necessary, enlarge the insertion window.
*/
- if ( buffer != NULL
- && cache->max_entry_size >= size
- && ensure_data_insertable_l1(cache, size))
+ level = buffer ? select_level(cache, size, priority) : NULL;
+ if (level)
{
/* Remove old data for this key, if that exists.
* Get an unused entry for the key and and initialize it with
@@ -1879,7 +1913,7 @@ membuffer_cache_set_internal(svn_membuff
*/
entry = find_entry(cache, group_index, to_find, TRUE);
entry->size = size;
- entry->offset = cache->l1.current_data;
+ entry->offset = level->current_data;
entry->priority = priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -2371,7 +2405,7 @@ typedef struct last_access_key_t
entry_key_t combined_key;
/* length of the key (or APR_HASH_KEY_STRING if not used) */
- apr_size_t key_len;
+ apr_ssize_t key_len;
/* the original key. Only KEY_LEN bytes are valid. We use uint32 for
* better compatibility with pseudo-md5 functions. */
@@ -2774,7 +2808,9 @@ svn_membuffer_cache_is_cachable(void *ca
* must be small enough to be stored in a 32 bit value.
*/
svn_membuffer_cache_t *cache = cache_void;
- return size <= cache->membuffer->max_entry_size;
+ return cache->priority >= SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY
+ ? cache->membuffer->l2.size >= size && MAX_ITEM_SIZE >= size
+ : size <= cache->membuffer->max_entry_size;
}
/* Add statistics of SEGMENT to INFO. If INCLUDE_HISTOGRAM is TRUE,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c Wed Nov 27 07:53:29 2013
@@ -757,12 +757,12 @@ svn_cmdline__print_xml_prop(svn_stringbu
outstr, pool, svn_xml_protect_pcdata,
inherited_prop ? "inherited_property" : "property",
"name", propname,
- "encoding", encoding, NULL);
+ "encoding", encoding, SVN_VA_NULL);
else
svn_xml_make_open_tag(
outstr, pool, svn_xml_protect_pcdata,
inherited_prop ? "inherited_property" : "property",
- "name", propname, NULL);
+ "name", propname, SVN_VA_NULL);
svn_stringbuf_appendcstr(*outstr, xml_safe);
@@ -988,7 +988,7 @@ svn_cmdline__print_xml_prop_hash(svn_str
svn_xml_make_open_tag(
outstr, pool, svn_xml_self_closing,
inherited_props ? "inherited_property" : "property",
- "name", pname, NULL);
+ "name", pname, SVN_VA_NULL);
}
else
{
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c Wed Nov 27 07:53:29 2013
@@ -421,6 +421,26 @@ make_hash_key(char *key)
return key;
}
+/* Return the value for KEY in HASH. If CASE_SENSITIVE is FALSE,
+ BUFFER will be used to construct the normalized hash key. */
+static void *
+get_hash_value(apr_hash_t *hash,
+ svn_stringbuf_t *buffer,
+ const char *key,
+ svn_boolean_t case_sensitive)
+{
+ apr_size_t i;
+ apr_size_t len = strlen(key);
+
+ if (case_sensitive)
+ return apr_hash_get(hash, key, len);
+
+ svn_stringbuf_ensure(buffer, len);
+ for (i = 0; i < len; ++i)
+ buffer->data[i] = (char)apr_tolower(key[i]);
+
+ return apr_hash_get(hash, buffer->data, len);
+}
/* Return a pointer to an option in CFG, or NULL if it doesn't exist.
if SECTIONP is non-null, return a pointer to the option's section.
@@ -429,30 +449,16 @@ static cfg_option_t *
find_option(svn_config_t *cfg, const char *section, const char *option,
cfg_section_t **sectionp)
{
- void *sec_ptr;
-
- /* Canonicalize the hash key */
- svn_stringbuf_set(cfg->tmp_key, section);
- if (! cfg->section_names_case_sensitive)
- make_hash_key(cfg->tmp_key->data);
-
- sec_ptr = apr_hash_get(cfg->sections, cfg->tmp_key->data,
- cfg->tmp_key->len);
+ void *sec_ptr = get_hash_value(cfg->sections, cfg->tmp_key, section,
+ cfg->section_names_case_sensitive);
if (sectionp != NULL)
*sectionp = sec_ptr;
if (sec_ptr != NULL && option != NULL)
{
cfg_section_t *sec = sec_ptr;
- cfg_option_t *opt;
-
- /* Canonicalize the option key */
- svn_stringbuf_set(cfg->tmp_key, option);
- if (! cfg->option_names_case_sensitive)
- make_hash_key(cfg->tmp_key->data);
-
- opt = apr_hash_get(sec->options, cfg->tmp_key->data,
- cfg->tmp_key->len);
+ cfg_option_t *opt = get_hash_value(sec->options, cfg->tmp_key, option,
+ cfg->option_names_case_sensitive);
/* NOTE: ConfigParser's sections are case sensitive. */
if (opt == NULL
&& apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0)
@@ -697,11 +703,11 @@ svn_config_get(svn_config_t *cfg, const
}
else
/* before attempting to expand an option, check for the placeholder.
- * If none is there, there is no point in calling expand_option_value.
+ * If there is none, there is no point in calling expand_option_value.
*/
if (default_value && strchr(default_value, '%'))
{
- apr_pool_t *tmp_pool = svn_pool_create(cfg->x_pool);
+ apr_pool_t *tmp_pool = svn_pool_create(cfg->pool);
const char *x_default;
expand_option_value(cfg, sec, default_value, &x_default, tmp_pool);
if (x_default)
@@ -979,7 +985,7 @@ svn_config_enumerate(svn_config_t *cfg,
if (sec == NULL)
return 0;
- subpool = svn_pool_create(cfg->x_pool);
+ subpool = svn_pool_create(cfg->pool);
count = 0;
for (opt_ndx = apr_hash_first(subpool, sec->options);
opt_ndx != NULL;
@@ -1246,13 +1252,6 @@ svn_config_get_server_setting_bool(svn_c
svn_boolean_t
svn_config_has_section(svn_config_t *cfg, const char *section)
{
- cfg_section_t *sec;
-
- /* Canonicalize the hash key */
- svn_stringbuf_set(cfg->tmp_key, section);
- if (! cfg->section_names_case_sensitive)
- make_hash_key(cfg->tmp_key->data);
-
- sec = svn_hash_gets(cfg->sections, cfg->tmp_key->data);
- return sec != NULL;
+ return NULL != get_hash_value(cfg->sections, cfg->tmp_key, section,
+ cfg->section_names_case_sensitive);
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c Wed Nov 27 07:53:29 2013
@@ -30,6 +30,7 @@
#include "svn_types.h"
#include "svn_dirent_uri.h"
#include "svn_auth.h"
+#include "svn_hash.h"
#include "svn_subst.h"
#include "svn_utf.h"
#include "svn_pools.h"
@@ -184,7 +185,25 @@ skip_to_eoln(parse_context_t *ctx, int *
SVN_ERR(parser_getc(ctx, &ch));
while (ch != '\n' && ch != EOF)
- SVN_ERR(parser_getc_plain(ctx, &ch));
+ {
+ /* This is much faster than checking individual bytes.
+ * We use this function a lot when skipping comment lines.
+ *
+ * This assumes that the ungetc buffer is empty, but that is a
+ * safe assumption right after reading a character (which would
+ * clear the buffer. */
+ const char *newline = memchr(ctx->parser_buffer + ctx->buffer_pos, '\n',
+ ctx->buffer_size - ctx->buffer_pos);
+ if (newline)
+ {
+ ch = '\n';
+ ctx->buffer_pos = newline - ctx->parser_buffer + 1;
+ break;
+ }
+
+ /* refill buffer, check for EOF */
+ SVN_ERR(parser_getc_plain(ctx, &ch));
+ }
*c = ch;
return SVN_NO_ERROR;
@@ -469,6 +488,38 @@ svn_config__is_read_only(svn_config_t *c
return cfg->read_only;
}
+svn_config_t *
+svn_config__shallow_copy(svn_config_t *src,
+ apr_pool_t *pool)
+{
+ svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
+
+ cfg->sections = src->sections;
+ cfg->pool = pool;
+
+ /* r/o configs are fully expanded and don't need the x_pool anymore */
+ cfg->x_pool = src->read_only ? NULL : svn_pool_create(pool);
+ cfg->x_values = src->x_values;
+ cfg->tmp_key = svn_stringbuf_create_empty(pool);
+ cfg->tmp_value = svn_stringbuf_create_empty(pool);
+ cfg->section_names_case_sensitive = src->section_names_case_sensitive;
+ cfg->option_names_case_sensitive = src->option_names_case_sensitive;
+ cfg->read_only = src->read_only;
+
+ return cfg;
+}
+
+void
+svn_config__shallow_replace_section(svn_config_t *target,
+ svn_config_t *source,
+ const char *section)
+{
+ if (target->read_only)
+ target->sections = apr_hash_copy(target->pool, target->sections);
+
+ svn_hash_sets(target->sections, section,
+ svn_hash_gets(source->sections, section));
+}
svn_error_t *
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h Wed Nov 27 07:53:29 2013
@@ -47,7 +47,8 @@ struct svn_config_t
/* Table of cfg_section_t's. */
apr_hash_t *sections;
- /* Pool for hash tables, table entries and unexpanded values */
+ /* Pool for hash tables, table entries and unexpanded values.
+ Also, parent pool for temporary pools. */
apr_pool_t *pool;
/* Pool for expanded values -- this is separate, so that we can
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c Wed Nov 27 07:53:29 2013
@@ -44,8 +44,10 @@
#include "svn_mergeinfo.h"
#include "svn_utf.h"
#include "svn_xml.h"
+#include "svn_auth.h"
#include "opt.h"
+#include "auth.h"
#include "private/svn_opt_private.h"
#include "private/svn_mergeinfo_private.h"
@@ -1321,3 +1323,54 @@ svn_ver_check_list(const svn_version_t *
return svn_ver_check_list2(my_version, checklist, svn_ver_compatible);
}
+/*** From win32_crypto.c ***/
+#if defined(WIN32) && !defined(__MINGW32__)
+void
+svn_auth_get_windows_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth__get_windows_simple_provider(provider, pool);
+}
+
+void
+svn_auth_get_windows_ssl_client_cert_pw_provider
+ (svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth__get_windows_ssl_client_cert_pw_provider(provider, pool);
+}
+
+void
+svn_auth_get_windows_ssl_server_trust_provider
+ (svn_auth_provider_object_t **provider, apr_pool_t *pool)
+{
+ svn_auth__get_windows_ssl_server_trust_provider(provider, pool);
+}
+#endif /* WIN32 && !__MINGW32__ */
+
+/*** From macos_keychain.c ***/
+#if defined(DARWIN)
+void
+svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth__get_keychain_simple_provider(provider, pool);
+}
+
+void
+svn_auth_get_keychain_ssl_client_cert_pw_provider
+ (svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth__get_keychain_ssl_client_cert_pw_provider(provider, pool);
+}
+#endif /* DARWIN */
+
+#if !defined(WIN32)
+void
+svn_auth_get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth__get_gpg_agent_simple_provider(provider, pool);
+}
+#endif /* !WIN32 */
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c Wed Nov 27 07:53:29 2013
@@ -1293,6 +1293,29 @@ svn_relpath_split(const char **dirpath,
*base_name = svn_relpath_basename(relpath, pool);
}
+const char *
+svn_relpath_limit(const char *relpath,
+ int max_components,
+ apr_pool_t *result_pool)
+{
+ const char *end;
+ assert(relpath_is_canonical(relpath));
+
+ if (max_components <= 0)
+ return "";
+
+ for (end = relpath; *end; end++)
+ {
+ if (*end == '/')
+ {
+ if (!--max_components)
+ break;
+ }
+ }
+
+ return apr_pstrmemdup(result_pool, relpath, end-relpath);
+}
+
char *
svn_uri_dirname(const char *uri, apr_pool_t *pool)
{
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c Wed Nov 27 07:53:29 2013
@@ -699,7 +699,7 @@ svn_error_symbolic_name(apr_status_t sta
return defn->errname;
/* "No error" is not in error_table. */
- if (statcode == SVN_NO_ERROR)
+ if (statcode == APR_SUCCESS)
return "SVN_NO_ERROR";
#ifdef SVN_DEBUG
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c Wed Nov 27 07:53:29 2013
@@ -73,6 +73,7 @@
#include "svn_checksum.h"
#include "svn_string.h"
+#include "auth.h"
#include "private/svn_auth_private.h"
#include "svn_private_config.h"
@@ -475,7 +476,7 @@ static const svn_auth_provider_t gpg_age
/* Public API */
void
-svn_auth_get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
+svn_auth__get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
apr_pool_t *pool)
{
svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c Wed Nov 27 07:53:29 2013
@@ -1591,14 +1591,9 @@ io_set_file_perms(const char *path,
{
if (enable_write) /* Make read-write. */
{
- apr_file_t *fd;
-
- /* Get the perms for the original file so we'll have any other bits
- * that were already set (like the execute bits, for example). */
- SVN_ERR(svn_io_file_open(&fd, path, APR_READ,
- APR_OS_DEFAULT, pool));
- SVN_ERR(merge_default_file_perms(fd, &perms_to_set, pool));
- SVN_ERR(svn_io_file_close(fd, pool));
+ /* Tweak the owner bits only. The group/other bits aren't safe to
+ * touch because we may end up setting them in undesired ways. */
+ perms_to_set |= (APR_UREAD|APR_UWRITE);
}
else
{
@@ -2312,12 +2307,11 @@ stringbuf_from_aprfile(svn_stringbuf_t *
efficient memory handling, we'll try to do so. */
if (check_size)
{
- apr_finfo_t finfo;
+ apr_finfo_t finfo = { 0 };
/* In some cases we get size 0 and no error for non files,
so we also check for the name. (= cached in apr_file_t) */
- if (! apr_file_info_get(&finfo, APR_FINFO_SIZE | APR_FINFO_NAME, file)
- && finfo.name != NULL)
+ if (! apr_file_info_get(&finfo, APR_FINFO_SIZE, file) && finfo.fname)
{
/* we've got the file length. Now, read it in one go. */
svn_boolean_t eof;
@@ -3787,15 +3781,21 @@ svn_io_write_atomic(const char *final_pa
if (!err && copy_perms_path)
err = svn_io_copy_perms(copy_perms_path, tmp_path, scratch_pool);
+ if (!err)
+ err = svn_io_file_rename(tmp_path, final_path, scratch_pool);
+
if (err)
{
- return svn_error_compose_create(err,
- svn_io_remove_file2(tmp_path, FALSE,
- scratch_pool));
+ err = svn_error_compose_create(err,
+ svn_io_remove_file2(tmp_path, TRUE,
+ scratch_pool));
+
+ return svn_error_createf(err->apr_err, err,
+ _("Can't write '%s' atomicly"),
+ svn_dirent_local_style(final_path,
+ scratch_pool));
}
- SVN_ERR(svn_io_file_rename(tmp_path, final_path, scratch_pool));
-
#ifdef __linux__
{
/* Linux has the unusual feature that fsync() on a file is not
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c Wed Nov 27 07:53:29 2013
@@ -193,24 +193,36 @@ svn_iter__break(void)
const void *svn__apr_hash_index_key(const apr_hash_index_t *hi)
{
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+ return apr_hash_this_key((apr_hash_index_t *)hi);
+#else
const void *key;
apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL);
return key;
+#endif
}
apr_ssize_t svn__apr_hash_index_klen(const apr_hash_index_t *hi)
{
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+ return apr_hash_this_key_len((apr_hash_index_t *)hi);
+#else
apr_ssize_t klen;
apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL);
return klen;
+#endif
}
void *svn__apr_hash_index_val(const apr_hash_index_t *hi)
{
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+ return apr_hash_this_val((apr_hash_index_t *)hi);
+#else
void *val;
apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val);
return val;
+#endif
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c Wed Nov 27 07:53:29 2013
@@ -32,6 +32,7 @@
#include "svn_config.h"
#include "svn_user.h"
+#include "auth.h"
#include "private/svn_auth_private.h"
#include "svn_private_config.h"
@@ -241,7 +242,7 @@ static const svn_auth_provider_t keychai
/* Public API */
void
-svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
+svn_auth__get_keychain_simple_provider(svn_auth_provider_object_t **provider,
apr_pool_t *pool)
{
svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
@@ -251,7 +252,7 @@ svn_auth_get_keychain_simple_provider(sv
}
void
-svn_auth_get_keychain_ssl_client_cert_pw_provider
+svn_auth__get_keychain_ssl_client_cert_pw_provider
(svn_auth_provider_object_t **provider,
apr_pool_t *pool)
{
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c Wed Nov 27 07:53:29 2013
@@ -849,7 +849,7 @@ svn_packed__get_bytes(svn_packed__byte_s
apr_size_t *len)
{
const char *result = stream->packed->data;
- apr_size_t count = svn_packed__get_uint(stream->lengths_stream);
+ apr_size_t count = (apr_size_t)svn_packed__get_uint(stream->lengths_stream);
if (count > stream->packed->len)
count = stream->packed->len;
@@ -1011,8 +1011,8 @@ svn_packed__data_read(svn_packed__data_r
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- apr_size_t i;
- apr_size_t count;
+ apr_uint64_t i;
+ apr_uint64_t count;
svn_packed__int_stream_t *int_stream;
svn_packed__byte_stream_t *byte_stream;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c Wed Nov 27 07:53:29 2013
@@ -184,7 +184,7 @@ svn_prefix_string__create(svn_prefix_tre
: 0;
/* any (partially) matching sub-nodes? */
- if (idx == node->sub_node_count
+ if (idx == (int)node->sub_node_count
|| node->sub_nodes[idx]->key.data[0] != s[node->length])
break;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c Wed Nov 27 07:53:29 2013
@@ -333,8 +333,9 @@ heap_is_less(svn_priority_queue__t *queu
char *lhs_value = queue->elements->elts + lhs * queue->elements->elt_size;
char *rhs_value = queue->elements->elts + rhs * queue->elements->elt_size;
- assert(lhs < queue->elements->nelts);
- assert(rhs < queue->elements->nelts);
+ /* nelts is never negative */
+ assert(lhs < (apr_size_t)queue->elements->nelts);
+ assert(rhs < (apr_size_t)queue->elements->nelts);
return queue->compare_func((void *)lhs_value, (void *)rhs_value) < 0;
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c Wed Nov 27 07:53:29 2013
@@ -270,7 +270,7 @@ release_name_from_uname(apr_pool_t *pool
#if __linux__
/* Split a stringbuf into a key/value pair.
- Return the key, leaving the striped value in the stringbuf. */
+ Return the key, leaving the stripped value in the stringbuf. */
static const char *
stringbuf_split_key(svn_stringbuf_t *buffer, char delim)
{
@@ -282,11 +282,21 @@ stringbuf_split_key(svn_stringbuf_t *buf
return NULL;
svn_stringbuf_strip_whitespace(buffer);
+
+ /* Now we split the currently allocated buffer in two parts:
+ - a const char * HEAD
+ - the remaining stringbuf_t. */
+
+ /* Create HEAD as '\0' terminated const char * */
key = buffer->data;
end = strchr(key, delim);
*end = '\0';
- buffer->len = 1 + end - key;
+
+ /* And update the TAIL to be a smaller, but still valid stringbuf */
buffer->data = end + 1;
+ buffer->len -= 1 + end - key;
+ buffer->blocksize -= 1 + end - key;
+
svn_stringbuf_strip_whitespace(buffer);
return key;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c Wed Nov 27 07:53:29 2013
@@ -155,7 +155,6 @@ ucs4cmp(const apr_int32_t *bufa, apr_siz
return (lena == lenb ? 0 : (lena < lenb ? -1 : 1));
}
-
svn_error_t *
svn_utf__normcmp(int *result,
const char *str1, apr_size_t len1,
@@ -182,6 +181,16 @@ svn_utf__normcmp(int *result,
return SVN_NO_ERROR;
}
+svn_error_t*
+svn_utf__normalize(const char **result,
+ const char *str, apr_size_t len,
+ svn_membuf_t *buf)
+{
+ apr_size_t result_length;
+ SVN_ERR(normalize_cstring(&result_length, str, len, buf));
+ *result = (const char*)(buf->data);
+ return SVN_NO_ERROR;
+}
/* Decode a single UCS-4 code point to UTF-8, appending the result to BUFFER.
* Assume BUFFER is already filled to *LENGTH and return the new size there.
@@ -424,7 +433,7 @@ svn_utf__fuzzy_escape(const char *src, a
len = utf8proc_utf8class[(uint8_t)*p];
/* Check if the multi-byte sequence is valid UTF-8. */
- if (len > 1 && len <= length - done)
+ if (len > 1 && len <= (apr_ssize_t)(length - done))
last = svn_utf__last_valid(p, len);
else
last = NULL;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c Wed Nov 27 07:53:29 2013
@@ -182,10 +182,10 @@ ssize_t utf8proc_encode_char(int32_t uc,
if (uc < 0x00) {
return 0;
} else if (uc < 0x80) {
- dst[0] = uc;
+ dst[0] = (uint8_t)uc;
return 1;
} else if (uc < 0x800) {
- dst[0] = 0xC0 + (uc >> 6);
+ dst[0] = 0xC0 + (uint8_t)(uc >> 6);
dst[1] = 0x80 + (uc & 0x3F);
return 2;
} else if (uc == 0xFFFF) {
@@ -195,12 +195,12 @@ ssize_t utf8proc_encode_char(int32_t uc,
dst[0] = 0xFE;
return 1;
} else if (uc < 0x10000) {
- dst[0] = 0xE0 + (uc >> 12);
+ dst[0] = 0xE0 + (uint8_t)(uc >> 12);
dst[1] = 0x80 + ((uc >> 6) & 0x3F);
dst[2] = 0x80 + (uc & 0x3F);
return 3;
} else if (uc < 0x110000) {
- dst[0] = 0xF0 + (uc >> 18);
+ dst[0] = 0xF0 + (uint8_t)(uc >> 18);
dst[1] = 0x80 + ((uc >> 12) & 0x3F);
dst[2] = 0x80 + ((uc >> 6) & 0x3F);
dst[3] = 0x80 + (uc & 0x3F);