Bug Summary

File:bin/initdb/initdb.c
Warning:line 1405, column 12
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

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