1 /*------------------------------------------------------------------------- 2 * 3 * initdb --- initialize a PostgreSQL installation 4 * 5 * initdb creates (initializes) a PostgreSQL database cluster (site, 6 * instance, installation, whatever). A database cluster is a 7 * collection of PostgreSQL databases all managed by the same server. 8 * NAMESPACE_BEGIN(CryptoPP)9 * To create the database cluster, we create the directory that contains 10 * all its data, create the files that hold the global tables, create 11 * a few other control files for it, and create three databases: the 12 * template databases "template0" and "template1", and a default user 13 * database "postgres". 14 * 15 * The template databases are ordinary PostgreSQL databases. template0 16 * is never supposed to change after initdb, whereas template1 can be 17 * changed to add site-local standard data. Either one can be copied 18 * to produce a new database. 19 * 20 * For largely-historical reasons, the template1 database is the one built 21 * by the basic bootstrap process. After it is complete, template0 and 22 * the default database, postgres, are made just by copying template1. 23 * 24 * To create template1, we run the postgres (backend) program in bootstrap 25 * mode and feed it data from the postgres.bki library file. After this 26 * initial bootstrap phase, some additional stuff is created by normal 27 * SQL commands fed to a standalone backend. Some of those commands are 28 * just embedded into this program (yeah, it's ugly), but larger chunks 29 * are taken from script files. 30 * 31 * 32 * Note: 33 * The program has some memory leakage - it isn't worth cleaning it up. 34 * 35 * This is a C implementation of the previous shell script for setting up a 36 * PostgreSQL cluster location, and should be highly compatible with it. 37 * author of C translation: Andrew Dunstan mailto:andrew@dunslane.net 38 * 39 * This code is released under the terms of the PostgreSQL License. 40 * 41 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group 42 * Portions Copyright (c) 1994, Regents of the University of California 43 * 44 * src/bin/initdb/initdb.c 45 * 46 *------------------------------------------------------------------------- 47 */ 48 49 #include "postgres_fe.h" 50 51 #include <dirent.h> 52 #include <fcntl.h> 53 #include <sys/stat.h> 54 #include <unistd.h> 55 #include <signal.h> 56 #include <time.h> 57 58 #ifdef HAVE_SHM_OPEN 59 #include "sys/mman.h" 60 #endif 61 62 #include "access/xlog_internal.h" 63 #include "catalog/pg_authid_d.h" 64 #include "catalog/pg_class_d.h" /* pgrminclude ignore */ 65 #include "catalog/pg_collation_d.h" 66 #include "common/file_perm.h" 67 #include "common/file_utils.h" 68 #include "common/logging.h" 69 #include "common/restricted_token.h" 70 #include "common/username.h" 71 #include "fe_utils/string_utils.h" 72 #include "getaddrinfo.h" 73 #include "getopt_long.h" 74 #include "mb/pg_wchar.h" 75 #include "miscadmin.h" 76 77 78 /* Ideally this would be in a .h file, but it hardly seems worth the trouble */ 79 extern const char *select_default_timezone(const char *share_path); 80 81 static const char *const auth_methods_host[] = { 82 "trust", "reject", "scram-sha-256", "md5", "password", "ident", "radius", 83 #ifdef ENABLE_GSS 84 "gss", 85 #endif 86 #ifdef ENABLE_SSPI 87 "sspi", 88 #endif 89 #ifdef USE_PAM 90 "pam", "pam ", 91 #endif 92 #ifdef USE_BSD_AUTH 93 "bsd", 94 #endif 95 #ifdef USE_LDAP 96 "ldap", 97 #endif 98 #ifdef USE_SSL 99 "cert", 100 #endif 101 NULL 102 }; 103 static const char *const auth_methods_local[] = { 104 "trust", "reject", "scram-sha-256", "md5", "password", "peer", "radius", 105 #ifdef USE_PAM 106 "pam", "pam ", 107 #endif 108 #ifdef USE_BSD_AUTH 109 "bsd", 110 #endif 111 #ifdef USE_LDAP 112 "ldap", 113 #endif 114 NULL 115 }; 116 117 /* 118 * these values are passed in by makefile defines 119 */ 120 static char *share_path = NULL; 121 122 /* values to be obtained from arguments */ 123 static char *pg_data = NULL; 124 static char *encoding = NULL; 125 static char *locale = NULL; 126 static char *lc_collate = NULL; 127 static char *lc_ctype = NULL; 128 static char *lc_monetary = NULL; 129 static char *lc_numeric = NULL; 130 static char *lc_time = NULL; 131 static char *lc_messages = NULL; 132 static const char *default_text_search_config = NULL; 133 static char *username = NULL; 134 static bool pwprompt = false; 135 static char *pwfilename = NULL; 136 static char *superuser_password = NULL; 137 static const char *authmethodhost = NULL; 138 static const char *authmethodlocal = NULL; 139 static bool debug = false; 140 static bool noclean = false; 141 static bool do_sync = true; 142 static bool sync_only = false; 143 static bool show_setting = false; 144 static bool data_checksums = false; 145 static char *xlog_dir = NULL; 146 static char *str_wal_segment_size_mb = NULL; 147 static int wal_segment_size_mb; 148 149 150 /* internal vars */ 151 static const char *progname; 152 static int encodingid; 153 static char *bki_file; 154 static char *desc_file; 155 static char *shdesc_file; 156 static char *hba_file; 157 static char *ident_file; 158 static char *conf_file; 159 static char *dictionary_file; 160 static char *info_schema_file; 161 static char *features_file; 162 static char *system_views_file; 163 static bool success = false; 164 static bool made_new_pgdata = false; 165 static bool found_existing_pgdata = false; 166 static bool made_new_xlogdir = false; 167 static bool found_existing_xlogdir = false; 168 static char infoversion[100]; 169 static bool caught_signal = false; 170 static bool output_failed = false; 171 static int output_errno = 0; 172 static char *pgdata_native; 173 174 /* defaults */ 175 static int n_connections = 10; 176 static int n_buffers = 50; 177 static const char *dynamic_shared_memory_type = NULL; 178 static const char *default_timezone = NULL; 179 180 /* 181 * Warning messages for authentication methods 182 */ 183 #define AUTHTRUST_WARNING \ 184 "# CAUTION: Configuring the system for local \"trust\" authentication\n" \ 185 "# allows any local user to connect as any PostgreSQL user, including\n" \ 186 "# the database superuser. If you do not trust all your local users,\n" \ 187 "# use another authentication method.\n" 188 static bool authwarning = false; 189 190 /* 191 * Centralized knowledge of switches to pass to backend 192 * 193 * Note: we run the backend with -F (fsync disabled) and then do a single 194 * pass of fsync'ing at the end. This is faster than fsync'ing each step. 195 * 196 * Note: in the shell-script version, we also passed PGDATA as a -D switch, 197 * but here it is more convenient to pass it as an environment variable 198 * (no quoting to worry about). 199 */ 200 static const char *boot_options = "-F"; 201 static const char *backend_options = "--single -F -O -j -c search_path=pg_catalog -c exit_on_error=true"; 202 203 static const char *const subdirs[] = { 204 "global", 205 "pg_wal/archive_status", 206 "pg_commit_ts", 207 "pg_dynshmem", 208 "pg_notify", 209 "pg_serial", 210 "pg_snapshots", 211 "pg_subtrans", 212 "pg_twophase", 213 "pg_multixact", 214 "pg_multixact/members", 215 "pg_multixact/offsets", 216 "base", 217 "base/1", 218 "pg_replslot", 219 "pg_tblspc", 220 "pg_stat", 221 "pg_stat_tmp", 222 "pg_xact", 223 "pg_logical", 224 "pg_logical/snapshots", 225 "pg_logical/mappings" 226 }; 227 228 229 /* path to 'initdb' binary directory */ 230 static char bin_path[MAXPGPATH]; 231 static char backend_exec[MAXPGPATH]; 232 233 static char **replace_token(char **lines, 234 const char *token, const char *replacement); 235 236 #ifndef HAVE_UNIX_SOCKETS 237 static char **filter_lines_with_token(char **lines, const char *token); 238 #endif 239 static char **readfile(const char *path); 240 static void writefile(char *path, char **lines); 241 static FILE *popen_check(const char *command, const char *mode); 242 static char *get_id(void); 243 static int get_encoding_id(const char *encoding_name); 244 static void set_input(char **dest, const char *filename); 245 static void check_input(char *path); 246 static void write_version_file(const char *extrapath); 247 static void set_null_conf(void); 248 static void test_config_settings(void); 249 static void setup_config(void); 250 static void bootstrap_template1(void); 251 static void setup_auth(FILE *cmdfd); 252 static void get_su_pwd(void); 253 static void setup_depend(FILE *cmdfd); 254 static void setup_sysviews(FILE *cmdfd); 255 static void setup_description(FILE *cmdfd); 256 static void setup_collation(FILE *cmdfd); 257 static void setup_dictionary(FILE *cmdfd); 258 static void setup_privileges(FILE *cmdfd); 259 static void set_info_version(void); 260 static void setup_schema(FILE *cmdfd); 261 static void load_plpgsql(FILE *cmdfd); 262 static void vacuum_db(FILE *cmdfd); 263 static void make_template0(FILE *cmdfd); 264 static void make_postgres(FILE *cmdfd); 265 static void trapsig(int signum); 266 static void check_ok(void); 267 static char *escape_quotes(const char *src); 268 static char *escape_quotes_bki(const char *src); 269 static int locale_date_order(const char *locale); 270 static void check_locale_name(int category, const char *locale, 271 char **canonname); 272 static bool check_locale_encoding(const char *locale, int encoding); 273 static void setlocales(void); 274 static void usage(const char *progname); 275 void setup_pgdata(void); 276 void setup_bin_paths(const char *argv0); 277 void setup_data_file_paths(void); 278 void setup_locale_encoding(void); 279 void setup_signals(void); 280 void setup_text_search(void); 281 void create_data_directory(void); 282 void create_xlog_or_symlink(void); 283 void warn_on_mount_point(int error); 284 void initialize_data_directory(void); 285 286 /* 287 * macros for running pipes to postgres 288 */ 289 #define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd 290 291 #define PG_CMD_OPEN \ 292 do { \ 293 cmdfd = popen_check(cmd, "w"); \ 294 if (cmdfd == NULL) \ 295 exit(1); /* message already printed by popen_check */ \ 296 } while (0) 297 298 #define PG_CMD_CLOSE \ 299 do { \ 300 if (pclose_check(cmdfd)) \ 301 exit(1); /* message already printed by pclose_check */ \ 302 } while (0) 303 304 #define PG_CMD_PUTS(line) \ 305 do { \ 306 if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \ 307 output_failed = true, output_errno = errno; \ 308 } while (0) 309 310 #define PG_CMD_PRINTF1(fmt, arg1) \ 311 do { \ 312 if (fprintf(cmdfd, fmt, arg1) < 0 || fflush(cmdfd) < 0) \ 313 output_failed = true, output_errno = errno; \ 314 } while (0) 315 316 #define PG_CMD_PRINTF2(fmt, arg1, arg2) \ 317 do { \ 318 if (fprintf(cmdfd, fmt, arg1, arg2) < 0 || fflush(cmdfd) < 0) \ 319 output_failed = true, output_errno = errno; \ 320 } while (0) 321 322 #define PG_CMD_PRINTF3(fmt, arg1, arg2, arg3) \ 323 do { \ 324 if (fprintf(cmdfd, fmt, arg1, arg2, arg3) < 0 || fflush(cmdfd) < 0) \ 325 output_failed = true, output_errno = errno; \ 326 } while (0) 327 328 /* 329 * Escape single quotes and backslashes, suitably for insertions into 330 * configuration files or SQL E'' strings. 331 */ 332 static char * 333 escape_quotes(const char *src) 334 { 335 char *result = escape_single_quotes_ascii(src); 336 337 if (!result) 338 { 339 pg_log_error("out of memory"); 340 exit(1); 341 } 342 return result; 343 } 344 345 /* 346 * Escape a field value to be inserted into the BKI data. 347 * Here, we first run the value through escape_quotes (which 348 * will be inverted by the backend's scanstr() function) and 349 * then overlay special processing of double quotes, which 350 * bootscanner.l will only accept as data if converted to octal 351 * representation ("\042"). We always wrap the value in double 352 * quotes, even if that isn't strictly necessary. 353 */ 354 static char * 355 escape_quotes_bki(const char *src) 356 { 357 char *result; 358 char *data = escape_quotes(src); 359 char *resultp; 360 char *datap; 361 int nquotes = 0; 362 363 /* count double quotes in data */ 364 datap = data; 365 while ((datap = strchr(datap, '"')) != NULL) 366 { 367 nquotes++; 368 datap++; 369 } 370 371 result = (char *) pg_malloc(strlen(data) + 3 + nquotes * 3); 372 resultp = result; 373 *resultp++ = '"'; 374 for (datap = data; *datap; datap++) 375 { 376 if (*datap == '"') 377 { 378 strcpy(resultp, "\\042"); 379 resultp += 4; 380 } 381 else 382 *resultp++ = *datap; 383 } 384 *resultp++ = '"'; 385 *resultp = '\0'; 386 387 free(data); 388 return result; 389 } 390 391 /* 392 * make a copy of the array of lines, with token replaced by replacement 393 * the first time it occurs on each line. 394 * 395 * This does most of what sed was used for in the shell script, but 396 * doesn't need any regexp stuff. 397 */ 398 static char ** 399 replace_token(char **lines, const char *token, const char *replacement) 400 { 401 int numlines = 1; 402 int i; 403 char **result; 404 int toklen, 405 replen, 406 diff; 407 408 for (i = 0; lines[i]; i++) 409 numlines++; 410 411 result = (char **) pg_malloc(numlines * sizeof(char *)); 412 413 toklen = strlen(token); 414 replen = strlen(replacement); 415 diff = replen - toklen; 416 417 for (i = 0; i < numlines; i++) 418 { 419 char *where; 420 char *newline; 421 int pre; 422 423 /* just copy pointer if NULL or no change needed */ 424 if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL) 425 { 426 result[i] = lines[i]; 427 continue; 428 } 429 430 /* if we get here a change is needed - set up new line */ 431 432 newline = (char *) pg_malloc(strlen(lines[i]) + diff + 1); 433 434 pre = where - lines[i]; 435 436 memcpy(newline, lines[i], pre); 437 438 memcpy(newline + pre, replacement, replen); 439 440 strcpy(newline + pre + replen, lines[i] + pre + toklen); 441 442 result[i] = newline; 443 } 444 445 return result; 446 } 447 448 /* 449 * make a copy of lines without any that contain the token 450 * 451 * a sort of poor man's grep -v 452 */ 453 #ifndef HAVE_UNIX_SOCKETS 454 static char ** 455 filter_lines_with_token(char **lines, const char *token) 456 { 457 int numlines = 1; 458 int i, 459 src, 460 dst; 461 char **result; 462 463 for (i = 0; lines[i]; i++) 464 numlines++; 465 466 result = (char **) pg_malloc(numlines * sizeof(char *)); 467 468 for (src = 0, dst = 0; src < numlines; src++) 469 { 470 if (lines[src] == NULL || strstr(lines[src], token) == NULL) 471 result[dst++] = lines[src]; 472 } 473 474 return result; 475 } 476 #endif 477 478 /* 479 * get the lines from a text file 480 */ 481 static char ** 482 readfile(const char *path) 483 { 484 FILE *infile; 485 int maxlength = 1, 486 linelen = 0; 487 int nlines = 0; 488 int n; 489 char **result; 490 char *buffer; 491 int c; 492 493 if ((infile = fopen(path, "r")) == NULL) 494 { 495 pg_log_error("could not open file \"%s\" for reading: %m", path); 496 exit(1); 497 } 498 499 /* pass over the file twice - the first time to size the result */ 500 501 while ((c = fgetc(infile)) != EOF) 502 { 503 linelen++; 504 if (c == '\n') 505 { 506 nlines++; 507 if (linelen > maxlength) 508 maxlength = linelen; 509 linelen = 0; 510 } 511 } 512 513 /* handle last line without a terminating newline (yuck) */ 514 if (linelen) 515 nlines++; 516 if (linelen > maxlength) 517 maxlength = linelen; 518 519 /* set up the result and the line buffer */ 520 result = (char **) pg_malloc((nlines + 1) * sizeof(char *)); 521 buffer = (char *) pg_malloc(maxlength + 1); 522 523 /* now reprocess the file and store the lines */ 524 rewind(infile); 525 n = 0; 526 while (fgets(buffer, maxlength + 1, infile) != NULL && n < nlines) 527 result[n++] = pg_strdup(buffer); 528 529 fclose(infile); 530 free(buffer); 531 result[n] = NULL; 532 533 return result; 534 } 535 536 /* 537 * write an array of lines to a file 538 * 539 * This is only used to write text files. Use fopen "w" not PG_BINARY_W 540 * so that the resulting configuration files are nicely editable on Windows. 541 */ 542 static void 543 writefile(char *path, char **lines) 544 { 545 FILE *out_file; 546 char **line; 547 548 if ((out_file = fopen(path, "w")) == NULL) 549 { 550 pg_log_error("could not open file \"%s\" for writing: %m", path); 551 exit(1); 552 } 553 for (line = lines; *line != NULL; line++) 554 { 555 if (fputs(*line, out_file) < 0) 556 { 557 pg_log_error("could not write file \"%s\": %m", path); 558 exit(1); 559 } 560 free(*line); 561 } 562 if (fclose(out_file)) 563 { 564 pg_log_error("could not write file \"%s\": %m", path); 565 exit(1); 566 } 567 } 568 569 /* 570 * Open a subcommand with suitable error messaging 571 */ 572 static FILE * 573 popen_check(const char *command, const char *mode) 574 { 575 FILE *cmdfd; 576 577 fflush(stdout); 578 fflush(stderr); 579 errno = 0; 580 cmdfd = popen(command, mode); 581 if (cmdfd == NULL) 582 pg_log_error("could not execute command \"%s\": %m", command); 583 return cmdfd; 584 } 585 586 /* 587 * clean up any files we created on failure 588 * if we created the data directory remove it too 589 */ 590 static void 591 cleanup_directories_atexit(void) 592 { 593 if (success) 594 return; 595 596 if (!noclean) 597 { 598 if (made_new_pgdata) 599 { 600 pg_log_info("removing data directory \"%s\"", pg_data); 601 if (!rmtree(pg_data, true)) 602 pg_log_error("failed to remove data directory"); 603 } 604 else if (found_existing_pgdata) 605 { 606 pg_log_info("removing contents of data directory \"%s\"", 607 pg_data); 608 if (!rmtree(pg_data, false)) 609 pg_log_error("failed to remove contents of data directory"); 610 } 611 612 if (made_new_xlogdir) 613 { 614 pg_log_info("removing WAL directory \"%s\"", xlog_dir); 615 if (!rmtree(xlog_dir, true)) 616 pg_log_error("failed to remove WAL directory"); 617 } 618 else if (found_existing_xlogdir) 619 { 620 pg_log_info("removing contents of WAL directory \"%s\"", xlog_dir); 621 if (!rmtree(xlog_dir, false)) 622 pg_log_error("failed to remove contents of WAL directory"); 623 } 624 /* otherwise died during startup, do nothing! */ 625 } 626 else 627 { 628 if (made_new_pgdata || found_existing_pgdata) 629 pg_log_info("data directory \"%s\" not removed at user's request", 630 pg_data); 631 632 if (made_new_xlogdir || found_existing_xlogdir) 633 pg_log_info("WAL directory \"%s\" not removed at user's request", 634 xlog_dir); 635 } 636 } 637 638 /* 639 * find the current user 640 * 641 * on unix make sure it isn't root 642 */ 643 static char * 644 get_id(void) 645 { 646 const char *username; 647 648 #ifndef WIN32 649 if (geteuid() == 0) /* 0 is root's uid */ 650 { 651 pg_log_error("cannot be run as root"); 652 fprintf(stderr, 653 _("Please log in (using, e.g., \"su\") as the (unprivileged) user that will\n" 654 "own the server process.\n")); 655 exit(1); 656 } 657 #endif 658 659 username = get_user_name_or_exit(progname); 660 661 return pg_strdup(username); 662 } 663 664 static char * 665 encodingid_to_string(int enc) 666 { 667 char result[20]; 668 669 sprintf(result, "%d", enc); 670 return pg_strdup(result); 671 } 672 673 /* 674 * get the encoding id for a given encoding name 675 */ 676 static int 677 get_encoding_id(const char *encoding_name) 678 { 679 int enc; 680 681 if (encoding_name && *encoding_name) 682 { 683 if ((enc = pg_valid_server_encoding(encoding_name)) >= 0) 684 return enc; 685 } 686 pg_log_error("\"%s\" is not a valid server encoding name", 687 encoding_name ? encoding_name : "(null)"); 688 exit(1); 689 } 690 691 /* 692 * Support for determining the best default text search configuration. 693 * We key this off the first part of LC_CTYPE (ie, the language name). 694 */ 695 struct tsearch_config_match 696 { 697 const char *tsconfname; 698 const char *langname; 699 }; 700 701 static const struct tsearch_config_match tsearch_config_languages[] = 702 { 703 {"arabic", "ar"}, 704 {"arabic", "Arabic"}, 705 {"danish", "da"}, 706 {"danish", "Danish"}, 707 {"dutch", "nl"}, 708 {"dutch", "Dutch"}, 709 {"english", "C"}, 710 {"english", "POSIX"}, 711 {"english", "en"}, 712 {"english", "English"}, 713 {"finnish", "fi"}, 714 {"finnish", "Finnish"}, 715 {"french", "fr"}, 716 {"french", "French"}, 717 {"german", "de"}, 718 {"german", "German"}, 719 {"hungarian", "hu"}, 720 {"hungarian", "Hungarian"}, 721 {"indonesian", "id"}, 722 {"indonesian", "Indonesian"}, 723 {"irish", "ga"}, 724 {"irish", "Irish"}, 725 {"italian", "it"}, 726 {"italian", "Italian"}, 727 {"lithuanian", "lt"}, 728 {"lithuanian", "Lithuanian"}, 729 {"nepali", "ne"}, 730 {"nepali", "Nepali"}, 731 {"norwegian", "no"}, 732 {"norwegian", "Norwegian"}, 733 {"portuguese", "pt"}, 734 {"portuguese", "Portuguese"}, 735 {"romanian", "ro"}, 736 {"russian", "ru"}, 737 {"russian", "Russian"}, 738 {"spanish", "es"}, 739 {"spanish", "Spanish"}, 740 {"swedish", "sv"}, 741 {"swedish", "Swedish"}, 742 {"tamil", "ta"}, 743 {"tamil", "Tamil"}, 744 {"turkish", "tr"}, 745 {"turkish", "Turkish"}, 746 {NULL, NULL} /* end marker */ 747 }; 748 749 /* 750 * Look for a text search configuration matching lc_ctype, and return its 751 * name; return NULL if no match. 752 */ 753 static const char * 754 find_matching_ts_config(const char *lc_type) 755 { 756 int i; 757 char *langname, 758 *ptr; 759 760 /* 761 * Convert lc_ctype to a language name by stripping everything after an 762 * underscore (usual case) or a hyphen (Windows "locale name"; see 763 * comments at IsoLocaleName()). 764 * 765 * XXX Should ' ' be a stop character? This would select "norwegian" for 766 * the Windows locale "Norwegian (Nynorsk)_Norway.1252". If we do so, we 767 * should also accept the "nn" and "nb" Unix locales. 768 * 769 * Just for paranoia, we also stop at '.' or '@'. 770 */ 771 if (lc_type == NULL) 772 langname = pg_strdup(""); 773 else 774 { 775 ptr = langname = pg_strdup(lc_type); 776 while (*ptr && 777 *ptr != '_' && *ptr != '-' && *ptr != '.' && *ptr != '@') 778 ptr++; 779 *ptr = '\0'; 780 } 781 782 for (i = 0; tsearch_config_languages[i].tsconfname; i++) 783 { 784 if (pg_strcasecmp(tsearch_config_languages[i].langname, langname) == 0) 785 { 786 free(langname); 787 return tsearch_config_languages[i].tsconfname; 788 } 789 } 790 791 free(langname); 792 return NULL; 793 } 794 795 796 /* 797 * set name of given input file variable under data directory 798 */ 799 static void 800 set_input(char **dest, const char *filename) 801 { 802 *dest = psprintf("%s/%s", share_path, filename); 803 } 804 805 /* 806 * check that given input file exists 807 */ 808 static void 809 check_input(char *path) 810 { 811 struct stat statbuf; 812 813 if (stat(path, &statbuf) != 0) 814 { 815 if (errno == ENOENT) 816 { 817 pg_log_error("file \"%s\" does not exist", path); 818 fprintf(stderr, 819 _("This might mean you have a corrupted installation or identified\n" 820 "the wrong directory with the invocation option -L.\n")); 821 } 822 else 823 { 824 pg_log_error("could not access file \"%s\": %m", path); 825 fprintf(stderr, 826 _("This might mean you have a corrupted installation or identified\n" 827 "the wrong directory with the invocation option -L.\n")); 828 } 829 exit(1); 830 } 831 if (!S_ISREG(statbuf.st_mode)) 832 { 833 pg_log_error("file \"%s\" is not a regular file", path); 834 fprintf(stderr, 835 _("This might mean you have a corrupted installation or identified\n" 836 "the wrong directory with the invocation option -L.\n")); 837 exit(1); 838 } 839 } 840 841 /* 842 * write out the PG_VERSION file in the data dir, or its subdirectory 843 * if extrapath is not NULL 844 */ 845 static void 846 write_version_file(const char *extrapath) 847 { 848 FILE *version_file; 849 char *path; 850 851 if (extrapath == NULL) 852 path = psprintf("%s/PG_VERSION", pg_data); 853 else 854 path = psprintf("%s/%s/PG_VERSION", pg_data, extrapath); 855 856 if ((version_file = fopen(path, PG_BINARY_W)) == NULL) 857 { 858 pg_log_error("could not open file \"%s\" for writing: %m", path); 859 exit(1); 860 } 861 if (fprintf(version_file, "%s\n", PG_MAJORVERSION) < 0 || 862 fclose(version_file)) 863 { 864 pg_log_error("could not write file \"%s\": %m", path); 865 exit(1); 866 } 867 free(path); 868 } 869 870 /* 871 * set up an empty config file so we can check config settings by launching 872 * a test backend 873 */ 874 static void 875 set_null_conf(void) 876 { 877 FILE *conf_file; 878 char *path; 879 880 path = psprintf("%s/postgresql.conf", pg_data); 881 conf_file = fopen(path, PG_BINARY_W); 882 if (conf_file == NULL) 883 { 884 pg_log_error("could not open file \"%s\" for writing: %m", path); 885 exit(1); 886 } 887 if (fclose(conf_file)) 888 { 889 pg_log_error("could not write file \"%s\": %m", path); 890 exit(1); 891 } 892 free(path); 893 } 894 895 /* 896 * Determine which dynamic shared memory implementation should be used on 897 * this platform. POSIX shared memory is preferable because the default 898 * allocation limits are much higher than the limits for System V on most 899 * systems that support both, but the fact that a platform has shm_open 900 * doesn't guarantee that that call will succeed when attempted. So, we 901 * attempt to reproduce what the postmaster will do when allocating a POSIX 902 * segment in dsm_impl.c; if it doesn't work, we assume it won't work for 903 * the postmaster either, and configure the cluster for System V shared 904 * memory instead. 905 */ 906 static const char * 907 choose_dsm_implementation(void) 908 { 909 #ifdef HAVE_SHM_OPEN 910 int ntries = 10; 911 912 /* Initialize random(); this function is its only user in this program. */ 913 srandom((unsigned int) (getpid() ^ time(NULL))); 914 915 while (ntries > 0) 916 { 917 uint32 handle; 918 char name[64]; 919 int fd; 920 921 handle = random(); 922 snprintf(name, 64, "/PostgreSQL.%u", handle); 923 if ((fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600)) != -1) 924 { 925 close(fd); 926 shm_unlink(name); 927 return "posix"; 928 } 929 if (errno != EEXIST) 930 break; 931 --ntries; 932 } 933 #endif 934 935 #ifdef WIN32 936 return "windows"; 937 #else 938 return "sysv"; 939 #endif 940 } 941 942 /* 943 * Determine platform-specific config settings 944 * 945 * Use reasonable values if kernel will let us, else scale back. 946 */ 947 static void 948 test_config_settings(void) 949 { 950 /* 951 * This macro defines the minimum shared_buffers we want for a given 952 * max_connections value. The arrays show the settings to try. 953 */ 954 #define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10) 955 956 static const int trial_conns[] = { 957 100, 50, 40, 30, 20 958 }; 959 static const int trial_bufs[] = { 960 16384, 8192, 4096, 3584, 3072, 2560, 2048, 1536, 961 1000, 900, 800, 700, 600, 500, 962 400, 300, 200, 100, 50 963 }; 964 965 char cmd[MAXPGPATH]; 966 const int connslen = sizeof(trial_conns) / sizeof(int); 967 const int bufslen = sizeof(trial_bufs) / sizeof(int); 968 int i, 969 status, 970 test_conns, 971 test_buffs, 972 ok_buffers = 0; 973 974 /* 975 * Need to determine working DSM implementation first so that subsequent 976 * tests don't fail because DSM setting doesn't work. 977 */ 978 printf(_("selecting dynamic shared memory implementation ... ")); 979 fflush(stdout); 980 dynamic_shared_memory_type = choose_dsm_implementation(); 981 printf("%s\n", dynamic_shared_memory_type); 982 983 /* 984 * Probe for max_connections before shared_buffers, since it is subject to 985 * more constraints than shared_buffers. 986 */ 987 printf(_("selecting default max_connections ... ")); 988 fflush(stdout); 989 990 for (i = 0; i < connslen; i++) 991 { 992 test_conns = trial_conns[i]; 993 test_buffs = MIN_BUFS_FOR_CONNS(test_conns); 994 995 snprintf(cmd, sizeof(cmd), 996 "\"%s\" --boot -x0 %s " 997 "-c max_connections=%d " 998 "-c shared_buffers=%d " 999 "-c dynamic_shared_memory_type=%s " 1000 "< \"%s\" > \"%s\" 2>&1", 1001 backend_exec, boot_options, 1002 test_conns, test_buffs, 1003 dynamic_shared_memory_type, 1004 DEVNULL, DEVNULL); 1005 status = system(cmd); 1006 if (status == 0) 1007 { 1008 ok_buffers = test_buffs; 1009 break; 1010 } 1011 } 1012 if (i >= connslen) 1013 i = connslen - 1; 1014 n_connections = trial_conns[i]; 1015 1016 printf("%d\n", n_connections); 1017 1018 printf(_("selecting default shared_buffers ... ")); 1019 fflush(stdout); 1020 1021 for (i = 0; i < bufslen; i++) 1022 { 1023 /* Use same amount of memory, independent of BLCKSZ */ 1024 test_buffs = (trial_bufs[i] * 8192) / BLCKSZ; 1025 if (test_buffs <= ok_buffers) 1026 { 1027 test_buffs = ok_buffers; 1028 break; 1029 } 1030 1031 snprintf(cmd, sizeof(cmd), 1032 "\"%s\" --boot -x0 %s " 1033 "-c max_connections=%d " 1034 "-c shared_buffers=%d " 1035 "-c dynamic_shared_memory_type=%s " 1036 "< \"%s\" > \"%s\" 2>&1", 1037 backend_exec, boot_options, 1038 n_connections, test_buffs, 1039 dynamic_shared_memory_type, 1040 DEVNULL, DEVNULL); 1041 status = system(cmd); 1042 if (status == 0) 1043 break; 1044 } 1045 n_buffers = test_buffs; 1046 1047 if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0) 1048 printf("%dMB\n", (n_buffers * (BLCKSZ / 1024)) / 1024); 1049 else 1050 printf("%dkB\n", n_buffers * (BLCKSZ / 1024)); 1051 1052 printf(_("selecting default time zone ... ")); 1053 fflush(stdout); 1054 default_timezone = select_default_timezone(share_path); 1055 printf("%s\n", default_timezone ? default_timezone : "GMT"); 1056 } 1057 1058 /* 1059 * Calculate the default wal_size with a "pretty" unit. 1060 */ 1061 static char * 1062 pretty_wal_size(int segment_count) 1063 { 1064 int sz = wal_segment_size_mb * segment_count; 1065 char *result = pg_malloc(14); 1066 1067 if ((sz % 1024) == 0) 1068 snprintf(result, 14, "%dGB", sz / 1024); 1069 else 1070 snprintf(result, 14, "%dMB", sz); 1071 1072 return result; 1073 } 1074 1075 /* 1076 * set up all the config files 1077 */ 1078 static void 1079 setup_config(void) 1080 { 1081 char **conflines; 1082 char repltok[MAXPGPATH]; 1083 char path[MAXPGPATH]; 1084 char *autoconflines[3]; 1085 1086 fputs(_("creating configuration files ... "), stdout); 1087 fflush(stdout); 1088 1089 /* postgresql.conf */ 1090 1091 conflines = readfile(conf_file); 1092 1093 snprintf(repltok, sizeof(repltok), "max_connections = %d", n_connections); 1094 conflines = replace_token(conflines, "#max_connections = 100", repltok); 1095 1096 if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0) 1097 snprintf(repltok, sizeof(repltok), "shared_buffers = %dMB", 1098 (n_buffers * (BLCKSZ / 1024)) / 1024); 1099 else 1100 snprintf(repltok, sizeof(repltok), "shared_buffers = %dkB", 1101 n_buffers * (BLCKSZ / 1024)); 1102 conflines = replace_token(conflines, "#shared_buffers = 32MB", repltok); 1103 1104 #ifdef HAVE_UNIX_SOCKETS 1105 snprintf(repltok, sizeof(repltok), "#unix_socket_directories = '%s'", 1106 DEFAULT_PGSOCKET_DIR); 1107 #else 1108 snprintf(repltok, sizeof(repltok), "#unix_socket_directories = ''"); 1109 #endif 1110 conflines = replace_token(conflines, "#unix_socket_directories = '/tmp'", 1111 repltok); 1112 1113 #if DEF_PGPORT != 5432 1114 snprintf(repltok, sizeof(repltok), "#port = %d", DEF_PGPORT); 1115 conflines = replace_token(conflines, "#port = 5432", repltok); 1116 #endif 1117 1118 /* set default max_wal_size and min_wal_size */ 1119 snprintf(repltok, sizeof(repltok), "min_wal_size = %s", 1120 pretty_wal_size(DEFAULT_MIN_WAL_SEGS)); 1121 conflines = replace_token(conflines, "#min_wal_size = 80MB", repltok); 1122 1123 snprintf(repltok, sizeof(repltok), "max_wal_size = %s", 1124 pretty_wal_size(DEFAULT_MAX_WAL_SEGS)); 1125 conflines = replace_token(conflines, "#max_wal_size = 1GB", repltok); 1126 1127 snprintf(repltok, sizeof(repltok), "lc_messages = '%s'", 1128 escape_quotes(lc_messages)); 1129 conflines = replace_token(conflines, "#lc_messages = 'C'", repltok); 1130 1131 snprintf(repltok, sizeof(repltok), "lc_monetary = '%s'", 1132 escape_quotes(lc_monetary)); 1133 conflines = replace_token(conflines, "#lc_monetary = 'C'", repltok); 1134 1135 snprintf(repltok, sizeof(repltok), "lc_numeric = '%s'", 1136 escape_quotes(lc_numeric)); 1137 conflines = replace_token(conflines, "#lc_numeric = 'C'", repltok); 1138 1139 snprintf(repltok, sizeof(repltok), "lc_time = '%s'", 1140 escape_quotes(lc_time)); 1141 conflines = replace_token(conflines, "#lc_time = 'C'", repltok); 1142 1143 switch (locale_date_order(lc_time)) 1144 { 1145 case DATEORDER_YMD: 1146 strcpy(repltok, "datestyle = 'iso, ymd'"); 1147 break; 1148 case DATEORDER_DMY: 1149 strcpy(repltok, "datestyle = 'iso, dmy'"); 1150 break; 1151 case DATEORDER_MDY: 1152 default: 1153 strcpy(repltok, "datestyle = 'iso, mdy'"); 1154 break; 1155 } 1156 conflines = replace_token(conflines, "#datestyle = 'iso, mdy'", repltok); 1157 1158 snprintf(repltok, sizeof(repltok), 1159 "default_text_search_config = 'pg_catalog.%s'", 1160 escape_quotes(default_text_search_config)); 1161 conflines = replace_token(conflines, 1162 "#default_text_search_config = 'pg_catalog.simple'", 1163 repltok); 1164 1165 if (default_timezone) 1166 { 1167 snprintf(repltok, sizeof(repltok), "timezone = '%s'", 1168 escape_quotes(default_timezone)); 1169 conflines = replace_token(conflines, "#timezone = 'GMT'", repltok); 1170 snprintf(repltok, sizeof(repltok), "log_timezone = '%s'", 1171 escape_quotes(default_timezone)); 1172 conflines = replace_token(conflines, "#log_timezone = 'GMT'", repltok); 1173 } 1174 1175 snprintf(repltok, sizeof(repltok), "dynamic_shared_memory_type = %s", 1176 dynamic_shared_memory_type); 1177 conflines = replace_token(conflines, "#dynamic_shared_memory_type = posix", 1178 repltok); 1179 1180 #if DEFAULT_BACKEND_FLUSH_AFTER > 0 1181 snprintf(repltok, sizeof(repltok), "#backend_flush_after = %dkB", 1182 DEFAULT_BACKEND_FLUSH_AFTER * (BLCKSZ / 1024)); 1183 conflines = replace_token(conflines, "#backend_flush_after = 0", 1184 repltok); 1185 #endif 1186 1187 #if DEFAULT_BGWRITER_FLUSH_AFTER > 0 1188 snprintf(repltok, sizeof(repltok), "#bgwriter_flush_after = %dkB", 1189 DEFAULT_BGWRITER_FLUSH_AFTER * (BLCKSZ / 1024)); 1190 conflines = replace_token(conflines, "#bgwriter_flush_after = 0", 1191 repltok); 1192 #endif 1193 1194 #if DEFAULT_CHECKPOINT_FLUSH_AFTER > 0 1195 snprintf(repltok, sizeof(repltok), "#checkpoint_flush_after = %dkB", 1196 DEFAULT_CHECKPOINT_FLUSH_AFTER * (BLCKSZ / 1024)); 1197 conflines = replace_token(conflines, "#checkpoint_flush_after = 0", 1198 repltok); 1199 #endif 1200 1201 #ifndef USE_PREFETCH 1202 conflines = replace_token(conflines, 1203 "#effective_io_concurrency = 1", 1204 "#effective_io_concurrency = 0"); 1205 #endif 1206 1207 #ifdef WIN32 1208 conflines = replace_token(conflines, 1209 "#update_process_title = on", 1210 "#update_process_title = off"); 1211 #endif 1212 1213 if (strcmp(authmethodlocal, "scram-sha-256") == 0 || 1214 strcmp(authmethodhost, "scram-sha-256") == 0) 1215 { 1216 conflines = replace_token(conflines, 1217 "#password_encryption = md5", 1218 "password_encryption = scram-sha-256"); 1219 } 1220 1221 /* 1222 * If group access has been enabled for the cluster then it makes sense to 1223 * ensure that the log files also allow group access. Otherwise a backup 1224 * from a user in the group would fail if the log files were not 1225 * relocated. 1226 */ 1227 if (pg_dir_create_mode == PG_DIR_MODE_GROUP) 1228 { 1229 conflines = replace_token(conflines, 1230 "#log_file_mode = 0600", 1231 "log_file_mode = 0640"); 1232 } 1233 1234 snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data); 1235 1236 writefile(path, conflines); 1237 if (chmod(path, pg_file_create_mode) != 0) 1238 { 1239 pg_log_error("could not change permissions of \"%s\": %m", path); 1240 exit(1); 1241 } 1242 1243 /* 1244 * create the automatic configuration file to store the configuration 1245 * parameters set by ALTER SYSTEM command. The parameters present in this 1246 * file will override the value of parameters that exists before parse of 1247 * this file. 1248 */ 1249 autoconflines[0] = pg_strdup("# Do not edit this file manually!\n"); 1250 autoconflines[1] = pg_strdup("# It will be overwritten by the ALTER SYSTEM command.\n"); 1251 autoconflines[2] = NULL; 1252 1253 sprintf(path, "%s/postgresql.auto.conf", pg_data); 1254 1255 writefile(path, autoconflines); 1256 if (chmod(path, pg_file_create_mode) != 0) 1257 { 1258 pg_log_error("could not change permissions of \"%s\": %m", path); 1259 exit(1); 1260 } 1261 1262 free(conflines); 1263 1264 1265 /* pg_hba.conf */ 1266 1267 conflines = readfile(hba_file); 1268 1269 #ifndef HAVE_UNIX_SOCKETS 1270 conflines = filter_lines_with_token(conflines, "@remove-line-for-nolocal@"); 1271 #else 1272 conflines = replace_token(conflines, "@remove-line-for-nolocal@", ""); 1273 #endif 1274 1275 #ifdef HAVE_IPV6 1276 1277 /* 1278 * Probe to see if there is really any platform support for IPv6, and 1279 * comment out the relevant pg_hba line if not. This avoids runtime 1280 * warnings if getaddrinfo doesn't actually cope with IPv6. Particularly 1281 * useful on Windows, where executables built on a machine with IPv6 may 1282 * have to run on a machine without. 1283 */ 1284 { 1285 struct addrinfo *gai_result; 1286 struct addrinfo hints; 1287 int err = 0; 1288 1289 #ifdef WIN32 1290 /* need to call WSAStartup before calling getaddrinfo */ 1291 WSADATA wsaData; 1292 1293 err = WSAStartup(MAKEWORD(2, 2), &wsaData); 1294 #endif 1295 1296 /* for best results, this code should match parse_hba() */ 1297 hints.ai_flags = AI_NUMERICHOST; 1298 hints.ai_family = AF_UNSPEC; 1299 hints.ai_socktype = 0; 1300 hints.ai_protocol = 0; 1301 hints.ai_addrlen = 0; 1302 hints.ai_canonname = NULL; 1303 hints.ai_addr = NULL; 1304 hints.ai_next = NULL; 1305 1306 if (err != 0 || 1307 getaddrinfo("::1", NULL, &hints, &gai_result) != 0) 1308 { 1309 conflines = replace_token(conflines, 1310 "host all all ::1", 1311 "#host all all ::1"); 1312 conflines = replace_token(conflines, 1313 "host replication all ::1", 1314 "#host replication all ::1"); 1315 } 1316 } 1317 #else /* !HAVE_IPV6 */ 1318 /* If we didn't compile IPV6 support at all, always comment it out */ 1319 conflines = replace_token(conflines, 1320 "host all all ::1", 1321 "#host all all ::1"); 1322 conflines = replace_token(conflines, 1323 "host replication all ::1", 1324 "#host replication all ::1"); 1325 #endif /* HAVE_IPV6 */ 1326 1327 /* Replace default authentication methods */ 1328 conflines = replace_token(conflines, 1329 "@authmethodhost@", 1330 authmethodhost); 1331 conflines = replace_token(conflines, 1332 "@authmethodlocal@", 1333 authmethodlocal); 1334 1335 conflines = replace_token(conflines, 1336 "@authcomment@", 1337 (strcmp(authmethodlocal, "trust") == 0 || strcmp(authmethodhost, "trust") == 0) ? AUTHTRUST_WARNING : ""); 1338 1339 snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data); 1340 1341 writefile(path, conflines); 1342 if (chmod(path, pg_file_create_mode) != 0) 1343 { 1344 pg_log_error("could not change permissions of \"%s\": %m", path); 1345 exit(1); 1346 } 1347 1348 free(conflines); 1349 1350 /* pg_ident.conf */ 1351 1352 conflines = readfile(ident_file); 1353 1354 snprintf(path, sizeof(path), "%s/pg_ident.conf", pg_data); 1355 1356 writefile(path, conflines); 1357 if (chmod(path, pg_file_create_mode) != 0) 1358 { 1359 pg_log_error("could not change permissions of \"%s\": %m", path); 1360 exit(1); 1361 } 1362 1363 free(conflines); 1364 1365 check_ok(); 1366 } 1367 1368 1369 /* 1370 * run the BKI script in bootstrap mode to create template1 1371 */ 1372 static void 1373 bootstrap_template1(void) 1374 { 1375 PG_CMD_DECL; 1376 char **line; 1377 char **bki_lines; 1378 char headerline[MAXPGPATH]; 1379 char buf[64]; 1380 1381 printf(_("running bootstrap script ... ")); 1382 fflush(stdout); 1383 1384 bki_lines = readfile(bki_file); 1385 1386 /* Check that bki file appears to be of the right version */ 1387 1388 snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n", 1389 PG_MAJORVERSION); 1390 1391 if (strcmp(headerline, *bki_lines) != 0) 1392 { 1393 pg_log_error("input file \"%s\" does not belong to PostgreSQL %s", 1394 bki_file, PG_VERSION); 1395 fprintf(stderr, 1396 _("Check your installation or specify the correct path " 1397 "using the option -L.\n")); 1398 exit(1); 1399 } 1400 1401 /* Substitute for various symbols used in the BKI file */ 1402 1403 sprintf(buf, "%d", NAMEDATALEN); 1404 bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf); 1405 1406 sprintf(buf, "%d", (int) sizeof(Pointer)); 1407 bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf); 1408 1409 bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER", 1410 (sizeof(Pointer) == 4) ? "i" : "d"); 1411 1412 bki_lines = replace_token(bki_lines, "FLOAT4PASSBYVAL", 1413 FLOAT4PASSBYVAL ? "true" : "false"); 1414 1415 bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL", 1416 FLOAT8PASSBYVAL ? "true" : "false"); 1417 1418 bki_lines = replace_token(bki_lines, "POSTGRES", 1419 escape_quotes_bki(username)); 1420 1421 bki_lines = replace_token(bki_lines, "ENCODING", 1422 encodingid_to_string(encodingid)); 1423 1424 bki_lines = replace_token(bki_lines, "LC_COLLATE", 1425 escape_quotes_bki(lc_collate)); 1426 1427 bki_lines = replace_token(bki_lines, "LC_CTYPE", 1428 escape_quotes_bki(lc_ctype)); 1429 1430 /* 1431 * Pass correct LC_xxx environment to bootstrap. 1432 * 1433 * The shell script arranged to restore the LC settings afterwards, but 1434 * there doesn't seem to be any compelling reason to do that. 1435 */ 1436 snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate); 1437 putenv(pg_strdup(cmd)); 1438 1439 snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype); 1440 putenv(pg_strdup(cmd)); 1441 1442 unsetenv("LC_ALL"); 1443 1444 /* Also ensure backend isn't confused by this environment var: */ 1445 unsetenv("PGCLIENTENCODING"); 1446 1447 snprintf(cmd, sizeof(cmd), 1448 "\"%s\" --boot -x1 -X %u %s %s %s", 1449 backend_exec, 1450 wal_segment_size_mb * (1024 * 1024), 1451 data_checksums ? "-k" : "", 1452 boot_options, 1453 debug ? "-d 5" : ""); 1454 1455 1456 PG_CMD_OPEN; 1457 1458 for (line = bki_lines; *line != NULL; line++) 1459 { 1460 PG_CMD_PUTS(*line); 1461 free(*line); 1462 } 1463 1464 PG_CMD_CLOSE; 1465 1466 free(bki_lines); 1467 1468 check_ok(); 1469 } 1470 1471 /* 1472 * set up the shadow password table 1473 */ 1474 static void 1475 setup_auth(FILE *cmdfd) 1476 { 1477 const char *const *line; 1478 static const char *const pg_authid_setup[] = { 1479 /* 1480 * The authid table shouldn't be readable except through views, to 1481 * ensure passwords are not publicly visible. 1482 */ 1483 "REVOKE ALL on pg_authid FROM public;\n\n", 1484 NULL 1485 }; 1486 1487 for (line = pg_authid_setup; *line != NULL; line++) 1488 PG_CMD_PUTS(*line); 1489 1490 if (superuser_password) 1491 PG_CMD_PRINTF2("ALTER USER \"%s\" WITH PASSWORD E'%s';\n\n", 1492 username, escape_quotes(superuser_password)); 1493 } 1494 1495 /* 1496 * get the superuser password if required 1497 */ 1498 static void 1499 get_su_pwd(void) 1500 { 1501 char pwd1[100]; 1502 char pwd2[100]; 1503 1504 if (pwprompt) 1505 { 1506 /* 1507 * Read password from terminal 1508 */ 1509 printf("\n"); 1510 fflush(stdout); 1511 simple_prompt("Enter new superuser password: ", pwd1, sizeof(pwd1), false); 1512 simple_prompt("Enter it again: ", pwd2, sizeof(pwd2), false); 1513 if (strcmp(pwd1, pwd2) != 0) 1514 { 1515 fprintf(stderr, _("Passwords didn't match.\n")); 1516 exit(1); 1517 } 1518 } 1519 else 1520 { 1521 /* 1522 * Read password from file 1523 * 1524 * Ideally this should insist that the file not be world-readable. 1525 * However, this option is mainly intended for use on Windows where 1526 * file permissions may not exist at all, so we'll skip the paranoia 1527 * for now. 1528 */ 1529 FILE *pwf = fopen(pwfilename, "r"); 1530 int i; 1531 1532 if (!pwf) 1533 { 1534 pg_log_error("could not open file \"%s\" for reading: %m", 1535 pwfilename); 1536 exit(1); 1537 } 1538 if (!fgets(pwd1, sizeof(pwd1), pwf)) 1539 { 1540 if (ferror(pwf)) 1541 pg_log_error("could not read password from file \"%s\": %m", 1542 pwfilename); 1543 else 1544 pg_log_error("password file \"%s\" is empty", 1545 pwfilename); 1546 exit(1); 1547 } 1548 fclose(pwf); 1549 1550 i = strlen(pwd1); 1551 while (i > 0 && (pwd1[i - 1] == '\r' || pwd1[i - 1] == '\n')) 1552 pwd1[--i] = '\0'; 1553 } 1554 1555 superuser_password = pg_strdup(pwd1); 1556 } 1557 1558 /* 1559 * set up pg_depend 1560 */ 1561 static void 1562 setup_depend(FILE *cmdfd) 1563 { 1564 const char *const *line; 1565 static const char *const pg_depend_setup[] = { 1566 /* 1567 * Make PIN entries in pg_depend for all objects made so far in the 1568 * tables that the dependency code handles. This is overkill (the 1569 * system doesn't really depend on having every last weird datatype, 1570 * for instance) but generating only the minimum required set of 1571 * dependencies seems hard. 1572 * 1573 * Catalogs that are intentionally not scanned here are: 1574 * 1575 * pg_database: it's a feature, not a bug, that template1 is not 1576 * pinned. 1577 * 1578 * pg_extension: a pinned extension isn't really an extension, hmm? 1579 * 1580 * pg_tablespace: tablespaces don't participate in the dependency 1581 * code, and DropTableSpace() explicitly protects the built-in 1582 * tablespaces. 1583 * 1584 * First delete any already-made entries; PINs override all else, and 1585 * must be the only entries for their objects. 1586 */ 1587 "DELETE FROM pg_depend;\n\n", 1588 "VACUUM pg_depend;\n\n", 1589 "DELETE FROM pg_shdepend;\n\n", 1590 "VACUUM pg_shdepend;\n\n", 1591 1592 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1593 " FROM pg_class;\n\n", 1594 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1595 " FROM pg_proc;\n\n", 1596 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1597 " FROM pg_type;\n\n", 1598 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1599 " FROM pg_cast;\n\n", 1600 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1601 " FROM pg_constraint;\n\n", 1602 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1603 " FROM pg_conversion;\n\n", 1604 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1605 " FROM pg_attrdef;\n\n", 1606 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1607 " FROM pg_language;\n\n", 1608 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1609 " FROM pg_operator;\n\n", 1610 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1611 " FROM pg_opclass;\n\n", 1612 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1613 " FROM pg_opfamily;\n\n", 1614 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1615 " FROM pg_am;\n\n", 1616 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1617 " FROM pg_amop;\n\n", 1618 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1619 " FROM pg_amproc;\n\n", 1620 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1621 " FROM pg_rewrite;\n\n", 1622 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1623 " FROM pg_trigger;\n\n", 1624 1625 /* 1626 * restriction here to avoid pinning the public namespace 1627 */ 1628 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1629 " FROM pg_namespace " 1630 " WHERE nspname LIKE 'pg%';\n\n", 1631 1632 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1633 " FROM pg_ts_parser;\n\n", 1634 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1635 " FROM pg_ts_dict;\n\n", 1636 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1637 " FROM pg_ts_template;\n\n", 1638 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1639 " FROM pg_ts_config;\n\n", 1640 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " 1641 " FROM pg_collation;\n\n", 1642 "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " 1643 " FROM pg_authid;\n\n", 1644 NULL 1645 }; 1646 1647 for (line = pg_depend_setup; *line != NULL; line++) 1648 PG_CMD_PUTS(*line); 1649 } 1650 1651 /* 1652 * set up system views 1653 */ 1654 static void 1655 setup_sysviews(FILE *cmdfd) 1656 { 1657 char **line; 1658 char **sysviews_setup; 1659 1660 sysviews_setup = readfile(system_views_file); 1661 1662 for (line = sysviews_setup; *line != NULL; line++) 1663 { 1664 PG_CMD_PUTS(*line); 1665 free(*line); 1666 } 1667 1668 PG_CMD_PUTS("\n\n"); 1669 1670 free(sysviews_setup); 1671 } 1672 1673 /* 1674 * load description data 1675 */ 1676 static void 1677 setup_description(FILE *cmdfd) 1678 { 1679 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( " 1680 " objoid oid, " 1681 " classname name, " 1682 " objsubid int4, " 1683 " description text);\n\n"); 1684 1685 PG_CMD_PRINTF1("COPY tmp_pg_description FROM E'%s';\n\n", 1686 escape_quotes(desc_file)); 1687 1688 PG_CMD_PUTS("INSERT INTO pg_description " 1689 " SELECT t.objoid, c.oid, t.objsubid, t.description " 1690 " FROM tmp_pg_description t, pg_class c " 1691 " WHERE c.relname = t.classname;\n\n"); 1692 1693 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_shdescription ( " 1694 " objoid oid, " 1695 " classname name, " 1696 " description text);\n\n"); 1697 1698 PG_CMD_PRINTF1("COPY tmp_pg_shdescription FROM E'%s';\n\n", 1699 escape_quotes(shdesc_file)); 1700 1701 PG_CMD_PUTS("INSERT INTO pg_shdescription " 1702 " SELECT t.objoid, c.oid, t.description " 1703 " FROM tmp_pg_shdescription t, pg_class c " 1704 " WHERE c.relname = t.classname;\n\n"); 1705 1706 /* Create default descriptions for operator implementation functions */ 1707 PG_CMD_PUTS("WITH funcdescs AS ( " 1708 "SELECT p.oid as p_oid, o.oid as o_oid, oprname " 1709 "FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) " 1710 "INSERT INTO pg_description " 1711 " SELECT p_oid, 'pg_proc'::regclass, 0, " 1712 " 'implementation of ' || oprname || ' operator' " 1713 " FROM funcdescs " 1714 " WHERE NOT EXISTS (SELECT 1 FROM pg_description " 1715 " WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass) " 1716 " AND NOT EXISTS (SELECT 1 FROM pg_description " 1717 " WHERE objoid = o_oid AND classoid = 'pg_operator'::regclass" 1718 " AND description LIKE 'deprecated%');\n\n"); 1719 1720 /* 1721 * Even though the tables are temp, drop them explicitly so they don't get 1722 * copied into template0/postgres databases. 1723 */ 1724 PG_CMD_PUTS("DROP TABLE tmp_pg_description;\n\n"); 1725 PG_CMD_PUTS("DROP TABLE tmp_pg_shdescription;\n\n"); 1726 } 1727 1728 /* 1729 * populate pg_collation 1730 */ 1731 static void 1732 setup_collation(FILE *cmdfd) 1733 { 1734 /* 1735 * Add an SQL-standard name. We don't want to pin this, so it doesn't go 1736 * in pg_collation.h. But add it before reading system collations, so 1737 * that it wins if libc defines a locale named ucs_basic. 1738 */ 1739 PG_CMD_PRINTF3("INSERT INTO pg_collation (oid, collname, collnamespace, collowner, collprovider, collisdeterministic, collencoding, collcollate, collctype)" 1740 "VALUES (pg_nextoid('pg_catalog.pg_collation', 'oid', 'pg_catalog.pg_collation_oid_index'), 'ucs_basic', 'pg_catalog'::regnamespace, %u, '%c', true, %d, 'C', 'C');\n\n", 1741 BOOTSTRAP_SUPERUSERID, COLLPROVIDER_LIBC, PG_UTF8); 1742 1743 /* Now import all collations we can find in the operating system */ 1744 PG_CMD_PUTS("SELECT pg_import_system_collations('pg_catalog');\n\n"); 1745 } 1746 1747 /* 1748 * load extra dictionaries (Snowball stemmers) 1749 */ 1750 static void 1751 setup_dictionary(FILE *cmdfd) 1752 { 1753 char **line; 1754 char **conv_lines; 1755 1756 conv_lines = readfile(dictionary_file); 1757 for (line = conv_lines; *line != NULL; line++) 1758 { 1759 PG_CMD_PUTS(*line); 1760 free(*line); 1761 } 1762 1763 PG_CMD_PUTS("\n\n"); 1764 1765 free(conv_lines); 1766 } 1767 1768 /* 1769 * Set up privileges 1770 * 1771 * We mark most system catalogs as world-readable. We don't currently have 1772 * to touch functions, languages, or databases, because their default 1773 * permissions are OK. 1774 * 1775 * Some objects may require different permissions by default, so we 1776 * make sure we don't overwrite privilege sets that have already been 1777 * set (NOT NULL). 1778 * 1779 * Also populate pg_init_privs to save what the privileges are at init 1780 * time. This is used by pg_dump to allow users to change privileges 1781 * on catalog objects and to have those privilege changes preserved 1782 * across dump/reload and pg_upgrade. 1783 * 1784 * Note that pg_init_privs is only for per-database objects and therefore 1785 * we don't include databases or tablespaces. 1786 */ 1787 static void 1788 setup_privileges(FILE *cmdfd) 1789 { 1790 char **line; 1791 char **priv_lines; 1792 static char *privileges_setup[] = { 1793 "UPDATE pg_class " 1794 " SET relacl = (SELECT array_agg(a.acl) FROM " 1795 " (SELECT E'=r/\"$POSTGRES_SUPERUSERNAME\"' as acl " 1796 " UNION SELECT unnest(pg_catalog.acldefault(" 1797 " CASE WHEN relkind = " CppAsString2(RELKIND_SEQUENCE) " THEN 's' " 1798 " ELSE 'r' END::\"char\"," CppAsString2(BOOTSTRAP_SUPERUSERID) "::oid))" 1799 " ) as a) " 1800 " WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", " 1801 CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " 1802 CppAsString2(RELKIND_SEQUENCE) ")" 1803 " AND relacl IS NULL;\n\n", 1804 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n", 1805 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n", 1806 "REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n", 1807 "INSERT INTO pg_init_privs " 1808 " (objoid, classoid, objsubid, initprivs, privtype)" 1809 " SELECT" 1810 " oid," 1811 " (SELECT oid FROM pg_class WHERE relname = 'pg_class')," 1812 " 0," 1813 " relacl," 1814 " 'i'" 1815 " FROM" 1816 " pg_class" 1817 " WHERE" 1818 " relacl IS NOT NULL" 1819 " AND relkind IN (" CppAsString2(RELKIND_RELATION) ", " 1820 CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " 1821 CppAsString2(RELKIND_SEQUENCE) ");\n\n", 1822 "INSERT INTO pg_init_privs " 1823 " (objoid, classoid, objsubid, initprivs, privtype)" 1824 " SELECT" 1825 " pg_class.oid," 1826 " (SELECT oid FROM pg_class WHERE relname = 'pg_class')," 1827 " pg_attribute.attnum," 1828 " pg_attribute.attacl," 1829 " 'i'" 1830 " FROM" 1831 " pg_class" 1832 " JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)" 1833 " WHERE" 1834 " pg_attribute.attacl IS NOT NULL" 1835 " AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION) ", " 1836 CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " 1837 CppAsString2(RELKIND_SEQUENCE) ");\n\n", 1838 "INSERT INTO pg_init_privs " 1839 " (objoid, classoid, objsubid, initprivs, privtype)" 1840 " SELECT" 1841 " oid," 1842 " (SELECT oid FROM pg_class WHERE relname = 'pg_proc')," 1843 " 0," 1844 " proacl," 1845 " 'i'" 1846 " FROM" 1847 " pg_proc" 1848 " WHERE" 1849 " proacl IS NOT NULL;\n\n", 1850 "INSERT INTO pg_init_privs " 1851 " (objoid, classoid, objsubid, initprivs, privtype)" 1852 " SELECT" 1853 " oid," 1854 " (SELECT oid FROM pg_class WHERE relname = 'pg_type')," 1855 " 0," 1856 " typacl," 1857 " 'i'" 1858 " FROM" 1859 " pg_type" 1860 " WHERE" 1861 " typacl IS NOT NULL;\n\n", 1862 "INSERT INTO pg_init_privs " 1863 " (objoid, classoid, objsubid, initprivs, privtype)" 1864 " SELECT" 1865 " oid," 1866 " (SELECT oid FROM pg_class WHERE relname = 'pg_language')," 1867 " 0," 1868 " lanacl," 1869 " 'i'" 1870 " FROM" 1871 " pg_language" 1872 " WHERE" 1873 " lanacl IS NOT NULL;\n\n", 1874 "INSERT INTO pg_init_privs " 1875 " (objoid, classoid, objsubid, initprivs, privtype)" 1876 " SELECT" 1877 " oid," 1878 " (SELECT oid FROM pg_class WHERE " 1879 " relname = 'pg_largeobject_metadata')," 1880 " 0," 1881 " lomacl," 1882 " 'i'" 1883 " FROM" 1884 " pg_largeobject_metadata" 1885 " WHERE" 1886 " lomacl IS NOT NULL;\n\n", 1887 "INSERT INTO pg_init_privs " 1888 " (objoid, classoid, objsubid, initprivs, privtype)" 1889 " SELECT" 1890 " oid," 1891 " (SELECT oid FROM pg_class WHERE relname = 'pg_namespace')," 1892 " 0," 1893 " nspacl," 1894 " 'i'" 1895 " FROM" 1896 " pg_namespace" 1897 " WHERE" 1898 " nspacl IS NOT NULL;\n\n", 1899 "INSERT INTO pg_init_privs " 1900 " (objoid, classoid, objsubid, initprivs, privtype)" 1901 " SELECT" 1902 " oid," 1903 " (SELECT oid FROM pg_class WHERE " 1904 " relname = 'pg_foreign_data_wrapper')," 1905 " 0," 1906 " fdwacl," 1907 " 'i'" 1908 " FROM" 1909 " pg_foreign_data_wrapper" 1910 " WHERE" 1911 " fdwacl IS NOT NULL;\n\n", 1912 "INSERT INTO pg_init_privs " 1913 " (objoid, classoid, objsubid, initprivs, privtype)" 1914 " SELECT" 1915 " oid," 1916 " (SELECT oid FROM pg_class " 1917 " WHERE relname = 'pg_foreign_server')," 1918 " 0," 1919 " srvacl," 1920 " 'i'" 1921 " FROM" 1922 " pg_foreign_server" 1923 " WHERE" 1924 " srvacl IS NOT NULL;\n\n", 1925 NULL 1926 }; 1927 1928 priv_lines = replace_token(privileges_setup, "$POSTGRES_SUPERUSERNAME", 1929 escape_quotes(username)); 1930 for (line = priv_lines; *line != NULL; line++) 1931 PG_CMD_PUTS(*line); 1932 } 1933 1934 /* 1935 * extract the strange version of version required for information schema 1936 * (09.08.0007abc) 1937 */ 1938 static void 1939 set_info_version(void) 1940 { 1941 char *letterversion; 1942 long major = 0, 1943 minor = 0, 1944 micro = 0; 1945 char *endptr; 1946 char *vstr = pg_strdup(PG_VERSION); 1947 char *ptr; 1948 1949 ptr = vstr + (strlen(vstr) - 1); 1950 while (ptr != vstr && (*ptr < '0' || *ptr > '9')) 1951 ptr--; 1952 letterversion = ptr + 1; 1953 major = strtol(vstr, &endptr, 10); 1954 if (*endptr) 1955 minor = strtol(endptr + 1, &endptr, 10); 1956 if (*endptr) 1957 micro = strtol(endptr + 1, &endptr, 10); 1958 snprintf(infoversion, sizeof(infoversion), "%02ld.%02ld.%04ld%s", 1959 major, minor, micro, letterversion); 1960 } 1961 1962 /* 1963 * load info schema and populate from features file 1964 */ 1965 static void 1966 setup_schema(FILE *cmdfd) 1967 { 1968 char **line; 1969 char **lines; 1970 1971 lines = readfile(info_schema_file); 1972 1973 for (line = lines; *line != NULL; line++) 1974 { 1975 PG_CMD_PUTS(*line); 1976 free(*line); 1977 } 1978 1979 PG_CMD_PUTS("\n\n"); 1980 1981 free(lines); 1982 1983 PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info " 1984 " SET character_value = '%s' " 1985 " WHERE implementation_info_name = 'DBMS VERSION';\n\n", 1986 infoversion); 1987 1988 PG_CMD_PRINTF1("COPY information_schema.sql_features " 1989 " (feature_id, feature_name, sub_feature_id, " 1990 " sub_feature_name, is_supported, comments) " 1991 " FROM E'%s';\n\n", 1992 escape_quotes(features_file)); 1993 } 1994 1995 /* 1996 * load PL/pgSQL server-side language 1997 */ 1998 static void 1999 load_plpgsql(FILE *cmdfd) 2000 { 2001 PG_CMD_PUTS("CREATE EXTENSION plpgsql;\n\n"); 2002 } 2003 2004 /* 2005 * clean everything up in template1 2006 */ 2007 static void 2008 vacuum_db(FILE *cmdfd) 2009 { 2010 /* Run analyze before VACUUM so the statistics are frozen. */ 2011 PG_CMD_PUTS("ANALYZE;\n\nVACUUM FREEZE;\n\n"); 2012 } 2013 2014 /* 2015 * copy template1 to template0 2016 */ 2017 static void 2018 make_template0(FILE *cmdfd) 2019 { 2020 const char *const *line; 2021 static const char *const template0_setup[] = { 2022 "CREATE DATABASE template0 IS_TEMPLATE = true ALLOW_CONNECTIONS = false;\n\n", 2023 2024 /* 2025 * We use the OID of template0 to determine lastsysoid 2026 */ 2027 "UPDATE pg_database SET datlastsysoid = " 2028 " (SELECT oid FROM pg_database " 2029 " WHERE datname = 'template0');\n\n", 2030 2031 /* 2032 * Explicitly revoke public create-schema and create-temp-table 2033 * privileges in template1 and template0; else the latter would be on 2034 * by default 2035 */ 2036 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n\n", 2037 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n\n", 2038 2039 "COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n\n", 2040 2041 /* 2042 * Finally vacuum to clean up dead rows in pg_database 2043 */ 2044 "VACUUM pg_database;\n\n", 2045 NULL 2046 }; 2047 2048 for (line = template0_setup; *line; line++) 2049 PG_CMD_PUTS(*line); 2050 } 2051 2052 /* 2053 * copy template1 to postgres 2054 */ 2055 static void 2056 make_postgres(FILE *cmdfd) 2057 { 2058 const char *const *line; 2059 static const char *const postgres_setup[] = { 2060 "CREATE DATABASE postgres;\n\n", 2061 "COMMENT ON DATABASE postgres IS 'default administrative connection database';\n\n", 2062 NULL 2063 }; 2064 2065 for (line = postgres_setup; *line; line++) 2066 PG_CMD_PUTS(*line); 2067 } 2068 2069 /* 2070 * signal handler in case we are interrupted. 2071 * 2072 * The Windows runtime docs at 2073 * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_signal.asp 2074 * specifically forbid a number of things being done from a signal handler, 2075 * including IO, memory allocation and system calls, and only allow jmpbuf 2076 * if you are handling SIGFPE. 2077 * 2078 * I avoided doing the forbidden things by setting a flag instead of calling 2079 * exit() directly. 2080 * 2081 * Also note the behaviour of Windows with SIGINT, which says this: 2082 * Note SIGINT is not supported for any Win32 application, including 2083 * Windows 98/Me and Windows NT/2000/XP. When a CTRL+C interrupt occurs, 2084 * Win32 operating systems generate a new thread to specifically handle 2085 * that interrupt. This can cause a single-thread application such as UNIX, 2086 * to become multithreaded, resulting in unexpected behavior. 2087 * 2088 * I have no idea how to handle this. (Strange they call UNIX an application!) 2089 * So this will need some testing on Windows. 2090 */ 2091 static void 2092 trapsig(int signum) 2093 { 2094 /* handle systems that reset the handler, like Windows (grr) */ 2095 pqsignal(signum, trapsig); 2096 caught_signal = true; 2097 } 2098 2099 /* 2100 * call exit() if we got a signal, or else output "ok". 2101 */ 2102 static void 2103 check_ok(void) 2104 { 2105 if (caught_signal) 2106 { 2107 printf(_("caught signal\n")); 2108 fflush(stdout); 2109 exit(1); 2110 } 2111 else if (output_failed) 2112 { 2113 printf(_("could not write to child process: %s\n"), 2114 strerror(output_errno)); 2115 fflush(stdout); 2116 exit(1); 2117 } 2118 else 2119 { 2120 /* all seems well */ 2121 printf(_("ok\n")); 2122 fflush(stdout); 2123 } 2124 } 2125 2126 /* Hack to suppress a warning about %x from some versions of gcc */ 2127 static inline size_t 2128 my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) 2129 { 2130 return strftime(s, max, fmt, tm); 2131 } 2132 2133 /* 2134 * Determine likely date order from locale 2135 */ 2136 static int 2137 locale_date_order(const char *locale) 2138 { 2139 struct tm testtime; 2140 char buf[128]; 2141 char *posD; 2142 char *posM; 2143 char *posY; 2144 char *save; 2145 size_t res; 2146 int result; 2147 2148 result = DATEORDER_MDY; /* default */ 2149 2150 save = setlocale(LC_TIME, NULL); 2151 if (!save) 2152 return result; 2153 save = pg_strdup(save); 2154 2155 setlocale(LC_TIME, locale); 2156 2157 memset(&testtime, 0, sizeof(testtime)); 2158 testtime.tm_mday = 22; 2159 testtime.tm_mon = 10; /* November, should come out as "11" */ 2160 testtime.tm_year = 133; /* 2033 */ 2161 2162 res = my_strftime(buf, sizeof(buf), "%x", &testtime); 2163 2164 setlocale(LC_TIME, save); 2165 free(save); 2166 2167 if (res == 0) 2168 return result; 2169 2170 posM = strstr(buf, "11"); 2171 posD = strstr(buf, "22"); 2172 posY = strstr(buf, "33"); 2173 2174 if (!posM || !posD || !posY) 2175 return result; 2176 2177 if (posY < posM && posM < posD) 2178 result = DATEORDER_YMD; 2179 else if (posD < posM) 2180 result = DATEORDER_DMY; 2181 else 2182 result = DATEORDER_MDY; 2183 2184 return result; 2185 } 2186 2187 /* 2188 * Verify that locale name is valid for the locale category. 2189 * 2190 * If successful, and canonname isn't NULL, a malloc'd copy of the locale's 2191 * canonical name is stored there. This is especially useful for figuring out 2192 * what locale name "" means (ie, the environment value). (Actually, 2193 * it seems that on most implementations that's the only thing it's good for; 2194 * we could wish that setlocale gave back a canonically spelled version of 2195 * the locale name, but typically it doesn't.) 2196 * 2197 * this should match the backend's check_locale() function 2198 */ 2199 static void 2200 check_locale_name(int category, const char *locale, char **canonname) 2201 { 2202 char *save; 2203 char *res; 2204 2205 if (canonname) 2206 *canonname = NULL; /* in case of failure */ 2207 2208 save = setlocale(category, NULL); 2209 if (!save) 2210 { 2211 pg_log_error("setlocale() failed"); 2212 exit(1); 2213 } 2214 2215 /* save may be pointing at a modifiable scratch variable, so copy it. */ 2216 save = pg_strdup(save); 2217 2218 /* for setlocale() call */ 2219 if (!locale) 2220 locale = ""; 2221 2222 /* set the locale with setlocale, to see if it accepts it. */ 2223 res = setlocale(category, locale); 2224 2225 /* save canonical name if requested. */ 2226 if (res && canonname) 2227 *canonname = pg_strdup(res); 2228 2229 /* restore old value. */ 2230 if (!setlocale(category, save)) 2231 { 2232 pg_log_error("failed to restore old locale \"%s\"", save); 2233 exit(1); 2234 } 2235 free(save); 2236 2237 /* complain if locale wasn't valid */ 2238 if (res == NULL) 2239 { 2240 if (*locale) 2241 pg_log_error("invalid locale name \"%s\"", locale); 2242 else 2243 { 2244 /* 2245 * If no relevant switch was given on command line, locale is an 2246 * empty string, which is not too helpful to report. Presumably 2247 * setlocale() found something it did not like in the environment. 2248 * Ideally we'd report the bad environment variable, but since 2249 * setlocale's behavior is implementation-specific, it's hard to 2250 * be sure what it didn't like. Print a safe generic message. 2251 */ 2252 pg_log_error("invalid locale settings; check LANG and LC_* environment variables"); 2253 } 2254 exit(1); 2255 } 2256 } 2257 2258 /* 2259 * check if the chosen encoding matches the encoding required by the locale 2260 * 2261 * this should match the similar check in the backend createdb() function 2262 */ 2263 static bool 2264 check_locale_encoding(const char *locale, int user_enc) 2265 { 2266 int locale_enc; 2267 2268 locale_enc = pg_get_encoding_from_locale(locale, true); 2269 2270 /* See notes in createdb() to understand these tests */ 2271 if (!(locale_enc == user_enc || 2272 locale_enc == PG_SQL_ASCII || 2273 locale_enc == -1 || 2274 #ifdef WIN32 2275 user_enc == PG_UTF8 || 2276 #endif 2277 user_enc == PG_SQL_ASCII)) 2278 { 2279 pg_log_error("encoding mismatch"); 2280 fprintf(stderr, 2281 _("The encoding you selected (%s) and the encoding that the\n" 2282 "selected locale uses (%s) do not match. This would lead to\n" 2283 "misbehavior in various character string processing functions.\n" 2284 "Rerun %s and either do not specify an encoding explicitly,\n" 2285 "or choose a matching combination.\n"), 2286 pg_encoding_to_char(user_enc), 2287 pg_encoding_to_char(locale_enc), 2288 progname); 2289 return false; 2290 } 2291 return true; 2292 } 2293 2294 /* 2295 * set up the locale variables 2296 * 2297 * assumes we have called setlocale(LC_ALL, "") -- see set_pglocale_pgservice 2298 */ 2299 static void 2300 setlocales(void) 2301 { 2302 char *canonname; 2303 2304 /* set empty lc_* values to locale config if set */ 2305 2306 if (locale) 2307 { 2308 if (!lc_ctype) 2309 lc_ctype = locale; 2310 if (!lc_collate) 2311 lc_collate = locale; 2312 if (!lc_numeric) 2313 lc_numeric = locale; 2314 if (!lc_time) 2315 lc_time = locale; 2316 if (!lc_monetary) 2317 lc_monetary = locale; 2318 if (!lc_messages) 2319 lc_messages = locale; 2320 } 2321 2322 /* 2323 * canonicalize locale names, and obtain any missing values from our 2324 * current environment 2325 */ 2326 2327 check_locale_name(LC_CTYPE, lc_ctype, &canonname); 2328 lc_ctype = canonname; 2329 check_locale_name(LC_COLLATE, lc_collate, &canonname); 2330 lc_collate = canonname; 2331 check_locale_name(LC_NUMERIC, lc_numeric, &canonname); 2332 lc_numeric = canonname; 2333 check_locale_name(LC_TIME, lc_time, &canonname); 2334 lc_time = canonname; 2335 check_locale_name(LC_MONETARY, lc_monetary, &canonname); 2336 lc_monetary = canonname; 2337 #if defined(LC_MESSAGES) && !defined(WIN32) 2338 check_locale_name(LC_MESSAGES, lc_messages, &canonname); 2339 lc_messages = canonname; 2340 #else 2341 /* when LC_MESSAGES is not available, use the LC_CTYPE setting */ 2342 check_locale_name(LC_CTYPE, lc_messages, &canonname); 2343 lc_messages = canonname; 2344 #endif 2345 } 2346 2347 /* 2348 * print help text 2349 */ 2350 static void 2351 usage(const char *progname) 2352 { 2353 printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname); 2354 printf(_("Usage:\n")); 2355 printf(_(" %s [OPTION]... [DATADIR]\n"), progname); 2356 printf(_("\nOptions:\n")); 2357 printf(_(" -A, --auth=METHOD default authentication method for local connections\n")); 2358 printf(_(" --auth-host=METHOD default authentication method for local TCP/IP connections\n")); 2359 printf(_(" --auth-local=METHOD default authentication method for local-socket connections\n")); 2360 printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n")); 2361 printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n")); 2362 printf(_(" -g, --allow-group-access allow group read/execute on data directory\n")); 2363 printf(_(" --locale=LOCALE set default locale for new databases\n")); 2364 printf(_(" --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" 2365 " --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n" 2366 " set default locale in the respective category for\n" 2367 " new databases (default taken from environment)\n")); 2368 printf(_(" --no-locale equivalent to --locale=C\n")); 2369 printf(_(" --pwfile=FILE read password for the new superuser from file\n")); 2370 printf(_(" -T, --text-search-config=CFG\n" 2371 " default text search configuration\n")); 2372 printf(_(" -U, --username=NAME database superuser name\n")); 2373 printf(_(" -W, --pwprompt prompt for a password for the new superuser\n")); 2374 printf(_(" -X, --waldir=WALDIR location for the write-ahead log directory\n")); 2375 printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n")); 2376 printf(_("\nLess commonly used options:\n")); 2377 printf(_(" -d, --debug generate lots of debugging output\n")); 2378 printf(_(" -k, --data-checksums use data page checksums\n")); 2379 printf(_(" -L DIRECTORY where to find the input files\n")); 2380 printf(_(" -n, --no-clean do not clean up after errors\n")); 2381 printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n")); 2382 printf(_(" -s, --show show internal settings\n")); 2383 printf(_(" -S, --sync-only only sync data directory\n")); 2384 printf(_("\nOther options:\n")); 2385 printf(_(" -V, --version output version information, then exit\n")); 2386 printf(_(" -?, --help show this help, then exit\n")); 2387 printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n" 2388 "is used.\n")); 2389 printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n")); 2390 } 2391 2392 static void 2393 check_authmethod_unspecified(const char **authmethod) 2394 { 2395 if (*authmethod == NULL) 2396 { 2397 authwarning = true; 2398 *authmethod = "trust"; 2399 } 2400 } 2401 2402 static void 2403 check_authmethod_valid(const char *authmethod, const char *const *valid_methods, const char *conntype) 2404 { 2405 const char *const *p; 2406 2407 for (p = valid_methods; *p; p++) 2408 { 2409 if (strcmp(authmethod, *p) == 0) 2410 return; 2411 /* with space = param */ 2412 if (strchr(authmethod, ' ')) 2413 if (strncmp(authmethod, *p, (authmethod - strchr(authmethod, ' '))) == 0) 2414 return; 2415 } 2416 2417 pg_log_error("invalid authentication method \"%s\" for \"%s\" connections", 2418 authmethod, conntype); 2419 exit(1); 2420 } 2421 2422 static void 2423 check_need_password(const char *authmethodlocal, const char *authmethodhost) 2424 { 2425 if ((strcmp(authmethodlocal, "md5") == 0 || 2426 strcmp(authmethodlocal, "password") == 0 || 2427 strcmp(authmethodlocal, "scram-sha-256") == 0) && 2428 (strcmp(authmethodhost, "md5") == 0 || 2429 strcmp(authmethodhost, "password") == 0 || 2430 strcmp(authmethodhost, "scram-sha-256") == 0) && 2431 !(pwprompt || pwfilename)) 2432 { 2433 pg_log_error("must specify a password for the superuser to enable %s authentication", 2434 (strcmp(authmethodlocal, "md5") == 0 || 2435 strcmp(authmethodlocal, "password") == 0 || 2436 strcmp(authmethodlocal, "scram-sha-256") == 0) 2437 ? authmethodlocal 2438 : authmethodhost); 2439 exit(1); 2440 } 2441 } 2442 2443 2444 void 2445 setup_pgdata(void) 2446 { 2447 char *pgdata_get_env, 2448 *pgdata_set_env; 2449 2450 if (!pg_data) 2451 { 2452 pgdata_get_env = getenv("PGDATA"); 2453 if (pgdata_get_env && strlen(pgdata_get_env)) 2454 { 2455 /* PGDATA found */ 2456 pg_data = pg_strdup(pgdata_get_env); 2457 } 2458 else 2459 { 2460 pg_log_error("no data directory specified"); 2461 fprintf(stderr, 2462 _("You must identify the directory where the data for this database system\n" 2463 "will reside. Do this with either the invocation option -D or the\n" 2464 "environment variable PGDATA.\n")); 2465 exit(1); 2466 } 2467 } 2468 2469 pgdata_native = pg_strdup(pg_data); 2470 canonicalize_path(pg_data); 2471 2472 /* 2473 * we have to set PGDATA for postgres rather than pass it on the command 2474 * line to avoid dumb quoting problems on Windows, and we would especially 2475 * need quotes otherwise on Windows because paths there are most likely to 2476 * have embedded spaces. 2477 */ 2478 pgdata_set_env = psprintf("PGDATA=%s", pg_data); 2479 putenv(pgdata_set_env); 2480 } 2481 2482 2483 void 2484 setup_bin_paths(const char *argv0) 2485 { 2486 int ret; 2487 2488 if ((ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR, 2489 backend_exec)) < 0) 2490 { 2491 char full_path[MAXPGPATH]; 2492 2493 if (find_my_exec(argv0, full_path) < 0) 2494 strlcpy(full_path, progname, sizeof(full_path)); 2495 2496 if (ret == -1) 2497 pg_log_error("The program \"postgres\" is needed by %s but was not found in the\n" 2498 "same directory as \"%s\".\n" 2499 "Check your installation.", 2500 progname, full_path); 2501 else 2502 pg_log_error("The program \"postgres\" was found by \"%s\"\n" 2503 "but was not the same version as %s.\n" 2504 "Check your installation.", 2505 full_path, progname); 2506 exit(1); 2507 } 2508 2509 /* store binary directory */ 2510 strcpy(bin_path, backend_exec); 2511 *last_dir_separator(bin_path) = '\0'; 2512 canonicalize_path(bin_path); 2513 2514 if (!share_path) 2515 { 2516 share_path = pg_malloc(MAXPGPATH); 2517 get_share_path(backend_exec, share_path); 2518 } 2519 else if (!is_absolute_path(share_path)) 2520 { 2521 pg_log_error("input file location must be an absolute path"); 2522 exit(1); 2523 } 2524 2525 canonicalize_path(share_path); 2526 } 2527 2528 void 2529 setup_locale_encoding(void) 2530 { 2531 setlocales(); 2532 2533 if (strcmp(lc_ctype, lc_collate) == 0 && 2534 strcmp(lc_ctype, lc_time) == 0 && 2535 strcmp(lc_ctype, lc_numeric) == 0 && 2536 strcmp(lc_ctype, lc_monetary) == 0 && 2537 strcmp(lc_ctype, lc_messages) == 0) 2538 printf(_("The database cluster will be initialized with locale \"%s\".\n"), lc_ctype); 2539 else 2540 { 2541 printf(_("The database cluster will be initialized with locales\n" 2542 " COLLATE: %s\n" 2543 " CTYPE: %s\n" 2544 " MESSAGES: %s\n" 2545 " MONETARY: %s\n" 2546 " NUMERIC: %s\n" 2547 " TIME: %s\n"), 2548 lc_collate, 2549 lc_ctype, 2550 lc_messages, 2551 lc_monetary, 2552 lc_numeric, 2553 lc_time); 2554 } 2555 2556 if (!encoding) 2557 { 2558 int ctype_enc; 2559 2560 ctype_enc = pg_get_encoding_from_locale(lc_ctype, true); 2561 2562 if (ctype_enc == -1) 2563 { 2564 /* Couldn't recognize the locale's codeset */ 2565 pg_log_error("could not find suitable encoding for locale \"%s\"", 2566 lc_ctype); 2567 fprintf(stderr, _("Rerun %s with the -E option.\n"), progname); 2568 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), 2569 progname); 2570 exit(1); 2571 } 2572 else if (!pg_valid_server_encoding_id(ctype_enc)) 2573 { 2574 /* 2575 * We recognized it, but it's not a legal server encoding. On 2576 * Windows, UTF-8 works with any locale, so we can fall back to 2577 * UTF-8. 2578 */ 2579 #ifdef WIN32 2580 encodingid = PG_UTF8; 2581 printf(_("Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" 2582 "The default database encoding will be set to \"%s\" instead.\n"), 2583 pg_encoding_to_char(ctype_enc), 2584 pg_encoding_to_char(encodingid)); 2585 #else 2586 pg_log_error("locale \"%s\" requires unsupported encoding \"%s\"", 2587 lc_ctype, pg_encoding_to_char(ctype_enc)); 2588 fprintf(stderr, 2589 _("Encoding \"%s\" is not allowed as a server-side encoding.\n" 2590 "Rerun %s with a different locale selection.\n"), 2591 pg_encoding_to_char(ctype_enc), progname); 2592 exit(1); 2593 #endif 2594 } 2595 else 2596 { 2597 encodingid = ctype_enc; 2598 printf(_("The default database encoding has accordingly been set to \"%s\".\n"), 2599 pg_encoding_to_char(encodingid)); 2600 } 2601 } 2602 else 2603 encodingid = get_encoding_id(encoding); 2604 2605 if (!check_locale_encoding(lc_ctype, encodingid) || 2606 !check_locale_encoding(lc_collate, encodingid)) 2607 exit(1); /* check_locale_encoding printed the error */ 2608 2609 } 2610 2611 2612 void 2613 setup_data_file_paths(void) 2614 { 2615 set_input(&bki_file, "postgres.bki"); 2616 set_input(&desc_file, "postgres.description"); 2617 set_input(&shdesc_file, "postgres.shdescription"); 2618 set_input(&hba_file, "pg_hba.conf.sample"); 2619 set_input(&ident_file, "pg_ident.conf.sample"); 2620 set_input(&conf_file, "postgresql.conf.sample"); 2621 set_input(&dictionary_file, "snowball_create.sql"); 2622 set_input(&info_schema_file, "information_schema.sql"); 2623 set_input(&features_file, "sql_features.txt"); 2624 set_input(&system_views_file, "system_views.sql"); 2625 2626 if (show_setting || debug) 2627 { 2628 fprintf(stderr, 2629 "VERSION=%s\n" 2630 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n" 2631 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n" 2632 "POSTGRES_DESCR=%s\nPOSTGRES_SHDESCR=%s\n" 2633 "POSTGRESQL_CONF_SAMPLE=%s\n" 2634 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n", 2635 PG_VERSION, 2636 pg_data, share_path, bin_path, 2637 username, bki_file, 2638 desc_file, shdesc_file, 2639 conf_file, 2640 hba_file, ident_file); 2641 if (show_setting) 2642 exit(0); 2643 } 2644 2645 check_input(bki_file); 2646 check_input(desc_file); 2647 check_input(shdesc_file); 2648 check_input(hba_file); 2649 check_input(ident_file); 2650 check_input(conf_file); 2651 check_input(dictionary_file); 2652 check_input(info_schema_file); 2653 check_input(features_file); 2654 check_input(system_views_file); 2655 } 2656 2657 2658 void 2659 setup_text_search(void) 2660 { 2661 if (!default_text_search_config) 2662 { 2663 default_text_search_config = find_matching_ts_config(lc_ctype); 2664 if (!default_text_search_config) 2665 { 2666 pg_log_info("could not find suitable text search configuration for locale \"%s\"", 2667 lc_ctype); 2668 default_text_search_config = "simple"; 2669 } 2670 } 2671 else 2672 { 2673 const char *checkmatch = find_matching_ts_config(lc_ctype); 2674 2675 if (checkmatch == NULL) 2676 { 2677 pg_log_warning("suitable text search configuration for locale \"%s\" is unknown", 2678 lc_ctype); 2679 } 2680 else if (strcmp(checkmatch, default_text_search_config) != 0) 2681 { 2682 pg_log_warning("specified text search configuration \"%s\" might not match locale \"%s\"", 2683 default_text_search_config, lc_ctype); 2684 } 2685 } 2686 2687 printf(_("The default text search configuration will be set to \"%s\".\n"), 2688 default_text_search_config); 2689 2690 } 2691 2692 2693 void 2694 setup_signals(void) 2695 { 2696 /* some of these are not valid on Windows */ 2697 #ifdef SIGHUP 2698 pqsignal(SIGHUP, trapsig); 2699 #endif 2700 #ifdef SIGINT 2701 pqsignal(SIGINT, trapsig); 2702 #endif 2703 #ifdef SIGQUIT 2704 pqsignal(SIGQUIT, trapsig); 2705 #endif 2706 #ifdef SIGTERM 2707 pqsignal(SIGTERM, trapsig); 2708 #endif 2709 2710 /* Ignore SIGPIPE when writing to backend, so we can clean up */ 2711 #ifdef SIGPIPE 2712 pqsignal(SIGPIPE, SIG_IGN); 2713 #endif 2714 2715 /* Prevent SIGSYS so we can probe for kernel calls that might not work */ 2716 #ifdef SIGSYS 2717 pqsignal(SIGSYS, SIG_IGN); 2718 #endif 2719 } 2720 2721 2722 void 2723 create_data_directory(void) 2724 { 2725 int ret; 2726 2727 switch ((ret = pg_check_dir(pg_data))) 2728 { 2729 case 0: 2730 /* PGDATA not there, must create it */ 2731 printf(_("creating directory %s ... "), 2732 pg_data); 2733 fflush(stdout); 2734 2735 if (pg_mkdir_p(pg_data, pg_dir_create_mode) != 0) 2736 { 2737 pg_log_error("could not create directory \"%s\": %m", pg_data); 2738 exit(1); 2739 } 2740 else 2741 check_ok(); 2742 2743 made_new_pgdata = true; 2744 break; 2745 2746 case 1: 2747 /* Present but empty, fix permissions and use it */ 2748 printf(_("fixing permissions on existing directory %s ... "), 2749 pg_data); 2750 fflush(stdout); 2751 2752 if (chmod(pg_data, pg_dir_create_mode) != 0) 2753 { 2754 pg_log_error("could not change permissions of directory \"%s\": %m", 2755 pg_data); 2756 exit(1); 2757 } 2758 else 2759 check_ok(); 2760 2761 found_existing_pgdata = true; 2762 break; 2763 2764 case 2: 2765 case 3: 2766 case 4: 2767 /* Present and not empty */ 2768 pg_log_error("directory \"%s\" exists but is not empty", pg_data); 2769 if (ret != 4) 2770 warn_on_mount_point(ret); 2771 else 2772 fprintf(stderr, 2773 _("If you want to create a new database system, either remove or empty\n" 2774 "the directory \"%s\" or run %s\n" 2775 "with an argument other than \"%s\".\n"), 2776 pg_data, progname, pg_data); 2777 exit(1); /* no further message needed */ 2778 2779 default: 2780 /* Trouble accessing directory */ 2781 pg_log_error("could not access directory \"%s\": %m", pg_data); 2782 exit(1); 2783 } 2784 } 2785 2786 2787 /* Create WAL directory, and symlink if required */ 2788 void 2789 create_xlog_or_symlink(void) 2790 { 2791 char *subdirloc; 2792 2793 /* form name of the place for the subdirectory or symlink */ 2794 subdirloc = psprintf("%s/pg_wal", pg_data); 2795 2796 if (xlog_dir) 2797 { 2798 int ret; 2799 2800 /* clean up xlog directory name, check it's absolute */ 2801 canonicalize_path(xlog_dir); 2802 if (!is_absolute_path(xlog_dir)) 2803 { 2804 pg_log_error("WAL directory location must be an absolute path"); 2805 exit(1); 2806 } 2807 2808 /* check if the specified xlog directory exists/is empty */ 2809 switch ((ret = pg_check_dir(xlog_dir))) 2810 { 2811 case 0: 2812 /* xlog directory not there, must create it */ 2813 printf(_("creating directory %s ... "), 2814 xlog_dir); 2815 fflush(stdout); 2816 2817 if (pg_mkdir_p(xlog_dir, pg_dir_create_mode) != 0) 2818 { 2819 pg_log_error("could not create directory \"%s\": %m", 2820 xlog_dir); 2821 exit(1); 2822 } 2823 else 2824 check_ok(); 2825 2826 made_new_xlogdir = true; 2827 break; 2828 2829 case 1: 2830 /* Present but empty, fix permissions and use it */ 2831 printf(_("fixing permissions on existing directory %s ... "), 2832 xlog_dir); 2833 fflush(stdout); 2834 2835 if (chmod(xlog_dir, pg_dir_create_mode) != 0) 2836 { 2837 pg_log_error("could not change permissions of directory \"%s\": %m", 2838 xlog_dir); 2839 exit(1); 2840 } 2841 else 2842 check_ok(); 2843 2844 found_existing_xlogdir = true; 2845 break; 2846 2847 case 2: 2848 case 3: 2849 case 4: 2850 /* Present and not empty */ 2851 pg_log_error("directory \"%s\" exists but is not empty", xlog_dir); 2852 if (ret != 4) 2853 warn_on_mount_point(ret); 2854 else 2855 fprintf(stderr, 2856 _("If you want to store the WAL there, either remove or empty the directory\n" 2857 "\"%s\".\n"), 2858 xlog_dir); 2859 exit(1); 2860 2861 default: 2862 /* Trouble accessing directory */ 2863 pg_log_error("could not access directory \"%s\": %m", xlog_dir); 2864 exit(1); 2865 } 2866 2867 #ifdef HAVE_SYMLINK 2868 if (symlink(xlog_dir, subdirloc) != 0) 2869 { 2870 pg_log_error("could not create symbolic link \"%s\": %m", 2871 subdirloc); 2872 exit(1); 2873 } 2874 #else 2875 pg_log_error("symlinks are not supported on this platform"); 2876 exit(1); 2877 #endif 2878 } 2879 else 2880 { 2881 /* Without -X option, just make the subdirectory normally */ 2882 if (mkdir(subdirloc, pg_dir_create_mode) < 0) 2883 { 2884 pg_log_error("could not create directory \"%s\": %m", 2885 subdirloc); 2886 exit(1); 2887 } 2888 } 2889 2890 free(subdirloc); 2891 } 2892 2893 2894 void 2895 warn_on_mount_point(int error) 2896 { 2897 if (error == 2) 2898 fprintf(stderr, 2899 _("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n")); 2900 else if (error == 3) 2901 fprintf(stderr, 2902 _("It contains a lost+found directory, perhaps due to it being a mount point.\n")); 2903 2904 fprintf(stderr, 2905 _("Using a mount point directly as the data directory is not recommended.\n" 2906 "Create a subdirectory under the mount point.\n")); 2907 } 2908 2909 2910 void 2911 initialize_data_directory(void) 2912 { 2913 PG_CMD_DECL; 2914 int i; 2915 2916 setup_signals(); 2917 2918 /* 2919 * Set mask based on requested PGDATA permissions. pg_mode_mask, and 2920 * friends like pg_dir_create_mode, are set to owner-only by default and 2921 * then updated if -g is passed in by calling SetDataDirectoryCreatePerm() 2922 * when parsing our options (see above). 2923 */ 2924 umask(pg_mode_mask); 2925 2926 create_data_directory(); 2927 2928 create_xlog_or_symlink(); 2929 2930 /* Create required subdirectories (other than pg_wal) */ 2931 printf(_("creating subdirectories ... ")); 2932 fflush(stdout); 2933 2934 for (i = 0; i < lengthof(subdirs); i++) 2935 { 2936 char *path; 2937 2938 path = psprintf("%s/%s", pg_data, subdirs[i]); 2939 2940 /* 2941 * The parent directory already exists, so we only need mkdir() not 2942 * pg_mkdir_p() here, which avoids some failure modes; cf bug #13853. 2943 */ 2944 if (mkdir(path, pg_dir_create_mode) < 0) 2945 { 2946 pg_log_error("could not create directory \"%s\": %m", path); 2947 exit(1); 2948 } 2949 2950 free(path); 2951 } 2952 2953 check_ok(); 2954 2955 /* Top level PG_VERSION is checked by bootstrapper, so make it first */ 2956 write_version_file(NULL); 2957 2958 /* Select suitable configuration settings */ 2959 set_null_conf(); 2960 test_config_settings(); 2961 2962 /* Now create all the text config files */ 2963 setup_config(); 2964 2965 /* Bootstrap template1 */ 2966 bootstrap_template1(); 2967 2968 /* 2969 * Make the per-database PG_VERSION for template1 only after init'ing it 2970 */ 2971 write_version_file("base/1"); 2972 2973 /* 2974 * Create the stuff we don't need to use bootstrap mode for, using a 2975 * backend running in simple standalone mode. 2976 */ 2977 fputs(_("performing post-bootstrap initialization ... "), stdout); 2978 fflush(stdout); 2979 2980 snprintf(cmd, sizeof(cmd), 2981 "\"%s\" %s template1 >%s", 2982 backend_exec, backend_options, 2983 DEVNULL); 2984 2985 PG_CMD_OPEN; 2986 2987 setup_auth(cmdfd); 2988 2989 setup_depend(cmdfd); 2990 2991 /* 2992 * Note that no objects created after setup_depend() will be "pinned". 2993 * They are all droppable at the whim of the DBA. 2994 */ 2995 2996 setup_sysviews(cmdfd); 2997 2998 setup_description(cmdfd); 2999 3000 setup_collation(cmdfd); 3001 3002 setup_dictionary(cmdfd); 3003 3004 setup_privileges(cmdfd); 3005 3006 setup_schema(cmdfd); 3007 3008 load_plpgsql(cmdfd); 3009 3010 vacuum_db(cmdfd); 3011 3012 make_template0(cmdfd); 3013 3014 make_postgres(cmdfd); 3015 3016 PG_CMD_CLOSE; 3017 3018 check_ok(); 3019 } 3020 3021 3022 int 3023 main(int argc, char *argv[]) 3024 { 3025 static struct option long_options[] = { 3026 {"pgdata", required_argument, NULL, 'D'}, 3027 {"encoding", required_argument, NULL, 'E'}, 3028 {"locale", required_argument, NULL, 1}, 3029 {"lc-collate", required_argument, NULL, 2}, 3030 {"lc-ctype", required_argument, NULL, 3}, 3031 {"lc-monetary", required_argument, NULL, 4}, 3032 {"lc-numeric", required_argument, NULL, 5}, 3033 {"lc-time", required_argument, NULL, 6}, 3034 {"lc-messages", required_argument, NULL, 7}, 3035 {"no-locale", no_argument, NULL, 8}, 3036 {"text-search-config", required_argument, NULL, 'T'}, 3037 {"auth", required_argument, NULL, 'A'}, 3038 {"auth-local", required_argument, NULL, 10}, 3039 {"auth-host", required_argument, NULL, 11}, 3040 {"pwprompt", no_argument, NULL, 'W'}, 3041 {"pwfile", required_argument, NULL, 9}, 3042 {"username", required_argument, NULL, 'U'}, 3043 {"help", no_argument, NULL, '?'}, 3044 {"version", no_argument, NULL, 'V'}, 3045 {"debug", no_argument, NULL, 'd'}, 3046 {"show", no_argument, NULL, 's'}, 3047 {"noclean", no_argument, NULL, 'n'}, /* for backwards compatibility */ 3048 {"no-clean", no_argument, NULL, 'n'}, 3049 {"nosync", no_argument, NULL, 'N'}, /* for backwards compatibility */ 3050 {"no-sync", no_argument, NULL, 'N'}, 3051 {"sync-only", no_argument, NULL, 'S'}, 3052 {"waldir", required_argument, NULL, 'X'}, 3053 {"wal-segsize", required_argument, NULL, 12}, 3054 {"data-checksums", no_argument, NULL, 'k'}, 3055 {"allow-group-access", no_argument, NULL, 'g'}, 3056 {NULL, 0, NULL, 0} 3057 }; 3058 3059 /* 3060 * options with no short version return a low integer, the rest return 3061 * their short version value 3062 */ 3063 int c; 3064 int option_index; 3065 char *effective_user; 3066 PQExpBuffer start_db_cmd; 3067 char pg_ctl_path[MAXPGPATH]; 3068 3069 /* 3070 * Ensure that buffering behavior of stdout matches what it is in 3071 * interactive usage (at least on most platforms). This prevents 3072 * unexpected output ordering when, eg, output is redirected to a file. 3073 * POSIX says we must do this before any other usage of these files. 3074 */ 3075 setvbuf(stdout, NULL, PG_IOLBF, 0); 3076 3077 pg_logging_init(argv[0]); 3078 progname = get_progname(argv[0]); 3079 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("initdb")); 3080 3081 if (argc > 1) 3082 { 3083 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) 3084 { 3085 usage(progname); 3086 exit(0); 3087 } 3088 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) 3089 { 3090 puts("initdb (PostgreSQL) " PG_VERSION); 3091 exit(0); 3092 } 3093 } 3094 3095 /* process command-line options */ 3096 3097 while ((c = getopt_long(argc, argv, "A:dD:E:gkL:nNsST:U:WX:", long_options, &option_index)) != -1) 3098 { 3099 switch (c) 3100 { 3101 case 'A': 3102 authmethodlocal = authmethodhost = pg_strdup(optarg); 3103 3104 /* 3105 * When ident is specified, use peer for local connections. 3106 * Mirrored, when peer is specified, use ident for TCP/IP 3107 * connections. 3108 */ 3109 if (strcmp(authmethodhost, "ident") == 0) 3110 authmethodlocal = "peer"; 3111 else if (strcmp(authmethodlocal, "peer") == 0) 3112 authmethodhost = "ident"; 3113 break; 3114 case 10: 3115 authmethodlocal = pg_strdup(optarg); 3116 break; 3117 case 11: 3118 authmethodhost = pg_strdup(optarg); 3119 break; 3120 case 'D': 3121 pg_data = pg_strdup(optarg); 3122 break; 3123 case 'E': 3124 encoding = pg_strdup(optarg); 3125 break; 3126 case 'W': 3127 pwprompt = true; 3128 break; 3129 case 'U': 3130 username = pg_strdup(optarg); 3131 break; 3132 case 'd': 3133 debug = true; 3134 printf(_("Running in debug mode.\n")); 3135 break; 3136 case 'n': 3137 noclean = true; 3138 printf(_("Running in no-clean mode. Mistakes will not be cleaned up.\n")); 3139 break; 3140 case 'N': 3141 do_sync = false; 3142 break; 3143 case 'S': 3144 sync_only = true; 3145 break; 3146 case 'k': 3147 data_checksums = true; 3148 break; 3149 case 'L': 3150 share_path = pg_strdup(optarg); 3151 break; 3152 case 1: 3153 locale = pg_strdup(optarg); 3154 break; 3155 case 2: 3156 lc_collate = pg_strdup(optarg); 3157 break; 3158 case 3: 3159 lc_ctype = pg_strdup(optarg); 3160 break; 3161 case 4: 3162 lc_monetary = pg_strdup(optarg); 3163 break; 3164 case 5: 3165 lc_numeric = pg_strdup(optarg); 3166 break; 3167 case 6: 3168 lc_time = pg_strdup(optarg); 3169 break; 3170 case 7: 3171 lc_messages = pg_strdup(optarg); 3172 break; 3173 case 8: 3174 locale = "C"; 3175 break; 3176 case 9: 3177 pwfilename = pg_strdup(optarg); 3178 break; 3179 case 's': 3180 show_setting = true; 3181 break; 3182 case 'T': 3183 default_text_search_config = pg_strdup(optarg); 3184 break; 3185 case 'X': 3186 xlog_dir = pg_strdup(optarg); 3187 break; 3188 case 12: 3189 str_wal_segment_size_mb = pg_strdup(optarg); 3190 break; 3191 case 'g': 3192 SetDataDirectoryCreatePerm(PG_DIR_MODE_GROUP); 3193 break; 3194 default: 3195 /* getopt_long already emitted a complaint */ 3196 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), 3197 progname); 3198 exit(1); 3199 } 3200 } 3201 3202 3203 /* 3204 * Non-option argument specifies data directory as long as it wasn't 3205 * already specified with -D / --pgdata 3206 */ 3207 if (optind < argc && !pg_data) 3208 { 3209 pg_data = pg_strdup(argv[optind]); 3210 optind++; 3211 } 3212 3213 if (optind < argc) 3214 { 3215 pg_log_error("too many command-line arguments (first is \"%s\")", 3216 argv[optind]); 3217 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), 3218 progname); 3219 exit(1); 3220 } 3221 3222 atexit(cleanup_directories_atexit); 3223 3224 /* If we only need to fsync, just do it and exit */ 3225 if (sync_only) 3226 { 3227 setup_pgdata(); 3228 3229 /* must check that directory is readable */ 3230 if (pg_check_dir(pg_data) <= 0) 3231 { 3232 pg_log_error("could not access directory \"%s\": %m", pg_data); 3233 exit(1); 3234 } 3235 3236 fputs(_("syncing data to disk ... "), stdout); 3237 fflush(stdout); 3238 fsync_pgdata(pg_data, PG_VERSION_NUM); 3239 check_ok(); 3240 return 0; 3241 } 3242 3243 if (pwprompt && pwfilename) 3244 { 3245 pg_log_error("password prompt and password file cannot be specified together"); 3246 exit(1); 3247 } 3248 3249 check_authmethod_unspecified(&authmethodlocal); 3250 check_authmethod_unspecified(&authmethodhost); 3251 3252 check_authmethod_valid(authmethodlocal, auth_methods_local, "local"); 3253 check_authmethod_valid(authmethodhost, auth_methods_host, "host"); 3254 3255 check_need_password(authmethodlocal, authmethodhost); 3256 3257 /* set wal segment size */ 3258 if (str_wal_segment_size_mb == NULL) 3259 wal_segment_size_mb = (DEFAULT_XLOG_SEG_SIZE) / (1024 * 1024); 3260 else 3261 { 3262 char *endptr; 3263 3264 /* check that the argument is a number */ 3265 wal_segment_size_mb = strtol(str_wal_segment_size_mb, &endptr, 10); 3266 3267 /* verify that wal segment size is valid */ 3268 if (endptr == str_wal_segment_size_mb || *endptr != '\0') 3269 { 3270 pg_log_error("argument of --wal-segsize must be a number"); 3271 exit(1); 3272 } 3273 if (!IsValidWalSegSize(wal_segment_size_mb * 1024 * 1024)) 3274 { 3275 pg_log_error("argument of --wal-segsize must be a power of 2 between 1 and 1024"); 3276 exit(1); 3277 } 3278 } 3279 3280 get_restricted_token(); 3281 3282 setup_pgdata(); 3283 3284 setup_bin_paths(argv[0]); 3285 3286 effective_user = get_id(); 3287 if (!username) 3288 username = effective_user; 3289 3290 if (strncmp(username, "pg_", 3) == 0) 3291 { 3292 pg_log_error("superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"", username); 3293 exit(1); 3294 } 3295 3296 printf(_("The files belonging to this database system will be owned " 3297 "by user \"%s\".\n" 3298 "This user must also own the server process.\n\n"), 3299 effective_user); 3300 3301 set_info_version(); 3302 3303 setup_data_file_paths(); 3304 3305 setup_locale_encoding(); 3306 3307 setup_text_search(); 3308 3309 printf("\n"); 3310 3311 if (data_checksums) 3312 printf(_("Data page checksums are enabled.\n")); 3313 else 3314 printf(_("Data page checksums are disabled.\n")); 3315 3316 if (pwprompt || pwfilename) 3317 get_su_pwd(); 3318 3319 printf("\n"); 3320 3321 initialize_data_directory(); 3322 3323 if (do_sync) 3324 { 3325 fputs(_("syncing data to disk ... "), stdout); 3326 fflush(stdout); 3327 fsync_pgdata(pg_data, PG_VERSION_NUM); 3328 check_ok(); 3329 } 3330 else 3331 printf(_("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n")); 3332 3333 if (authwarning) 3334 { 3335 printf("\n"); 3336 pg_log_warning("enabling \"trust\" authentication for local connections"); 3337 fprintf(stderr, _("You can change this by editing pg_hba.conf or using the option -A, or\n" 3338 "--auth-local and --auth-host, the next time you run initdb.\n")); 3339 } 3340 3341 /* 3342 * Build up a shell command to tell the user how to start the server 3343 */ 3344 start_db_cmd = createPQExpBuffer(); 3345 3346 /* Get directory specification used to start initdb ... */ 3347 strlcpy(pg_ctl_path, argv[0], sizeof(pg_ctl_path)); 3348 canonicalize_path(pg_ctl_path); 3349 get_parent_directory(pg_ctl_path); 3350 /* ... and tag on pg_ctl instead */ 3351 join_path_components(pg_ctl_path, pg_ctl_path, "pg_ctl"); 3352 3353 /* Convert the path to use native separators */ 3354 make_native_path(pg_ctl_path); 3355 3356 /* path to pg_ctl, properly quoted */ 3357 appendShellString(start_db_cmd, pg_ctl_path); 3358 3359 /* add -D switch, with properly quoted data directory */ 3360 appendPQExpBufferStr(start_db_cmd, " -D "); 3361 appendShellString(start_db_cmd, pgdata_native); 3362 3363 /* add suggested -l switch and "start" command */ 3364 /* translator: This is a placeholder in a shell command. */ 3365 appendPQExpBuffer(start_db_cmd, " -l %s start", _("logfile")); 3366 3367 printf(_("\nSuccess. You can now start the database server using:\n\n" 3368 " %s\n\n"), 3369 start_db_cmd->data); 3370 3371 destroyPQExpBuffer(start_db_cmd); 3372 3373 success = true; 3374 return 0; 3375 } 3376