summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/config.c')
-rw-r--r--subversion/libsvn_subr/config.c150
1 files changed, 104 insertions, 46 deletions
diff --git a/subversion/libsvn_subr/config.c b/subversion/libsvn_subr/config.c
index cf97f0d..770d699 100644
--- a/subversion/libsvn_subr/config.c
+++ b/subversion/libsvn_subr/config.c
@@ -23,6 +23,8 @@
+#include <assert.h>
+
#define APR_WANT_STRFUNC
#define APR_WANT_MEMFUNC
#include <apr_want.h>
@@ -36,6 +38,7 @@
#include "svn_private_config.h"
#include "private/svn_dep_compat.h"
+#include "private/svn_subr_private.h"
@@ -92,6 +95,7 @@ svn_config_create2(svn_config_t **cfgp,
cfg->tmp_value = svn_stringbuf_create_empty(result_pool);
cfg->section_names_case_sensitive = section_names_case_sensitive;
cfg->option_names_case_sensitive = option_names_case_sensitive;
+ cfg->read_only = FALSE;
*cfgp = cfg;
return SVN_NO_ERROR;
@@ -188,7 +192,8 @@ read_all(svn_config_t **cfgp,
#ifdef WIN32
if (sys_registry_path)
{
- SVN_ERR(svn_config_read2(cfgp, sys_registry_path, FALSE, FALSE, pool));
+ SVN_ERR(svn_config_read3(cfgp, sys_registry_path, FALSE, FALSE, FALSE,
+ pool));
red_config = TRUE;
}
#endif /* WIN32 */
@@ -214,8 +219,8 @@ read_all(svn_config_t **cfgp,
SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE));
else
{
- SVN_ERR(svn_config_read2(cfgp, usr_registry_path,
- FALSE, FALSE, pool));
+ SVN_ERR(svn_config_read3(cfgp, usr_registry_path,
+ FALSE, FALSE, FALSE, pool));
red_config = TRUE;
}
}
@@ -242,7 +247,7 @@ read_all(svn_config_t **cfgp,
/* CONFIG_DIR provides an override for the default behavior of reading
the default set of overlay files described by read_all()'s doc
- string. */
+ string. Returns non-NULL *CFG or an error. */
static svn_error_t *
get_category_config(svn_config_t **cfg,
const char *config_dir,
@@ -259,9 +264,9 @@ get_category_config(svn_config_t **cfg,
{
#ifdef WIN32
sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,
- category, NULL);
+ category, SVN_VA_NULL);
usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,
- category, NULL);
+ category, SVN_VA_NULL);
#endif /* WIN32 */
err = svn_config__sys_config_path(&sys_cfg_path, category, pool);
@@ -291,19 +296,29 @@ svn_config_get_config(apr_hash_t **cfg_hash,
svn_config_t *cfg;
*cfg_hash = apr_hash_make(pool);
-#define CATLEN (sizeof(SVN_CONFIG_CATEGORY_SERVERS) - 1)
SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS,
pool));
- if (cfg)
- apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, CATLEN, cfg);
-#undef CATLEN
+ svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, cfg);
-#define CATLEN (sizeof(SVN_CONFIG_CATEGORY_CONFIG) - 1)
SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG,
pool));
- if (cfg)
- apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, CATLEN, cfg);
-#undef CATLEN
+ svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, cfg);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_config__get_default_config(apr_hash_t **cfg_hash,
+ apr_pool_t *pool)
+{
+ svn_config_t *empty_cfg;
+ *cfg_hash = apr_hash_make(pool);
+
+ SVN_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
+ svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, empty_cfg);
+
+ SVN_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
+ svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, empty_cfg);
return SVN_NO_ERROR;
}
@@ -415,6 +430,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.
@@ -423,30 +458,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)
@@ -482,7 +503,13 @@ make_string_from_option(const char **valuep, svn_config_t *cfg,
*/
if (opt->value && strchr(opt->value, '%'))
{
- apr_pool_t *tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool));
+ apr_pool_t *tmp_pool;
+
+ /* setting read-only mode should have expanded all values
+ * automatically. */
+ assert(!cfg->read_only);
+
+ tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool));
expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool);
opt->expanded = TRUE;
@@ -642,6 +669,33 @@ svn_config_create_option(cfg_option_t **opt,
*opt = o;
}
+svn_boolean_t
+svn_config__is_expanded(svn_config_t *cfg,
+ const char *section,
+ const char *option)
+{
+ cfg_option_t *opt;
+
+ if (cfg == NULL)
+ return FALSE;
+
+ /* does the option even exist? */
+ opt = find_option(cfg, section, option, NULL);
+ if (opt == NULL)
+ return FALSE;
+
+ /* already expanded? */
+ if (opt->expanded)
+ return TRUE;
+
+ /* needs expansion? */
+ if (opt->value && strchr(opt->value, '%'))
+ return FALSE;
+
+ /* no expansion necessary */
+ return TRUE;
+}
+
void
svn_config_get(svn_config_t *cfg, const char **valuep,
@@ -659,11 +713,11 @@ svn_config_get(svn_config_t *cfg, const char **valuep,
}
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)
@@ -686,6 +740,17 @@ svn_config_set(svn_config_t *cfg,
cfg_section_t *sec;
cfg_option_t *opt;
+ /* Ignore write attempts to r/o configurations.
+ *
+ * Since we should never try to modify r/o data, trigger an assertion
+ * in debug mode.
+ */
+#ifdef SVN_DEBUG
+ SVN_ERR_ASSERT_NO_RETURN(!cfg->read_only);
+#endif
+ if (cfg->read_only)
+ return;
+
remove_expansions(cfg);
opt = find_option(cfg, section, option, &sec);
@@ -930,7 +995,7 @@ svn_config_enumerate(svn_config_t *cfg, const char *section,
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;
@@ -1059,7 +1124,7 @@ svn_config_get_server_setting(svn_config_t *cfg,
svn_error_t *
svn_config_dup(svn_config_t **cfgp,
- svn_config_t *src,
+ const svn_config_t *src,
apr_pool_t *pool)
{
apr_hash_index_t *sectidx;
@@ -1197,13 +1262,6 @@ svn_config_get_server_setting_bool(svn_config_t *cfg,
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);
}