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
This commit is contained in:
Tom Lane 2014-04-04 18:42:13 -04:00
parent 8120c7452a
commit 9aca512506
6 changed files with 124 additions and 101 deletions

View 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

View 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");

View 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 */

View 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);

View File

@ -13,7 +13,11 @@
*-------------------------------------------------------------------------
*/
#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
*/

View 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)
{