diff options
author | Bruce Momjian <bruce@momjian.us> | 2004-05-17 14:35:34 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2004-05-17 14:35:34 +0000 |
commit | 3febb477e643c1cd37fc8d2d3e02685dce6d1196 (patch) | |
tree | adc5f3696ec9001b0bda4d9c0336c50c251c2f62 /src/port/path.c | |
parent | 85383214ea2b0085658a650b4e6b293464dcf045 (diff) |
Reorganize code to allow path-relative installs.
Create new get_* functions to access compiled-in paths and adjust if
relative installs are to be used.
Clean up substitute_libpath_macro() code.
Diffstat (limited to 'src/port/path.c')
-rw-r--r-- | src/port/path.c | 278 |
1 files changed, 241 insertions, 37 deletions
diff --git a/src/port/path.c b/src/port/path.c index 5d102a90c24..f5fccca2787 100644 --- a/src/port/path.c +++ b/src/port/path.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/path.c,v 1.7 2004/05/12 13:38:49 momjian Exp $ + * $PostgreSQL: pgsql/src/port/path.c,v 1.8 2004/05/17 14:35:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,24 @@ #include "c.h" #include <ctype.h> +#ifndef WIN32 +#define ISSEP(ch) ((ch) == '/') +#else +#define ISSEP(ch) ((ch) == '/' || (ch) == '\\') +#endif + +static bool relative_path(const char *path1, const char *path2); +static void trim_directory(char *path); +static void trim_trailing_separator(char *path); + +/* Move to last of consecutive separators or to null byte */ +#define MOVE_TO_SEP_END(p) \ +{ \ + while (ISSEP((p)[0]) && (ISSEP((p)[1]) || !(p)[1])) \ + (p)++; \ +} + + /* * is_absolute_path */ @@ -40,22 +58,12 @@ is_absolute_path(const char *filename) char * first_path_separator(const char *filename) { -#ifndef WIN32 - return strchr(filename, '/'); -#else - char *slash, - *bslash; - - /* How should we handle "C:file.c"? */ - slash = strchr(filename, '/'); - bslash = strchr(filename, '\\'); - if (slash == NULL) - return bslash; - else if (bslash == NULL) - return slash; - else - return (slash < bslash) ? slash : bslash; -#endif + char *p; + + for (p = (char *)filename; *p; p++) + if (ISSEP(*p)) + return p; + return NULL; } @@ -65,22 +73,12 @@ first_path_separator(const char *filename) char * last_path_separator(const char *filename) { -#ifndef WIN32 - return strrchr(filename, '/'); -#else - char *slash, - *bslash; - - /* How should we handle "C:file.c"? */ - slash = strrchr(filename, '/'); - bslash = strrchr(filename, '\\'); - if (slash == NULL) - return bslash; - else if (bslash == NULL) - return slash; - else - return (slash > bslash) ? slash : bslash; -#endif + char *p, *ret = NULL; + + for (p = (char *)filename; *p; p++) + if (ISSEP(*p)) + ret = p; + return ret; } @@ -96,17 +94,17 @@ last_path_separator(const char *filename) void canonicalize_path(char *path) { +#ifdef WIN32 char *p; for (p = path; *p; p++) { -#ifdef WIN32 if (*p == '\\') *p = '/'; -#endif } - if (p > path+1 && *--p == '/') - *p = '\0'; +#endif + + trim_trailing_separator(path); } @@ -122,3 +120,209 @@ get_progname(const char *argv0) return last_path_separator(argv0) + 1; } + +/* + * get_share_path + */ +void +get_share_path(const char *my_exec_path, char *ret_path) +{ + if (relative_path(PGBINDIR, PGDATADIR)) + { + /* Autoconf calls our /share 'datadir' */ + StrNCpy(ret_path, my_exec_path, MAXPGPATH); + trim_directory(ret_path); /* trim off binary */ + trim_directory(ret_path); /* trim off /bin */ + strcat(ret_path, "/share"); /* add /share */ + } + else + StrNCpy(ret_path, PGDATADIR, MAXPGPATH); +} + + + +/* + * get_etc_path + */ +void +get_etc_path(const char *my_exec_path, char *ret_path) +{ + if (relative_path(PGBINDIR, SYSCONFDIR)) + { + StrNCpy(ret_path, my_exec_path, MAXPGPATH); + trim_directory(ret_path); + trim_directory(ret_path); + strcat(ret_path, "/etc"); + } + else + StrNCpy(ret_path, SYSCONFDIR, MAXPGPATH); +} + + + +/* + * get_include_path + */ +void +get_include_path(const char *my_exec_path, char *ret_path) +{ + if (relative_path(PGBINDIR, INCLUDEDIR)) + { + StrNCpy(ret_path, my_exec_path, MAXPGPATH); + trim_directory(ret_path); + trim_directory(ret_path); + strcat(ret_path, "/include"); + } + else + StrNCpy(ret_path, INCLUDEDIR, MAXPGPATH); +} + + + +/* + * get_pkginclude_path + */ +void +get_pkginclude_path(const char *my_exec_path, char *ret_path) +{ + if (relative_path(PGBINDIR, PKGINCLUDEDIR)) + { + StrNCpy(ret_path, my_exec_path, MAXPGPATH); + trim_directory(ret_path); + trim_directory(ret_path); + strcat(ret_path, "/include"); + } + else + StrNCpy(ret_path, PKGINCLUDEDIR, MAXPGPATH); +} + + + +/* + * get_pkglib_path + * + * Return library path, either relative to /bin or hardcoded + */ +void +get_pkglib_path(const char *my_exec_path, char *ret_path) +{ + if (relative_path(PGBINDIR, PKGLIBDIR)) + { + StrNCpy(ret_path, my_exec_path, MAXPGPATH); + trim_directory(ret_path); + trim_directory(ret_path); + strcat(ret_path, "/lib"); + } + else + StrNCpy(ret_path, PKGLIBDIR, MAXPGPATH); +} + + + +/* + * relative_path + * + * Do the supplied paths differ only in their last component? + */ +static bool +relative_path(const char *path1, const char *path2) +{ + +#ifdef WIN32 + /* Driver letters match? */ + if (isalpha(*path1) && path1[1] == ':' && + (!isalpha(*path2) || !path2[1] == ':')) + return false; + if ((!isalpha(*path1) || !path1[1] == ':') && + (isalpha(*path2) && path2[1] == ':') + return false; + if (isalpha(*path1) && path1[1] == ':' && + isalpha(*path2) && path2[1] == ':') + { + if (toupper(*path1) != toupper(*path2)) + return false; + path1 += 2; + path2 += 2; + } +#endif + + while (1) + { + /* Move past adjacent slashes like //, and trailing ones */ + MOVE_TO_SEP_END(path1); + MOVE_TO_SEP_END(path2); + + /* One of the paths is done? */ + if (!*path1 || !*path2) + break; + + /* Win32 filesystem is case insensitive */ +#ifndef WIN32 + if (*path1 != *path2) +#else + if (toupper((unsigned char) *path1) != toupper((unsigned char)*path2)) +#endif + break; + + path1++; + path2++; + } + + /* both done, identical? */ + if (!*path1 && !*path2) + return false; + + /* advance past directory name */ + while (!ISSEP(*path1) && *path1) + path1++; + while (!ISSEP(*path2) && *path2) + path2++; + + MOVE_TO_SEP_END(path1); + MOVE_TO_SEP_END(path2); + + /* Are both strings done? */ + if (!*path1 && !*path2) + return true; + else + return false; +} + + +/* + * trim_directory + * + * Trim trailing directory from path + */ +static void +trim_directory(char *path) +{ + char *p; + + if (path[0] == '\0') + return; + + for (p = path + strlen(path) - 1; ISSEP(*p) && p > path; p--) + ; + for (; !ISSEP(*p) && p > path; p--) + ; + *p = '\0'; + return; +} + + + +/* + * trim_trailing_separator + */ +static void +trim_trailing_separator(char *path) +{ + char *p = path + strlen(path); + + /* trim off trailing slashes */ + if (p > path) + for (p--; p >= path && ISSEP(*p); p--) + *p = '\0'; +} + |