OSDN Git Service

* path.h (INTERIX_SYMLINK_COOKIE): Define.
authorcorinna <corinna>
Wed, 26 Aug 2009 20:32:35 +0000 (20:32 +0000)
committercorinna <corinna>
Wed, 26 Aug 2009 20:32:35 +0000 (20:32 +0000)
* path.cc (symlink_info::check_sysfile): Read Interix symlinks as well.

winsup/cygwin/ChangeLog
winsup/cygwin/path.cc
winsup/cygwin/path.h

index 82a0f33..faa4c82 100644 (file)
@@ -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.
 
index 4d0b1b9..db514d3 100644 (file)
@@ -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;
 }
index 40aaf44..531a108 100644 (file)
@@ -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