2 * config_file.c : parsing configuration files
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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
21 * ====================================================================
28 #include "config_impl.h"
30 #include "svn_types.h"
31 #include "svn_dirent_uri.h"
34 #include "svn_subst.h"
36 #include "svn_pools.h"
38 #include "svn_ctype.h"
40 #include "svn_private_config.h"
41 #include "private/svn_subr_private.h"
44 # include <FindDirectory.h>
45 # include <StorageDefs.h>
48 /* Used to terminate lines in large multi-line string literals. */
49 #define NL APR_EOL_STR
52 /* File parsing context */
53 typedef struct parse_context_t
55 /* This config struct */
58 /* The stream struct */
61 /* The current line in the file */
64 /* Emulate an ungetc */
67 /* Temporary strings */
68 svn_stringbuf_t *section;
69 svn_stringbuf_t *option;
70 svn_stringbuf_t *value;
72 /* Parser buffer for getc() to avoid call overhead into several libraries
73 for every character */
74 char parser_buffer[SVN__STREAM_CHUNK_SIZE]; /* Larger than most config files */
75 size_t buffer_pos; /* Current position within parser_buffer */
76 size_t buffer_size; /* parser_buffer contains this many bytes */
78 /* Non-zero if we hit EOF on the stream. */
79 svn_boolean_t hit_stream_eof;
84 /* Emulate getc() because streams don't support it.
86 * In order to be able to ungetc(), use the CXT instead of the stream
87 * to be able to store the 'ungotton' character.
90 static APR_INLINE svn_error_t *
91 parser_getc(parse_context_t *ctx, int *c)
95 if (ctx->ungotten_char != EOF)
97 *c = ctx->ungotten_char;
98 ctx->ungotten_char = EOF;
100 else if (ctx->buffer_pos < ctx->buffer_size)
102 *c = (unsigned char)ctx->parser_buffer[ctx->buffer_pos];
107 if (!ctx->hit_stream_eof)
110 ctx->buffer_size = sizeof(ctx->parser_buffer);
112 SVN_ERR(svn_stream_read_full(ctx->stream, ctx->parser_buffer,
113 &(ctx->buffer_size)));
114 ctx->hit_stream_eof = (ctx->buffer_size != sizeof(ctx->parser_buffer));
117 if (ctx->buffer_pos < ctx->buffer_size)
119 *c = (unsigned char)ctx->parser_buffer[ctx->buffer_pos];
131 /* Simplified version of parser_getc() to be used inside skipping loops.
132 * It will not check for 'ungotton' chars and may or may not ignore '\r'.
134 * In a 'while(cond) getc();' loop, the first iteration must call
135 * parser_getc to handle all the special cases. Later iterations should
136 * use parser_getc_plain for maximum performance.
138 static APR_INLINE svn_error_t *
139 parser_getc_plain(parse_context_t *ctx, int *c)
141 if (ctx->buffer_pos < ctx->buffer_size)
143 *c = (unsigned char)ctx->parser_buffer[ctx->buffer_pos];
149 return parser_getc(ctx, c);
152 /* Emulate ungetc() because streams don't support it.
154 * Use CTX to store the ungotten character C.
156 static APR_INLINE svn_error_t *
157 parser_ungetc(parse_context_t *ctx, int c)
159 ctx->ungotten_char = c;
164 /* Eat chars from STREAM until encounter non-whitespace, newline, or EOF.
165 Set *PCOUNT to the number of characters eaten, not counting the
166 last one, and return the last char read (the one that caused the
168 static APR_INLINE svn_error_t *
169 skip_whitespace(parse_context_t *ctx, int *c, int *pcount)
174 SVN_ERR(parser_getc(ctx, &ch));
175 while (svn_ctype_isspace(ch) && ch != '\n' && ch != EOF)
178 SVN_ERR(parser_getc_plain(ctx, &ch));
186 /* Skip to the end of the line (or file). Returns the char that ended
187 the line; the char is either EOF or newline. */
188 static APR_INLINE svn_error_t *
189 skip_to_eoln(parse_context_t *ctx, int *c)
193 SVN_ERR(parser_getc(ctx, &ch));
194 while (ch != '\n' && ch != EOF)
196 /* This is much faster than checking individual bytes.
197 * We use this function a lot when skipping comment lines.
199 * This assumes that the ungetc buffer is empty, but that is a
200 * safe assumption right after reading a character (which would
201 * clear the buffer. */
202 const char *newline = memchr(ctx->parser_buffer + ctx->buffer_pos, '\n',
203 ctx->buffer_size - ctx->buffer_pos);
207 ctx->buffer_pos = newline - ctx->parser_buffer + 1;
211 /* refill buffer, check for EOF */
212 SVN_ERR(parser_getc_plain(ctx, &ch));
219 /* Skip a UTF-8 Byte Order Mark if found. */
220 static APR_INLINE svn_error_t *
221 skip_bom(parse_context_t *ctx)
225 SVN_ERR(parser_getc(ctx, &ch));
228 const unsigned char *buf = (unsigned char *)ctx->parser_buffer;
229 /* This makes assumptions about the implementation of parser_getc and
230 * the use of skip_bom. Specifically that parser_getc() will get all
231 * of the BOM characters into the parse_context_t buffer. This can
232 * safely be assumed as long as we only try to use skip_bom() at the
233 * start of the stream and the buffer is longer than 3 characters. */
234 SVN_ERR_ASSERT(ctx->buffer_size > ctx->buffer_pos + 1 ||
235 ctx->hit_stream_eof);
236 if (ctx->buffer_size > ctx->buffer_pos + 1 &&
237 buf[ctx->buffer_pos] == 0xBB && buf[ctx->buffer_pos + 1] == 0xBF)
238 ctx->buffer_pos += 2;
240 SVN_ERR(parser_ungetc(ctx, ch));
243 SVN_ERR(parser_ungetc(ctx, ch));
248 /* Parse a single option value */
250 parse_value(int *pch, parse_context_t *ctx)
252 svn_boolean_t end_of_val = FALSE;
255 /* Read the first line of the value */
256 svn_stringbuf_setempty(ctx->value);
257 SVN_ERR(parser_getc(ctx, &ch));
258 while (ch != EOF && ch != '\n')
259 /* last ch seen was ':' or '=' in parse_option. */
261 const char char_from_int = (char)ch;
262 svn_stringbuf_appendbyte(ctx->value, char_from_int);
263 SVN_ERR(parser_getc(ctx, &ch));
265 /* Leading and trailing whitespace is ignored. */
266 svn_stringbuf_strip_whitespace(ctx->value);
268 /* Look for any continuation lines. */
272 if (ch == EOF || end_of_val)
274 /* At end of file. The value is complete, there can't be
275 any continuation lines. */
276 svn_config_set(ctx->cfg, ctx->section->data,
277 ctx->option->data, ctx->value->data);
284 SVN_ERR(skip_whitespace(ctx, &ch, &count));
289 /* The next line was empty. Ergo, it can't be a
290 continuation line. */
296 /* This is also an empty line. */
303 /* This line starts in the first column. That means
304 it's either a section, option or comment. Put
305 the char back into the stream, because it doesn't
307 SVN_ERR(parser_ungetc(ctx, ch));
312 /* This is a continuation line. Read it. */
313 svn_stringbuf_appendbyte(ctx->value, ' ');
315 while (ch != EOF && ch != '\n')
317 const char char_from_int = (char)ch;
318 svn_stringbuf_appendbyte(ctx->value, char_from_int);
319 SVN_ERR(parser_getc(ctx, &ch));
321 /* Trailing whitespace is ignored. */
322 svn_stringbuf_strip_whitespace(ctx->value);
333 /* Parse a single option */
335 parse_option(int *pch, parse_context_t *ctx, apr_pool_t *scratch_pool)
337 svn_error_t *err = SVN_NO_ERROR;
340 svn_stringbuf_setempty(ctx->option);
341 ch = *pch; /* Yes, the first char is relevant. */
342 while (ch != EOF && ch != ':' && ch != '=' && ch != '\n')
344 const char char_from_int = (char)ch;
345 svn_stringbuf_appendbyte(ctx->option, char_from_int);
346 SVN_ERR(parser_getc(ctx, &ch));
349 if (ch != ':' && ch != '=')
352 err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
353 _("line %d: Option must end with ':' or '='"),
358 /* Whitespace around the name separator is ignored. */
359 svn_stringbuf_strip_whitespace(ctx->option);
360 err = parse_value(&ch, ctx);
368 /* Read chars until enounter ']', then skip everything to the end of
369 * the line. Set *PCH to the character that ended the line (either
370 * newline or EOF), and set CTX->section to the string of characters
373 * This is meant to be called immediately after reading the '[' that
374 * starts a section name.
377 parse_section_name(int *pch, parse_context_t *ctx,
378 apr_pool_t *scratch_pool)
380 svn_error_t *err = SVN_NO_ERROR;
383 svn_stringbuf_setempty(ctx->section);
384 SVN_ERR(parser_getc(ctx, &ch));
385 while (ch != EOF && ch != ']' && ch != '\n')
387 const char char_from_int = (char)ch;
388 svn_stringbuf_appendbyte(ctx->section, char_from_int);
389 SVN_ERR(parser_getc(ctx, &ch));
395 err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
396 _("line %d: Section header must end with ']'"),
401 /* Everything from the ']' to the end of the line is ignored. */
402 SVN_ERR(skip_to_eoln(ctx, &ch));
413 svn_config__sys_config_path(const char **path_p,
419 /* Note that even if fname is null, svn_dirent_join_many will DTRT. */
424 SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool, pool));
425 *path_p = svn_dirent_join_many(pool, folder,
426 SVN_CONFIG__SUBDIRECTORY, fname,
430 #elif defined(__HAIKU__)
432 char folder[B_PATH_NAME_LENGTH];
434 status_t error = find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false,
435 folder, sizeof(folder));
439 *path_p = svn_dirent_join_many(pool, folder,
440 SVN_CONFIG__SYS_DIRECTORY, fname,
443 #else /* ! WIN32 && !__HAIKU__ */
445 *path_p = svn_dirent_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname,
453 /* Callback for svn_config_enumerate2: Continue to next value. */
455 expand_value(const char *name,
463 /* Callback for svn_config_enumerate_sections2:
464 * Enumerate and implicitly expand all values in this section.
467 expand_values_in_section(const char *name,
471 svn_config_t *cfg = baton;
472 svn_config_enumerate2(cfg, name, expand_value, NULL, pool);
478 /*** Exported interfaces. ***/
481 svn_config__set_read_only(svn_config_t *cfg,
482 apr_pool_t *scratch_pool)
484 /* expand all items such that later calls to getters won't need to
485 * change internal state */
486 svn_config_enumerate_sections2(cfg, expand_values_in_section,
489 /* now, any modification attempt will be ignored / trigger an assertion
491 cfg->read_only = TRUE;
495 svn_config__is_read_only(svn_config_t *cfg)
497 return cfg->read_only;
501 svn_config__shallow_copy(svn_config_t *src,
504 svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
506 cfg->sections = src->sections;
509 /* r/o configs are fully expanded and don't need the x_pool anymore */
510 cfg->x_pool = src->read_only ? NULL : svn_pool_create(pool);
511 cfg->x_values = src->x_values;
512 cfg->tmp_key = svn_stringbuf_create_empty(pool);
513 cfg->tmp_value = svn_stringbuf_create_empty(pool);
514 cfg->section_names_case_sensitive = src->section_names_case_sensitive;
515 cfg->option_names_case_sensitive = src->option_names_case_sensitive;
516 cfg->read_only = src->read_only;
522 svn_config__shallow_replace_section(svn_config_t *target,
523 svn_config_t *source,
526 if (target->read_only)
527 target->sections = apr_hash_copy(target->pool, target->sections);
529 svn_hash_sets(target->sections, section,
530 svn_hash_gets(source->sections, section));
535 svn_config__parse_file(svn_config_t *cfg, const char *file,
536 svn_boolean_t must_exist, apr_pool_t *result_pool)
538 svn_error_t *err = SVN_NO_ERROR;
539 apr_file_t *apr_file;
540 svn_stream_t *stream;
541 apr_pool_t *scratch_pool = svn_pool_create(result_pool);
543 /* Use unbuffered IO since we use our own buffering. */
544 err = svn_io_file_open(&apr_file, file, APR_READ, APR_OS_DEFAULT,
547 if (! must_exist && err && APR_STATUS_IS_ENOENT(err->apr_err))
549 svn_error_clear(err);
550 svn_pool_destroy(scratch_pool);
556 stream = svn_stream_from_aprfile2(apr_file, FALSE, scratch_pool);
557 err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
559 if (err != SVN_NO_ERROR)
561 /* Add the filename to the error stack. */
562 err = svn_error_createf(err->apr_err, err,
563 _("Error while parsing config file: %s:"),
564 svn_dirent_local_style(file, scratch_pool));
567 /* Close the streams (and other cleanup): */
568 svn_pool_destroy(scratch_pool);
574 svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream,
575 apr_pool_t *result_pool, apr_pool_t *scratch_pool)
577 parse_context_t *ctx;
580 ctx = apr_palloc(scratch_pool, sizeof(*ctx));
583 ctx->stream = stream;
585 ctx->ungotten_char = EOF;
586 ctx->section = svn_stringbuf_create_empty(scratch_pool);
587 ctx->option = svn_stringbuf_create_empty(scratch_pool);
588 ctx->value = svn_stringbuf_create_empty(scratch_pool);
590 ctx->buffer_size = 0;
591 ctx->hit_stream_eof = FALSE;
593 SVN_ERR(skip_bom(ctx));
597 SVN_ERR(skip_whitespace(ctx, &ch, &count));
601 case '[': /* Start of section header */
603 SVN_ERR(parse_section_name(&ch, ctx, scratch_pool));
605 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
606 _("line %d: Section header"
607 " must start in the first column"),
611 case '#': /* Comment */
614 SVN_ERR(skip_to_eoln(ctx, &ch));
618 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
620 " must start in the first column"),
624 case '\n': /* Empty line */
628 case EOF: /* End of file or read error */
632 if (svn_stringbuf_isempty(ctx->section))
633 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
634 _("line %d: Section header expected"),
637 return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
638 _("line %d: Option expected"),
641 SVN_ERR(parse_option(&ch, ctx, scratch_pool));
651 /* Helper for ensure_auth_dirs: create SUBDIR under AUTH_DIR, iff
652 SUBDIR does not already exist, but ignore any errors. Use POOL for
653 temporary allocation. */
655 ensure_auth_subdir(const char *auth_dir,
660 const char *subdir_full_path;
661 svn_node_kind_t kind;
663 subdir_full_path = svn_dirent_join(auth_dir, subdir, pool);
664 err = svn_io_check_path(subdir_full_path, &kind, pool);
665 if (err || kind == svn_node_none)
667 svn_error_clear(err);
668 svn_error_clear(svn_io_dir_make(subdir_full_path, APR_OS_DEFAULT, pool));
672 /* Helper for svn_config_ensure: see if ~/.subversion/auth/ and its
673 subdirs exist, try to create them, but don't throw errors on
674 failure. PATH is assumed to be a path to the user's private config
677 ensure_auth_dirs(const char *path,
680 svn_node_kind_t kind;
681 const char *auth_dir;
684 /* Ensure ~/.subversion/auth/ */
685 auth_dir = svn_dirent_join(path, SVN_CONFIG__AUTH_SUBDIR, pool);
686 err = svn_io_check_path(auth_dir, &kind, pool);
687 if (err || kind == svn_node_none)
689 svn_error_clear(err);
690 /* 'chmod 700' permissions: */
691 err = svn_io_dir_make(auth_dir,
692 (APR_UREAD | APR_UWRITE | APR_UEXECUTE),
696 /* Don't try making subdirs if we can't make the top-level dir. */
697 svn_error_clear(err);
702 /* If a provider exists that wants to store credentials in
703 ~/.subversion, a subdirectory for the cred_kind must exist. */
704 ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SIMPLE, pool);
705 ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_USERNAME, pool);
706 ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SSL_SERVER_TRUST, pool);
707 ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, pool);
712 svn_config_ensure(const char *config_dir, apr_pool_t *pool)
715 svn_node_kind_t kind;
718 /* Ensure that the user-specific config directory exists. */
719 SVN_ERR(svn_config_get_user_config_path(&path, config_dir, NULL, pool));
724 err = svn_io_check_resolved_path(path, &kind, pool);
727 /* Don't throw an error, but don't continue. */
728 svn_error_clear(err);
732 if (kind == svn_node_none)
734 err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
737 /* Don't throw an error, but don't continue. */
738 svn_error_clear(err);
742 else if (kind == svn_node_file)
744 /* Somebody put a file where the config directory should be.
745 Wacky. Let's bail. */
749 /* Else, there's a configuration directory. */
751 /* If we get errors trying to do things below, just stop and return
752 success. There's no _need_ to init a config directory if
753 something's preventing it. */
755 /** If non-existent, try to create a number of auth/ subdirectories. */
756 ensure_auth_dirs(path, pool);
758 /** Ensure that the `README.txt' file exists. **/
759 SVN_ERR(svn_config_get_user_config_path
760 (&path, config_dir, SVN_CONFIG__USR_README_FILE, pool));
762 if (! path) /* highly unlikely, since a previous call succeeded */
765 err = svn_io_check_path(path, &kind, pool);
768 svn_error_clear(err);
772 if (kind == svn_node_none)
775 const char *contents =
776 "This directory holds run-time configuration information for Subversion" NL
777 "clients. The configuration files all share the same syntax, but you" NL
778 "should examine a particular file to learn what configuration" NL
779 "directives are valid for that file." NL
781 "The syntax is standard INI format:" NL
783 " - Empty lines, and lines starting with '#', are ignored." NL
784 " The first significant line in a file must be a section header." NL
786 " - A section starts with a section header, which must start in" NL
787 " the first column:" NL
791 " - An option, which must always appear within a section, is a pair" NL
792 " (name, value). There are two valid forms for defining an" NL
793 " option, both of which must start in the first column:" NL
798 " Whitespace around the separator (:, =) is optional." NL
800 " - Section and option names are case-insensitive, but case is" NL
803 " - An option's value may be broken into several lines. The value" NL
804 " continuation lines must start with at least one whitespace." NL
805 " Trailing whitespace in the previous line, the newline character" NL
806 " and the leading whitespace in the continuation line is compressed" NL
807 " into a single space character." NL
809 " - All leading and trailing whitespace around a value is trimmed," NL
810 " but the whitespace within a value is preserved, with the" NL
811 " exception of whitespace around line continuations, as" NL
812 " described above." NL
814 " - When a value is a boolean, any of the following strings are" NL
815 " recognised as truth values (case does not matter):" NL
822 " - When a value is a list, it is comma-separated. Again, the" NL
823 " whitespace around each element of the list is trimmed." NL
825 " - Option values may be expanded within a value by enclosing the" NL
826 " option name in parentheses, preceded by a percent sign and" NL
827 " followed by an 's':" NL
831 " The expansion is performed recursively and on demand, during" NL
832 " svn_option_get. The name is first searched for in the same" NL
833 " section, then in the special [DEFAULT] section. If the name" NL
834 " is not found, the whole '%(name)s' placeholder is left" NL
837 " Any modifications to the configuration data invalidate all" NL
838 " previously expanded values, so that the next svn_option_get" NL
839 " will take the modifications into account." NL
841 "The syntax of the configuration files is a subset of the one used by" NL
842 "Python's ConfigParser module; see" NL
844 " http://www.python.org/doc/current/lib/module-ConfigParser.html" NL
846 "Configuration data in the Windows registry" NL
847 "==========================================" NL
849 "On Windows, configuration data may also be stored in the registry. The" NL
850 "functions svn_config_read and svn_config_merge will read from the" NL
851 "registry when passed file names of the form:" NL
853 " REGISTRY:<hive>/path/to/config-key" NL
855 "The REGISTRY: prefix must be in upper case. The <hive> part must be" NL
858 " HKLM for HKEY_LOCAL_MACHINE" NL
859 " HKCU for HKEY_CURRENT_USER" NL
861 "The values in config-key represent the options in the [DEFAULT] section."NL
862 "The keys below config-key represent other sections, and their values" NL
863 "represent the options. Only values of type REG_SZ whose name doesn't" NL
864 "start with a '#' will be used; other values, as well as the keys'" NL
865 "default values, will be ignored." NL
871 "Typically, Subversion uses two config directories, one for site-wide" NL
875 " /etc/subversion/servers" NL
876 " /etc/subversion/config" NL
877 " /etc/subversion/hairstyles" NL
879 " %ALLUSERSPROFILE%\\Application Data\\Subversion\\servers" NL
880 " %ALLUSERSPROFILE%\\Application Data\\Subversion\\config" NL
881 " %ALLUSERSPROFILE%\\Application Data\\Subversion\\hairstyles" NL
882 " REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Servers" NL
883 " REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Config" NL
884 " REGISTRY:HKLM\\Software\\Tigris.org\\Subversion\\Hairstyles" NL
886 "and one for per-user configuration:" NL
889 " ~/.subversion/servers" NL
890 " ~/.subversion/config" NL
891 " ~/.subversion/hairstyles" NL
893 " %APPDATA%\\Subversion\\servers" NL
894 " %APPDATA%\\Subversion\\config" NL
895 " %APPDATA%\\Subversion\\hairstyles" NL
896 " REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Servers" NL
897 " REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Config" NL
898 " REGISTRY:HKCU\\Software\\Tigris.org\\Subversion\\Hairstyles" NL
901 err = svn_io_file_open(&f, path,
902 (APR_WRITE | APR_CREATE | APR_EXCL),
908 SVN_ERR(svn_io_file_write_full(f, contents,
909 strlen(contents), NULL, pool));
910 SVN_ERR(svn_io_file_close(f, pool));
913 svn_error_clear(err);
916 /** Ensure that the `servers' file exists. **/
917 SVN_ERR(svn_config_get_user_config_path
918 (&path, config_dir, SVN_CONFIG_CATEGORY_SERVERS, pool));
920 if (! path) /* highly unlikely, since a previous call succeeded */
923 err = svn_io_check_path(path, &kind, pool);
926 svn_error_clear(err);
930 if (kind == svn_node_none)
933 const char *contents =
934 "### This file specifies server-specific parameters," NL
935 "### including HTTP proxy information, HTTP timeout settings," NL
936 "### and authentication settings." NL
938 "### The currently defined server options are:" NL
939 "### http-proxy-host Proxy host for HTTP connection" NL
940 "### http-proxy-port Port number of proxy host service" NL
941 "### http-proxy-username Username for auth to proxy service"NL
942 "### http-proxy-password Password for auth to proxy service"NL
943 "### http-proxy-exceptions List of sites that do not use proxy"
945 "### http-timeout Timeout for HTTP requests in seconds"
947 "### http-compression Whether to compress HTTP requests" NL
948 "### http-max-connections Maximum number of parallel server" NL
949 "### connections to use for any given" NL
950 "### HTTP operation." NL
951 "### http-chunked-requests Whether to use chunked transfer" NL
952 "### encoding for HTTP requests body." NL
953 "### neon-debug-mask Debug mask for Neon HTTP library" NL
954 "### ssl-authority-files List of files, each of a trusted CA"
956 "### ssl-trust-default-ca Trust the system 'default' CAs" NL
957 "### ssl-client-cert-file PKCS#12 format client certificate file"
959 "### ssl-client-cert-password Client Key password, if needed." NL
960 "### ssl-pkcs11-provider Name of PKCS#11 provider to use." NL
961 "### http-library Which library to use for http/https"
963 "### connections." NL
964 "### http-bulk-updates Whether to request bulk update" NL
965 "### responses or to fetch each file" NL
966 "### in an individual request. " NL
967 "### store-passwords Specifies whether passwords used" NL
968 "### to authenticate against a" NL
969 "### Subversion server may be cached" NL
970 "### to disk in any way." NL
971 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
972 "### store-plaintext-passwords Specifies whether passwords may" NL
973 "### be cached on disk unencrypted." NL
975 "### store-ssl-client-cert-pp Specifies whether passphrase used" NL
976 "### to authenticate against a client" NL
977 "### certificate may be cached to disk" NL
979 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
980 "### store-ssl-client-cert-pp-plaintext" NL
981 "### Specifies whether client cert" NL
982 "### passphrases may be cached on disk" NL
983 "### unencrypted (i.e., as plaintext)." NL
985 "### store-auth-creds Specifies whether any auth info" NL
986 "### (passwords, server certs, etc.)" NL
987 "### may be cached to disk." NL
988 "### username Specifies the default username." NL
990 "### Set store-passwords to 'no' to avoid storing passwords on disk" NL
991 "### in any way, including in password stores. It defaults to" NL
992 "### 'yes', but Subversion will never save your password to disk in" NL
993 "### plaintext unless explicitly configured to do so." NL
994 "### Note that this option only prevents saving of *new* passwords;" NL
995 "### it doesn't invalidate existing passwords. (To do that, remove" NL
996 "### the cache files by hand as described in the Subversion book.)" NL
998 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
999 "### Set store-plaintext-passwords to 'no' to avoid storing" NL
1000 "### passwords in unencrypted form in the auth/ area of your config" NL
1001 "### directory. Set it to 'yes' to allow Subversion to store" NL
1002 "### unencrypted passwords in the auth/ area. The default is" NL
1003 "### 'ask', which means that Subversion will ask you before" NL
1004 "### saving a password to disk in unencrypted form. Note that" NL
1005 "### this option has no effect if either 'store-passwords' or " NL
1006 "### 'store-auth-creds' is set to 'no'." NL
1009 "### Set store-ssl-client-cert-pp to 'no' to avoid storing ssl" NL
1010 "### client certificate passphrases in the auth/ area of your" NL
1011 "### config directory. It defaults to 'yes', but Subversion will" NL
1012 "### never save your passphrase to disk in plaintext unless" NL
1013 "### explicitly configured to do so." NL
1015 "### Note store-ssl-client-cert-pp only prevents the saving of *new*"NL
1016 "### passphrases; it doesn't invalidate existing passphrases. To do"NL
1017 "### that, remove the cache files by hand as described in the" NL
1018 "### Subversion book at http://svnbook.red-bean.com/nightly/en/\\" NL
1019 "### svn.serverconfig.netmodel.html\\" NL
1020 "### #svn.serverconfig.netmodel.credcache" NL
1022 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
1023 "### Set store-ssl-client-cert-pp-plaintext to 'no' to avoid storing"NL
1024 "### passphrases in unencrypted form in the auth/ area of your" NL
1025 "### config directory. Set it to 'yes' to allow Subversion to" NL
1026 "### store unencrypted passphrases in the auth/ area. The default" NL
1027 "### is 'ask', which means that Subversion will prompt before" NL
1028 "### saving a passphrase to disk in unencrypted form. Note that" NL
1029 "### this option has no effect if either 'store-auth-creds' or " NL
1030 "### 'store-ssl-client-cert-pp' is set to 'no'." NL
1033 "### Set store-auth-creds to 'no' to avoid storing any Subversion" NL
1034 "### credentials in the auth/ area of your config directory." NL
1035 "### Note that this includes SSL server certificates." NL
1036 "### It defaults to 'yes'. Note that this option only prevents" NL
1037 "### saving of *new* credentials; it doesn't invalidate existing" NL
1038 "### caches. (To do that, remove the cache files by hand.)" NL
1040 "### HTTP timeouts, if given, are specified in seconds. A timeout" NL
1041 "### of 0, i.e. zero, causes a builtin default to be used." NL
1043 "### Most users will not need to explicitly set the http-library" NL
1044 "### option, but valid values for the option include:" NL
1045 "### 'serf': Serf-based module (Subversion 1.5 - present)" NL
1046 "### 'neon': Neon-based module (Subversion 1.0 - 1.7)" NL
1047 "### Availability of these modules may depend on your specific" NL
1048 "### Subversion distribution." NL
1050 "### The commented-out examples below are intended only to" NL
1051 "### demonstrate how to use this file; any resemblance to actual" NL
1052 "### servers, living or dead, is entirely coincidental." NL
1054 "### In the 'groups' section, the URL of the repository you're" NL
1055 "### trying to access is matched against the patterns on the right." NL
1056 "### If a match is found, the server options are taken from the" NL
1057 "### section with the corresponding name on the left." NL
1060 "# group1 = *.collab.net" NL
1061 "# othergroup = repository.blarggitywhoomph.com" NL
1062 "# thirdgroup = *.example.com" NL
1064 "### Information for the first group:" NL
1066 "# http-proxy-host = proxy1.some-domain-name.com" NL
1067 "# http-proxy-port = 80" NL
1068 "# http-proxy-username = blah" NL
1069 "# http-proxy-password = doubleblah" NL
1070 "# http-timeout = 60" NL
1071 "# neon-debug-mask = 130" NL
1072 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
1073 "# store-plaintext-passwords = no" NL
1075 "# username = harry" NL
1077 "### Information for the second group:" NL
1079 "# http-proxy-host = proxy2.some-domain-name.com" NL
1080 "# http-proxy-port = 9000" NL
1081 "# No username and password for the proxy, so use the defaults below."
1084 "### You can set default parameters in the 'global' section." NL
1085 "### These parameters apply if no corresponding parameter is set in" NL
1086 "### a specifically matched group as shown above. Thus, if you go" NL
1087 "### through the same proxy server to reach every site on the" NL
1088 "### Internet, you probably just want to put that server's" NL
1089 "### information in the 'global' section and not bother with" NL
1090 "### 'groups' or any other sections." NL
1092 "### Most people might want to configure password caching" NL
1093 "### parameters here, but you can also configure them per server" NL
1094 "### group (per-group settings override global settings)." NL
1096 "### If you go through a proxy for all but a few sites, you can" NL
1097 "### list those exceptions under 'http-proxy-exceptions'. This only"NL
1098 "### overrides defaults, not explicitly matched server names." NL
1100 "### 'ssl-authority-files' is a semicolon-delimited list of files," NL
1101 "### each pointing to a PEM-encoded Certificate Authority (CA) " NL
1102 "### SSL certificate. See details above for overriding security " NL
1103 "### due to SSL." NL
1105 "# http-proxy-exceptions = *.exception.com, www.internal-site.org" NL
1106 "# http-proxy-host = defaultproxy.whatever.com" NL
1107 "# http-proxy-port = 7000" NL
1108 "# http-proxy-username = defaultusername" NL
1109 "# http-proxy-password = defaultpassword" NL
1110 "# http-compression = no" NL
1111 "# No http-timeout, so just use the builtin default." NL
1112 "# No neon-debug-mask, so neon debugging is disabled." NL
1113 "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem" NL
1115 "# Password / passphrase caching parameters:" NL
1116 "# store-passwords = no" NL
1117 "# store-ssl-client-cert-pp = no" NL
1118 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
1119 "# store-plaintext-passwords = no" NL
1120 "# store-ssl-client-cert-pp-plaintext = no" NL
1124 err = svn_io_file_open(&f, path,
1125 (APR_WRITE | APR_CREATE | APR_EXCL),
1131 SVN_ERR(svn_io_file_write_full(f, contents,
1132 strlen(contents), NULL, pool));
1133 SVN_ERR(svn_io_file_close(f, pool));
1136 svn_error_clear(err);
1139 /** Ensure that the `config' file exists. **/
1140 SVN_ERR(svn_config_get_user_config_path
1141 (&path, config_dir, SVN_CONFIG_CATEGORY_CONFIG, pool));
1143 if (! path) /* highly unlikely, since a previous call succeeded */
1144 return SVN_NO_ERROR;
1146 err = svn_io_check_path(path, &kind, pool);
1149 svn_error_clear(err);
1150 return SVN_NO_ERROR;
1153 if (kind == svn_node_none)
1156 const char *contents =
1157 "### This file configures various client-side behaviors." NL
1159 "### The commented-out examples below are intended to demonstrate" NL
1160 "### how to use this file." NL
1162 "### Section for authentication and authorization customizations." NL
1164 "### Set password stores used by Subversion. They should be" NL
1165 "### delimited by spaces or commas. The order of values determines" NL
1166 "### the order in which password stores are used." NL
1167 "### Valid password stores:" NL
1168 "### gnome-keyring (Unix-like systems)" NL
1169 "### kwallet (Unix-like systems)" NL
1170 "### gpg-agent (Unix-like systems)" NL
1171 "### keychain (Mac OS X)" NL
1172 "### windows-cryptoapi (Windows)" NL
1173 #ifdef SVN_HAVE_KEYCHAIN_SERVICES
1174 "# password-stores = keychain" NL
1175 #elif defined(WIN32) && !defined(__MINGW32__)
1176 "# password-stores = windows-cryptoapi" NL
1178 "# password-stores = gpg-agent,gnome-keyring,kwallet" NL
1180 "### To disable all password stores, use an empty list:" NL
1181 "# password-stores =" NL
1182 #ifdef SVN_HAVE_KWALLET
1184 "### Set KWallet wallet used by Subversion. If empty or unset," NL
1185 "### then the default network wallet will be used." NL
1186 "# kwallet-wallet =" NL
1188 "### Include PID (Process ID) in Subversion application name when" NL
1189 "### using KWallet. It defaults to 'no'." NL
1190 "# kwallet-svn-application-name-with-pid = yes" NL
1193 "### Set ssl-client-cert-file-prompt to 'yes' to cause the client" NL
1194 "### to prompt for a path to a client cert file when the server" NL
1195 "### requests a client cert but no client cert file is found in the" NL
1196 "### expected place (see the 'ssl-client-cert-file' option in the" NL
1197 "### 'servers' configuration file). Defaults to 'no'." NL
1198 "# ssl-client-cert-file-prompt = no" NL
1200 "### The rest of the [auth] section in this file has been deprecated."
1202 "### Both 'store-passwords' and 'store-auth-creds' can now be" NL
1203 "### specified in the 'servers' file in your config directory" NL
1204 "### and are documented there. Anything specified in this section " NL
1205 "### is overridden by settings specified in the 'servers' file." NL
1206 "# store-passwords = no" NL
1207 "# store-auth-creds = no" NL
1209 "### Section for configuring external helper applications." NL
1211 "### Set editor-cmd to the command used to invoke your text editor." NL
1212 "### This will override the environment variables that Subversion" NL
1213 "### examines by default to find this information ($EDITOR, " NL
1215 "# editor-cmd = editor (vi, emacs, notepad, etc.)" NL
1216 "### Set diff-cmd to the absolute path of your 'diff' program." NL
1217 "### This will override the compile-time default, which is to use" NL
1218 "### Subversion's internal diff implementation." NL
1219 "# diff-cmd = diff_program (diff, gdiff, etc.)" NL
1220 "### Diff-extensions are arguments passed to an external diff" NL
1221 "### program or to Subversion's internal diff implementation." NL
1222 "### Set diff-extensions to override the default arguments ('-u')." NL
1223 "# diff-extensions = -u -p" NL
1224 "### Set diff3-cmd to the absolute path of your 'diff3' program." NL
1225 "### This will override the compile-time default, which is to use" NL
1226 "### Subversion's internal diff3 implementation." NL
1227 "# diff3-cmd = diff3_program (diff3, gdiff3, etc.)" NL
1228 "### Set diff3-has-program-arg to 'yes' if your 'diff3' program" NL
1229 "### accepts the '--diff-program' option." NL
1230 "# diff3-has-program-arg = [yes | no]" NL
1231 "### Set merge-tool-cmd to the command used to invoke your external" NL
1232 "### merging tool of choice. Subversion will pass 5 arguments to" NL
1233 "### the specified command: base theirs mine merged wcfile" NL
1234 "# merge-tool-cmd = merge_command" NL
1236 "### Section for configuring tunnel agents." NL
1238 "### Configure svn protocol tunnel schemes here. By default, only" NL
1239 "### the 'ssh' scheme is defined. You can define other schemes to" NL
1240 "### be used with 'svn+scheme://hostname/path' URLs. A scheme" NL
1241 "### definition is simply a command, optionally prefixed by an" NL
1242 "### environment variable name which can override the command if it" NL
1243 "### is defined. The command (or environment variable) may contain" NL
1244 "### arguments, using standard shell quoting for arguments with" NL
1245 "### spaces. The command will be invoked as:" NL
1246 "### <command> <hostname> svnserve -t" NL
1247 "### (If the URL includes a username, then the hostname will be" NL
1248 "### passed to the tunnel agent as <user>@<hostname>.) If the" NL
1249 "### built-in ssh scheme were not predefined, it could be defined" NL
1251 "# ssh = $SVN_SSH ssh -q" NL
1252 "### If you wanted to define a new 'rsh' scheme, to be used with" NL
1253 "### 'svn+rsh:' URLs, you could do so as follows:" NL
1255 "### Or, if you wanted to specify a full path and arguments:" NL
1256 "# rsh = /path/to/rsh -l myusername" NL
1257 "### On Windows, if you are specifying a full path to a command," NL
1258 "### use a forward slash (/) or a paired backslash (\\\\) as the" NL
1259 "### path separator. A single backslash will be treated as an" NL
1260 "### escape for the following character." NL
1262 "### Section for configuring miscellaneous Subversion options." NL
1264 "### Set global-ignores to a set of whitespace-delimited globs" NL
1265 "### which Subversion will ignore in its 'status' output, and" NL
1266 "### while importing or adding files and directories." NL
1267 "### '*' matches leading dots, e.g. '*.rej' matches '.foo.rej'." NL
1268 "# global-ignores = " SVN_CONFIG__DEFAULT_GLOBAL_IGNORES_LINE_1 NL
1269 "# " SVN_CONFIG__DEFAULT_GLOBAL_IGNORES_LINE_2 NL
1270 "### Set log-encoding to the default encoding for log messages" NL
1271 "# log-encoding = latin1" NL
1272 "### Set use-commit-times to make checkout/update/switch/revert" NL
1273 "### put last-committed timestamps on every file touched." NL
1274 "# use-commit-times = yes" NL
1275 "### Set no-unlock to prevent 'svn commit' from automatically" NL
1276 "### releasing locks on files." NL
1277 "# no-unlock = yes" NL
1278 "### Set mime-types-file to a MIME type registry file, used to" NL
1279 "### provide hints to Subversion's MIME type auto-detection" NL
1281 "# mime-types-file = /path/to/mime.types" NL
1282 "### Set preserved-conflict-file-exts to a whitespace-delimited" NL
1283 "### list of patterns matching file extensions which should be" NL
1284 "### preserved in generated conflict file names. By default," NL
1285 "### conflict files use custom extensions." NL
1286 "# preserved-conflict-file-exts = doc ppt xls od?" NL
1287 "### Set enable-auto-props to 'yes' to enable automatic properties" NL
1288 "### for 'svn add' and 'svn import', it defaults to 'no'." NL
1289 "### Automatic properties are defined in the section 'auto-props'." NL
1290 "# enable-auto-props = yes" NL
1291 #ifdef SVN_HAVE_LIBMAGIC
1292 "### Set enable-magic-file to 'no' to disable magic file detection" NL
1293 "### of the file type when automatically setting svn:mime-type. It" NL
1294 "### defaults to 'yes' if magic file support is possible." NL
1295 "# enable-magic-file = yes" NL
1297 "### Set interactive-conflicts to 'no' to disable interactive" NL
1298 "### conflict resolution prompting. It defaults to 'yes'." NL
1299 "# interactive-conflicts = no" NL
1300 "### Set memory-cache-size to define the size of the memory cache" NL
1301 "### used by the client when accessing a FSFS repository via" NL
1302 "### ra_local (the file:// scheme). The value represents the number" NL
1303 "### of MB used by the cache." NL
1304 "# memory-cache-size = 16" NL
1305 "### Set diff-ignore-content-type to 'yes' to cause 'svn diff' to" NL
1306 "### attempt to show differences of all modified files regardless" NL
1307 "### of their MIME content type. By default, Subversion will only" NL
1308 "### attempt to show differences for files believed to have human-" NL
1309 "### readable (non-binary) content. This option is especially" NL
1310 "### useful when Subversion is configured (via the 'diff-cmd'" NL
1311 "### option) to employ an external differencing tool which is able" NL
1312 "### to show meaningful differences for binary file formats. [New" NL
1314 "# diff-ignore-content-type = no" NL
1316 "### Section for configuring automatic properties." NL
1318 "### The format of the entries is:" NL
1319 "### file-name-pattern = propname[=value][;propname[=value]...]" NL
1320 "### The file-name-pattern can contain wildcards (such as '*' and" NL
1321 "### '?'). All entries which match (case-insensitively) will be" NL
1322 "### applied to the file. Note that auto-props functionality" NL
1323 "### must be enabled, which is typically done by setting the" NL
1324 "### 'enable-auto-props' option." NL
1325 "# *.c = svn:eol-style=native" NL
1326 "# *.cpp = svn:eol-style=native" NL
1327 "# *.h = svn:keywords=Author Date Id Rev URL;svn:eol-style=native" NL
1328 "# *.dsp = svn:eol-style=CRLF" NL
1329 "# *.dsw = svn:eol-style=CRLF" NL
1330 "# *.sh = svn:eol-style=native;svn:executable" NL
1331 "# *.txt = svn:eol-style=native;svn:keywords=Author Date Id Rev URL;"NL
1332 "# *.png = svn:mime-type=image/png" NL
1333 "# *.jpg = svn:mime-type=image/jpeg" NL
1334 "# Makefile = svn:eol-style=native" NL
1336 "### Section for configuring working copies." NL
1338 "### Set to a list of the names of specific clients that should use" NL
1339 "### exclusive SQLite locking of working copies. This increases the"NL
1340 "### performance of the client but prevents concurrent access by" NL
1341 "### other clients. Third-party clients may also support this" NL
1343 "### Possible values:" NL
1344 "### svn (the command line client)" NL
1345 "# exclusive-locking-clients =" NL
1346 "### Set to true to enable exclusive SQLite locking of working" NL
1347 "### copies by all clients using the 1.8 APIs. Enabling this may" NL
1348 "### cause some clients to fail to work properly. This does not have"NL
1349 "### to be set for exclusive-locking-clients to work." NL
1350 "# exclusive-locking = false" NL
1351 "### Set the SQLite busy timeout in milliseconds: the maximum time" NL
1352 "### the client waits to get access to the SQLite database before" NL
1353 "### returning an error. The default is 10000, i.e. 10 seconds." NL
1354 "### Longer values may be useful when exclusive locking is enabled." NL
1355 "# busy-timeout = 10000" NL
1358 err = svn_io_file_open(&f, path,
1359 (APR_WRITE | APR_CREATE | APR_EXCL),
1365 SVN_ERR(svn_io_file_write_full(f, contents,
1366 strlen(contents), NULL, pool));
1367 SVN_ERR(svn_io_file_close(f, pool));
1370 svn_error_clear(err);
1373 return SVN_NO_ERROR;
1377 svn_config_get_user_config_path(const char **path,
1378 const char *config_dir,
1384 /* Note that even if fname is null, svn_dirent_join_many will DTRT. */
1388 *path = svn_dirent_join_many(pool, config_dir, fname, SVN_VA_NULL);
1389 return SVN_NO_ERROR;
1395 SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool, pool));
1398 return SVN_NO_ERROR;
1400 *path = svn_dirent_join_many(pool, folder,
1401 SVN_CONFIG__SUBDIRECTORY, fname, SVN_VA_NULL);
1404 #elif defined(__HAIKU__)
1406 char folder[B_PATH_NAME_LENGTH];
1408 status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false,
1409 folder, sizeof(folder));
1411 return SVN_NO_ERROR;
1413 *path = svn_dirent_join_many(pool, folder,
1414 SVN_CONFIG__USR_DIRECTORY, fname,
1417 #else /* ! WIN32 && !__HAIKU__ */
1420 const char *homedir = svn_user_get_homedir(pool);
1422 return SVN_NO_ERROR;
1423 *path = svn_dirent_join_many(pool,
1424 svn_dirent_canonicalize(homedir, pool),
1425 SVN_CONFIG__USR_DIRECTORY, fname, SVN_VA_NULL);
1429 return SVN_NO_ERROR;