*** a/src/backend/utils/init/miscinit.c --- b/src/backend/utils/init/miscinit.c *************** *** 88,98 **** void SetDataDir(const char *dir) { char *new; AssertArg(dir); /* If presented path is relative, convert to absolute */ ! new = make_absolute_path(dir); if (DataDir) free(DataDir); --- 88,101 ---- SetDataDir(const char *dir) { char *new; + char *errstr; AssertArg(dir); /* If presented path is relative, convert to absolute */ ! new = make_absolute_path(dir, &errstr); ! if (new == NULL) ! ereport(FATAL, (errmsg_internal("%s", errstr))); if (DataDir) free(DataDir); *************** *** 117,194 **** 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 * --- 120,125 ---- *** a/src/backend/utils/misc/guc.c --- b/src/backend/utils/misc/guc.c *************** *** 4214,4226 **** SelectConfigFiles(const char *userDoption, const char *progname) { char *configdir; char *fname; struct stat stat_buf; /* configdir is -D option, or $PGDATA if no -D */ if (userDoption) ! configdir = make_absolute_path(userDoption); else ! configdir = make_absolute_path(getenv("PGDATA")); /* * Find the configuration file: if config_file was specified on the --- 4214,4230 ---- { char *configdir; char *fname; + char *errstr; struct stat stat_buf; /* configdir is -D option, or $PGDATA if no -D */ if (userDoption) ! configdir = make_absolute_path(userDoption, &errstr); else ! configdir = make_absolute_path(getenv("PGDATA"), &errstr); ! ! if (configdir == NULL) ! ereport(FATAL, (errmsg_internal("%s", errstr))); /* * Find the configuration file: if config_file was specified on the *************** *** 4229,4235 **** SelectConfigFiles(const char *userDoption, const char *progname) * the same way by future backends. */ if (ConfigFileName) ! fname = make_absolute_path(ConfigFileName); else if (configdir) { fname = guc_malloc(FATAL, --- 4233,4243 ---- * the same way by future backends. */ if (ConfigFileName) ! { ! fname = make_absolute_path(ConfigFileName, &errstr); ! if (fname == NULL) ! ereport(FATAL, (errmsg_internal("%s", errstr))); ! } else if (configdir) { fname = guc_malloc(FATAL, *************** *** 4311,4317 **** SelectConfigFiles(const char *userDoption, const char *progname) * Figure out where pg_hba.conf is, and make sure the path is absolute. */ if (HbaFileName) ! fname = make_absolute_path(HbaFileName); else if (configdir) { fname = guc_malloc(FATAL, --- 4319,4329 ---- * Figure out where pg_hba.conf is, and make sure the path is absolute. */ if (HbaFileName) ! { ! fname = make_absolute_path(HbaFileName, &errstr); ! if (fname == NULL) ! ereport(FATAL, (errmsg_internal("%s", errstr))); ! } else if (configdir) { fname = guc_malloc(FATAL, *************** *** 4334,4340 **** SelectConfigFiles(const char *userDoption, const char *progname) * Likewise for pg_ident.conf. */ if (IdentFileName) ! fname = make_absolute_path(IdentFileName); else if (configdir) { fname = guc_malloc(FATAL, --- 4346,4356 ---- * Likewise for pg_ident.conf. */ if (IdentFileName) ! { ! fname = make_absolute_path(IdentFileName, &errstr); ! if (fname == NULL) ! ereport(FATAL, (errmsg_internal("%s", errstr))); ! } else if (configdir) { fname = guc_malloc(FATAL, *** a/src/include/miscadmin.h --- b/src/include/miscadmin.h *************** *** 296,302 **** 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 */ --- 296,301 ---- *** a/src/include/port.h --- b/src/include/port.h *************** *** 60,65 **** extern void get_man_path(const char *my_exec_path, char *ret_path); --- 60,69 ---- extern bool get_home_path(char *ret_path); extern void get_parent_directory(char *path); + /* port/abspath.c */ + extern char *make_absolute_path(const char *path, char **errstr); + extern char *make_absolute_path_or_exit(const char *progname, const char *path); + /* port/dirmod.c */ extern char **pgfnames(const char *path); extern void pgfnames_cleanup(char **filenames); *** a/src/interfaces/ecpg/ecpglib/Makefile --- b/src/interfaces/ecpg/ecpglib/Makefile *************** *** 25,31 **** override CFLAGS += $(PTHREAD_CFLAGS) LIBS := $(filter-out -lpgport, $(LIBS)) OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \ ! connect.o misc.o path.o pgstrcasecmp.o \ $(filter snprintf.o strlcpy.o win32setlocale.o isinf.o, $(LIBOBJS)) # thread.c is needed only for non-WIN32 implementation of path.c --- 25,31 ---- LIBS := $(filter-out -lpgport, $(LIBS)) OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \ ! connect.o misc.o path.o pgstrcasecmp.o psprintf.o \ $(filter snprintf.o strlcpy.o win32setlocale.o isinf.o, $(LIBOBJS)) # thread.c is needed only for non-WIN32 implementation of path.c *************** *** 62,67 **** include $(top_srcdir)/src/Makefile.shlib --- 62,70 ---- path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . + psprintf.c : % : $(top_srcdir)/src/common/% + rm -f $@ && $(LN_S) $< . + misc.o: misc.c $(top_builddir)/src/port/pg_config_paths.h path.o: path.c $(top_builddir)/src/port/pg_config_paths.h *************** *** 76,81 **** uninstall: uninstall-lib clean distclean: clean-lib rm -f $(OBJS) ! rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c maintainer-clean: distclean maintainer-clean-lib --- 79,84 ---- clean distclean: clean-lib rm -f $(OBJS) ! rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c psprintf.c maintainer-clean: distclean maintainer-clean-lib *** a/src/port/path.c --- b/src/port/path.c *************** *** 13,18 **** --- 13,24 ---- *------------------------------------------------------------------------- */ + #ifndef FRONTEND + #include "postgres.h" + #else + #include "postgres_fe.h" + #endif + #include "c.h" #include *************** *** 757,759 **** trim_trailing_separator(char *path) --- 763,861 ---- 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 canonicalizes the path. The result is always a malloc'd copy. + * incase of error, the errstr is filled with palloced copy of error and + * returns NULL. Caller needs to take care of freeing the errstr memory. + */ + char * + make_absolute_path(const char *path, char **errstr) + { + char *result; + + /* 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 == NULL) + { + *errstr = psprintf("out of memory"); + return NULL; + } + if (getcwd(buf, buflen)) + break; + else if (errno == ERANGE) + { + free(buf); + buflen *= 2; + continue; + } + else + { + free(buf); + *errstr = psprintf("could not get current working directory :%s", strerror(errno)); + return NULL; + } + } + + result = malloc(strlen(buf) + strlen(path) + 2); + if (result == NULL) + { + free(buf); + *errstr = psprintf("out of memory"); + return NULL; + } + + sprintf(result, "%s/%s", buf, path); + free(buf); + } + else + { + result = strdup(path); + if (result == NULL) + { + *errstr = psprintf("out of memory"); + return NULL; + } + } + + /* Make sure punctuation is canonical, too */ + canonicalize_path(result); + return result; + } + + /* + * 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. + * incase of error it exits. + */ + char * + make_absolute_path_or_exit(const char *progname, const char *path) + { + char *errstr; + char *result; + + result = make_absolute_path(path, &errstr); + if (result == NULL) + { + fprintf(stderr, "%s: %s\n", progname, errstr); + exit(1); + } + + return result; + } *** a/src/test/regress/pg_regress.c --- b/src/test/regress/pg_regress.c *************** *** 1832,1864 **** 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) { --- 1832,1837 ---- *************** *** 2003,2009 **** regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc add_stringlist_item(&schedulelist, optarg); break; case 9: ! temp_install = make_absolute_path(optarg); break; case 10: nolocale = true; --- 1976,1982 ---- add_stringlist_item(&schedulelist, optarg); break; case 9: ! temp_install = make_absolute_path_or_exit(progname, optarg); break; case 10: nolocale = true; *************** *** 2073,2081 **** regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc */ port = 0xC000 | (PG_VERSION_NUM & 0x3FFF); ! inputdir = make_absolute_path(inputdir); ! outputdir = make_absolute_path(outputdir); ! dlpath = make_absolute_path(dlpath); /* * Initialization --- 2046,2054 ---- */ port = 0xC000 | (PG_VERSION_NUM & 0x3FFF); ! inputdir = make_absolute_path_or_exit(progname, inputdir); ! outputdir = make_absolute_path_or_exit(progname, outputdir); ! dlpath = make_absolute_path_or_exit(progname, dlpath); /* * Initialization