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