summaryrefslogtreecommitdiffstats
path: root/winsup/utils
diff options
context:
space:
mode:
authorBrian Dessent <brian@dessent.net>2008-03-11 17:20:02 +0000
committerBrian Dessent <brian@dessent.net>2008-03-11 17:20:02 +0000
commit60efa4e546a8f2e8e23f2de5ccd77c8c30240162 (patch)
treec6e1cc51637891191e4a42196a4f75d701206a83 /winsup/utils
parent0c4cb56009a42d4f0c3b837315ac8ed09d4a63b9 (diff)
downloadcygnal-60efa4e546a8f2e8e23f2de5ccd77c8c30240162.tar.gz
cygnal-60efa4e546a8f2e8e23f2de5ccd77c8c30240162.tar.bz2
cygnal-60efa4e546a8f2e8e23f2de5ccd77c8c30240162.zip
* cygcheck.cc (dirname): New static function.
(find_app_on_path): Use SYMLINK_MAX. Resolve symlink relative to link's location. Adjust to the fact that cygpath already normalizes its return value. * path.cc (rel_vconcat): Add cwd parameter, and use it instead of calling GetCurrentDirectory() if possible. Rename throughout. (vcygpath): Rename from cygpath and accept cwd and va_list. Pass cwd on to rel_vconcat(). (cygpath_rel): New front end for vcygpath. (cygpath): Ditto. * path.h (cygpath_rel): Declare. (SYMLINK_MAX): Define to 4095.
Diffstat (limited to 'winsup/utils')
-rw-r--r--winsup/utils/ChangeLog15
-rw-r--r--winsup/utils/cygcheck.cc41
-rw-r--r--winsup/utils/path.cc73
-rw-r--r--winsup/utils/path.h2
4 files changed, 100 insertions, 31 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
index 18f70518a..288beafd0 100644
--- a/winsup/utils/ChangeLog
+++ b/winsup/utils/ChangeLog
@@ -1,3 +1,18 @@
+2008-03-11 Brian Dessent <brian@dessent.net>
+
+ * cygcheck.cc (dirname): New static function.
+ (find_app_on_path): Use SYMLINK_MAX. Resolve symlink relative
+ to link's location. Adjust to the fact that cygpath already
+ normalizes its return value.
+ * path.cc (rel_vconcat): Add cwd parameter, and use it instead
+ of calling GetCurrentDirectory() if possible. Rename throughout.
+ (vcygpath): Rename from cygpath and accept cwd and va_list. Pass
+ cwd on to rel_vconcat().
+ (cygpath_rel): New front end for vcygpath.
+ (cygpath): Ditto.
+ * path.h (cygpath_rel): Declare.
+ (SYMLINK_MAX): Define to 4095.
+
2008-03-09 Brian Dessent <brian@dessent.net>
* Makefile.in (install): Don't install the testsuite.
diff --git a/winsup/utils/cygcheck.cc b/winsup/utils/cygcheck.cc
index 5e9713e03..e23a6858e 100644
--- a/winsup/utils/cygcheck.cc
+++ b/winsup/utils/cygcheck.cc
@@ -807,6 +807,28 @@ ls (char *f)
display_error ("ls: CloseHandle()");
}
+/* Remove filename from 's' and return directory name without trailing
+ backslash, or NULL if 's' doesn't seem to have a dirname. */
+static char *
+dirname (const char *s)
+{
+ static char buf[MAX_PATH];
+
+ if (!s)
+ return NULL;
+
+ strncpy (buf, s, MAX_PATH);
+ buf[MAX_PATH - 1] = '\0'; // in case strlen(s) > MAX_PATH
+ char *lastsep = strrchr (buf, '\\');
+ if (!lastsep)
+ return NULL; // no backslash -> no dirname
+ else if (lastsep - buf <= 2 && buf[1] == ':')
+ lastsep[1] = '\0'; // can't remove backslash of "x:\"
+ else
+ *lastsep = '\0';
+ return buf;
+}
+
// Find a real application on the path (possibly following symlinks)
static const char *
find_app_on_path (const char *app, bool showall = false)
@@ -821,26 +843,25 @@ find_app_on_path (const char *app, bool showall = false)
if (is_symlink (fh))
{
- static char tmp[4000] = "";
- char *ptr;
- if (!readlink (fh, tmp, 3999))
+ static char tmp[SYMLINK_MAX];
+ if (!readlink (fh, tmp, SYMLINK_MAX))
display_error("readlink failed");
- ptr = cygpath (tmp, NULL);
- for (char *p = ptr; (p = strchr (p, '/')); p++)
- *p = '\\';
+
+ /* Resolve the linkname relative to the directory of the link. */
+ char *ptr = cygpath_rel (dirname (papp), tmp, NULL);
printf (" -> %s\n", ptr);
if (!strchr (ptr, '\\'))
{
char *lastsep;
- strncpy (tmp, cygpath (papp, NULL), 3999);
- for (char *p = tmp; (p = strchr (p, '/')); p++)
- *p = '\\';
+ strncpy (tmp, cygpath (papp, NULL), SYMLINK_MAX - 1);
lastsep = strrchr (tmp, '\\');
- strncpy (lastsep+1, ptr, 3999-(lastsep-tmp));
+ strncpy (lastsep+1, ptr, SYMLINK_MAX - 1 - (lastsep-tmp));
ptr = tmp;
}
if (!CloseHandle (fh))
display_error ("find_app_on_path: CloseHandle()");
+ /* FIXME: We leak the ptr returned by cygpath() here which is a
+ malloc()d string. */
return find_app_on_path (ptr, showall);
}
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 *
diff --git a/winsup/utils/path.h b/winsup/utils/path.h
index 134235e38..48739df74 100644
--- a/winsup/utils/path.h
+++ b/winsup/utils/path.h
@@ -9,9 +9,11 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
char *cygpath (const char *s, ...);
+char *cygpath_rel (const char *cwd, const char *s, ...);
bool is_exe (HANDLE);
bool is_symlink (HANDLE);
bool readlink (HANDLE, char *, int);
int get_word (HANDLE, int);
int get_dword (HANDLE, int);
+#define SYMLINK_MAX 4095 /* PATH_MAX - 1 */