* path.cc (symlink_info::posixify): New mothod converting NT and DOS
paths in symlinks to POSIX. (symlink_info::check_shortcut): Allocate buf allowing for a trailing 0. Call posixify on the result. (symlink_info::check_sysfile): Read from file into local buffer. Eliminate old b16 considerations. Call posixify on the result. (symlink_info::check_reparse_point): Don't use PrintName but SubstituteName which is relevant for Windows' path handling. Call posixify on the result.
This commit is contained in:
parent
a45b9181ea
commit
5fc8f227dc
@ -1,3 +1,15 @@
|
|||||||
|
2006-11-02 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* path.cc (symlink_info::posixify): New mothod converting NT and DOS
|
||||||
|
paths in symlinks to POSIX.
|
||||||
|
(symlink_info::check_shortcut): Allocate buf allowing for a trailing 0.
|
||||||
|
Call posixify on the result.
|
||||||
|
(symlink_info::check_sysfile): Read from file into local buffer.
|
||||||
|
Eliminate old b16 considerations. Call posixify on the result.
|
||||||
|
(symlink_info::check_reparse_point): Don't use PrintName but
|
||||||
|
SubstituteName which is relevant for Windows' path handling.
|
||||||
|
Call posixify on the result.
|
||||||
|
|
||||||
2006-11-01 Corinna Vinschen <corinna@vinschen.de>
|
2006-11-01 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* security.h (cygpriv_idx): Add privileges new in Vista.
|
* security.h (cygpriv_idx): Add privileges new in Vista.
|
||||||
|
@ -105,6 +105,7 @@ struct symlink_info
|
|||||||
int check_sysfile (const char *path, HANDLE h);
|
int check_sysfile (const char *path, HANDLE h);
|
||||||
int check_shortcut (const char *path, HANDLE h);
|
int check_shortcut (const char *path, HANDLE h);
|
||||||
int check_reparse_point (const char *path, HANDLE h);
|
int check_reparse_point (const char *path, HANDLE h);
|
||||||
|
int posixify (char *srcbuf);
|
||||||
bool set_error (int);
|
bool set_error (int);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2999,7 +3000,7 @@ symlink_info::check_shortcut (const char *path, HANDLE h)
|
|||||||
|
|
||||||
if ((size = GetFileSize (h, NULL)) > 8192) /* Not a Cygwin symlink. */
|
if ((size = GetFileSize (h, NULL)) > 8192) /* Not a Cygwin symlink. */
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
buf = (char *) alloca (size);
|
buf = (char *) alloca (size + 1);
|
||||||
if (!ReadFile (h, buf, size, &got, 0))
|
if (!ReadFile (h, buf, size, &got, 0))
|
||||||
{
|
{
|
||||||
set_error (EIO);
|
set_error (EIO);
|
||||||
@ -3013,9 +3014,9 @@ symlink_info::check_shortcut (const char *path, HANDLE h)
|
|||||||
cp += *(unsigned short *) cp + 2;
|
cp += *(unsigned short *) cp + 2;
|
||||||
if ((len = *(unsigned short *) cp) == 0 || len >= CYG_MAX_PATH)
|
if ((len = *(unsigned short *) cp) == 0 || len >= CYG_MAX_PATH)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
strncpy (contents, cp += 2, len);
|
cp += 2;
|
||||||
contents[len] = '\0';
|
cp[len] = '\0';
|
||||||
res = len;
|
res = posixify (cp);
|
||||||
if (res) /* It's a symlink. */
|
if (res) /* It's a symlink. */
|
||||||
pflags = PATH_SYMLINK | PATH_LNK;
|
pflags = PATH_SYMLINK | PATH_LNK;
|
||||||
goto close_it;
|
goto close_it;
|
||||||
@ -3034,6 +3035,7 @@ int
|
|||||||
symlink_info::check_sysfile (const char *path, HANDLE h)
|
symlink_info::check_sysfile (const char *path, HANDLE h)
|
||||||
{
|
{
|
||||||
char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
|
char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
|
||||||
|
char srcbuf[CYG_MAX_PATH];
|
||||||
DWORD got;
|
DWORD got;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
@ -3048,26 +3050,14 @@ symlink_info::check_sysfile (const char *path, HANDLE h)
|
|||||||
/* It's a symlink. */
|
/* It's a symlink. */
|
||||||
pflags = PATH_SYMLINK;
|
pflags = PATH_SYMLINK;
|
||||||
|
|
||||||
res = ReadFile (h, contents, CYG_MAX_PATH, &got, 0);
|
res = ReadFile (h, srcbuf, CYG_MAX_PATH, &got, 0);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
debug_printf ("ReadFile2 failed");
|
debug_printf ("ReadFile2 failed");
|
||||||
set_error (EIO);
|
set_error (EIO);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
res = posixify (srcbuf);
|
||||||
/* Versions prior to b16 stored several trailing
|
|
||||||
NULs with the path (to fill the path out to 1024
|
|
||||||
chars). Current versions only store one trailing
|
|
||||||
NUL. The length returned is the path without
|
|
||||||
*any* trailing NULs. We also have to handle (or
|
|
||||||
at least not die from) corrupted paths. */
|
|
||||||
char *end;
|
|
||||||
if ((end = (char *) memchr (contents, 0, got)) != NULL)
|
|
||||||
res = end - contents;
|
|
||||||
else
|
|
||||||
res = got;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (got == sizeof (cookie_buf)
|
else if (got == sizeof (cookie_buf)
|
||||||
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
|
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
|
||||||
@ -3096,6 +3086,7 @@ symlink_info::check_reparse_point (const char *path, HANDLE h)
|
|||||||
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
|
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
|
||||||
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
char srcbuf[CYG_MAX_PATH + 6];
|
||||||
|
|
||||||
if (!DeviceIoControl (h, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID) rp,
|
if (!DeviceIoControl (h, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID) rp,
|
||||||
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, NULL))
|
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, NULL))
|
||||||
@ -3106,16 +3097,17 @@ symlink_info::check_reparse_point (const char *path, HANDLE h)
|
|||||||
}
|
}
|
||||||
if (rp->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
if (rp->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||||
{
|
{
|
||||||
if (rp->SymbolicLinkReparseBuffer.PrintNameLength > 2 * CYG_MAX_PATH)
|
if (rp->SymbolicLinkReparseBuffer.SubstituteNameLength
|
||||||
|
> 2 * (CYG_MAX_PATH + 6))
|
||||||
{
|
{
|
||||||
debug_printf ("Symlink name too long");
|
debug_printf ("Symlink name too long");
|
||||||
set_error (EIO);
|
set_error (EIO);
|
||||||
goto close_it;
|
goto close_it;
|
||||||
}
|
}
|
||||||
res = sys_wcstombs (contents, CYG_MAX_PATH,
|
sys_wcstombs (srcbuf, CYG_MAX_PATH,
|
||||||
(WCHAR *)((char *)rp->SymbolicLinkReparseBuffer.PathBuffer
|
(WCHAR *)((char *)rp->SymbolicLinkReparseBuffer.PathBuffer
|
||||||
+ rp->SymbolicLinkReparseBuffer.PrintNameOffset),
|
+ rp->SymbolicLinkReparseBuffer.SubstituteNameOffset),
|
||||||
rp->SymbolicLinkReparseBuffer.PrintNameLength / 2);
|
rp->SymbolicLinkReparseBuffer.SubstituteNameLength / 2);
|
||||||
pflags = PATH_SYMLINK | PATH_REP;
|
pflags = PATH_SYMLINK | PATH_REP;
|
||||||
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
|
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
}
|
}
|
||||||
@ -3126,24 +3118,82 @@ symlink_info::check_reparse_point (const char *path, HANDLE h)
|
|||||||
/* Likely a volume mount point. Not treated as symlink. */
|
/* Likely a volume mount point. Not treated as symlink. */
|
||||||
goto close_it;
|
goto close_it;
|
||||||
}
|
}
|
||||||
if (rp->MountPointReparseBuffer.PrintNameLength > 2 * CYG_MAX_PATH)
|
if (rp->MountPointReparseBuffer.SubstituteNameLength
|
||||||
|
> 2 * (CYG_MAX_PATH + 6))
|
||||||
{
|
{
|
||||||
debug_printf ("Symlink name too long");
|
debug_printf ("Symlink name too long");
|
||||||
set_error (EIO);
|
set_error (EIO);
|
||||||
goto close_it;
|
goto close_it;
|
||||||
}
|
}
|
||||||
res = sys_wcstombs (contents, CYG_MAX_PATH,
|
sys_wcstombs (srcbuf, CYG_MAX_PATH,
|
||||||
(WCHAR *)((char *)rp->MountPointReparseBuffer.PathBuffer
|
(WCHAR *)((char *)rp->MountPointReparseBuffer.PathBuffer
|
||||||
+ rp->MountPointReparseBuffer.PrintNameOffset),
|
+ rp->MountPointReparseBuffer.SubstituteNameOffset),
|
||||||
rp->MountPointReparseBuffer.PrintNameLength / 2);
|
rp->MountPointReparseBuffer.SubstituteNameLength / 2);
|
||||||
pflags = PATH_SYMLINK | PATH_REP;
|
pflags = PATH_SYMLINK | PATH_REP;
|
||||||
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
|
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
res = posixify (srcbuf);
|
||||||
close_it:
|
close_it:
|
||||||
CloseHandle (h);
|
CloseHandle (h);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
symlink_info::posixify (char *srcbuf)
|
||||||
|
{
|
||||||
|
/* The definition for a path in a native symlink is a bit weird. The Flags
|
||||||
|
value seem to contain 0 for absolute paths (stored as NT native path)
|
||||||
|
and 1 for relative paths. Relative paths are paths not starting with a
|
||||||
|
drive letter. These are not converted to NT native, but stored as
|
||||||
|
given. A path starting with a single backslash is relative to the
|
||||||
|
current drive thus a "relative" value (Flags == 1).
|
||||||
|
Funny enough it's possible to store paths with slashes instead of
|
||||||
|
backslashes, but they are evaluated incorrectly by subsequent Windows
|
||||||
|
calls like CreateFile (ERROR_INVALID_NAME). So, what we do here is to
|
||||||
|
take paths starting with slashes at face value, evaluating them as
|
||||||
|
Cygwin specific POSIX paths.
|
||||||
|
A path starting with two slashes(!) or backslashes is converted into an
|
||||||
|
NT UNC path. Unfortunately, in contrast to POSIX rules, paths starting
|
||||||
|
with three or more (back)slashes are also converted into UNC paths,
|
||||||
|
just incorrectly sticking to their redundant backslashes. We go along
|
||||||
|
with this behaviour to avoid scenarios in which native tools access
|
||||||
|
other files than Cygwin.
|
||||||
|
The above rules are used exactly the same way on Cygwin specific symlinks
|
||||||
|
(sysfiles and shortcuts) to eliminate non-POSIX paths in the output. */
|
||||||
|
|
||||||
|
/* Eliminate native NT prefixes. */
|
||||||
|
if (srcbuf[0] == '\\' && !strncmp (srcbuf + 1, "??\\", 3))
|
||||||
|
{
|
||||||
|
srcbuf += 4;
|
||||||
|
if (!strncmp (srcbuf, "UNC\\", 4))
|
||||||
|
{
|
||||||
|
srcbuf += 2;
|
||||||
|
*srcbuf = '\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isdrive (srcbuf))
|
||||||
|
mount_table->conv_to_posix_path (srcbuf, contents, 0);
|
||||||
|
else if (srcbuf[0] == '\\')
|
||||||
|
{
|
||||||
|
if (srcbuf[1] == '\\') /* UNC path */
|
||||||
|
slashify (srcbuf, contents, 0);
|
||||||
|
else /* Paths starting with \ are current drive relative. */
|
||||||
|
{
|
||||||
|
char cvtbuf[CYG_MAX_PATH + 6];
|
||||||
|
|
||||||
|
if (cygheap->cwd.win32)
|
||||||
|
strncpy (cvtbuf, cygheap->cwd.win32, 2);
|
||||||
|
else
|
||||||
|
GetCurrentDirectory (CYG_MAX_PATH, cvtbuf);
|
||||||
|
strcpy (cvtbuf + 2, srcbuf);
|
||||||
|
mount_table->conv_to_posix_path (cvtbuf, contents, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* Everything else is taken as is. */
|
||||||
|
slashify (srcbuf, contents, 0);
|
||||||
|
return strlen (contents);
|
||||||
|
}
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SCAN_BEG,
|
SCAN_BEG,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user