This is the mail archive of the
cygwin-cvs@cygwin.com
mailing list for the Cygwin project.
[newlib-cygwin] cygpath: Try to return system directories with correct case
- From: Corinna Vinschen <corinna at sourceware dot org>
- To: cygwin-cvs at sourceware dot org
- Date: 7 Jan 2016 20:08:04 -0000
- Subject: [newlib-cygwin] cygpath: Try to return system directories with correct case
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=e70dbe774a0c5fe2f8112e06df1e231b1f114560
commit e70dbe774a0c5fe2f8112e06df1e231b1f114560
Author: Corinna Vinschen <corinna@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 <corinna@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",