summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-08-26 20:32:35 +0000
committerCorinna Vinschen <corinna@vinschen.de>2009-08-26 20:32:35 +0000
commit2671595b4acd429d9f9e8f52c5da6f71e1a0762f (patch)
tree187c1c57fad38583d86ef87c34270b2c3ba6c55e
parent50bd7b0bb6e66425b5b1cb315dacd157a6d30e1c (diff)
downloadcygnal-2671595b4acd429d9f9e8f52c5da6f71e1a0762f.tar.gz
cygnal-2671595b4acd429d9f9e8f52c5da6f71e1a0762f.tar.bz2
cygnal-2671595b4acd429d9f9e8f52c5da6f71e1a0762f.zip
* path.h (INTERIX_SYMLINK_COOKIE): Define.
* path.cc (symlink_info::check_sysfile): Read Interix symlinks as well.
-rw-r--r--winsup/cygwin/ChangeLog5
-rw-r--r--winsup/cygwin/path.cc36
-rw-r--r--winsup/cygwin/path.h3
3 files changed, 38 insertions, 6 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 82a0f338d..faa4c8215 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,10 @@
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>
+
* fhandler.cc (fhandler_base::open): Only set R/O attribute if ACLs
are not used.
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 4d0b1b9d2..db514d325 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1784,6 +1784,7 @@ symlink_info::check_sysfile (HANDLE in_h)
NTSTATUS status;
HANDLE h;
IO_STATUS_BLOCK io;
+ bool interix_symlink = false;
InitializeObjectAttributes (&attr, &same, 0, in_h, NULL);
status = NtOpenFile (&h, FILE_READ_DATA | SYNCHRONIZE,
@@ -1805,7 +1806,26 @@ symlink_info::check_sysfile (HANDLE in_h)
{
/* It's a 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,
NT_MAX_PATH, NULL, NULL);
if (!NT_SUCCESS (status))
@@ -1814,10 +1834,17 @@ symlink_info::check_sysfile (HANDLE in_h)
if (status != STATUS_END_OF_FILE)
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 ();
- if (sys_wcstombs (tmpbuf, NT_MAX_PATH, (PWCHAR) (srcbuf + 2))
+ if (sys_wcstombs (tmpbuf, NT_MAX_PATH, (PWCHAR) srcbuf)
> SYMLINK_MAX + 1)
debug_printf ("symlink string too long");
else
@@ -1828,9 +1855,6 @@ symlink_info::check_sysfile (HANDLE in_h)
else
res = posixify (srcbuf);
}
- else if (io.Information == sizeof (cookie_buf)
- && memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
- pflags |= PATH_SOCKET;
NtClose (h);
return res;
}
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 40aaf4498..531a108ca 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -258,6 +258,9 @@ class path_conv
/* Socket marker */
#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)));
enum fe_types