~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_subr/config.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * config.c :  reading configuration information
 
3
 *
 
4
 * ====================================================================
 
5
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
6
 *
 
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.
 
12
 *
 
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
 * ====================================================================
 
17
 */
 
18
 
 
19
 
 
20
 
 
21
#define APR_WANT_STRFUNC
 
22
#define APR_WANT_MEMFUNC
 
23
#include <apr_want.h>
 
24
 
 
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"
 
30
 
 
31
#include "svn_private_config.h"
 
32
 
 
33
 
 
34
 
 
35
 
 
36
/* Section table entries. */
 
37
typedef struct cfg_section_t cfg_section_t;
 
38
struct cfg_section_t
 
39
{
 
40
  /* The section name. */
 
41
  const char *name;
 
42
 
 
43
  /* The section name, converted into a hash key. */
 
44
  const char *hash_key;
 
45
 
 
46
  /* Table of cfg_option_t's. */
 
47
  apr_hash_t *options;
 
48
};
 
49
 
 
50
 
 
51
/* Option table entries. */
 
52
typedef struct cfg_option_t cfg_option_t;
 
53
struct cfg_option_t
 
54
{
 
55
  /* The option name. */
 
56
  const char *name;
 
57
 
 
58
  /* The option name, converted into a hash key. */
 
59
  const char *hash_key;
 
60
 
 
61
  /* The unexpanded option value. */
 
62
  const char *value;
 
63
 
 
64
  /* The expanded option value. */
 
65
  const char *x_value;
 
66
 
 
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;
 
71
};
 
72
 
 
73
 
 
74
 
 
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)
 
78
{
 
79
  svn_config_t *cfg = apr_palloc (pool, sizeof (*cfg));
 
80
  svn_error_t *err;
 
81
 
 
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);
 
88
 
 
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);
 
98
  else
 
99
#endif /* WIN32 */
 
100
    err = svn_config__parse_file (cfg, file, must_exist);
 
101
 
 
102
  if (err != SVN_NO_ERROR)
 
103
    return err;
 
104
  else
 
105
    *cfgp = cfg;
 
106
 
 
107
  return SVN_NO_ERROR;
 
108
}
 
109
 
 
110
 
 
111
 
 
112
/* Read various configuration sources into *CFGP, in this order, with
 
113
 * later reads overriding the results of earlier ones:
 
114
 *
 
115
 *    1. SYS_REGISTRY_PATH   (only on Win32, but ignored if NULL)
 
116
 *
 
117
 *    2. SYS_FILE_PATH       (everywhere, but ignored if NULL)
 
118
 *
 
119
 *    3. USR_REGISTRY_PATH   (only on Win32, but ignored if NULL)
 
120
 *
 
121
 *    4. USR_FILE_PATH       (everywhere, but ignored if NULL)
 
122
 *
 
123
 * Allocate *CFGP in POOL.  Even if no configurations are read,
 
124
 * allocate an empty *CFGP.
 
125
 */
 
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)
 
133
{
 
134
  svn_boolean_t red_config = FALSE;  /* "red" is the past tense of "read" */
 
135
 
 
136
  /*** Read system-wide configurations first... ***/
 
137
 
 
138
#ifdef WIN32
 
139
  if (sys_registry_path)
 
140
    {
 
141
      SVN_ERR (svn_config_read (cfgp, sys_registry_path, FALSE, pool));
 
142
      red_config = TRUE;
 
143
    }
 
144
#endif /* WIN32 */
 
145
 
 
146
  if (sys_file_path)
 
147
    {
 
148
      if (red_config)
 
149
        SVN_ERR (svn_config_merge (*cfgp, sys_file_path, FALSE));
 
150
      else
 
151
        {
 
152
          SVN_ERR (svn_config_read (cfgp, sys_file_path, FALSE, pool));
 
153
          red_config = TRUE;
 
154
        }
 
155
    }
 
156
 
 
157
  /*** ...followed by per-user configurations. ***/
 
158
 
 
159
#ifdef WIN32
 
160
  if (usr_registry_path)
 
161
    {
 
162
      if (red_config)
 
163
        SVN_ERR (svn_config_merge (*cfgp, usr_registry_path, FALSE));
 
164
      else
 
165
        {
 
166
          SVN_ERR (svn_config_read (cfgp, usr_registry_path, FALSE, pool));
 
167
          red_config = TRUE;
 
168
        }
 
169
    }
 
170
#endif /* WIN32 */
 
171
 
 
172
  if (usr_file_path)
 
173
    {
 
174
      if (red_config)
 
175
        SVN_ERR (svn_config_merge (*cfgp, usr_file_path, FALSE));
 
176
      else
 
177
        {
 
178
          SVN_ERR (svn_config_read (cfgp, usr_file_path, FALSE, pool));
 
179
          red_config = TRUE;
 
180
        }
 
181
    }
 
182
 
 
183
  if (! red_config)
 
184
    *cfgp = NULL;
 
185
 
 
186
  return SVN_NO_ERROR;
 
187
}
 
188
 
 
189
 
 
190
static svn_error_t *
 
191
get_category_config (svn_config_t **cfg,
 
192
                     const char *config_dir,
 
193
                     const char *category,
 
194
                     apr_pool_t *pool)
 
195
{
 
196
  const char *usr_reg_path = NULL, *sys_reg_path = NULL;
 
197
  const char *usr_cfg_path, *sys_cfg_path;
 
198
  
 
199
  *cfg = NULL;
 
200
 
 
201
  if (! config_dir)
 
202
    {
 
203
#ifdef WIN32
 
204
      sys_reg_path = apr_pstrcat (pool, SVN_REGISTRY_SYS_CONFIG_PATH,
 
205
                                  category, NULL);
 
206
      usr_reg_path = apr_pstrcat (pool, SVN_REGISTRY_USR_CONFIG_PATH,
 
207
                                  category, NULL);
 
208
#endif /* WIN32 */
 
209
 
 
210
      SVN_ERR (svn_config__sys_config_path (&sys_cfg_path, category, pool));
 
211
    }
 
212
  else
 
213
    sys_cfg_path = NULL;
 
214
 
 
215
  SVN_ERR (svn_config__user_config_path (config_dir, &usr_cfg_path, category,
 
216
                                         pool));
 
217
  SVN_ERR (read_all (cfg,
 
218
                     sys_reg_path, usr_reg_path,
 
219
                     sys_cfg_path, usr_cfg_path,
 
220
                     pool));
 
221
 
 
222
  return SVN_NO_ERROR;
 
223
}
 
224
 
 
225
 
 
226
svn_error_t *
 
227
svn_config_get_config (apr_hash_t **cfg_hash,
 
228
                       const char *config_dir,
 
229
                       apr_pool_t *pool)
 
230
{
 
231
  svn_config_t *cfg;
 
232
  *cfg_hash = apr_hash_make (pool);
 
233
  
 
234
#define CATLEN (sizeof (SVN_CONFIG_CATEGORY_SERVERS) - 1)
 
235
  SVN_ERR (get_category_config (&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS,
 
236
                                pool));
 
237
  if (cfg)
 
238
    apr_hash_set (*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, CATLEN, cfg);
 
239
#undef CATLEN
 
240
 
 
241
#define CATLEN (sizeof (SVN_CONFIG_CATEGORY_CONFIG) - 1)
 
242
  SVN_ERR (get_category_config (&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG,
 
243
                                pool));
 
244
  if (cfg)
 
245
    apr_hash_set (*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, CATLEN, cfg);
 
246
#undef CATLEN
 
247
 
 
248
  return SVN_NO_ERROR;
 
249
}
 
250
 
 
251
 
 
252
 
 
253
/* Iterate through CFG, passing BATON to CALLBACK for every (SECTION, OPTION)
 
254
   pair.  Stop if CALLBACK returns TRUE.  Allocate from POOL. */
 
255
static void
 
256
for_each_option (svn_config_t *cfg, void *baton, apr_pool_t *pool,
 
257
                 svn_boolean_t callback (void *same_baton,
 
258
                                         cfg_section_t *section,
 
259
                                         cfg_option_t *option))
 
260
{
 
261
  apr_hash_index_t *sec_ndx;
 
262
  for (sec_ndx = apr_hash_first (pool, cfg->sections);
 
263
       sec_ndx != NULL;
 
264
       sec_ndx = apr_hash_next (sec_ndx))
 
265
    {
 
266
      void *sec_ptr;
 
267
      cfg_section_t *sec;
 
268
      apr_hash_index_t *opt_ndx;
 
269
 
 
270
      apr_hash_this (sec_ndx, NULL, NULL, &sec_ptr);
 
271
      sec = sec_ptr;
 
272
 
 
273
      for (opt_ndx = apr_hash_first (pool, sec->options);
 
274
           opt_ndx != NULL;
 
275
           opt_ndx = apr_hash_next (opt_ndx))
 
276
        {
 
277
          void *opt_ptr;
 
278
          cfg_option_t *opt;
 
279
 
 
280
          apr_hash_this (opt_ndx, NULL, NULL, &opt_ptr);
 
281
          opt = opt_ptr;
 
282
 
 
283
          if (callback (baton, sec, opt))
 
284
            return;
 
285
        }
 
286
    }
 
287
}
 
288
 
 
289
 
 
290
 
 
291
static svn_boolean_t
 
292
merge_callback (void *baton, cfg_section_t *section, cfg_option_t *option)
 
293
{
 
294
  svn_config_set (baton, section->name, option->name, option->value);
 
295
  return FALSE;
 
296
}
 
297
 
 
298
svn_error_t *
 
299
svn_config_merge (svn_config_t *cfg, const char *file,
 
300
                  svn_boolean_t must_exist)
 
301
{
 
302
  /* The original config hash shouldn't change if there's an error
 
303
     while reading the confguration, so read into a temporary table.
 
304
     ### We could use a tmp subpool for this, since merge_cfg is going
 
305
     to be tossed afterwards.  Premature optimization, though? */
 
306
  svn_config_t *merge_cfg;
 
307
  SVN_ERR (svn_config_read (&merge_cfg, file, must_exist, cfg->pool));
 
308
 
 
309
  /* Now copy the new options into the original table. */
 
310
  for_each_option (merge_cfg, cfg, merge_cfg->pool, merge_callback);
 
311
  return SVN_NO_ERROR;
 
312
}
 
313
 
 
314
 
 
315
 
 
316
/* Remove variable expansions from CFG.  Walk through the options tree,
 
317
   killing all expanded values, then clear the expanded value pool. */
 
318
static svn_boolean_t
 
319
rmex_callback (void *baton, cfg_section_t *section, cfg_option_t *option)
 
320
{
 
321
  /* Only clear the `expanded' flag if the value actually contains
 
322
     variable expansions. */
 
323
  if (option->expanded && option->x_value != NULL)
 
324
    {
 
325
      option->x_value = NULL;
 
326
      option->expanded = FALSE;
 
327
    }
 
328
 
 
329
  (void)(baton);                /* Unused parameter. */
 
330
  (void)(section);              /* Unused parameter. */
 
331
  return FALSE;
 
332
}
 
333
 
 
334
static void
 
335
remove_expansions (svn_config_t *cfg)
 
336
{
 
337
  if (!cfg->x_values)
 
338
    return;
 
339
 
 
340
  for_each_option (cfg, NULL, cfg->x_pool, rmex_callback);
 
341
  apr_pool_clear (cfg->x_pool);
 
342
  cfg->x_values = FALSE;
 
343
}
 
344
 
 
345
 
 
346
 
 
347
/* Canonicalize a string for hashing.  Modifies KEY in place. */
 
348
static APR_INLINE char *
 
349
make_hash_key (char *key)
 
350
{
 
351
  register char *p;
 
352
  for (p = key; *p != 0; ++p)
 
353
    *p = apr_tolower (*p);
 
354
  return key;
 
355
}
 
356
 
 
357
 
 
358
/* Return a pointer to an option in CFG, or NULL if it doesn't exist.
 
359
   if SECTIONP is non-null, return a pointer to the option's section.
 
360
   OPTION may be NULL. */
 
361
static cfg_option_t *
 
362
find_option (svn_config_t *cfg, const char *section, const char *option,
 
363
             cfg_section_t **sectionp)
 
364
{
 
365
  void *sec_ptr;
 
366
 
 
367
  /* Canonicalize the hash key */
 
368
  svn_stringbuf_set (cfg->tmp_key, section);
 
369
  make_hash_key (cfg->tmp_key->data);
 
370
 
 
371
  sec_ptr = apr_hash_get (cfg->sections, cfg->tmp_key->data,
 
372
                          cfg->tmp_key->len);
 
373
  if (sectionp != NULL)
 
374
    *sectionp = sec_ptr;
 
375
 
 
376
  if (sec_ptr != NULL && option != NULL)
 
377
    {
 
378
      cfg_section_t *sec = sec_ptr;
 
379
      cfg_option_t *opt;
 
380
 
 
381
      /* Canonicalize the option key */
 
382
      svn_stringbuf_set (cfg->tmp_key, option);
 
383
      make_hash_key (cfg->tmp_key->data);
 
384
 
 
385
      opt = apr_hash_get (sec->options, cfg->tmp_key->data,
 
386
                          cfg->tmp_key->len);
 
387
      /* NOTE: ConfigParser's sections are case sensitive. */
 
388
      if (opt == NULL
 
389
          && apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0)
 
390
        /* Options which aren't found in the requested section are
 
391
           also sought after in the default section. */
 
392
        opt = find_option (cfg, SVN_CONFIG__DEFAULT_SECTION, option, &sec);
 
393
      return opt;
 
394
    }
 
395
 
 
396
  return NULL;
 
397
}
 
398
 
 
399
 
 
400
/* Has a bi-directional dependency with make_string_from_option(). */
 
401
static void
 
402
expand_option_value (svn_config_t *cfg, cfg_section_t *section,
 
403
                     const char *opt_value, const char **opt_x_valuep,
 
404
                     apr_pool_t *x_pool);
 
405
 
 
406
 
 
407
/* Set *VALUEP according to the OPT's value.  A value for X_POOL must
 
408
   only ever be passed into this function by expand_option_value(). */
 
409
static void
 
410
make_string_from_option (const char **valuep, svn_config_t *cfg,
 
411
                         cfg_section_t *section, cfg_option_t *opt,
 
412
                         apr_pool_t* x_pool)
 
413
{
 
414
  /* Expand the option value if necessary. */
 
415
  if (!opt->expanded)
 
416
    {
 
417
      apr_pool_t *tmp_pool = (x_pool ? x_pool : svn_pool_create (cfg->x_pool));
 
418
 
 
419
      expand_option_value (cfg, section, opt->value, &opt->x_value, tmp_pool);
 
420
      opt->expanded = TRUE;
 
421
 
 
422
      if (!x_pool)
 
423
        {
 
424
          /* Grab the fully expanded value from tmp_pool before its
 
425
             disappearing act. */
 
426
          if (opt->x_value)
 
427
            opt->x_value = apr_pstrmemdup (cfg->x_pool, opt->x_value,
 
428
                                           strlen (opt->x_value));
 
429
          svn_pool_destroy (tmp_pool);
 
430
        }
 
431
    }
 
432
 
 
433
  if (opt->x_value)
 
434
    *valuep = opt->x_value;
 
435
  else
 
436
    *valuep = opt->value;
 
437
}
 
438
 
 
439
 
 
440
/* Start of variable-replacement placeholder */
 
441
#define FMT_START     "%("
 
442
#define FMT_START_LEN (sizeof (FMT_START) - 1)
 
443
 
 
444
/* End of variable-replacement placeholder */
 
445
#define FMT_END       ")s"
 
446
#define FMT_END_LEN   (sizeof (FMT_END) - 1)
 
447
 
 
448
 
 
449
/* Expand OPT_VALUE in SECTION to *OPT_X_VALUE. If no variable
 
450
   replacements are done, set OPT_X_VALUE to NULL. Allocate from
 
451
   X_POOL */
 
452
static void
 
453
expand_option_value (svn_config_t *cfg, cfg_section_t *section,
 
454
                     const char *opt_value, const char **opt_x_valuep,
 
455
                     apr_pool_t *x_pool)
 
456
{
 
457
  svn_stringbuf_t *buf = NULL;
 
458
  const char *parse_from = opt_value;
 
459
  const char *copy_from = parse_from;
 
460
  const char *name_start, *name_end;
 
461
 
 
462
  while (parse_from != NULL
 
463
         && *parse_from != '\0'
 
464
         && (name_start = strstr (parse_from, FMT_START)) != NULL)
 
465
    {
 
466
      name_start += FMT_START_LEN;
 
467
      if (*name_start == '\0')
 
468
        /* FMT_START at end of opt_value. */
 
469
        break;
 
470
 
 
471
      name_end = strstr (name_start, FMT_END);
 
472
      if (name_end != NULL)
 
473
        {
 
474
          cfg_option_t *x_opt;
 
475
          apr_size_t len = name_end - name_start;
 
476
          char *name = apr_pstrmemdup (x_pool, name_start, len);
 
477
 
 
478
          x_opt = find_option (cfg, section->name, name, NULL);
 
479
 
 
480
          if (x_opt != NULL)
 
481
            {
 
482
              const char *cstring;
 
483
 
 
484
              /* Pass back the sub-pool originally provided by
 
485
                 make_string_from_option() as an indication of when it
 
486
                 should terminate. */
 
487
              make_string_from_option (&cstring, cfg, section, x_opt, x_pool);
 
488
 
 
489
              /* Append the plain text preceding the expansion. */
 
490
              len = name_start - FMT_START_LEN - copy_from;
 
491
              if (buf == NULL)
 
492
                {
 
493
                  buf = svn_stringbuf_ncreate (copy_from, len, x_pool);
 
494
                  cfg->x_values = TRUE;
 
495
                }
 
496
              else
 
497
                svn_stringbuf_appendbytes(buf, copy_from, len);
 
498
 
 
499
              /* Append the expansion and adjust parse pointers. */
 
500
              svn_stringbuf_appendcstr (buf, cstring);
 
501
              parse_from = name_end + FMT_END_LEN;
 
502
              copy_from = parse_from;
 
503
            }
 
504
          else
 
505
            /* Though ConfigParser considers the failure to resolve
 
506
               the requested expansion an exception condition, we
 
507
               consider it to be plain text, and look for the start of
 
508
               the next one. */
 
509
            parse_from = name_end + FMT_END_LEN;
 
510
        }
 
511
      else
 
512
        /* Though ConfigParser treats unterminated format specifiers
 
513
           as an exception condition, we consider them to be plain
 
514
           text.  The fact that there are no more format specifier
 
515
           endings means we're done parsing. */
 
516
        parse_from = NULL;
 
517
    }
 
518
 
 
519
  if (buf != NULL)
 
520
    {
 
521
      /* Copy the remainder of the plain text. */
 
522
      svn_stringbuf_appendcstr (buf, copy_from);
 
523
      *opt_x_valuep = buf->data;
 
524
    }
 
525
  else
 
526
    *opt_x_valuep = NULL;
 
527
}
 
528
 
 
529
 
 
530
 
 
531
void
 
532
svn_config_get (svn_config_t *cfg, const char **valuep,
 
533
                const char *section, const char *option,
 
534
                const char *default_value)
 
535
{
 
536
  if (cfg)
 
537
    {
 
538
      cfg_section_t *sec;
 
539
      cfg_option_t *opt = find_option (cfg, section, option, &sec);
 
540
      if (opt != NULL)
 
541
        {
 
542
          make_string_from_option (valuep, cfg, sec, opt, NULL);
 
543
        }
 
544
      else
 
545
        {
 
546
          apr_pool_t *tmp_pool = svn_pool_create (cfg->x_pool);
 
547
          const char *x_default;
 
548
          expand_option_value (cfg, sec, default_value, &x_default, tmp_pool);
 
549
          if (x_default)
 
550
            {
 
551
              svn_stringbuf_set (cfg->tmp_value, x_default);
 
552
              *valuep = cfg->tmp_value->data;
 
553
            }
 
554
          else
 
555
            *valuep = default_value;
 
556
          svn_pool_destroy (tmp_pool);
 
557
        }
 
558
    }
 
559
  else
 
560
    {
 
561
      *valuep = default_value;
 
562
    }
 
563
}
 
564
 
 
565
 
 
566
 
 
567
void
 
568
svn_config_set (svn_config_t *cfg,
 
569
                const char *section, const char *option,
 
570
                const char *value)
 
571
{
 
572
  cfg_section_t *sec;
 
573
  cfg_option_t *opt;
 
574
 
 
575
  remove_expansions (cfg);
 
576
 
 
577
  opt = find_option (cfg, section, option, &sec);
 
578
  if (opt != NULL)
 
579
    {
 
580
      /* Replace the option's value. */
 
581
      opt->value = apr_pstrdup (cfg->pool, value);
 
582
      opt->expanded = FALSE;
 
583
      return;
 
584
    }
 
585
 
 
586
  /* Create a new option */
 
587
  opt = apr_palloc (cfg->pool, sizeof (*opt));
 
588
  opt->name = apr_pstrdup (cfg->pool, option);
 
589
  opt->hash_key = make_hash_key (apr_pstrdup (cfg->pool, option));
 
590
 
 
591
  opt->value = apr_pstrdup (cfg->pool, value);
 
592
  opt->x_value = NULL;
 
593
  opt->expanded = FALSE;
 
594
 
 
595
  if (sec == NULL)
 
596
    {
 
597
      /* Even the section doesn't exist. Create it. */
 
598
      sec = apr_palloc (cfg->pool, sizeof (*sec));
 
599
      sec->name = apr_pstrdup (cfg->pool, section);
 
600
      sec->hash_key = make_hash_key (apr_pstrdup (cfg->pool, section));
 
601
      sec->options = apr_hash_make (cfg->pool);
 
602
      apr_hash_set (cfg->sections, sec->hash_key, APR_HASH_KEY_STRING, sec);
 
603
    }
 
604
 
 
605
  apr_hash_set (sec->options, opt->hash_key, APR_HASH_KEY_STRING, opt);
 
606
}
 
607
 
 
608
 
 
609
 
 
610
svn_error_t *
 
611
svn_config_get_bool (svn_config_t *cfg, svn_boolean_t *valuep,
 
612
                     const char *section, const char *option,
 
613
                     svn_boolean_t default_value)
 
614
{
 
615
  const char *tmp_value;
 
616
 
 
617
  svn_config_get (cfg, &tmp_value, section, option, NULL);
 
618
  if (tmp_value == NULL)
 
619
    *valuep = default_value;
 
620
  else if (0 == strcasecmp (tmp_value, SVN_CONFIG_TRUE)
 
621
           || 0 == strcasecmp (tmp_value, "yes")
 
622
           || 0 == strcasecmp (tmp_value, "on")
 
623
           || 0 == strcmp (tmp_value, "1"))
 
624
    *valuep = TRUE;
 
625
  else if (0 == strcasecmp (tmp_value, SVN_CONFIG_FALSE)
 
626
           || 0 == strcasecmp (tmp_value, "no")
 
627
           || 0 == strcasecmp (tmp_value, "off")
 
628
           || 0 == strcmp (tmp_value, "0"))
 
629
    *valuep = FALSE;
 
630
  else
 
631
    return svn_error_createf (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL,
 
632
                              _("Config error: invalid boolean value '%s'"),
 
633
                              tmp_value);
 
634
 
 
635
  return SVN_NO_ERROR;
 
636
}
 
637
 
 
638
 
 
639
 
 
640
void
 
641
svn_config_set_bool (svn_config_t *cfg,
 
642
                     const char *section, const char *option,
 
643
                     svn_boolean_t value)
 
644
{
 
645
  svn_config_set (cfg, section, option,
 
646
                  (value ? SVN_CONFIG_TRUE : SVN_CONFIG_FALSE));
 
647
}
 
648
 
 
649
 
 
650
 
 
651
int
 
652
svn_config__enumerate_sections (svn_config_t *cfg,
 
653
                               svn_config__section_enumerator_t callback,
 
654
                                void *baton)
 
655
{
 
656
  return svn_config_enumerate_sections (cfg,
 
657
           (svn_config_section_enumerator_t) callback, baton);
 
658
}
 
659
 
 
660
int
 
661
svn_config_enumerate_sections (svn_config_t *cfg,
 
662
                               svn_config_section_enumerator_t callback,
 
663
                               void *baton)
 
664
{
 
665
  apr_hash_index_t *sec_ndx;
 
666
  int count = 0;
 
667
 
 
668
  for (sec_ndx = apr_hash_first (cfg->x_pool, cfg->sections);
 
669
       sec_ndx != NULL;
 
670
       sec_ndx = apr_hash_next (sec_ndx))
 
671
    {
 
672
      void *sec_ptr;
 
673
      cfg_section_t *sec;
 
674
 
 
675
      apr_hash_this (sec_ndx, NULL, NULL, &sec_ptr);
 
676
      sec = sec_ptr;
 
677
      ++count;
 
678
      if (!callback (sec->name, baton))
 
679
        break;
 
680
    }
 
681
 
 
682
  return count;
 
683
}
 
684
 
 
685
 
 
686
 
 
687
int
 
688
svn_config_enumerate (svn_config_t *cfg, const char *section,
 
689
                      svn_config_enumerator_t callback, void *baton)
 
690
{
 
691
  cfg_section_t *sec;
 
692
  apr_hash_index_t *opt_ndx;
 
693
  int count;
 
694
 
 
695
  find_option (cfg, section, NULL, &sec);
 
696
  if (sec == NULL)
 
697
    return 0;
 
698
 
 
699
  count = 0;
 
700
  for (opt_ndx = apr_hash_first (cfg->x_pool, sec->options);
 
701
       opt_ndx != NULL;
 
702
       opt_ndx = apr_hash_next (opt_ndx))
 
703
    {
 
704
      void *opt_ptr;
 
705
      cfg_option_t *opt;
 
706
      const char *temp_value;
 
707
 
 
708
      apr_hash_this (opt_ndx, NULL, NULL, &opt_ptr);
 
709
      opt = opt_ptr;
 
710
 
 
711
      ++count;
 
712
      make_string_from_option (&temp_value, cfg, sec, opt, NULL);
 
713
      if (!callback (opt->name, temp_value, baton))
 
714
        break;
 
715
    }
 
716
 
 
717
  return count;
 
718
}
 
719
 
 
720
 
 
721
 
 
722
/* Baton for search_groups() */
 
723
struct search_groups_baton
 
724
{
 
725
  const char *key;          /* Provided by caller of svn_config_find_group */
 
726
  const char *match;        /* Filled in by search_groups */
 
727
  apr_pool_t *pool;
 
728
};
 
729
 
 
730
 
 
731
/* This is an `svn_config_enumerator_t' function, and BATON is a
 
732
 * `struct search_groups_baton *'.
 
733
 */
 
734
static svn_boolean_t search_groups (const char *name,
 
735
                                    const char *value,
 
736
                                    void *baton)
 
737
{
 
738
  struct search_groups_baton *b = baton;
 
739
  apr_array_header_t *list;
 
740
 
 
741
  list = svn_cstring_split (value, ",", TRUE, b->pool);
 
742
  if (svn_cstring_match_glob_list (b->key, list))
 
743
    {
 
744
      /* Fill in the match and return false, to stop enumerating. */
 
745
      b->match = apr_pstrdup (b->pool, name);
 
746
      return FALSE;
 
747
    }
 
748
  else
 
749
    return TRUE;
 
750
}
 
751
 
 
752
 
 
753
const char *svn_config_find_group (svn_config_t *cfg, const char *key,
 
754
                                   const char *master_section,
 
755
                                   apr_pool_t *pool)
 
756
{
 
757
  struct search_groups_baton gb;
 
758
 
 
759
  gb.key = key;
 
760
  gb.match = NULL;
 
761
  gb.pool = pool;
 
762
  svn_config_enumerate (cfg, master_section, search_groups, &gb);
 
763
  return gb.match;
 
764
}
 
765
 
 
766
 
 
767
const char*
 
768
svn_config_get_server_setting (svn_config_t *cfg,
 
769
                               const char* server_group,
 
770
                               const char* option_name,
 
771
                               const char* default_value)
 
772
{
 
773
  const char *retval;
 
774
  svn_config_get (cfg, &retval, SVN_CONFIG_SECTION_GLOBAL,
 
775
                  option_name, default_value);
 
776
  if (server_group)
 
777
    {
 
778
      svn_config_get (cfg, &retval, server_group, option_name, retval);
 
779
    }
 
780
  return retval;
 
781
}
 
782
 
 
783
svn_error_t*
 
784
svn_config_get_server_setting_int (svn_config_t *cfg,
 
785
                                   const char *server_group,
 
786
                                   const char *option_name,
 
787
                                   apr_int64_t default_value,
 
788
                                   apr_int64_t *result_value,
 
789
                                   apr_pool_t *pool)
 
790
{
 
791
  const char* tmp_value;
 
792
  char *end_pos;
 
793
 
 
794
  tmp_value = svn_config_get_server_setting (cfg, server_group,
 
795
                                             option_name, NULL);
 
796
  if (tmp_value == NULL)
 
797
    *result_value = default_value;
 
798
  else
 
799
    {
 
800
      /* read tmp_value as an int now */
 
801
      *result_value = apr_strtoi64 (tmp_value, &end_pos, 0);
 
802
 
 
803
      if (*end_pos != 0)
 
804
        {
 
805
          return svn_error_createf
 
806
            (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL,
 
807
             _("Config error: invalid integer value '%s'"),
 
808
             tmp_value);
 
809
        }
 
810
    }
 
811
 
 
812
  return SVN_NO_ERROR;
 
813
}
 
814