]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_subr/config_file.c
MFC r309356: svn 1.9.4 -> 1.9.5
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_subr / config_file.c
1 /*
2  * config_file.c :  parsing configuration files
3  *
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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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
20  *    under the License.
21  * ====================================================================
22  */
23
24
25 \f
26 #include <apr_lib.h>
27 #include <apr_env.h>
28 #include "config_impl.h"
29 #include "svn_io.h"
30 #include "svn_types.h"
31 #include "svn_dirent_uri.h"
32 #include "svn_auth.h"
33 #include "svn_hash.h"
34 #include "svn_subst.h"
35 #include "svn_utf.h"
36 #include "svn_pools.h"
37 #include "svn_user.h"
38 #include "svn_ctype.h"
39
40 #include "svn_private_config.h"
41 #include "private/svn_subr_private.h"
42
43 #ifdef __HAIKU__
44 #  include <FindDirectory.h>
45 #  include <StorageDefs.h>
46 #endif
47
48 /* Used to terminate lines in large multi-line string literals. */
49 #define NL APR_EOL_STR
50
51 \f
52 /* File parsing context */
53 typedef struct parse_context_t
54 {
55   /* This config struct */
56   svn_config_t *cfg;
57
58   /* The stream struct */
59   svn_stream_t *stream;
60
61   /* The current line in the file */
62   int line;
63
64   /* Emulate an ungetc */
65   int ungotten_char;
66
67   /* Temporary strings */
68   svn_stringbuf_t *section;
69   svn_stringbuf_t *option;
70   svn_stringbuf_t *value;
71
72   /* Parser buffer for getc() to avoid call overhead into several libraries
73      for every character */
74   char parser_buffer[SVN__STREAM_CHUNK_SIZE]; /* Larger than most config files */
75   size_t buffer_pos; /* Current position within parser_buffer */
76   size_t buffer_size; /* parser_buffer contains this many bytes */
77
78   /* Non-zero if we hit EOF on the stream. */
79   svn_boolean_t hit_stream_eof;
80 } parse_context_t;
81
82
83
84 /* Emulate getc() because streams don't support it.
85  *
86  * In order to be able to ungetc(), use the CXT instead of the stream
87  * to be able to store the 'ungotton' character.
88  *
89  */
90 static APR_INLINE svn_error_t *
91 parser_getc(parse_context_t *ctx, int *c)
92 {
93   do
94     {
95       if (ctx->ungotten_char != EOF)
96         {
97           *c = ctx->ungotten_char;
98           ctx->ungotten_char = EOF;
99         }
100       else if (ctx->buffer_pos < ctx->buffer_size)
101         {
102           *c = (unsigned char)ctx->parser_buffer[ctx->buffer_pos];
103           ctx->buffer_pos++;
104         }
105       else
106         {
107           if (!ctx->hit_stream_eof)
108             {
109               ctx->buffer_pos = 0;
110               ctx->buffer_size = sizeof(ctx->parser_buffer);
111
112               SVN_ERR(svn_stream_read_full(ctx->stream, ctx->parser_buffer,
113                                            &(ctx->buffer_size)));
114               ctx->hit_stream_eof = (ctx->buffer_size != sizeof(ctx->parser_buffer));
115             }
116
117           if (ctx->buffer_pos < ctx->buffer_size)
118             {
119               *c = (unsigned char)ctx->parser_buffer[ctx->buffer_pos];
120               ctx->buffer_pos++;
121             }
122           else
123             *c = EOF;
124         }
125     }
126   while (*c == '\r');
127
128   return SVN_NO_ERROR;
129 }
130
131 /* Simplified version of parser_getc() to be used inside skipping loops.
132  * It will not check for 'ungotton' chars and may or may not ignore '\r'.
133  *
134  * In a 'while(cond) getc();' loop, the first iteration must call
135  * parser_getc to handle all the special cases.  Later iterations should
136  * use parser_getc_plain for maximum performance.
137  */
138 static APR_INLINE svn_error_t *
139 parser_getc_plain(parse_context_t *ctx, int *c)
140 {
141   if (ctx->buffer_pos < ctx->buffer_size)
142     {
143       *c = (unsigned char)ctx->parser_buffer[ctx->buffer_pos];
144       ctx->buffer_pos++;
145
146       return SVN_NO_ERROR;
147     }
148
149   return parser_getc(ctx, c);
150 }
151
152 /* Emulate ungetc() because streams don't support it.
153  *
154  * Use CTX to store the ungotten character C.
155  */
156 static APR_INLINE svn_error_t *
157 parser_ungetc(parse_context_t *ctx, int c)
158 {
159   ctx->ungotten_char = c;
160
161   return SVN_NO_ERROR;
162 }
163
164 /* Eat chars from STREAM until encounter non-whitespace, newline, or EOF.
165    Set *PCOUNT to the number of characters eaten, not counting the
166    last one, and return the last char read (the one that caused the
167    break).  */
168 static APR_INLINE svn_error_t *
169 skip_whitespace(parse_context_t *ctx, int *c, int *pcount)
170 {
171   int ch = 0;
172   int count = 0;
173
174   SVN_ERR(parser_getc(ctx, &ch));
175   while (svn_ctype_isspace(ch) && ch != '\n' && ch != EOF)
176     {
177       ++count;
178       SVN_ERR(parser_getc_plain(ctx, &ch));
179     }
180   *pcount = count;
181   *c = ch;
182   return SVN_NO_ERROR;
183 }
184
185
186 /* Skip to the end of the line (or file).  Returns the char that ended
187    the line; the char is either EOF or newline. */
188 static APR_INLINE svn_error_t *
189 skip_to_eoln(parse_context_t *ctx, int *c)
190 {
191   int ch;
192
193   SVN_ERR(parser_getc(ctx, &ch));
194   while (ch != '\n' && ch != EOF)
195     {
196       /* This is much faster than checking individual bytes.
197        * We use this function a lot when skipping comment lines.
198        *
199        * This assumes that the ungetc buffer is empty, but that is a
200        * safe assumption right after reading a character (which would
201        * clear the buffer. */
202       const char *newline = memchr(ctx->parser_buffer + ctx->buffer_pos, '\n',
203                                    ctx->buffer_size - ctx->buffer_pos);
204       if (newline)
205         {
206           ch = '\n';
207           ctx->buffer_pos = newline - ctx->parser_buffer + 1;
208           break;
209         }
210
211       /* refill buffer, check for EOF */
212       SVN_ERR(parser_getc_plain(ctx, &ch));
213     }
214
215   *c = ch;
216   return SVN_NO_ERROR;
217 }
218
219 /* Skip a UTF-8 Byte Order Mark if found. */
220 static APR_INLINE svn_error_t *
221 skip_bom(parse_context_t *ctx)
222 {
223   int ch;
224
225   SVN_ERR(parser_getc(ctx, &ch));
226   if (ch == 0xEF)
227     {
228       const unsigned char *buf = (unsigned char *)ctx->parser_buffer;
229       /* This makes assumptions about the implementation of parser_getc and
230        * the use of skip_bom.  Specifically that parser_getc() will get all
231        * of the BOM characters into the parse_context_t buffer.  This can
232        * safely be assumed as long as we only try to use skip_bom() at the
233        * start of the stream and the buffer is longer than 3 characters. */
234       SVN_ERR_ASSERT(ctx->buffer_size > ctx->buffer_pos + 1 ||
235                      ctx->hit_stream_eof);
236       if (ctx->buffer_size > ctx->buffer_pos + 1 &&
237           buf[ctx->buffer_pos] == 0xBB && buf[ctx->buffer_pos + 1] == 0xBF)
238         ctx->buffer_pos += 2;
239       else
240         SVN_ERR(parser_ungetc(ctx, ch));
241     }
242   else
243     SVN_ERR(parser_ungetc(ctx, ch));
244
245   return SVN_NO_ERROR;
246 }
247
248 /* Parse a single option value */
249 static svn_error_t *
250 parse_value(int *pch, parse_context_t *ctx)
251 {
252   svn_boolean_t end_of_val = FALSE;
253   int ch;
254
255   /* Read the first line of the value */
256   svn_stringbuf_setempty(ctx->value);
257   SVN_ERR(parser_getc(ctx, &ch));
258   while (ch != EOF && ch != '\n')
259     /* last ch seen was ':' or '=' in parse_option. */
260     {
261       const char char_from_int = (char)ch;
262       svn_stringbuf_appendbyte(ctx->value, char_from_int);
263       SVN_ERR(parser_getc(ctx, &ch));
264     }
265   /* Leading and trailing whitespace is ignored. */
266   svn_stringbuf_strip_whitespace(ctx->value);
267
268   /* Look for any continuation lines. */
269   for (;;)
270     {
271
272       if (ch == EOF || end_of_val)
273         {
274           /* At end of file. The value is complete, there can't be
275              any continuation lines. */
276           svn_config_set(ctx->cfg, ctx->section->data,
277                          ctx->option->data, ctx->value->data);
278           break;
279         }
280       else
281         {
282           int count;
283           ++ctx->line;
284           SVN_ERR(skip_whitespace(ctx, &ch, &count));
285
286           switch (ch)
287             {
288             case '\n':
289               /* The next line was empty. Ergo, it can't be a
290                  continuation line. */
291               ++ctx->line;
292               end_of_val = TRUE;
293               continue;
294
295             case EOF:
296               /* This is also an empty line. */
297               end_of_val = TRUE;
298               continue;
299
300             default:
301               if (count == 0)
302                 {
303                   /* This line starts in the first column.  That means
304                      it's either a section, option or comment.  Put
305                      the char back into the stream, because it doesn't
306                      belong to us. */
307                   SVN_ERR(parser_ungetc(ctx, ch));
308                   end_of_val = TRUE;
309                 }
310               else
311                 {
312                   /* This is a continuation line. Read it. */
313                   svn_stringbuf_appendbyte(ctx->value, ' ');
314
315                   while (ch != EOF && ch != '\n')
316                     {
317                       const char char_from_int = (char)ch;
318                       svn_stringbuf_appendbyte(ctx->value, char_from_int);
319                       SVN_ERR(parser_getc(ctx, &ch));
320                     }
321                   /* Trailing whitespace is ignored. */
322                   svn_stringbuf_strip_whitespace(ctx->value);
323                 }
324             }
325         }
326     }
327
328   *pch = ch;
329   return SVN_NO_ERROR;
330 }
331
332
333 /* Parse a single option */
334 static svn_error_t *
335 parse_option(int *pch, parse_context_t *ctx, apr_pool_t *scratch_pool)
336 {
337   svn_error_t *err = SVN_NO_ERROR;
338   int ch;
339
340   svn_stringbuf_setempty(ctx->option);
341   ch = *pch;   /* Yes, the first char is relevant. */
342   while (ch != EOF && ch != ':' && ch != '=' && ch != '\n')
343     {
344       const char char_from_int = (char)ch;
345       svn_stringbuf_appendbyte(ctx->option, char_from_int);
346       SVN_ERR(parser_getc(ctx, &ch));
347     }
348
349   if (ch != ':' && ch != '=')
350     {
351       ch = EOF;
352       err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
353                               _("line %d: Option must end with ':' or '='"),
354                               ctx->line);
355     }
356   else
357     {
358       /* Whitespace around the name separator is ignored. */
359       svn_stringbuf_strip_whitespace(ctx->option);
360       err = parse_value(&ch, ctx);
361     }
362
363   *pch = ch;
364   return err;
365 }
366
367
368 /* Read chars until enounter ']', then skip everything to the end of
369  * the line.  Set *PCH to the character that ended the line (either
370  * newline or EOF), and set CTX->section to the string of characters
371  * seen before ']'.
372  *
373  * This is meant to be called immediately after reading the '[' that
374  * starts a section name.
375  */
376 static svn_error_t *
377 parse_section_name(int *pch, parse_context_t *ctx,
378                    apr_pool_t *scratch_pool)
379 {
380   svn_error_t *err = SVN_NO_ERROR;
381   int ch;
382
383   svn_stringbuf_setempty(ctx->section);
384   SVN_ERR(parser_getc(ctx, &ch));
385   while (ch != EOF && ch != ']' && ch != '\n')
386     {
387       const char char_from_int = (char)ch;
388       svn_stringbuf_appendbyte(ctx->section, char_from_int);
389       SVN_ERR(parser_getc(ctx, &ch));
390     }
391
392   if (ch != ']')
393     {
394       ch = EOF;
395       err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
396                               _("line %d: Section header must end with ']'"),
397                               ctx->line);
398     }
399   else
400     {
401       /* Everything from the ']' to the end of the line is ignored. */
402       SVN_ERR(skip_to_eoln(ctx, &ch));
403       if (ch != EOF)
404         ++ctx->line;
405     }
406
407   *pch = ch;
408   return err;
409 }
410
411
412 svn_error_t *
413 svn_config__sys_config_path(const char **path_p,
414                             const char *fname,
415                             apr_pool_t *pool)
416 {
417   *path_p = NULL;
418
419   /* Note that even if fname is null, svn_dirent_join_many will DTRT. */
420
421 #ifdef WIN32
422   {
423     const char *folder;
424     SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool, pool));
425     *path_p = svn_dirent_join_many(pool, folder,
426                                    SVN_CONFIG__SUBDIRECTORY, fname,
427                                    SVN_VA_NULL);
428   }
429
430 #elif defined(__HAIKU__)
431   {
432     char folder[B_PATH_NAME_LENGTH];
433
434     status_t error = find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false,
435                                     folder, sizeof(folder));
436     if (error)
437       return SVN_NO_ERROR;
438
439     *path_p = svn_dirent_join_many(pool, folder,
440                                    SVN_CONFIG__SYS_DIRECTORY, fname,
441                                    SVN_VA_NULL);
442   }
443 #else  /* ! WIN32 && !__HAIKU__ */
444
445   *path_p = svn_dirent_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname,
446                                  SVN_VA_NULL);
447
448 #endif /* WIN32 */
449
450   return SVN_NO_ERROR;
451 }
452
453 /* Callback for svn_config_enumerate2: Continue to next value. */
454 static svn_boolean_t
455 expand_value(const char *name,
456              const char *value,
457              void *baton,
458              apr_pool_t *pool)
459 {
460   return TRUE;
461 }
462
463 /* Callback for svn_config_enumerate_sections2:
464  * Enumerate and implicitly expand all values in this section.
465  */
466 static svn_boolean_t
467 expand_values_in_section(const char *name,
468                          void *baton,
469                          apr_pool_t *pool)
470 {
471   svn_config_t *cfg = baton;
472   svn_config_enumerate2(cfg, name, expand_value, NULL, pool);
473
474   return TRUE;
475 }
476
477 \f
478 /*** Exported interfaces. ***/
479
480 void
481 svn_config__set_read_only(svn_config_t *cfg,
482                           apr_pool_t *scratch_pool)
483 {
484   /* expand all items such that later calls to getters won't need to
485    * change internal state */
486   svn_config_enumerate_sections2(cfg, expand_values_in_section,
487                                  cfg, scratch_pool);
488
489   /* now, any modification attempt will be ignored / trigger an assertion
490    * in debug mode */
491   cfg->read_only = TRUE;
492 }
493
494 svn_boolean_t
495 svn_config__is_read_only(svn_config_t *cfg)
496 {
497   return cfg->read_only;
498 }
499
500 svn_config_t *
501 svn_config__shallow_copy(svn_config_t *src,
502                          apr_pool_t *pool)
503 {
504   svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
505
506   cfg->sections = src->sections;
507   cfg->pool = pool;
508
509   /* r/o configs are fully expanded and don't need the x_pool anymore */
510   cfg->x_pool = src->read_only ? NULL : svn_pool_create(pool);
511   cfg->x_values = src->x_values;
512   cfg->tmp_key = svn_stringbuf_create_empty(pool);
513   cfg->tmp_value = svn_stringbuf_create_empty(pool);
514   cfg->section_names_case_sensitive = src->section_names_case_sensitive;
515   cfg->option_names_case_sensitive = src->option_names_case_sensitive;
516   cfg->read_only = src->read_only;
517
518   return cfg;
519 }
520
521 void
522 svn_config__shallow_replace_section(svn_config_t *target,
523                                     svn_config_t *source,
524                                     const char *section)
525 {
526   if (target->read_only)
527     target->sections = apr_hash_copy(target->pool, target->sections);
528
529   svn_hash_sets(target->sections, section,
530                 svn_hash_gets(source->sections, section));
531 }
532
533 \f
534 svn_error_t *
535 svn_config__parse_file(svn_config_t *cfg, const char *file,
536                        svn_boolean_t must_exist, apr_pool_t *result_pool)
537 {
538   svn_error_t *err = SVN_NO_ERROR;
539   apr_file_t *apr_file;
540   svn_stream_t *stream;
541   apr_pool_t *scratch_pool = svn_pool_create(result_pool);
542
543   /* Use unbuffered IO since we use our own buffering. */
544   err = svn_io_file_open(&apr_file, file, APR_READ, APR_OS_DEFAULT,
545                          scratch_pool);
546
547   if (! must_exist && err && APR_STATUS_IS_ENOENT(err->apr_err))
548     {
549       svn_error_clear(err);
550       svn_pool_destroy(scratch_pool);
551       return SVN_NO_ERROR;
552     }
553   else
554     SVN_ERR(err);
555
556   stream = svn_stream_from_aprfile2(apr_file, FALSE, scratch_pool);
557   err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
558
559   if (err != SVN_NO_ERROR)
560     {
561       /* Add the filename to the error stack. */
562       err = svn_error_createf(err->apr_err, err,
563                               _("Error while parsing config file: %s:"),
564                               svn_dirent_local_style(file, scratch_pool));
565     }
566
567   /* Close the streams (and other cleanup): */
568   svn_pool_destroy(scratch_pool);
569
570   return err;
571 }
572
573 svn_error_t *
574 svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream,
575                          apr_pool_t *result_pool, apr_pool_t *scratch_pool)
576 {
577   parse_context_t *ctx;
578   int ch, count;
579
580   ctx = apr_palloc(scratch_pool, sizeof(*ctx));
581
582   ctx->cfg = cfg;
583   ctx->stream = stream;
584   ctx->line = 1;
585   ctx->ungotten_char = EOF;
586   ctx->section = svn_stringbuf_create_empty(scratch_pool);
587   ctx->option = svn_stringbuf_create_empty(scratch_pool);
588   ctx->value = svn_stringbuf_create_empty(scratch_pool);
589   ctx->buffer_pos = 0;
590   ctx->buffer_size = 0;
591   ctx->hit_stream_eof = FALSE;
592
593   SVN_ERR(skip_bom(ctx));
594
595   do
596     {
597       SVN_ERR(skip_whitespace(ctx, &ch, &count));
598
599       switch (ch)
600         {
601         case '[':               /* Start of section header */
602           if (count == 0)
603             SVN_ERR(parse_section_name(&ch, ctx, scratch_pool));
604           else
605             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
606                                      _("line %d: Section header"
607                                        " must start in the first column"),
608                                      ctx->line);
609           break;
610
611         case '#':               /* Comment */
612           if (count == 0)
613             {
614               SVN_ERR(skip_to_eoln(ctx, &ch));
615               ++(ctx->line);
616             }
617           else
618             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
619                                      _("line %d: Comment"
620                                        " must start in the first column"),
621                                      ctx->line);
622           break;
623
624         case '\n':              /* Empty line */
625           ++(ctx->line);
626           break;
627
628         case EOF:               /* End of file or read error */
629           break;
630
631         default:
632           if (svn_stringbuf_isempty(ctx->section))
633             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
634                                      _("line %d: Section header expected"),
635                                      ctx->line);
636           else if (count != 0)
637             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
638                                      _("line %d: Option expected"),
639                                      ctx->line);
640           else
641             SVN_ERR(parse_option(&ch, ctx, scratch_pool));
642           break;
643         }
644     }
645   while (ch != EOF);
646
647   return SVN_NO_ERROR;
648 }
649
650
651 /* Helper for ensure_auth_dirs: create SUBDIR under AUTH_DIR, iff
652    SUBDIR does not already exist, but ignore any errors.  Use POOL for
653    temporary allocation. */
654 static void
655 ensure_auth_subdir(const char *auth_dir,
656                    const char *subdir,
657                    apr_pool_t *pool)
658 {
659   svn_error_t *err;
660   const char *subdir_full_path;
661   svn_node_kind_t kind;
662
663   subdir_full_path = svn_dirent_join(auth_dir, subdir, pool);
664   err = svn_io_check_path(subdir_full_path, &kind, pool);
665   if (err || kind == svn_node_none)
666     {
667       svn_error_clear(err);
668       svn_error_clear(svn_io_dir_make(subdir_full_path, APR_OS_DEFAULT, pool));
669     }
670 }
671
672 /* Helper for svn_config_ensure:  see if ~/.subversion/auth/ and its
673    subdirs exist, try to create them, but don't throw errors on
674    failure.  PATH is assumed to be a path to the user's private config
675    directory. */
676 static void
677 ensure_auth_dirs(const char *path,
678                  apr_pool_t *pool)
679 {
680   svn_node_kind_t kind;
681   const char *auth_dir;
682   svn_error_t *err;
683
684   /* Ensure ~/.subversion/auth/ */
685   auth_dir = svn_dirent_join(path, SVN_CONFIG__AUTH_SUBDIR, pool);
686   err = svn_io_check_path(auth_dir, &kind, pool);
687   if (err || kind == svn_node_none)
688     {
689       svn_error_clear(err);
690       /* 'chmod 700' permissions: */
691       err = svn_io_dir_make(auth_dir,
692                             (APR_UREAD | APR_UWRITE | APR_UEXECUTE),
693                             pool);
694       if (err)
695         {
696           /* Don't try making subdirs if we can't make the top-level dir. */
697           svn_error_clear(err);
698           return;
699         }
700     }
701
702   /* If a provider exists that wants to store credentials in
703      ~/.subversion, a subdirectory for the cred_kind must exist. */
704   ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SIMPLE, pool);
705   ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_USERNAME, pool);
706   ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SSL_SERVER_TRUST, pool);
707   ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, pool);
708 }
709
710
711 svn_error_t *
712 svn_config_ensure(const char *config_dir, apr_pool_t *pool)
713 {
714   const char *path;
715   svn_node_kind_t kind;
716   svn_error_t *err;
717
718   /* Ensure that the user-specific config directory exists.  */
719   SVN_ERR(svn_config_get_user_config_path(&path, config_dir, NULL, pool));
720
721   if (! path)
722     return SVN_NO_ERROR;
723
724   err = svn_io_check_resolved_path(path, &kind, pool);
725   if (err)
726     {
727       /* Don't throw an error, but don't continue. */
728       svn_error_clear(err);
729       return SVN_NO_ERROR;
730     }
731
732   if (kind == svn_node_none)
733     {
734       err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
735       if (err)
736         {
737           /* Don't throw an error, but don't continue. */
738           svn_error_clear(err);
739           return SVN_NO_ERROR;
740         }
741     }
742   else if (kind == svn_node_file)
743     {
744       /* Somebody put a file where the config directory should be.
745          Wacky.  Let's bail. */
746       return SVN_NO_ERROR;
747     }
748
749   /* Else, there's a configuration directory. */
750
751   /* If we get errors trying to do things below, just stop and return
752      success.  There's no _need_ to init a config directory if
753      something's preventing it. */
754
755   /** If non-existent, try to create a number of auth/ subdirectories. */
756   ensure_auth_dirs(path, pool);
757
758   /** Ensure that the `README.txt' file exists. **/
759   SVN_ERR(svn_config_get_user_config_path
760           (&path, config_dir, SVN_CONFIG__USR_README_FILE, pool));
761
762   if (! path)  /* highly unlikely, since a previous call succeeded */
763     return SVN_NO_ERROR;
764
765   err = svn_io_check_path(path, &kind, pool);
766   if (err)
767     {
768       svn_error_clear(err);
769       return SVN_NO_ERROR;
770     }
771
772   if (kind == svn_node_none)
773     {
774       apr_file_t *f;
775       const char *contents =
776    "This directory holds run-time configuration information for Subversion"  NL
777    "clients.  The configuration files all share the same syntax, but you"    NL
778    "should examine a particular file to learn what configuration"            NL
779    "directives are valid for that file."                                     NL
780    ""                                                                        NL
781    "The syntax is standard INI format:"                                      NL
782    ""                                                                        NL
783    "   - Empty lines, and lines starting with '#', are ignored."             NL
784    "     The first significant line in a file must be a section header."     NL
785    ""                                                                        NL
786    "   - A section starts with a section header, which must start in"        NL
787    "     the first column:"                                                  NL
788    ""                                                                        NL
789    "       [section-name]"                                                   NL
790    ""                                                                        NL
791    "   - An option, which must always appear within a section, is a pair"    NL
792    "     (name, value).  There are two valid forms for defining an"          NL
793    "     option, both of which must start in the first column:"              NL
794    ""                                                                        NL
795    "       name: value"                                                      NL
796    "       name = value"                                                     NL
797    ""                                                                        NL
798    "     Whitespace around the separator (:, =) is optional."                NL
799    ""                                                                        NL
800    "   - Section and option names are case-insensitive, but case is"         NL
801    "     preserved."                                                         NL
802    ""                                                                        NL
803    "   - An option's value may be broken into several lines.  The value"     NL
804    "     continuation lines must start with at least one whitespace."        NL
805    "     Trailing whitespace in the previous line, the newline character"    NL
806    "     and the leading whitespace in the continuation line is compressed"  NL
807    "     into a single space character."                                     NL
808    ""                                                                        NL
809    "   - All leading and trailing whitespace around a value is trimmed,"     NL
810    "     but the whitespace within a value is preserved, with the"           NL
811    "     exception of whitespace around line continuations, as"              NL
812    "     described above."                                                   NL
813    ""                                                                        NL
814    "   - When a value is a boolean, any of the following strings are"        NL
815    "     recognised as truth values (case does not matter):"                 NL
816    ""                                                                        NL
817    "       true      false"                                                  NL
818    "       yes       no"                                                     NL
819    "       on        off"                                                    NL
820    "       1         0"                                                      NL
821    ""                                                                        NL
822    "   - When a value is a list, it is comma-separated.  Again, the"         NL
823    "     whitespace around each element of the list is trimmed."             NL
824    ""                                                                        NL
825    "   - Option values may be expanded within a value by enclosing the"      NL
826    "     option name in parentheses, preceded by a percent sign and"         NL
827    "     followed by an 's':"                                                NL
828    ""                                                                        NL
829    "       %(name)s"                                                         NL
830    ""                                                                        NL
831    "     The expansion is performed recursively and on demand, during"       NL
832    "     svn_option_get.  The name is first searched for in the same"        NL
833    "     section, then in the special [DEFAULT] section. If the name"        NL
834    "     is not found, the whole '%(name)s' placeholder is left"             NL
835    "     unchanged."                                                         NL
836    ""                                                                        NL
837    "     Any modifications to the configuration data invalidate all"         NL
838    "     previously expanded values, so that the next svn_option_get"        NL
839    "     will take the modifications into account."                          NL
840    ""                                                                        NL
841    "The syntax of the configuration files is a subset of the one used by"    NL
842    "Python's ConfigParser module; see"                                       NL
843    ""                                                                        NL
844    "   http://www.python.org/doc/current/lib/module-ConfigParser.html"       NL
845    ""                                                                        NL
846    "Configuration data in the Windows registry"                              NL
847    "=========================================="                              NL
848    ""                                                                        NL
849    "On Windows, configuration data may also be stored in the registry. The"  NL
850    "functions svn_config_read and svn_config_merge will read from the"       NL
851    "registry when passed file names of the form:"                            NL
852    ""                                                                        NL
853    "   REGISTRY:<hive>/path/to/config-key"                                   NL
854    ""                                                                        NL
855    "The REGISTRY: prefix must be in upper case. The <hive> part must be"     NL
856    "one of:"                                                                 NL
857    ""                                                                        NL
858    "   HKLM for HKEY_LOCAL_MACHINE"                                          NL
859    "   HKCU for HKEY_CURRENT_USER"                                           NL
860    ""                                                                        NL
861    "The values in config-key represent the options in the [DEFAULT] section."NL
862    "The keys below config-key represent other sections, and their values"    NL
863    "represent the options. Only values of type REG_SZ whose name doesn't"    NL
864    "start with a '#' will be used; other values, as well as the keys'"       NL
865    "default values, will be ignored."                                        NL
866    ""                                                                        NL
867    ""                                                                        NL
868    "File locations"                                                          NL
869    "=============="                                                          NL
870    ""                                                                        NL
871    "Typically, Subversion uses two config directories, one for site-wide"    NL
872    "configuration,"                                                          NL
873    ""                                                                        NL
874    "  Unix:"                                                                 NL
875    "    /etc/subversion/servers"                                             NL
876    "    /etc/subversion/config"                                              NL
877    "    /etc/subversion/hairstyles"                                          NL
878    "  Windows:"                                                              NL
879    "    %ALLUSERSPROFILE%\\Application Data\\Subversion\\servers"            NL
880    "    %ALLUSERSPROFILE%\\Application Data\\Subversion\\config"             NL
881    "    %ALLUSERSPROFILE%\\Application Data\\Subversion\\hairstyles"         NL
882    "    REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Servers"            NL
883    "    REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Config"             NL
884    "    REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Hairstyles"         NL
885    ""                                                                        NL
886    "and one for per-user configuration:"                                     NL
887    ""                                                                        NL
888    "  Unix:"                                                                 NL
889    "    ~/.subversion/servers"                                               NL
890    "    ~/.subversion/config"                                                NL
891    "    ~/.subversion/hairstyles"                                            NL
892    "  Windows:"                                                              NL
893    "    %APPDATA%\\Subversion\\servers"                                      NL
894    "    %APPDATA%\\Subversion\\config"                                       NL
895    "    %APPDATA%\\Subversion\\hairstyles"                                   NL
896    "    REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Servers"            NL
897    "    REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Config"             NL
898    "    REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Hairstyles"         NL
899    ""                                                                        NL;
900
901       err = svn_io_file_open(&f, path,
902                              (APR_WRITE | APR_CREATE | APR_EXCL),
903                              APR_OS_DEFAULT,
904                              pool);
905
906       if (! err)
907         {
908           SVN_ERR(svn_io_file_write_full(f, contents,
909                                          strlen(contents), NULL, pool));
910           SVN_ERR(svn_io_file_close(f, pool));
911         }
912
913       svn_error_clear(err);
914     }
915
916   /** Ensure that the `servers' file exists. **/
917   SVN_ERR(svn_config_get_user_config_path
918           (&path, config_dir, SVN_CONFIG_CATEGORY_SERVERS, pool));
919
920   if (! path)  /* highly unlikely, since a previous call succeeded */
921     return SVN_NO_ERROR;
922
923   err = svn_io_check_path(path, &kind, pool);
924   if (err)
925     {
926       svn_error_clear(err);
927       return SVN_NO_ERROR;
928     }
929
930   if (kind == svn_node_none)
931     {
932       apr_file_t *f;
933       const char *contents =
934         "### This file specifies server-specific parameters,"                NL
935         "### including HTTP proxy information, HTTP timeout settings,"       NL
936         "### and authentication settings."                                   NL
937         "###"                                                                NL
938         "### The currently defined server options are:"                      NL
939         "###   http-proxy-host            Proxy host for HTTP connection"    NL
940         "###   http-proxy-port            Port number of proxy host service" NL
941         "###   http-proxy-username        Username for auth to proxy service"NL
942         "###   http-proxy-password        Password for auth to proxy service"NL
943         "###   http-proxy-exceptions      List of sites that do not use proxy"
944                                                                              NL
945         "###   http-timeout               Timeout for HTTP requests in seconds"
946                                                                              NL
947         "###   http-compression           Whether to compress HTTP requests" NL
948         "###   http-max-connections       Maximum number of parallel server" NL
949         "###                              connections to use for any given"  NL
950         "###                              HTTP operation."                   NL
951         "###   http-chunked-requests      Whether to use chunked transfer"   NL
952         "###                              encoding for HTTP requests body."  NL
953         "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
954         "###   ssl-authority-files        List of files, each of a trusted CA"
955                                                                              NL
956         "###   ssl-trust-default-ca       Trust the system 'default' CAs"    NL
957         "###   ssl-client-cert-file       PKCS#12 format client certificate file"
958                                                                              NL
959         "###   ssl-client-cert-password   Client Key password, if needed."   NL
960         "###   ssl-pkcs11-provider        Name of PKCS#11 provider to use."  NL
961         "###   http-library               Which library to use for http/https"
962                                                                              NL
963         "###                              connections."                      NL
964         "###   http-bulk-updates          Whether to request bulk update"    NL
965         "###                              responses or to fetch each file"   NL
966         "###                              in an individual request. "        NL
967         "###   store-passwords            Specifies whether passwords used"  NL
968         "###                              to authenticate against a"         NL
969         "###                              Subversion server may be cached"   NL
970         "###                              to disk in any way."               NL
971 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
972         "###   store-plaintext-passwords  Specifies whether passwords may"   NL
973         "###                              be cached on disk unencrypted."    NL
974 #endif
975         "###   store-ssl-client-cert-pp   Specifies whether passphrase used" NL
976         "###                              to authenticate against a client"  NL
977         "###                              certificate may be cached to disk" NL
978         "###                              in any way"                        NL
979 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
980         "###   store-ssl-client-cert-pp-plaintext"                           NL
981         "###                              Specifies whether client cert"     NL
982         "###                              passphrases may be cached on disk" NL
983         "###                              unencrypted (i.e., as plaintext)." NL
984 #endif
985         "###   store-auth-creds           Specifies whether any auth info"   NL
986         "###                              (passwords, server certs, etc.)"   NL
987         "###                              may be cached to disk."            NL
988         "###   username                   Specifies the default username."   NL
989         "###"                                                                NL
990         "### Set store-passwords to 'no' to avoid storing passwords on disk" NL
991         "### in any way, including in password stores.  It defaults to"      NL
992         "### 'yes', but Subversion will never save your password to disk in" NL
993         "### plaintext unless explicitly configured to do so."               NL
994         "### Note that this option only prevents saving of *new* passwords;" NL
995         "### it doesn't invalidate existing passwords.  (To do that, remove" NL
996         "### the cache files by hand as described in the Subversion book.)"  NL
997         "###"                                                                NL
998 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
999         "### Set store-plaintext-passwords to 'no' to avoid storing"         NL
1000         "### passwords in unencrypted form in the auth/ area of your config" NL
1001         "### directory. Set it to 'yes' to allow Subversion to store"        NL
1002         "### unencrypted passwords in the auth/ area.  The default is"       NL
1003         "### 'ask', which means that Subversion will ask you before"         NL
1004         "### saving a password to disk in unencrypted form.  Note that"      NL
1005         "### this option has no effect if either 'store-passwords' or "      NL
1006         "### 'store-auth-creds' is set to 'no'."                             NL
1007         "###"                                                                NL
1008 #endif
1009         "### Set store-ssl-client-cert-pp to 'no' to avoid storing ssl"      NL
1010         "### client certificate passphrases in the auth/ area of your"       NL
1011         "### config directory.  It defaults to 'yes', but Subversion will"   NL
1012         "### never save your passphrase to disk in plaintext unless"         NL
1013         "### explicitly configured to do so."                                NL
1014         "###"                                                                NL
1015         "### Note store-ssl-client-cert-pp only prevents the saving of *new*"NL
1016         "### passphrases; it doesn't invalidate existing passphrases.  To do"NL
1017         "### that, remove the cache files by hand as described in the"       NL
1018         "### Subversion book at http://svnbook.red-bean.com/nightly/en/\\"   NL
1019         "###                    svn.serverconfig.netmodel.html\\"            NL
1020         "###                    #svn.serverconfig.netmodel.credcache"        NL
1021         "###"                                                                NL
1022 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
1023         "### Set store-ssl-client-cert-pp-plaintext to 'no' to avoid storing"NL
1024         "### passphrases in unencrypted form in the auth/ area of your"      NL
1025         "### config directory.  Set it to 'yes' to allow Subversion to"      NL
1026         "### store unencrypted passphrases in the auth/ area.  The default"  NL
1027         "### is 'ask', which means that Subversion will prompt before"       NL
1028         "### saving a passphrase to disk in unencrypted form.  Note that"    NL
1029         "### this option has no effect if either 'store-auth-creds' or "     NL
1030         "### 'store-ssl-client-cert-pp' is set to 'no'."                     NL
1031         "###"                                                                NL
1032 #endif
1033         "### Set store-auth-creds to 'no' to avoid storing any Subversion"   NL
1034         "### credentials in the auth/ area of your config directory."        NL
1035         "### Note that this includes SSL server certificates."               NL
1036         "### It defaults to 'yes'.  Note that this option only prevents"     NL
1037         "### saving of *new* credentials;  it doesn't invalidate existing"   NL
1038         "### caches.  (To do that, remove the cache files by hand.)"         NL
1039         "###"                                                                NL
1040         "### HTTP timeouts, if given, are specified in seconds.  A timeout"  NL
1041         "### of 0, i.e. zero, causes a builtin default to be used."          NL
1042         "###"                                                                NL
1043         "### Most users will not need to explicitly set the http-library"    NL
1044         "### option, but valid values for the option include:"               NL
1045         "###    'serf': Serf-based module (Subversion 1.5 - present)"        NL
1046         "###    'neon': Neon-based module (Subversion 1.0 - 1.7)"            NL
1047         "### Availability of these modules may depend on your specific"      NL
1048         "### Subversion distribution."                                       NL
1049         "###"                                                                NL
1050         "### The commented-out examples below are intended only to"          NL
1051         "### demonstrate how to use this file; any resemblance to actual"    NL
1052         "### servers, living or dead, is entirely coincidental."             NL
1053         ""                                                                   NL
1054         "### In the 'groups' section, the URL of the repository you're"      NL
1055         "### trying to access is matched against the patterns on the right." NL
1056         "### If a match is found, the server options are taken from the"     NL
1057         "### section with the corresponding name on the left."               NL
1058         ""                                                                   NL
1059         "[groups]"                                                           NL
1060         "# group1 = *.collab.net"                                            NL
1061         "# othergroup = repository.blarggitywhoomph.com"                     NL
1062         "# thirdgroup = *.example.com"                                       NL
1063         ""                                                                   NL
1064         "### Information for the first group:"                               NL
1065         "# [group1]"                                                         NL
1066         "# http-proxy-host = proxy1.some-domain-name.com"                    NL
1067         "# http-proxy-port = 80"                                             NL
1068         "# http-proxy-username = blah"                                       NL
1069         "# http-proxy-password = doubleblah"                                 NL
1070         "# http-timeout = 60"                                                NL
1071         "# neon-debug-mask = 130"                                            NL
1072 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
1073         "# store-plaintext-passwords = no"                                   NL
1074 #endif
1075         "# username = harry"                                                 NL
1076         ""                                                                   NL
1077         "### Information for the second group:"                              NL
1078         "# [othergroup]"                                                     NL
1079         "# http-proxy-host = proxy2.some-domain-name.com"                    NL
1080         "# http-proxy-port = 9000"                                           NL
1081         "# No username and password for the proxy, so use the defaults below."
1082                                                                              NL
1083         ""                                                                   NL
1084         "### You can set default parameters in the 'global' section."        NL
1085         "### These parameters apply if no corresponding parameter is set in" NL
1086         "### a specifically matched group as shown above.  Thus, if you go"  NL
1087         "### through the same proxy server to reach every site on the"       NL
1088         "### Internet, you probably just want to put that server's"          NL
1089         "### information in the 'global' section and not bother with"        NL
1090         "### 'groups' or any other sections."                                NL
1091         "###"                                                                NL
1092         "### Most people might want to configure password caching"           NL
1093         "### parameters here, but you can also configure them per server"    NL
1094         "### group (per-group settings override global settings)."           NL
1095         "###"                                                                NL
1096         "### If you go through a proxy for all but a few sites, you can"     NL
1097         "### list those exceptions under 'http-proxy-exceptions'.  This only"NL
1098         "### overrides defaults, not explicitly matched server names."       NL
1099         "###"                                                                NL
1100         "### 'ssl-authority-files' is a semicolon-delimited list of files,"  NL
1101         "### each pointing to a PEM-encoded Certificate Authority (CA) "     NL
1102         "### SSL certificate.  See details above for overriding security "   NL
1103         "### due to SSL."                                                    NL
1104         "[global]"                                                           NL
1105         "# http-proxy-exceptions = *.exception.com, www.internal-site.org"   NL
1106         "# http-proxy-host = defaultproxy.whatever.com"                      NL
1107         "# http-proxy-port = 7000"                                           NL
1108         "# http-proxy-username = defaultusername"                            NL
1109         "# http-proxy-password = defaultpassword"                            NL
1110         "# http-compression = no"                                            NL
1111         "# No http-timeout, so just use the builtin default."                NL
1112         "# No neon-debug-mask, so neon debugging is disabled."               NL
1113         "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem"   NL
1114         "#"                                                                  NL
1115         "# Password / passphrase caching parameters:"                        NL
1116         "# store-passwords = no"                                             NL
1117         "# store-ssl-client-cert-pp = no"                                    NL
1118 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
1119         "# store-plaintext-passwords = no"                                   NL
1120         "# store-ssl-client-cert-pp-plaintext = no"                          NL
1121 #endif
1122         ;
1123
1124       err = svn_io_file_open(&f, path,
1125                              (APR_WRITE | APR_CREATE | APR_EXCL),
1126                              APR_OS_DEFAULT,
1127                              pool);
1128
1129       if (! err)
1130         {
1131           SVN_ERR(svn_io_file_write_full(f, contents,
1132                                          strlen(contents), NULL, pool));
1133           SVN_ERR(svn_io_file_close(f, pool));
1134         }
1135
1136       svn_error_clear(err);
1137     }
1138
1139   /** Ensure that the `config' file exists. **/
1140   SVN_ERR(svn_config_get_user_config_path
1141           (&path, config_dir, SVN_CONFIG_CATEGORY_CONFIG, pool));
1142
1143   if (! path)  /* highly unlikely, since a previous call succeeded */
1144     return SVN_NO_ERROR;
1145
1146   err = svn_io_check_path(path, &kind, pool);
1147   if (err)
1148     {
1149       svn_error_clear(err);
1150       return SVN_NO_ERROR;
1151     }
1152
1153   if (kind == svn_node_none)
1154     {
1155       apr_file_t *f;
1156       const char *contents =
1157         "### This file configures various client-side behaviors."            NL
1158         "###"                                                                NL
1159         "### The commented-out examples below are intended to demonstrate"   NL
1160         "### how to use this file."                                          NL
1161         ""                                                                   NL
1162         "### Section for authentication and authorization customizations."   NL
1163         "[auth]"                                                             NL
1164         "### Set password stores used by Subversion. They should be"         NL
1165         "### delimited by spaces or commas. The order of values determines"  NL
1166         "### the order in which password stores are used."                   NL
1167         "### Valid password stores:"                                         NL
1168         "###   gnome-keyring        (Unix-like systems)"                     NL
1169         "###   kwallet              (Unix-like systems)"                     NL
1170         "###   gpg-agent            (Unix-like systems)"                     NL
1171         "###   keychain             (Mac OS X)"                              NL
1172         "###   windows-cryptoapi    (Windows)"                               NL
1173 #ifdef SVN_HAVE_KEYCHAIN_SERVICES
1174         "# password-stores = keychain"                                       NL
1175 #elif defined(WIN32) && !defined(__MINGW32__)
1176         "# password-stores = windows-cryptoapi"                              NL
1177 #else
1178         "# password-stores = gpg-agent,gnome-keyring,kwallet"                NL
1179 #endif
1180         "### To disable all password stores, use an empty list:"             NL
1181         "# password-stores ="                                                NL
1182 #ifdef SVN_HAVE_KWALLET
1183         "###"                                                                NL
1184         "### Set KWallet wallet used by Subversion. If empty or unset,"      NL
1185         "### then the default network wallet will be used."                  NL
1186         "# kwallet-wallet ="                                                 NL
1187         "###"                                                                NL
1188         "### Include PID (Process ID) in Subversion application name when"   NL
1189         "### using KWallet. It defaults to 'no'."                            NL
1190         "# kwallet-svn-application-name-with-pid = yes"                      NL
1191 #endif
1192         "###"                                                                NL
1193         "### Set ssl-client-cert-file-prompt to 'yes' to cause the client"   NL
1194         "### to prompt for a path to a client cert file when the server"     NL
1195         "### requests a client cert but no client cert file is found in the" NL
1196         "### expected place (see the 'ssl-client-cert-file' option in the"   NL
1197         "### 'servers' configuration file). Defaults to 'no'."               NL
1198         "# ssl-client-cert-file-prompt = no"                                 NL
1199         "###"                                                                NL
1200         "### The rest of the [auth] section in this file has been deprecated."
1201                                                                              NL
1202         "### Both 'store-passwords' and 'store-auth-creds' can now be"       NL
1203         "### specified in the 'servers' file in your config directory"       NL
1204         "### and are documented there. Anything specified in this section "  NL
1205         "### is overridden by settings specified in the 'servers' file."     NL
1206         "# store-passwords = no"                                             NL
1207         "# store-auth-creds = no"                                            NL
1208         ""                                                                   NL
1209         "### Section for configuring external helper applications."          NL
1210         "[helpers]"                                                          NL
1211         "### Set editor-cmd to the command used to invoke your text editor." NL
1212         "###   This will override the environment variables that Subversion" NL
1213         "###   examines by default to find this information ($EDITOR, "      NL
1214         "###   et al)."                                                      NL
1215         "# editor-cmd = editor (vi, emacs, notepad, etc.)"                   NL
1216         "### Set diff-cmd to the absolute path of your 'diff' program."      NL
1217         "###   This will override the compile-time default, which is to use" NL
1218         "###   Subversion's internal diff implementation."                   NL
1219         "# diff-cmd = diff_program (diff, gdiff, etc.)"                      NL
1220         "### Diff-extensions are arguments passed to an external diff"       NL
1221         "### program or to Subversion's internal diff implementation."       NL
1222         "### Set diff-extensions to override the default arguments ('-u')."  NL
1223         "# diff-extensions = -u -p"                                          NL
1224         "### Set diff3-cmd to the absolute path of your 'diff3' program."    NL
1225         "###   This will override the compile-time default, which is to use" NL
1226         "###   Subversion's internal diff3 implementation."                  NL
1227         "# diff3-cmd = diff3_program (diff3, gdiff3, etc.)"                  NL
1228         "### Set diff3-has-program-arg to 'yes' if your 'diff3' program"     NL
1229         "###   accepts the '--diff-program' option."                         NL
1230         "# diff3-has-program-arg = [yes | no]"                               NL
1231         "### Set merge-tool-cmd to the command used to invoke your external" NL
1232         "### merging tool of choice. Subversion will pass 5 arguments to"    NL
1233         "### the specified command: base theirs mine merged wcfile"          NL
1234         "# merge-tool-cmd = merge_command"                                   NL
1235         ""                                                                   NL
1236         "### Section for configuring tunnel agents."                         NL
1237         "[tunnels]"                                                          NL
1238         "### Configure svn protocol tunnel schemes here.  By default, only"  NL
1239         "### the 'ssh' scheme is defined.  You can define other schemes to"  NL
1240         "### be used with 'svn+scheme://hostname/path' URLs.  A scheme"      NL
1241         "### definition is simply a command, optionally prefixed by an"      NL
1242         "### environment variable name which can override the command if it" NL
1243         "### is defined.  The command (or environment variable) may contain" NL
1244         "### arguments, using standard shell quoting for arguments with"     NL
1245         "### spaces.  The command will be invoked as:"                       NL
1246         "###   <command> <hostname> svnserve -t"                             NL
1247         "### (If the URL includes a username, then the hostname will be"     NL
1248         "### passed to the tunnel agent as <user>@<hostname>.)  If the"      NL
1249         "### built-in ssh scheme were not predefined, it could be defined"   NL
1250         "### as:"                                                            NL
1251         "# ssh = $SVN_SSH ssh -q"                                            NL
1252         "### If you wanted to define a new 'rsh' scheme, to be used with"    NL
1253         "### 'svn+rsh:' URLs, you could do so as follows:"                   NL
1254         "# rsh = rsh"                                                        NL
1255         "### Or, if you wanted to specify a full path and arguments:"        NL
1256         "# rsh = /path/to/rsh -l myusername"                                 NL
1257         "### On Windows, if you are specifying a full path to a command,"    NL
1258         "### use a forward slash (/) or a paired backslash (\\\\) as the"    NL
1259         "### path separator.  A single backslash will be treated as an"      NL
1260         "### escape for the following character."                            NL
1261         ""                                                                   NL
1262         "### Section for configuring miscellaneous Subversion options."      NL
1263         "[miscellany]"                                                       NL
1264         "### Set global-ignores to a set of whitespace-delimited globs"      NL
1265         "### which Subversion will ignore in its 'status' output, and"       NL
1266         "### while importing or adding files and directories."               NL
1267         "### '*' matches leading dots, e.g. '*.rej' matches '.foo.rej'."     NL
1268         "# global-ignores = " SVN_CONFIG__DEFAULT_GLOBAL_IGNORES_LINE_1      NL
1269         "#   " SVN_CONFIG__DEFAULT_GLOBAL_IGNORES_LINE_2                     NL
1270         "### Set log-encoding to the default encoding for log messages"      NL
1271         "# log-encoding = latin1"                                            NL
1272         "### Set use-commit-times to make checkout/update/switch/revert"     NL
1273         "### put last-committed timestamps on every file touched."           NL
1274         "# use-commit-times = yes"                                           NL
1275         "### Set no-unlock to prevent 'svn commit' from automatically"       NL
1276         "### releasing locks on files."                                      NL
1277         "# no-unlock = yes"                                                  NL
1278         "### Set mime-types-file to a MIME type registry file, used to"      NL
1279         "### provide hints to Subversion's MIME type auto-detection"         NL
1280         "### algorithm."                                                     NL
1281         "# mime-types-file = /path/to/mime.types"                            NL
1282         "### Set preserved-conflict-file-exts to a whitespace-delimited"     NL
1283         "### list of patterns matching file extensions which should be"      NL
1284         "### preserved in generated conflict file names.  By default,"       NL
1285         "### conflict files use custom extensions."                          NL
1286         "# preserved-conflict-file-exts = doc ppt xls od?"                   NL
1287         "### Set enable-auto-props to 'yes' to enable automatic properties"  NL
1288         "### for 'svn add' and 'svn import', it defaults to 'no'."           NL
1289         "### Automatic properties are defined in the section 'auto-props'."  NL
1290         "# enable-auto-props = yes"                                          NL
1291 #ifdef SVN_HAVE_LIBMAGIC
1292         "### Set enable-magic-file to 'no' to disable magic file detection"  NL
1293         "### of the file type when automatically setting svn:mime-type. It"  NL
1294         "### defaults to 'yes' if magic file support is possible."           NL
1295         "# enable-magic-file = yes"                                          NL
1296 #endif
1297         "### Set interactive-conflicts to 'no' to disable interactive"       NL
1298         "### conflict resolution prompting.  It defaults to 'yes'."          NL
1299         "# interactive-conflicts = no"                                       NL
1300         "### Set memory-cache-size to define the size of the memory cache"   NL
1301         "### used by the client when accessing a FSFS repository via"        NL
1302         "### ra_local (the file:// scheme). The value represents the number" NL
1303         "### of MB used by the cache."                                       NL
1304         "# memory-cache-size = 16"                                           NL
1305         "### Set diff-ignore-content-type to 'yes' to cause 'svn diff' to"   NL
1306         "### attempt to show differences of all modified files regardless"   NL
1307         "### of their MIME content type.  By default, Subversion will only"  NL
1308         "### attempt to show differences for files believed to have human-"  NL
1309         "### readable (non-binary) content.  This option is especially"      NL
1310         "### useful when Subversion is configured (via the 'diff-cmd'"       NL
1311         "### option) to employ an external differencing tool which is able"  NL
1312         "### to show meaningful differences for binary file formats.  [New"  NL
1313         "### in 1.9]"                                                        NL
1314         "# diff-ignore-content-type = no"                                    NL
1315         ""                                                                   NL
1316         "### Section for configuring automatic properties."                  NL
1317         "[auto-props]"                                                       NL
1318         "### The format of the entries is:"                                  NL
1319         "###   file-name-pattern = propname[=value][;propname[=value]...]"   NL
1320         "### The file-name-pattern can contain wildcards (such as '*' and"   NL
1321         "### '?').  All entries which match (case-insensitively) will be"    NL
1322         "### applied to the file.  Note that auto-props functionality"       NL
1323         "### must be enabled, which is typically done by setting the"        NL
1324         "### 'enable-auto-props' option."                                    NL
1325         "# *.c = svn:eol-style=native"                                       NL
1326         "# *.cpp = svn:eol-style=native"                                     NL
1327         "# *.h = svn:keywords=Author Date Id Rev URL;svn:eol-style=native"   NL
1328         "# *.dsp = svn:eol-style=CRLF"                                       NL
1329         "# *.dsw = svn:eol-style=CRLF"                                       NL
1330         "# *.sh = svn:eol-style=native;svn:executable"                       NL
1331         "# *.txt = svn:eol-style=native;svn:keywords=Author Date Id Rev URL;"NL
1332         "# *.png = svn:mime-type=image/png"                                  NL
1333         "# *.jpg = svn:mime-type=image/jpeg"                                 NL
1334         "# Makefile = svn:eol-style=native"                                  NL
1335         ""                                                                   NL
1336         "### Section for configuring working copies."                        NL
1337         "[working-copy]"                                                     NL
1338         "### Set to a list of the names of specific clients that should use" NL
1339         "### exclusive SQLite locking of working copies.  This increases the"NL
1340         "### performance of the client but prevents concurrent access by"    NL
1341         "### other clients.  Third-party clients may also support this"      NL
1342         "### option."                                                        NL
1343         "### Possible values:"                                               NL
1344         "###   svn                (the command line client)"                 NL
1345         "# exclusive-locking-clients ="                                      NL
1346         "### Set to true to enable exclusive SQLite locking of working"      NL
1347         "### copies by all clients using the 1.8 APIs.  Enabling this may"   NL
1348         "### cause some clients to fail to work properly. This does not have"NL
1349         "### to be set for exclusive-locking-clients to work."               NL
1350         "# exclusive-locking = false"                                        NL
1351         "### Set the SQLite busy timeout in milliseconds: the maximum time"  NL
1352         "### the client waits to get access to the SQLite database before"   NL
1353         "### returning an error.  The default is 10000, i.e. 10 seconds."    NL
1354         "### Longer values may be useful when exclusive locking is enabled." NL
1355         "# busy-timeout = 10000"                                             NL
1356         ;
1357
1358       err = svn_io_file_open(&f, path,
1359                              (APR_WRITE | APR_CREATE | APR_EXCL),
1360                              APR_OS_DEFAULT,
1361                              pool);
1362
1363       if (! err)
1364         {
1365           SVN_ERR(svn_io_file_write_full(f, contents,
1366                                          strlen(contents), NULL, pool));
1367           SVN_ERR(svn_io_file_close(f, pool));
1368         }
1369
1370       svn_error_clear(err);
1371     }
1372
1373   return SVN_NO_ERROR;
1374 }
1375
1376 svn_error_t *
1377 svn_config_get_user_config_path(const char **path,
1378                                 const char *config_dir,
1379                                 const char *fname,
1380                                 apr_pool_t *pool)
1381 {
1382   *path= NULL;
1383
1384   /* Note that even if fname is null, svn_dirent_join_many will DTRT. */
1385
1386   if (config_dir)
1387     {
1388       *path = svn_dirent_join_many(pool, config_dir, fname, SVN_VA_NULL);
1389       return SVN_NO_ERROR;
1390     }
1391
1392 #ifdef WIN32
1393   {
1394     const char *folder;
1395     SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool, pool));
1396
1397     if (! folder)
1398       return SVN_NO_ERROR;
1399
1400     *path = svn_dirent_join_many(pool, folder,
1401                                  SVN_CONFIG__SUBDIRECTORY, fname, SVN_VA_NULL);
1402   }
1403
1404 #elif defined(__HAIKU__)
1405   {
1406     char folder[B_PATH_NAME_LENGTH];
1407
1408     status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false,
1409                                     folder, sizeof(folder));
1410     if (error)
1411       return SVN_NO_ERROR;
1412
1413     *path = svn_dirent_join_many(pool, folder,
1414                                  SVN_CONFIG__USR_DIRECTORY, fname,
1415                                  SVN_VA_NULL);
1416   }
1417 #else  /* ! WIN32 && !__HAIKU__ */
1418
1419   {
1420     const char *homedir = svn_user_get_homedir(pool);
1421     if (! homedir)
1422       return SVN_NO_ERROR;
1423     *path = svn_dirent_join_many(pool,
1424                                svn_dirent_canonicalize(homedir, pool),
1425                                SVN_CONFIG__USR_DIRECTORY, fname, SVN_VA_NULL);
1426   }
1427 #endif /* WIN32 */
1428
1429   return SVN_NO_ERROR;
1430 }
1431