LCOV - code coverage report
Current view: top level - src/bin/pg_upgrade - option.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 127 228 55.7 %
Date: 2025-02-22 07:14:56 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14