From 5b312b4747cc4acda39c187369c02fcea456513b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 31 Oct 2013 14:26:42 +0000 Subject: [PATCH] * devices.in (dev_cygdrive_storage): Revert mapping to \Device\Null. (dev_storage): Ditto for /dev. * devices.cc: Regenerate. * fhandler.cc (fhandler_base::open_null): New method to open a fake \Device\Null handler. (fhandler_base::open): Fix formatting. Change O_ACCMODE test to a switch statement. Simplify a test which still tested for a now unused create_disposition. * fhandler.h (fhandler_base::open_null): Declare. (fhandler_netdrive::close): Declare. * fhandler_dev.cc (fhandler_dev::open): Open fake \Device\Null handle by just calling new open_null method. * fhandler_disk_file.cc (fhandler_cygdrive::open): Ditto. * fhandler_netdrive.cc (fhandler_netdrive::open): Call open_null rather than setting nohandle. (fhandler_netdrive::close): New method. * fhandler_registry.cc (fetch_hkey): Fix token in RegOpenUserClassesRoot call. Create valid key for HKEY_CURRENT_CONFIG by mapping to real key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Hardware Profiles\Current. (fhandler_registry::open): Set nohandle only when using pseudo registry handle. * fhandler_virtual.cc (fhandler_virtual::opendir): Call open rather than just setting nohandle here. * fhandler_virtual::fstatvfs): Set ST_RDONLY fs flag. * globals.cc (ro_u_null): New readonly UNICODE_STRING for \Device\Null. * path.h (path_conv::set_path): Revert previous change caring for wide_path. --- winsup/cygwin/ChangeLog | 30 +++++++++ winsup/cygwin/devices.cc | 4 +- winsup/cygwin/devices.in | 4 +- winsup/cygwin/fhandler.cc | 98 ++++++++++++++++++++--------- winsup/cygwin/fhandler.h | 2 + winsup/cygwin/fhandler_dev.cc | 12 +--- winsup/cygwin/fhandler_disk_file.cc | 12 +--- winsup/cygwin/fhandler_netdrive.cc | 29 ++++----- winsup/cygwin/fhandler_registry.cc | 16 ++++- winsup/cygwin/fhandler_virtual.cc | 8 +-- winsup/cygwin/globals.cc | 1 + winsup/cygwin/path.h | 1 - 12 files changed, 138 insertions(+), 79 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7ea534b23..e1c6fb7cb 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,33 @@ +2013-10-30 Corinna Vinschen + + * devices.in (dev_cygdrive_storage): Revert mapping to \Device\Null. + (dev_storage): Ditto for /dev. + * devices.cc: Regenerate. + * fhandler.cc (fhandler_base::open_null): New method to open a fake + \Device\Null handler. + (fhandler_base::open): Fix formatting. Change O_ACCMODE test to a + switch statement. Simplify a test which still tested for a now unused + create_disposition. + * fhandler.h (fhandler_base::open_null): Declare. + (fhandler_netdrive::close): Declare. + * fhandler_dev.cc (fhandler_dev::open): Open fake \Device\Null handle + by just calling new open_null method. + * fhandler_disk_file.cc (fhandler_cygdrive::open): Ditto. + * fhandler_netdrive.cc (fhandler_netdrive::open): Call open_null + rather than setting nohandle. + (fhandler_netdrive::close): New method. + * fhandler_registry.cc (fetch_hkey): Fix token in RegOpenUserClassesRoot + call. Create valid key for HKEY_CURRENT_CONFIG by mapping to real key + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Hardware Profiles\Current. + (fhandler_registry::open): Set nohandle only when using pseudo registry + handle. + * fhandler_virtual.cc (fhandler_virtual::opendir): Call open rather + than just setting nohandle here. + * fhandler_virtual::fstatvfs): Set ST_RDONLY fs flag. + * globals.cc (ro_u_null): New readonly UNICODE_STRING for \Device\Null. + * path.h (path_conv::set_path): Revert previous change caring for + wide_path. + 2013-10-30 Corinna Vinschen * devices.in (dev_cygdrive_storage): Map to \Device\Null. diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index cd49d4959..8aba6d840 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -91,7 +91,7 @@ exists_pty (const device& dev) } const device dev_cygdrive_storage = - {"/cygdrive", {FH_CYGDRIVE}, "\\Device\\Null", exists}; + {"/cygdrive", {FH_CYGDRIVE}, "", exists}; const device dev_fs_storage = {"", {FH_FS}, "", exists}; @@ -141,7 +141,7 @@ const device dev_error_storage = #define BRACK(x) {devn_int: x} const _RDATA device dev_storage[] = { - {"/dev", BRACK(FH_DEV), "\\Device\\Null", exists, S_IFDIR, false}, + {"/dev", BRACK(FH_DEV), "", exists, S_IFDIR, false}, {"/dev/clipboard", BRACK(FH_CLIPBOARD), "\\Device\\Null", exists_ntdev, S_IFCHR, true}, {"/dev/com1", BRACK(FHDEV(DEV_SERIAL_MAJOR, 0)), "\\??\\COM1", exists_ntdev_silent, S_IFCHR, true}, {"/dev/com2", BRACK(FHDEV(DEV_SERIAL_MAJOR, 1)), "\\??\\COM2", exists_ntdev_silent, S_IFCHR, true}, diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index 520191eb7..c43f11c0f 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -87,7 +87,7 @@ exists_pty (const device& dev) } const device dev_cygdrive_storage = - {"/cygdrive", {FH_CYGDRIVE}, "\\Device\\Null", exists}; + {"/cygdrive", {FH_CYGDRIVE}, "", exists}; const device dev_fs_storage = {"", {FH_FS}, "", exists}; @@ -140,7 +140,7 @@ const device dev_error_storage = /* Internal devices below are prefixed with a ":". This moves them out of the POSIX namespace. */ %% -"/dev", BRACK(FH_DEV), "\\Device\\Null", exists, S_IFDIR +"/dev", BRACK(FH_DEV), "", exists, S_IFDIR "/dev/tty", BRACK(FH_TTY), "/dev/tty", exists, S_IFCHR "/dev/pty%(0-63)d", BRACK(FHDEV(DEV_PTYS_MAJOR, {$1})), "/dev/pty{$1}", exists_pty, S_IFCHR, =ptys_dev ":ptym%(0-63)d", BRACK(FHDEV(DEV_PTYM_MAJOR, {$1})), "/dev/ptym{$1}", exists_internal, S_IFCHR, =ptym_dev diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 39dcbd057..c64fc33b1 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -507,6 +507,38 @@ fhandler_base::open_with_arch (int flags, mode_t mode) return res; } +/* Open a fake handle to \\Device\\Null. This is a helper function for + fhandlers which just need some handle to keep track of BSD flock locks. */ +int +fhandler_base::open_null (int flags) +{ + int res = 0; + HANDLE fh; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + NTSTATUS status; + + InitializeObjectAttributes (&attr, &ro_u_null, OBJ_CASE_INSENSITIVE | + ((flags & O_CLOEXEC) ? 0 : OBJ_INHERIT), + NULL, NULL); + status = NtCreateFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + goto done; + } + set_io_handle (fh); + set_flags (flags, pc.binmode ()); + res = 1; + set_open_status (); +done: + debug_printf ("%y = NtCreateFile (%p, ... %S ...)", status, fh, &ro_u_null); + syscall_printf ("%d = fhandler_base::open_null (%y)", res, flags); + return res; +} + /* Open system call handler function. */ int fhandler_base::open (int flags, mode_t mode) @@ -529,38 +561,44 @@ fhandler_base::open (int flags, mode_t mode) options = FILE_OPEN_FOR_BACKUP_INTENT; switch (query_open ()) { - case query_read_control: - access = READ_CONTROL; - break; - case query_read_attributes: - access = READ_CONTROL | FILE_READ_ATTRIBUTES; - break; - case query_write_control: - access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES; - break; - case query_write_dac: - access = READ_CONTROL | WRITE_DAC | FILE_WRITE_ATTRIBUTES; - break; - case query_write_attributes: - access = READ_CONTROL | FILE_WRITE_ATTRIBUTES; - break; - default: - if ((flags & O_ACCMODE) == O_RDONLY) + case query_read_control: + access = READ_CONTROL; + break; + case query_read_attributes: + access = READ_CONTROL | FILE_READ_ATTRIBUTES; + break; + case query_write_control: + access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES; + break; + case query_write_dac: + access = READ_CONTROL | WRITE_DAC | FILE_WRITE_ATTRIBUTES; + break; + case query_write_attributes: + access = READ_CONTROL | FILE_WRITE_ATTRIBUTES; + break; + default: + switch (flags & O_ACCMODE) + { + case O_RDONLY: access = GENERIC_READ; - else if ((flags & O_ACCMODE) == O_WRONLY) + break; + case O_WRONLY: access = GENERIC_WRITE | READ_CONTROL | FILE_READ_ATTRIBUTES; - else + break; + default: access = GENERIC_READ | GENERIC_WRITE; - if (flags & O_SYNC) - options |= FILE_WRITE_THROUGH; - if (flags & O_DIRECT) - options |= FILE_NO_INTERMEDIATE_BUFFERING; - if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR) - { - options |= FILE_SYNCHRONOUS_IO_NONALERT; - access |= SYNCHRONIZE; - } - break; + break; + } + if (flags & O_SYNC) + options |= FILE_WRITE_THROUGH; + if (flags & O_DIRECT) + options |= FILE_NO_INTERMEDIATE_BUFFERING; + if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR) + { + options |= FILE_SYNCHRONOUS_IO_NONALERT; + access |= SYNCHRONIZE; + } + break; } /* Don't use the FILE_OVERWRITE{_IF} flags here. See below for an @@ -596,7 +634,7 @@ fhandler_base::open (int flags, mode_t mode) and/or FILE_ATTRIBUTE_SYSTEM attribute set, NtCreateFile fails with STATUS_ACCESS_DENIED. Per MSDN you have to create the file with the same attributes as already specified for the file. */ - if (((flags & O_CREAT) || create_disposition == FILE_OVERWRITE) + if (create_disposition == FILE_CREATE && has_attribute (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) file_attributes |= pc.file_attributes (); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index d2f9758d8..d63e7448f 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -310,6 +310,7 @@ class fhandler_base virtual bool need_fixup_before () const {return false;} int open_with_arch (int, mode_t = 0); + int open_null (int flags); virtual int open (int, mode_t); virtual void open_setup (int flags); void set_unique_id () { NtAllocateLocallyUniqueId ((PLUID) &unique_id); } @@ -1962,6 +1963,7 @@ class fhandler_netdrive: public fhandler_virtual void rewinddir (DIR *); int closedir (DIR *); int open (int flags, mode_t mode = 0); + int close (); int __reg2 fstat (struct stat *buf); fhandler_netdrive (void *) {} diff --git a/winsup/cygwin/fhandler_dev.cc b/winsup/cygwin/fhandler_dev.cc index 668d0b480..4f92a1db8 100644 --- a/winsup/cygwin/fhandler_dev.cc +++ b/winsup/cygwin/fhandler_dev.cc @@ -16,7 +16,6 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "devices.h" -#include "tls_pbuf.h" #define _COMPILING_NEWLIB #include @@ -54,16 +53,9 @@ fhandler_dev::open (int flags, mode_t mode) int ret = fhandler_disk_file::open (flags & ~O_CREAT, mode); if (!ret) { + /* Open a fake handle to \\Device\\Null */ + ret = open_null (flags); dir_exists = false; - /* Open a fake handle to \\Device\\Null, but revert to the old path - string afterwards, otherwise readdir will return with an EFAULT - when trying to fetch the inode number of ".." */ - tmp_pathbuf tp; - char *orig_path = tp.c_get (); - stpcpy (orig_path, get_win32_name ()); - pc.set_path (dev ().native); - ret = fhandler_base::open (flags, mode); - pc.set_path (orig_path); } return ret; } diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 9ee487dc1..ebdc806e2 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -2384,16 +2384,8 @@ fhandler_cygdrive::open (int flags, mode_t mode) set_errno (EISDIR); return 0; } - /* Open a fake handle to \\Device\\Null, but revert to the old path - string afterwards, otherwise readdir will return with an EFAULT - when trying to fetch the inode number of ".." */ - tmp_pathbuf tp; - char *orig_path = tp.c_get (); - stpcpy (orig_path, get_win32_name ()); - pc.set_path (dev ().native); - int ret = fhandler_base::open (flags, mode); - pc.set_path (orig_path); - return ret; + /* Open a fake handle to \\Device\\Null */ + return open_null (flags); } void diff --git a/winsup/cygwin/fhandler_netdrive.cc b/winsup/cygwin/fhandler_netdrive.cc index af9abcada..909e02354 100644 --- a/winsup/cygwin/fhandler_netdrive.cc +++ b/winsup/cygwin/fhandler_netdrive.cc @@ -295,30 +295,23 @@ fhandler_netdrive::closedir (DIR *dir) int fhandler_netdrive::open (int flags, mode_t mode) { - int res = fhandler_virtual::open (flags, mode); - if (!res) - goto out; - - nohandle (true); - if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { set_errno (EEXIST); - res = 0; - goto out; + return 0; } - else if (flags & O_WRONLY) + if (flags & O_WRONLY) { set_errno (EISDIR); - res = 0; - goto out; + return 0; } - - res = 1; - set_flags ((flags & ~O_TEXT) | O_BINARY | O_DIROPEN); - set_open_status (); -out: - syscall_printf ("%d = fhandler_netdrive::open(%y, 0%o)", res, flags, mode); - return res; + /* Open a fake handle to \\Device\\Null */ + return open_null (flags); } +int +fhandler_netdrive::close () +{ + /* Skip fhandler_virtual::close, which is a no-op. */ + return fhandler_base::close (); +} diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc index 10370550a..d4b6706c7 100644 --- a/winsup/cygwin/fhandler_registry.cc +++ b/winsup/cygwin/fhandler_registry.cc @@ -87,7 +87,7 @@ fetch_hkey (int idx) /* idx *must* be valid */ if (registry_keys[idx] == HKEY_CLASSES_ROOT) { if (RegOpenUserClassesRoot (cygheap->user.issetuid () - ? cygheap->user.imp_token () : hProcImpToken, + ? cygheap->user.imp_token () : hProcToken, 0, KEY_READ, &key) == ERROR_SUCCESS) return key; } @@ -96,6 +96,17 @@ fetch_hkey (int idx) /* idx *must* be valid */ if (RegOpenCurrentUser (KEY_READ, &key) == ERROR_SUCCESS) return key; } + else if (registry_keys[idx] == HKEY_CURRENT_CONFIG) + { + if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Hardware Profiles\\Current", + 0, KEY_READ, &key) == ERROR_SUCCESS) + return key; + } + /* Unfortunately there's no way to generate a valid OS registry key for + the other root keys. HKEY_USERS and HKEY_LOCAL_MACHINE are file + handles internally, HKEY_PERFORMANCE_DATA is just a bad hack and + no registry key at all. */ return registry_keys[idx]; } @@ -820,7 +831,8 @@ fhandler_registry::open (int flags, mode_t mode) set_io_handle (fetch_hkey (i)); /* Marking as nohandle allows to call dup on pseudo registry handles. */ - nohandle (true); + if (get_handle () >= HKEY_CLASSES_ROOT) + nohandle (true); flags |= O_DIROPEN; goto success; } diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc index 07b8e4b0b..2d56d7413 100644 --- a/winsup/cygwin/fhandler_virtual.cc +++ b/winsup/cygwin/fhandler_virtual.cc @@ -1,7 +1,7 @@ /* fhandler_virtual.cc: base fhandler class for virtual filesystems - Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Red Hat, Inc. + Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, + 2013 Red Hat, Inc. This file is part of Cygwin. @@ -84,10 +84,9 @@ fhandler_virtual::opendir (int fd) else { cygheap_fdnew cfd; - if (cfd >= 0) + if (cfd >= 0 && open (O_RDONLY, 0)) { cfd = this; - cfd->nohandle (true); dir->__d_fd = cfd; dir->__fh = this; res = dir; @@ -273,6 +272,7 @@ fhandler_virtual::fstatvfs (struct statvfs *sfs) set to something useful. Just as on Linux. */ memset (sfs, 0, sizeof (*sfs)); sfs->f_bsize = sfs->f_frsize = 4096; + sfs->f_flag = ST_RDONLY; sfs->f_namemax = NAME_MAX; return 0; } diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index fa32749ba..531703a7a 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -146,6 +146,7 @@ extern "C" { extern UNICODE_STRING _RDATA ro_u_volume = _ROU (L"\\??\\Volume{"); extern UNICODE_STRING _RDATA ro_u_pipedir = _ROU (L"\\\\?\\PIPE\\"); extern UNICODE_STRING _RDATA ro_u_globalroot = _ROU (L"\\\\.\\GLOBALROOT"); + extern UNICODE_STRING _RDATA ro_u_null = _ROU (L"\\Device\\Null"); #undef _ROU /* Cygwin properties are meant to be readonly data placed in the DLL, but diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 5c329e33f..d6c386075 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -380,7 +380,6 @@ class path_conv cfree (modifiable_path ()); char *new_path = (char *) cmalloc_abort (HEAP_STR, strlen (p) + 7); strcpy (new_path, p); - cfree_and_null (wide_path); return path = new_path; } bool is_binary ();