1/*
2 * opt.c
3 *
4 * options functions
5 *
6 * Copyright (c) 2010-2019, PostgreSQL Global Development Group
7 * src/bin/pg_upgrade/option.c
8 */
9
10#include "postgres_fe.h"
11
12#include <time.h>
13#ifdef WIN32
14#include <io.h>
15#endif
16
17#include "getopt_long.h"
18#include "utils/pidfile.h"
19
20#include "pg_upgrade.h"
21
22
23static void usage(void);
24static void check_required_directory(char **dirpath,
25 const char *envVarName, bool useCwd,
26 const char *cmdLineOption, const char *description);
27#define FIX_DEFAULT_READ_ONLY "-c default_transaction_read_only=false"
28
29
30UserOpts user_opts;
31
32
33/*
34 * parseCommandLine()
35 *
36 * Parses the command line (argc, argv[]) and loads structures
37 */
38void
39parseCommandLine(int argc, char *argv[])
40{
41 static struct option long_options[] = {
42 {"old-datadir", required_argument, NULL, 'd'},
43 {"new-datadir", required_argument, NULL, 'D'},
44 {"old-bindir", required_argument, NULL, 'b'},
45 {"new-bindir", required_argument, NULL, 'B'},
46 {"old-options", required_argument, NULL, 'o'},
47 {"new-options", required_argument, NULL, 'O'},
48 {"old-port", required_argument, NULL, 'p'},
49 {"new-port", required_argument, NULL, 'P'},
50
51 {"username", required_argument, NULL, 'U'},
52 {"check", no_argument, NULL, 'c'},
53 {"link", no_argument, NULL, 'k'},
54 {"retain", no_argument, NULL, 'r'},
55 {"jobs", required_argument, NULL, 'j'},
56 {"socketdir", required_argument, NULL, 's'},
57 {"verbose", no_argument, NULL, 'v'},
58 {"clone", no_argument, NULL, 1},
59
60 {NULL, 0, NULL, 0}
61 };
62 int option; /* Command line option */
63 int optindex = 0; /* used by getopt_long */
64 int os_user_effective_id;
65 FILE *fp;
66 char **filename;
67 time_t run_time = time(NULL);
68
69 user_opts.transfer_mode = TRANSFER_MODE_COPY;
70
71 os_info.progname = get_progname(argv[0]);
72
73 /* Process libpq env. variables; load values here for usage() output */
74 old_cluster.port = getenv("PGPORTOLD") ? atoi(getenv("PGPORTOLD")) : DEF_PGUPORT;
75 new_cluster.port = getenv("PGPORTNEW") ? atoi(getenv("PGPORTNEW")) : DEF_PGUPORT;
76
77 os_user_effective_id = get_user_info(&os_info.user);
78 /* we override just the database user name; we got the OS id above */
79 if (getenv("PGUSER"))
80 {
81 pg_free(os_info.user);
82 /* must save value, getenv()'s pointer is not stable */
83 os_info.user = pg_strdup(getenv("PGUSER"));
84 }
85
86 if (argc > 1)
87 {
88 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
89 {
90 usage();
91 exit(0);
92 }
93 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
94 {
95 puts("pg_upgrade (PostgreSQL) " PG_VERSION);
96 exit(0);
97 }
98 }
99
100 /* Allow help and version to be run as root, so do the test here. */
101 if (os_user_effective_id == 0)
102 pg_fatal("%s: cannot be run as root\n", os_info.progname);
103
104 while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rs:U:v",
105 long_options, &optindex)) != -1)
106 {
107 switch (option)
108 {
109 case 'b':
110 old_cluster.bindir = pg_strdup(optarg);
111 break;
112
113 case 'B':
114 new_cluster.bindir = pg_strdup(optarg);
115 break;
116
117 case 'c':
118 user_opts.check = true;
119 break;
120
121 case 'd':
122 old_cluster.pgdata = pg_strdup(optarg);
123 break;
124
125 case 'D':
126 new_cluster.pgdata = pg_strdup(optarg);
127 break;
128
129 case 'j':
130 user_opts.jobs = atoi(optarg);
131 break;
132
133 case 'k':
134 user_opts.transfer_mode = TRANSFER_MODE_LINK;
135 break;
136
137 case 'o':
138 /* append option? */
139 if (!old_cluster.pgopts)
140 old_cluster.pgopts = pg_strdup(optarg);
141 else
142 {
143 char *old_pgopts = old_cluster.pgopts;
144
145 old_cluster.pgopts = psprintf("%s %s", old_pgopts, optarg);
146 free(old_pgopts);
147 }
148 break;
149
150 case 'O':
151 /* append option? */
152 if (!new_cluster.pgopts)
153 new_cluster.pgopts = pg_strdup(optarg);
154 else
155 {
156 char *new_pgopts = new_cluster.pgopts;
157
158 new_cluster.pgopts = psprintf("%s %s", new_pgopts, optarg);
159 free(new_pgopts);
160 }
161 break;
162
163 /*
164 * Someday, the port number option could be removed and passed
165 * using -o/-O, but that requires postmaster -C to be
166 * supported on all old/new versions (added in PG 9.2).
167 */
168 case 'p':
169 if ((old_cluster.port = atoi(optarg)) <= 0)
170 {
171 pg_fatal("invalid old port number\n");
172 exit(1);
173 }
174 break;
175
176 case 'P':
177 if ((new_cluster.port = atoi(optarg)) <= 0)
178 {
179 pg_fatal("invalid new port number\n");
180 exit(1);
181 }
182 break;
183
184 case 'r':
185 log_opts.retain = true;
186 break;
187
188 case 's':
189 user_opts.socketdir = pg_strdup(optarg);
190 break;
191
192 case 'U':
193 pg_free(os_info.user);
194 os_info.user = pg_strdup(optarg);
195 os_info.user_specified = true;
196
197 /*
198 * Push the user name into the environment so pre-9.1
199 * pg_ctl/libpq uses it.
200 */
201 pg_putenv("PGUSER", os_info.user);
202 break;
203
204 case 'v':
205 log_opts.verbose = true;
206 break;
207
208 case 1:
209 user_opts.transfer_mode = TRANSFER_MODE_CLONE;
210 break;
211
212 default:
213 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
214 os_info.progname);
215 exit(1);
216 }
217 }
218
219 if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL)
220 pg_fatal("could not open log file \"%s\": %m\n", INTERNAL_LOG_FILE);
221
222 if (log_opts.verbose)
223 pg_log(PG_REPORT, "Running in verbose mode\n");
224
225 /* label start of upgrade in logfiles */
226 for (filename = output_files; *filename != NULL; filename++)
227 {
228 if ((fp = fopen_priv(*filename, "a")) == NULL)
229 pg_fatal("could not write to log file \"%s\": %m\n", *filename);
230
231 /* Start with newline because we might be appending to a file. */
232 fprintf(fp, "\n"
233 "-----------------------------------------------------------------\n"
234 " pg_upgrade run on %s"
235 "-----------------------------------------------------------------\n\n",
236 ctime(&run_time));
237 fclose(fp);
238 }
239
240 /* Turn off read-only mode; add prefix to PGOPTIONS? */
241 if (getenv("PGOPTIONS"))
242 {
243 char *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
244 getenv("PGOPTIONS"));
245
246 pg_putenv("PGOPTIONS", pgoptions);
247 pfree(pgoptions);
248 }
249 else
250 pg_putenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY);
251
252 /* Get values from env if not already set */
253 check_required_directory(&old_cluster.bindir, "PGBINOLD", false,
254 "-b", _("old cluster binaries reside"));
255 check_required_directory(&new_cluster.bindir, "PGBINNEW", false,
256 "-B", _("new cluster binaries reside"));
257 check_required_directory(&old_cluster.pgdata, "PGDATAOLD", false,
258 "-d", _("old cluster data resides"));
259 check_required_directory(&new_cluster.pgdata, "PGDATANEW", false,
260 "-D", _("new cluster data resides"));
261 check_required_directory(&user_opts.socketdir, "PGSOCKETDIR", true,
262 "-s", _("sockets will be created"));
263
264#ifdef WIN32
265
266 /*
267 * On Windows, initdb --sync-only will fail with a "Permission denied"
268 * error on file pg_upgrade_utility.log if pg_upgrade is run inside the
269 * new cluster directory, so we do a check here.
270 */
271 {
272 char cwd[MAXPGPATH],
273 new_cluster_pgdata[MAXPGPATH];
274
275 strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
276 canonicalize_path(new_cluster_pgdata);
277
278 if (!getcwd(cwd, MAXPGPATH))
279 pg_fatal("could not determine current directory\n");
280 canonicalize_path(cwd);
281 if (path_is_prefix_of_path(new_cluster_pgdata, cwd))
282 pg_fatal("cannot run pg_upgrade from inside the new cluster data directory on Windows\n");
283 }
284#endif
285}
286
287
288static void
289usage(void)
290{
291 printf(_("pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n\n"));
292 printf(_("Usage:\n"));
293 printf(_(" pg_upgrade [OPTION]...\n\n"));
294 printf(_("Options:\n"));
295 printf(_(" -b, --old-bindir=BINDIR old cluster executable directory\n"));
296 printf(_(" -B, --new-bindir=BINDIR new cluster executable directory\n"));
297 printf(_(" -c, --check check clusters only, don't change any data\n"));
298 printf(_(" -d, --old-datadir=DATADIR old cluster data directory\n"));
299 printf(_(" -D, --new-datadir=DATADIR new cluster data directory\n"));
300 printf(_(" -j, --jobs number of simultaneous processes or threads to use\n"));
301 printf(_(" -k, --link link instead of copying files to new cluster\n"));
302 printf(_(" -o, --old-options=OPTIONS old cluster options to pass to the server\n"));
303 printf(_(" -O, --new-options=OPTIONS new cluster options to pass to the server\n"));
304 printf(_(" -p, --old-port=PORT old cluster port number (default %d)\n"), old_cluster.port);
305 printf(_(" -P, --new-port=PORT new cluster port number (default %d)\n"), new_cluster.port);
306 printf(_(" -r, --retain retain SQL and log files after success\n"));
307 printf(_(" -s, --socketdir=DIR socket directory to use (default current dir.)\n"));
308 printf(_(" -U, --username=NAME cluster superuser (default \"%s\")\n"), os_info.user);
309 printf(_(" -v, --verbose enable verbose internal logging\n"));
310 printf(_(" -V, --version display version information, then exit\n"));
311 printf(_(" --clone clone instead of copying files to new cluster\n"));
312 printf(_(" -?, --help show this help, then exit\n"));
313 printf(_("\n"
314 "Before running pg_upgrade you must:\n"
315 " create a new database cluster (using the new version of initdb)\n"
316 " shutdown the postmaster servicing the old cluster\n"
317 " shutdown the postmaster servicing the new cluster\n"));
318 printf(_("\n"
319 "When you run pg_upgrade, you must provide the following information:\n"
320 " the data directory for the old cluster (-d DATADIR)\n"
321 " the data directory for the new cluster (-D DATADIR)\n"
322 " the \"bin\" directory for the old version (-b BINDIR)\n"
323 " the \"bin\" directory for the new version (-B BINDIR)\n"));
324 printf(_("\n"
325 "For example:\n"
326 " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n"
327 "or\n"));
328#ifndef WIN32
329 printf(_(" $ export PGDATAOLD=oldCluster/data\n"
330 " $ export PGDATANEW=newCluster/data\n"
331 " $ export PGBINOLD=oldCluster/bin\n"
332 " $ export PGBINNEW=newCluster/bin\n"
333 " $ pg_upgrade\n"));
334#else
335 printf(_(" C:\\> set PGDATAOLD=oldCluster/data\n"
336 " C:\\> set PGDATANEW=newCluster/data\n"
337 " C:\\> set PGBINOLD=oldCluster/bin\n"
338 " C:\\> set PGBINNEW=newCluster/bin\n"
339 " C:\\> pg_upgrade\n"));
340#endif
341 printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
342}
343
344
345/*
346 * check_required_directory()
347 *
348 * Checks a directory option.
349 * dirpath - the directory name supplied on the command line, or NULL
350 * envVarName - the name of an environment variable to get if dirpath is NULL
351 * useCwd - true if OK to default to CWD
352 * cmdLineOption - the command line option for this directory
353 * description - a description of this directory option
354 *
355 * We use the last two arguments to construct a meaningful error message if the
356 * user hasn't provided the required directory name.
357 */
358static void
359check_required_directory(char **dirpath, const char *envVarName, bool useCwd,
360 const char *cmdLineOption, const char *description)
361{
362 if (*dirpath == NULL || strlen(*dirpath) == 0)
363 {
364 const char *envVar;
365
366 if ((envVar = getenv(envVarName)) && strlen(envVar))
367 *dirpath = pg_strdup(envVar);
368 else if (useCwd)
369 {
370 char cwd[MAXPGPATH];
371
372 if (!getcwd(cwd, MAXPGPATH))
373 pg_fatal("could not determine current directory\n");
374 *dirpath = pg_strdup(cwd);
375 }
376 else
377 pg_fatal("You must identify the directory where the %s.\n"
378 "Please use the %s command-line option or the %s environment variable.\n",
379 description, cmdLineOption, envVarName);
380 }
381
382 /*
383 * Clean up the path, in particular trimming any trailing path separators,
384 * because we construct paths by appending to this path.
385 */
386 canonicalize_path(*dirpath);
387}
388
389/*
390 * adjust_data_dir
391 *
392 * If a configuration-only directory was specified, find the real data dir
393 * by querying the running server. This has limited checking because we
394 * can't check for a running server because we can't find postmaster.pid.
395 *
396 * On entry, cluster->pgdata has been set from command line or env variable,
397 * but cluster->pgconfig isn't set. We fill both variables with corrected
398 * values.
399 */
400void
401adjust_data_dir(ClusterInfo *cluster)
402{
403 char filename[MAXPGPATH];
404 char cmd[MAXPGPATH],
405 cmd_output[MAX_STRING];
406 FILE *fp,
407 *output;
408
409 /* Initially assume config dir and data dir are the same */
410 cluster->pgconfig = pg_strdup(cluster->pgdata);
411
412 /* If there is no postgresql.conf, it can't be a config-only dir */
413 snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig);
414 if ((fp = fopen(filename, "r")) == NULL)
415 return;
416 fclose(fp);
417
418 /* If PG_VERSION exists, it can't be a config-only dir */
419 snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig);
420 if ((fp = fopen(filename, "r")) != NULL)
421 {
422 fclose(fp);
423 return;
424 }
425
426 /* Must be a configuration directory, so find the real data directory. */
427
428 if (cluster == &old_cluster)
429 prep_status("Finding the real data directory for the source cluster");
430 else
431 prep_status("Finding the real data directory for the target cluster");
432
433 /*
434 * We don't have a data directory yet, so we can't check the PG version,
435 * so this might fail --- only works for PG 9.2+. If this fails,
436 * pg_upgrade will fail anyway because the data files will not be found.
437 */
438 snprintf(cmd, sizeof(cmd), "\"%s/postgres\" -D \"%s\" -C data_directory",
439 cluster->bindir, cluster->pgconfig);
440
441 if ((output = popen(cmd, "r")) == NULL ||
442 fgets(cmd_output, sizeof(cmd_output), output) == NULL)
443 pg_fatal("could not get data directory using %s: %s\n",
444 cmd, strerror(errno));
445
446 pclose(output);
447
448 /* Remove trailing newline */
449 if (strchr(cmd_output, '\n') != NULL)
450 *strchr(cmd_output, '\n') = '\0';
451
452 cluster->pgdata = pg_strdup(cmd_output);
453
454 check_ok();
455}
456
457
458/*
459 * get_sock_dir
460 *
461 * Identify the socket directory to use for this cluster. If we're doing
462 * a live check (old cluster only), we need to find out where the postmaster
463 * is listening. Otherwise, we're going to put the socket into the current
464 * directory.
465 */
466void
467get_sock_dir(ClusterInfo *cluster, bool live_check)
468{
469#ifdef HAVE_UNIX_SOCKETS
470
471 /*
472 * sockdir and port were added to postmaster.pid in PG 9.1. Pre-9.1 cannot
473 * process pg_ctl -w for sockets in non-default locations.
474 */
475 if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
476 {
477 if (!live_check)
478 cluster->sockdir = user_opts.socketdir;
479 else
480 {
481 /*
482 * If we are doing a live check, we will use the old cluster's
483 * Unix domain socket directory so we can connect to the live
484 * server.
485 */
486 unsigned short orig_port = cluster->port;
487 char filename[MAXPGPATH],
488 line[MAXPGPATH];
489 FILE *fp;
490 int lineno;
491
492 snprintf(filename, sizeof(filename), "%s/postmaster.pid",
493 cluster->pgdata);
494 if ((fp = fopen(filename, "r")) == NULL)
495 pg_fatal("could not open file \"%s\": %s\n",
496 filename, strerror(errno));
497
498 for (lineno = 1;
499 lineno <= Max(LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR);
500 lineno++)
501 {
502 if (fgets(line, sizeof(line), fp) == NULL)
503 pg_fatal("could not read line %d from file \"%s\": %s\n",
504 lineno, filename, strerror(errno));
505
506 /* potentially overwrite user-supplied value */
507 if (lineno == LOCK_FILE_LINE_PORT)
508 sscanf(line, "%hu", &old_cluster.port);
509 if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
510 {
511 cluster->sockdir = pg_strdup(line);
512 /* strip off newline */
513 if (strchr(cluster->sockdir, '\n') != NULL)
514 *strchr(cluster->sockdir, '\n') = '\0';
515 }
516 }
517 fclose(fp);
518
519 /* warn of port number correction */
520 if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
521 pg_log(PG_WARNING, "user-supplied old port number %hu corrected to %hu\n",
522 orig_port, cluster->port);
523 }
524 }
525 else
526
527 /*
528 * Can't get sockdir and pg_ctl -w can't use a non-default, use
529 * default
530 */
531 cluster->sockdir = NULL;
532#else /* !HAVE_UNIX_SOCKETS */
533 cluster->sockdir = NULL;
534#endif
535}
536