From 9aca51250681d2e8d18ed1d73e7cd1283d1cf303 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 4 Apr 2014 18:42:13 -0400 Subject: [PATCH] Make sure -D is an absolute path when starting server on Windows. This is needed because Windows services may get started with a different current directory than where pg_ctl is executed. We want relative -D paths to be interpreted relative to pg_ctl's CWD, similarly to what happens on other platforms. In support of this, move the backend's make_absolute_path() function into src/port/path.c (where it probably should have been long since) and get rid of the rather inferior version in pg_regress. Kumar Rajeev Rastogi, reviewed by MauMau --- src/backend/utils/init/miscinit.c | 71 ------------------- src/bin/pg_ctl/pg_ctl.c | 14 +++- src/include/miscadmin.h | 1 - src/include/port.h | 1 + src/port/path.c | 111 +++++++++++++++++++++++++++++- src/test/regress/pg_regress.c | 27 -------- 6 files changed, 124 insertions(+), 101 deletions(-) diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index c17bca8306..6115ce3f33 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -117,77 +117,6 @@ ChangeToDataDir(void) DataDir))); } -/* - * If the given pathname isn't already absolute, make it so, interpreting - * it relative to the current working directory. - * - * Also canonicalizes the path. The result is always a malloc'd copy. - * - * Note: interpretation of relative-path arguments during postmaster startup - * should happen before doing ChangeToDataDir(), else the user will probably - * not like the results. - */ -char * -make_absolute_path(const char *path) -{ - char *new; - - /* Returning null for null input is convenient for some callers */ - if (path == NULL) - return NULL; - - if (!is_absolute_path(path)) - { - char *buf; - size_t buflen; - - buflen = MAXPGPATH; - for (;;) - { - buf = malloc(buflen); - if (!buf) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - - if (getcwd(buf, buflen)) - break; - else if (errno == ERANGE) - { - free(buf); - buflen *= 2; - continue; - } - else - { - free(buf); - elog(FATAL, "could not get current working directory: %m"); - } - } - - new = malloc(strlen(buf) + strlen(path) + 2); - if (!new) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - sprintf(new, "%s/%s", buf, path); - free(buf); - } - else - { - new = strdup(path); - if (!new) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - } - - /* Make sure punctuation is canonical, too */ - canonicalize_path(new); - - return new; -} - /* ---------------------------------------------------------------- * User ID state diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 56d238f394..1f921819c2 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -1387,7 +1387,19 @@ pgwin32_CommandLine(bool registration) register_servicename); if (pg_config) - appendPQExpBuffer(cmdLine, " -D \"%s\"", pg_config); + { + /* We need the -D path to be absolute */ + char *dataDir; + + if ((dataDir = make_absolute_path(pg_config)) == NULL) + { + /* make_absolute_path already reported the error */ + exit(1); + } + make_native_path(dataDir); + appendPQExpBuffer(cmdLine, " -D \"%s\"", dataDir); + free(dataDir); + } if (registration && do_wait) appendPQExpBuffer(cmdLine, " -w"); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 947906a280..0d61b82eb5 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -296,7 +296,6 @@ extern void SetCurrentRoleId(Oid roleid, bool is_superuser); extern void SetDataDir(const char *dir); extern void ChangeToDataDir(void); -extern char *make_absolute_path(const char *path); /* in utils/misc/superuser.c */ extern bool superuser(void); /* current user is superuser */ diff --git a/src/include/port.h b/src/include/port.h index aeb7754cb0..06986858b6 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -45,6 +45,7 @@ extern void make_native_path(char *path); extern bool path_contains_parent_reference(const char *path); extern bool path_is_relative_and_below_cwd(const char *path); extern bool path_is_prefix_of_path(const char *path1, const char *path2); +extern char *make_absolute_path(const char *path); extern const char *get_progname(const char *argv0); extern void get_share_path(const char *my_exec_path, char *ret_path); extern void get_etc_path(const char *my_exec_path, char *ret_path); diff --git a/src/port/path.c b/src/port/path.c index 39d6e43404..438b529604 100644 --- a/src/port/path.c +++ b/src/port/path.c @@ -13,7 +13,11 @@ *------------------------------------------------------------------------- */ -#include "c.h" +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif #include #include @@ -549,6 +553,111 @@ no_match: } +/* + * make_absolute_path + * + * If the given pathname isn't already absolute, make it so, interpreting + * it relative to the current working directory. + * + * Also canonicalizes the path. The result is always a malloc'd copy. + * + * In backend, failure cases result in ereport(ERROR); in frontend, + * we write a complaint on stderr and return NULL. + * + * Note: interpretation of relative-path arguments during postmaster startup + * should happen before doing ChangeToDataDir(), else the user will probably + * not like the results. + */ +char * +make_absolute_path(const char *path) +{ + char *new; + + /* Returning null for null input is convenient for some callers */ + if (path == NULL) + return NULL; + + if (!is_absolute_path(path)) + { + char *buf; + size_t buflen; + + buflen = MAXPGPATH; + for (;;) + { + buf = malloc(buflen); + if (!buf) + { +#ifndef FRONTEND + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); +#else + fprintf(stderr, _("out of memory\n")); + return NULL; +#endif + } + + if (getcwd(buf, buflen)) + break; + else if (errno == ERANGE) + { + free(buf); + buflen *= 2; + continue; + } + else + { + free(buf); +#ifndef FRONTEND + elog(ERROR, "could not get current working directory: %m"); +#else + fprintf(stderr, _("could not get current working directory: %s\n"), + strerror(errno)); + return NULL; +#endif + } + } + + new = malloc(strlen(buf) + strlen(path) + 2); + if (!new) + { + free(buf); +#ifndef FRONTEND + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); +#else + fprintf(stderr, _("out of memory\n")); + return NULL; +#endif + } + sprintf(new, "%s/%s", buf, path); + free(buf); + } + else + { + new = strdup(path); + if (!new) + { +#ifndef FRONTEND + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); +#else + fprintf(stderr, _("out of memory\n")); + return NULL; +#endif + } + } + + /* Make sure punctuation is canonical, too */ + canonicalize_path(new); + + return new; +} + + /* * get_share_path */ diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index abde5b477c..07dd8037ac 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -1855,33 +1855,6 @@ create_role(const char *rolename, const _stringlist * granted_dbs) } } -static char * -make_absolute_path(const char *in) -{ - char *result; - - if (is_absolute_path(in)) - result = strdup(in); - else - { - static char cwdbuf[MAXPGPATH]; - - if (!cwdbuf[0]) - { - if (!getcwd(cwdbuf, sizeof(cwdbuf))) - { - fprintf(stderr, _("could not get current working directory: %s\n"), strerror(errno)); - exit(2); - } - } - - result = psprintf("%s/%s", cwdbuf, in); - } - - canonicalize_path(result); - return result; -} - static void help(void) {