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