1 /*-------------------------------------------------------------------------
3 * initdb --- initialize a PostgreSQL installation
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.
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".
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.
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.
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.
33 * The program has some memory leakage - it isn't worth cleaning it up.
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
39 * This code is released under the terms of the PostgreSQL License.
41 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
42 * Portions Copyright (c) 1994, Regents of the University of California
44 * src/bin/initdb/initdb.c
46 *-------------------------------------------------------------------------
49 #include "postgres_fe.h"
62 #include "access/xlog_internal.h"
63 #include "catalog/pg_authid_d.h"
64 #include "catalog/pg_class_d.h" /* pgrminclude ignore */
65 #include "catalog/pg_collation_d.h"
66 #include "common/file_perm.h"
67 #include "common/file_utils.h"
68 #include "common/logging.h"
69 #include "common/restricted_token.h"
70 #include "common/string.h"
71 #include "common/username.h"
72 #include "fe_utils/string_utils.h"
73 #include "getaddrinfo.h"
74 #include "getopt_long.h"
75 #include "mb/pg_wchar.h"
76 #include "miscadmin.h"
79 /* Ideally this would be in a .h file, but it hardly seems worth the trouble */
80 extern const char *select_default_timezone(const char *share_path
);
82 static const char *const auth_methods_host
[] = {
83 "trust", "reject", "scram-sha-256", "md5", "password", "ident", "radius",
104 static const char *const auth_methods_local
[] = {
105 "trust", "reject", "scram-sha-256", "md5", "password", "peer", "radius",
119 * these values are passed in by makefile defines
121 static char *share_path
= NULL
;
123 /* values to be obtained from arguments */
124 static char *pg_data
= NULL
;
125 static char *encoding
= NULL
;
126 static char *locale
= NULL
;
127 static char *lc_collate
= NULL
;
128 static char *lc_ctype
= NULL
;
129 static char *lc_monetary
= NULL
;
130 static char *lc_numeric
= NULL
;
131 static char *lc_time
= NULL
;
132 static char *lc_messages
= NULL
;
133 static const char *default_text_search_config
= NULL
;
134 static char *username
= NULL
;
135 static bool pwprompt
= false;
136 static char *pwfilename
= NULL
;
137 static char *superuser_password
= NULL
;
138 static const char *authmethodhost
= NULL
;
139 static const char *authmethodlocal
= NULL
;
140 static bool debug
= false;
141 static bool noclean
= false;
142 static bool noinstructions
= false;
143 static bool do_sync
= true;
144 static bool sync_only
= false;
145 static bool show_setting
= false;
146 static bool data_checksums
= false;
147 static char *xlog_dir
= NULL
;
148 static char *str_wal_segment_size_mb
= NULL
;
149 static int wal_segment_size_mb
;
153 static const char *progname
;
154 static int encodingid
;
155 static char *bki_file
;
156 static char *hba_file
;
157 static char *ident_file
;
158 static char *conf_file
;
159 static char *dictionary_file
;
160 static char *info_schema_file
;
161 static char *features_file
;
162 static char *system_constraints_file
;
163 static char *system_functions_file
;
164 static char *system_views_file
;
165 static bool success
= false;
166 static bool made_new_pgdata
= false;
167 static bool found_existing_pgdata
= false;
168 static bool made_new_xlogdir
= false;
169 static bool found_existing_xlogdir
= false;
170 static char infoversion
[100];
171 static bool caught_signal
= false;
172 static bool output_failed
= false;
173 static int output_errno
= 0;
174 static char *pgdata_native
;
177 static int n_connections
= 10;
178 static int n_buffers
= 50;
179 static const char *dynamic_shared_memory_type
= NULL
;
180 static const char *default_timezone
= NULL
;
183 * Warning messages for authentication methods
185 #define AUTHTRUST_WARNING \
186 "# CAUTION: Configuring the system for local \"trust\" authentication\n" \
187 "# allows any local user to connect as any PostgreSQL user, including\n" \
188 "# the database superuser. If you do not trust all your local users,\n" \
189 "# use another authentication method.\n"
190 static bool authwarning
= false;
193 * Centralized knowledge of switches to pass to backend
195 * Note: we run the backend with -F (fsync disabled) and then do a single
196 * pass of fsync'ing at the end. This is faster than fsync'ing each step.
198 * Note: in the shell-script version, we also passed PGDATA as a -D switch,
199 * but here it is more convenient to pass it as an environment variable
200 * (no quoting to worry about).
202 static const char *boot_options
= "-F";
203 static const char *backend_options
= "--single -F -O -j -c search_path=pg_catalog -c exit_on_error=true";
205 /* Additional switches to pass to backend (either boot or standalone) */
206 static char *extra_options
= "";
208 static const char *const subdirs
[] = {
210 "pg_wal/archive_status",
219 "pg_multixact/members",
220 "pg_multixact/offsets",
229 "pg_logical/snapshots",
230 "pg_logical/mappings"
234 /* path to 'initdb' binary directory */
235 static char bin_path
[MAXPGPATH
];
236 static char backend_exec
[MAXPGPATH
];
238 static char **replace_token(char **lines
,
239 const char *token
, const char *replacement
);
241 #ifndef HAVE_UNIX_SOCKETS
242 static char **filter_lines_with_token(char **lines
, const char *token
);
244 static char **readfile(const char *path
);
245 static void writefile(char *path
, char **lines
);
246 static FILE *popen_check(const char *command
, const char *mode
);
247 static char *get_id(void);
248 static int get_encoding_id(const char *encoding_name
);
249 static void set_input(char **dest
, const char *filename
);
250 static void check_input(char *path
);
251 static void write_version_file(const char *extrapath
);
252 static void set_null_conf(void);
253 static void test_config_settings(void);
254 static void setup_config(void);
255 static void bootstrap_template1(void);
256 static void setup_auth(FILE *cmdfd
);
257 static void get_su_pwd(void);
258 static void setup_depend(FILE *cmdfd
);
259 static void setup_run_file(FILE *cmdfd
, const char *filename
);
260 static void setup_description(FILE *cmdfd
);
261 static void setup_collation(FILE *cmdfd
);
262 static void setup_privileges(FILE *cmdfd
);
263 static void set_info_version(void);
264 static void setup_schema(FILE *cmdfd
);
265 static void load_plpgsql(FILE *cmdfd
);
266 static void vacuum_db(FILE *cmdfd
);
267 static void make_template0(FILE *cmdfd
);
268 static void make_postgres(FILE *cmdfd
);
269 static void trapsig(int signum
);
270 static void check_ok(void);
271 static char *escape_quotes(const char *src
);
272 static char *escape_quotes_bki(const char *src
);
273 static int locale_date_order(const char *locale
);
274 static void check_locale_name(int category
, const char *locale
,
276 static bool check_locale_encoding(const char *locale
, int encoding
);
277 static void setlocales(void);
278 static void usage(const char *progname
);
279 void setup_pgdata(void);
280 void setup_bin_paths(const char *argv0
);
281 void setup_data_file_paths(void);
282 void setup_locale_encoding(void);
283 void setup_signals(void);
284 void setup_text_search(void);
285 void create_data_directory(void);
286 void create_xlog_or_symlink(void);
287 void warn_on_mount_point(int error
);
288 void initialize_data_directory(void);
291 * macros for running pipes to postgres
293 #define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd
295 #define PG_CMD_OPEN \
297 cmdfd = popen_check(cmd, "w"); \
299 exit(1); /* message already printed by popen_check */ \
302 #define PG_CMD_CLOSE \
304 if (pclose_check(cmdfd)) \
305 exit(1); /* message already printed by pclose_check */ \
308 #define PG_CMD_PUTS(line) \
310 if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \
311 output_failed = true, output_errno = errno; \
314 #define PG_CMD_PRINTF(fmt, ...) \
316 if (fprintf(cmdfd, fmt, __VA_ARGS__) < 0 || fflush(cmdfd) < 0) \
317 output_failed = true, output_errno = errno; \
321 * Escape single quotes and backslashes, suitably for insertions into
322 * configuration files or SQL E'' strings.
325 escape_quotes(const char *src
)
327 char *result
= escape_single_quotes_ascii(src
);
331 pg_log_error("out of memory");
338 * Escape a field value to be inserted into the BKI data.
339 * Run the value through escape_quotes (which will be inverted
340 * by the backend's DeescapeQuotedString() function), then wrap
341 * the value in single quotes, even if that isn't strictly necessary.
344 escape_quotes_bki(const char *src
)
347 char *data
= escape_quotes(src
);
351 result
= (char *) pg_malloc(strlen(data
) + 3);
354 for (datap
= data
; *datap
; datap
++)
364 * make a copy of the array of lines, with token replaced by replacement
365 * the first time it occurs on each line.
367 * This does most of what sed was used for in the shell script, but
368 * doesn't need any regexp stuff.
371 replace_token(char **lines
, const char *token
, const char *replacement
)
380 for (i
= 0; lines
[i
]; i
++)
383 result
= (char **) pg_malloc(numlines
* sizeof(char *));
385 toklen
= strlen(token
);
386 replen
= strlen(replacement
);
387 diff
= replen
- toklen
;
389 for (i
= 0; i
< numlines
; i
++)
395 /* just copy pointer if NULL or no change needed */
396 if (lines
[i
] == NULL
|| (where
= strstr(lines
[i
], token
)) == NULL
)
398 result
[i
] = lines
[i
];
402 /* if we get here a change is needed - set up new line */
404 newline
= (char *) pg_malloc(strlen(lines
[i
]) + diff
+ 1);
406 pre
= where
- lines
[i
];
408 memcpy(newline
, lines
[i
], pre
);
410 memcpy(newline
+ pre
, replacement
, replen
);
412 strcpy(newline
+ pre
+ replen
, lines
[i
] + pre
+ toklen
);
421 * make a copy of lines without any that contain the token
423 * a sort of poor man's grep -v
425 #ifndef HAVE_UNIX_SOCKETS
427 filter_lines_with_token(char **lines
, const char *token
)
435 for (i
= 0; lines
[i
]; i
++)
438 result
= (char **) pg_malloc(numlines
* sizeof(char *));
440 for (src
= 0, dst
= 0; src
< numlines
; src
++)
442 if (lines
[src
] == NULL
|| strstr(lines
[src
], token
) == NULL
)
443 result
[dst
++] = lines
[src
];
451 * get the lines from a text file
454 readfile(const char *path
)
462 if ((infile
= fopen(path
, "r")) == NULL
)
464 pg_log_error("could not open file \"%s\" for reading: %m", path
);
468 initStringInfo(&line
);
471 result
= (char **) pg_malloc(maxlines
* sizeof(char *));
474 while (pg_get_line_buf(infile
, &line
))
476 /* make sure there will be room for a trailing NULL pointer */
477 if (n
>= maxlines
- 1)
480 result
= (char **) pg_realloc(result
, maxlines
* sizeof(char *));
483 result
[n
++] = pg_strdup(line
.data
);
495 * write an array of lines to a file
497 * This is only used to write text files. Use fopen "w" not PG_BINARY_W
498 * so that the resulting configuration files are nicely editable on Windows.
501 writefile(char *path
, char **lines
)
506 if ((out_file
= fopen(path
, "w")) == NULL
)
508 pg_log_error("could not open file \"%s\" for writing: %m", path
);
511 for (line
= lines
; *line
!= NULL
; line
++)
513 if (fputs(*line
, out_file
) < 0)
515 pg_log_error("could not write file \"%s\": %m", path
);
520 if (fclose(out_file
))
522 pg_log_error("could not write file \"%s\": %m", path
);
528 * Open a subcommand with suitable error messaging
531 popen_check(const char *command
, const char *mode
)
538 cmdfd
= popen(command
, mode
);
540 pg_log_error("could not execute command \"%s\": %m", command
);
545 * clean up any files we created on failure
546 * if we created the data directory remove it too
549 cleanup_directories_atexit(void)
558 pg_log_info("removing data directory \"%s\"", pg_data
);
559 if (!rmtree(pg_data
, true))
560 pg_log_error("failed to remove data directory");
562 else if (found_existing_pgdata
)
564 pg_log_info("removing contents of data directory \"%s\"",
566 if (!rmtree(pg_data
, false))
567 pg_log_error("failed to remove contents of data directory");
570 if (made_new_xlogdir
)
572 pg_log_info("removing WAL directory \"%s\"", xlog_dir
);
573 if (!rmtree(xlog_dir
, true))
574 pg_log_error("failed to remove WAL directory");
576 else if (found_existing_xlogdir
)
578 pg_log_info("removing contents of WAL directory \"%s\"", xlog_dir
);
579 if (!rmtree(xlog_dir
, false))
580 pg_log_error("failed to remove contents of WAL directory");
582 /* otherwise died during startup, do nothing! */
586 if (made_new_pgdata
|| found_existing_pgdata
)
587 pg_log_info("data directory \"%s\" not removed at user's request",
590 if (made_new_xlogdir
|| found_existing_xlogdir
)
591 pg_log_info("WAL directory \"%s\" not removed at user's request",
597 * find the current user
599 * on unix make sure it isn't root
604 const char *username
;
607 if (geteuid() == 0) /* 0 is root's uid */
609 pg_log_error("cannot be run as root");
611 _("Please log in (using, e.g., \"su\") as the (unprivileged) user that will\n"
612 "own the server process.\n"));
617 username
= get_user_name_or_exit(progname
);
619 return pg_strdup(username
);
623 encodingid_to_string(int enc
)
627 sprintf(result
, "%d", enc
);
628 return pg_strdup(result
);
632 * get the encoding id for a given encoding name
635 get_encoding_id(const char *encoding_name
)
639 if (encoding_name
&& *encoding_name
)
641 if ((enc
= pg_valid_server_encoding(encoding_name
)) >= 0)
644 pg_log_error("\"%s\" is not a valid server encoding name",
645 encoding_name
? encoding_name
: "(null)");
650 * Support for determining the best default text search configuration.
651 * We key this off the first part of LC_CTYPE (ie, the language name).
653 struct tsearch_config_match
655 const char *tsconfname
;
656 const char *langname
;
659 static const struct tsearch_config_match tsearch_config_languages
[] =
662 {"arabic", "Arabic"},
664 {"armenian", "Armenian"},
666 {"basque", "Basque"},
668 {"catalan", "Catalan"},
670 {"danish", "Danish"},
674 {"english", "POSIX"},
676 {"english", "English"},
678 {"finnish", "Finnish"},
680 {"french", "French"},
682 {"german", "German"},
688 {"hungarian", "Hungarian"},
689 {"indonesian", "id"},
690 {"indonesian", "Indonesian"},
694 {"italian", "Italian"},
695 {"lithuanian", "lt"},
696 {"lithuanian", "Lithuanian"},
698 {"nepali", "Nepali"},
700 {"norwegian", "Norwegian"},
701 {"portuguese", "pt"},
702 {"portuguese", "Portuguese"},
705 {"russian", "Russian"},
707 {"serbian", "Serbian"},
709 {"spanish", "Spanish"},
711 {"swedish", "Swedish"},
715 {"turkish", "Turkish"},
717 {"yiddish", "Yiddish"},
718 {NULL
, NULL
} /* end marker */
722 * Look for a text search configuration matching lc_ctype, and return its
723 * name; return NULL if no match.
726 find_matching_ts_config(const char *lc_type
)
733 * Convert lc_ctype to a language name by stripping everything after an
734 * underscore (usual case) or a hyphen (Windows "locale name"; see
735 * comments at IsoLocaleName()).
737 * XXX Should ' ' be a stop character? This would select "norwegian" for
738 * the Windows locale "Norwegian (Nynorsk)_Norway.1252". If we do so, we
739 * should also accept the "nn" and "nb" Unix locales.
741 * Just for paranoia, we also stop at '.' or '@'.
744 langname
= pg_strdup("");
747 ptr
= langname
= pg_strdup(lc_type
);
749 *ptr
!= '_' && *ptr
!= '-' && *ptr
!= '.' && *ptr
!= '@')
754 for (i
= 0; tsearch_config_languages
[i
].tsconfname
; i
++)
756 if (pg_strcasecmp(tsearch_config_languages
[i
].langname
, langname
) == 0)
759 return tsearch_config_languages
[i
].tsconfname
;
769 * set name of given input file variable under data directory
772 set_input(char **dest
, const char *filename
)
774 *dest
= psprintf("%s/%s", share_path
, filename
);
778 * check that given input file exists
781 check_input(char *path
)
785 if (stat(path
, &statbuf
) != 0)
789 pg_log_error("file \"%s\" does not exist", path
);
791 _("This might mean you have a corrupted installation or identified\n"
792 "the wrong directory with the invocation option -L.\n"));
796 pg_log_error("could not access file \"%s\": %m", path
);
798 _("This might mean you have a corrupted installation or identified\n"
799 "the wrong directory with the invocation option -L.\n"));
803 if (!S_ISREG(statbuf
.st_mode
))
805 pg_log_error("file \"%s\" is not a regular file", path
);
807 _("This might mean you have a corrupted installation or identified\n"
808 "the wrong directory with the invocation option -L.\n"));
814 * write out the PG_VERSION file in the data dir, or its subdirectory
815 * if extrapath is not NULL
818 write_version_file(const char *extrapath
)
823 if (extrapath
== NULL
)
824 path
= psprintf("%s/PG_VERSION", pg_data
);
826 path
= psprintf("%s/%s/PG_VERSION", pg_data
, extrapath
);
828 if ((version_file
= fopen(path
, PG_BINARY_W
)) == NULL
)
830 pg_log_error("could not open file \"%s\" for writing: %m", path
);
833 if (fprintf(version_file
, "%s\n", PG_MAJORVERSION
) < 0 ||
834 fclose(version_file
))
836 pg_log_error("could not write file \"%s\": %m", path
);
843 * set up an empty config file so we can check config settings by launching
852 path
= psprintf("%s/postgresql.conf", pg_data
);
853 conf_file
= fopen(path
, PG_BINARY_W
);
854 if (conf_file
== NULL
)
856 pg_log_error("could not open file \"%s\" for writing: %m", path
);
859 if (fclose(conf_file
))
861 pg_log_error("could not write file \"%s\": %m", path
);
868 * Determine which dynamic shared memory implementation should be used on
869 * this platform. POSIX shared memory is preferable because the default
870 * allocation limits are much higher than the limits for System V on most
871 * systems that support both, but the fact that a platform has shm_open
872 * doesn't guarantee that that call will succeed when attempted. So, we
873 * attempt to reproduce what the postmaster will do when allocating a POSIX
874 * segment in dsm_impl.c; if it doesn't work, we assume it won't work for
875 * the postmaster either, and configure the cluster for System V shared
879 choose_dsm_implementation(void)
884 /* Initialize random(); this function is its only user in this program. */
885 srandom((unsigned int) (getpid() ^ time(NULL
)));
894 snprintf(name
, 64, "/PostgreSQL.%u", handle
);
895 if ((fd
= shm_open(name
, O_CREAT
| O_RDWR
| O_EXCL
, 0600)) != -1)
915 * Determine platform-specific config settings
917 * Use reasonable values if kernel will let us, else scale back.
920 test_config_settings(void)
923 * This macro defines the minimum shared_buffers we want for a given
924 * max_connections value. The arrays show the settings to try.
926 #define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10)
928 static const int trial_conns
[] = {
931 static const int trial_bufs
[] = {
932 16384, 8192, 4096, 3584, 3072, 2560, 2048, 1536,
933 1000, 900, 800, 700, 600, 500,
934 400, 300, 200, 100, 50
938 const int connslen
= sizeof(trial_conns
) / sizeof(int);
939 const int bufslen
= sizeof(trial_bufs
) / sizeof(int);
947 * Need to determine working DSM implementation first so that subsequent
948 * tests don't fail because DSM setting doesn't work.
950 printf(_("selecting dynamic shared memory implementation ... "));
952 dynamic_shared_memory_type
= choose_dsm_implementation();
953 printf("%s\n", dynamic_shared_memory_type
);
956 * Probe for max_connections before shared_buffers, since it is subject to
957 * more constraints than shared_buffers.
959 printf(_("selecting default max_connections ... "));
962 for (i
= 0; i
< connslen
; i
++)
964 test_conns
= trial_conns
[i
];
965 test_buffs
= MIN_BUFS_FOR_CONNS(test_conns
);
967 snprintf(cmd
, sizeof(cmd
),
968 "\"%s\" --check %s %s "
969 "-c max_connections=%d "
970 "-c shared_buffers=%d "
971 "-c dynamic_shared_memory_type=%s "
972 "< \"%s\" > \"%s\" 2>&1",
973 backend_exec
, boot_options
, extra_options
,
974 test_conns
, test_buffs
,
975 dynamic_shared_memory_type
,
977 status
= system(cmd
);
980 ok_buffers
= test_buffs
;
986 n_connections
= trial_conns
[i
];
988 printf("%d\n", n_connections
);
990 printf(_("selecting default shared_buffers ... "));
993 for (i
= 0; i
< bufslen
; i
++)
995 /* Use same amount of memory, independent of BLCKSZ */
996 test_buffs
= (trial_bufs
[i
] * 8192) / BLCKSZ
;
997 if (test_buffs
<= ok_buffers
)
999 test_buffs
= ok_buffers
;
1003 snprintf(cmd
, sizeof(cmd
),
1004 "\"%s\" --check %s %s "
1005 "-c max_connections=%d "
1006 "-c shared_buffers=%d "
1007 "-c dynamic_shared_memory_type=%s "
1008 "< \"%s\" > \"%s\" 2>&1",
1009 backend_exec
, boot_options
, extra_options
,
1010 n_connections
, test_buffs
,
1011 dynamic_shared_memory_type
,
1013 status
= system(cmd
);
1017 n_buffers
= test_buffs
;
1019 if ((n_buffers
* (BLCKSZ
/ 1024)) % 1024 == 0)
1020 printf("%dMB\n", (n_buffers
* (BLCKSZ
/ 1024)) / 1024);
1022 printf("%dkB\n", n_buffers
* (BLCKSZ
/ 1024));
1024 printf(_("selecting default time zone ... "));
1026 default_timezone
= select_default_timezone(share_path
);
1027 printf("%s\n", default_timezone
? default_timezone
: "GMT");
1031 * Calculate the default wal_size with a "pretty" unit.
1034 pretty_wal_size(int segment_count
)
1036 int sz
= wal_segment_size_mb
* segment_count
;
1037 char *result
= pg_malloc(14);
1039 if ((sz
% 1024) == 0)
1040 snprintf(result
, 14, "%dGB", sz
/ 1024);
1042 snprintf(result
, 14, "%dMB", sz
);
1048 * set up all the config files
1054 char repltok
[MAXPGPATH
];
1055 char path
[MAXPGPATH
];
1056 char *autoconflines
[3];
1058 fputs(_("creating configuration files ... "), stdout
);
1061 /* postgresql.conf */
1063 conflines
= readfile(conf_file
);
1065 snprintf(repltok
, sizeof(repltok
), "max_connections = %d", n_connections
);
1066 conflines
= replace_token(conflines
, "#max_connections = 100", repltok
);
1068 if ((n_buffers
* (BLCKSZ
/ 1024)) % 1024 == 0)
1069 snprintf(repltok
, sizeof(repltok
), "shared_buffers = %dMB",
1070 (n_buffers
* (BLCKSZ
/ 1024)) / 1024);
1072 snprintf(repltok
, sizeof(repltok
), "shared_buffers = %dkB",
1073 n_buffers
* (BLCKSZ
/ 1024));
1074 conflines
= replace_token(conflines
, "#shared_buffers = 128MB", repltok
);
1076 #ifdef HAVE_UNIX_SOCKETS
1077 snprintf(repltok
, sizeof(repltok
), "#unix_socket_directories = '%s'",
1078 DEFAULT_PGSOCKET_DIR
);
1080 snprintf(repltok
, sizeof(repltok
), "#unix_socket_directories = ''");
1082 conflines
= replace_token(conflines
, "#unix_socket_directories = '/tmp'",
1085 #if DEF_PGPORT != 5432
1086 snprintf(repltok
, sizeof(repltok
), "#port = %d", DEF_PGPORT
);
1087 conflines
= replace_token(conflines
, "#port = 5432", repltok
);
1090 /* set default max_wal_size and min_wal_size */
1091 snprintf(repltok
, sizeof(repltok
), "min_wal_size = %s",
1092 pretty_wal_size(DEFAULT_MIN_WAL_SEGS
));
1093 conflines
= replace_token(conflines
, "#min_wal_size = 80MB", repltok
);
1095 snprintf(repltok
, sizeof(repltok
), "max_wal_size = %s",
1096 pretty_wal_size(DEFAULT_MAX_WAL_SEGS
));
1097 conflines
= replace_token(conflines
, "#max_wal_size = 1GB", repltok
);
1099 snprintf(repltok
, sizeof(repltok
), "lc_messages = '%s'",
1100 escape_quotes(lc_messages
));
1101 conflines
= replace_token(conflines
, "#lc_messages = 'C'", repltok
);
1103 snprintf(repltok
, sizeof(repltok
), "lc_monetary = '%s'",
1104 escape_quotes(lc_monetary
));
1105 conflines
= replace_token(conflines
, "#lc_monetary = 'C'", repltok
);
1107 snprintf(repltok
, sizeof(repltok
), "lc_numeric = '%s'",
1108 escape_quotes(lc_numeric
));
1109 conflines
= replace_token(conflines
, "#lc_numeric = 'C'", repltok
);
1111 snprintf(repltok
, sizeof(repltok
), "lc_time = '%s'",
1112 escape_quotes(lc_time
));
1113 conflines
= replace_token(conflines
, "#lc_time = 'C'", repltok
);
1115 switch (locale_date_order(lc_time
))
1118 strcpy(repltok
, "datestyle = 'iso, ymd'");
1121 strcpy(repltok
, "datestyle = 'iso, dmy'");
1125 strcpy(repltok
, "datestyle = 'iso, mdy'");
1128 conflines
= replace_token(conflines
, "#datestyle = 'iso, mdy'", repltok
);
1130 snprintf(repltok
, sizeof(repltok
),
1131 "default_text_search_config = 'pg_catalog.%s'",
1132 escape_quotes(default_text_search_config
));
1133 conflines
= replace_token(conflines
,
1134 "#default_text_search_config = 'pg_catalog.simple'",
1137 if (default_timezone
)
1139 snprintf(repltok
, sizeof(repltok
), "timezone = '%s'",
1140 escape_quotes(default_timezone
));
1141 conflines
= replace_token(conflines
, "#timezone = 'GMT'", repltok
);
1142 snprintf(repltok
, sizeof(repltok
), "log_timezone = '%s'",
1143 escape_quotes(default_timezone
));
1144 conflines
= replace_token(conflines
, "#log_timezone = 'GMT'", repltok
);
1147 snprintf(repltok
, sizeof(repltok
), "dynamic_shared_memory_type = %s",
1148 dynamic_shared_memory_type
);
1149 conflines
= replace_token(conflines
, "#dynamic_shared_memory_type = posix",
1152 #if DEFAULT_BACKEND_FLUSH_AFTER > 0
1153 snprintf(repltok
, sizeof(repltok
), "#backend_flush_after = %dkB",
1154 DEFAULT_BACKEND_FLUSH_AFTER
* (BLCKSZ
/ 1024));
1155 conflines
= replace_token(conflines
, "#backend_flush_after = 0",
1159 #if DEFAULT_BGWRITER_FLUSH_AFTER > 0
1160 snprintf(repltok
, sizeof(repltok
), "#bgwriter_flush_after = %dkB",
1161 DEFAULT_BGWRITER_FLUSH_AFTER
* (BLCKSZ
/ 1024));
1162 conflines
= replace_token(conflines
, "#bgwriter_flush_after = 0",
1166 #if DEFAULT_CHECKPOINT_FLUSH_AFTER > 0
1167 snprintf(repltok
, sizeof(repltok
), "#checkpoint_flush_after = %dkB",
1168 DEFAULT_CHECKPOINT_FLUSH_AFTER
* (BLCKSZ
/ 1024));
1169 conflines
= replace_token(conflines
, "#checkpoint_flush_after = 0",
1173 #ifndef USE_PREFETCH
1174 conflines
= replace_token(conflines
,
1175 "#effective_io_concurrency = 1",
1176 "#effective_io_concurrency = 0");
1180 conflines
= replace_token(conflines
,
1181 "#update_process_title = on",
1182 "#update_process_title = off");
1186 * Change password_encryption setting to md5 if md5 was chosen as an
1187 * authentication method, unless scram-sha-256 was also chosen.
1189 if ((strcmp(authmethodlocal
, "md5") == 0 &&
1190 strcmp(authmethodhost
, "scram-sha-256") != 0) ||
1191 (strcmp(authmethodhost
, "md5") == 0 &&
1192 strcmp(authmethodlocal
, "scram-sha-256") != 0))
1194 conflines
= replace_token(conflines
,
1195 "#password_encryption = scram-sha-256",
1196 "password_encryption = md5");
1200 * If group access has been enabled for the cluster then it makes sense to
1201 * ensure that the log files also allow group access. Otherwise a backup
1202 * from a user in the group would fail if the log files were not
1205 if (pg_dir_create_mode
== PG_DIR_MODE_GROUP
)
1207 conflines
= replace_token(conflines
,
1208 "#log_file_mode = 0600",
1209 "log_file_mode = 0640");
1212 snprintf(path
, sizeof(path
), "%s/postgresql.conf", pg_data
);
1214 writefile(path
, conflines
);
1215 if (chmod(path
, pg_file_create_mode
) != 0)
1217 pg_log_error("could not change permissions of \"%s\": %m", path
);
1222 * create the automatic configuration file to store the configuration
1223 * parameters set by ALTER SYSTEM command. The parameters present in this
1224 * file will override the value of parameters that exists before parse of
1227 autoconflines
[0] = pg_strdup("# Do not edit this file manually!\n");
1228 autoconflines
[1] = pg_strdup("# It will be overwritten by the ALTER SYSTEM command.\n");
1229 autoconflines
[2] = NULL
;
1231 sprintf(path
, "%s/postgresql.auto.conf", pg_data
);
1233 writefile(path
, autoconflines
);
1234 if (chmod(path
, pg_file_create_mode
) != 0)
1236 pg_log_error("could not change permissions of \"%s\": %m", path
);
1245 conflines
= readfile(hba_file
);
1247 #ifndef HAVE_UNIX_SOCKETS
1248 conflines
= filter_lines_with_token(conflines
, "@remove-line-for-nolocal@");
1250 conflines
= replace_token(conflines
, "@remove-line-for-nolocal@", "");
1256 * Probe to see if there is really any platform support for IPv6, and
1257 * comment out the relevant pg_hba line if not. This avoids runtime
1258 * warnings if getaddrinfo doesn't actually cope with IPv6. Particularly
1259 * useful on Windows, where executables built on a machine with IPv6 may
1260 * have to run on a machine without.
1263 struct addrinfo
*gai_result
;
1264 struct addrinfo hints
;
1268 /* need to call WSAStartup before calling getaddrinfo */
1271 err
= WSAStartup(MAKEWORD(2, 2), &wsaData
);
1274 /* for best results, this code should match parse_hba_line() */
1275 hints
.ai_flags
= AI_NUMERICHOST
;
1276 hints
.ai_family
= AF_UNSPEC
;
1277 hints
.ai_socktype
= 0;
1278 hints
.ai_protocol
= 0;
1279 hints
.ai_addrlen
= 0;
1280 hints
.ai_canonname
= NULL
;
1281 hints
.ai_addr
= NULL
;
1282 hints
.ai_next
= NULL
;
1285 getaddrinfo("::1", NULL
, &hints
, &gai_result
) != 0)
1287 conflines
= replace_token(conflines
,
1289 "#host all all ::1");
1290 conflines
= replace_token(conflines
,
1291 "host replication all ::1",
1292 "#host replication all ::1");
1295 #else /* !HAVE_IPV6 */
1296 /* If we didn't compile IPV6 support at all, always comment it out */
1297 conflines
= replace_token(conflines
,
1299 "#host all all ::1");
1300 conflines
= replace_token(conflines
,
1301 "host replication all ::1",
1302 "#host replication all ::1");
1303 #endif /* HAVE_IPV6 */
1305 /* Replace default authentication methods */
1306 conflines
= replace_token(conflines
,
1309 conflines
= replace_token(conflines
,
1310 "@authmethodlocal@",
1313 conflines
= replace_token(conflines
,
1315 (strcmp(authmethodlocal
, "trust") == 0 || strcmp(authmethodhost
, "trust") == 0) ? AUTHTRUST_WARNING
: "");
1317 snprintf(path
, sizeof(path
), "%s/pg_hba.conf", pg_data
);
1319 writefile(path
, conflines
);
1320 if (chmod(path
, pg_file_create_mode
) != 0)
1322 pg_log_error("could not change permissions of \"%s\": %m", path
);
1330 conflines
= readfile(ident_file
);
1332 snprintf(path
, sizeof(path
), "%s/pg_ident.conf", pg_data
);
1334 writefile(path
, conflines
);
1335 if (chmod(path
, pg_file_create_mode
) != 0)
1337 pg_log_error("could not change permissions of \"%s\": %m", path
);
1348 * run the BKI script in bootstrap mode to create template1
1351 bootstrap_template1(void)
1356 char headerline
[MAXPGPATH
];
1359 printf(_("running bootstrap script ... "));
1362 bki_lines
= readfile(bki_file
);
1364 /* Check that bki file appears to be of the right version */
1366 snprintf(headerline
, sizeof(headerline
), "# PostgreSQL %s\n",
1369 if (strcmp(headerline
, *bki_lines
) != 0)
1371 pg_log_error("input file \"%s\" does not belong to PostgreSQL %s",
1372 bki_file
, PG_VERSION
);
1374 _("Check your installation or specify the correct path "
1375 "using the option -L.\n"));
1379 /* Substitute for various symbols used in the BKI file */
1381 sprintf(buf
, "%d", NAMEDATALEN
);
1382 bki_lines
= replace_token(bki_lines
, "NAMEDATALEN", buf
);
1384 sprintf(buf
, "%d", (int) sizeof(Pointer
));
1385 bki_lines
= replace_token(bki_lines
, "SIZEOF_POINTER", buf
);
1387 bki_lines
= replace_token(bki_lines
, "ALIGNOF_POINTER",
1388 (sizeof(Pointer
) == 4) ? "i" : "d");
1390 bki_lines
= replace_token(bki_lines
, "FLOAT8PASSBYVAL",
1391 FLOAT8PASSBYVAL
? "true" : "false");
1393 bki_lines
= replace_token(bki_lines
, "POSTGRES",
1394 escape_quotes_bki(username
));
1396 bki_lines
= replace_token(bki_lines
, "ENCODING",
1397 encodingid_to_string(encodingid
));
1399 bki_lines
= replace_token(bki_lines
, "LC_COLLATE",
1400 escape_quotes_bki(lc_collate
));
1402 bki_lines
= replace_token(bki_lines
, "LC_CTYPE",
1403 escape_quotes_bki(lc_ctype
));
1405 /* Also ensure backend isn't confused by this environment var: */
1406 unsetenv("PGCLIENTENCODING");
1408 snprintf(cmd
, sizeof(cmd
),
1409 "\"%s\" --boot -X %u %s %s %s %s",
1411 wal_segment_size_mb
* (1024 * 1024),
1412 data_checksums
? "-k" : "",
1413 boot_options
, extra_options
,
1414 debug
? "-d 5" : "");
1419 for (line
= bki_lines
; *line
!= NULL
; line
++)
1433 * set up the shadow password table
1436 setup_auth(FILE *cmdfd
)
1438 const char *const *line
;
1439 static const char *const pg_authid_setup
[] = {
1441 * The authid table shouldn't be readable except through views, to
1442 * ensure passwords are not publicly visible.
1444 "REVOKE ALL ON pg_authid FROM public;\n\n",
1448 for (line
= pg_authid_setup
; *line
!= NULL
; line
++)
1451 if (superuser_password
)
1452 PG_CMD_PRINTF("ALTER USER \"%s\" WITH PASSWORD E'%s';\n\n",
1453 username
, escape_quotes(superuser_password
));
1457 * get the superuser password if required
1467 * Read password from terminal
1473 pwd1
= simple_prompt("Enter new superuser password: ", false);
1474 pwd2
= simple_prompt("Enter it again: ", false);
1475 if (strcmp(pwd1
, pwd2
) != 0)
1477 fprintf(stderr
, _("Passwords didn't match.\n"));
1485 * Read password from file
1487 * Ideally this should insist that the file not be world-readable.
1488 * However, this option is mainly intended for use on Windows where
1489 * file permissions may not exist at all, so we'll skip the paranoia
1492 FILE *pwf
= fopen(pwfilename
, "r");
1496 pg_log_error("could not open file \"%s\" for reading: %m",
1500 pwd1
= pg_get_line(pwf
);
1504 pg_log_error("could not read password from file \"%s\": %m",
1507 pg_log_error("password file \"%s\" is empty",
1513 (void) pg_strip_crlf(pwd1
);
1516 superuser_password
= pwd1
;
1523 setup_depend(FILE *cmdfd
)
1525 const char *const *line
;
1526 static const char *const pg_depend_setup
[] = {
1528 * Advance the OID counter so that subsequently-created objects aren't
1531 "SELECT pg_stop_making_pinned_objects();\n\n",
1535 for (line
= pg_depend_setup
; *line
!= NULL
; line
++)
1543 setup_run_file(FILE *cmdfd
, const char *filename
)
1547 lines
= readfile(filename
);
1549 for (char **line
= lines
; *line
!= NULL
; line
++)
1555 PG_CMD_PUTS("\n\n");
1561 * fill in extra description data
1564 setup_description(FILE *cmdfd
)
1566 /* Create default descriptions for operator implementation functions */
1567 PG_CMD_PUTS("WITH funcdescs AS ( "
1568 "SELECT p.oid as p_oid, o.oid as o_oid, oprname "
1569 "FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) "
1570 "INSERT INTO pg_description "
1571 " SELECT p_oid, 'pg_proc'::regclass, 0, "
1572 " 'implementation of ' || oprname || ' operator' "
1574 " WHERE NOT EXISTS (SELECT 1 FROM pg_description "
1575 " WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass) "
1576 " AND NOT EXISTS (SELECT 1 FROM pg_description "
1577 " WHERE objoid = o_oid AND classoid = 'pg_operator'::regclass"
1578 " AND description LIKE 'deprecated%');\n\n");
1582 * populate pg_collation
1585 setup_collation(FILE *cmdfd
)
1588 * Add an SQL-standard name. We don't want to pin this, so it doesn't go
1589 * in pg_collation.h. But add it before reading system collations, so
1590 * that it wins if libc defines a locale named ucs_basic.
1592 PG_CMD_PRINTF("INSERT INTO pg_collation (oid, collname, collnamespace, collowner, collprovider, collisdeterministic, collencoding, collcollate, collctype)"
1593 "VALUES (pg_nextoid('pg_catalog.pg_collation', 'oid', 'pg_catalog.pg_collation_oid_index'), 'ucs_basic', 'pg_catalog'::regnamespace, %u, '%c', true, %d, 'C', 'C');\n\n",
1594 BOOTSTRAP_SUPERUSERID
, COLLPROVIDER_LIBC
, PG_UTF8
);
1596 /* Now import all collations we can find in the operating system */
1597 PG_CMD_PUTS("SELECT pg_import_system_collations('pg_catalog');\n\n");
1603 * We mark most system catalogs as world-readable. We don't currently have
1604 * to touch functions, languages, or databases, because their default
1605 * permissions are OK.
1607 * Some objects may require different permissions by default, so we
1608 * make sure we don't overwrite privilege sets that have already been
1611 * Also populate pg_init_privs to save what the privileges are at init
1612 * time. This is used by pg_dump to allow users to change privileges
1613 * on catalog objects and to have those privilege changes preserved
1614 * across dump/reload and pg_upgrade.
1616 * Note that pg_init_privs is only for per-database objects and therefore
1617 * we don't include databases or tablespaces.
1620 setup_privileges(FILE *cmdfd
)
1624 static char *privileges_setup
[] = {
1626 " SET relacl = (SELECT array_agg(a.acl) FROM "
1627 " (SELECT E'=r/\"$POSTGRES_SUPERUSERNAME\"' as acl "
1628 " UNION SELECT unnest(pg_catalog.acldefault("
1629 " CASE WHEN relkind = " CppAsString2(RELKIND_SEQUENCE
) " THEN 's' "
1630 " ELSE 'r' END::\"char\"," CppAsString2(BOOTSTRAP_SUPERUSERID
) "::oid))"
1632 " WHERE relkind IN (" CppAsString2(RELKIND_RELATION
) ", "
1633 CppAsString2(RELKIND_VIEW
) ", " CppAsString2(RELKIND_MATVIEW
) ", "
1634 CppAsString2(RELKIND_SEQUENCE
) ")"
1635 " AND relacl IS NULL;\n\n",
1636 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n",
1637 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n",
1638 "REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n",
1639 "INSERT INTO pg_init_privs "
1640 " (objoid, classoid, objsubid, initprivs, privtype)"
1643 " (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
1650 " relacl IS NOT NULL"
1651 " AND relkind IN (" CppAsString2(RELKIND_RELATION
) ", "
1652 CppAsString2(RELKIND_VIEW
) ", " CppAsString2(RELKIND_MATVIEW
) ", "
1653 CppAsString2(RELKIND_SEQUENCE
) ");\n\n",
1654 "INSERT INTO pg_init_privs "
1655 " (objoid, classoid, objsubid, initprivs, privtype)"
1658 " (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
1659 " pg_attribute.attnum,"
1660 " pg_attribute.attacl,"
1664 " JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)"
1666 " pg_attribute.attacl IS NOT NULL"
1667 " AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION
) ", "
1668 CppAsString2(RELKIND_VIEW
) ", " CppAsString2(RELKIND_MATVIEW
) ", "
1669 CppAsString2(RELKIND_SEQUENCE
) ");\n\n",
1670 "INSERT INTO pg_init_privs "
1671 " (objoid, classoid, objsubid, initprivs, privtype)"
1674 " (SELECT oid FROM pg_class WHERE relname = 'pg_proc'),"
1681 " proacl IS NOT NULL;\n\n",
1682 "INSERT INTO pg_init_privs "
1683 " (objoid, classoid, objsubid, initprivs, privtype)"
1686 " (SELECT oid FROM pg_class WHERE relname = 'pg_type'),"
1693 " typacl IS NOT NULL;\n\n",
1694 "INSERT INTO pg_init_privs "
1695 " (objoid, classoid, objsubid, initprivs, privtype)"
1698 " (SELECT oid FROM pg_class WHERE relname = 'pg_language'),"
1705 " lanacl IS NOT NULL;\n\n",
1706 "INSERT INTO pg_init_privs "
1707 " (objoid, classoid, objsubid, initprivs, privtype)"
1710 " (SELECT oid FROM pg_class WHERE "
1711 " relname = 'pg_largeobject_metadata'),"
1716 " pg_largeobject_metadata"
1718 " lomacl IS NOT NULL;\n\n",
1719 "INSERT INTO pg_init_privs "
1720 " (objoid, classoid, objsubid, initprivs, privtype)"
1723 " (SELECT oid FROM pg_class WHERE relname = 'pg_namespace'),"
1730 " nspacl IS NOT NULL;\n\n",
1731 "INSERT INTO pg_init_privs "
1732 " (objoid, classoid, objsubid, initprivs, privtype)"
1735 " (SELECT oid FROM pg_class WHERE "
1736 " relname = 'pg_foreign_data_wrapper'),"
1741 " pg_foreign_data_wrapper"
1743 " fdwacl IS NOT NULL;\n\n",
1744 "INSERT INTO pg_init_privs "
1745 " (objoid, classoid, objsubid, initprivs, privtype)"
1748 " (SELECT oid FROM pg_class "
1749 " WHERE relname = 'pg_foreign_server'),"
1754 " pg_foreign_server"
1756 " srvacl IS NOT NULL;\n\n",
1760 priv_lines
= replace_token(privileges_setup
, "$POSTGRES_SUPERUSERNAME",
1761 escape_quotes(username
));
1762 for (line
= priv_lines
; *line
!= NULL
; line
++)
1767 * extract the strange version of version required for information schema
1771 set_info_version(void)
1773 char *letterversion
;
1778 char *vstr
= pg_strdup(PG_VERSION
);
1781 ptr
= vstr
+ (strlen(vstr
) - 1);
1782 while (ptr
!= vstr
&& (*ptr
< '0' || *ptr
> '9'))
1784 letterversion
= ptr
+ 1;
1785 major
= strtol(vstr
, &endptr
, 10);
1787 minor
= strtol(endptr
+ 1, &endptr
, 10);
1789 micro
= strtol(endptr
+ 1, &endptr
, 10);
1790 snprintf(infoversion
, sizeof(infoversion
), "%02ld.%02ld.%04ld%s",
1791 major
, minor
, micro
, letterversion
);
1795 * load info schema and populate from features file
1798 setup_schema(FILE *cmdfd
)
1800 setup_run_file(cmdfd
, info_schema_file
);
1802 PG_CMD_PRINTF("UPDATE information_schema.sql_implementation_info "
1803 " SET character_value = '%s' "
1804 " WHERE implementation_info_name = 'DBMS VERSION';\n\n",
1807 PG_CMD_PRINTF("COPY information_schema.sql_features "
1808 " (feature_id, feature_name, sub_feature_id, "
1809 " sub_feature_name, is_supported, comments) "
1811 escape_quotes(features_file
));
1815 * load PL/pgSQL server-side language
1818 load_plpgsql(FILE *cmdfd
)
1820 PG_CMD_PUTS("CREATE EXTENSION plpgsql;\n\n");
1824 * clean everything up in template1
1827 vacuum_db(FILE *cmdfd
)
1829 /* Run analyze before VACUUM so the statistics are frozen. */
1830 PG_CMD_PUTS("ANALYZE;\n\nVACUUM FREEZE;\n\n");
1834 * copy template1 to template0
1837 make_template0(FILE *cmdfd
)
1839 const char *const *line
;
1840 static const char *const template0_setup
[] = {
1841 "CREATE DATABASE template0 IS_TEMPLATE = true ALLOW_CONNECTIONS = false;\n\n",
1844 * We use the OID of template0 to determine datlastsysoid
1846 "UPDATE pg_database SET datlastsysoid = "
1847 " (SELECT oid FROM pg_database "
1848 " WHERE datname = 'template0');\n\n",
1851 * Explicitly revoke public create-schema and create-temp-table
1852 * privileges in template1 and template0; else the latter would be on
1855 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n\n",
1856 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n\n",
1858 "COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n\n",
1861 * Finally vacuum to clean up dead rows in pg_database
1863 "VACUUM pg_database;\n\n",
1867 for (line
= template0_setup
; *line
; line
++)
1872 * copy template1 to postgres
1875 make_postgres(FILE *cmdfd
)
1877 const char *const *line
;
1878 static const char *const postgres_setup
[] = {
1879 "CREATE DATABASE postgres;\n\n",
1880 "COMMENT ON DATABASE postgres IS 'default administrative connection database';\n\n",
1884 for (line
= postgres_setup
; *line
; line
++)
1889 * signal handler in case we are interrupted.
1891 * The Windows runtime docs at
1892 * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/signal
1893 * specifically forbid a number of things being done from a signal handler,
1894 * including IO, memory allocation and system calls, and only allow jmpbuf
1895 * if you are handling SIGFPE.
1897 * I avoided doing the forbidden things by setting a flag instead of calling
1900 * Also note the behaviour of Windows with SIGINT, which says this:
1901 * SIGINT is not supported for any Win32 application. When a CTRL+C interrupt
1902 * occurs, Win32 operating systems generate a new thread to specifically
1903 * handle that interrupt. This can cause a single-thread application, such as
1904 * one in UNIX, to become multithreaded and cause unexpected behavior.
1906 * I have no idea how to handle this. (Strange they call UNIX an application!)
1907 * So this will need some testing on Windows.
1912 /* handle systems that reset the handler, like Windows (grr) */
1913 pqsignal(signum
, trapsig
);
1914 caught_signal
= true;
1918 * call exit() if we got a signal, or else output "ok".
1925 printf(_("caught signal\n"));
1929 else if (output_failed
)
1931 printf(_("could not write to child process: %s\n"),
1932 strerror(output_errno
));
1938 /* all seems well */
1944 /* Hack to suppress a warning about %x from some versions of gcc */
1945 static inline size_t
1946 my_strftime(char *s
, size_t max
, const char *fmt
, const struct tm
*tm
)
1948 return strftime(s
, max
, fmt
, tm
);
1952 * Determine likely date order from locale
1955 locale_date_order(const char *locale
)
1966 result
= DATEORDER_MDY
; /* default */
1968 save
= setlocale(LC_TIME
, NULL
);
1971 save
= pg_strdup(save
);
1973 setlocale(LC_TIME
, locale
);
1975 memset(&testtime
, 0, sizeof(testtime
));
1976 testtime
.tm_mday
= 22;
1977 testtime
.tm_mon
= 10; /* November, should come out as "11" */
1978 testtime
.tm_year
= 133; /* 2033 */
1980 res
= my_strftime(buf
, sizeof(buf
), "%x", &testtime
);
1982 setlocale(LC_TIME
, save
);
1988 posM
= strstr(buf
, "11");
1989 posD
= strstr(buf
, "22");
1990 posY
= strstr(buf
, "33");
1992 if (!posM
|| !posD
|| !posY
)
1995 if (posY
< posM
&& posM
< posD
)
1996 result
= DATEORDER_YMD
;
1997 else if (posD
< posM
)
1998 result
= DATEORDER_DMY
;
2000 result
= DATEORDER_MDY
;
2006 * Verify that locale name is valid for the locale category.
2008 * If successful, and canonname isn't NULL, a malloc'd copy of the locale's
2009 * canonical name is stored there. This is especially useful for figuring out
2010 * what locale name "" means (ie, the environment value). (Actually,
2011 * it seems that on most implementations that's the only thing it's good for;
2012 * we could wish that setlocale gave back a canonically spelled version of
2013 * the locale name, but typically it doesn't.)
2015 * this should match the backend's check_locale() function
2018 check_locale_name(int category
, const char *locale
, char **canonname
)
2024 *canonname
= NULL
; /* in case of failure */
2026 save
= setlocale(category
, NULL
);
2029 pg_log_error("setlocale() failed");
2033 /* save may be pointing at a modifiable scratch variable, so copy it. */
2034 save
= pg_strdup(save
);
2036 /* for setlocale() call */
2040 /* set the locale with setlocale, to see if it accepts it. */
2041 res
= setlocale(category
, locale
);
2043 /* save canonical name if requested. */
2044 if (res
&& canonname
)
2045 *canonname
= pg_strdup(res
);
2047 /* restore old value. */
2048 if (!setlocale(category
, save
))
2050 pg_log_error("failed to restore old locale \"%s\"", save
);
2055 /* complain if locale wasn't valid */
2059 pg_log_error("invalid locale name \"%s\"", locale
);
2063 * If no relevant switch was given on command line, locale is an
2064 * empty string, which is not too helpful to report. Presumably
2065 * setlocale() found something it did not like in the environment.
2066 * Ideally we'd report the bad environment variable, but since
2067 * setlocale's behavior is implementation-specific, it's hard to
2068 * be sure what it didn't like. Print a safe generic message.
2070 pg_log_error("invalid locale settings; check LANG and LC_* environment variables");
2077 * check if the chosen encoding matches the encoding required by the locale
2079 * this should match the similar check in the backend createdb() function
2082 check_locale_encoding(const char *locale
, int user_enc
)
2086 locale_enc
= pg_get_encoding_from_locale(locale
, true);
2088 /* See notes in createdb() to understand these tests */
2089 if (!(locale_enc
== user_enc
||
2090 locale_enc
== PG_SQL_ASCII
||
2093 user_enc
== PG_UTF8
||
2095 user_enc
== PG_SQL_ASCII
))
2097 pg_log_error("encoding mismatch");
2099 _("The encoding you selected (%s) and the encoding that the\n"
2100 "selected locale uses (%s) do not match. This would lead to\n"
2101 "misbehavior in various character string processing functions.\n"
2102 "Rerun %s and either do not specify an encoding explicitly,\n"
2103 "or choose a matching combination.\n"),
2104 pg_encoding_to_char(user_enc
),
2105 pg_encoding_to_char(locale_enc
),
2113 * set up the locale variables
2115 * assumes we have called setlocale(LC_ALL, "") -- see set_pglocale_pgservice
2122 /* set empty lc_* values to locale config if set */
2129 lc_collate
= locale
;
2131 lc_numeric
= locale
;
2135 lc_monetary
= locale
;
2137 lc_messages
= locale
;
2141 * canonicalize locale names, and obtain any missing values from our
2142 * current environment
2145 check_locale_name(LC_CTYPE
, lc_ctype
, &canonname
);
2146 lc_ctype
= canonname
;
2147 check_locale_name(LC_COLLATE
, lc_collate
, &canonname
);
2148 lc_collate
= canonname
;
2149 check_locale_name(LC_NUMERIC
, lc_numeric
, &canonname
);
2150 lc_numeric
= canonname
;
2151 check_locale_name(LC_TIME
, lc_time
, &canonname
);
2152 lc_time
= canonname
;
2153 check_locale_name(LC_MONETARY
, lc_monetary
, &canonname
);
2154 lc_monetary
= canonname
;
2155 #if defined(LC_MESSAGES) && !defined(WIN32)
2156 check_locale_name(LC_MESSAGES
, lc_messages
, &canonname
);
2157 lc_messages
= canonname
;
2159 /* when LC_MESSAGES is not available, use the LC_CTYPE setting */
2160 check_locale_name(LC_CTYPE
, lc_messages
, &canonname
);
2161 lc_messages
= canonname
;
2169 usage(const char *progname
)
2171 printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname
);
2172 printf(_("Usage:\n"));
2173 printf(_(" %s [OPTION]... [DATADIR]\n"), progname
);
2174 printf(_("\nOptions:\n"));
2175 printf(_(" -A, --auth=METHOD default authentication method for local connections\n"));
2176 printf(_(" --auth-host=METHOD default authentication method for local TCP/IP connections\n"));
2177 printf(_(" --auth-local=METHOD default authentication method for local-socket connections\n"));
2178 printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n"));
2179 printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n"));
2180 printf(_(" -g, --allow-group-access allow group read/execute on data directory\n"));
2181 printf(_(" -k, --data-checksums use data page checksums\n"));
2182 printf(_(" --locale=LOCALE set default locale for new databases\n"));
2183 printf(_(" --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n"
2184 " --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n"
2185 " set default locale in the respective category for\n"
2186 " new databases (default taken from environment)\n"));
2187 printf(_(" --no-locale equivalent to --locale=C\n"));
2188 printf(_(" --pwfile=FILE read password for the new superuser from file\n"));
2189 printf(_(" -T, --text-search-config=CFG\n"
2190 " default text search configuration\n"));
2191 printf(_(" -U, --username=NAME database superuser name\n"));
2192 printf(_(" -W, --pwprompt prompt for a password for the new superuser\n"));
2193 printf(_(" -X, --waldir=WALDIR location for the write-ahead log directory\n"));
2194 printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
2195 printf(_("\nLess commonly used options:\n"));
2196 printf(_(" -d, --debug generate lots of debugging output\n"));
2197 printf(_(" --discard-caches set debug_discard_caches=1\n"));
2198 printf(_(" -L DIRECTORY where to find the input files\n"));
2199 printf(_(" -n, --no-clean do not clean up after errors\n"));
2200 printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n"));
2201 printf(_(" --no-instructions do not print instructions for next steps\n"));
2202 printf(_(" -s, --show show internal settings\n"));
2203 printf(_(" -S, --sync-only only sync database files to disk, then exit\n"));
2204 printf(_("\nOther options:\n"));
2205 printf(_(" -V, --version output version information, then exit\n"));
2206 printf(_(" -?, --help show this help, then exit\n"));
2207 printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
2209 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
2210 printf(_("%s home page: <%s>\n"), PACKAGE_NAME
, PACKAGE_URL
);
2214 check_authmethod_unspecified(const char **authmethod
)
2216 if (*authmethod
== NULL
)
2219 *authmethod
= "trust";
2224 check_authmethod_valid(const char *authmethod
, const char *const *valid_methods
, const char *conntype
)
2226 const char *const *p
;
2228 for (p
= valid_methods
; *p
; p
++)
2230 if (strcmp(authmethod
, *p
) == 0)
2232 /* with space = param */
2233 if (strchr(authmethod
, ' '))
2234 if (strncmp(authmethod
, *p
, (authmethod
- strchr(authmethod
, ' '))) == 0)
2238 pg_log_error("invalid authentication method \"%s\" for \"%s\" connections",
2239 authmethod
, conntype
);
2244 check_need_password(const char *authmethodlocal
, const char *authmethodhost
)
2246 if ((strcmp(authmethodlocal
, "md5") == 0 ||
2247 strcmp(authmethodlocal
, "password") == 0 ||
2248 strcmp(authmethodlocal
, "scram-sha-256") == 0) &&
2249 (strcmp(authmethodhost
, "md5") == 0 ||
2250 strcmp(authmethodhost
, "password") == 0 ||
2251 strcmp(authmethodhost
, "scram-sha-256") == 0) &&
2252 !(pwprompt
|| pwfilename
))
2254 pg_log_error("must specify a password for the superuser to enable password authentication");
2263 char *pgdata_get_env
;
2267 pgdata_get_env
= getenv("PGDATA");
2268 if (pgdata_get_env
&& strlen(pgdata_get_env
))
2271 pg_data
= pg_strdup(pgdata_get_env
);
2275 pg_log_error("no data directory specified");
2277 _("You must identify the directory where the data for this database system\n"
2278 "will reside. Do this with either the invocation option -D or the\n"
2279 "environment variable PGDATA.\n"));
2284 pgdata_native
= pg_strdup(pg_data
);
2285 canonicalize_path(pg_data
);
2288 * we have to set PGDATA for postgres rather than pass it on the command
2289 * line to avoid dumb quoting problems on Windows, and we would especially
2290 * need quotes otherwise on Windows because paths there are most likely to
2291 * have embedded spaces.
2293 if (setenv("PGDATA", pg_data
, 1) != 0)
2295 pg_log_error("could not set environment");
2302 setup_bin_paths(const char *argv0
)
2306 if ((ret
= find_other_exec(argv0
, "postgres", PG_BACKEND_VERSIONSTR
,
2309 char full_path
[MAXPGPATH
];
2311 if (find_my_exec(argv0
, full_path
) < 0)
2312 strlcpy(full_path
, progname
, sizeof(full_path
));
2315 pg_log_error("The program \"%s\" is needed by %s but was not found in the\n"
2316 "same directory as \"%s\".\n"
2317 "Check your installation.",
2318 "postgres", progname
, full_path
);
2320 pg_log_error("The program \"%s\" was found by \"%s\"\n"
2321 "but was not the same version as %s.\n"
2322 "Check your installation.",
2323 "postgres", full_path
, progname
);
2327 /* store binary directory */
2328 strcpy(bin_path
, backend_exec
);
2329 *last_dir_separator(bin_path
) = '\0';
2330 canonicalize_path(bin_path
);
2334 share_path
= pg_malloc(MAXPGPATH
);
2335 get_share_path(backend_exec
, share_path
);
2337 else if (!is_absolute_path(share_path
))
2339 pg_log_error("input file location must be an absolute path");
2343 canonicalize_path(share_path
);
2347 setup_locale_encoding(void)
2351 if (strcmp(lc_ctype
, lc_collate
) == 0 &&
2352 strcmp(lc_ctype
, lc_time
) == 0 &&
2353 strcmp(lc_ctype
, lc_numeric
) == 0 &&
2354 strcmp(lc_ctype
, lc_monetary
) == 0 &&
2355 strcmp(lc_ctype
, lc_messages
) == 0)
2356 printf(_("The database cluster will be initialized with locale \"%s\".\n"), lc_ctype
);
2359 printf(_("The database cluster will be initialized with locales\n"
2378 ctype_enc
= pg_get_encoding_from_locale(lc_ctype
, true);
2380 if (ctype_enc
== -1)
2382 /* Couldn't recognize the locale's codeset */
2383 pg_log_error("could not find suitable encoding for locale \"%s\"",
2385 fprintf(stderr
, _("Rerun %s with the -E option.\n"), progname
);
2386 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
2390 else if (!pg_valid_server_encoding_id(ctype_enc
))
2393 * We recognized it, but it's not a legal server encoding. On
2394 * Windows, UTF-8 works with any locale, so we can fall back to
2398 encodingid
= PG_UTF8
;
2399 printf(_("Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n"
2400 "The default database encoding will be set to \"%s\" instead.\n"),
2401 pg_encoding_to_char(ctype_enc
),
2402 pg_encoding_to_char(encodingid
));
2404 pg_log_error("locale \"%s\" requires unsupported encoding \"%s\"",
2405 lc_ctype
, pg_encoding_to_char(ctype_enc
));
2407 _("Encoding \"%s\" is not allowed as a server-side encoding.\n"
2408 "Rerun %s with a different locale selection.\n"),
2409 pg_encoding_to_char(ctype_enc
), progname
);
2415 encodingid
= ctype_enc
;
2416 printf(_("The default database encoding has accordingly been set to \"%s\".\n"),
2417 pg_encoding_to_char(encodingid
));
2421 encodingid
= get_encoding_id(encoding
);
2423 if (!check_locale_encoding(lc_ctype
, encodingid
) ||
2424 !check_locale_encoding(lc_collate
, encodingid
))
2425 exit(1); /* check_locale_encoding printed the error */
2431 setup_data_file_paths(void)
2433 set_input(&bki_file
, "postgres.bki");
2434 set_input(&hba_file
, "pg_hba.conf.sample");
2435 set_input(&ident_file
, "pg_ident.conf.sample");
2436 set_input(&conf_file
, "postgresql.conf.sample");
2437 set_input(&dictionary_file
, "snowball_create.sql");
2438 set_input(&info_schema_file
, "information_schema.sql");
2439 set_input(&features_file
, "sql_features.txt");
2440 set_input(&system_constraints_file
, "system_constraints.sql");
2441 set_input(&system_functions_file
, "system_functions.sql");
2442 set_input(&system_views_file
, "system_views.sql");
2444 if (show_setting
|| debug
)
2448 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
2449 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
2450 "POSTGRESQL_CONF_SAMPLE=%s\n"
2451 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
2453 pg_data
, share_path
, bin_path
,
2456 hba_file
, ident_file
);
2461 check_input(bki_file
);
2462 check_input(hba_file
);
2463 check_input(ident_file
);
2464 check_input(conf_file
);
2465 check_input(dictionary_file
);
2466 check_input(info_schema_file
);
2467 check_input(features_file
);
2468 check_input(system_constraints_file
);
2469 check_input(system_functions_file
);
2470 check_input(system_views_file
);
2475 setup_text_search(void)
2477 if (!default_text_search_config
)
2479 default_text_search_config
= find_matching_ts_config(lc_ctype
);
2480 if (!default_text_search_config
)
2482 pg_log_info("could not find suitable text search configuration for locale \"%s\"",
2484 default_text_search_config
= "simple";
2489 const char *checkmatch
= find_matching_ts_config(lc_ctype
);
2491 if (checkmatch
== NULL
)
2493 pg_log_warning("suitable text search configuration for locale \"%s\" is unknown",
2496 else if (strcmp(checkmatch
, default_text_search_config
) != 0)
2498 pg_log_warning("specified text search configuration \"%s\" might not match locale \"%s\"",
2499 default_text_search_config
, lc_ctype
);
2503 printf(_("The default text search configuration will be set to \"%s\".\n"),
2504 default_text_search_config
);
2512 /* some of these are not valid on Windows */
2514 pqsignal(SIGHUP
, trapsig
);
2517 pqsignal(SIGINT
, trapsig
);
2520 pqsignal(SIGQUIT
, trapsig
);
2523 pqsignal(SIGTERM
, trapsig
);
2526 /* Ignore SIGPIPE when writing to backend, so we can clean up */
2528 pqsignal(SIGPIPE
, SIG_IGN
);
2531 /* Prevent SIGSYS so we can probe for kernel calls that might not work */
2533 pqsignal(SIGSYS
, SIG_IGN
);
2539 create_data_directory(void)
2543 switch ((ret
= pg_check_dir(pg_data
)))
2546 /* PGDATA not there, must create it */
2547 printf(_("creating directory %s ... "),
2551 if (pg_mkdir_p(pg_data
, pg_dir_create_mode
) != 0)
2553 pg_log_error("could not create directory \"%s\": %m", pg_data
);
2559 made_new_pgdata
= true;
2563 /* Present but empty, fix permissions and use it */
2564 printf(_("fixing permissions on existing directory %s ... "),
2568 if (chmod(pg_data
, pg_dir_create_mode
) != 0)
2570 pg_log_error("could not change permissions of directory \"%s\": %m",
2577 found_existing_pgdata
= true;
2583 /* Present and not empty */
2584 pg_log_error("directory \"%s\" exists but is not empty", pg_data
);
2586 warn_on_mount_point(ret
);
2589 _("If you want to create a new database system, either remove or empty\n"
2590 "the directory \"%s\" or run %s\n"
2591 "with an argument other than \"%s\".\n"),
2592 pg_data
, progname
, pg_data
);
2593 exit(1); /* no further message needed */
2596 /* Trouble accessing directory */
2597 pg_log_error("could not access directory \"%s\": %m", pg_data
);
2603 /* Create WAL directory, and symlink if required */
2605 create_xlog_or_symlink(void)
2609 /* form name of the place for the subdirectory or symlink */
2610 subdirloc
= psprintf("%s/pg_wal", pg_data
);
2616 /* clean up xlog directory name, check it's absolute */
2617 canonicalize_path(xlog_dir
);
2618 if (!is_absolute_path(xlog_dir
))
2620 pg_log_error("WAL directory location must be an absolute path");
2624 /* check if the specified xlog directory exists/is empty */
2625 switch ((ret
= pg_check_dir(xlog_dir
)))
2628 /* xlog directory not there, must create it */
2629 printf(_("creating directory %s ... "),
2633 if (pg_mkdir_p(xlog_dir
, pg_dir_create_mode
) != 0)
2635 pg_log_error("could not create directory \"%s\": %m",
2642 made_new_xlogdir
= true;
2646 /* Present but empty, fix permissions and use it */
2647 printf(_("fixing permissions on existing directory %s ... "),
2651 if (chmod(xlog_dir
, pg_dir_create_mode
) != 0)
2653 pg_log_error("could not change permissions of directory \"%s\": %m",
2660 found_existing_xlogdir
= true;
2666 /* Present and not empty */
2667 pg_log_error("directory \"%s\" exists but is not empty", xlog_dir
);
2669 warn_on_mount_point(ret
);
2672 _("If you want to store the WAL there, either remove or empty the directory\n"
2678 /* Trouble accessing directory */
2679 pg_log_error("could not access directory \"%s\": %m", xlog_dir
);
2684 if (symlink(xlog_dir
, subdirloc
) != 0)
2686 pg_log_error("could not create symbolic link \"%s\": %m",
2691 pg_log_error("symlinks are not supported on this platform");
2697 /* Without -X option, just make the subdirectory normally */
2698 if (mkdir(subdirloc
, pg_dir_create_mode
) < 0)
2700 pg_log_error("could not create directory \"%s\": %m",
2711 warn_on_mount_point(int error
)
2715 _("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n"));
2716 else if (error
== 3)
2718 _("It contains a lost+found directory, perhaps due to it being a mount point.\n"));
2721 _("Using a mount point directly as the data directory is not recommended.\n"
2722 "Create a subdirectory under the mount point.\n"));
2727 initialize_data_directory(void)
2735 * Set mask based on requested PGDATA permissions. pg_mode_mask, and
2736 * friends like pg_dir_create_mode, are set to owner-only by default and
2737 * then updated if -g is passed in by calling SetDataDirectoryCreatePerm()
2738 * when parsing our options (see above).
2740 umask(pg_mode_mask
);
2742 create_data_directory();
2744 create_xlog_or_symlink();
2746 /* Create required subdirectories (other than pg_wal) */
2747 printf(_("creating subdirectories ... "));
2750 for (i
= 0; i
< lengthof(subdirs
); i
++)
2754 path
= psprintf("%s/%s", pg_data
, subdirs
[i
]);
2757 * The parent directory already exists, so we only need mkdir() not
2758 * pg_mkdir_p() here, which avoids some failure modes; cf bug #13853.
2760 if (mkdir(path
, pg_dir_create_mode
) < 0)
2762 pg_log_error("could not create directory \"%s\": %m", path
);
2771 /* Top level PG_VERSION is checked by bootstrapper, so make it first */
2772 write_version_file(NULL
);
2774 /* Select suitable configuration settings */
2776 test_config_settings();
2778 /* Now create all the text config files */
2781 /* Bootstrap template1 */
2782 bootstrap_template1();
2785 * Make the per-database PG_VERSION for template1 only after init'ing it
2787 write_version_file("base/1");
2790 * Create the stuff we don't need to use bootstrap mode for, using a
2791 * backend running in simple standalone mode.
2793 fputs(_("performing post-bootstrap initialization ... "), stdout
);
2796 snprintf(cmd
, sizeof(cmd
),
2797 "\"%s\" %s %s template1 >%s",
2798 backend_exec
, backend_options
, extra_options
,
2805 setup_run_file(cmdfd
, system_constraints_file
);
2807 setup_run_file(cmdfd
, system_functions_file
);
2809 setup_depend(cmdfd
);
2812 * Note that no objects created after setup_depend() will be "pinned".
2813 * They are all droppable at the whim of the DBA.
2816 setup_run_file(cmdfd
, system_views_file
);
2818 setup_description(cmdfd
);
2820 setup_collation(cmdfd
);
2822 setup_run_file(cmdfd
, dictionary_file
);
2824 setup_privileges(cmdfd
);
2826 setup_schema(cmdfd
);
2828 load_plpgsql(cmdfd
);
2832 make_template0(cmdfd
);
2834 make_postgres(cmdfd
);
2843 main(int argc
, char *argv
[])
2845 static struct option long_options
[] = {
2846 {"pgdata", required_argument
, NULL
, 'D'},
2847 {"encoding", required_argument
, NULL
, 'E'},
2848 {"locale", required_argument
, NULL
, 1},
2849 {"lc-collate", required_argument
, NULL
, 2},
2850 {"lc-ctype", required_argument
, NULL
, 3},
2851 {"lc-monetary", required_argument
, NULL
, 4},
2852 {"lc-numeric", required_argument
, NULL
, 5},
2853 {"lc-time", required_argument
, NULL
, 6},
2854 {"lc-messages", required_argument
, NULL
, 7},
2855 {"no-locale", no_argument
, NULL
, 8},
2856 {"text-search-config", required_argument
, NULL
, 'T'},
2857 {"auth", required_argument
, NULL
, 'A'},
2858 {"auth-local", required_argument
, NULL
, 10},
2859 {"auth-host", required_argument
, NULL
, 11},
2860 {"pwprompt", no_argument
, NULL
, 'W'},
2861 {"pwfile", required_argument
, NULL
, 9},
2862 {"username", required_argument
, NULL
, 'U'},
2863 {"help", no_argument
, NULL
, '?'},
2864 {"version", no_argument
, NULL
, 'V'},
2865 {"debug", no_argument
, NULL
, 'd'},
2866 {"show", no_argument
, NULL
, 's'},
2867 {"noclean", no_argument
, NULL
, 'n'}, /* for backwards compatibility */
2868 {"no-clean", no_argument
, NULL
, 'n'},
2869 {"nosync", no_argument
, NULL
, 'N'}, /* for backwards compatibility */
2870 {"no-sync", no_argument
, NULL
, 'N'},
2871 {"no-instructions", no_argument
, NULL
, 13},
2872 {"sync-only", no_argument
, NULL
, 'S'},
2873 {"waldir", required_argument
, NULL
, 'X'},
2874 {"wal-segsize", required_argument
, NULL
, 12},
2875 {"data-checksums", no_argument
, NULL
, 'k'},
2876 {"allow-group-access", no_argument
, NULL
, 'g'},
2877 {"discard-caches", no_argument
, NULL
, 14},
2882 * options with no short version return a low integer, the rest return
2883 * their short version value
2887 char *effective_user
;
2888 PQExpBuffer start_db_cmd
;
2889 char pg_ctl_path
[MAXPGPATH
];
2892 * Ensure that buffering behavior of stdout matches what it is in
2893 * interactive usage (at least on most platforms). This prevents
2894 * unexpected output ordering when, eg, output is redirected to a file.
2895 * POSIX says we must do this before any other usage of these files.
2897 setvbuf(stdout
, NULL
, PG_IOLBF
, 0);
2899 pg_logging_init(argv
[0]);
2900 progname
= get_progname(argv
[0]);
2901 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("initdb"));
2905 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
2910 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
2912 puts("initdb (PostgreSQL) " PG_VERSION
);
2917 /* process command-line options */
2919 while ((c
= getopt_long(argc
, argv
, "A:dD:E:gkL:nNsST:U:WX:", long_options
, &option_index
)) != -1)
2924 authmethodlocal
= authmethodhost
= pg_strdup(optarg
);
2927 * When ident is specified, use peer for local connections.
2928 * Mirrored, when peer is specified, use ident for TCP/IP
2931 if (strcmp(authmethodhost
, "ident") == 0)
2932 authmethodlocal
= "peer";
2933 else if (strcmp(authmethodlocal
, "peer") == 0)
2934 authmethodhost
= "ident";
2937 authmethodlocal
= pg_strdup(optarg
);
2940 authmethodhost
= pg_strdup(optarg
);
2943 pg_data
= pg_strdup(optarg
);
2946 encoding
= pg_strdup(optarg
);
2952 username
= pg_strdup(optarg
);
2956 printf(_("Running in debug mode.\n"));
2960 printf(_("Running in no-clean mode. Mistakes will not be cleaned up.\n"));
2969 data_checksums
= true;
2972 share_path
= pg_strdup(optarg
);
2975 locale
= pg_strdup(optarg
);
2978 lc_collate
= pg_strdup(optarg
);
2981 lc_ctype
= pg_strdup(optarg
);
2984 lc_monetary
= pg_strdup(optarg
);
2987 lc_numeric
= pg_strdup(optarg
);
2990 lc_time
= pg_strdup(optarg
);
2993 lc_messages
= pg_strdup(optarg
);
2999 pwfilename
= pg_strdup(optarg
);
3002 show_setting
= true;
3005 default_text_search_config
= pg_strdup(optarg
);
3008 xlog_dir
= pg_strdup(optarg
);
3011 str_wal_segment_size_mb
= pg_strdup(optarg
);
3014 noinstructions
= true;
3017 SetDataDirectoryCreatePerm(PG_DIR_MODE_GROUP
);
3020 extra_options
= psprintf("%s %s",
3022 "-c debug_discard_caches=1");
3025 /* getopt_long already emitted a complaint */
3026 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
3034 * Non-option argument specifies data directory as long as it wasn't
3035 * already specified with -D / --pgdata
3037 if (optind
< argc
&& !pg_data
)
3039 pg_data
= pg_strdup(argv
[optind
]);
3045 pg_log_error("too many command-line arguments (first is \"%s\")",
3047 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
3052 atexit(cleanup_directories_atexit
);
3054 /* If we only need to fsync, just do it and exit */
3059 /* must check that directory is readable */
3060 if (pg_check_dir(pg_data
) <= 0)
3062 pg_log_error("could not access directory \"%s\": %m", pg_data
);
3066 fputs(_("syncing data to disk ... "), stdout
);
3068 fsync_pgdata(pg_data
, PG_VERSION_NUM
);
3073 if (pwprompt
&& pwfilename
)
3075 pg_log_error("password prompt and password file cannot be specified together");
3079 check_authmethod_unspecified(&authmethodlocal
);
3080 check_authmethod_unspecified(&authmethodhost
);
3082 check_authmethod_valid(authmethodlocal
, auth_methods_local
, "local");
3083 check_authmethod_valid(authmethodhost
, auth_methods_host
, "host");
3085 check_need_password(authmethodlocal
, authmethodhost
);
3087 /* set wal segment size */
3088 if (str_wal_segment_size_mb
== NULL
)
3089 wal_segment_size_mb
= (DEFAULT_XLOG_SEG_SIZE
) / (1024 * 1024);
3094 /* check that the argument is a number */
3095 wal_segment_size_mb
= strtol(str_wal_segment_size_mb
, &endptr
, 10);
3097 /* verify that wal segment size is valid */
3098 if (endptr
== str_wal_segment_size_mb
|| *endptr
!= '\0')
3100 pg_log_error("argument of --wal-segsize must be a number");
3103 if (!IsValidWalSegSize(wal_segment_size_mb
* 1024 * 1024))
3105 pg_log_error("argument of --wal-segsize must be a power of 2 between 1 and 1024");
3110 get_restricted_token();
3114 setup_bin_paths(argv
[0]);
3116 effective_user
= get_id();
3118 username
= effective_user
;
3120 if (strncmp(username
, "pg_", 3) == 0)
3122 pg_log_error("superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"", username
);
3126 printf(_("The files belonging to this database system will be owned "
3128 "This user must also own the server process.\n\n"),
3133 setup_data_file_paths();
3135 setup_locale_encoding();
3137 setup_text_search();
3142 printf(_("Data page checksums are enabled.\n"));
3144 printf(_("Data page checksums are disabled.\n"));
3146 if (pwprompt
|| pwfilename
)
3151 initialize_data_directory();
3155 fputs(_("syncing data to disk ... "), stdout
);
3157 fsync_pgdata(pg_data
, PG_VERSION_NUM
);
3161 printf(_("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n"));
3166 pg_log_warning("enabling \"trust\" authentication for local connections");
3167 fprintf(stderr
, _("You can change this by editing pg_hba.conf or using the option -A, or\n"
3168 "--auth-local and --auth-host, the next time you run initdb.\n"));
3171 if (!noinstructions
)
3174 * Build up a shell command to tell the user how to start the server
3176 start_db_cmd
= createPQExpBuffer();
3178 /* Get directory specification used to start initdb ... */
3179 strlcpy(pg_ctl_path
, argv
[0], sizeof(pg_ctl_path
));
3180 canonicalize_path(pg_ctl_path
);
3181 get_parent_directory(pg_ctl_path
);
3182 /* ... and tag on pg_ctl instead */
3183 join_path_components(pg_ctl_path
, pg_ctl_path
, "pg_ctl");
3185 /* Convert the path to use native separators */
3186 make_native_path(pg_ctl_path
);
3188 /* path to pg_ctl, properly quoted */
3189 appendShellString(start_db_cmd
, pg_ctl_path
);
3191 /* add -D switch, with properly quoted data directory */
3192 appendPQExpBufferStr(start_db_cmd
, " -D ");
3193 appendShellString(start_db_cmd
, pgdata_native
);
3195 /* add suggested -l switch and "start" command */
3196 /* translator: This is a placeholder in a shell command. */
3197 appendPQExpBuffer(start_db_cmd
, " -l %s start", _("logfile"));
3199 printf(_("\nSuccess. You can now start the database server using:\n\n"
3201 start_db_cmd
->data
);
3203 destroyPQExpBuffer(start_db_cmd
);