Make sure -D is an absolute path when starting server on Windows.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 4 Apr 2014 22:42:13 +0000 (18:42 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 4 Apr 2014 22:42:13 +0000 (18:42 -0400)
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
src/bin/pg_ctl/pg_ctl.c
src/include/miscadmin.h
src/include/port.h
src/port/path.c
src/test/regress/pg_regress.c

index c17bca8306161b143f1515ab8cd0db76171d89b2..6115ce3f3373640d48bc9be9d0c0ab7858f69122 100644 (file)
@@ -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
index 56d238f39481da3c8bd5043e8889a3e58cfdca84..1f921819c23563bc9068fb1bab83ba2bec61627d 100644 (file)
@@ -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");
index 947906a280546b81a855f4ebfcb3f4c80889abcc..0d61b82eb50d9df67c16a2c8dca6fdbe52535f26 100644 (file)
@@ -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 */
index aeb7754cb0940b4fb0355ba015f98f3ab40fc681..06986858b60d88d459190f1e2ca8918618da9882 100644 (file)
@@ -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);
index 39d6e43404a65eca8b41de7ead942ba04c709bbb..438b52960423bfec077e78e7d80246fffa4899ac 100644 (file)
  *-------------------------------------------------------------------------
  */
 
-#include "c.h"
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
 
 #include <ctype.h>
 #include <sys/stat.h>
@@ -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
  */
index abde5b477c670068e051315e04650af365b2a92f..07dd8037ac3f3323a869cc8bbaa1aad37302061d 100644 (file)
@@ -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)
 {