Code cleanup in path.c and exec.c. Handle Windows drive and network specs
everywhere not just some places, get rid of . and .. when joining path sections together. This should eliminate most of the ugly paths like /foo/bar/./baz that we've been generating.
This commit is contained in:
parent
3d6e538edf
commit
4867afef7a
@ -1,12 +1,12 @@
|
|||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* port.h
|
* port.h
|
||||||
* Header for /port compatibility functions.
|
* Header for src/port/ compatibility functions.
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/port.h,v 1.64 2004/10/11 22:50:33 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/port.h,v 1.65 2004/11/06 01:16:14 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,25 +20,15 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
/* non-blocking */
|
/* non-blocking */
|
||||||
bool set_noblock(int sock);
|
extern bool set_noblock(int sock);
|
||||||
|
|
||||||
/* Portable path handling for Unix/Win32 */
|
/* Portable path handling for Unix/Win32 */
|
||||||
|
|
||||||
/* Find the location of the first directory separator, return
|
|
||||||
* NULL if not found.
|
|
||||||
*/
|
|
||||||
extern char *first_dir_separator(const char *filename);
|
extern char *first_dir_separator(const char *filename);
|
||||||
|
|
||||||
/* Find the location of the last directory separator, return
|
|
||||||
* NULL if not found.
|
|
||||||
*/
|
|
||||||
extern char *last_dir_separator(const char *filename);
|
extern char *last_dir_separator(const char *filename);
|
||||||
|
extern char *first_path_separator(const char *pathlist);
|
||||||
/* Find the location of the first path separator (i.e. ':' on
|
extern void join_path_components(char *ret_path,
|
||||||
* Unix, ';' on Windows), return NULL if not found.
|
const char *head, const char *tail);
|
||||||
*/
|
|
||||||
extern char *first_path_separator(const char *filename);
|
|
||||||
|
|
||||||
extern void canonicalize_path(char *path);
|
extern void canonicalize_path(char *path);
|
||||||
extern void make_native_path(char *path);
|
extern void make_native_path(char *path);
|
||||||
extern const char *get_progname(const char *argv0);
|
extern const char *get_progname(const char *argv0);
|
||||||
@ -123,11 +113,6 @@ extern unsigned char pg_tolower(unsigned char ch);
|
|||||||
/* Portable prompt handling */
|
/* Portable prompt handling */
|
||||||
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
|
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
|
||||||
|
|
||||||
#if defined(bsdi) || defined(netbsd)
|
|
||||||
extern int fseeko(FILE *stream, off_t offset, int whence);
|
|
||||||
extern off_t ftello(FILE *stream);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WIN32 doesn't allow descriptors returned by pipe() to be used in select(),
|
* WIN32 doesn't allow descriptors returned by pipe() to be used in select(),
|
||||||
* so for that platform we use socket() instead of pipe().
|
* so for that platform we use socket() instead of pipe().
|
||||||
@ -185,7 +170,7 @@ extern int pgsymlink(const char *oldpath, const char *newpath);
|
|||||||
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
|
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif /* defined(WIN32) || defined(__CYGWIN__) */
|
||||||
|
|
||||||
extern bool rmtree(char *path, bool rmtopdir);
|
extern bool rmtree(char *path, bool rmtopdir);
|
||||||
|
|
||||||
@ -212,14 +197,14 @@ extern void srand48(long seed);
|
|||||||
/* Last parameter not used */
|
/* Last parameter not used */
|
||||||
extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
|
extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
|
||||||
|
|
||||||
#else
|
#else /* !WIN32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Win32 requires a special close for sockets and pipes, while on Unix
|
* Win32 requires a special close for sockets and pipes, while on Unix
|
||||||
* close() does them all.
|
* close() does them all.
|
||||||
*/
|
*/
|
||||||
#define closesocket close
|
#define closesocket close
|
||||||
#endif
|
#endif /* WIN32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default "extern" declarations or macro substitutes for library routines.
|
* Default "extern" declarations or macro substitutes for library routines.
|
||||||
@ -229,6 +214,11 @@ extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
|
|||||||
extern char *crypt(const char *key, const char *setting);
|
extern char *crypt(const char *key, const char *setting);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(bsdi) || defined(netbsd)
|
||||||
|
extern int fseeko(FILE *stream, off_t offset, int whence);
|
||||||
|
extern off_t ftello(FILE *stream);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_FSEEKO
|
#ifndef HAVE_FSEEKO
|
||||||
#define fseeko(a, b, c) fseek((a), (b), (c))
|
#define fseeko(a, b, c) fseek((a), (b), (c))
|
||||||
#define ftello(a) ftell((a))
|
#define ftello(a) ftell((a))
|
||||||
|
118
src/port/exec.c
118
src/port/exec.c
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/port/exec.c,v 1.30 2004/10/18 19:08:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/port/exec.c,v 1.31 2004/11/06 01:16:22 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -42,15 +42,12 @@
|
|||||||
|
|
||||||
#ifndef FRONTEND
|
#ifndef FRONTEND
|
||||||
/* We use only 3-parameter elog calls in this file, for simplicity */
|
/* We use only 3-parameter elog calls in this file, for simplicity */
|
||||||
#define log_error(str, param) elog(LOG, (str), (param))
|
#define log_error(str, param) elog(LOG, str, param)
|
||||||
#else
|
#else
|
||||||
#define log_error(str, param) fprintf(stderr, (str), (param))
|
#define log_error(str, param) (fprintf(stderr, str, param), fputc('\n', stderr))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void win32_make_absolute(char *path);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* validate_exec -- validate "path" as an executable file
|
* validate_exec -- validate "path" as an executable file
|
||||||
*
|
*
|
||||||
@ -165,7 +162,7 @@ validate_exec(const char *path)
|
|||||||
* executable's location. Also, we need a full path not a relative
|
* executable's location. Also, we need a full path not a relative
|
||||||
* path because we will later change working directory.
|
* path because we will later change working directory.
|
||||||
*
|
*
|
||||||
* This function is not thread-safe because of it calls validate_exec(),
|
* This function is not thread-safe because it calls validate_exec(),
|
||||||
* which calls getgrgid(). This function should be used only in
|
* which calls getgrgid(). This function should be used only in
|
||||||
* non-threaded binaries, not in library routines.
|
* non-threaded binaries, not in library routines.
|
||||||
*/
|
*/
|
||||||
@ -178,61 +175,40 @@ find_my_exec(const char *argv0, char *retpath)
|
|||||||
|
|
||||||
#ifndef WIN32_CLIENT_ONLY
|
#ifndef WIN32_CLIENT_ONLY
|
||||||
if (!getcwd(cwd, MAXPGPATH))
|
if (!getcwd(cwd, MAXPGPATH))
|
||||||
|
strcpy(cwd, "."); /* cheesy, but better than nothing */
|
||||||
#else
|
#else
|
||||||
if (!GetCurrentDirectory(MAXPGPATH, cwd))
|
if (!GetCurrentDirectory(MAXPGPATH, cwd))
|
||||||
|
strcpy(cwd, "."); /* cheesy, but better than nothing */
|
||||||
#endif
|
#endif
|
||||||
cwd[0] = '\0';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First try: use the binary that's located in the same directory if
|
* If argv0 contains a separator, then PATH wasn't used.
|
||||||
* it was invoked with an explicit path. Presumably the user used an
|
|
||||||
* explicit path because it wasn't in PATH, and we don't want to use
|
|
||||||
* incompatible executables.
|
|
||||||
*
|
|
||||||
* For the binary: First try: if we're given some kind of path, use it
|
|
||||||
* (making sure that a relative path is made absolute before returning
|
|
||||||
* it).
|
|
||||||
*/
|
*/
|
||||||
/* Does argv0 have a separator? */
|
if (first_dir_separator(argv0) != NULL)
|
||||||
if ((path = last_dir_separator(argv0)))
|
|
||||||
{
|
{
|
||||||
if (*++path == '\0')
|
|
||||||
{
|
|
||||||
log_error("argv[0] ends with a path separator \"%s\"", argv0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_absolute_path(argv0))
|
if (is_absolute_path(argv0))
|
||||||
StrNCpy(retpath, argv0, MAXPGPATH);
|
StrNCpy(retpath, argv0, MAXPGPATH);
|
||||||
else
|
else
|
||||||
snprintf(retpath, MAXPGPATH, "%s/%s", cwd, argv0);
|
join_path_components(retpath, cwd, argv0);
|
||||||
|
|
||||||
canonicalize_path(retpath);
|
canonicalize_path(retpath);
|
||||||
|
|
||||||
if (validate_exec(retpath) == 0)
|
if (validate_exec(retpath) == 0)
|
||||||
{
|
|
||||||
win32_make_absolute(retpath);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
else
|
log_error("invalid binary \"%s\"", retpath);
|
||||||
{
|
return -1;
|
||||||
log_error("invalid binary \"%s\"", retpath);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
/* Win32 checks the current directory first for names without slashes */
|
/* Win32 checks the current directory first for names without slashes */
|
||||||
if (validate_exec(argv0) == 0)
|
join_path_components(retpath, cwd, argv0);
|
||||||
{
|
if (validate_exec(retpath) == 0)
|
||||||
snprintf(retpath, MAXPGPATH, "%s/%s", cwd, argv0);
|
|
||||||
win32_make_absolute(retpath);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Second try: since no explicit path was supplied, the user must have
|
* Since no explicit path was supplied, the user must have
|
||||||
* been relying on PATH. We'll use the same PATH.
|
* been relying on PATH. We'll search the same PATH.
|
||||||
*/
|
*/
|
||||||
if ((path = getenv("PATH")) && *path)
|
if ((path = getenv("PATH")) && *path)
|
||||||
{
|
{
|
||||||
@ -253,40 +229,33 @@ find_my_exec(const char *argv0, char *retpath)
|
|||||||
StrNCpy(test_path, startp, Min(endp - startp + 1, MAXPGPATH));
|
StrNCpy(test_path, startp, Min(endp - startp + 1, MAXPGPATH));
|
||||||
|
|
||||||
if (is_absolute_path(test_path))
|
if (is_absolute_path(test_path))
|
||||||
snprintf(retpath, MAXPGPATH, "%s/%s", test_path, argv0);
|
join_path_components(retpath, test_path, argv0);
|
||||||
else
|
else
|
||||||
snprintf(retpath, MAXPGPATH, "%s/%s/%s", cwd, test_path, argv0);
|
{
|
||||||
|
join_path_components(retpath, cwd, test_path);
|
||||||
|
join_path_components(retpath, retpath, argv0);
|
||||||
|
}
|
||||||
canonicalize_path(retpath);
|
canonicalize_path(retpath);
|
||||||
|
|
||||||
switch (validate_exec(retpath))
|
switch (validate_exec(retpath))
|
||||||
{
|
{
|
||||||
case 0: /* found ok */
|
case 0: /* found ok */
|
||||||
win32_make_absolute(retpath);
|
|
||||||
return 0;
|
return 0;
|
||||||
case -1: /* wasn't even a candidate, keep looking */
|
case -1: /* wasn't even a candidate, keep looking */
|
||||||
continue;
|
break;
|
||||||
case -2: /* found but disqualified */
|
case -2: /* found but disqualified */
|
||||||
log_error("could not read binary \"%s\"", retpath);
|
log_error("could not read binary \"%s\"", retpath);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
} while (*endp);
|
} while (*endp);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_error("could not find a \"%s\" to execute", argv0);
|
log_error("could not find a \"%s\" to execute", argv0);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#if NOT_USED
|
|
||||||
/*
|
|
||||||
* Win32 has a native way to find the executable name, but the above
|
|
||||||
* method works too.
|
|
||||||
*/
|
|
||||||
if (GetModuleFileName(NULL, retpath, MAXPGPATH) == 0)
|
|
||||||
log_error("GetModuleFileName failed (%i)", (int) GetLastError());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The runtime librarys popen() on win32 does not work when being
|
* The runtime library's popen() on win32 does not work when being
|
||||||
* called from a service when running on windows <= 2000, because
|
* called from a service when running on windows <= 2000, because
|
||||||
* there is no stdin/stdout/stderr.
|
* there is no stdin/stdout/stderr.
|
||||||
*
|
*
|
||||||
@ -427,10 +396,9 @@ pipe_read_line(char *cmd, char *line, int maxsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find our binary directory, then make sure the "target" executable
|
* Find another program in our binary's directory,
|
||||||
* is the proper version.
|
* then make sure it is the proper version.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
find_other_exec(const char *argv0, const char *target,
|
find_other_exec(const char *argv0, const char *target,
|
||||||
@ -487,41 +455,19 @@ pclose_check(FILE *stream)
|
|||||||
}
|
}
|
||||||
else if (WIFEXITED(exitstatus))
|
else if (WIFEXITED(exitstatus))
|
||||||
{
|
{
|
||||||
log_error(_("child process exited with exit code %d\n"),
|
log_error(_("child process exited with exit code %d"),
|
||||||
WEXITSTATUS(exitstatus));
|
WEXITSTATUS(exitstatus));
|
||||||
}
|
}
|
||||||
else if (WIFSIGNALED(exitstatus))
|
else if (WIFSIGNALED(exitstatus))
|
||||||
{
|
{
|
||||||
log_error(_("child process was terminated by signal %d\n"),
|
log_error(_("child process was terminated by signal %d"),
|
||||||
WTERMSIG(exitstatus));
|
WTERMSIG(exitstatus));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error(_("child process exited with unrecognized status %d\n"),
|
log_error(_("child process exited with unrecognized status %d"),
|
||||||
exitstatus);
|
exitstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Windows doesn't like relative paths to executables (other things work fine)
|
|
||||||
* so we call its builtin function to expand them. Elsewhere this is a NOOP
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
win32_make_absolute(char *path)
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
char abspath[MAXPGPATH];
|
|
||||||
|
|
||||||
if (_fullpath(abspath, path, MAXPGPATH) == NULL)
|
|
||||||
{
|
|
||||||
log_error("Win32 path expansion failed: %s", strerror(errno));
|
|
||||||
StrNCpy(abspath, path, MAXPGPATH);
|
|
||||||
}
|
|
||||||
canonicalize_path(abspath);
|
|
||||||
|
|
||||||
StrNCpy(path, abspath, MAXPGPATH);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
186
src/port/path.c
186
src/port/path.c
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/port/path.c,v 1.41 2004/11/02 03:09:06 momjian Exp $
|
* $PostgreSQL: pgsql/src/port/path.c,v 1.42 2004/11/06 01:16:22 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -44,53 +44,95 @@ static void trim_trailing_separator(char *path);
|
|||||||
(p)++; \
|
(p)++; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* skip_drive
|
||||||
|
*
|
||||||
|
* On Windows, a path may begin with "C:" or "//network/". Advance over
|
||||||
|
* this and point to the effective start of the path.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
static char *
|
||||||
|
skip_drive(const char *path)
|
||||||
|
{
|
||||||
|
if (IS_DIR_SEP(path[0]) && IS_DIR_SEP(path[1]))
|
||||||
|
{
|
||||||
|
path += 2;
|
||||||
|
while (*path && !IS_DIR_SEP(*path))
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
else if (isalpha(path[0]) && path[1] == ':')
|
||||||
|
{
|
||||||
|
path += 2;
|
||||||
|
}
|
||||||
|
return (char *) path;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define skip_drive(path) (path)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* first_dir_separator
|
* first_dir_separator
|
||||||
|
*
|
||||||
|
* Find the location of the first directory separator, return
|
||||||
|
* NULL if not found.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
first_dir_separator(const char *filename)
|
first_dir_separator(const char *filename)
|
||||||
{
|
{
|
||||||
char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = (char *) filename; *p; p++)
|
for (p = skip_drive(filename); *p; p++)
|
||||||
if (IS_DIR_SEP(*p))
|
if (IS_DIR_SEP(*p))
|
||||||
return p;
|
return (char *) p;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* first_path_separator
|
* first_path_separator
|
||||||
|
*
|
||||||
|
* Find the location of the first path separator (i.e. ':' on
|
||||||
|
* Unix, ';' on Windows), return NULL if not found.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
first_path_separator(const char *filename)
|
first_path_separator(const char *pathlist)
|
||||||
{
|
{
|
||||||
char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = (char *) filename; *p; p++)
|
/* skip_drive is not needed */
|
||||||
|
for (p = pathlist; *p; p++)
|
||||||
if (IS_PATH_SEP(*p))
|
if (IS_PATH_SEP(*p))
|
||||||
return p;
|
return (char *) p;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* last_dir_separator
|
* last_dir_separator
|
||||||
|
*
|
||||||
|
* Find the location of the last directory separator, return
|
||||||
|
* NULL if not found.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
last_dir_separator(const char *filename)
|
last_dir_separator(const char *filename)
|
||||||
{
|
{
|
||||||
char *p,
|
const char *p,
|
||||||
*ret = NULL;
|
*ret = NULL;
|
||||||
|
|
||||||
for (p = (char *) filename; *p; p++)
|
for (p = skip_drive(filename); *p; p++)
|
||||||
if (IS_DIR_SEP(*p))
|
if (IS_DIR_SEP(*p))
|
||||||
ret = p;
|
ret = p;
|
||||||
return ret;
|
return (char *) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make_native_path - on WIN32, change / to \ in the path
|
* make_native_path - on WIN32, change / to \ in the path
|
||||||
*
|
*
|
||||||
|
* This effectively undoes canonicalize_path.
|
||||||
|
*
|
||||||
* This is required because WIN32 COPY is an internal CMD.EXE
|
* This is required because WIN32 COPY is an internal CMD.EXE
|
||||||
* command and doesn't process forward slashes in the same way
|
* command and doesn't process forward slashes in the same way
|
||||||
* as external commands. Quoting the first argument to COPY
|
* as external commands. Quoting the first argument to COPY
|
||||||
@ -114,11 +156,59 @@ make_native_path(char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* join_path_components - join two path components, inserting a slash
|
||||||
|
*
|
||||||
|
* ret_path is the output area (must be of size MAXPGPATH)
|
||||||
|
*
|
||||||
|
* ret_path can be the same as head, but not the same as tail.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
join_path_components(char *ret_path,
|
||||||
|
const char *head, const char *tail)
|
||||||
|
{
|
||||||
|
if (ret_path != head)
|
||||||
|
StrNCpy(ret_path, head, MAXPGPATH);
|
||||||
|
/*
|
||||||
|
* Remove any leading "." and ".." in the tail component,
|
||||||
|
* adjusting head as needed.
|
||||||
|
*/
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (tail[0] == '.' && IS_DIR_SEP(tail[1]))
|
||||||
|
{
|
||||||
|
tail += 2;
|
||||||
|
}
|
||||||
|
else if (tail[0] == '.' && tail[1] == '\0')
|
||||||
|
{
|
||||||
|
tail += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (tail[0] == '.' && tail[1] == '.' && IS_DIR_SEP(tail[2]))
|
||||||
|
{
|
||||||
|
trim_directory(ret_path);
|
||||||
|
tail += 3;
|
||||||
|
}
|
||||||
|
else if (tail[0] == '.' && tail[1] == '.' && tail[2] == '\0')
|
||||||
|
{
|
||||||
|
trim_directory(ret_path);
|
||||||
|
tail += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*tail)
|
||||||
|
snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path),
|
||||||
|
"/%s", tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up path by:
|
* Clean up path by:
|
||||||
* o make Win32 path use Unix slashes
|
* o make Win32 path use Unix slashes
|
||||||
* o remove trailling quote on Win32
|
* o remove trailing quote on Win32
|
||||||
* o remove trailling slash
|
* o remove trailing slash
|
||||||
* o remove trailing '.'
|
* o remove trailing '.'
|
||||||
* o process trailing '..' ourselves
|
* o process trailing '..' ourselves
|
||||||
*/
|
*/
|
||||||
@ -165,13 +255,11 @@ canonicalize_path(char *path)
|
|||||||
if (len >= 2 && strcmp(path + len - 2, "/.") == 0)
|
if (len >= 2 && strcmp(path + len - 2, "/.") == 0)
|
||||||
{
|
{
|
||||||
trim_directory(path);
|
trim_directory(path);
|
||||||
trim_trailing_separator(path);
|
|
||||||
}
|
}
|
||||||
else if (len >= 3 && strcmp(path + len - 3, "/..") == 0)
|
else if (len >= 3 && strcmp(path + len - 3, "/..") == 0)
|
||||||
{
|
{
|
||||||
trim_directory(path);
|
trim_directory(path);
|
||||||
trim_directory(path); /* remove directory above */
|
trim_directory(path); /* remove directory above */
|
||||||
trim_trailing_separator(path);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -188,10 +276,11 @@ get_progname(const char *argv0)
|
|||||||
{
|
{
|
||||||
const char *nodir_name;
|
const char *nodir_name;
|
||||||
|
|
||||||
if (!last_dir_separator(argv0))
|
nodir_name = last_dir_separator(argv0);
|
||||||
nodir_name = argv0;
|
if (nodir_name)
|
||||||
|
nodir_name++;
|
||||||
else
|
else
|
||||||
nodir_name = last_dir_separator(argv0) + 1;
|
nodir_name = skip_drive(argv0);
|
||||||
|
|
||||||
#if defined(__CYGWIN__) || defined(WIN32)
|
#if defined(__CYGWIN__) || defined(WIN32)
|
||||||
/* strip .exe suffix, regardless of case */
|
/* strip .exe suffix, regardless of case */
|
||||||
@ -231,7 +320,6 @@ get_share_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_etc_path
|
* get_etc_path
|
||||||
*/
|
*/
|
||||||
@ -248,7 +336,6 @@ get_etc_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_include_path
|
* get_include_path
|
||||||
*/
|
*/
|
||||||
@ -265,7 +352,6 @@ get_include_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_pkginclude_path
|
* get_pkginclude_path
|
||||||
*/
|
*/
|
||||||
@ -282,7 +368,6 @@ get_pkginclude_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_includeserver_path
|
* get_includeserver_path
|
||||||
*/
|
*/
|
||||||
@ -299,7 +384,6 @@ get_includeserver_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_lib_path
|
* get_lib_path
|
||||||
*/
|
*/
|
||||||
@ -316,7 +400,6 @@ get_lib_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_pkglib_path
|
* get_pkglib_path
|
||||||
*/
|
*/
|
||||||
@ -333,7 +416,6 @@ get_pkglib_path(const char *my_exec_path, char *ret_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_locale_path
|
* get_locale_path
|
||||||
*
|
*
|
||||||
@ -382,7 +464,6 @@ void
|
|||||||
get_parent_directory(char *path)
|
get_parent_directory(char *path)
|
||||||
{
|
{
|
||||||
trim_directory(path);
|
trim_directory(path);
|
||||||
trim_trailing_separator(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -436,6 +517,8 @@ set_pglocale_pgservice(const char *argv0, const char *app)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* make_relative - adjust path to be relative to bin/
|
* make_relative - adjust path to be relative to bin/
|
||||||
|
*
|
||||||
|
* ret_path is the output area (must be of size MAXPGPATH)
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
make_relative(const char *my_exec_path, const char *p, char *ret_path)
|
make_relative(const char *my_exec_path, const char *p, char *ret_path)
|
||||||
@ -443,9 +526,9 @@ make_relative(const char *my_exec_path, const char *p, char *ret_path)
|
|||||||
char path[MAXPGPATH];
|
char path[MAXPGPATH];
|
||||||
|
|
||||||
StrNCpy(path, my_exec_path, MAXPGPATH);
|
StrNCpy(path, my_exec_path, MAXPGPATH);
|
||||||
trim_directory(path);
|
trim_directory(path); /* remove my executable name */
|
||||||
trim_directory(path);
|
trim_directory(path); /* remove last directory component (/bin) */
|
||||||
snprintf(ret_path, MAXPGPATH, "%s/%s", path, p);
|
join_path_components(ret_path, path, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -520,57 +603,48 @@ relative_path(const char *bin_path, const char *other_path)
|
|||||||
/*
|
/*
|
||||||
* trim_directory
|
* trim_directory
|
||||||
*
|
*
|
||||||
* Trim trailing directory from path
|
* Trim trailing directory from path, that is, remove any trailing slashes,
|
||||||
|
* the last pathname component, and the slash just ahead of it --- but never
|
||||||
|
* remove a leading slash.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
trim_directory(char *path)
|
trim_directory(char *path)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
path = skip_drive(path);
|
||||||
|
|
||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* back up over trailing slash(es) */
|
||||||
for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
|
for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
|
||||||
;
|
;
|
||||||
|
/* back up over directory name */
|
||||||
for (; !IS_DIR_SEP(*p) && p > path; p--)
|
for (; !IS_DIR_SEP(*p) && p > path; p--)
|
||||||
;
|
;
|
||||||
|
/* if multiple slashes before directory name, remove 'em all */
|
||||||
|
for (; p > path && IS_DIR_SEP(*(p - 1)); p--)
|
||||||
|
;
|
||||||
|
/* don't erase a leading slash */
|
||||||
|
if (p == path && IS_DIR_SEP(*p))
|
||||||
|
p++;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* trim_trailing_separator
|
* trim_trailing_separator
|
||||||
|
*
|
||||||
|
* trim off trailing slashes, but not a leading slash
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
trim_trailing_separator(char *path)
|
trim_trailing_separator(char *path)
|
||||||
{
|
{
|
||||||
char *p = path + strlen(path);
|
char *p;
|
||||||
|
|
||||||
#ifdef WIN32
|
path = skip_drive(path);
|
||||||
|
p = path + strlen(path);
|
||||||
/*
|
|
||||||
* Skip over network and drive specifiers for win32. Set 'path' to
|
|
||||||
* point to the last character we must keep.
|
|
||||||
*/
|
|
||||||
if (strlen(path) >= 2)
|
|
||||||
{
|
|
||||||
if (IS_DIR_SEP(path[0]) && IS_DIR_SEP(path[1]))
|
|
||||||
{
|
|
||||||
path += 2;
|
|
||||||
while (*path && !IS_DIR_SEP(*path))
|
|
||||||
path++;
|
|
||||||
}
|
|
||||||
else if (isalpha(path[0]) && path[1] == ':')
|
|
||||||
{
|
|
||||||
path++;
|
|
||||||
if (IS_DIR_SEP(path[1]))
|
|
||||||
path++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* trim off trailing slashes */
|
|
||||||
if (p > path)
|
if (p > path)
|
||||||
for (p--; p > path && IS_DIR_SEP(*p); p--)
|
for (p--; p > path && IS_DIR_SEP(*p); p--)
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user