* path.h (INTERIX_SYMLINK_COOKIE): Define.

* path.cc (symlink_info::check_sysfile): Read Interix symlinks as well.
This commit is contained in:
Corinna Vinschen 2009-08-26 20:32:35 +00:00
parent 50bd7b0bb6
commit 2671595b4a
3 changed files with 38 additions and 6 deletions

View File

@ -1,3 +1,8 @@
2009-08-26 Corinna Vinschen <corinna@vinschen.de>
* path.h (INTERIX_SYMLINK_COOKIE): Define.
* path.cc (symlink_info::check_sysfile): Read Interix symlinks as well.
2009-08-26 Corinna Vinschen <corinna@vinschen.de> 2009-08-26 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_base::open): Only set R/O attribute if ACLs * fhandler.cc (fhandler_base::open): Only set R/O attribute if ACLs

View File

@ -1784,6 +1784,7 @@ symlink_info::check_sysfile (HANDLE in_h)
NTSTATUS status; NTSTATUS status;
HANDLE h; HANDLE h;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
bool interix_symlink = false;
InitializeObjectAttributes (&attr, &same, 0, in_h, NULL); InitializeObjectAttributes (&attr, &same, 0, in_h, NULL);
status = NtOpenFile (&h, FILE_READ_DATA | SYNCHRONIZE, status = NtOpenFile (&h, FILE_READ_DATA | SYNCHRONIZE,
@ -1805,7 +1806,26 @@ symlink_info::check_sysfile (HANDLE in_h)
{ {
/* It's a symlink. */ /* It's a symlink. */
pflags = PATH_SYMLINK; pflags = PATH_SYMLINK;
}
else if (io.Information == sizeof (cookie_buf)
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
pflags |= PATH_SOCKET;
else if (io.Information >= sizeof (INTERIX_SYMLINK_COOKIE)
&& memcmp (cookie_buf, INTERIX_SYMLINK_COOKIE,
sizeof (INTERIX_SYMLINK_COOKIE) - 1) == 0)
{
/* It's an Interix symlink. */
pflags = PATH_SYMLINK;
interix_symlink = true;
/* Interix symlink cookies are shorter than Cygwin symlink cookies, so
in case of an Interix symlink cooky we have read too far into the
file. Set file pointer back to the position right after the cookie. */
FILE_POSITION_INFORMATION fpi;
fpi.CurrentByteOffset.QuadPart = sizeof (INTERIX_SYMLINK_COOKIE) - 1;
NtSetInformationFile (h, &io, &fpi, sizeof fpi, FilePositionInformation);
}
if (pflags == PATH_SYMLINK)
{
status = NtReadFile (h, NULL, NULL, NULL, &io, srcbuf, status = NtReadFile (h, NULL, NULL, NULL, &io, srcbuf,
NT_MAX_PATH, NULL, NULL); NT_MAX_PATH, NULL, NULL);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
@ -1814,10 +1834,17 @@ symlink_info::check_sysfile (HANDLE in_h)
if (status != STATUS_END_OF_FILE) if (status != STATUS_END_OF_FILE)
set_error (EIO); set_error (EIO);
} }
else if (*(PWCHAR) srcbuf == 0xfeff) /* BOM */ else if (*(PWCHAR) srcbuf == 0xfeff /* BOM */
|| interix_symlink)
{ {
/* Add trailing 0 to Interix symlink target. Skip BOM in Cygwin
symlinks. */
if (interix_symlink)
((PWCHAR) srcbuf)[io.Information / sizeof (WCHAR)] = L'\0';
else
srcbuf += 2;
char *tmpbuf = tp.c_get (); char *tmpbuf = tp.c_get ();
if (sys_wcstombs (tmpbuf, NT_MAX_PATH, (PWCHAR) (srcbuf + 2)) if (sys_wcstombs (tmpbuf, NT_MAX_PATH, (PWCHAR) srcbuf)
> SYMLINK_MAX + 1) > SYMLINK_MAX + 1)
debug_printf ("symlink string too long"); debug_printf ("symlink string too long");
else else
@ -1828,9 +1855,6 @@ symlink_info::check_sysfile (HANDLE in_h)
else else
res = posixify (srcbuf); res = posixify (srcbuf);
} }
else if (io.Information == sizeof (cookie_buf)
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
pflags |= PATH_SOCKET;
NtClose (h); NtClose (h);
return res; return res;
} }

View File

@ -258,6 +258,9 @@ class path_conv
/* Socket marker */ /* Socket marker */
#define SOCKET_COOKIE "!<socket >" #define SOCKET_COOKIE "!<socket >"
/* Interix symlink marker */
#define INTERIX_SYMLINK_COOKIE "IntxLNK\1"
int __stdcall slash_unc_prefix_p (const char *path) __attribute__ ((regparm(1))); int __stdcall slash_unc_prefix_p (const char *path) __attribute__ ((regparm(1)));
enum fe_types enum fe_types