From 1121c57f54af94fb8e4af815c8469c392c8fce69 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 27 Aug 2010 17:58:45 +0000 Subject: [PATCH] * external.cc (sync_wincwd): Remove. (cygwin_internal): Drop CW_SYNC_WINCWD case. * globals.cc (ro_u_pipedir): New R/O unicode string. * ntdll.h (RtlSetCurrentDirectory_U): Declare. * path.cc (cwdstuff::set): Improve comments. Drop setting Win32 CWD to \\?\PIPE\ on init. Keep Win32 CWD in sync, if possible. Set to \\?\PIPE\ otherwise. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Revert to 230. * include/sys/cygwin.h (cygwin_getinfo_types): Remove CW_SYNC_WINCWD. --- winsup/cygwin/ChangeLog | 12 ++++++ winsup/cygwin/external.cc | 26 ------------ winsup/cygwin/globals.cc | 1 + winsup/cygwin/include/cygwin/version.h | 3 +- winsup/cygwin/include/sys/cygwin.h | 3 +- winsup/cygwin/ntdll.h | 1 + winsup/cygwin/path.cc | 59 ++++++++++++++++---------- 7 files changed, 52 insertions(+), 53 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e7043c0a4..c29e89309 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,15 @@ +2010-08-27 Corinna Vinschen + + * external.cc (sync_wincwd): Remove. + (cygwin_internal): Drop CW_SYNC_WINCWD case. + * globals.cc (ro_u_pipedir): New R/O unicode string. + * ntdll.h (RtlSetCurrentDirectory_U): Declare. + * path.cc (cwdstuff::set): Improve comments. Drop setting Win32 CWD to + \\?\PIPE\ on init. Keep Win32 CWD in sync, if possible. Set to + \\?\PIPE\ otherwise. + * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Revert to 230. + * include/sys/cygwin.h (cygwin_getinfo_types): Remove CW_SYNC_WINCWD. + 2010-08-27 Corinna Vinschen * fhandler_proc.cc (format_proc_partitions): Improve comment. diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index 7b26eefa0..93fc2b331 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -162,29 +162,6 @@ sync_winenv () free (envblock); } -/* Synchronize Win32 CWD with Cygwin CWD. Return -1 and set errno if - setting the Win32 CWD fails. */ -static unsigned long -sync_wincwd () -{ - unsigned long ret = (unsigned long) -1; - /* Lock cwd. We're accessing it directly here. */ - cygheap->cwd.cwd_lock.acquire (); - /* First check if the path can work at all. Fortunately we already have - an error code in the cwd, which was stored there for the sake of - spawn_guts. */ - if (cygheap->cwd.get_error ()) - set_errno (cygheap->cwd.get_error ()); - /* Of course, SetCurrentDirectoryW still can fail, for instance, if the - CWD has been removed or renamed in the meantime. */ - else if (!SetCurrentDirectoryW (cygheap->cwd.win32.Buffer)) - __seterrno (); - else - ret = 0; - cygheap->cwd.cwd_lock.release (); - return ret; -} - /* * Cygwin-specific wrapper for win32 ExitProcess and TerminateProcess. * It ensures that the correct exit code, derived from the specified @@ -537,9 +514,6 @@ cygwin_internal (cygwin_getinfo_types t, ...) res = (uintptr_t) strerror (err); } break; - case CW_SYNC_WINCWD: - res = sync_wincwd (); - break; default: set_errno (ENOSYS); diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index 6060edcf3..c517a6233 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -109,6 +109,7 @@ UNICODE_STRING _RDATA ro_u_udf = _ROU (L"UDF"); UNICODE_STRING _RDATA ro_u_unixfs = _ROU (L"UNIXFS"); UNICODE_STRING _RDATA ro_u_nwfs = _ROU (L"NWFS"); UNICODE_STRING _RDATA ro_u_volume = _ROU (L"\\??\\Volume{"); +UNICODE_STRING _RDATA ro_u_pipedir = _ROU (L"\\\\?\\PIPE\\"); #undef _ROU /* Cygwin properties are meant to be readonly data placed in the DLL, but diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 14286a0f5..6a28b7bf6 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -390,13 +390,12 @@ details. */ 228: CW_STRERROR added. 229: Add mkostemp, mkostemps. 230: Add CLOCK_MONOTONIC. - 231: CW_SYNC_WINCWD. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 231 +#define CYGWIN_VERSION_API_MINOR 230 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index aa4ce4d7c..d6df27df9 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -149,8 +149,7 @@ typedef enum CW_INT_SETLOCALE, CW_CVT_MNT_OPTS, CW_LST_MNT_OPTS, - CW_STRERROR, - CW_SYNC_WINCWD + CW_STRERROR } cygwin_getinfo_types; /* Token type for CW_SET_EXTERNAL_TOKEN */ diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 0b2229d97..94b17ee51 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -1005,6 +1005,7 @@ extern "C" BOOLEAN); VOID NTAPI RtlReleasePebLock (); VOID NTAPI RtlSecondsSince1970ToTime (ULONG, PLARGE_INTEGER); + NTSTATUS NTAPI RtlSetCurrentDirectory_U (PUNICODE_STRING); BOOLEAN NTAPI RtlSetCurrentTransaction (HANDLE); NTSTATUS NTAPI RtlUnicodeStringToAnsiString (PANSI_STRING, PUNICODE_STRING, BOOLEAN); diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index deefc7791..f0cdbee1c 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -3286,36 +3286,48 @@ cwdstuff::init () int cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd) { + NTSTATUS status; UNICODE_STRING upath; bool virtual_path = false; bool unc_path = false; bool inaccessible_path = false; - /* Here are the problems with using SetCurrentDirectory: + /* Here are the problems with using SetCurrentDirectory. Just skip this + comment if you don't like whining. - SetCurrentDirectory only supports paths of up to MAX_PATH - 1 chars, including a trailing backslash. That's an absolute restriction, even in the UNICODE API. - - SetCurrentDirectory fails for directories with strict - permissions even for processes with the SE_BACKUP_NAME - privilege enabled. The reason is apparently that - SetCurrentDirectory calls NtOpenFile without the + - SetCurrentDirectory fails for directories with strict permissions even + for processes with the SE_BACKUP_NAME privilege enabled. The reason + is apparently that SetCurrentDirectory calls NtOpenFile without the FILE_OPEN_FOR_BACKUP_INTENT flag set. - SetCurrentDirectory does not support case-sensitivity. - - Unlinking a cwd fails because SetCurrentDirectory seems to - open directories so that deleting the directory is disallowed. + - Unlinking a cwd fails because SetCurrentDirectory seems to open + directories so that deleting the directory is disallowed. - SetCurrentDirectory can naturally not work on virtual Cygwin paths like /proc or /cygdrive. - Therefore, we do without SetCurrentDirectory and handle the CWD all - by ourselves. To avoid surprising behaviour in the Win32 API which - would stem from the fact that the Win32 CWD is different from the - POSIX CWD, we move the Win32 CWD to an invalid directory in which - typical relative Win32 path handling fails. */ + Unfortunately, even though we have access to the Win32 process parameter + block, we can't just replace the directory handle. Starting with Vista, + the handle is used elsewhere, and just replacing the handle in the process + parameter block shows quite surprising results. + FIXME: If we ever find a *safe* way to replace the directory handle in + the process parameter block, we're back in business. + + Nevertheless, doing entirely without SetCurrentDirectory is not really + feasible, because it breaks too many mixed applications using the Win32 + API. + + Therefore we handle the CWD all by ourselves and just keep the Win32 + CWD in sync. However, to avoid surprising behaviour in the Win32 API + when we are in a CWD which is inaccessible as Win32 CWD, we set the + Win32 CWD to a "weird" directory in which all relative filesystem-related + calls fail. */ cwd_lock.acquire (); @@ -3332,7 +3344,6 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd) HANDLE h = NULL; if (!virtual_path) { - NTSTATUS status; IO_STATUS_BLOCK io; OBJECT_ATTRIBUTES attr; @@ -3351,7 +3362,9 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd) nat_cwd->objcaseinsensitive () | OBJ_INHERIT, NULL, NULL); /* First try without FILE_OPEN_FOR_BACKUP_INTENT, to find out if the - directory is valid for Win32 apps. */ + directory is valid for Win32 apps. And, no, we can't just call + SetCurrentDirectory here, since that would potentially break + case-sensitivity. */ status = NtOpenFile (&h, SYNCHRONIZE | FILE_TRAVERSE, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE @@ -3397,15 +3410,6 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd) unc_path = true; posix_cwd = NULL; - - /* When inited move the actual Win32 CWD out of the way, as explained - above. Surprisingly, the PIPE filesystem seems to be usable as CWD - on all Windows systems. */ - if (!SetCurrentDirectoryW (L"\\\\?\\PIPE\\")) - system_printf ( -"WARNING: Couldn't set Win32 CWD to //?/PIPE (error %E). This will\n" -"probably not affect normal POSIX path operations. However, please report\n" -"this problem to the mailing list mailto:cygwin@cygwin.com. Thank you."); } else { @@ -3468,6 +3472,15 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd) else error = 0; } + /* Keep the Win32 CWD in sync. Don't check for error, other than for + strace output. Try to keep overhead low. */ + if (nat_cwd) + { + status = RtlSetCurrentDirectory_U (error ? &ro_u_pipedir : &win32); + if (!NT_SUCCESS (status)) + debug_printf ("RtlSetCurrentDirectory_U(%S) failed, %p", + error ? &ro_u_pipedir : &win32, status); + } /* Eventually, create POSIX path if it's not set on entry. */ tmp_pathbuf tp;