| 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 | |
| 23 | static void usage(void); |
| 24 | static 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 | |
| 30 | UserOpts user_opts; |
| 31 | |
| 32 | |
| 33 | /* |
| 34 | * parseCommandLine() |
| 35 | * |
| 36 | * Parses the command line (argc, argv[]) and loads structures |
| 37 | */ |
| 38 | void |
| 39 | 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 | {"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 | |
| 288 | static void |
| 289 | usage(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 | */ |
| 358 | static void |
| 359 | check_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 | */ |
| 400 | void |
| 401 | adjust_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 | */ |
| 466 | void |
| 467 | get_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 | |