* subversion/libsvn_subr/validate.c
[svn.git] / subversion / libsvn_subr / config.c
blobac2cde5a4f91e2dd984093c723e28c3d04eff9ad
1 /*
2 * config.c : reading configuration information
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #define APR_WANT_STRFUNC
22 #define APR_WANT_MEMFUNC
23 #include <apr_want.h>
25 #include <apr_general.h>
26 #include <apr_lib.h>
27 #include "svn_error.h"
28 #include "svn_pools.h"
29 #include "config_impl.h"
31 #include "svn_private_config.h"
36 /* Section table entries. */
37 typedef struct cfg_section_t cfg_section_t;
38 struct cfg_section_t
40 /* The section name. */
41 const char *name;
43 /* The section name, converted into a hash key. */
44 const char *hash_key;
46 /* Table of cfg_option_t's. */
47 apr_hash_t *options;
51 /* Option table entries. */
52 typedef struct cfg_option_t cfg_option_t;
53 struct cfg_option_t
55 /* The option name. */
56 const char *name;
58 /* The option name, converted into a hash key. */
59 const char *hash_key;
61 /* The unexpanded option value. */
62 const char *value;
64 /* The expanded option value. */
65 const char *x_value;
67 /* Expansion flag. If this is TRUE, this value has already been expanded.
68 In this case, if x_value is NULL, no expansions were necessary,
69 and value should be used directly. */
70 svn_boolean_t expanded;
75 svn_error_t *
76 svn_config_read(svn_config_t **cfgp, const char *file,
77 svn_boolean_t must_exist, apr_pool_t *pool)
79 svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
80 svn_error_t *err;
82 cfg->sections = apr_hash_make(pool);
83 cfg->pool = pool;
84 cfg->x_pool = svn_pool_create(pool);
85 cfg->x_values = FALSE;
86 cfg->tmp_key = svn_stringbuf_create("", pool);
87 cfg->tmp_value = svn_stringbuf_create("", pool);
89 /* Yes, this is platform-specific code in Subversion, but there's no
90 practical way to migrate it into APR, as it's simultaneously
91 Subversion-specific and Windows-specific. Even if we eventually
92 want to have APR offer a generic config-reading interface, it
93 makes sense to test it here first and migrate it later. */
94 #ifdef WIN32
95 if (0 == strncmp(file, SVN_REGISTRY_PREFIX, SVN_REGISTRY_PREFIX_LEN))
96 err = svn_config__parse_registry(cfg, file + SVN_REGISTRY_PREFIX_LEN,
97 must_exist, pool);
98 else
99 #endif /* WIN32 */
100 err = svn_config__parse_file(cfg, file, must_exist, pool);
102 if (err != SVN_NO_ERROR)
103 return err;
104 else
105 *cfgp = cfg;
107 return SVN_NO_ERROR;
112 /* Read various configuration sources into *CFGP, in this order, with
113 * later reads overriding the results of earlier ones:
115 * 1. SYS_REGISTRY_PATH (only on Win32, but ignored if NULL)
117 * 2. SYS_FILE_PATH (everywhere, but ignored if NULL)
119 * 3. USR_REGISTRY_PATH (only on Win32, but ignored if NULL)
121 * 4. USR_FILE_PATH (everywhere, but ignored if NULL)
123 * Allocate *CFGP in POOL. Even if no configurations are read,
124 * allocate an empty *CFGP.
126 static svn_error_t *
127 read_all(svn_config_t **cfgp,
128 const char *sys_registry_path,
129 const char *usr_registry_path,
130 const char *sys_file_path,
131 const char *usr_file_path,
132 apr_pool_t *pool)
134 svn_boolean_t red_config = FALSE; /* "red" is the past tense of "read" */
136 /*** Read system-wide configurations first... ***/
138 #ifdef WIN32
139 if (sys_registry_path)
141 SVN_ERR(svn_config_read(cfgp, sys_registry_path, FALSE, pool));
142 red_config = TRUE;
144 #endif /* WIN32 */
146 if (sys_file_path)
148 if (red_config)
149 SVN_ERR(svn_config_merge(*cfgp, sys_file_path, FALSE));
150 else
152 SVN_ERR(svn_config_read(cfgp, sys_file_path, FALSE, pool));
153 red_config = TRUE;
157 /*** ...followed by per-user configurations. ***/
159 #ifdef WIN32
160 if (usr_registry_path)
162 if (red_config)
163 SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE));
164 else
166 SVN_ERR(svn_config_read(cfgp, usr_registry_path, FALSE, pool));
167 red_config = TRUE;
170 #endif /* WIN32 */
172 if (usr_file_path)
174 if (red_config)
175 SVN_ERR(svn_config_merge(*cfgp, usr_file_path, FALSE));
176 else
178 SVN_ERR(svn_config_read(cfgp, usr_file_path, FALSE, pool));
179 red_config = TRUE;
183 if (! red_config)
184 *cfgp = NULL;
186 return SVN_NO_ERROR;
190 /* CONFIG_DIR provides an override for the default behavior of reading
191 the default set of overlay files described by read_all()'s doc
192 string. */
193 static svn_error_t *
194 get_category_config(svn_config_t **cfg,
195 const char *config_dir,
196 const char *category,
197 apr_pool_t *pool)
199 const char *usr_reg_path = NULL, *sys_reg_path = NULL;
200 const char *usr_cfg_path, *sys_cfg_path;
202 *cfg = NULL;
204 if (! config_dir)
206 #ifdef WIN32
207 sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,
208 category, NULL);
209 usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,
210 category, NULL);
211 #endif /* WIN32 */
213 SVN_ERR(svn_config__sys_config_path(&sys_cfg_path, category, pool));
215 else
216 sys_cfg_path = NULL;
218 SVN_ERR(svn_config__user_config_path(config_dir, &usr_cfg_path, category,
219 pool));
220 SVN_ERR(read_all(cfg,
221 sys_reg_path, usr_reg_path,
222 sys_cfg_path, usr_cfg_path,
223 pool));
225 return SVN_NO_ERROR;
229 svn_error_t *
230 svn_config_get_config(apr_hash_t **cfg_hash,
231 const char *config_dir,
232 apr_pool_t *pool)
234 svn_config_t *cfg;
235 *cfg_hash = apr_hash_make(pool);
237 #define CATLEN (sizeof(SVN_CONFIG_CATEGORY_SERVERS) - 1)
238 SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS,
239 pool));
240 if (cfg)
241 apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, CATLEN, cfg);
242 #undef CATLEN
244 #define CATLEN (sizeof(SVN_CONFIG_CATEGORY_CONFIG) - 1)
245 SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG,
246 pool));
247 if (cfg)
248 apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, CATLEN, cfg);
249 #undef CATLEN
251 return SVN_NO_ERROR;
256 /* Iterate through CFG, passing BATON to CALLBACK for every (SECTION, OPTION)
257 pair. Stop if CALLBACK returns TRUE. Allocate from POOL. */
258 static void
259 for_each_option(svn_config_t *cfg, void *baton, apr_pool_t *pool,
260 svn_boolean_t callback(void *same_baton,
261 cfg_section_t *section,
262 cfg_option_t *option))
264 apr_hash_index_t *sec_ndx;
265 for (sec_ndx = apr_hash_first(pool, cfg->sections);
266 sec_ndx != NULL;
267 sec_ndx = apr_hash_next(sec_ndx))
269 void *sec_ptr;
270 cfg_section_t *sec;
271 apr_hash_index_t *opt_ndx;
273 apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
274 sec = sec_ptr;
276 for (opt_ndx = apr_hash_first(pool, sec->options);
277 opt_ndx != NULL;
278 opt_ndx = apr_hash_next(opt_ndx))
280 void *opt_ptr;
281 cfg_option_t *opt;
283 apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
284 opt = opt_ptr;
286 if (callback(baton, sec, opt))
287 return;
294 static svn_boolean_t
295 merge_callback(void *baton, cfg_section_t *section, cfg_option_t *option)
297 svn_config_set(baton, section->name, option->name, option->value);
298 return FALSE;
301 svn_error_t *
302 svn_config_merge(svn_config_t *cfg, const char *file,
303 svn_boolean_t must_exist)
305 /* The original config hash shouldn't change if there's an error
306 while reading the confguration, so read into a temporary table.
307 ### We could use a tmp subpool for this, since merge_cfg is going
308 to be tossed afterwards. Premature optimization, though? */
309 svn_config_t *merge_cfg;
310 SVN_ERR(svn_config_read(&merge_cfg, file, must_exist, cfg->pool));
312 /* Now copy the new options into the original table. */
313 for_each_option(merge_cfg, cfg, merge_cfg->pool, merge_callback);
314 return SVN_NO_ERROR;
319 /* Remove variable expansions from CFG. Walk through the options tree,
320 killing all expanded values, then clear the expanded value pool. */
321 static svn_boolean_t
322 rmex_callback(void *baton, cfg_section_t *section, cfg_option_t *option)
324 /* Only clear the `expanded' flag if the value actually contains
325 variable expansions. */
326 if (option->expanded && option->x_value != NULL)
328 option->x_value = NULL;
329 option->expanded = FALSE;
332 return FALSE;
335 static void
336 remove_expansions(svn_config_t *cfg)
338 if (!cfg->x_values)
339 return;
341 for_each_option(cfg, NULL, cfg->x_pool, rmex_callback);
342 svn_pool_clear(cfg->x_pool);
343 cfg->x_values = FALSE;
348 /* Canonicalize a string for hashing. Modifies KEY in place. */
349 static APR_INLINE char *
350 make_hash_key(char *key)
352 register char *p;
353 for (p = key; *p != 0; ++p)
354 *p = apr_tolower(*p);
355 return key;
359 /* Return a pointer to an option in CFG, or NULL if it doesn't exist.
360 if SECTIONP is non-null, return a pointer to the option's section.
361 OPTION may be NULL. */
362 static cfg_option_t *
363 find_option(svn_config_t *cfg, const char *section, const char *option,
364 cfg_section_t **sectionp)
366 void *sec_ptr;
368 /* Canonicalize the hash key */
369 svn_stringbuf_set(cfg->tmp_key, section);
370 make_hash_key(cfg->tmp_key->data);
372 sec_ptr = apr_hash_get(cfg->sections, cfg->tmp_key->data,
373 cfg->tmp_key->len);
374 if (sectionp != NULL)
375 *sectionp = sec_ptr;
377 if (sec_ptr != NULL && option != NULL)
379 cfg_section_t *sec = sec_ptr;
380 cfg_option_t *opt;
382 /* Canonicalize the option key */
383 svn_stringbuf_set(cfg->tmp_key, option);
384 make_hash_key(cfg->tmp_key->data);
386 opt = apr_hash_get(sec->options, cfg->tmp_key->data,
387 cfg->tmp_key->len);
388 /* NOTE: ConfigParser's sections are case sensitive. */
389 if (opt == NULL
390 && apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0)
391 /* Options which aren't found in the requested section are
392 also sought after in the default section. */
393 opt = find_option(cfg, SVN_CONFIG__DEFAULT_SECTION, option, &sec);
394 return opt;
397 return NULL;
401 /* Has a bi-directional dependency with make_string_from_option(). */
402 static void
403 expand_option_value(svn_config_t *cfg, cfg_section_t *section,
404 const char *opt_value, const char **opt_x_valuep,
405 apr_pool_t *x_pool);
408 /* Set *VALUEP according to the OPT's value. A value for X_POOL must
409 only ever be passed into this function by expand_option_value(). */
410 static void
411 make_string_from_option(const char **valuep, svn_config_t *cfg,
412 cfg_section_t *section, cfg_option_t *opt,
413 apr_pool_t* x_pool)
415 /* Expand the option value if necessary. */
416 if (!opt->expanded)
418 apr_pool_t *tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool));
420 expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool);
421 opt->expanded = TRUE;
423 if (!x_pool)
425 /* Grab the fully expanded value from tmp_pool before its
426 disappearing act. */
427 if (opt->x_value)
428 opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value,
429 strlen(opt->x_value));
430 svn_pool_destroy(tmp_pool);
434 if (opt->x_value)
435 *valuep = opt->x_value;
436 else
437 *valuep = opt->value;
441 /* Start of variable-replacement placeholder */
442 #define FMT_START "%("
443 #define FMT_START_LEN (sizeof(FMT_START) - 1)
445 /* End of variable-replacement placeholder */
446 #define FMT_END ")s"
447 #define FMT_END_LEN (sizeof(FMT_END) - 1)
450 /* Expand OPT_VALUE (which may be NULL) in SECTION into *OPT_X_VALUEP.
451 If no variable replacements are done, set *OPT_X_VALUEP to
452 NULL. Allocate from X_POOL. */
453 static void
454 expand_option_value(svn_config_t *cfg, cfg_section_t *section,
455 const char *opt_value, const char **opt_x_valuep,
456 apr_pool_t *x_pool)
458 svn_stringbuf_t *buf = NULL;
459 const char *parse_from = opt_value;
460 const char *copy_from = parse_from;
461 const char *name_start, *name_end;
463 while (parse_from != NULL
464 && *parse_from != '\0'
465 && (name_start = strstr(parse_from, FMT_START)) != NULL)
467 name_start += FMT_START_LEN;
468 if (*name_start == '\0')
469 /* FMT_START at end of opt_value. */
470 break;
472 name_end = strstr(name_start, FMT_END);
473 if (name_end != NULL)
475 cfg_option_t *x_opt;
476 apr_size_t len = name_end - name_start;
477 char *name = apr_pstrmemdup(x_pool, name_start, len);
479 x_opt = find_option(cfg, section->name, name, NULL);
481 if (x_opt != NULL)
483 const char *cstring;
485 /* Pass back the sub-pool originally provided by
486 make_string_from_option() as an indication of when it
487 should terminate. */
488 make_string_from_option(&cstring, cfg, section, x_opt, x_pool);
490 /* Append the plain text preceding the expansion. */
491 len = name_start - FMT_START_LEN - copy_from;
492 if (buf == NULL)
494 buf = svn_stringbuf_ncreate(copy_from, len, x_pool);
495 cfg->x_values = TRUE;
497 else
498 svn_stringbuf_appendbytes(buf, copy_from, len);
500 /* Append the expansion and adjust parse pointers. */
501 svn_stringbuf_appendcstr(buf, cstring);
502 parse_from = name_end + FMT_END_LEN;
503 copy_from = parse_from;
505 else
506 /* Though ConfigParser considers the failure to resolve
507 the requested expansion an exception condition, we
508 consider it to be plain text, and look for the start of
509 the next one. */
510 parse_from = name_end + FMT_END_LEN;
512 else
513 /* Though ConfigParser treats unterminated format specifiers
514 as an exception condition, we consider them to be plain
515 text. The fact that there are no more format specifier
516 endings means we're done parsing. */
517 parse_from = NULL;
520 if (buf != NULL)
522 /* Copy the remainder of the plain text. */
523 svn_stringbuf_appendcstr(buf, copy_from);
524 *opt_x_valuep = buf->data;
526 else
527 *opt_x_valuep = NULL;
532 void
533 svn_config_get(svn_config_t *cfg, const char **valuep,
534 const char *section, const char *option,
535 const char *default_value)
537 if (cfg)
539 cfg_section_t *sec;
540 cfg_option_t *opt = find_option(cfg, section, option, &sec);
541 if (opt != NULL)
543 make_string_from_option(valuep, cfg, sec, opt, NULL);
545 else
547 apr_pool_t *tmp_pool = svn_pool_create(cfg->x_pool);
548 const char *x_default;
549 expand_option_value(cfg, sec, default_value, &x_default, tmp_pool);
550 if (x_default)
552 svn_stringbuf_set(cfg->tmp_value, x_default);
553 *valuep = cfg->tmp_value->data;
555 else
556 *valuep = default_value;
557 svn_pool_destroy(tmp_pool);
560 else
562 *valuep = default_value;
568 void
569 svn_config_set(svn_config_t *cfg,
570 const char *section, const char *option,
571 const char *value)
573 cfg_section_t *sec;
574 cfg_option_t *opt;
576 remove_expansions(cfg);
578 opt = find_option(cfg, section, option, &sec);
579 if (opt != NULL)
581 /* Replace the option's value. */
582 opt->value = apr_pstrdup(cfg->pool, value);
583 opt->expanded = FALSE;
584 return;
587 /* Create a new option */
588 opt = apr_palloc(cfg->pool, sizeof(*opt));
589 opt->name = apr_pstrdup(cfg->pool, option);
590 opt->hash_key = make_hash_key(apr_pstrdup(cfg->pool, option));
592 opt->value = apr_pstrdup(cfg->pool, value);
593 opt->x_value = NULL;
594 opt->expanded = FALSE;
596 if (sec == NULL)
598 /* Even the section doesn't exist. Create it. */
599 sec = apr_palloc(cfg->pool, sizeof(*sec));
600 sec->name = apr_pstrdup(cfg->pool, section);
601 sec->hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
602 sec->options = apr_hash_make(cfg->pool);
603 apr_hash_set(cfg->sections, sec->hash_key, APR_HASH_KEY_STRING, sec);
606 apr_hash_set(sec->options, opt->hash_key, APR_HASH_KEY_STRING, opt);
611 svn_error_t *
612 svn_config_get_bool(svn_config_t *cfg, svn_boolean_t *valuep,
613 const char *section, const char *option,
614 svn_boolean_t default_value)
616 const char *tmp_value;
618 svn_config_get(cfg, &tmp_value, section, option, NULL);
619 if (tmp_value == NULL)
620 *valuep = default_value;
621 else if (0 == svn_cstring_casecmp(tmp_value, SVN_CONFIG_TRUE)
622 || 0 == svn_cstring_casecmp(tmp_value, "yes")
623 || 0 == svn_cstring_casecmp(tmp_value, "on")
624 || 0 == strcmp(tmp_value, "1"))
625 *valuep = TRUE;
626 else if (0 == svn_cstring_casecmp(tmp_value, SVN_CONFIG_FALSE)
627 || 0 == svn_cstring_casecmp(tmp_value, "no")
628 || 0 == svn_cstring_casecmp(tmp_value, "off")
629 || 0 == strcmp(tmp_value, "0"))
630 *valuep = FALSE;
631 else
632 return svn_error_createf(SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL,
633 _("Config error: invalid boolean value '%s'"),
634 tmp_value);
636 return SVN_NO_ERROR;
641 void
642 svn_config_set_bool(svn_config_t *cfg,
643 const char *section, const char *option,
644 svn_boolean_t value)
646 svn_config_set(cfg, section, option,
647 (value ? SVN_CONFIG_TRUE : SVN_CONFIG_FALSE));
653 svn_config__enumerate_sections(svn_config_t *cfg,
654 svn_config__section_enumerator_t callback,
655 void *baton)
657 return svn_config_enumerate_sections(cfg,
658 (svn_config_section_enumerator_t) callback, baton);
662 svn_config_enumerate_sections(svn_config_t *cfg,
663 svn_config_section_enumerator_t callback,
664 void *baton)
666 apr_hash_index_t *sec_ndx;
667 int count = 0;
668 apr_pool_t *subpool = svn_pool_create(cfg->x_pool);
670 for (sec_ndx = apr_hash_first(subpool, cfg->sections);
671 sec_ndx != NULL;
672 sec_ndx = apr_hash_next(sec_ndx))
674 void *sec_ptr;
675 cfg_section_t *sec;
677 apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
678 sec = sec_ptr;
679 ++count;
680 if (!callback(sec->name, baton))
681 break;
684 svn_pool_destroy(subpool);
685 return count;
690 svn_config_enumerate_sections2(svn_config_t *cfg,
691 svn_config_section_enumerator2_t callback,
692 void *baton, apr_pool_t *pool)
694 apr_hash_index_t *sec_ndx;
695 apr_pool_t *iteration_pool;
696 int count = 0;
698 iteration_pool = svn_pool_create(pool);
699 for (sec_ndx = apr_hash_first(pool, cfg->sections);
700 sec_ndx != NULL;
701 sec_ndx = apr_hash_next(sec_ndx))
703 void *sec_ptr;
704 cfg_section_t *sec;
706 apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
707 sec = sec_ptr;
708 ++count;
709 svn_pool_clear(iteration_pool);
710 if (!callback(sec->name, baton, iteration_pool))
711 break;
713 svn_pool_destroy(iteration_pool);
715 return count;
721 svn_config_enumerate(svn_config_t *cfg, const char *section,
722 svn_config_enumerator_t callback, void *baton)
724 cfg_section_t *sec;
725 apr_hash_index_t *opt_ndx;
726 int count;
727 apr_pool_t *subpool;
729 find_option(cfg, section, NULL, &sec);
730 if (sec == NULL)
731 return 0;
733 subpool = svn_pool_create(cfg->x_pool);
734 count = 0;
735 for (opt_ndx = apr_hash_first(subpool, sec->options);
736 opt_ndx != NULL;
737 opt_ndx = apr_hash_next(opt_ndx))
739 void *opt_ptr;
740 cfg_option_t *opt;
741 const char *temp_value;
743 apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
744 opt = opt_ptr;
746 ++count;
747 make_string_from_option(&temp_value, cfg, sec, opt, NULL);
748 if (!callback(opt->name, temp_value, baton))
749 break;
752 svn_pool_destroy(subpool);
753 return count;
758 svn_config_enumerate2(svn_config_t *cfg, const char *section,
759 svn_config_enumerator2_t callback, void *baton,
760 apr_pool_t *pool)
762 cfg_section_t *sec;
763 apr_hash_index_t *opt_ndx;
764 apr_pool_t *iteration_pool;
765 int count;
767 find_option(cfg, section, NULL, &sec);
768 if (sec == NULL)
769 return 0;
771 iteration_pool = svn_pool_create(pool);
772 count = 0;
773 for (opt_ndx = apr_hash_first(pool, sec->options);
774 opt_ndx != NULL;
775 opt_ndx = apr_hash_next(opt_ndx))
777 void *opt_ptr;
778 cfg_option_t *opt;
779 const char *temp_value;
781 apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
782 opt = opt_ptr;
784 ++count;
785 make_string_from_option(&temp_value, cfg, sec, opt, NULL);
786 svn_pool_clear(iteration_pool);
787 if (!callback(opt->name, temp_value, baton, iteration_pool))
788 break;
790 svn_pool_destroy(iteration_pool);
792 return count;
797 /* Baton for search_groups() */
798 struct search_groups_baton
800 const char *key; /* Provided by caller of svn_config_find_group */
801 const char *match; /* Filled in by search_groups */
802 apr_pool_t *pool;
806 /* This is an `svn_config_enumerator_t' function, and BATON is a
807 * `struct search_groups_baton *'.
809 static svn_boolean_t search_groups(const char *name,
810 const char *value,
811 void *baton,
812 apr_pool_t *pool)
814 struct search_groups_baton *b = baton;
815 apr_array_header_t *list;
817 list = svn_cstring_split(value, ",", TRUE, pool);
818 if (svn_cstring_match_glob_list(b->key, list))
820 /* Fill in the match and return false, to stop enumerating. */
821 b->match = apr_pstrdup(b->pool, name);
822 return FALSE;
824 else
825 return TRUE;
829 const char *svn_config_find_group(svn_config_t *cfg, const char *key,
830 const char *master_section,
831 apr_pool_t *pool)
833 struct search_groups_baton gb;
835 gb.key = key;
836 gb.match = NULL;
837 gb.pool = pool;
838 svn_config_enumerate2(cfg, master_section, search_groups, &gb, pool);
839 return gb.match;
843 const char*
844 svn_config_get_server_setting(svn_config_t *cfg,
845 const char* server_group,
846 const char* option_name,
847 const char* default_value)
849 const char *retval;
850 svn_config_get(cfg, &retval, SVN_CONFIG_SECTION_GLOBAL,
851 option_name, default_value);
852 if (server_group)
854 svn_config_get(cfg, &retval, server_group, option_name, retval);
856 return retval;
859 svn_error_t*
860 svn_config_get_server_setting_int(svn_config_t *cfg,
861 const char *server_group,
862 const char *option_name,
863 apr_int64_t default_value,
864 apr_int64_t *result_value,
865 apr_pool_t *pool)
867 const char* tmp_value;
868 char *end_pos;
870 tmp_value = svn_config_get_server_setting(cfg, server_group,
871 option_name, NULL);
872 if (tmp_value == NULL)
873 *result_value = default_value;
874 else
876 /* read tmp_value as an int now */
877 *result_value = apr_strtoi64(tmp_value, &end_pos, 0);
879 if (*end_pos != 0)
881 return svn_error_createf
882 (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL,
883 _("Config error: invalid integer value '%s'"),
884 tmp_value);
888 return SVN_NO_ERROR;
891 svn_boolean_t
892 svn_config_has_section(svn_config_t *cfg, const char *section)
894 return apr_hash_get(cfg->sections, section, APR_HASH_KEY_STRING) != NULL;