From: Corinna Vinschen Date: Thu, 31 Jan 2008 14:18:49 +0000 (+0000) Subject: * cygheap.h (struct cwdstuff): Add dir member to store cwd handle. X-Git-Tag: gdb_6_8-2008-02-26-branchpoint~50 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=8e87af7ed082bf06a30e226e6bc779c932db625a;p=newlib-cygwin.git * cygheap.h (struct cwdstuff): Add dir member to store cwd handle. (cwdstuff::get_handle): New method. * path.cc (cwdstuff::set): When doit is true, always try to get directory handle. Fail if duplicating handle fails. Store handle in dir. Fix potential SEGV when setting drive_length. --- diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f88b56212..20af6ca60 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +2008-01-31 Corinna Vinschen + + * cygheap.h (struct cwdstuff): Add dir member to store cwd handle. + (cwdstuff::get_handle): New method. + * path.cc (cwdstuff::set): When doit is true, always try to get + directory handle. Fail if duplicating handle fails. Store handle + in dir. Fix potential SEGV when setting drive_length. + 2008-01-28 Corinna Vinschen * path.cc: Fix Samba version in comment. diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index f51b9a1e9..7d232584a 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -223,9 +223,11 @@ struct cwdstuff { char *posix; UNICODE_STRING win32; + HANDLE dir; DWORD drive_length; static muto cwd_lock; char *get (char *, int = 1, int = 0, unsigned = CYG_MAX_PATH); + HANDLE get_handle () { return dir; } DWORD get_drive (char * dst) { cwd_lock.acquire (); diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index a3b0f007e..8d7703e40 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -4431,7 +4431,7 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) - Unlinking a cwd fails because SetCurrentDirectory seems to open directories so that deleting the directory is disallowed. The below code opens with *all* sharing flags set. */ - HANDLE h; + HANDLE h, h_copy; NTSTATUS status; IO_STATUS_BLOCK io; OBJECT_ATTRIBUTES attr; @@ -4441,18 +4441,6 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) phdl = &get_user_proc_parms ()->CurrentDirectoryHandle; if (!nat_cwd) /* On init, just reopen CWD with desired access flags. */ RtlInitUnicodeString (&upath, L""); - else - { - /* TODO: - Check the length of the new CWD. Windows can only handle - CWDs of up to MAX_PATH length, including a trailing backslash. - If the path is longer, it's not an error condition for Cygwin, - so we don't fail. Windows on the other hand has a problem now. - For now, we just don't store the path in the PEB and proceed as - usual. */ - if (len > MAX_PATH - (nat_cwd->Buffer[len - 1] == L'\\' ? 1 : 2)) - goto skip_peb_storing; - } InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT, nat_cwd ? NULL : *phdl, NULL); @@ -4468,8 +4456,36 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) res = -1; goto out; } + /* Workaround a problem in Vista which fails in subsequent calls to + CreateFile with ERROR_INVALID_HANDLE if the handle in + CurrentDirectoryHandle changes without calling SetCurrentDirectory, + and the filename given to CreateFile is a relative path. It looks + like Vista stores a copy of the CWD handle in some other undocumented + place. The NtClose/DuplicateHandle reuses the original handle for + the copy of the new handle and the next CreateFile works. + Note that this is not thread-safe (yet?) */ + if (!DuplicateHandle (GetCurrentProcess (), h, GetCurrentProcess (), + &h_copy, 0, TRUE, DUPLICATE_SAME_ACCESS)) + { + RtlReleasePebLock (); + __seterrno (); + NtClose (h); + res = -1; + goto out; + } + NtClose (*phdl); + dir = *phdl = h; - if (nat_cwd) /* No need to set path on init. */ + /* No need to set path on init. */ + if (nat_cwd + /* TODO: + Check the length of the new CWD. Windows can only handle + CWDs of up to MAX_PATH length, including a trailing backslash. + If the path is longer, it's not an error condition for Cygwin, + so we don't fail. Windows on the other hand has a problem now. + For now, we just don't store the path in the PEB and proceed as + usual. */ + && len <= MAX_PATH - (nat_cwd->Buffer[len - 1] == L'\\' ? 1 : 2)) { /* Convert to a Win32 path. */ upath.Buffer += upath.Length / sizeof (WCHAR) - len; @@ -4485,22 +4501,6 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) RtlCopyUnicodeString (&get_user_proc_parms ()->CurrentDirectoryName, &upath); } - NtClose (*phdl); - /* Workaround a problem in Vista which fails in subsequent calls to - CreateFile with ERROR_INVALID_HANDLE if the handle in - CurrentDirectoryHandle changes without calling SetCurrentDirectory, - and the filename given to CreateFile is a relative path. It looks - like Vista stores a copy of the CWD handle in some other undocumented - place. The NtClose/DuplicateHandle reuses the original handle for - the copy of the new handle and the next CreateFile works. - Note that this is not thread-safe (yet?) */ - if (DuplicateHandle (GetCurrentProcess (), h, GetCurrentProcess (), phdl, - 0, TRUE, DUPLICATE_SAME_ACCESS)) - NtClose (h); - else - *phdl = h; - -skip_peb_storing: RtlReleasePebLock (); } @@ -4552,7 +4552,7 @@ skip_peb_storing: else if (win32.Buffer[1] == L'\\') { PWCHAR ptr = wcschr (win32.Buffer + 2, L'\\'); - if (*ptr) + if (ptr) ptr = wcschr (ptr + 1, L'\\'); if (ptr) drive_length = ptr - win32.Buffer;