https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=e70dbe774a0c5fe2f8112e06df1e231b1f114560

commit e70dbe774a0c5fe2f8112e06df1e231b1f114560
Author: Corinna Vinschen <cori...@vinschen.de>
Date:   Thu Jan 7 21:07:56 2016 +0100

    cygpath: Try to return system directories with correct case
    
        * cygpath.cc (do_sysfolders): Drop lame workaround to fix case of
        directory returned by GetSystemDirectoryW.  Try to fix case of
        any path returned by this function in case it has to return a
        POSIX path to support case-sensitivity.
    
    Signed-off-by: Corinna Vinschen <cori...@vinschen.de>

Diff:
---
 winsup/cygwin/release/2.4.0 |  4 ++++
 winsup/utils/cygpath.cc     | 50 ++++++++++++++++++++++++++++++++-------------
 2 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/winsup/cygwin/release/2.4.0 b/winsup/cygwin/release/2.4.0
index 4feff5b..5953d61 100644
--- a/winsup/cygwin/release/2.4.0
+++ b/winsup/cygwin/release/2.4.0
@@ -73,3 +73,7 @@ Bug Fixes
 - Fix a potential crash reading invalid passwd and group entries from
   /etc/passwd and /etc/group.
   Addresses: https://cygwin.com/ml/cygwin/2015-12/msg00170.html
+
+- Cygpath(1) now tries to correct the case of system directories when
+  returned as POSIX paths.
+  Addresses: https://cygwin.com/ml/cygwin/2016-01/msg00002.html
diff --git a/winsup/utils/cygpath.cc b/winsup/utils/cygpath.cc
index 0fbb2e9..c0a5276 100644
--- a/winsup/utils/cygpath.cc
+++ b/winsup/utils/cygpath.cc
@@ -20,6 +20,7 @@ details. */
 #include <sys/cygwin.h>
 #include <cygwin/version.h>
 #include <ctype.h>
+#include <wctype.h>
 #include <errno.h>
 
 #define _WIN32_WINNT 0x0602
@@ -579,20 +580,7 @@ do_sysfolders (char option)
       break;
 
     case 'S':
-      {
-       HANDLE fh;
-       WIN32_FIND_DATAW w32_fd;
-
-       GetSystemDirectoryW (wbuf, MAX_PATH);
-       /* The path returned by GetSystemDirectoryW is not case preserving.
-          The below code is a trick to get the correct case of the system
-          directory from Windows. */
-       if ((fh = FindFirstFileW (wbuf, &w32_fd)) != INVALID_HANDLE_VALUE)
-         {
-           FindClose (fh);
-           wcscpy (wcsrchr (wbuf, L'\\') + 1, w32_fd.cFileName);
-         }
-      }
+      GetSystemDirectoryW (wbuf, MAX_PATH);
       break;
 
     case 'W':
@@ -607,9 +595,43 @@ do_sysfolders (char option)
     {
       fprintf (stderr, "%s: failed to retrieve special folder path\n",
               prog_name);
+      return;
     }
   else if (!windows_flag)
     {
+      /* The system folders are not necessarily case-correct.  To allow
+        case-sensitivity, try to correct the case.  Note that this only
+        works for local filesystems. */
+      if (iswalpha (wbuf[0]) && wbuf[1] == L':' && wbuf[2] == L'\\')
+       {
+         OBJECT_ATTRIBUTES attr;
+         NTSTATUS status;
+         HANDLE h;
+         IO_STATUS_BLOCK io;
+         UNICODE_STRING upath;
+         const ULONG size = sizeof (FILE_NAME_INFORMATION)
+                            + PATH_MAX * sizeof (WCHAR);
+         PFILE_NAME_INFORMATION pfni = (PFILE_NAME_INFORMATION) alloca (size);
+
+         /* Avoid another buffer, reuse pfni. */
+         wcpcpy (wcpcpy (pfni->FileName, L"\\??\\"), wbuf);
+         RtlInitUnicodeString (&upath, pfni->FileName);
+         InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
+                                     NULL, NULL);
+         status = NtOpenFile (&h, READ_CONTROL, &attr, &io,
+                              FILE_SHARE_VALID_FLAGS, FILE_OPEN_REPARSE_POINT);
+         if (NT_SUCCESS (status))
+           {
+             status = NtQueryInformationFile (h, &io, pfni, size,
+                                              FileNameInformation);
+             if (NT_SUCCESS (status))
+               {
+                 pfni->FileName[pfni->FileNameLength / sizeof (WCHAR)] = L'\0';
+                 wcscpy (wbuf + 2, pfni->FileName);
+               }
+             NtClose (h);
+           }
+       }
       if (cygwin_conv_path (CCP_WIN_W_TO_POSIX | cygdrive_flag,
                            wbuf, buf, PATH_MAX))
        fprintf (stderr, "%s: error converting \"%ls\" - %s\n",

Reply via email to