2 * config.c : reading configuration information
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
28 #define APR_WANT_STRFUNC
29 #define APR_WANT_MEMFUNC
32 #include <apr_general.h>
35 #include "svn_error.h"
36 #include "svn_pools.h"
37 #include "config_impl.h"
39 #include "svn_private_config.h"
40 #include "private/svn_dep_compat.h"
41 #include "private/svn_subr_private.h"
46 /* Section table entries. */
47 typedef struct cfg_section_t cfg_section_t;
50 /* The section name. */
53 /* Table of cfg_option_t's. */
58 /* Option table entries. */
59 typedef struct cfg_option_t cfg_option_t;
62 /* The option name. */
65 /* The option name, converted into a hash key. */
68 /* The unexpanded option value. */
71 /* The expanded option value. */
74 /* Expansion flag. If this is TRUE, this value has already been expanded.
75 In this case, if x_value is NULL, no expansions were necessary,
76 and value should be used directly. */
77 svn_boolean_t expanded;
83 svn_config_create2(svn_config_t **cfgp,
84 svn_boolean_t section_names_case_sensitive,
85 svn_boolean_t option_names_case_sensitive,
86 apr_pool_t *result_pool)
88 svn_config_t *cfg = apr_palloc(result_pool, sizeof(*cfg));
90 cfg->sections = apr_hash_make(result_pool);
91 cfg->pool = result_pool;
92 cfg->x_pool = svn_pool_create(result_pool);
93 cfg->x_values = FALSE;
94 cfg->tmp_key = svn_stringbuf_create_empty(result_pool);
95 cfg->tmp_value = svn_stringbuf_create_empty(result_pool);
96 cfg->section_names_case_sensitive = section_names_case_sensitive;
97 cfg->option_names_case_sensitive = option_names_case_sensitive;
98 cfg->read_only = FALSE;
105 svn_config_read3(svn_config_t **cfgp, const char *file,
106 svn_boolean_t must_exist,
107 svn_boolean_t section_names_case_sensitive,
108 svn_boolean_t option_names_case_sensitive,
109 apr_pool_t *result_pool)
114 SVN_ERR(svn_config_create2(&cfg,
115 section_names_case_sensitive,
116 option_names_case_sensitive,
119 /* Yes, this is platform-specific code in Subversion, but there's no
120 practical way to migrate it into APR, as it's simultaneously
121 Subversion-specific and Windows-specific. Even if we eventually
122 want to have APR offer a generic config-reading interface, it
123 makes sense to test it here first and migrate it later. */
125 if (0 == strncmp(file, SVN_REGISTRY_PREFIX, SVN_REGISTRY_PREFIX_LEN))
126 err = svn_config__parse_registry(cfg, file + SVN_REGISTRY_PREFIX_LEN,
127 must_exist, result_pool);
130 err = svn_config__parse_file(cfg, file, must_exist, result_pool);
132 if (err != SVN_NO_ERROR)
141 svn_config_parse(svn_config_t **cfgp, svn_stream_t *stream,
142 svn_boolean_t section_names_case_sensitive,
143 svn_boolean_t option_names_case_sensitive,
144 apr_pool_t *result_pool)
148 apr_pool_t *scratch_pool = svn_pool_create(result_pool);
150 err = svn_config_create2(&cfg,
151 section_names_case_sensitive,
152 option_names_case_sensitive,
155 if (err == SVN_NO_ERROR)
156 err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
158 if (err == SVN_NO_ERROR)
161 svn_pool_destroy(scratch_pool);
166 /* Read various configuration sources into *CFGP, in this order, with
167 * later reads overriding the results of earlier ones:
169 * 1. SYS_REGISTRY_PATH (only on Win32, but ignored if NULL)
171 * 2. SYS_FILE_PATH (everywhere, but ignored if NULL)
173 * 3. USR_REGISTRY_PATH (only on Win32, but ignored if NULL)
175 * 4. USR_FILE_PATH (everywhere, but ignored if NULL)
177 * Allocate *CFGP in POOL. Even if no configurations are read,
178 * allocate an empty *CFGP.
181 read_all(svn_config_t **cfgp,
182 const char *sys_registry_path,
183 const char *usr_registry_path,
184 const char *sys_file_path,
185 const char *usr_file_path,
188 svn_boolean_t red_config = FALSE; /* "red" is the past tense of "read" */
190 /*** Read system-wide configurations first... ***/
193 if (sys_registry_path)
195 SVN_ERR(svn_config_read3(cfgp, sys_registry_path, FALSE, FALSE, FALSE,
204 SVN_ERR(svn_config_merge(*cfgp, sys_file_path, FALSE));
207 SVN_ERR(svn_config_read3(cfgp, sys_file_path,
208 FALSE, FALSE, FALSE, pool));
213 /*** ...followed by per-user configurations. ***/
216 if (usr_registry_path)
219 SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE));
222 SVN_ERR(svn_config_read3(cfgp, usr_registry_path,
223 FALSE, FALSE, FALSE, pool));
232 SVN_ERR(svn_config_merge(*cfgp, usr_file_path, FALSE));
235 SVN_ERR(svn_config_read3(cfgp, usr_file_path,
236 FALSE, FALSE, FALSE, pool));
242 SVN_ERR(svn_config_create2(cfgp, FALSE, FALSE, pool));
248 /* CONFIG_DIR provides an override for the default behavior of reading
249 the default set of overlay files described by read_all()'s doc
250 string. Returns non-NULL *CFG or an error. */
252 get_category_config(svn_config_t **cfg,
253 const char *config_dir,
254 const char *category,
257 const char *usr_reg_path = NULL, *sys_reg_path = NULL;
258 const char *usr_cfg_path, *sys_cfg_path;
259 svn_error_t *err = NULL;
266 sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,
267 category, SVN_VA_NULL);
268 usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,
269 category, SVN_VA_NULL);
272 err = svn_config__sys_config_path(&sys_cfg_path, category, pool);
273 if ((err) && (err->apr_err == SVN_ERR_BAD_FILENAME))
276 svn_error_clear(err);
284 SVN_ERR(svn_config_get_user_config_path(&usr_cfg_path, config_dir, category,
286 return read_all(cfg, sys_reg_path, usr_reg_path,
287 sys_cfg_path, usr_cfg_path, pool);
292 svn_config_get_config(apr_hash_t **cfg_hash,
293 const char *config_dir,
297 *cfg_hash = apr_hash_make(pool);
299 SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS,
301 svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, cfg);
303 SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG,
305 svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, cfg);
311 svn_config__get_default_config(apr_hash_t **cfg_hash,
314 svn_config_t *empty_cfg;
315 *cfg_hash = apr_hash_make(pool);
317 SVN_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
318 svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, empty_cfg);
320 SVN_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
321 svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, empty_cfg);
328 /* Iterate through CFG, passing BATON to CALLBACK for every (SECTION, OPTION)
329 pair. Stop if CALLBACK returns TRUE. Allocate from POOL. */
331 for_each_option(svn_config_t *cfg, void *baton, apr_pool_t *pool,
332 svn_boolean_t callback(void *same_baton,
333 cfg_section_t *section,
334 cfg_option_t *option))
336 apr_hash_index_t *sec_ndx;
337 for (sec_ndx = apr_hash_first(pool, cfg->sections);
339 sec_ndx = apr_hash_next(sec_ndx))
343 apr_hash_index_t *opt_ndx;
345 apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
348 for (opt_ndx = apr_hash_first(pool, sec->options);
350 opt_ndx = apr_hash_next(opt_ndx))
355 apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
358 if (callback(baton, sec, opt))
367 merge_callback(void *baton, cfg_section_t *section, cfg_option_t *option)
369 svn_config_set(baton, section->name, option->name, option->value);
374 svn_config_merge(svn_config_t *cfg, const char *file,
375 svn_boolean_t must_exist)
377 /* The original config hash shouldn't change if there's an error
378 while reading the confguration, so read into a temporary table.
379 ### We could use a tmp subpool for this, since merge_cfg is going
380 to be tossed afterwards. Premature optimization, though? */
381 svn_config_t *merge_cfg;
382 SVN_ERR(svn_config_read3(&merge_cfg, file, must_exist,
383 cfg->section_names_case_sensitive,
384 cfg->option_names_case_sensitive,
387 /* Now copy the new options into the original table. */
388 for_each_option(merge_cfg, cfg, merge_cfg->pool, merge_callback);
394 /* Remove variable expansions from CFG. Walk through the options tree,
395 killing all expanded values, then clear the expanded value pool. */
397 rmex_callback(void *baton, cfg_section_t *section, cfg_option_t *option)
399 /* Only clear the `expanded' flag if the value actually contains
400 variable expansions. */
401 if (option->expanded && option->x_value != NULL)
403 option->x_value = NULL;
404 option->expanded = FALSE;
411 remove_expansions(svn_config_t *cfg)
416 for_each_option(cfg, NULL, cfg->x_pool, rmex_callback);
417 svn_pool_clear(cfg->x_pool);
418 cfg->x_values = FALSE;
423 /* Canonicalize a string for hashing. Modifies KEY in place. */
424 static APR_INLINE char *
425 make_hash_key(char *key)
428 for (p = key; *p != 0; ++p)
429 *p = (char)apr_tolower(*p);
433 /* Return the value for KEY in HASH. If CASE_SENSITIVE is FALSE,
434 BUFFER will be used to construct the normalized hash key. */
436 get_hash_value(apr_hash_t *hash,
437 svn_stringbuf_t *buffer,
439 svn_boolean_t case_sensitive)
442 apr_size_t len = strlen(key);
445 return apr_hash_get(hash, key, len);
447 svn_stringbuf_ensure(buffer, len);
448 for (i = 0; i < len; ++i)
449 buffer->data[i] = (char)apr_tolower(key[i]);
451 return apr_hash_get(hash, buffer->data, len);
454 /* Return a pointer to an option in CFG, or NULL if it doesn't exist.
455 if SECTIONP is non-null, return a pointer to the option's section.
456 OPTION may be NULL. */
457 static cfg_option_t *
458 find_option(svn_config_t *cfg, const char *section, const char *option,
459 cfg_section_t **sectionp)
461 void *sec_ptr = get_hash_value(cfg->sections, cfg->tmp_key, section,
462 cfg->section_names_case_sensitive);
463 if (sectionp != NULL)
466 if (sec_ptr != NULL && option != NULL)
468 cfg_section_t *sec = sec_ptr;
469 cfg_option_t *opt = get_hash_value(sec->options, cfg->tmp_key, option,
470 cfg->option_names_case_sensitive);
471 /* NOTE: ConfigParser's sections are case sensitive. */
473 && apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0)
474 /* Options which aren't found in the requested section are
475 also sought after in the default section. */
476 opt = find_option(cfg, SVN_CONFIG__DEFAULT_SECTION, option, &sec);
484 /* Has a bi-directional dependency with make_string_from_option(). */
486 expand_option_value(svn_config_t *cfg, cfg_section_t *section,
487 const char *opt_value, const char **opt_x_valuep,
491 /* Set *VALUEP according to the OPT's value. A value for X_POOL must
492 only ever be passed into this function by expand_option_value(). */
494 make_string_from_option(const char **valuep, svn_config_t *cfg,
495 cfg_section_t *section, cfg_option_t *opt,
498 /* Expand the option value if necessary. */
501 /* before attempting to expand an option, check for the placeholder.
502 * If none is there, there is no point in calling expand_option_value.
504 if (opt->value && strchr(opt->value, '%'))
506 apr_pool_t *tmp_pool;
508 /* setting read-only mode should have expanded all values
510 assert(!cfg->read_only);
512 tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool));
514 expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool);
515 opt->expanded = TRUE;
517 if (x_pool != cfg->x_pool)
519 /* Grab the fully expanded value from tmp_pool before its
522 opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value,
523 strlen(opt->x_value));
525 svn_pool_destroy(tmp_pool);
530 opt->expanded = TRUE;
535 *valuep = opt->x_value;
537 *valuep = opt->value;
541 /* Start of variable-replacement placeholder */
542 #define FMT_START "%("
543 #define FMT_START_LEN (sizeof(FMT_START) - 1)
545 /* End of variable-replacement placeholder */
547 #define FMT_END_LEN (sizeof(FMT_END) - 1)
550 /* Expand OPT_VALUE (which may be NULL) in SECTION into *OPT_X_VALUEP.
551 If no variable replacements are done, set *OPT_X_VALUEP to
552 NULL. Allocate from X_POOL. */
554 expand_option_value(svn_config_t *cfg, cfg_section_t *section,
555 const char *opt_value, const char **opt_x_valuep,
558 svn_stringbuf_t *buf = NULL;
559 const char *parse_from = opt_value;
560 const char *copy_from = parse_from;
561 const char *name_start, *name_end;
563 while (parse_from != NULL
564 && *parse_from != '\0'
565 && (name_start = strstr(parse_from, FMT_START)) != NULL)
567 name_start += FMT_START_LEN;
568 if (*name_start == '\0')
569 /* FMT_START at end of opt_value. */
572 name_end = strstr(name_start, FMT_END);
573 if (name_end != NULL)
576 apr_size_t len = name_end - name_start;
577 char *name = apr_pstrmemdup(x_pool, name_start, len);
579 x_opt = find_option(cfg, section->name, name, NULL);
585 /* Pass back the sub-pool originally provided by
586 make_string_from_option() as an indication of when it
588 make_string_from_option(&cstring, cfg, section, x_opt, x_pool);
590 /* Append the plain text preceding the expansion. */
591 len = name_start - FMT_START_LEN - copy_from;
594 buf = svn_stringbuf_ncreate(copy_from, len, x_pool);
595 cfg->x_values = TRUE;
598 svn_stringbuf_appendbytes(buf, copy_from, len);
600 /* Append the expansion and adjust parse pointers. */
601 svn_stringbuf_appendcstr(buf, cstring);
602 parse_from = name_end + FMT_END_LEN;
603 copy_from = parse_from;
606 /* Though ConfigParser considers the failure to resolve
607 the requested expansion an exception condition, we
608 consider it to be plain text, and look for the start of
610 parse_from = name_end + FMT_END_LEN;
613 /* Though ConfigParser treats unterminated format specifiers
614 as an exception condition, we consider them to be plain
615 text. The fact that there are no more format specifier
616 endings means we're done parsing. */
622 /* Copy the remainder of the plain text. */
623 svn_stringbuf_appendcstr(buf, copy_from);
624 *opt_x_valuep = buf->data;
627 *opt_x_valuep = NULL;
630 static cfg_section_t *
631 svn_config_addsection(svn_config_t *cfg,
635 const char *hash_key;
637 s = apr_palloc(cfg->pool, sizeof(cfg_section_t));
638 s->name = apr_pstrdup(cfg->pool, section);
639 if(cfg->section_names_case_sensitive)
642 hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
643 s->options = apr_hash_make(cfg->pool);
644 svn_hash_sets(cfg->sections, hash_key, s);
650 svn_config_create_option(cfg_option_t **opt,
653 svn_boolean_t option_names_case_sensitive,
658 o = apr_palloc(pool, sizeof(cfg_option_t));
659 o->name = apr_pstrdup(pool, option);
660 if(option_names_case_sensitive)
661 o->hash_key = o->name;
663 o->hash_key = make_hash_key(apr_pstrdup(pool, option));
665 o->value = apr_pstrdup(pool, value);
673 svn_config__is_expanded(svn_config_t *cfg,
682 /* does the option even exist? */
683 opt = find_option(cfg, section, option, NULL);
687 /* already expanded? */
691 /* needs expansion? */
692 if (opt->value && strchr(opt->value, '%'))
695 /* no expansion necessary */
701 svn_config_get(svn_config_t *cfg, const char **valuep,
702 const char *section, const char *option,
703 const char *default_value)
705 *valuep = default_value;
709 cfg_option_t *opt = find_option(cfg, section, option, &sec);
712 make_string_from_option(valuep, cfg, sec, opt, NULL);
715 /* before attempting to expand an option, check for the placeholder.
716 * If there is none, there is no point in calling expand_option_value.
718 if (default_value && strchr(default_value, '%'))
720 apr_pool_t *tmp_pool = svn_pool_create(cfg->pool);
721 const char *x_default;
722 expand_option_value(cfg, sec, default_value, &x_default, tmp_pool);
725 svn_stringbuf_set(cfg->tmp_value, x_default);
726 *valuep = cfg->tmp_value->data;
728 svn_pool_destroy(tmp_pool);
736 svn_config_set(svn_config_t *cfg,
737 const char *section, const char *option,
743 /* Ignore write attempts to r/o configurations.
745 * Since we should never try to modify r/o data, trigger an assertion
749 SVN_ERR_ASSERT_NO_RETURN(!cfg->read_only);
754 remove_expansions(cfg);
756 opt = find_option(cfg, section, option, &sec);
759 /* Replace the option's value. */
760 opt->value = apr_pstrdup(cfg->pool, value);
761 opt->expanded = FALSE;
765 /* Create a new option */
766 svn_config_create_option(&opt, option, value,
767 cfg->option_names_case_sensitive,
772 /* Even the section doesn't exist. Create it. */
773 sec = svn_config_addsection(cfg, section);
776 svn_hash_sets(sec->options, opt->hash_key, opt);
781 /* Set *BOOLP to true or false depending (case-insensitively) on INPUT.
782 If INPUT is null, set *BOOLP to DEFAULT_VALUE.
784 INPUT is a string indicating truth or falsehood in any of the usual
785 ways: "true"/"yes"/"on"/etc, "false"/"no"/"off"/etc.
787 If INPUT is neither NULL nor a recognized string, return an error
788 with code SVN_ERR_BAD_CONFIG_VALUE; use SECTION and OPTION in
789 constructing the error string. */
791 get_bool(svn_boolean_t *boolp, const char *input, svn_boolean_t default_value,
792 const char *section, const char *option)
794 svn_tristate_t value = svn_tristate__from_word(input);
796 if (value == svn_tristate_true)
798 else if (value == svn_tristate_false)
800 else if (input == NULL) /* no value provided */
801 *boolp = default_value;
803 else if (section) /* unrecognized value */
804 return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
805 _("Config error: invalid boolean "
806 "value '%s' for '[%s] %s'"),
807 input, section, option);
809 return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
810 _("Config error: invalid boolean "
811 "value '%s' for '%s'"),
819 svn_config_get_bool(svn_config_t *cfg, svn_boolean_t *valuep,
820 const char *section, const char *option,
821 svn_boolean_t default_value)
823 const char *tmp_value;
824 svn_config_get(cfg, &tmp_value, section, option, NULL);
825 return get_bool(valuep, tmp_value, default_value, section, option);
831 svn_config_set_bool(svn_config_t *cfg,
832 const char *section, const char *option,
835 svn_config_set(cfg, section, option,
836 (value ? SVN_CONFIG_TRUE : SVN_CONFIG_FALSE));
840 svn_config_get_int64(svn_config_t *cfg,
844 apr_int64_t default_value)
846 const char *tmp_value;
847 svn_config_get(cfg, &tmp_value, section, option, NULL);
849 return svn_cstring_strtoi64(valuep, tmp_value,
850 APR_INT64_MIN, APR_INT64_MAX, 10);
852 *valuep = default_value;
857 svn_config_set_int64(svn_config_t *cfg,
862 svn_config_set(cfg, section, option,
863 apr_psprintf(cfg->pool, "%" APR_INT64_T_FMT, value));
867 svn_config_get_yes_no_ask(svn_config_t *cfg, const char **valuep,
868 const char *section, const char *option,
869 const char* default_value)
871 const char *tmp_value;
873 svn_config_get(cfg, &tmp_value, section, option, NULL);
876 tmp_value = default_value;
878 if (tmp_value && (0 == svn_cstring_casecmp(tmp_value, SVN_CONFIG_ASK)))
880 *valuep = SVN_CONFIG_ASK;
884 svn_boolean_t bool_val;
885 /* We already incorporated default_value into tmp_value if
886 necessary, so the FALSE below will be ignored unless the
887 caller is doing something it shouldn't be doing. */
888 SVN_ERR(get_bool(&bool_val, tmp_value, FALSE, section, option));
889 *valuep = bool_val ? SVN_CONFIG_TRUE : SVN_CONFIG_FALSE;
896 svn_config_get_tristate(svn_config_t *cfg, svn_tristate_t *valuep,
897 const char *section, const char *option,
898 const char *unknown_value,
899 svn_tristate_t default_value)
901 const char *tmp_value;
903 svn_config_get(cfg, &tmp_value, section, option, NULL);
907 *valuep = default_value;
909 else if (0 == svn_cstring_casecmp(tmp_value, unknown_value))
911 *valuep = svn_tristate_unknown;
915 svn_boolean_t bool_val;
916 /* We already incorporated default_value into tmp_value if
917 necessary, so the FALSE below will be ignored unless the
918 caller is doing something it shouldn't be doing. */
919 SVN_ERR(get_bool(&bool_val, tmp_value, FALSE, section, option));
920 *valuep = bool_val ? svn_tristate_true : svn_tristate_false;
927 svn_config_enumerate_sections(svn_config_t *cfg,
928 svn_config_section_enumerator_t callback,
931 apr_hash_index_t *sec_ndx;
933 apr_pool_t *subpool = svn_pool_create(cfg->x_pool);
935 for (sec_ndx = apr_hash_first(subpool, cfg->sections);
937 sec_ndx = apr_hash_next(sec_ndx))
942 apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
945 if (!callback(sec->name, baton))
949 svn_pool_destroy(subpool);
955 svn_config_enumerate_sections2(svn_config_t *cfg,
956 svn_config_section_enumerator2_t callback,
957 void *baton, apr_pool_t *pool)
959 apr_hash_index_t *sec_ndx;
960 apr_pool_t *iteration_pool;
963 iteration_pool = svn_pool_create(pool);
964 for (sec_ndx = apr_hash_first(pool, cfg->sections);
966 sec_ndx = apr_hash_next(sec_ndx))
971 apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
974 svn_pool_clear(iteration_pool);
975 if (!callback(sec->name, baton, iteration_pool))
978 svn_pool_destroy(iteration_pool);
986 svn_config_enumerate(svn_config_t *cfg, const char *section,
987 svn_config_enumerator_t callback, void *baton)
990 apr_hash_index_t *opt_ndx;
994 find_option(cfg, section, NULL, &sec);
998 subpool = svn_pool_create(cfg->pool);
1000 for (opt_ndx = apr_hash_first(subpool, sec->options);
1002 opt_ndx = apr_hash_next(opt_ndx))
1006 const char *temp_value;
1008 apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
1012 make_string_from_option(&temp_value, cfg, sec, opt, NULL);
1013 if (!callback(opt->name, temp_value, baton))
1017 svn_pool_destroy(subpool);
1023 svn_config_enumerate2(svn_config_t *cfg, const char *section,
1024 svn_config_enumerator2_t callback, void *baton,
1028 apr_hash_index_t *opt_ndx;
1029 apr_pool_t *iteration_pool;
1032 find_option(cfg, section, NULL, &sec);
1036 iteration_pool = svn_pool_create(pool);
1038 for (opt_ndx = apr_hash_first(pool, sec->options);
1040 opt_ndx = apr_hash_next(opt_ndx))
1044 const char *temp_value;
1046 apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
1050 make_string_from_option(&temp_value, cfg, sec, opt, NULL);
1051 svn_pool_clear(iteration_pool);
1052 if (!callback(opt->name, temp_value, baton, iteration_pool))
1055 svn_pool_destroy(iteration_pool);
1062 /* Baton for search_groups() */
1063 struct search_groups_baton
1065 const char *key; /* Provided by caller of svn_config_find_group */
1066 const char *match; /* Filled in by search_groups */
1071 /* This is an `svn_config_enumerator_t' function, and BATON is a
1072 * `struct search_groups_baton *'.
1074 static svn_boolean_t search_groups(const char *name,
1079 struct search_groups_baton *b = baton;
1080 apr_array_header_t *list;
1082 list = svn_cstring_split(value, ",", TRUE, pool);
1083 if (svn_cstring_match_glob_list(b->key, list))
1085 /* Fill in the match and return false, to stop enumerating. */
1086 b->match = apr_pstrdup(b->pool, name);
1094 const char *svn_config_find_group(svn_config_t *cfg, const char *key,
1095 const char *master_section,
1098 struct search_groups_baton gb;
1103 (void) svn_config_enumerate2(cfg, master_section, search_groups, &gb, pool);
1109 svn_config_get_server_setting(svn_config_t *cfg,
1110 const char* server_group,
1111 const char* option_name,
1112 const char* default_value)
1115 svn_config_get(cfg, &retval, SVN_CONFIG_SECTION_GLOBAL,
1116 option_name, default_value);
1119 svn_config_get(cfg, &retval, server_group, option_name, retval);
1126 svn_config_dup(svn_config_t **cfgp,
1127 const svn_config_t *src,
1130 apr_hash_index_t *sectidx;
1131 apr_hash_index_t *optidx;
1134 SVN_ERR(svn_config_create2(cfgp, FALSE, FALSE, pool));
1136 (*cfgp)->x_values = src->x_values;
1137 (*cfgp)->section_names_case_sensitive = src->section_names_case_sensitive;
1138 (*cfgp)->option_names_case_sensitive = src->option_names_case_sensitive;
1140 for (sectidx = apr_hash_first(pool, src->sections);
1142 sectidx = apr_hash_next(sectidx))
1144 const void *sectkey;
1146 apr_ssize_t sectkeyLength;
1147 cfg_section_t * srcsect;
1148 cfg_section_t * destsec;
1150 apr_hash_this(sectidx, §key, §keyLength, §val);
1153 destsec = svn_config_addsection(*cfgp, srcsect->name);
1155 for (optidx = apr_hash_first(pool, srcsect->options);
1157 optidx = apr_hash_next(optidx))
1161 apr_ssize_t optkeyLength;
1162 cfg_option_t *srcopt;
1163 cfg_option_t *destopt;
1165 apr_hash_this(optidx, &optkey, &optkeyLength, &optval);
1168 svn_config_create_option(&destopt, srcopt->name, srcopt->value,
1169 (*cfgp)->option_names_case_sensitive,
1172 destopt->value = apr_pstrdup(pool, srcopt->value);
1173 destopt->x_value = apr_pstrdup(pool, srcopt->x_value);
1174 destopt->expanded = srcopt->expanded;
1175 apr_hash_set(destsec->options,
1176 apr_pstrdup(pool, (const char*)optkey),
1177 optkeyLength, destopt);
1181 return SVN_NO_ERROR;
1185 svn_config_copy_config(apr_hash_t **cfg_hash,
1186 apr_hash_t *src_hash,
1189 apr_hash_index_t *cidx;
1191 *cfg_hash = apr_hash_make(pool);
1192 for (cidx = apr_hash_first(pool, src_hash);
1194 cidx = apr_hash_next(cidx))
1198 apr_ssize_t ckeyLength;
1199 svn_config_t * srcconfig;
1200 svn_config_t * destconfig;
1202 apr_hash_this(cidx, &ckey, &ckeyLength, &cval);
1205 SVN_ERR(svn_config_dup(&destconfig, srcconfig, pool));
1207 apr_hash_set(*cfg_hash,
1208 apr_pstrdup(pool, (const char*)ckey),
1209 ckeyLength, destconfig);
1212 return SVN_NO_ERROR;
1216 svn_config_get_server_setting_int(svn_config_t *cfg,
1217 const char *server_group,
1218 const char *option_name,
1219 apr_int64_t default_value,
1220 apr_int64_t *result_value,
1223 const char* tmp_value;
1226 tmp_value = svn_config_get_server_setting(cfg, server_group,
1228 if (tmp_value == NULL)
1229 *result_value = default_value;
1232 /* read tmp_value as an int now */
1233 *result_value = apr_strtoi64(tmp_value, &end_pos, 0);
1237 return svn_error_createf
1238 (SVN_ERR_BAD_CONFIG_VALUE, NULL,
1239 _("Config error: invalid integer value '%s'"),
1244 return SVN_NO_ERROR;
1248 svn_config_get_server_setting_bool(svn_config_t *cfg,
1249 svn_boolean_t *valuep,
1250 const char *server_group,
1251 const char *option_name,
1252 svn_boolean_t default_value)
1254 const char* tmp_value;
1255 tmp_value = svn_config_get_server_setting(cfg, server_group,
1257 return get_bool(valuep, tmp_value, default_value,
1258 server_group, option_name);
1263 svn_config_has_section(svn_config_t *cfg, const char *section)
1265 return NULL != get_hash_value(cfg->sections, cfg->tmp_key, section,
1266 cfg->section_names_case_sensitive);