From b06c90764526ccf291011ecbbcab49ae9729f65a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 9 Aug 2004 20:20:47 +0000 Subject: [PATCH] Path-mangling logic was failing to account for paths containing mentions of '.' or '..'. Extend canonicalize_path() to trim off trailing occurrences of these things, and use it to fix up paths where needed (which I think is only after places where we trim the last path component, but maybe some others will turn up). Fixes Josh's complaint that './initdb' does not work. --- src/bin/initdb/initdb.c | 3 ++- src/port/exec.c | 5 ++++- src/port/path.c | 32 +++++++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 55b782004c..de059e65bc 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -39,7 +39,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions taken from FreeBSD. * - * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.46 2004/08/01 06:19:23 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.47 2004/08/09 20:20:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2227,6 +2227,7 @@ main(int argc, char *argv[]) /* store binary directory */ strcpy(bin_path, backend_exec); *last_dir_separator(bin_path) = '\0'; + canonicalize_path(bin_path); if (!share_path) { diff --git a/src/port/exec.c b/src/port/exec.c index 440c63f0c5..85fec3ac47 100644 --- a/src/port/exec.c +++ b/src/port/exec.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/exec.c,v 1.20 2004/08/09 03:12:38 momjian Exp $ + * $PostgreSQL: pgsql/src/port/exec.c,v 1.21 2004/08/09 20:20:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -433,6 +433,9 @@ find_other_exec(const char *argv0, const char *target, /* Trim off program name and keep just directory */ *last_dir_separator(retpath) = '\0'; + canonicalize_path(retpath); + + /* Now append the other program's name */ snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath), "/%s%s", target, EXE); diff --git a/src/port/path.c b/src/port/path.c index 1e45a8f3e2..040c8a6eb7 100644 --- a/src/port/path.c +++ b/src/port/path.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/path.c,v 1.26 2004/08/01 06:56:39 momjian Exp $ + * $PostgreSQL: pgsql/src/port/path.c,v 1.27 2004/08/09 20:20:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -116,11 +116,33 @@ canonicalize_path(char *path) #endif /* - * Removing the trailing slash on a path means we never get - * ugly double slashes. Don't remove a leading slash, though. - * Also, Win32 can't stat() a directory with a trailing slash. + * Removing the trailing slash on a path means we never get ugly double + * slashes. Also, Win32 can't stat() a directory with a trailing slash. + * Don't remove a leading slash, though. */ trim_trailing_separator(path); + + /* + * Remove any trailing uses of "." or "..", too. + */ + for (;;) + { + int len = strlen(path); + + if (len >= 2 && strcmp(path + len - 2, "/.") == 0) + { + trim_directory(path); + trim_trailing_separator(path); + } + else if (len >= 3 && strcmp(path + len - 3, "/..") == 0) + { + trim_directory(path); + trim_directory(path); + trim_trailing_separator(path); + } + else + break; + } } @@ -444,7 +466,7 @@ trim_trailing_separator(char *path) #ifdef WIN32 /* * Skip over network and drive specifiers for win32. - * Set 'path' to point to the last character to keep. + * Set 'path' to point to the last character we must keep. */ if (strlen(path) >= 2) {