* 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:
parent
0c4cb56009
commit
60efa4e546
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue