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