]> sourceware.org Git - newlib-cygwin.git/commitdiff
* path.cc (cnt_bs): New inline function.
authorCorinna Vinschen <corinna@vinschen.de>
Mon, 17 Jun 2013 12:37:09 +0000 (12:37 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Mon, 17 Jun 2013 12:37:09 +0000 (12:37 +0000)
(symlink_native): Fix creating relative native symlink.

winsup/cygwin/ChangeLog
winsup/cygwin/path.cc
winsup/cygwin/release/1.7.21

index 7c2f442e52fe1ce569f2a8c1d1ade84d907c6c43..00ba880cb469e06e4a1f12367c53ad5a6f69b50c 100644 (file)
@@ -1,3 +1,8 @@
+2013-06-17  Corinna Vinschen  <corinna@vinschen.de>
+
+       * path.cc (cnt_bs): New inline function.
+       (symlink_native): Fix creating relative native symlink.
+
 2013-06-17  Corinna Vinschen  <corinna@vinschen.de>
 
        * fhandler_clipboard.cc (fhandler_dev_clipboard::read): Fix buffer
index e0fa37670126a6e3b0766788fa7c741d3ed25b3c..9492590c347fe3b9c43e20023a14e00a2be548c7 100644 (file)
@@ -1530,12 +1530,25 @@ symlink_nfs (const char *oldpath, path_conv &win32_newpath)
   return 0;
 }
 
+/* Count backslashes between s and e. */
+static inline int
+cnt_bs (PWCHAR s, PWCHAR e)
+{
+  int num = 0;
+
+  while (s < e)
+    if (*s++ == L'\\')
+      ++num;
+  return num;
+}
+
 static int
 symlink_native (const char *oldpath, path_conv &win32_newpath)
 {
   tmp_pathbuf tp;
   path_conv win32_oldpath;
   PUNICODE_STRING final_oldpath, final_newpath;
+  UNICODE_STRING final_oldpath_buf;
 
   if (isabspath (oldpath))
     {
@@ -1554,10 +1567,48 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
       stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path, len),
              oldpath);
       win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes);
-      UNICODE_STRING dirpath;
-      RtlSplitUnicodePath (win32_newpath.get_nt_native_path (), &dirpath, NULL);
-      final_oldpath = win32_oldpath.get_nt_native_path ();
-      final_oldpath->Buffer += dirpath.Length / sizeof (WCHAR);
+
+      /* Try hard to keep Windows symlink path relative. */
+
+      /* 1. Find common path prefix. */
+      PWCHAR c_old = win32_oldpath.get_nt_native_path ()->Buffer;
+      PWCHAR c_new = win32_newpath.get_nt_native_path ()->Buffer;
+      /* Windows compatible == always check case insensitive. */
+      while (towupper (*c_old++) == towupper (*c_new++))
+       ;
+      /* The last component could share a common prefix, so make sure we end
+         up on the first char after the last common backslash. */
+      while (c_old[-1] != L'\\')
+       --c_old, --c_new;
+
+      /* 2. Check if prefix is long enough.  The prefix must at least points to
+            a complete device:  \\?\X:\ or \\?\UNC\server\share\ are the minimum
+           prefix strings.  We start counting behind the \\?\ for speed. */
+      int num = cnt_bs (win32_oldpath.get_nt_native_path ()->Buffer + 4, c_old);
+      if (num < 1              /* locale drive. */
+         || (win32_oldpath.get_nt_native_path ()->Buffer[6] != L':'
+             && num < 3))      /* UNC path. */
+       {
+         /* 3a. No valid common path prefix: Create absolute symlink. */
+         final_oldpath = win32_oldpath.get_nt_native_path ();
+         final_oldpath->Buffer[1] = L'\\';
+       }
+      else
+       {
+         /* 3b. Common path prefx.  Count number of additional directories
+                in symlink's path, and prepend as much ".." path components
+                to the target path. */
+         PWCHAR e_new = win32_newpath.get_nt_native_path ()->Buffer
+                        + win32_newpath.get_nt_native_path ()->Length
+                          / sizeof (WCHAR);
+         num = cnt_bs (c_new, e_new);
+         final_oldpath = &final_oldpath_buf;
+         final_oldpath->Buffer = tp.w_get ();
+         PWCHAR e_old = final_oldpath->Buffer;
+         while (num-- > 0)
+           e_old = wcpcpy (e_old, L"..\\");
+         wcpcpy (e_old, c_old);
+       }
     }
   /* If the symlink target doesn't exist, don't create native symlink.
      Otherwise the directory flag in the symlink is potentially wrong
index 2ea267778d7d2612de3a272fdd14f574763ea6c1..b1a045eeb5fa2d79c38e3a7d504a9146f4ab65a2 100644 (file)
@@ -11,3 +11,6 @@ Bug fixes:
 
 - Fix EFAULT when reading large clipboard.
   Fixes: http://cygwin.com/ml/cygwin/2013-06/msg00311.html
+
+- Fix creation of relative native symlinks.
+  Fixes: http://cygwin.com/ml/cygwin/2013-06/msg00340.html
This page took 0.044788 seconds and 5 git commands to generate.