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