00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "postgres_fe.h"
00050
00051 #include <dirent.h>
00052 #include <fcntl.h>
00053 #include <sys/stat.h>
00054 #include <unistd.h>
00055 #include <locale.h>
00056 #include <signal.h>
00057 #include <time.h>
00058
00059 #include "mb/pg_wchar.h"
00060 #include "getaddrinfo.h"
00061 #include "getopt_long.h"
00062 #include "miscadmin.h"
00063
00064
00065 extern const char *select_default_timezone(const char *share_path);
00066
00067 static const char *auth_methods_host[] = {"trust", "reject", "md5", "password", "ident", "radius",
00068 #ifdef ENABLE_GSS
00069 "gss",
00070 #endif
00071 #ifdef ENABLE_SSPI
00072 "sspi",
00073 #endif
00074 #ifdef KRB5
00075 "krb5",
00076 #endif
00077 #ifdef USE_PAM
00078 "pam", "pam ",
00079 #endif
00080 #ifdef USE_LDAP
00081 "ldap",
00082 #endif
00083 #ifdef USE_SSL
00084 "cert",
00085 #endif
00086 NULL};
00087 static const char *auth_methods_local[] = {"trust", "reject", "md5", "password", "peer", "radius",
00088 #ifdef USE_PAM
00089 "pam", "pam ",
00090 #endif
00091 #ifdef USE_LDAP
00092 "ldap",
00093 #endif
00094 NULL};
00095
00096
00097
00098
00099 static char *share_path = NULL;
00100
00101
00102 static char *pg_data = "";
00103 static char *encoding = "";
00104 static char *locale = "";
00105 static char *lc_collate = "";
00106 static char *lc_ctype = "";
00107 static char *lc_monetary = "";
00108 static char *lc_numeric = "";
00109 static char *lc_time = "";
00110 static char *lc_messages = "";
00111 static const char *default_text_search_config = "";
00112 static char *username = "";
00113 static bool pwprompt = false;
00114 static char *pwfilename = NULL;
00115 static const char *authmethodhost = "";
00116 static const char *authmethodlocal = "";
00117 static bool debug = false;
00118 static bool noclean = false;
00119 static bool do_sync = true;
00120 static bool sync_only = false;
00121 static bool show_setting = false;
00122 static bool data_checksums = false;
00123 static char *xlog_dir = "";
00124
00125
00126
00127 static const char *progname;
00128 static char *encodingid = "0";
00129 static char *bki_file;
00130 static char *desc_file;
00131 static char *shdesc_file;
00132 static char *hba_file;
00133 static char *ident_file;
00134 static char *conf_file;
00135 static char *conversion_file;
00136 static char *dictionary_file;
00137 static char *info_schema_file;
00138 static char *features_file;
00139 static char *system_views_file;
00140 static bool made_new_pgdata = false;
00141 static bool found_existing_pgdata = false;
00142 static bool made_new_xlogdir = false;
00143 static bool found_existing_xlogdir = false;
00144 static char infoversion[100];
00145 static bool caught_signal = false;
00146 static bool output_failed = false;
00147 static int output_errno = 0;
00148 static char *pgdata_native;
00149
00150
00151 static int n_connections = 10;
00152 static int n_buffers = 50;
00153
00154
00155
00156
00157 #define AUTHTRUST_WARNING \
00158 "# CAUTION: Configuring the system for local \"trust\" authentication\n" \
00159 "# allows any local user to connect as any PostgreSQL user, including\n" \
00160 "# the database superuser. If you do not trust all your local users,\n" \
00161 "# use another authentication method.\n"
00162 static char *authwarning = NULL;
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 static const char *boot_options = "-F";
00175 static const char *backend_options = "--single -F -O -c search_path=pg_catalog -c exit_on_error=true";
00176
00177 #ifdef WIN32
00178 char *restrict_env;
00179 #endif
00180 const char *subdirs[] = {
00181 "global",
00182 "pg_xlog",
00183 "pg_xlog/archive_status",
00184 "pg_clog",
00185 "pg_notify",
00186 "pg_serial",
00187 "pg_snapshots",
00188 "pg_subtrans",
00189 "pg_twophase",
00190 "pg_multixact/members",
00191 "pg_multixact/offsets",
00192 "base",
00193 "base/1",
00194 "pg_tblspc",
00195 "pg_stat",
00196 "pg_stat_tmp"
00197 };
00198
00199
00200
00201 static char bin_path[MAXPGPATH];
00202 static char backend_exec[MAXPGPATH];
00203
00204 static char **replace_token(char **lines,
00205 const char *token, const char *replacement);
00206
00207 #ifndef HAVE_UNIX_SOCKETS
00208 static char **filter_lines_with_token(char **lines, const char *token);
00209 #endif
00210 static char **readfile(const char *path);
00211 static void writefile(char *path, char **lines);
00212 static void walkdir(char *path, void (*action)(char *fname, bool isdir));
00213 static void pre_sync_fname(char *fname, bool isdir);
00214 static void fsync_fname(char *fname, bool isdir);
00215 static FILE *popen_check(const char *command, const char *mode);
00216 static void exit_nicely(void);
00217 static char *get_id(void);
00218 static char *get_encoding_id(char *encoding_name);
00219 static bool mkdatadir(const char *subdir);
00220 static void set_input(char **dest, char *filename);
00221 static void check_input(char *path);
00222 static void write_version_file(char *extrapath);
00223 static void set_null_conf(void);
00224 static void test_config_settings(void);
00225 static void setup_config(void);
00226 static void bootstrap_template1(void);
00227 static void setup_auth(void);
00228 static void get_set_pwd(void);
00229 static void setup_depend(void);
00230 static void setup_sysviews(void);
00231 static void setup_description(void);
00232 static void setup_collation(void);
00233 static void setup_conversion(void);
00234 static void setup_dictionary(void);
00235 static void setup_privileges(void);
00236 static void set_info_version(void);
00237 static void setup_schema(void);
00238 static void load_plpgsql(void);
00239 static void vacuum_db(void);
00240 static void make_template0(void);
00241 static void make_postgres(void);
00242 static void perform_fsync(void);
00243 static void trapsig(int signum);
00244 static void check_ok(void);
00245 static char *escape_quotes(const char *src);
00246 static int locale_date_order(const char *locale);
00247 static bool check_locale_name(int category, const char *locale,
00248 char **canonname);
00249 static bool check_locale_encoding(const char *locale, int encoding);
00250 static void setlocales(void);
00251 static void usage(const char *progname);
00252 void get_restricted_token(void);
00253 void setup_pgdata(void);
00254 void setup_bin_paths(const char *argv0);
00255 void setup_data_file_paths(void);
00256 void setup_locale_encoding(void);
00257 void setup_signals(void);
00258 void setup_text_search(void);
00259 void create_data_directory(void);
00260 void create_xlog_symlink(void);
00261 void warn_on_mount_point(int error);
00262 void initialize_data_directory(void);
00263
00264
00265 #ifdef WIN32
00266 static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
00267 #endif
00268
00269
00270
00271
00272
00273 #define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd
00274
00275 #define PG_CMD_OPEN \
00276 do { \
00277 cmdfd = popen_check(cmd, "w"); \
00278 if (cmdfd == NULL) \
00279 exit_nicely(); \
00280 } while (0)
00281
00282 #define PG_CMD_CLOSE \
00283 do { \
00284 if (pclose_check(cmdfd)) \
00285 exit_nicely(); \
00286 } while (0)
00287
00288 #define PG_CMD_PUTS(line) \
00289 do { \
00290 if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \
00291 output_failed = true, output_errno = errno; \
00292 } while (0)
00293
00294 #define PG_CMD_PRINTF1(fmt, arg1) \
00295 do { \
00296 if (fprintf(cmdfd, fmt, arg1) < 0 || fflush(cmdfd) < 0) \
00297 output_failed = true, output_errno = errno; \
00298 } while (0)
00299
00300 #define PG_CMD_PRINTF2(fmt, arg1, arg2) \
00301 do { \
00302 if (fprintf(cmdfd, fmt, arg1, arg2) < 0 || fflush(cmdfd) < 0) \
00303 output_failed = true, output_errno = errno; \
00304 } while (0)
00305
00306 #define PG_CMD_PRINTF3(fmt, arg1, arg2, arg3) \
00307 do { \
00308 if (fprintf(cmdfd, fmt, arg1, arg2, arg3) < 0 || fflush(cmdfd) < 0) \
00309 output_failed = true, output_errno = errno; \
00310 } while (0)
00311
00312 #ifndef WIN32
00313 #define QUOTE_PATH ""
00314 #define DIR_SEP "/"
00315 #else
00316 #define QUOTE_PATH "\""
00317 #define DIR_SEP "\\"
00318 #endif
00319
00320 static char *
00321 escape_quotes(const char *src)
00322 {
00323 char *result = escape_single_quotes_ascii(src);
00324 if (!result)
00325 {
00326 fprintf(stderr, _("%s: out of memory\n"), progname);
00327 exit(1);
00328 }
00329 return result;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339 static char **
00340 replace_token(char **lines, const char *token, const char *replacement)
00341 {
00342 int numlines = 1;
00343 int i;
00344 char **result;
00345 int toklen,
00346 replen,
00347 diff;
00348
00349 for (i = 0; lines[i]; i++)
00350 numlines++;
00351
00352 result = (char **) pg_malloc(numlines * sizeof(char *));
00353
00354 toklen = strlen(token);
00355 replen = strlen(replacement);
00356 diff = replen - toklen;
00357
00358 for (i = 0; i < numlines; i++)
00359 {
00360 char *where;
00361 char *newline;
00362 int pre;
00363
00364
00365 if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL)
00366 {
00367 result[i] = lines[i];
00368 continue;
00369 }
00370
00371
00372
00373 newline = (char *) pg_malloc(strlen(lines[i]) + diff + 1);
00374
00375 pre = where - lines[i];
00376
00377 strncpy(newline, lines[i], pre);
00378
00379 strcpy(newline + pre, replacement);
00380
00381 strcpy(newline + pre + replen, lines[i] + pre + toklen);
00382
00383 result[i] = newline;
00384 }
00385
00386 return result;
00387 }
00388
00389
00390
00391
00392
00393
00394 #ifndef HAVE_UNIX_SOCKETS
00395 static char **
00396 filter_lines_with_token(char **lines, const char *token)
00397 {
00398 int numlines = 1;
00399 int i,
00400 src,
00401 dst;
00402 char **result;
00403
00404 for (i = 0; lines[i]; i++)
00405 numlines++;
00406
00407 result = (char **) pg_malloc(numlines * sizeof(char *));
00408
00409 for (src = 0, dst = 0; src < numlines; src++)
00410 {
00411 if (lines[src] == NULL || strstr(lines[src], token) == NULL)
00412 result[dst++] = lines[src];
00413 }
00414
00415 return result;
00416 }
00417 #endif
00418
00419
00420
00421
00422 static char **
00423 readfile(const char *path)
00424 {
00425 FILE *infile;
00426 int maxlength = 1,
00427 linelen = 0;
00428 int nlines = 0;
00429 int n;
00430 char **result;
00431 char *buffer;
00432 int c;
00433
00434 if ((infile = fopen(path, "r")) == NULL)
00435 {
00436 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
00437 progname, path, strerror(errno));
00438 exit_nicely();
00439 }
00440
00441
00442
00443 while ((c = fgetc(infile)) != EOF)
00444 {
00445 linelen++;
00446 if (c == '\n')
00447 {
00448 nlines++;
00449 if (linelen > maxlength)
00450 maxlength = linelen;
00451 linelen = 0;
00452 }
00453 }
00454
00455
00456 if (linelen)
00457 nlines++;
00458 if (linelen > maxlength)
00459 maxlength = linelen;
00460
00461
00462 result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
00463 buffer = (char *) pg_malloc(maxlength + 1);
00464
00465
00466 rewind(infile);
00467 n = 0;
00468 while (fgets(buffer, maxlength + 1, infile) != NULL && n < nlines)
00469 result[n++] = pg_strdup(buffer);
00470
00471 fclose(infile);
00472 free(buffer);
00473 result[n] = NULL;
00474
00475 return result;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 static void
00485 writefile(char *path, char **lines)
00486 {
00487 FILE *out_file;
00488 char **line;
00489
00490 if ((out_file = fopen(path, "w")) == NULL)
00491 {
00492 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
00493 progname, path, strerror(errno));
00494 exit_nicely();
00495 }
00496 for (line = lines; *line != NULL; line++)
00497 {
00498 if (fputs(*line, out_file) < 0)
00499 {
00500 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
00501 progname, path, strerror(errno));
00502 exit_nicely();
00503 }
00504 free(*line);
00505 }
00506 if (fclose(out_file))
00507 {
00508 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
00509 progname, path, strerror(errno));
00510 exit_nicely();
00511 }
00512 }
00513
00514
00515
00516
00517
00518
00519
00520 static void
00521 walkdir(char *path, void (*action) (char *fname, bool isdir))
00522 {
00523 DIR *dir;
00524 struct dirent *direntry;
00525 char subpath[MAXPGPATH];
00526
00527 dir = opendir(path);
00528 if (dir == NULL)
00529 {
00530 fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
00531 progname, path, strerror(errno));
00532 exit_nicely();
00533 }
00534
00535 while (errno = 0, (direntry = readdir(dir)) != NULL)
00536 {
00537 struct stat fst;
00538
00539 if (strcmp(direntry->d_name, ".") == 0 ||
00540 strcmp(direntry->d_name, "..") == 0)
00541 continue;
00542
00543 snprintf(subpath, MAXPGPATH, "%s/%s", path, direntry->d_name);
00544
00545 if (lstat(subpath, &fst) < 0)
00546 {
00547 fprintf(stderr, _("%s: could not stat file \"%s\": %s\n"),
00548 progname, subpath, strerror(errno));
00549 exit_nicely();
00550 }
00551
00552 if (S_ISDIR(fst.st_mode))
00553 walkdir(subpath, action);
00554 else if (S_ISREG(fst.st_mode))
00555 (*action) (subpath, false);
00556 }
00557
00558 #ifdef WIN32
00559
00560
00561
00562
00563 if (GetLastError() == ERROR_NO_MORE_FILES)
00564 errno = 0;
00565 #endif
00566
00567 if (errno)
00568 {
00569 fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
00570 progname, path, strerror(errno));
00571 exit_nicely();
00572 }
00573
00574 closedir(dir);
00575
00576
00577
00578
00579
00580
00581
00582 (*action) (path, true);
00583 }
00584
00585
00586
00587
00588 static void
00589 pre_sync_fname(char *fname, bool isdir)
00590 {
00591 #if defined(HAVE_SYNC_FILE_RANGE) || \
00592 (defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED))
00593 int fd;
00594
00595 fd = open(fname, O_RDONLY | PG_BINARY);
00596
00597
00598
00599
00600
00601 if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
00602 return;
00603
00604 if (fd < 0)
00605 {
00606 fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
00607 progname, fname, strerror(errno));
00608 exit_nicely();
00609 }
00610
00611
00612
00613
00614
00615 #if defined(HAVE_SYNC_FILE_RANGE)
00616 sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE);
00617 #elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
00618 posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
00619 #endif
00620
00621 close(fd);
00622 #endif
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 static void
00634 fsync_fname(char *fname, bool isdir)
00635 {
00636 int fd;
00637 int returncode;
00638
00639
00640
00641
00642
00643
00644 if (!isdir)
00645 fd = open(fname, O_RDWR | PG_BINARY);
00646 else
00647 fd = open(fname, O_RDONLY | PG_BINARY);
00648
00649
00650
00651
00652
00653 if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
00654 return;
00655
00656 else if (fd < 0)
00657 {
00658 fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
00659 progname, fname, strerror(errno));
00660 exit_nicely();
00661 }
00662
00663 returncode = fsync(fd);
00664
00665
00666 if (returncode != 0 && isdir && errno == EBADF)
00667 {
00668 close(fd);
00669 return;
00670 }
00671
00672 if (returncode != 0)
00673 {
00674 fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
00675 progname, fname, strerror(errno));
00676 exit_nicely();
00677 }
00678
00679 close(fd);
00680 }
00681
00682
00683
00684
00685 static FILE *
00686 popen_check(const char *command, const char *mode)
00687 {
00688 FILE *cmdfd;
00689
00690 fflush(stdout);
00691 fflush(stderr);
00692 errno = 0;
00693 cmdfd = popen(command, mode);
00694 if (cmdfd == NULL)
00695 fprintf(stderr, _("%s: could not execute command \"%s\": %s\n"),
00696 progname, command, strerror(errno));
00697 return cmdfd;
00698 }
00699
00700
00701
00702
00703
00704 static void
00705 exit_nicely(void)
00706 {
00707 if (!noclean)
00708 {
00709 if (made_new_pgdata)
00710 {
00711 fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
00712 progname, pg_data);
00713 if (!rmtree(pg_data, true))
00714 fprintf(stderr, _("%s: failed to remove data directory\n"),
00715 progname);
00716 }
00717 else if (found_existing_pgdata)
00718 {
00719 fprintf(stderr,
00720 _("%s: removing contents of data directory \"%s\"\n"),
00721 progname, pg_data);
00722 if (!rmtree(pg_data, false))
00723 fprintf(stderr, _("%s: failed to remove contents of data directory\n"),
00724 progname);
00725 }
00726
00727 if (made_new_xlogdir)
00728 {
00729 fprintf(stderr, _("%s: removing transaction log directory \"%s\"\n"),
00730 progname, xlog_dir);
00731 if (!rmtree(xlog_dir, true))
00732 fprintf(stderr, _("%s: failed to remove transaction log directory\n"),
00733 progname);
00734 }
00735 else if (found_existing_xlogdir)
00736 {
00737 fprintf(stderr,
00738 _("%s: removing contents of transaction log directory \"%s\"\n"),
00739 progname, xlog_dir);
00740 if (!rmtree(xlog_dir, false))
00741 fprintf(stderr, _("%s: failed to remove contents of transaction log directory\n"),
00742 progname);
00743 }
00744
00745 }
00746 else
00747 {
00748 if (made_new_pgdata || found_existing_pgdata)
00749 fprintf(stderr,
00750 _("%s: data directory \"%s\" not removed at user's request\n"),
00751 progname, pg_data);
00752
00753 if (made_new_xlogdir || found_existing_xlogdir)
00754 fprintf(stderr,
00755 _("%s: transaction log directory \"%s\" not removed at user's request\n"),
00756 progname, xlog_dir);
00757 }
00758
00759 exit(1);
00760 }
00761
00762
00763
00764
00765
00766
00767 static char *
00768 get_id(void)
00769 {
00770 #ifndef WIN32
00771
00772 struct passwd *pw;
00773
00774 if (geteuid() == 0)
00775 {
00776 fprintf(stderr,
00777 _("%s: cannot be run as root\n"
00778 "Please log in (using, e.g., \"su\") as the "
00779 "(unprivileged) user that will\n"
00780 "own the server process.\n"),
00781 progname);
00782 exit(1);
00783 }
00784
00785 pw = getpwuid(geteuid());
00786 if (!pw)
00787 {
00788 fprintf(stderr,
00789 _("%s: could not obtain information about current user: %s\n"),
00790 progname, strerror(errno));
00791 exit(1);
00792 }
00793 #else
00794
00795 struct passwd_win32
00796 {
00797 int pw_uid;
00798 char pw_name[128];
00799 } pass_win32;
00800 struct passwd_win32 *pw = &pass_win32;
00801 DWORD pwname_size = sizeof(pass_win32.pw_name) - 1;
00802
00803 pw->pw_uid = 1;
00804 if (!GetUserName(pw->pw_name, &pwname_size))
00805 {
00806 fprintf(stderr, _("%s: could not get current user name: %s\n"),
00807 progname, strerror(errno));
00808 exit(1);
00809 }
00810 #endif
00811
00812 return pg_strdup(pw->pw_name);
00813 }
00814
00815 static char *
00816 encodingid_to_string(int enc)
00817 {
00818 char result[20];
00819
00820 sprintf(result, "%d", enc);
00821 return pg_strdup(result);
00822 }
00823
00824
00825
00826
00827 static char *
00828 get_encoding_id(char *encoding_name)
00829 {
00830 int enc;
00831
00832 if (encoding_name && *encoding_name)
00833 {
00834 if ((enc = pg_valid_server_encoding(encoding_name)) >= 0)
00835 return encodingid_to_string(enc);
00836 }
00837 fprintf(stderr, _("%s: \"%s\" is not a valid server encoding name\n"),
00838 progname, encoding_name ? encoding_name : "(null)");
00839 exit(1);
00840 }
00841
00842
00843
00844
00845
00846 struct tsearch_config_match
00847 {
00848 const char *tsconfname;
00849 const char *langname;
00850 };
00851
00852 static const struct tsearch_config_match tsearch_config_languages[] =
00853 {
00854 {"danish", "da"},
00855 {"danish", "Danish"},
00856 {"dutch", "nl"},
00857 {"dutch", "Dutch"},
00858 {"english", "C"},
00859 {"english", "POSIX"},
00860 {"english", "en"},
00861 {"english", "English"},
00862 {"finnish", "fi"},
00863 {"finnish", "Finnish"},
00864 {"french", "fr"},
00865 {"french", "French"},
00866 {"german", "de"},
00867 {"german", "German"},
00868 {"hungarian", "hu"},
00869 {"hungarian", "Hungarian"},
00870 {"italian", "it"},
00871 {"italian", "Italian"},
00872 {"norwegian", "no"},
00873 {"norwegian", "Norwegian"},
00874 {"portuguese", "pt"},
00875 {"portuguese", "Portuguese"},
00876 {"romanian", "ro"},
00877 {"russian", "ru"},
00878 {"russian", "Russian"},
00879 {"spanish", "es"},
00880 {"spanish", "Spanish"},
00881 {"swedish", "sv"},
00882 {"swedish", "Swedish"},
00883 {"turkish", "tr"},
00884 {"turkish", "Turkish"},
00885 {NULL, NULL}
00886 };
00887
00888
00889
00890
00891
00892 static const char *
00893 find_matching_ts_config(const char *lc_type)
00894 {
00895 int i;
00896 char *langname,
00897 *ptr;
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 if (lc_type == NULL)
00911 langname = pg_strdup("");
00912 else
00913 {
00914 ptr = langname = pg_strdup(lc_type);
00915 while (*ptr &&
00916 *ptr != '_' && *ptr != '-' && *ptr != '.' && *ptr != '@')
00917 ptr++;
00918 *ptr = '\0';
00919 }
00920
00921 for (i = 0; tsearch_config_languages[i].tsconfname; i++)
00922 {
00923 if (pg_strcasecmp(tsearch_config_languages[i].langname, langname) == 0)
00924 {
00925 free(langname);
00926 return tsearch_config_languages[i].tsconfname;
00927 }
00928 }
00929
00930 free(langname);
00931 return NULL;
00932 }
00933
00934
00935
00936
00937
00938 static bool
00939 mkdatadir(const char *subdir)
00940 {
00941 char *path;
00942
00943 path = pg_malloc(strlen(pg_data) + 2 +
00944 (subdir == NULL ? 0 : strlen(subdir)));
00945
00946 if (subdir != NULL)
00947 sprintf(path, "%s/%s", pg_data, subdir);
00948 else
00949 strcpy(path, pg_data);
00950
00951 if (pg_mkdir_p(path, S_IRWXU) == 0)
00952 return true;
00953
00954 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
00955 progname, path, strerror(errno));
00956
00957 return false;
00958 }
00959
00960
00961
00962
00963
00964 static void
00965 set_input(char **dest, char *filename)
00966 {
00967 *dest = pg_malloc(strlen(share_path) + strlen(filename) + 2);
00968 sprintf(*dest, "%s/%s", share_path, filename);
00969 }
00970
00971
00972
00973
00974 static void
00975 check_input(char *path)
00976 {
00977 struct stat statbuf;
00978
00979 if (stat(path, &statbuf) != 0)
00980 {
00981 if (errno == ENOENT)
00982 {
00983 fprintf(stderr,
00984 _("%s: file \"%s\" does not exist\n"), progname, path);
00985 fprintf(stderr,
00986 _("This might mean you have a corrupted installation or identified\n"
00987 "the wrong directory with the invocation option -L.\n"));
00988 }
00989 else
00990 {
00991 fprintf(stderr,
00992 _("%s: could not access file \"%s\": %s\n"), progname, path,
00993 strerror(errno));
00994 fprintf(stderr,
00995 _("This might mean you have a corrupted installation or identified\n"
00996 "the wrong directory with the invocation option -L.\n"));
00997 }
00998 exit(1);
00999 }
01000 if (!S_ISREG(statbuf.st_mode))
01001 {
01002 fprintf(stderr,
01003 _("%s: file \"%s\" is not a regular file\n"), progname, path);
01004 fprintf(stderr,
01005 _("This might mean you have a corrupted installation or identified\n"
01006 "the wrong directory with the invocation option -L.\n"));
01007 exit(1);
01008 }
01009 }
01010
01011
01012
01013
01014
01015 static void
01016 write_version_file(char *extrapath)
01017 {
01018 FILE *version_file;
01019 char *path;
01020
01021 if (extrapath == NULL)
01022 {
01023 path = pg_malloc(strlen(pg_data) + 12);
01024 sprintf(path, "%s/PG_VERSION", pg_data);
01025 }
01026 else
01027 {
01028 path = pg_malloc(strlen(pg_data) + strlen(extrapath) + 13);
01029 sprintf(path, "%s/%s/PG_VERSION", pg_data, extrapath);
01030 }
01031
01032 if ((version_file = fopen(path, PG_BINARY_W)) == NULL)
01033 {
01034 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
01035 progname, path, strerror(errno));
01036 exit_nicely();
01037 }
01038 if (fprintf(version_file, "%s\n", PG_MAJORVERSION) < 0 ||
01039 fclose(version_file))
01040 {
01041 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
01042 progname, path, strerror(errno));
01043 exit_nicely();
01044 }
01045 free(path);
01046 }
01047
01048
01049
01050
01051
01052 static void
01053 set_null_conf(void)
01054 {
01055 FILE *conf_file;
01056 char *path;
01057
01058 path = pg_malloc(strlen(pg_data) + 17);
01059 sprintf(path, "%s/postgresql.conf", pg_data);
01060 conf_file = fopen(path, PG_BINARY_W);
01061 if (conf_file == NULL)
01062 {
01063 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
01064 progname, path, strerror(errno));
01065 exit_nicely();
01066 }
01067 if (fclose(conf_file))
01068 {
01069 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
01070 progname, path, strerror(errno));
01071 exit_nicely();
01072 }
01073 free(path);
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083 static void
01084 test_config_settings(void)
01085 {
01086
01087
01088
01089
01090 #define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10)
01091
01092 static const int trial_conns[] = {
01093 100, 50, 40, 30, 20, 10
01094 };
01095 static const int trial_bufs[] = {
01096 16384, 8192, 4096, 3584, 3072, 2560, 2048, 1536,
01097 1000, 900, 800, 700, 600, 500,
01098 400, 300, 200, 100, 50
01099 };
01100
01101 char cmd[MAXPGPATH];
01102 const int connslen = sizeof(trial_conns) / sizeof(int);
01103 const int bufslen = sizeof(trial_bufs) / sizeof(int);
01104 int i,
01105 status,
01106 test_conns,
01107 test_buffs,
01108 ok_buffers = 0;
01109
01110
01111 printf(_("selecting default max_connections ... "));
01112 fflush(stdout);
01113
01114 for (i = 0; i < connslen; i++)
01115 {
01116 test_conns = trial_conns[i];
01117 test_buffs = MIN_BUFS_FOR_CONNS(test_conns);
01118
01119 snprintf(cmd, sizeof(cmd),
01120 SYSTEMQUOTE "\"%s\" --boot -x0 %s "
01121 "-c max_connections=%d "
01122 "-c shared_buffers=%d "
01123 "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
01124 backend_exec, boot_options,
01125 test_conns, test_buffs,
01126 DEVNULL, DEVNULL);
01127 status = system(cmd);
01128 if (status == 0)
01129 {
01130 ok_buffers = test_buffs;
01131 break;
01132 }
01133 }
01134 if (i >= connslen)
01135 i = connslen - 1;
01136 n_connections = trial_conns[i];
01137
01138 printf("%d\n", n_connections);
01139
01140 printf(_("selecting default shared_buffers ... "));
01141 fflush(stdout);
01142
01143 for (i = 0; i < bufslen; i++)
01144 {
01145
01146 test_buffs = (trial_bufs[i] * 8192) / BLCKSZ;
01147 if (test_buffs <= ok_buffers)
01148 {
01149 test_buffs = ok_buffers;
01150 break;
01151 }
01152
01153 snprintf(cmd, sizeof(cmd),
01154 SYSTEMQUOTE "\"%s\" --boot -x0 %s "
01155 "-c max_connections=%d "
01156 "-c shared_buffers=%d "
01157 "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
01158 backend_exec, boot_options,
01159 n_connections, test_buffs,
01160 DEVNULL, DEVNULL);
01161 status = system(cmd);
01162 if (status == 0)
01163 break;
01164 }
01165 n_buffers = test_buffs;
01166
01167 if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0)
01168 printf("%dMB\n", (n_buffers * (BLCKSZ / 1024)) / 1024);
01169 else
01170 printf("%dkB\n", n_buffers * (BLCKSZ / 1024));
01171 }
01172
01173
01174
01175
01176 static void
01177 setup_config(void)
01178 {
01179 char **conflines;
01180 char repltok[MAXPGPATH];
01181 char path[MAXPGPATH];
01182 const char *default_timezone;
01183
01184 fputs(_("creating configuration files ... "), stdout);
01185 fflush(stdout);
01186
01187
01188
01189 conflines = readfile(conf_file);
01190
01191 snprintf(repltok, sizeof(repltok), "max_connections = %d", n_connections);
01192 conflines = replace_token(conflines, "#max_connections = 100", repltok);
01193
01194 if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0)
01195 snprintf(repltok, sizeof(repltok), "shared_buffers = %dMB",
01196 (n_buffers * (BLCKSZ / 1024)) / 1024);
01197 else
01198 snprintf(repltok, sizeof(repltok), "shared_buffers = %dkB",
01199 n_buffers * (BLCKSZ / 1024));
01200 conflines = replace_token(conflines, "#shared_buffers = 32MB", repltok);
01201
01202 #ifdef HAVE_UNIX_SOCKETS
01203 snprintf(repltok, sizeof(repltok), "#unix_socket_directories = '%s'",
01204 DEFAULT_PGSOCKET_DIR);
01205 #else
01206 snprintf(repltok, sizeof(repltok), "#unix_socket_directories = ''");
01207 #endif
01208 conflines = replace_token(conflines, "#unix_socket_directories = '/tmp'",
01209 repltok);
01210
01211 #if DEF_PGPORT != 5432
01212 snprintf(repltok, sizeof(repltok), "#port = %d", DEF_PGPORT);
01213 conflines = replace_token(conflines, "#port = 5432", repltok);
01214 #endif
01215
01216 snprintf(repltok, sizeof(repltok), "lc_messages = '%s'",
01217 escape_quotes(lc_messages));
01218 conflines = replace_token(conflines, "#lc_messages = 'C'", repltok);
01219
01220 snprintf(repltok, sizeof(repltok), "lc_monetary = '%s'",
01221 escape_quotes(lc_monetary));
01222 conflines = replace_token(conflines, "#lc_monetary = 'C'", repltok);
01223
01224 snprintf(repltok, sizeof(repltok), "lc_numeric = '%s'",
01225 escape_quotes(lc_numeric));
01226 conflines = replace_token(conflines, "#lc_numeric = 'C'", repltok);
01227
01228 snprintf(repltok, sizeof(repltok), "lc_time = '%s'",
01229 escape_quotes(lc_time));
01230 conflines = replace_token(conflines, "#lc_time = 'C'", repltok);
01231
01232 switch (locale_date_order(lc_time))
01233 {
01234 case DATEORDER_YMD:
01235 strcpy(repltok, "datestyle = 'iso, ymd'");
01236 break;
01237 case DATEORDER_DMY:
01238 strcpy(repltok, "datestyle = 'iso, dmy'");
01239 break;
01240 case DATEORDER_MDY:
01241 default:
01242 strcpy(repltok, "datestyle = 'iso, mdy'");
01243 break;
01244 }
01245 conflines = replace_token(conflines, "#datestyle = 'iso, mdy'", repltok);
01246
01247 snprintf(repltok, sizeof(repltok),
01248 "default_text_search_config = 'pg_catalog.%s'",
01249 escape_quotes(default_text_search_config));
01250 conflines = replace_token(conflines,
01251 "#default_text_search_config = 'pg_catalog.simple'",
01252 repltok);
01253
01254 default_timezone = select_default_timezone(share_path);
01255 if (default_timezone)
01256 {
01257 snprintf(repltok, sizeof(repltok), "timezone = '%s'",
01258 escape_quotes(default_timezone));
01259 conflines = replace_token(conflines, "#timezone = 'GMT'", repltok);
01260 snprintf(repltok, sizeof(repltok), "log_timezone = '%s'",
01261 escape_quotes(default_timezone));
01262 conflines = replace_token(conflines, "#log_timezone = 'GMT'", repltok);
01263 }
01264
01265 snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
01266
01267 writefile(path, conflines);
01268 chmod(path, S_IRUSR | S_IWUSR);
01269
01270 free(conflines);
01271
01272
01273
01274
01275 conflines = readfile(hba_file);
01276
01277 #ifndef HAVE_UNIX_SOCKETS
01278 conflines = filter_lines_with_token(conflines, "@remove-line-for-nolocal@");
01279 #else
01280 conflines = replace_token(conflines, "@remove-line-for-nolocal@", "");
01281 #endif
01282
01283 #ifdef HAVE_IPV6
01284
01285
01286
01287
01288
01289
01290
01291
01292 {
01293 struct addrinfo *gai_result;
01294 struct addrinfo hints;
01295 int err = 0;
01296
01297 #ifdef WIN32
01298
01299 WSADATA wsaData;
01300
01301 err = WSAStartup(MAKEWORD(2, 2), &wsaData);
01302 #endif
01303
01304
01305 hints.ai_flags = AI_NUMERICHOST;
01306 hints.ai_family = PF_UNSPEC;
01307 hints.ai_socktype = 0;
01308 hints.ai_protocol = 0;
01309 hints.ai_addrlen = 0;
01310 hints.ai_canonname = NULL;
01311 hints.ai_addr = NULL;
01312 hints.ai_next = NULL;
01313
01314 if (err != 0 ||
01315 getaddrinfo("::1", NULL, &hints, &gai_result) != 0)
01316 conflines = replace_token(conflines,
01317 "host all all ::1",
01318 "#host all all ::1");
01319 }
01320 #else
01321
01322 conflines = replace_token(conflines,
01323 "host all all ::1",
01324 "#host all all ::1");
01325 #endif
01326
01327
01328 conflines = replace_token(conflines,
01329 "@authmethodhost@",
01330 authmethodhost);
01331 conflines = replace_token(conflines,
01332 "@authmethodlocal@",
01333 authmethodlocal);
01334
01335 conflines = replace_token(conflines,
01336 "@authcomment@",
01337 (strcmp(authmethodlocal, "trust") == 0 || strcmp(authmethodhost, "trust") == 0) ? AUTHTRUST_WARNING : "");
01338
01339
01340 conflines = replace_token(conflines,
01341 "@default_username@",
01342 username);
01343
01344 snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
01345
01346 writefile(path, conflines);
01347 chmod(path, S_IRUSR | S_IWUSR);
01348
01349 free(conflines);
01350
01351
01352
01353 conflines = readfile(ident_file);
01354
01355 snprintf(path, sizeof(path), "%s/pg_ident.conf", pg_data);
01356
01357 writefile(path, conflines);
01358 chmod(path, S_IRUSR | S_IWUSR);
01359
01360 free(conflines);
01361
01362 check_ok();
01363 }
01364
01365
01366
01367
01368
01369 static void
01370 bootstrap_template1(void)
01371 {
01372 PG_CMD_DECL;
01373 char **line;
01374 char *talkargs = "";
01375 char **bki_lines;
01376 char headerline[MAXPGPATH];
01377 char buf[64];
01378
01379 printf(_("creating template1 database in %s/base/1 ... "), pg_data);
01380 fflush(stdout);
01381
01382 if (debug)
01383 talkargs = "-d 5";
01384
01385 bki_lines = readfile(bki_file);
01386
01387
01388
01389 snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
01390 PG_MAJORVERSION);
01391
01392 if (strcmp(headerline, *bki_lines) != 0)
01393 {
01394 fprintf(stderr,
01395 _("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
01396 "Check your installation or specify the correct path "
01397 "using the option -L.\n"),
01398 progname, bki_file, PG_VERSION);
01399 exit_nicely();
01400 }
01401
01402
01403
01404 sprintf(buf, "%d", NAMEDATALEN);
01405 bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);
01406
01407 sprintf(buf, "%d", (int) sizeof(Pointer));
01408 bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf);
01409
01410 bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
01411 (sizeof(Pointer) == 4) ? "i" : "d");
01412
01413 bki_lines = replace_token(bki_lines, "FLOAT4PASSBYVAL",
01414 FLOAT4PASSBYVAL ? "true" : "false");
01415
01416 bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
01417 FLOAT8PASSBYVAL ? "true" : "false");
01418
01419 bki_lines = replace_token(bki_lines, "POSTGRES", escape_quotes(username));
01420
01421 bki_lines = replace_token(bki_lines, "ENCODING", encodingid);
01422
01423 bki_lines = replace_token(bki_lines, "LC_COLLATE", escape_quotes(lc_collate));
01424
01425 bki_lines = replace_token(bki_lines, "LC_CTYPE", escape_quotes(lc_ctype));
01426
01427
01428
01429
01430
01431
01432
01433 snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
01434 putenv(pg_strdup(cmd));
01435
01436 snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
01437 putenv(pg_strdup(cmd));
01438
01439 unsetenv("LC_ALL");
01440
01441
01442 unsetenv("PGCLIENTENCODING");
01443
01444 snprintf(cmd, sizeof(cmd),
01445 "\"%s\" --boot -x1 %s %s %s",
01446 backend_exec,
01447 data_checksums ? "-k" : "",
01448 boot_options, talkargs);
01449
01450 PG_CMD_OPEN;
01451
01452 for (line = bki_lines; *line != NULL; line++)
01453 {
01454 PG_CMD_PUTS(*line);
01455 free(*line);
01456 }
01457
01458 PG_CMD_CLOSE;
01459
01460 free(bki_lines);
01461
01462 check_ok();
01463 }
01464
01465
01466
01467
01468 static void
01469 setup_auth(void)
01470 {
01471 PG_CMD_DECL;
01472 const char **line;
01473 static const char *pg_authid_setup[] = {
01474
01475
01476
01477
01478 "REVOKE ALL on pg_authid FROM public;\n",
01479 NULL
01480 };
01481
01482 fputs(_("initializing pg_authid ... "), stdout);
01483 fflush(stdout);
01484
01485 snprintf(cmd, sizeof(cmd),
01486 "\"%s\" %s template1 >%s",
01487 backend_exec, backend_options,
01488 DEVNULL);
01489
01490 PG_CMD_OPEN;
01491
01492 for (line = pg_authid_setup; *line != NULL; line++)
01493 PG_CMD_PUTS(*line);
01494
01495 PG_CMD_CLOSE;
01496
01497 check_ok();
01498 }
01499
01500
01501
01502
01503 static void
01504 get_set_pwd(void)
01505 {
01506 PG_CMD_DECL;
01507
01508 char *pwd1,
01509 *pwd2;
01510
01511 if (pwprompt)
01512 {
01513
01514
01515
01516 pwd1 = simple_prompt("Enter new superuser password: ", 100, false);
01517 pwd2 = simple_prompt("Enter it again: ", 100, false);
01518 if (strcmp(pwd1, pwd2) != 0)
01519 {
01520 fprintf(stderr, _("Passwords didn't match.\n"));
01521 exit_nicely();
01522 }
01523 free(pwd2);
01524 }
01525 else
01526 {
01527
01528
01529
01530
01531
01532
01533
01534
01535 FILE *pwf = fopen(pwfilename, "r");
01536 char pwdbuf[MAXPGPATH];
01537 int i;
01538
01539 if (!pwf)
01540 {
01541 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
01542 progname, pwfilename, strerror(errno));
01543 exit_nicely();
01544 }
01545 if (!fgets(pwdbuf, sizeof(pwdbuf), pwf))
01546 {
01547 fprintf(stderr, _("%s: could not read password from file \"%s\": %s\n"),
01548 progname, pwfilename, strerror(errno));
01549 exit_nicely();
01550 }
01551 fclose(pwf);
01552
01553 i = strlen(pwdbuf);
01554 while (i > 0 && (pwdbuf[i - 1] == '\r' || pwdbuf[i - 1] == '\n'))
01555 pwdbuf[--i] = '\0';
01556
01557 pwd1 = pg_strdup(pwdbuf);
01558
01559 }
01560 printf(_("setting password ... "));
01561 fflush(stdout);
01562
01563 snprintf(cmd, sizeof(cmd),
01564 "\"%s\" %s template1 >%s",
01565 backend_exec, backend_options,
01566 DEVNULL);
01567
01568 PG_CMD_OPEN;
01569
01570 PG_CMD_PRINTF2("ALTER USER \"%s\" WITH PASSWORD E'%s';\n",
01571 username, escape_quotes(pwd1));
01572
01573
01574 free(pwd1);
01575
01576 PG_CMD_CLOSE;
01577
01578 check_ok();
01579 }
01580
01581
01582
01583
01584 static void
01585 setup_depend(void)
01586 {
01587 PG_CMD_DECL;
01588 const char **line;
01589 static const char *pg_depend_setup[] = {
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604 "DELETE FROM pg_depend;\n",
01605 "VACUUM pg_depend;\n",
01606 "DELETE FROM pg_shdepend;\n",
01607 "VACUUM pg_shdepend;\n",
01608
01609 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01610 " FROM pg_class;\n",
01611 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01612 " FROM pg_proc;\n",
01613 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01614 " FROM pg_type;\n",
01615 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01616 " FROM pg_cast;\n",
01617 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01618 " FROM pg_constraint;\n",
01619 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01620 " FROM pg_attrdef;\n",
01621 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01622 " FROM pg_language;\n",
01623 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01624 " FROM pg_operator;\n",
01625 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01626 " FROM pg_opclass;\n",
01627 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01628 " FROM pg_opfamily;\n",
01629 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01630 " FROM pg_amop;\n",
01631 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01632 " FROM pg_amproc;\n",
01633 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01634 " FROM pg_rewrite;\n",
01635 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01636 " FROM pg_trigger;\n",
01637
01638
01639
01640
01641 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01642 " FROM pg_namespace "
01643 " WHERE nspname LIKE 'pg%';\n",
01644
01645 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01646 " FROM pg_ts_parser;\n",
01647 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01648 " FROM pg_ts_dict;\n",
01649 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01650 " FROM pg_ts_template;\n",
01651 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01652 " FROM pg_ts_config;\n",
01653 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
01654 " FROM pg_collation;\n",
01655 "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' "
01656 " FROM pg_authid;\n",
01657 NULL
01658 };
01659
01660 fputs(_("initializing dependencies ... "), stdout);
01661 fflush(stdout);
01662
01663 snprintf(cmd, sizeof(cmd),
01664 "\"%s\" %s template1 >%s",
01665 backend_exec, backend_options,
01666 DEVNULL);
01667
01668 PG_CMD_OPEN;
01669
01670 for (line = pg_depend_setup; *line != NULL; line++)
01671 PG_CMD_PUTS(*line);
01672
01673 PG_CMD_CLOSE;
01674
01675 check_ok();
01676 }
01677
01678
01679
01680
01681 static void
01682 setup_sysviews(void)
01683 {
01684 PG_CMD_DECL;
01685 char **line;
01686 char **sysviews_setup;
01687
01688 fputs(_("creating system views ... "), stdout);
01689 fflush(stdout);
01690
01691 sysviews_setup = readfile(system_views_file);
01692
01693
01694
01695
01696 snprintf(cmd, sizeof(cmd),
01697 "\"%s\" %s -j template1 >%s",
01698 backend_exec, backend_options,
01699 DEVNULL);
01700
01701 PG_CMD_OPEN;
01702
01703 for (line = sysviews_setup; *line != NULL; line++)
01704 {
01705 PG_CMD_PUTS(*line);
01706 free(*line);
01707 }
01708
01709 PG_CMD_CLOSE;
01710
01711 free(sysviews_setup);
01712
01713 check_ok();
01714 }
01715
01716
01717
01718
01719 static void
01720 setup_description(void)
01721 {
01722 PG_CMD_DECL;
01723
01724 fputs(_("loading system objects' descriptions ... "), stdout);
01725 fflush(stdout);
01726
01727 snprintf(cmd, sizeof(cmd),
01728 "\"%s\" %s template1 >%s",
01729 backend_exec, backend_options,
01730 DEVNULL);
01731
01732 PG_CMD_OPEN;
01733
01734 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( "
01735 " objoid oid, "
01736 " classname name, "
01737 " objsubid int4, "
01738 " description text) WITHOUT OIDS;\n");
01739
01740 PG_CMD_PRINTF1("COPY tmp_pg_description FROM E'%s';\n",
01741 escape_quotes(desc_file));
01742
01743 PG_CMD_PUTS("INSERT INTO pg_description "
01744 " SELECT t.objoid, c.oid, t.objsubid, t.description "
01745 " FROM tmp_pg_description t, pg_class c "
01746 " WHERE c.relname = t.classname;\n");
01747
01748 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_shdescription ( "
01749 " objoid oid, "
01750 " classname name, "
01751 " description text) WITHOUT OIDS;\n");
01752
01753 PG_CMD_PRINTF1("COPY tmp_pg_shdescription FROM E'%s';\n",
01754 escape_quotes(shdesc_file));
01755
01756 PG_CMD_PUTS("INSERT INTO pg_shdescription "
01757 " SELECT t.objoid, c.oid, t.description "
01758 " FROM tmp_pg_shdescription t, pg_class c "
01759 " WHERE c.relname = t.classname;\n");
01760
01761
01762 PG_CMD_PUTS("WITH funcdescs AS ( "
01763 "SELECT p.oid as p_oid, oprname, "
01764 "coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc "
01765 "FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) "
01766 "INSERT INTO pg_description "
01767 " SELECT p_oid, 'pg_proc'::regclass, 0, "
01768 " 'implementation of ' || oprname || ' operator' "
01769 " FROM funcdescs "
01770 " WHERE opdesc NOT LIKE 'deprecated%' AND "
01771 " NOT EXISTS (SELECT 1 FROM pg_description "
01772 " WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass);\n");
01773
01774 PG_CMD_CLOSE;
01775
01776 check_ok();
01777 }
01778
01779 #ifdef HAVE_LOCALE_T
01780
01781
01782
01783
01784
01785
01786 static bool
01787 normalize_locale_name(char *new, const char *old)
01788 {
01789 char *n = new;
01790 const char *o = old;
01791 bool changed = false;
01792
01793 while (*o)
01794 {
01795 if (*o == '.')
01796 {
01797
01798 o++;
01799 while ((*o >= 'A' && *o <= 'Z')
01800 || (*o >= 'a' && *o <= 'z')
01801 || (*o >= '0' && *o <= '9')
01802 || (*o == '-'))
01803 o++;
01804 changed = true;
01805 }
01806 else
01807 *n++ = *o++;
01808 }
01809 *n = '\0';
01810
01811 return changed;
01812 }
01813 #endif
01814
01815
01816
01817
01818 static void
01819 setup_collation(void)
01820 {
01821 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
01822 int i;
01823 FILE *locale_a_handle;
01824 char localebuf[NAMEDATALEN];
01825 int count = 0;
01826
01827 PG_CMD_DECL;
01828 #endif
01829
01830 fputs(_("creating collations ... "), stdout);
01831 fflush(stdout);
01832
01833 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
01834 snprintf(cmd, sizeof(cmd),
01835 "\"%s\" %s template1 >%s",
01836 backend_exec, backend_options,
01837 DEVNULL);
01838
01839 locale_a_handle = popen_check("locale -a", "r");
01840 if (!locale_a_handle)
01841 return;
01842
01843 PG_CMD_OPEN;
01844
01845 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_collation ( "
01846 " collname name, "
01847 " locale name, "
01848 " encoding int) WITHOUT OIDS;\n");
01849
01850 while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
01851 {
01852 size_t len;
01853 int enc;
01854 bool skip;
01855 char *quoted_locale;
01856 char alias[NAMEDATALEN];
01857
01858 len = strlen(localebuf);
01859
01860 if (len == 0 || localebuf[len - 1] != '\n')
01861 {
01862 if (debug)
01863 fprintf(stderr, _("%s: locale name too long, skipped: \"%s\"\n"),
01864 progname, localebuf);
01865 continue;
01866 }
01867 localebuf[len - 1] = '\0';
01868
01869
01870
01871
01872
01873
01874
01875
01876 skip = false;
01877 for (i = 0; i < len; i++)
01878 {
01879 if (IS_HIGHBIT_SET(localebuf[i]))
01880 {
01881 skip = true;
01882 break;
01883 }
01884 }
01885 if (skip)
01886 {
01887 if (debug)
01888 fprintf(stderr, _("%s: locale name has non-ASCII characters, skipped: \"%s\"\n"),
01889 progname, localebuf);
01890 continue;
01891 }
01892
01893 enc = pg_get_encoding_from_locale(localebuf, debug);
01894 if (enc < 0)
01895 {
01896
01897 continue;
01898 }
01899 if (!PG_VALID_BE_ENCODING(enc))
01900 continue;
01901 if (enc == PG_SQL_ASCII)
01902 continue;
01903
01904 count++;
01905
01906 quoted_locale = escape_quotes(localebuf);
01907
01908 PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation VALUES (E'%s', E'%s', %d);\n",
01909 quoted_locale, quoted_locale, enc);
01910
01911
01912
01913
01914
01915
01916 if (normalize_locale_name(alias, localebuf))
01917 PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation VALUES (E'%s', E'%s', %d);\n",
01918 escape_quotes(alias), quoted_locale, enc);
01919 }
01920
01921
01922 PG_CMD_PRINTF1("INSERT INTO tmp_pg_collation VALUES ('ucs_basic', 'C', %d);\n", PG_UTF8);
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 PG_CMD_PUTS("INSERT INTO pg_collation (collname, collnamespace, collowner, collencoding, collcollate, collctype) "
01936 " SELECT DISTINCT ON (collname, encoding)"
01937 " collname, "
01938 " (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') AS collnamespace, "
01939 " (SELECT relowner FROM pg_class WHERE relname = 'pg_collation') AS collowner, "
01940 " encoding, locale, locale "
01941 " FROM tmp_pg_collation"
01942 " WHERE NOT EXISTS (SELECT 1 FROM pg_collation WHERE collname = tmp_pg_collation.collname)"
01943 " ORDER BY collname, encoding, (collname = locale) DESC, locale;\n");
01944
01945 pclose(locale_a_handle);
01946 PG_CMD_CLOSE;
01947
01948 check_ok();
01949 if (count == 0 && !debug)
01950 {
01951 printf(_("No usable system locales were found.\n"));
01952 printf(_("Use the option \"--debug\" to see details.\n"));
01953 }
01954 #else
01955 printf(_("not supported on this platform\n"));
01956 fflush(stdout);
01957 #endif
01958 }
01959
01960
01961
01962
01963 static void
01964 setup_conversion(void)
01965 {
01966 PG_CMD_DECL;
01967 char **line;
01968 char **conv_lines;
01969
01970 fputs(_("creating conversions ... "), stdout);
01971 fflush(stdout);
01972
01973 snprintf(cmd, sizeof(cmd),
01974 "\"%s\" %s template1 >%s",
01975 backend_exec, backend_options,
01976 DEVNULL);
01977
01978 PG_CMD_OPEN;
01979
01980 conv_lines = readfile(conversion_file);
01981 for (line = conv_lines; *line != NULL; line++)
01982 {
01983 if (strstr(*line, "DROP CONVERSION") != *line)
01984 PG_CMD_PUTS(*line);
01985 free(*line);
01986 }
01987
01988 free(conv_lines);
01989
01990 PG_CMD_CLOSE;
01991
01992 check_ok();
01993 }
01994
01995
01996
01997
01998 static void
01999 setup_dictionary(void)
02000 {
02001 PG_CMD_DECL;
02002 char **line;
02003 char **conv_lines;
02004
02005 fputs(_("creating dictionaries ... "), stdout);
02006 fflush(stdout);
02007
02008
02009
02010
02011 snprintf(cmd, sizeof(cmd),
02012 "\"%s\" %s -j template1 >%s",
02013 backend_exec, backend_options,
02014 DEVNULL);
02015
02016 PG_CMD_OPEN;
02017
02018 conv_lines = readfile(dictionary_file);
02019 for (line = conv_lines; *line != NULL; line++)
02020 {
02021 PG_CMD_PUTS(*line);
02022 free(*line);
02023 }
02024
02025 free(conv_lines);
02026
02027 PG_CMD_CLOSE;
02028
02029 check_ok();
02030 }
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043 static void
02044 setup_privileges(void)
02045 {
02046 PG_CMD_DECL;
02047 char **line;
02048 char **priv_lines;
02049 static char *privileges_setup[] = {
02050 "UPDATE pg_class "
02051 " SET relacl = E'{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
02052 " WHERE relkind IN ('r', 'v', 'm', 'S') AND relacl IS NULL;\n",
02053 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n",
02054 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n",
02055 "REVOKE ALL ON pg_largeobject FROM PUBLIC;\n",
02056 NULL
02057 };
02058
02059 fputs(_("setting privileges on built-in objects ... "), stdout);
02060 fflush(stdout);
02061
02062 snprintf(cmd, sizeof(cmd),
02063 "\"%s\" %s template1 >%s",
02064 backend_exec, backend_options,
02065 DEVNULL);
02066
02067 PG_CMD_OPEN;
02068
02069 priv_lines = replace_token(privileges_setup, "$POSTGRES_SUPERUSERNAME",
02070 escape_quotes(username));
02071 for (line = priv_lines; *line != NULL; line++)
02072 PG_CMD_PUTS(*line);
02073
02074 PG_CMD_CLOSE;
02075
02076 check_ok();
02077 }
02078
02079
02080
02081
02082
02083 static void
02084 set_info_version(void)
02085 {
02086 char *letterversion;
02087 long major = 0,
02088 minor = 0,
02089 micro = 0;
02090 char *endptr;
02091 char *vstr = pg_strdup(PG_VERSION);
02092 char *ptr;
02093
02094 ptr = vstr + (strlen(vstr) - 1);
02095 while (ptr != vstr && (*ptr < '0' || *ptr > '9'))
02096 ptr--;
02097 letterversion = ptr + 1;
02098 major = strtol(vstr, &endptr, 10);
02099 if (*endptr)
02100 minor = strtol(endptr + 1, &endptr, 10);
02101 if (*endptr)
02102 micro = strtol(endptr + 1, &endptr, 10);
02103 snprintf(infoversion, sizeof(infoversion), "%02ld.%02ld.%04ld%s",
02104 major, minor, micro, letterversion);
02105 }
02106
02107
02108
02109
02110 static void
02111 setup_schema(void)
02112 {
02113 PG_CMD_DECL;
02114 char **line;
02115 char **lines;
02116
02117 fputs(_("creating information schema ... "), stdout);
02118 fflush(stdout);
02119
02120 lines = readfile(info_schema_file);
02121
02122
02123
02124
02125 snprintf(cmd, sizeof(cmd),
02126 "\"%s\" %s -j template1 >%s",
02127 backend_exec, backend_options,
02128 DEVNULL);
02129
02130 PG_CMD_OPEN;
02131
02132 for (line = lines; *line != NULL; line++)
02133 {
02134 PG_CMD_PUTS(*line);
02135 free(*line);
02136 }
02137
02138 free(lines);
02139
02140 PG_CMD_CLOSE;
02141
02142 snprintf(cmd, sizeof(cmd),
02143 "\"%s\" %s template1 >%s",
02144 backend_exec, backend_options,
02145 DEVNULL);
02146
02147 PG_CMD_OPEN;
02148
02149 PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info "
02150 " SET character_value = '%s' "
02151 " WHERE implementation_info_name = 'DBMS VERSION';\n",
02152 infoversion);
02153
02154 PG_CMD_PRINTF1("COPY information_schema.sql_features "
02155 " (feature_id, feature_name, sub_feature_id, "
02156 " sub_feature_name, is_supported, comments) "
02157 " FROM E'%s';\n",
02158 escape_quotes(features_file));
02159
02160 PG_CMD_CLOSE;
02161
02162 check_ok();
02163 }
02164
02165
02166
02167
02168 static void
02169 load_plpgsql(void)
02170 {
02171 PG_CMD_DECL;
02172
02173 fputs(_("loading PL/pgSQL server-side language ... "), stdout);
02174 fflush(stdout);
02175
02176 snprintf(cmd, sizeof(cmd),
02177 "\"%s\" %s template1 >%s",
02178 backend_exec, backend_options,
02179 DEVNULL);
02180
02181 PG_CMD_OPEN;
02182
02183 PG_CMD_PUTS("CREATE EXTENSION plpgsql;\n");
02184
02185 PG_CMD_CLOSE;
02186
02187 check_ok();
02188 }
02189
02190
02191
02192
02193 static void
02194 vacuum_db(void)
02195 {
02196 PG_CMD_DECL;
02197
02198 fputs(_("vacuuming database template1 ... "), stdout);
02199 fflush(stdout);
02200
02201 snprintf(cmd, sizeof(cmd),
02202 "\"%s\" %s template1 >%s",
02203 backend_exec, backend_options,
02204 DEVNULL);
02205
02206 PG_CMD_OPEN;
02207
02208 PG_CMD_PUTS("ANALYZE;\nVACUUM FULL;\nVACUUM FREEZE;\n");
02209
02210 PG_CMD_CLOSE;
02211
02212 check_ok();
02213 }
02214
02215
02216
02217
02218 static void
02219 make_template0(void)
02220 {
02221 PG_CMD_DECL;
02222 const char **line;
02223 static const char *template0_setup[] = {
02224 "CREATE DATABASE template0;\n",
02225 "UPDATE pg_database SET "
02226 " datistemplate = 't', "
02227 " datallowconn = 'f' "
02228 " WHERE datname = 'template0';\n",
02229
02230
02231
02232
02233 "UPDATE pg_database SET datlastsysoid = "
02234 " (SELECT oid FROM pg_database "
02235 " WHERE datname = 'template0');\n",
02236
02237
02238
02239
02240
02241
02242 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n",
02243 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n",
02244
02245 "COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n",
02246
02247
02248
02249
02250 "VACUUM FULL pg_database;\n",
02251 NULL
02252 };
02253
02254 fputs(_("copying template1 to template0 ... "), stdout);
02255 fflush(stdout);
02256
02257 snprintf(cmd, sizeof(cmd),
02258 "\"%s\" %s template1 >%s",
02259 backend_exec, backend_options,
02260 DEVNULL);
02261
02262 PG_CMD_OPEN;
02263
02264 for (line = template0_setup; *line; line++)
02265 PG_CMD_PUTS(*line);
02266
02267 PG_CMD_CLOSE;
02268
02269 check_ok();
02270 }
02271
02272
02273
02274
02275 static void
02276 make_postgres(void)
02277 {
02278 PG_CMD_DECL;
02279 const char **line;
02280 static const char *postgres_setup[] = {
02281 "CREATE DATABASE postgres;\n",
02282 "COMMENT ON DATABASE postgres IS 'default administrative connection database';\n",
02283 NULL
02284 };
02285
02286 fputs(_("copying template1 to postgres ... "), stdout);
02287 fflush(stdout);
02288
02289 snprintf(cmd, sizeof(cmd),
02290 "\"%s\" %s template1 >%s",
02291 backend_exec, backend_options,
02292 DEVNULL);
02293
02294 PG_CMD_OPEN;
02295
02296 for (line = postgres_setup; *line; line++)
02297 PG_CMD_PUTS(*line);
02298
02299 PG_CMD_CLOSE;
02300
02301 check_ok();
02302 }
02303
02304
02305
02306
02307 static void
02308 perform_fsync(void)
02309 {
02310 char pdir[MAXPGPATH];
02311
02312 fputs(_("syncing data to disk ... "), stdout);
02313 fflush(stdout);
02314
02315
02316
02317
02318
02319 snprintf(pdir, MAXPGPATH, "%s/..", pg_data);
02320 canonicalize_path(pdir);
02321
02322
02323
02324
02325
02326
02327 pre_sync_fname(pdir, true);
02328
02329
02330 walkdir(pg_data, pre_sync_fname);
02331
02332
02333
02334
02335
02336
02337 fsync_fname(pdir, true);
02338
02339
02340 walkdir(pg_data, fsync_fname);
02341
02342 check_ok();
02343 }
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368 static void
02369 trapsig(int signum)
02370 {
02371
02372 pqsignal(signum, trapsig);
02373 caught_signal = true;
02374 }
02375
02376
02377
02378
02379 static void
02380 check_ok(void)
02381 {
02382 if (caught_signal)
02383 {
02384 printf(_("caught signal\n"));
02385 fflush(stdout);
02386 exit_nicely();
02387 }
02388 else if (output_failed)
02389 {
02390 printf(_("could not write to child process: %s\n"),
02391 strerror(output_errno));
02392 fflush(stdout);
02393 exit_nicely();
02394 }
02395 else
02396 {
02397
02398 printf(_("ok\n"));
02399 fflush(stdout);
02400 }
02401 }
02402
02403
02404 static inline size_t
02405 my_strftime(char *s, size_t max, const char *fmt, const struct tm * tm)
02406 {
02407 return strftime(s, max, fmt, tm);
02408 }
02409
02410
02411
02412
02413 static int
02414 locale_date_order(const char *locale)
02415 {
02416 struct tm testtime;
02417 char buf[128];
02418 char *posD;
02419 char *posM;
02420 char *posY;
02421 char *save;
02422 size_t res;
02423 int result;
02424
02425 result = DATEORDER_MDY;
02426
02427 save = setlocale(LC_TIME, NULL);
02428 if (!save)
02429 return result;
02430 save = pg_strdup(save);
02431
02432 setlocale(LC_TIME, locale);
02433
02434 memset(&testtime, 0, sizeof(testtime));
02435 testtime.tm_mday = 22;
02436 testtime.tm_mon = 10;
02437 testtime.tm_year = 133;
02438
02439 res = my_strftime(buf, sizeof(buf), "%x", &testtime);
02440
02441 setlocale(LC_TIME, save);
02442 free(save);
02443
02444 if (res == 0)
02445 return result;
02446
02447 posM = strstr(buf, "11");
02448 posD = strstr(buf, "22");
02449 posY = strstr(buf, "33");
02450
02451 if (!posM || !posD || !posY)
02452 return result;
02453
02454 if (posY < posM && posM < posD)
02455 result = DATEORDER_YMD;
02456 else if (posD < posM)
02457 result = DATEORDER_DMY;
02458 else
02459 result = DATEORDER_MDY;
02460
02461 return result;
02462 }
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476 static bool
02477 check_locale_name(int category, const char *locale, char **canonname)
02478 {
02479 char *save;
02480 char *res;
02481
02482 if (canonname)
02483 *canonname = NULL;
02484
02485 save = setlocale(category, NULL);
02486 if (!save)
02487 return false;
02488
02489
02490 save = pg_strdup(save);
02491
02492
02493 res = setlocale(category, locale);
02494
02495
02496 if (res && canonname)
02497 *canonname = pg_strdup(res);
02498
02499
02500 if (!setlocale(category, save))
02501 fprintf(stderr, _("%s: failed to restore old locale \"%s\"\n"),
02502 progname, save);
02503 free(save);
02504
02505
02506 if (res == NULL)
02507 fprintf(stderr, _("%s: invalid locale name \"%s\"\n"),
02508 progname, locale);
02509
02510 return (res != NULL);
02511 }
02512
02513
02514
02515
02516
02517
02518 static bool
02519 check_locale_encoding(const char *locale, int user_enc)
02520 {
02521 int locale_enc;
02522
02523 locale_enc = pg_get_encoding_from_locale(locale, true);
02524
02525
02526 if (!(locale_enc == user_enc ||
02527 locale_enc == PG_SQL_ASCII ||
02528 locale_enc == -1 ||
02529 #ifdef WIN32
02530 user_enc == PG_UTF8 ||
02531 #endif
02532 user_enc == PG_SQL_ASCII))
02533 {
02534 fprintf(stderr, _("%s: encoding mismatch\n"), progname);
02535 fprintf(stderr,
02536 _("The encoding you selected (%s) and the encoding that the\n"
02537 "selected locale uses (%s) do not match. This would lead to\n"
02538 "misbehavior in various character string processing functions.\n"
02539 "Rerun %s and either do not specify an encoding explicitly,\n"
02540 "or choose a matching combination.\n"),
02541 pg_encoding_to_char(user_enc),
02542 pg_encoding_to_char(locale_enc),
02543 progname);
02544 return false;
02545 }
02546 return true;
02547 }
02548
02549
02550
02551
02552
02553
02554 static void
02555 setlocales(void)
02556 {
02557 char *canonname;
02558
02559
02560
02561 if (strlen(locale) > 0)
02562 {
02563 if (strlen(lc_ctype) == 0)
02564 lc_ctype = locale;
02565 if (strlen(lc_collate) == 0)
02566 lc_collate = locale;
02567 if (strlen(lc_numeric) == 0)
02568 lc_numeric = locale;
02569 if (strlen(lc_time) == 0)
02570 lc_time = locale;
02571 if (strlen(lc_monetary) == 0)
02572 lc_monetary = locale;
02573 if (strlen(lc_messages) == 0)
02574 lc_messages = locale;
02575 }
02576
02577
02578
02579
02580
02581
02582 if (check_locale_name(LC_CTYPE, lc_ctype, &canonname))
02583 lc_ctype = canonname;
02584 else
02585 lc_ctype = pg_strdup(setlocale(LC_CTYPE, NULL));
02586 if (check_locale_name(LC_COLLATE, lc_collate, &canonname))
02587 lc_collate = canonname;
02588 else
02589 lc_collate = pg_strdup(setlocale(LC_COLLATE, NULL));
02590 if (check_locale_name(LC_NUMERIC, lc_numeric, &canonname))
02591 lc_numeric = canonname;
02592 else
02593 lc_numeric = pg_strdup(setlocale(LC_NUMERIC, NULL));
02594 if (check_locale_name(LC_TIME, lc_time, &canonname))
02595 lc_time = canonname;
02596 else
02597 lc_time = pg_strdup(setlocale(LC_TIME, NULL));
02598 if (check_locale_name(LC_MONETARY, lc_monetary, &canonname))
02599 lc_monetary = canonname;
02600 else
02601 lc_monetary = pg_strdup(setlocale(LC_MONETARY, NULL));
02602 #if defined(LC_MESSAGES) && !defined(WIN32)
02603 if (check_locale_name(LC_MESSAGES, lc_messages, &canonname))
02604 lc_messages = canonname;
02605 else
02606 lc_messages = pg_strdup(setlocale(LC_MESSAGES, NULL));
02607 #else
02608
02609 if (check_locale_name(LC_CTYPE, lc_messages, &canonname))
02610 lc_messages = canonname;
02611 else
02612 lc_messages = pg_strdup(setlocale(LC_CTYPE, NULL));
02613 #endif
02614 }
02615
02616 #ifdef WIN32
02617 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
02618
02619
02620 #ifndef DISABLE_MAX_PRIVILEGE
02621 #define DISABLE_MAX_PRIVILEGE 0x1
02622 #endif
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632 static int
02633 CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo)
02634 {
02635 BOOL b;
02636 STARTUPINFO si;
02637 HANDLE origToken;
02638 HANDLE restrictedToken;
02639 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
02640 SID_AND_ATTRIBUTES dropSids[2];
02641 __CreateRestrictedToken _CreateRestrictedToken = NULL;
02642 HANDLE Advapi32Handle;
02643
02644 ZeroMemory(&si, sizeof(si));
02645 si.cb = sizeof(si);
02646
02647 Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
02648 if (Advapi32Handle != NULL)
02649 {
02650 _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
02651 }
02652
02653 if (_CreateRestrictedToken == NULL)
02654 {
02655 fprintf(stderr, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
02656 if (Advapi32Handle != NULL)
02657 FreeLibrary(Advapi32Handle);
02658 return 0;
02659 }
02660
02661
02662 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
02663 {
02664 fprintf(stderr, _("%s: could not open process token: error code %lu\n"), progname, GetLastError());
02665 return 0;
02666 }
02667
02668
02669 ZeroMemory(&dropSids, sizeof(dropSids));
02670 if (!AllocateAndInitializeSid(&NtAuthority, 2,
02671 SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
02672 0, &dropSids[0].Sid) ||
02673 !AllocateAndInitializeSid(&NtAuthority, 2,
02674 SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
02675 0, &dropSids[1].Sid))
02676 {
02677 fprintf(stderr, _("%s: could not to allocate SIDs: error code %lu\n"), progname, GetLastError());
02678 return 0;
02679 }
02680
02681 b = _CreateRestrictedToken(origToken,
02682 DISABLE_MAX_PRIVILEGE,
02683 sizeof(dropSids) / sizeof(dropSids[0]),
02684 dropSids,
02685 0, NULL,
02686 0, NULL,
02687 &restrictedToken);
02688
02689 FreeSid(dropSids[1].Sid);
02690 FreeSid(dropSids[0].Sid);
02691 CloseHandle(origToken);
02692 FreeLibrary(Advapi32Handle);
02693
02694 if (!b)
02695 {
02696 fprintf(stderr, _("%s: could not create restricted token: error code %lu\n"), progname, GetLastError());
02697 return 0;
02698 }
02699
02700 #ifndef __CYGWIN__
02701 AddUserToTokenDacl(restrictedToken);
02702 #endif
02703
02704 if (!CreateProcessAsUser(restrictedToken,
02705 NULL,
02706 cmd,
02707 NULL,
02708 NULL,
02709 TRUE,
02710 CREATE_SUSPENDED,
02711 NULL,
02712 NULL,
02713 &si,
02714 processInfo))
02715
02716 {
02717 fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
02718 return 0;
02719 }
02720
02721 return ResumeThread(processInfo->hThread);
02722 }
02723 #endif
02724
02725
02726
02727
02728 static void
02729 usage(const char *progname)
02730 {
02731 printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname);
02732 printf(_("Usage:\n"));
02733 printf(_(" %s [OPTION]... [DATADIR]\n"), progname);
02734 printf(_("\nOptions:\n"));
02735 printf(_(" -A, --auth=METHOD default authentication method for local connections\n"));
02736 printf(_(" --auth-host=METHOD default authentication method for local TCP/IP connections\n"));
02737 printf(_(" --auth-local=METHOD default authentication method for local-socket connections\n"));
02738 printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n"));
02739 printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n"));
02740 printf(_(" --locale=LOCALE set default locale for new databases\n"));
02741 printf(_(" --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n"
02742 " --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n"
02743 " set default locale in the respective category for\n"
02744 " new databases (default taken from environment)\n"));
02745 printf(_(" --no-locale equivalent to --locale=C\n"));
02746 printf(_(" --pwfile=FILE read password for the new superuser from file\n"));
02747 printf(_(" -T, --text-search-config=CFG\n"
02748 " default text search configuration\n"));
02749 printf(_(" -U, --username=NAME database superuser name\n"));
02750 printf(_(" -W, --pwprompt prompt for a password for the new superuser\n"));
02751 printf(_(" -X, --xlogdir=XLOGDIR location for the transaction log directory\n"));
02752 printf(_("\nLess commonly used options:\n"));
02753 printf(_(" -d, --debug generate lots of debugging output\n"));
02754 printf(_(" -k, --data-checksums use data page checksums\n"));
02755 printf(_(" -L DIRECTORY where to find the input files\n"));
02756 printf(_(" -n, --noclean do not clean up after errors\n"));
02757 printf(_(" -N, --nosync do not wait for changes to be written safely to disk\n"));
02758 printf(_(" -s, --show show internal settings\n"));
02759 printf(_(" -S, --sync-only only sync data directory\n"));
02760 printf(_("\nOther options:\n"));
02761 printf(_(" -V, --version output version information, then exit\n"));
02762 printf(_(" -?, --help show this help, then exit\n"));
02763 printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
02764 "is used.\n"));
02765 printf(_("\nReport bugs to <[email protected]>.\n"));
02766 }
02767
02768 static void
02769 check_authmethod_unspecified(const char **authmethod)
02770 {
02771 if (*authmethod == NULL || strlen(*authmethod) == 0)
02772 {
02773 authwarning = _("\nWARNING: enabling \"trust\" authentication for local connections\n"
02774 "You can change this by editing pg_hba.conf or using the option -A, or\n"
02775 "--auth-local and --auth-host, the next time you run initdb.\n");
02776 *authmethod = "trust";
02777 }
02778 }
02779
02780 static void
02781 check_authmethod_valid(const char *authmethod, const char **valid_methods, const char *conntype)
02782 {
02783 const char **p;
02784
02785 for (p = valid_methods; *p; p++)
02786 {
02787 if (strcmp(authmethod, *p) == 0)
02788 return;
02789
02790 if (strchr(authmethod, ' '))
02791 if (strncmp(authmethod, *p, (authmethod - strchr(authmethod, ' '))) == 0)
02792 return;
02793 }
02794
02795 fprintf(stderr, _("%s: invalid authentication method \"%s\" for \"%s\" connections\n"),
02796 progname, authmethod, conntype);
02797 exit(1);
02798 }
02799
02800 static void
02801 check_need_password(const char *authmethodlocal, const char *authmethodhost)
02802 {
02803 if ((strcmp(authmethodlocal, "md5") == 0 ||
02804 strcmp(authmethodlocal, "password") == 0) &&
02805 (strcmp(authmethodhost, "md5") == 0 ||
02806 strcmp(authmethodhost, "password") == 0) &&
02807 !(pwprompt || pwfilename))
02808 {
02809 fprintf(stderr, _("%s: must specify a password for the superuser to enable %s authentication\n"), progname,
02810 (strcmp(authmethodlocal, "md5") == 0 ||
02811 strcmp(authmethodlocal, "password") == 0)
02812 ? authmethodlocal
02813 : authmethodhost);
02814 exit(1);
02815 }
02816 }
02817
02818 void
02819 get_restricted_token(void)
02820 {
02821 #ifdef WIN32
02822
02823
02824
02825
02826
02827 if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
02828 || strcmp(restrict_env, "1") != 0)
02829 {
02830 PROCESS_INFORMATION pi;
02831 char *cmdline;
02832
02833 ZeroMemory(&pi, sizeof(pi));
02834
02835 cmdline = pg_strdup(GetCommandLine());
02836
02837 putenv("PG_RESTRICT_EXEC=1");
02838
02839 if (!CreateRestrictedProcess(cmdline, &pi))
02840 {
02841 fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, GetLastError());
02842 }
02843 else
02844 {
02845
02846
02847
02848
02849 DWORD x;
02850
02851 CloseHandle(pi.hThread);
02852 WaitForSingleObject(pi.hProcess, INFINITE);
02853
02854 if (!GetExitCodeProcess(pi.hProcess, &x))
02855 {
02856 fprintf(stderr, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
02857 exit(1);
02858 }
02859 exit(x);
02860 }
02861 }
02862 #endif
02863 }
02864
02865 void
02866 setup_pgdata(void)
02867 {
02868 char *pgdata_get_env, *pgdata_set_env;
02869
02870 if (strlen(pg_data) == 0)
02871 {
02872 pgdata_get_env = getenv("PGDATA");
02873 if (pgdata_get_env && strlen(pgdata_get_env))
02874 {
02875
02876 pg_data = pg_strdup(pgdata_get_env);
02877 }
02878 else
02879 {
02880 fprintf(stderr,
02881 _("%s: no data directory specified\n"
02882 "You must identify the directory where the data for this database system\n"
02883 "will reside. Do this with either the invocation option -D or the\n"
02884 "environment variable PGDATA.\n"),
02885 progname);
02886 exit(1);
02887 }
02888 }
02889
02890 pgdata_native = pg_strdup(pg_data);
02891 canonicalize_path(pg_data);
02892
02893
02894
02895
02896
02897
02898
02899 pgdata_set_env = pg_malloc(8 + strlen(pg_data));
02900 sprintf(pgdata_set_env, "PGDATA=%s", pg_data);
02901 putenv(pgdata_set_env);
02902 }
02903
02904
02905 void
02906 setup_bin_paths(const char *argv0)
02907 {
02908 int ret;
02909
02910 if ((ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
02911 backend_exec)) < 0)
02912 {
02913 char full_path[MAXPGPATH];
02914
02915 if (find_my_exec(argv0, full_path) < 0)
02916 strlcpy(full_path, progname, sizeof(full_path));
02917
02918 if (ret == -1)
02919 fprintf(stderr,
02920 _("The program \"postgres\" is needed by %s "
02921 "but was not found in the\n"
02922 "same directory as \"%s\".\n"
02923 "Check your installation.\n"),
02924 progname, full_path);
02925 else
02926 fprintf(stderr,
02927 _("The program \"postgres\" was found by \"%s\"\n"
02928 "but was not the same version as %s.\n"
02929 "Check your installation.\n"),
02930 full_path, progname);
02931 exit(1);
02932 }
02933
02934
02935 strcpy(bin_path, backend_exec);
02936 *last_dir_separator(bin_path) = '\0';
02937 canonicalize_path(bin_path);
02938
02939 if (!share_path)
02940 {
02941 share_path = pg_malloc(MAXPGPATH);
02942 get_share_path(backend_exec, share_path);
02943 }
02944 else if (!is_absolute_path(share_path))
02945 {
02946 fprintf(stderr, _("%s: input file location must be an absolute path\n"), progname);
02947 exit(1);
02948 }
02949
02950 canonicalize_path(share_path);
02951 }
02952
02953 void
02954 setup_locale_encoding(void)
02955 {
02956 int user_enc;
02957
02958 setlocales();
02959
02960 if (strcmp(lc_ctype, lc_collate) == 0 &&
02961 strcmp(lc_ctype, lc_time) == 0 &&
02962 strcmp(lc_ctype, lc_numeric) == 0 &&
02963 strcmp(lc_ctype, lc_monetary) == 0 &&
02964 strcmp(lc_ctype, lc_messages) == 0)
02965 printf(_("The database cluster will be initialized with locale \"%s\".\n"), lc_ctype);
02966 else
02967 {
02968 printf(_("The database cluster will be initialized with locales\n"
02969 " COLLATE: %s\n"
02970 " CTYPE: %s\n"
02971 " MESSAGES: %s\n"
02972 " MONETARY: %s\n"
02973 " NUMERIC: %s\n"
02974 " TIME: %s\n"),
02975 lc_collate,
02976 lc_ctype,
02977 lc_messages,
02978 lc_monetary,
02979 lc_numeric,
02980 lc_time);
02981 }
02982
02983 if (strlen(encoding) == 0)
02984 {
02985 int ctype_enc;
02986
02987 ctype_enc = pg_get_encoding_from_locale(lc_ctype, true);
02988
02989 if (ctype_enc == -1)
02990 {
02991
02992 fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"),
02993 progname, lc_ctype);
02994 fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
02995 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
02996 progname);
02997 exit(1);
02998 }
02999 else if (!pg_valid_server_encoding_id(ctype_enc))
03000 {
03001
03002
03003
03004
03005
03006 #ifdef WIN32
03007 printf(_("Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n"
03008 "The default database encoding will be set to \"%s\" instead.\n"),
03009 pg_encoding_to_char(ctype_enc),
03010 pg_encoding_to_char(PG_UTF8));
03011 ctype_enc = PG_UTF8;
03012 encodingid = encodingid_to_string(ctype_enc);
03013 #else
03014 fprintf(stderr,
03015 _("%s: locale \"%s\" requires unsupported encoding \"%s\"\n"),
03016 progname, lc_ctype, pg_encoding_to_char(ctype_enc));
03017 fprintf(stderr,
03018 _("Encoding \"%s\" is not allowed as a server-side encoding.\n"
03019 "Rerun %s with a different locale selection.\n"),
03020 pg_encoding_to_char(ctype_enc), progname);
03021 exit(1);
03022 #endif
03023 }
03024 else
03025 {
03026 encodingid = encodingid_to_string(ctype_enc);
03027 printf(_("The default database encoding has accordingly been set to \"%s\".\n"),
03028 pg_encoding_to_char(ctype_enc));
03029 }
03030 }
03031 else
03032 encodingid = get_encoding_id(encoding);
03033
03034 user_enc = atoi(encodingid);
03035 if (!check_locale_encoding(lc_ctype, user_enc) ||
03036 !check_locale_encoding(lc_collate, user_enc))
03037 exit(1);
03038
03039 }
03040
03041
03042 void
03043 setup_data_file_paths(void)
03044 {
03045 set_input(&bki_file, "postgres.bki");
03046 set_input(&desc_file, "postgres.description");
03047 set_input(&shdesc_file, "postgres.shdescription");
03048 set_input(&hba_file, "pg_hba.conf.sample");
03049 set_input(&ident_file, "pg_ident.conf.sample");
03050 set_input(&conf_file, "postgresql.conf.sample");
03051 set_input(&conversion_file, "conversion_create.sql");
03052 set_input(&dictionary_file, "snowball_create.sql");
03053 set_input(&info_schema_file, "information_schema.sql");
03054 set_input(&features_file, "sql_features.txt");
03055 set_input(&system_views_file, "system_views.sql");
03056
03057 if (show_setting || debug)
03058 {
03059 fprintf(stderr,
03060 "VERSION=%s\n"
03061 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
03062 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
03063 "POSTGRES_DESCR=%s\nPOSTGRES_SHDESCR=%s\n"
03064 "POSTGRESQL_CONF_SAMPLE=%s\n"
03065 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
03066 PG_VERSION,
03067 pg_data, share_path, bin_path,
03068 username, bki_file,
03069 desc_file, shdesc_file,
03070 conf_file,
03071 hba_file, ident_file);
03072 if (show_setting)
03073 exit(0);
03074 }
03075
03076 check_input(bki_file);
03077 check_input(desc_file);
03078 check_input(shdesc_file);
03079 check_input(hba_file);
03080 check_input(ident_file);
03081 check_input(conf_file);
03082 check_input(conversion_file);
03083 check_input(dictionary_file);
03084 check_input(info_schema_file);
03085 check_input(features_file);
03086 check_input(system_views_file);
03087 }
03088
03089
03090 void
03091 setup_text_search(void)
03092 {
03093 if (strlen(default_text_search_config) == 0)
03094 {
03095 default_text_search_config = find_matching_ts_config(lc_ctype);
03096 if (default_text_search_config == NULL)
03097 {
03098 printf(_("%s: could not find suitable text search configuration for locale \"%s\"\n"),
03099 progname, lc_ctype);
03100 default_text_search_config = "simple";
03101 }
03102 }
03103 else
03104 {
03105 const char *checkmatch = find_matching_ts_config(lc_ctype);
03106
03107 if (checkmatch == NULL)
03108 {
03109 printf(_("%s: warning: suitable text search configuration for locale \"%s\" is unknown\n"),
03110 progname, lc_ctype);
03111 }
03112 else if (strcmp(checkmatch, default_text_search_config) != 0)
03113 {
03114 printf(_("%s: warning: specified text search configuration \"%s\" might not match locale \"%s\"\n"),
03115 progname, default_text_search_config, lc_ctype);
03116 }
03117 }
03118
03119 printf(_("The default text search configuration will be set to \"%s\".\n"),
03120 default_text_search_config);
03121
03122 }
03123
03124
03125 void
03126 setup_signals(void)
03127 {
03128
03129 #ifdef SIGHUP
03130 pqsignal(SIGHUP, trapsig);
03131 #endif
03132 #ifdef SIGINT
03133 pqsignal(SIGINT, trapsig);
03134 #endif
03135 #ifdef SIGQUIT
03136 pqsignal(SIGQUIT, trapsig);
03137 #endif
03138 #ifdef SIGTERM
03139 pqsignal(SIGTERM, trapsig);
03140 #endif
03141
03142
03143 #ifdef SIGPIPE
03144 pqsignal(SIGPIPE, SIG_IGN);
03145 #endif
03146 }
03147
03148
03149 void
03150 create_data_directory(void)
03151 {
03152 int ret;
03153
03154 switch ((ret = pg_check_dir(pg_data)))
03155 {
03156 case 0:
03157
03158 printf(_("creating directory %s ... "),
03159 pg_data);
03160 fflush(stdout);
03161
03162 if (!mkdatadir(NULL))
03163 exit_nicely();
03164 else
03165 check_ok();
03166
03167 made_new_pgdata = true;
03168 break;
03169
03170 case 1:
03171
03172 printf(_("fixing permissions on existing directory %s ... "),
03173 pg_data);
03174 fflush(stdout);
03175
03176 if (chmod(pg_data, S_IRWXU) != 0)
03177 {
03178 fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
03179 progname, pg_data, strerror(errno));
03180 exit_nicely();
03181 }
03182 else
03183 check_ok();
03184
03185 found_existing_pgdata = true;
03186 break;
03187
03188 case 2:
03189 case 3:
03190 case 4:
03191
03192 fprintf(stderr,
03193 _("%s: directory \"%s\" exists but is not empty\n"),
03194 progname, pg_data);
03195 if (ret != 4)
03196 warn_on_mount_point(ret);
03197 else
03198 fprintf(stderr,
03199 _("If you want to create a new database system, either remove or empty\n"
03200 "the directory \"%s\" or run %s\n"
03201 "with an argument other than \"%s\".\n"),
03202 pg_data, progname, pg_data);
03203 exit(1);
03204
03205 default:
03206
03207 fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
03208 progname, pg_data, strerror(errno));
03209 exit_nicely();
03210 }
03211 }
03212
03213
03214 void
03215 create_xlog_symlink(void)
03216 {
03217
03218 if (strcmp(xlog_dir, "") != 0)
03219 {
03220 char *linkloc;
03221 int ret;
03222
03223
03224 canonicalize_path(xlog_dir);
03225 if (!is_absolute_path(xlog_dir))
03226 {
03227 fprintf(stderr, _("%s: transaction log directory location must be an absolute path\n"), progname);
03228 exit_nicely();
03229 }
03230
03231
03232 switch ((ret = pg_check_dir(xlog_dir)))
03233 {
03234 case 0:
03235
03236 printf(_("creating directory %s ... "),
03237 xlog_dir);
03238 fflush(stdout);
03239
03240 if (pg_mkdir_p(xlog_dir, S_IRWXU) != 0)
03241 {
03242 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
03243 progname, xlog_dir, strerror(errno));
03244 exit_nicely();
03245 }
03246 else
03247 check_ok();
03248
03249 made_new_xlogdir = true;
03250 break;
03251
03252 case 1:
03253
03254 printf(_("fixing permissions on existing directory %s ... "),
03255 xlog_dir);
03256 fflush(stdout);
03257
03258 if (chmod(xlog_dir, S_IRWXU) != 0)
03259 {
03260 fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
03261 progname, xlog_dir, strerror(errno));
03262 exit_nicely();
03263 }
03264 else
03265 check_ok();
03266
03267 found_existing_xlogdir = true;
03268 break;
03269
03270 case 2:
03271 case 3:
03272 case 4:
03273
03274 fprintf(stderr,
03275 _("%s: directory \"%s\" exists but is not empty\n"),
03276 progname, xlog_dir);
03277 if (ret != 4)
03278 warn_on_mount_point(ret);
03279 else
03280 fprintf(stderr,
03281 _("If you want to store the transaction log there, either\n"
03282 "remove or empty the directory \"%s\".\n"),
03283 xlog_dir);
03284 exit_nicely();
03285
03286 default:
03287
03288 fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
03289 progname, xlog_dir, strerror(errno));
03290 exit_nicely();
03291 }
03292
03293
03294 linkloc = (char *) pg_malloc(strlen(pg_data) + 8 + 1);
03295 sprintf(linkloc, "%s/pg_xlog", pg_data);
03296
03297 #ifdef HAVE_SYMLINK
03298 if (symlink(xlog_dir, linkloc) != 0)
03299 {
03300 fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"),
03301 progname, linkloc, strerror(errno));
03302 exit_nicely();
03303 }
03304 #else
03305 fprintf(stderr, _("%s: symlinks are not supported on this platform"));
03306 exit_nicely();
03307 #endif
03308 }
03309 }
03310
03311
03312 void
03313 warn_on_mount_point(int error)
03314 {
03315 if (error == 2)
03316 fprintf(stderr,
03317 _("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n"));
03318 else if (error == 3)
03319 fprintf(stderr,
03320 _("It contains a lost+found directory, perhaps due to it being a mount point.\n"));
03321
03322 fprintf(stderr,
03323 _("Using a mount point directly as the data directory is not recommended.\n"
03324 "Create a subdirectory under the mount point.\n"));
03325 }
03326
03327
03328 void
03329 initialize_data_directory(void)
03330 {
03331 int i;
03332
03333 setup_signals();
03334
03335 umask(S_IRWXG | S_IRWXO);
03336
03337 create_data_directory();
03338
03339 create_xlog_symlink();
03340
03341
03342 printf(_("creating subdirectories ... "));
03343 fflush(stdout);
03344
03345 for (i = 0; i < (sizeof(subdirs) / sizeof(char *)); i++)
03346 {
03347 if (!mkdatadir(subdirs[i]))
03348 exit_nicely();
03349 }
03350
03351 check_ok();
03352
03353
03354 write_version_file(NULL);
03355
03356
03357 set_null_conf();
03358 test_config_settings();
03359
03360
03361 setup_config();
03362
03363
03364 bootstrap_template1();
03365
03366
03367
03368
03369 write_version_file("base/1");
03370
03371
03372
03373 setup_auth();
03374 if (pwprompt || pwfilename)
03375 get_set_pwd();
03376
03377 setup_depend();
03378
03379 setup_sysviews();
03380
03381 setup_description();
03382
03383 setup_collation();
03384
03385 setup_conversion();
03386
03387 setup_dictionary();
03388
03389 setup_privileges();
03390
03391 setup_schema();
03392
03393 load_plpgsql();
03394
03395 vacuum_db();
03396
03397 make_template0();
03398
03399 make_postgres();
03400 }
03401
03402
03403 int
03404 main(int argc, char *argv[])
03405 {
03406 static struct option long_options[] = {
03407 {"pgdata", required_argument, NULL, 'D'},
03408 {"encoding", required_argument, NULL, 'E'},
03409 {"locale", required_argument, NULL, 1},
03410 {"lc-collate", required_argument, NULL, 2},
03411 {"lc-ctype", required_argument, NULL, 3},
03412 {"lc-monetary", required_argument, NULL, 4},
03413 {"lc-numeric", required_argument, NULL, 5},
03414 {"lc-time", required_argument, NULL, 6},
03415 {"lc-messages", required_argument, NULL, 7},
03416 {"no-locale", no_argument, NULL, 8},
03417 {"text-search-config", required_argument, NULL, 'T'},
03418 {"auth", required_argument, NULL, 'A'},
03419 {"auth-local", required_argument, NULL, 10},
03420 {"auth-host", required_argument, NULL, 11},
03421 {"pwprompt", no_argument, NULL, 'W'},
03422 {"pwfile", required_argument, NULL, 9},
03423 {"username", required_argument, NULL, 'U'},
03424 {"help", no_argument, NULL, '?'},
03425 {"version", no_argument, NULL, 'V'},
03426 {"debug", no_argument, NULL, 'd'},
03427 {"show", no_argument, NULL, 's'},
03428 {"noclean", no_argument, NULL, 'n'},
03429 {"nosync", no_argument, NULL, 'N'},
03430 {"sync-only", no_argument, NULL, 'S'},
03431 {"xlogdir", required_argument, NULL, 'X'},
03432 {"data-checksums", no_argument, NULL, 'k'},
03433 {NULL, 0, NULL, 0}
03434 };
03435
03436
03437
03438
03439
03440 int c;
03441 int option_index;
03442 char *effective_user;
03443 char bin_dir[MAXPGPATH];
03444
03445 progname = get_progname(argv[0]);
03446 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("initdb"));
03447
03448 if (argc > 1)
03449 {
03450 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
03451 {
03452 usage(progname);
03453 exit(0);
03454 }
03455 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
03456 {
03457 puts("initdb (PostgreSQL) " PG_VERSION);
03458 exit(0);
03459 }
03460 }
03461
03462
03463
03464 while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
03465 {
03466 switch (c)
03467 {
03468 case 'A':
03469 authmethodlocal = authmethodhost = pg_strdup(optarg);
03470
03471
03472
03473
03474
03475
03476 if (strcmp(authmethodhost, "ident") == 0)
03477 authmethodlocal = "peer";
03478 else if (strcmp(authmethodlocal, "peer") == 0)
03479 authmethodhost = "ident";
03480 break;
03481 case 10:
03482 authmethodlocal = pg_strdup(optarg);
03483 break;
03484 case 11:
03485 authmethodhost = pg_strdup(optarg);
03486 break;
03487 case 'D':
03488 pg_data = pg_strdup(optarg);
03489 break;
03490 case 'E':
03491 encoding = pg_strdup(optarg);
03492 break;
03493 case 'W':
03494 pwprompt = true;
03495 break;
03496 case 'U':
03497 username = pg_strdup(optarg);
03498 break;
03499 case 'd':
03500 debug = true;
03501 printf(_("Running in debug mode.\n"));
03502 break;
03503 case 'n':
03504 noclean = true;
03505 printf(_("Running in noclean mode. Mistakes will not be cleaned up.\n"));
03506 break;
03507 case 'N':
03508 do_sync = false;
03509 break;
03510 case 'S':
03511 sync_only = true;
03512 break;
03513 case 'k':
03514 data_checksums = true;
03515 break;
03516 case 'L':
03517 share_path = pg_strdup(optarg);
03518 break;
03519 case 1:
03520 locale = pg_strdup(optarg);
03521 break;
03522 case 2:
03523 lc_collate = pg_strdup(optarg);
03524 break;
03525 case 3:
03526 lc_ctype = pg_strdup(optarg);
03527 break;
03528 case 4:
03529 lc_monetary = pg_strdup(optarg);
03530 break;
03531 case 5:
03532 lc_numeric = pg_strdup(optarg);
03533 break;
03534 case 6:
03535 lc_time = pg_strdup(optarg);
03536 break;
03537 case 7:
03538 lc_messages = pg_strdup(optarg);
03539 break;
03540 case 8:
03541 locale = "C";
03542 break;
03543 case 9:
03544 pwfilename = pg_strdup(optarg);
03545 break;
03546 case 's':
03547 show_setting = true;
03548 break;
03549 case 'T':
03550 default_text_search_config = pg_strdup(optarg);
03551 break;
03552 case 'X':
03553 xlog_dir = pg_strdup(optarg);
03554 break;
03555 default:
03556
03557 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
03558 progname);
03559 exit(1);
03560 }
03561 }
03562
03563
03564
03565
03566
03567
03568 if (optind < argc && strlen(pg_data) == 0)
03569 {
03570 pg_data = pg_strdup(argv[optind]);
03571 optind++;
03572 }
03573
03574 if (optind < argc)
03575 {
03576 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
03577 progname, argv[optind]);
03578 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
03579 progname);
03580 exit(1);
03581 }
03582
03583
03584 if (sync_only)
03585 {
03586 setup_pgdata();
03587 perform_fsync();
03588 return 0;
03589 }
03590
03591 if (pwprompt && pwfilename)
03592 {
03593 fprintf(stderr, _("%s: password prompt and password file cannot be specified together\n"), progname);
03594 exit(1);
03595 }
03596
03597 check_authmethod_unspecified(&authmethodlocal);
03598 check_authmethod_unspecified(&authmethodhost);
03599
03600 check_authmethod_valid(authmethodlocal, auth_methods_local, "local");
03601 check_authmethod_valid(authmethodhost, auth_methods_host, "host");
03602
03603 check_need_password(authmethodlocal, authmethodhost);
03604
03605 get_restricted_token();
03606
03607 setup_pgdata();
03608
03609 setup_bin_paths(argv[0]);
03610
03611 effective_user = get_id();
03612 if (strlen(username) == 0)
03613 username = effective_user;
03614
03615 printf(_("The files belonging to this database system will be owned "
03616 "by user \"%s\".\n"
03617 "This user must also own the server process.\n\n"),
03618 effective_user);
03619
03620 set_info_version();
03621
03622 setup_data_file_paths();
03623
03624 setup_locale_encoding();
03625
03626 setup_text_search();
03627
03628 if (data_checksums)
03629 printf(_("Data page checksums are enabled.\n"));
03630 else
03631 printf(_("Data page checksums are disabled.\n"));
03632
03633 printf("\n");
03634
03635 initialize_data_directory();
03636
03637 if (do_sync)
03638 perform_fsync();
03639 else
03640 printf(_("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n"));
03641
03642 if (authwarning != NULL)
03643 fprintf(stderr, "%s", authwarning);
03644
03645
03646 strlcpy(bin_dir, argv[0], sizeof(bin_dir));
03647 get_parent_directory(bin_dir);
03648
03649 printf(_("\nSuccess. You can now start the database server using:\n\n"
03650 " %s%s%spostgres%s -D %s%s%s\n"
03651 "or\n"
03652 " %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
03653 QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
03654 QUOTE_PATH, pgdata_native, QUOTE_PATH,
03655 QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
03656 QUOTE_PATH, pgdata_native, QUOTE_PATH);
03657
03658 return 0;
03659 }