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