summaryrefslogtreecommitdiffstats
path: root/winsup/utils/path.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/utils/path.cc')
-rw-r--r--winsup/utils/path.cc73
1 files changed, 52 insertions, 21 deletions
diff --git a/winsup/utils/path.cc b/winsup/utils/path.cc
index 569196344..4a29d14e9 100644
--- a/winsup/utils/path.cc
+++ b/winsup/utils/path.cc
@@ -486,26 +486,35 @@ unconvert_slashes (char* name)
*name++ = '\\';
}
+/* This is a helper function for when vcygpath is passed what appears
+ to be a relative POSIX path. We take a Win32 CWD (either as specified
+ in 'cwd' or as retrieved with GetCurrentDirectory() if 'cwd' is NULL)
+ and find the mount table entry with the longest match. We replace the
+ matching portion with the corresponding POSIX prefix, and to that append
+ 's' and anything in 'v'. The returned result is a mostly-POSIX
+ absolute path -- 'mostly' because the portions of CWD that didn't
+ match the mount prefix will still have '\\' separators. */
static char *
-rel_vconcat (const char *s, va_list v)
+rel_vconcat (const char *cwd, const char *s, va_list v)
{
- char path[MAX_PATH + 1];
- if (!GetCurrentDirectory (MAX_PATH, path))
- return NULL;
+ char pathbuf[MAX_PATH];
+ if (!cwd || *cwd == '\0')
+ {
+ if (!GetCurrentDirectory (MAX_PATH, pathbuf))
+ return NULL;
+ cwd = pathbuf;
+ }
int max_len = -1;
struct mnt *m, *match = NULL;
- if (s[0] == '.' && isslash (s[1]))
- s += 2;
-
- for (m = mount_table; m->posix ; m++)
+ for (m = mount_table; m->posix; m++)
{
if (m->flags & MOUNT_CYGDRIVE)
continue;
int n = strlen (m->native);
- if (n < max_len || !path_prefix_p (m->native, path, n))
+ if (n < max_len || !path_prefix_p (m->native, cwd, n))
continue;
max_len = n;
match = m;
@@ -514,34 +523,36 @@ rel_vconcat (const char *s, va_list v)
char *temppath;
if (!match)
// No prefix matched - best effort to return meaningful value.
- temppath = concat (path, "/", s, NULL);
+ temppath = concat (cwd, "/", s, NULL);
else if (strcmp (match->posix, "/") != 0)
// Matched on non-root. Copy matching prefix + remaining 'path'.
- temppath = concat (match->posix, path + max_len, "/", s, NULL);
- else if (path[max_len] == '\0')
+ temppath = concat (match->posix, cwd + max_len, "/", s, NULL);
+ else if (cwd[max_len] == '\0')
// Matched on root and there's no remaining 'path'.
temppath = concat ("/", s, NULL);
- else if (isslash (path[max_len]))
+ else if (isslash (cwd[max_len]))
// Matched on root but remaining 'path' starts with a slash anyway.
- temppath = concat (path + max_len, "/", s, NULL);
+ temppath = concat (cwd + max_len, "/", s, NULL);
else
- temppath = concat ("/", path + max_len, "/", s, NULL);
+ temppath = concat ("/", cwd + max_len, "/", s, NULL);
char *res = vconcat (temppath, v);
free (temppath);
return res;
}
-char *
-cygpath (const char *s, ...)
+/* Convert a POSIX path in 's' to an absolute Win32 path, and append
+ anything in 'v' to the end, returning the result. If 's' is a
+ relative path then 'cwd' is used as the working directory to make
+ it absolute. Pass NULL in 'cwd' to use GetCurrentDirectory. */
+static char *
+vcygpath (const char *cwd, const char *s, va_list v)
{
- va_list v;
int max_len = -1;
struct mnt *m, *match = NULL;
if (!mount_table[0].posix)
read_mounts ();
- va_start (v, s);
char *path;
if (s[0] == '.' && isslash (s[1]))
s += 2;
@@ -549,7 +560,7 @@ cygpath (const char *s, ...)
if (s[0] == '/' || s[1] == ':') /* FIXME: too crude? */
path = vconcat (s, v);
else
- path = rel_vconcat (s, v);
+ path = rel_vconcat (cwd, s, v);
if (!path)
return NULL;
@@ -557,7 +568,7 @@ cygpath (const char *s, ...)
if (strncmp (path, "/./", 3) == 0)
memmove (path + 1, path + 3, strlen (path + 3) + 1);
- for (m = mount_table; m->posix ; m++)
+ for (m = mount_table; m->posix; m++)
{
if (m->flags & MOUNT_CYGDRIVE)
continue;
@@ -586,6 +597,26 @@ cygpath (const char *s, ...)
return native;
}
+char *
+cygpath_rel (const char *cwd, const char *s, ...)
+{
+ va_list v;
+
+ va_start (v, s);
+
+ return vcygpath (cwd, s, v);
+}
+
+char *
+cygpath (const char *s, ...)
+{
+ va_list v;
+
+ va_start (v, s);
+
+ return vcygpath (NULL, s, v);
+}
+
static mnt *m = NULL;
extern "C" FILE *