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>
This commit is contained in:
Corinna Vinschen 2016-01-07 21:07:56 +01:00
parent 9614a29f17
commit e70dbe774a
2 changed files with 40 additions and 14 deletions

View File

@ -73,3 +73,7 @@ Bug Fixes
- Fix a potential crash reading invalid passwd and group entries from - Fix a potential crash reading invalid passwd and group entries from
/etc/passwd and /etc/group. /etc/passwd and /etc/group.
Addresses: https://cygwin.com/ml/cygwin/2015-12/msg00170.html 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

View File

@ -20,6 +20,7 @@ details. */
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <cygwin/version.h> #include <cygwin/version.h>
#include <ctype.h> #include <ctype.h>
#include <wctype.h>
#include <errno.h> #include <errno.h>
#define _WIN32_WINNT 0x0602 #define _WIN32_WINNT 0x0602
@ -579,20 +580,7 @@ do_sysfolders (char option)
break; break;
case 'S': case 'S':
{ GetSystemDirectoryW (wbuf, MAX_PATH);
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);
}
}
break; break;
case 'W': case 'W':
@ -607,9 +595,43 @@ do_sysfolders (char option)
{ {
fprintf (stderr, "%s: failed to retrieve special folder path\n", fprintf (stderr, "%s: failed to retrieve special folder path\n",
prog_name); prog_name);
return;
} }
else if (!windows_flag) 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, if (cygwin_conv_path (CCP_WIN_W_TO_POSIX | cygdrive_flag,
wbuf, buf, PATH_MAX)) wbuf, buf, PATH_MAX))
fprintf (stderr, "%s: error converting \"%ls\" - %s\n", fprintf (stderr, "%s: error converting \"%ls\" - %s\n",