* 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.
This commit is contained in:
Brian Dessent 2008-03-11 17:20:02 +00:00
parent 0c4cb56009
commit 60efa4e546
4 changed files with 100 additions and 31 deletions

View File

@ -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.

View File

@ -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);
}

View File

@ -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 *

View File

@ -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 */