From ffd210505e1a331a8c6980a4032178a42e6f797a Mon Sep 17 00:00:00 2001 From: Michael P Date: Thu, 14 Apr 2011 15:21:14 +0900 Subject: Fix for bug 2990360: relative path to working directory for gtm Fix an issue with GTM path when its binary is called with a relative path Ex: ./bin/gtm -D data-gtm This was causing gtm to quit with a FATAL error because it was not able to find gtm data repository correctly. Patch written by Benny Wang --- src/gtm/main/main.c | 26 +++++++++++++++++++ src/gtm/path/path.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ src/gtm/proxy/proxy_main.c | 26 +++++++++++++++++++ src/include/gtm/path.h | 5 ++++ 4 files changed, 119 insertions(+) diff --git a/src/gtm/main/main.c b/src/gtm/main/main.c index 80f35b32ae..9bfa9da475 100644 --- a/src/gtm/main/main.c +++ b/src/gtm/main/main.c @@ -26,6 +26,7 @@ #include "gtm/gtm_c.h" #include "gtm/gtm.h" +#include "gtm/path.h" #include "gtm/elog.h" #include "gtm/memutils.h" #include "gtm/gtm_list.h" @@ -84,6 +85,7 @@ static void GTM_UnregisterPGXCNode(Port *myport, GTM_PGXCNodeId pgxc_node_id); static bool CreateOptsFile(int argc, char *argv[]); static void CreateDataDirLockFile(void); static void CreateLockFile(const char *filename, const char *refName); +static void SetDataDir(void); static void ChangeToDataDir(void); static void checkDataDir(void); static void DeleteLockFile(const char *filename); @@ -143,6 +145,7 @@ BaseInit() MemoryContextInit(); checkDataDir(); + SetDataDir(); ChangeToDataDir(); CreateDataDirLockFile(); @@ -1180,6 +1183,29 @@ retry: #endif } +/* + * Set data directory, but make sure it's an absolute path. Use this, + * never set DataDir directly. + */ +void +SetDataDir() +{ + char *new; + + /* If presented path is relative, convert to absolute */ + new = make_absolute_path(GTMDataDir); + if (!new) + ereport(FATAL, + (errno, + errmsg("failed to set the data directory \"%s\"", + GTMDataDir))); + + if (GTMDataDir) + free(GTMDataDir); + + GTMDataDir = new; +} + /* * Change working directory to DataDir. Most of the postmaster and backend * code assumes that we are in DataDir so it can use relative paths to access diff --git a/src/gtm/path/path.c b/src/gtm/path/path.c index 11c62908ab..4a3298b3d7 100644 --- a/src/gtm/path/path.c +++ b/src/gtm/path/path.c @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -175,3 +176,64 @@ trim_trailing_separator(char *path) for (p--; p > path && IS_DIR_SEP(*p); p--) *p = '\0'; } +/* + * If the given pathname isn't already absolute, make it so, interpreting + * it relative to the current working directory. + * + * Also canonicalize the path. The result is always a malloc'd copy. + * + */ +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) + return NULL; + + if (getcwd(buf, buflen)) + break; + else if (errno == ERANGE) + { + free(buf); + buflen *= 2; + continue; + } + else + { + free(buf); + return NULL; + } + } + + new = malloc(strlen(buf) + strlen(path) + 2); + if (!new) + return NULL; + sprintf(new, "%s/%s", buf, path); + free(buf); + } + else + { + new = strdup(path); + if (!new) + return NULL; + } + + /* Make sure punctuation is canonical, too */ + canonicalize_path(new); + + return new; +} diff --git a/src/gtm/proxy/proxy_main.c b/src/gtm/proxy/proxy_main.c index f1e8553dd6..e7632e15d8 100644 --- a/src/gtm/proxy/proxy_main.c +++ b/src/gtm/proxy/proxy_main.c @@ -24,6 +24,7 @@ #include #include "gtm/gtm_c.h" +#include "gtm/path.h" #include "gtm/gtm_proxy.h" #include "gtm/register.h" #include "gtm/elog.h" @@ -112,6 +113,7 @@ static void GTMProxy_CommandPending(GTMProxy_ConnectionInfo *conninfo, static bool CreateOptsFile(int argc, char *argv[]); static void CreateDataDirLockFile(void); static void CreateLockFile(const char *filename, const char *refName); +static void SetDataDir(void); static void ChangeToDataDir(void); static void checkDataDir(void); static void DeleteLockFile(const char *filename); @@ -174,6 +176,7 @@ BaseInit() MemoryContextInit(); checkDataDir(); + SetDataDir(); ChangeToDataDir(); CreateDataDirLockFile(); @@ -2007,6 +2010,29 @@ retry: #endif } +/* + * Set data directory, but make sure it's an absolute path. Use this, + * never set DataDir directly. + */ +void +SetDataDir() +{ + char *new; + + /* If presented path is relative, convert to absolute */ + new = make_absolute_path(GTMProxyDataDir); + if (!new) + ereport(FATAL, + (errno, + errmsg("failed to set the data directory \"%s\"", + GTMProxyDataDir))); + + if (GTMProxyDataDir) + free(GTMProxyDataDir); + + GTMProxyDataDir = new; +} + /* * Change working directory to DataDir. Most of the postmaster and backend * code assumes that we are in DataDir so it can use relative paths to access diff --git a/src/include/gtm/path.h b/src/include/gtm/path.h index e95ca5e86b..cc07813ace 100644 --- a/src/include/gtm/path.h +++ b/src/include/gtm/path.h @@ -11,6 +11,11 @@ * *------------------------------------------------------------------------- */ +#ifndef _PATH_H +#define _PATH_H + #include "gtm/gtm_c.h" extern void canonicalize_path(char *path); +extern char *make_absolute_path(const char *path); +#endif -- cgit v1.2.3