LCOV - code coverage report
Current view: top level - src/bin/pg_upgrade - option.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 61.4 % 233 143
Test Date: 2026-07-16 11:17:59 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 37.3 % 110 41

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

Generated by: LCOV version 2.0-1