Change the format of the revprops block sent in svnserve for
[svn.git] / subversion / libsvn_subr / config_file.c
blob76f614fc1a5a44140cbce8a91363a0cc5bce0039
1 /*
2 * config_file.c : parsing configuration files
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #include <apr_lib.h>
22 #include <apr_md5.h>
23 #include <apr_env.h>
24 #include "config_impl.h"
25 #include "svn_io.h"
26 #include "svn_types.h"
27 #include "svn_path.h"
28 #include "svn_auth.h"
29 #include "svn_subst.h"
30 #include "svn_utf.h"
31 #include "svn_pools.h"
32 #include "svn_user.h"
34 #include "svn_private_config.h"
36 /* Used to terminate lines in large multi-line string literals. */
37 #define NL APR_EOL_STR
40 /* File parsing context */
41 typedef struct parse_context_t
43 /* This config struct and file */
44 svn_config_t *cfg;
45 const char *file;
47 /* The file descriptor */
48 svn_stream_t *stream;
50 /* The current line in the file */
51 int line;
53 /* Cached ungotten character - streams don't support ungetc()
54 [emulate it] */
55 int ungotten_char;
56 svn_boolean_t have_ungotten_char;
58 /* Temporary strings, allocated from the temp pool */
59 svn_stringbuf_t *section;
60 svn_stringbuf_t *option;
61 svn_stringbuf_t *value;
62 } parse_context_t;
66 /* Emulate getc() because streams don't support it.
68 * In order to be able to ungetc(), use the CXT instead of the stream
69 * to be able to store the 'ungotton' character.
72 static APR_INLINE svn_error_t *
73 parser_getc(parse_context_t *ctx, int *c)
75 if (ctx->have_ungotten_char)
77 *c = ctx->ungotten_char;
78 ctx->have_ungotten_char = FALSE;
80 else
82 char char_buf;
83 apr_size_t readlen = 1;
85 SVN_ERR(svn_stream_read(ctx->stream, &char_buf, &readlen));
87 if (readlen == 1)
88 *c = char_buf;
89 else
90 *c = EOF;
93 return SVN_NO_ERROR;
96 /* Emulate ungetc() because streams don't support it.
98 * Use CTX to store the ungotten character C.
100 static APR_INLINE svn_error_t *
101 parser_ungetc(parse_context_t *ctx, int c)
103 ctx->ungotten_char = c;
104 ctx->have_ungotten_char = TRUE;
106 return SVN_NO_ERROR;
109 /* Eat chars from STREAM until encounter non-whitespace, newline, or EOF.
110 Set *PCOUNT to the number of characters eaten, not counting the
111 last one, and return the last char read (the one that caused the
112 break). */
113 static APR_INLINE svn_error_t *
114 skip_whitespace(parse_context_t *ctx, int *c, int *pcount)
116 int ch;
117 int count = 0;
119 SVN_ERR(parser_getc(ctx, &ch));
120 while (ch != EOF && ch != '\n' && apr_isspace(ch))
122 ++count;
123 SVN_ERR(parser_getc(ctx, &ch));
125 *pcount = count;
126 *c = ch;
127 return SVN_NO_ERROR;
131 /* Skip to the end of the line (or file). Returns the char that ended
132 the line; the char is either EOF or newline. */
133 static APR_INLINE svn_error_t *
134 skip_to_eoln(parse_context_t *ctx, int *c)
136 int ch;
138 SVN_ERR(parser_getc(ctx, &ch));
139 while (ch != EOF && ch != '\n')
140 SVN_ERR(parser_getc(ctx, &ch));
142 *c = ch;
143 return SVN_NO_ERROR;
147 /* Parse a single option value */
148 static svn_error_t *
149 parse_value(int *pch, parse_context_t *ctx)
151 svn_boolean_t end_of_val = FALSE;
152 int ch;
154 /* Read the first line of the value */
155 svn_stringbuf_setempty(ctx->value);
156 SVN_ERR(parser_getc(ctx, &ch));
157 while (ch != EOF && ch != '\n')
158 /* last ch seen was ':' or '=' in parse_option. */
160 const char char_from_int = ch;
161 svn_stringbuf_appendbytes(ctx->value, &char_from_int, 1);
162 SVN_ERR(parser_getc(ctx, &ch));
164 /* Leading and trailing whitespace is ignored. */
165 svn_stringbuf_strip_whitespace(ctx->value);
167 /* Look for any continuation lines. */
168 for (;;)
171 if (ch == EOF || end_of_val)
173 /* At end of file. The value is complete, there can't be
174 any continuation lines. */
175 svn_config_set(ctx->cfg, ctx->section->data,
176 ctx->option->data, ctx->value->data);
177 break;
179 else
181 int count;
182 ++ctx->line;
183 SVN_ERR(skip_whitespace(ctx, &ch, &count));
185 switch (ch)
187 case '\n':
188 /* The next line was empty. Ergo, it can't be a
189 continuation line. */
190 ++ctx->line;
191 end_of_val = TRUE;
192 continue;
194 case EOF:
195 /* This is also an empty line. */
196 end_of_val = TRUE;
197 continue;
199 default:
200 if (count == 0)
202 /* This line starts in the first column. That means
203 it's either a section, option or comment. Put
204 the char back into the stream, because it doesn't
205 belong to us. */
206 SVN_ERR(parser_ungetc(ctx, ch));
207 end_of_val = TRUE;
209 else
211 /* This is a continuation line. Read it. */
212 svn_stringbuf_appendbytes(ctx->value, " ", 1);
214 while (ch != EOF && ch != '\n')
216 const char char_from_int = ch;
217 svn_stringbuf_appendbytes(ctx->value,
218 &char_from_int, 1);
219 SVN_ERR(parser_getc(ctx, &ch));
221 /* Trailing whitespace is ignored. */
222 svn_stringbuf_strip_whitespace(ctx->value);
228 *pch = ch;
229 return SVN_NO_ERROR;
233 /* Parse a single option */
234 static svn_error_t *
235 parse_option(int *pch, parse_context_t *ctx, apr_pool_t *pool)
237 svn_error_t *err = SVN_NO_ERROR;
238 int ch;
240 svn_stringbuf_setempty(ctx->option);
241 ch = *pch; /* Yes, the first char is relevant. */
242 while (ch != EOF && ch != ':' && ch != '=' && ch != '\n')
244 const char char_from_int = ch;
245 svn_stringbuf_appendbytes(ctx->option, &char_from_int, 1);
246 SVN_ERR(parser_getc(ctx, &ch));
249 if (ch != ':' && ch != '=')
251 ch = EOF;
252 err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
253 "%s:%d: Option must end with ':' or '='",
254 svn_path_local_style(ctx->file, pool),
255 ctx->line);
257 else
259 /* Whitespace around the name separator is ignored. */
260 svn_stringbuf_strip_whitespace(ctx->option);
261 err = parse_value(&ch, ctx);
264 *pch = ch;
265 return err;
269 /* Read chars until enounter ']', then skip everything to the end of
270 * the line. Set *PCH to the character that ended the line (either
271 * newline or EOF), and set CTX->section to the string of characters
272 * seen before ']'.
274 * This is meant to be called immediately after reading the '[' that
275 * starts a section name.
277 static svn_error_t *
278 parse_section_name(int *pch, parse_context_t *ctx, apr_pool_t *pool)
280 svn_error_t *err = SVN_NO_ERROR;
281 int ch;
283 svn_stringbuf_setempty(ctx->section);
284 SVN_ERR(parser_getc(ctx, &ch));
285 while (ch != EOF && ch != ']' && ch != '\n')
287 const char char_from_int = ch;
288 svn_stringbuf_appendbytes(ctx->section, &char_from_int, 1);
289 SVN_ERR(parser_getc(ctx, &ch));
292 if (ch != ']')
294 ch = EOF;
295 err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
296 "%s:%d: Section header must end with ']'",
297 svn_path_local_style(ctx->file, pool),
298 ctx->line);
300 else
302 /* Everything from the ']' to the end of the line is ignored. */
303 SVN_ERR(skip_to_eoln(ctx, &ch));
304 if (ch != EOF)
305 ++ctx->line;
308 *pch = ch;
309 return err;
313 svn_error_t *
314 svn_config__sys_config_path(const char **path_p,
315 const char *fname,
316 apr_pool_t *pool)
318 /* ### This never actually returns error in practice. Perhaps the
319 prototype should change? */
321 *path_p = NULL;
323 /* Note that even if fname is null, svn_path_join_many will DTRT. */
325 #ifdef WIN32
327 const char *folder;
328 SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool));
329 *path_p = svn_path_join_many(pool, folder,
330 SVN_CONFIG__SUBDIRECTORY, fname, NULL);
333 #else /* ! WIN32 */
335 *path_p = svn_path_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
337 #endif /* WIN32 */
339 return SVN_NO_ERROR;
343 svn_error_t *
344 svn_config__user_config_path(const char *config_dir,
345 const char **path_p,
346 const char *fname,
347 apr_pool_t *pool)
349 /* ### This never actually returns error in practice. Perhaps the
350 prototype should change? */
352 *path_p = NULL;
354 /* Note that even if fname is null, svn_path_join_many will DTRT. */
356 if (config_dir)
358 *path_p = svn_path_join_many(pool, config_dir, fname, NULL);
359 return SVN_NO_ERROR;
362 #ifdef WIN32
364 const char *folder;
365 SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool));
366 *path_p = svn_path_join_many(pool, folder,
367 SVN_CONFIG__SUBDIRECTORY, fname, NULL);
370 #else /* ! WIN32 */
372 const char *homedir = svn_user_get_homedir(pool);
373 if (! homedir)
374 return SVN_NO_ERROR;
375 *path_p = svn_path_join_many(pool,
376 svn_path_canonicalize(homedir, pool),
377 SVN_CONFIG__USR_DIRECTORY, fname, NULL);
379 #endif /* WIN32 */
381 return SVN_NO_ERROR;
386 /*** Exported interfaces. ***/
389 svn_error_t *
390 svn_config__parse_file(svn_config_t *cfg, const char *file,
391 svn_boolean_t must_exist, apr_pool_t *pool)
393 svn_error_t *err = SVN_NO_ERROR;
394 parse_context_t ctx;
395 int ch, count;
396 apr_file_t *f;
398 /* No need for buffering; a translated stream buffers */
399 err = svn_io_file_open(&f, file, APR_BINARY | APR_READ,
400 APR_OS_DEFAULT, pool);
402 if (! must_exist && err && APR_STATUS_IS_ENOENT(err->apr_err))
404 svn_error_clear(err);
405 return SVN_NO_ERROR;
407 else
408 SVN_ERR(err);
410 ctx.cfg = cfg;
411 ctx.file = file;
412 ctx.stream = svn_subst_stream_translated(svn_stream_from_aprfile(f, pool),
413 "\n", TRUE, NULL, FALSE, pool);
414 ctx.line = 1;
415 ctx.have_ungotten_char = FALSE;
416 ctx.section = svn_stringbuf_create("", pool);
417 ctx.option = svn_stringbuf_create("", pool);
418 ctx.value = svn_stringbuf_create("", pool);
422 SVN_ERR(skip_whitespace(&ctx, &ch, &count));
424 switch (ch)
426 case '[': /* Start of section header */
427 if (count == 0)
428 SVN_ERR(parse_section_name(&ch, &ctx, pool));
429 else
430 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
431 "%s:%d: Section header"
432 " must start in the first column",
433 svn_path_local_style(file, pool),
434 ctx.line);
435 break;
437 case '#': /* Comment */
438 if (count == 0)
440 SVN_ERR(skip_to_eoln(&ctx, &ch));
441 ++ctx.line;
443 else
444 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
445 "%s:%d: Comment"
446 " must start in the first column",
447 svn_path_local_style(file, pool),
448 ctx.line);
449 break;
451 case '\n': /* Empty line */
452 ++ctx.line;
453 break;
455 case EOF: /* End of file or read error */
456 break;
458 default:
459 if (svn_stringbuf_isempty(ctx.section))
460 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
461 "%s:%d: Section header expected",
462 svn_path_local_style(file, pool),
463 ctx.line);
464 else if (count != 0)
465 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
466 "%s:%d: Option expected",
467 svn_path_local_style(file, pool),
468 ctx.line);
469 else
470 SVN_ERR(parse_option(&ch, &ctx, pool));
471 break;
474 while (ch != EOF);
476 /* Close the file and streams (and other cleanup): */
477 SVN_ERR(svn_stream_close(ctx.stream));
478 SVN_ERR(svn_io_file_close(f, pool));
480 return SVN_NO_ERROR;
484 /* Helper for svn_config_ensure: see if ~/.subversion/auth/ and its
485 subdirs exist, try to create them, but don't throw errors on
486 failure. PATH is assumed to be a path to the user's private config
487 directory. */
488 static void
489 ensure_auth_dirs(const char *path,
490 apr_pool_t *pool)
492 svn_node_kind_t kind;
493 const char *auth_dir, *auth_subdir;
494 svn_error_t *err;
496 /* Ensure ~/.subversion/auth/ */
497 auth_dir = svn_path_join_many(pool, path, SVN_CONFIG__AUTH_SUBDIR, NULL);
498 err = svn_io_check_path(auth_dir, &kind, pool);
499 if (err || kind == svn_node_none)
501 svn_error_clear(err);
502 /* 'chmod 700' permissions: */
503 err = svn_io_dir_make(auth_dir,
504 (APR_UREAD | APR_UWRITE | APR_UEXECUTE),
505 pool);
506 if (err)
508 /* Don't try making subdirs if we can't make the top-level dir. */
509 svn_error_clear(err);
510 return;
514 /* If a provider exists that wants to store credentials in
515 ~/.subversion, a subdirectory for the cred_kind must exist. */
517 auth_subdir = svn_path_join_many(pool, auth_dir,
518 SVN_AUTH_CRED_SIMPLE, NULL);
519 err = svn_io_check_path(auth_subdir, &kind, pool);
520 if (err || kind == svn_node_none)
522 svn_error_clear(err);
523 svn_error_clear(svn_io_dir_make(auth_subdir, APR_OS_DEFAULT, pool));
526 auth_subdir = svn_path_join_many(pool, auth_dir,
527 SVN_AUTH_CRED_USERNAME, NULL);
528 err = svn_io_check_path(auth_subdir, &kind, pool);
529 if (err || kind == svn_node_none)
531 svn_error_clear(err);
532 svn_error_clear(svn_io_dir_make(auth_subdir, APR_OS_DEFAULT, pool));
535 auth_subdir = svn_path_join_many(pool, auth_dir,
536 SVN_AUTH_CRED_SSL_SERVER_TRUST, NULL);
537 err = svn_io_check_path(auth_subdir, &kind, pool);
538 if (err || kind == svn_node_none)
540 svn_error_clear(err);
541 svn_error_clear(svn_io_dir_make(auth_subdir, APR_OS_DEFAULT, pool));
546 svn_error_t *
547 svn_config_ensure(const char *config_dir, apr_pool_t *pool)
549 const char *path;
550 svn_node_kind_t kind;
551 svn_error_t *err;
553 /* Ensure that the user-specific config directory exists. */
554 SVN_ERR(svn_config__user_config_path(config_dir, &path, NULL, pool));
556 if (! path)
557 return SVN_NO_ERROR;
559 err = svn_io_check_path(path, &kind, pool);
560 if (err)
562 /* Don't throw an error, but don't continue. */
563 svn_error_clear(err);
564 return SVN_NO_ERROR;
567 if (kind == svn_node_none)
569 err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
570 if (err)
572 /* Don't throw an error, but don't continue. */
573 svn_error_clear(err);
574 return SVN_NO_ERROR;
577 else if (kind == svn_node_file)
579 /* Somebody put a file where the config directory should be.
580 Wacky. Let's bail. */
581 return SVN_NO_ERROR;
584 /* Else, there's a configuration directory. */
586 /* If we get errors trying to do things below, just stop and return
587 success. There's no _need_ to init a config directory if
588 something's preventing it. */
590 /** If non-existent, try to create a number of auth/ subdirectories. */
591 ensure_auth_dirs(path, pool);
593 /** Ensure that the `README.txt' file exists. **/
594 SVN_ERR(svn_config__user_config_path
595 (config_dir, &path, SVN_CONFIG__USR_README_FILE, pool));
597 if (! path) /* highly unlikely, since a previous call succeeded */
598 return SVN_NO_ERROR;
600 err = svn_io_check_path(path, &kind, pool);
601 if (err)
603 svn_error_clear(err);
604 return SVN_NO_ERROR;
607 if (kind == svn_node_none)
609 apr_file_t *f;
610 const char *contents =
611 "This directory holds run-time configuration information for Subversion" NL
612 "clients. The configuration files all share the same syntax, but you" NL
613 "should examine a particular file to learn what configuration" NL
614 "directives are valid for that file." NL
615 "" NL
616 "The syntax is standard INI format:" NL
617 "" NL
618 " - Empty lines, and lines starting with '#', are ignored." NL
619 " The first significant line in a file must be a section header." NL
620 "" NL
621 " - A section starts with a section header, which must start in" NL
622 " the first column:" NL
623 "" NL
624 " [section-name]" NL
625 "" NL
626 " - An option, which must always appear within a section, is a pair" NL
627 " (name, value). There are two valid forms for defining an" NL
628 " option, both of which must start in the first column:" NL
629 "" NL
630 " name: value" NL
631 " name = value" NL
632 "" NL
633 " Whitespace around the separator (:, =) is optional." NL
634 "" NL
635 " - Section and option names are case-insensitive, but case is" NL
636 " preserved." NL
637 "" NL
638 " - An option's value may be broken into several lines. The value" NL
639 " continuation lines must start with at least one whitespace." NL
640 " Trailing whitespace in the previous line, the newline character" NL
641 " and the leading whitespace in the continuation line is compressed" NL
642 " into a single space character." NL
643 "" NL
644 " - All leading and trailing whitespace around a value is trimmed," NL
645 " but the whitespace within a value is preserved, with the" NL
646 " exception of whitespace around line continuations, as" NL
647 " described above." NL
648 "" NL
649 " - When a value is a boolean, any of the following strings are" NL
650 " recognised as truth values (case does not matter):" NL
651 "" NL
652 " true false" NL
653 " yes no" NL
654 " on off" NL
655 " 1 0" NL
656 "" NL
657 " - When a value is a list, it is comma-separated. Again, the" NL
658 " whitespace around each element of the list is trimmed." NL
659 "" NL
660 " - Option values may be expanded within a value by enclosing the" NL
661 " option name in parentheses, preceded by a percent sign and" NL
662 " followed by an 's':" NL
663 "" NL
664 " %(name)s" NL
665 "" NL
666 " The expansion is performed recursively and on demand, during" NL
667 " svn_option_get. The name is first searched for in the same" NL
668 " section, then in the special [DEFAULT] section. If the name" NL
669 " is not found, the whole '%(name)s' placeholder is left" NL
670 " unchanged." NL
671 "" NL
672 " Any modifications to the configuration data invalidate all" NL
673 " previously expanded values, so that the next svn_option_get" NL
674 " will take the modifications into account." NL
675 "" NL
676 "The syntax of the configuration files is a subset of the one used by" NL
677 "Python's ConfigParser module; see" NL
678 "" NL
679 " http://www.python.org/doc/current/lib/module-ConfigParser.html" NL
680 "" NL
681 "Configuration data in the Windows registry" NL
682 "==========================================" NL
683 "" NL
684 "On Windows, configuration data may also be stored in the registry. The" NL
685 "functions svn_config_read and svn_config_merge will read from the" NL
686 "registry when passed file names of the form:" NL
687 "" NL
688 " REGISTRY:<hive>/path/to/config-key" NL
689 "" NL
690 "The REGISTRY: prefix must be in upper case. The <hive> part must be" NL
691 "one of:" NL
692 "" NL
693 " HKLM for HKEY_LOCAL_MACHINE" NL
694 " HKCU for HKEY_CURRENT_USER" NL
695 "" NL
696 "The values in config-key represent the options in the [DEFAULT] section."NL
697 "The keys below config-key represent other sections, and their values" NL
698 "represent the options. Only values of type REG_SZ whose name doesn't" NL
699 "start with a '#' will be used; other values, as well as the keys'" NL
700 "default values, will be ignored." NL
701 "" NL
702 "" NL
703 "File locations" NL
704 "==============" NL
705 "" NL
706 "Typically, Subversion uses two config directories, one for site-wide" NL
707 "configuration," NL
708 "" NL
709 " Unix:" NL
710 " /etc/subversion/servers" NL
711 " /etc/subversion/config" NL
712 " /etc/subversion/hairstyles" NL
713 " Windows:" NL
714 " %ALLUSERSPROFILE%\\Application Data\\Subversion\\servers" NL
715 " %ALLUSERSPROFILE%\\Application Data\\Subversion\\config" NL
716 " %ALLUSERSPROFILE%\\Application Data\\Subversion\\hairstyles" NL
717 " REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Servers" NL
718 " REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Config" NL
719 " REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Hairstyles" NL
720 "" NL
721 "and one for per-user configuration:" NL
722 "" NL
723 " Unix:" NL
724 " ~/.subversion/servers" NL
725 " ~/.subversion/config" NL
726 " ~/.subversion/hairstyles" NL
727 " Windows:" NL
728 " %APPDATA%\\Subversion\\servers" NL
729 " %APPDATA%\\Subversion\\config" NL
730 " %APPDATA%\\Subversion\\hairstyles" NL
731 " REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Servers" NL
732 " REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Config" NL
733 " REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Hairstyles" NL
734 "" NL;
736 err = svn_io_file_open(&f, path,
737 (APR_WRITE | APR_CREATE | APR_EXCL),
738 APR_OS_DEFAULT,
739 pool);
741 if (! err)
743 SVN_ERR(svn_io_file_write_full(f, contents,
744 strlen(contents), NULL, pool));
745 SVN_ERR(svn_io_file_close(f, pool));
748 svn_error_clear(err);
751 /** Ensure that the `servers' file exists. **/
752 SVN_ERR(svn_config__user_config_path
753 (config_dir, &path, SVN_CONFIG_CATEGORY_SERVERS, pool));
755 if (! path) /* highly unlikely, since a previous call succeeded */
756 return SVN_NO_ERROR;
758 err = svn_io_check_path(path, &kind, pool);
759 if (err)
761 svn_error_clear(err);
762 return SVN_NO_ERROR;
765 if (kind == svn_node_none)
767 apr_file_t *f;
768 const char *contents =
769 "### This file specifies server-specific protocol parameters," NL
770 "### including HTTP proxy information, and HTTP timeout settings." NL
771 "###" NL
772 "### The currently defined server options are:" NL
773 "### http-proxy-host Proxy host for HTTP connection" NL
774 "### http-proxy-port Port number of proxy host service" NL
775 "### http-proxy-username Username for auth to proxy service"NL
776 "### http-proxy-password Password for auth to proxy service"NL
777 "### http-proxy-exceptions List of sites that do not use proxy"
779 "### http-timeout Timeout for HTTP requests in seconds"
781 "### http-compression Whether to compress HTTP requests" NL
782 "### neon-debug-mask Debug mask for Neon HTTP library" NL
783 #ifdef SVN_NEON_0_26
784 "### http-auth-types Auth types to use for HTTP library"NL
785 #endif
786 "### ssl-authority-files List of files, each of a trusted CAs"
788 "### ssl-trust-default-ca Trust the system 'default' CAs" NL
789 "### ssl-client-cert-file PKCS#12 format client certificate file"
791 "### ssl-client-cert-password Client Key password, if needed." NL
792 "### http-library Which library to use for http/https"
794 "### connections (neon or serf)" NL
795 "###" NL
796 "### HTTP timeouts, if given, are specified in seconds. A timeout" NL
797 "### of 0, i.e. zero, causes a builtin default to be used." NL
798 "###" NL
799 "### The commented-out examples below are intended only to" NL
800 "### demonstrate how to use this file; any resemblance to actual" NL
801 "### servers, living or dead, is entirely coincidental." NL
802 "" NL
803 "### In this section, the URL of the repository you're trying to" NL
804 "### access is matched against the patterns on the right. If a" NL
805 "### match is found, the server info is from the section with the" NL
806 "### corresponding name." NL
807 "" NL
808 "[groups]" NL
809 "# group1 = *.collab.net" NL
810 "# othergroup = repository.blarggitywhoomph.com" NL
811 "# thirdgroup = *.example.com" NL
812 "" NL
813 "### Information for the first group:" NL
814 "# [group1]" NL
815 "# http-proxy-host = proxy1.some-domain-name.com" NL
816 "# http-proxy-port = 80" NL
817 "# http-proxy-username = blah" NL
818 "# http-proxy-password = doubleblah" NL
819 "# http-timeout = 60" NL
820 #ifdef SVN_NEON_0_26
821 "# http-auth-types = basic;digest;negotiate" NL
822 #endif
823 "# neon-debug-mask = 130" NL
824 "" NL
825 "### Information for the second group:" NL
826 "# [othergroup]" NL
827 "# http-proxy-host = proxy2.some-domain-name.com" NL
828 "# http-proxy-port = 9000" NL
829 "# No username and password, so use the defaults below." NL
830 "" NL
831 "### You can set default parameters in the 'global' section." NL
832 "### These parameters apply if no corresponding parameter is set in" NL
833 "### a specifically matched group as shown above. Thus, if you go" NL
834 "### through the same proxy server to reach every site on the" NL
835 "### Internet, you probably just want to put that server's" NL
836 "### information in the 'global' section and not bother with" NL
837 "### 'groups' or any other sections." NL
838 "###" NL
839 "### If you go through a proxy for all but a few sites, you can" NL
840 "### list those exceptions under 'http-proxy-exceptions'. This only"NL
841 "### overrides defaults, not explicitly matched server names." NL
842 "###" NL
843 "### 'ssl-authority-files' is a semicolon-delimited list of files," NL
844 "### each pointing to a PEM-encoded Certificate Authority (CA) " NL
845 "### SSL certificate. See details above for overriding security " NL
846 "### due to SSL." NL
847 "[global]" NL
848 "# http-proxy-exceptions = *.exception.com, www.internal-site.org" NL
849 "# http-proxy-host = defaultproxy.whatever.com" NL
850 "# http-proxy-port = 7000" NL
851 "# http-proxy-username = defaultusername" NL
852 "# http-proxy-password = defaultpassword" NL
853 "# http-compression = no" NL
854 #ifdef SVN_NEON_0_26
855 "# http-auth-types = basic;digest;negotiate" NL
856 #endif
857 "# No http-timeout, so just use the builtin default." NL
858 "# No neon-debug-mask, so neon debugging is disabled." NL
859 "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem" NL;
861 err = svn_io_file_open(&f, path,
862 (APR_WRITE | APR_CREATE | APR_EXCL),
863 APR_OS_DEFAULT,
864 pool);
866 if (! err)
868 SVN_ERR(svn_io_file_write_full(f, contents,
869 strlen(contents), NULL, pool));
870 SVN_ERR(svn_io_file_close(f, pool));
873 svn_error_clear(err);
876 /** Ensure that the `config' file exists. **/
877 SVN_ERR(svn_config__user_config_path
878 (config_dir, &path, SVN_CONFIG_CATEGORY_CONFIG, pool));
880 if (! path) /* highly unlikely, since a previous call succeeded */
881 return SVN_NO_ERROR;
883 err = svn_io_check_path(path, &kind, pool);
884 if (err)
886 svn_error_clear(err);
887 return SVN_NO_ERROR;
890 if (kind == svn_node_none)
892 apr_file_t *f;
893 const char *contents =
894 "### This file configures various client-side behaviors." NL
895 "###" NL
896 "### The commented-out examples below are intended to demonstrate" NL
897 "### how to use this file." NL
898 "" NL
899 "### Section for authentication and authorization customizations." NL
900 "[auth]" NL
901 "### Set store-passwords to 'no' to avoid storing passwords in the" NL
902 "### auth/ area of your config directory. It defaults to 'yes'." NL
903 "### Note that this option only prevents saving of *new* passwords;" NL
904 "### it doesn't invalidate existing passwords. (To do that, remove" NL
905 "### the cache files by hand as described in the Subversion book.)" NL
906 "# store-passwords = no" NL
907 "### Set store-auth-creds to 'no' to avoid storing any subversion" NL
908 "### credentials in the auth/ area of your config directory." NL
909 "### It defaults to 'yes'. Note that this option only prevents" NL
910 "### saving of *new* credentials; it doesn't invalidate existing" NL
911 "### caches. (To do that, remove the cache files by hand.)" NL
912 "# store-auth-creds = no" NL
913 "" NL
914 "### Section for configuring external helper applications." NL
915 "[helpers]" NL
916 "### Set editor to the command used to invoke your text editor." NL
917 "### This will override the environment variables that Subversion" NL
918 "### examines by default to find this information ($EDITOR, " NL
919 "### et al)." NL
920 "# editor-cmd = editor (vi, emacs, notepad, etc.)" NL
921 "### Set diff-cmd to the absolute path of your 'diff' program." NL
922 "### This will override the compile-time default, which is to use" NL
923 "### Subversion's internal diff implementation." NL
924 "# diff-cmd = diff_program (diff, gdiff, etc.)" NL
925 "### Set diff3-cmd to the absolute path of your 'diff3' program." NL
926 "### This will override the compile-time default, which is to use" NL
927 "### Subversion's internal diff3 implementation." NL
928 "# diff3-cmd = diff3_program (diff3, gdiff3, etc.)" NL
929 "### Set diff3-has-program-arg to 'true' or 'yes' if your 'diff3'" NL
930 "### program accepts the '--diff-program' option." NL
931 "# diff3-has-program-arg = [true | false]" NL
932 "### Set merge-tool-cmd to the command used to invoke your external" NL
933 "### merging tool of choice. Subversion will pass 4 arguments to" NL
934 "### the specified command: base theirs mine merged" NL
935 "# merge-tool-cmd = merge_command" NL
936 "" NL
937 "### Section for configuring tunnel agents." NL
938 "[tunnels]" NL
939 "### Configure svn protocol tunnel schemes here. By default, only" NL
940 "### the 'ssh' scheme is defined. You can define other schemes to" NL
941 "### be used with 'svn+scheme://hostname/path' URLs. A scheme" NL
942 "### definition is simply a command, optionally prefixed by an" NL
943 "### environment variable name which can override the command if it" NL
944 "### is defined. The command (or environment variable) may contain" NL
945 "### arguments, using standard shell quoting for arguments with" NL
946 "### spaces. The command will be invoked as:" NL
947 "### <command> <hostname> svnserve -t" NL
948 "### (If the URL includes a username, then the hostname will be" NL
949 "### passed to the tunnel agent as <user>@<hostname>.) If the" NL
950 "### built-in ssh scheme were not predefined, it could be defined" NL
951 "### as:" NL
952 "# ssh = $SVN_SSH ssh" NL
953 "### If you wanted to define a new 'rsh' scheme, to be used with" NL
954 "### 'svn+rsh:' URLs, you could do so as follows:" NL
955 "# rsh = rsh" NL
956 "### Or, if you wanted to specify a full path and arguments:" NL
957 "# rsh = /path/to/rsh -l myusername" NL
958 "### On Windows, if you are specifying a full path to a command," NL
959 "### use a forward slash (/) or a paired backslash (\\\\) as the" NL
960 "### path separator. A single backslash will be treated as an" NL
961 "### escape for the following character." NL
962 "" NL
963 "### Section for configuring miscelleneous Subversion options." NL
964 "[miscellany]" NL
965 "### Set global-ignores to a set of whitespace-delimited globs" NL
966 "### which Subversion will ignore in its 'status' output, and" NL
967 "### while importing or adding files and directories." NL
968 "### '*' matches leading dots, e.g. '*.rej' matches '.foo.rej'." NL
969 "# global-ignores = " SVN_CONFIG__DEFAULT_GLOBAL_IGNORES_LINE_1 NL
970 "# " SVN_CONFIG__DEFAULT_GLOBAL_IGNORES_LINE_2 NL
971 "### Set log-encoding to the default encoding for log messages" NL
972 "# log-encoding = latin1" NL
973 "### Set use-commit-times to make checkout/update/switch/revert" NL
974 "### put last-committed timestamps on every file touched." NL
975 "# use-commit-times = yes" NL
976 "### Set no-unlock to prevent 'svn commit' from automatically" NL
977 "### releasing locks on files." NL
978 "# no-unlock = yes" NL
979 "### Set mime-types-file to a MIME type registry file, used to" NL
980 "### provide hints to Subversion's MIME type auto-detection" NL
981 "### algorithm." NL
982 "# mime-types-file = /path/to/mime.types" NL
983 "### Set preserved-conflict-file-exts to a whitespace-delimited" NL
984 "### list of patterns matching file extensions which should be" NL
985 "### preserved in generated conflict file names. By default," NL
986 "### conflict files use custom extensions." NL
987 "# preserved-conflict-file-exts = doc ppt xls od?" NL
988 "### Set enable-auto-props to 'yes' to enable automatic properties" NL
989 "### for 'svn add' and 'svn import', it defaults to 'no'." NL
990 "### Automatic properties are defined in the section 'auto-props'." NL
991 "# enable-auto-props = yes" NL
992 "### Set interactive-conflicts to 'no' to disable interactive" NL
993 "### conflict resolution prompting. It defaults to 'yes'." NL
994 "# interactive-conflicts = no" NL
995 "" NL
996 "### Section for configuring automatic properties." NL
997 "[auto-props]" NL
998 "### The format of the entries is:" NL
999 "### file-name-pattern = propname[=value][;propname[=value]...]" NL
1000 "### The file-name-pattern can contain wildcards (such as '*' and" NL
1001 "### '?'). All entries which match (case-insensitively) will be" NL
1002 "### applied to the file. Note that auto-props functionality" NL
1003 "### must be enabled, which is typically done by setting the" NL
1004 "### 'enable-auto-props' option." NL
1005 "# *.c = svn:eol-style=native" NL
1006 "# *.cpp = svn:eol-style=native" NL
1007 "# *.h = svn:eol-style=native" NL
1008 "# *.dsp = svn:eol-style=CRLF" NL
1009 "# *.dsw = svn:eol-style=CRLF" NL
1010 "# *.sh = svn:eol-style=native;svn:executable" NL
1011 "# *.txt = svn:eol-style=native" NL
1012 "# *.png = svn:mime-type=image/png" NL
1013 "# *.jpg = svn:mime-type=image/jpeg" NL
1014 "# Makefile = svn:eol-style=native" NL
1015 "" NL;
1017 err = svn_io_file_open(&f, path,
1018 (APR_WRITE | APR_CREATE | APR_EXCL),
1019 APR_OS_DEFAULT,
1020 pool);
1022 if (! err)
1024 SVN_ERR(svn_io_file_write_full(f, contents,
1025 strlen(contents), NULL, pool));
1026 SVN_ERR(svn_io_file_close(f, pool));
1029 svn_error_clear(err);
1032 return SVN_NO_ERROR;