Backport from PostgreSQL12 Upstream commit: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=2d34ad84303181111c6f0747186857ff50106267 diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c index c74eb25e18..92a2ed5e4c 100644 --- a/src/bin/pg_upgrade/option.c +++ b/src/bin/pg_upgrade/option.c @@ -21,8 +21,9 @@ static void usage(void); -static void check_required_directory(char **dirpath, char **configpath, - char *envVarName, char *cmdLineOption, char *description); +static void check_required_directory(char **dirpath, + const char *envVarName, bool useCwd, + const char *cmdLineOption, const char *description); #define FIX_DEFAULT_READ_ONLY "-c default_transaction_read_only=false" @@ -52,6 +53,7 @@ parseCommandLine(int argc, char *argv[]) {"link", no_argument, NULL, 'k'}, {"retain", no_argument, NULL, 'r'}, {"jobs", required_argument, NULL, 'j'}, + {"socketdir", required_argument, NULL, 's'}, {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} }; @@ -100,7 +102,7 @@ parseCommandLine(int argc, char *argv[]) if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL) pg_fatal("could not write to log file \"%s\"\n", INTERNAL_LOG_FILE); - while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rU:v", + while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rs:U:v", long_options, &optindex)) != -1) { switch (option) @@ -119,12 +121,10 @@ parseCommandLine(int argc, char *argv[]) case 'd': old_cluster.pgdata = pg_strdup(optarg); - old_cluster.pgconfig = pg_strdup(optarg); break; case 'D': new_cluster.pgdata = pg_strdup(optarg); - new_cluster.pgconfig = pg_strdup(optarg); break; case 'j': @@ -186,6 +186,10 @@ parseCommandLine(int argc, char *argv[]) log_opts.retain = true; break; + case 's': + user_opts.socketdir = pg_strdup(optarg); + break; + case 'U': pg_free(os_info.user); os_info.user = pg_strdup(optarg); @@ -238,14 +242,16 @@ parseCommandLine(int argc, char *argv[]) pg_putenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY); /* Get values from env if not already set */ - check_required_directory(&old_cluster.bindir, NULL, "PGBINOLD", "-b", - _("old cluster binaries reside")); - check_required_directory(&new_cluster.bindir, NULL, "PGBINNEW", "-B", - _("new cluster binaries reside")); - check_required_directory(&old_cluster.pgdata, &old_cluster.pgconfig, - "PGDATAOLD", "-d", _("old cluster data resides")); - check_required_directory(&new_cluster.pgdata, &new_cluster.pgconfig, - "PGDATANEW", "-D", _("new cluster data resides")); + check_required_directory(&old_cluster.bindir, "PGBINOLD", false, + "-b", _("old cluster binaries reside")); + check_required_directory(&new_cluster.bindir, "PGBINNEW", false, + "-B", _("new cluster binaries reside")); + check_required_directory(&old_cluster.pgdata, "PGDATAOLD", false, + "-d", _("old cluster data resides")); + check_required_directory(&new_cluster.pgdata, "PGDATANEW", false, + "-D", _("new cluster data resides")); + check_required_directory(&user_opts.socketdir, "PGSOCKETDIR", true, + "-s", _("sockets will be created")); #ifdef WIN32 @@ -290,6 +296,7 @@ usage(void) printf(_(" -p, --old-port=PORT old cluster port number (default %d)\n"), old_cluster.port); printf(_(" -P, --new-port=PORT new cluster port number (default %d)\n"), new_cluster.port); printf(_(" -r, --retain retain SQL and log files after success\n")); + printf(_(" -s, --socketdir=DIR socket directory to use (default CWD)\n")); printf(_(" -U, --username=NAME cluster superuser (default \"%s\")\n"), os_info.user); printf(_(" -v, --verbose enable verbose internal logging\n")); printf(_(" -V, --version display version information, then exit\n")); @@ -330,29 +337,32 @@ usage(void) * check_required_directory() * * Checks a directory option. - * dirpath - the directory name supplied on the command line - * configpath - optional configuration directory + * dirpath - the directory name supplied on the command line, or NULL * envVarName - the name of an environment variable to get if dirpath is NULL - * cmdLineOption - the command line option corresponds to this directory (-o, -O, -n, -N) + * useCwd - true if OK to default to CWD + * cmdLineOption - the command line option for this directory * description - a description of this directory option * * We use the last two arguments to construct a meaningful error message if the * user hasn't provided the required directory name. */ static void -check_required_directory(char **dirpath, char **configpath, - char *envVarName, char *cmdLineOption, - char *description) +check_required_directory(char **dirpath, const char *envVarName, bool useCwd, + const char *cmdLineOption, const char *description) { if (*dirpath == NULL || strlen(*dirpath) == 0) { const char *envVar; if ((envVar = getenv(envVarName)) && strlen(envVar)) + *dirpath = pg_strdup(envVar); + else if (useCwd) { - *dirpath = pg_strdup(envVar); - if (configpath) - *configpath = pg_strdup(envVar); + char cwd[MAXPGPATH]; + + if (!getcwd(cwd, MAXPGPATH)) + pg_fatal("could not determine current directory\n"); + *dirpath = pg_strdup(cwd); } else pg_fatal("You must identify the directory where the %s.\n" @@ -361,16 +371,10 @@ check_required_directory(char **dirpath, char **configpath, } /* - * Trim off any trailing path separators because we construct paths by - * appending to this path. + * Clean up the path, in particular trimming any trailing path separators, + * because we construct paths by appending to this path. */ -#ifndef WIN32 - if ((*dirpath)[strlen(*dirpath) - 1] == '/') -#else - if ((*dirpath)[strlen(*dirpath) - 1] == '/' || - (*dirpath)[strlen(*dirpath) - 1] == '\\') -#endif - (*dirpath)[strlen(*dirpath) - 1] = 0; + canonicalize_path(*dirpath); } /* @@ -379,6 +383,10 @@ check_required_directory(char **dirpath, char **configpath, * If a configuration-only directory was specified, find the real data dir * by querying the running server. This has limited checking because we * can't check for a running server because we can't find postmaster.pid. + * + * On entry, cluster->pgdata has been set from command line or env variable, + * but cluster->pgconfig isn't set. We fill both variables with corrected + * values. */ void adjust_data_dir(ClusterInfo *cluster) @@ -389,6 +397,9 @@ adjust_data_dir(ClusterInfo *cluster) FILE *fp, *output; + /* Initially assume config dir and data dir are the same */ + cluster->pgconfig = pg_strdup(cluster->pgdata); + /* If there is no postgresql.conf, it can't be a config-only dir */ snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig); if ((fp = fopen(filename, "r")) == NULL) @@ -455,12 +466,7 @@ get_sock_dir(ClusterInfo *cluster, bool live_check) if (GET_MAJOR_VERSION(cluster->major_version) >= 901) { if (!live_check) - { - /* Use the current directory for the socket */ - cluster->sockdir = pg_malloc(MAXPGPATH); - if (!getcwd(cluster->sockdir, MAXPGPATH)) - pg_fatal("could not determine current directory\n"); - } + cluster->sockdir = user_opts.socketdir; else { /* diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index dccc3e3b63..65a9166414 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -297,7 +297,8 @@ typedef struct bool check; /* TRUE -> ask user for permission to make * changes */ transferMode transfer_mode; /* copy files or link them? */ - int jobs; + int jobs; /* number of processes/threads to use */ + char *socketdir; /* directory to use for Unix sockets */ } UserOpts;