diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7d4a6d30b..7ea534b23 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,47 @@ +2013-10-30 Corinna Vinschen + + * devices.in (dev_cygdrive_storage): Map to \Device\Null. + (dev_storage): Map /dev and /dev/windows to \Device\Null. + * devices.cc: Regenerate. + * dir.cc (opendir): Create unique id. Explain why. + * fhandler.h (fhandler_dev::get_dev): Implement inline. + (fhandler_cygdrive::close): Drop declaration. + (fhandler_cygdrive::get_dev): Implement inline. + (fhandler_windows::get_hwnd): Ditto. + (fhandler_windows::set_close_on_exec): Drop declaration. + (fhandler_windows::fixup_after_fork): Ditto. + * fhandler_dev.cc (fhandler_dev::open): Call fhandler_disk_file::open + without O_CREAT flag. Explain why. Create \Device\Null handle if + /dev/ doesn't actually exist. + (fhandler_dev::close): Drop nohandle case. + (fhandler_dev::fstatvfs): Drop nohandle check. Test for fs_got_fs + instead. Set ST_RDONLY fs flag for simulated /dev. + (fhandler_dev::opendir): If /dev doesn't exist, call open() to create + fake \Device\Null handle. Don't set nohandle. Set dir_exists + correctly. + (fhandler_dev::rewinddir): Call fhandler_disk_file::rewinddir only if + /dev is a real directory. + * fhandler_disk_file.cc (fhandler_disk_file::opendir): If called for + the cygdrive dir, call open() to create fake \Device\Null handle. + Only attach __DIR_mounts buffer to dir if not called for cygdrive dir. + Don't set nohandle. + (fhandler_cygdrive::open): Create \Device\Null handle. + (fhandler_cygdrive::close): Remove. + (fhandler_cygdrive::fstatvfs): Set ST_RDONLY fs flag. + * fhandler_windows.cc (fhandler_windows::open): Create \Device\Null + handle. + (fhandler_windows::read): Don't add io_handle to WFMO handle array. + Change subsequent test for return value accordingly. Fix test for + "message arrived". + (fhandler_windows::set_close_on_exec): Remove. + (fhandler_windows::fixup_after_fork): Remove. + * path.h (path_conv::set_path): Make sure wide_path is NULL when + setting a new path. + * select.cc (peek_windows): Use correct hWnd value, not io_handle. + (fhandler_windows::select_read): Don't use io_handle as wait object. + (fhandler_windows::select_write): Ditto. + (fhandler_windows::select_except): Ditto. + 2013-10-27 Corinna Vinschen * exception.h: Fold in content of include/exceptions.h. diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index 539dba3d8..cd49d4959 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}, "/cygdrive", exists}; + {"/cygdrive", {FH_CYGDRIVE}, "\\Device\\Null", 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), "/dev", exists, S_IFDIR, false}, + {"/dev", BRACK(FH_DEV), "\\Device\\Null", 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}, @@ -2714,7 +2714,7 @@ const _RDATA device dev_storage[] = {"/dev/ttyS62", BRACK(FHDEV(DEV_SERIAL_MAJOR, 62)), "\\??\\COM63", exists_ntdev, S_IFCHR, true}, {"/dev/ttyS63", BRACK(FHDEV(DEV_SERIAL_MAJOR, 63)), "\\??\\COM64", exists_ntdev, S_IFCHR, true}, {"/dev/urandom", BRACK(FH_URANDOM), "\\Device\\Null", exists_ntdev, S_IFCHR, true}, - {"/dev/windows", BRACK(FH_WINDOWS), "/dev/windows", exists, S_IFCHR, true}, + {"/dev/windows", BRACK(FH_WINDOWS), "\\Device\\Null", exists_ntdev, S_IFCHR, true}, {"/dev/zero", BRACK(FH_ZERO), "\\Device\\Null", exists_ntdev, S_IFCHR, true}, {":fifo", BRACK(FH_FIFO), "/dev/fifo", exists_internal, S_IFCHR, false}, {":pipe", BRACK(FH_PIPE), "/dev/pipe", exists_internal, S_IFCHR, false}, diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index bba5fdd7c..520191eb7 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}, "/cygdrive", exists}; + {"/cygdrive", {FH_CYGDRIVE}, "\\Device\\Null", exists}; const device dev_fs_storage = {"", {FH_FS}, "", exists}; @@ -140,14 +140,14 @@ const device dev_error_storage = /* Internal devices below are prefixed with a ":". This moves them out of the POSIX namespace. */ %% -"/dev", BRACK(FH_DEV), "/dev", exists, S_IFDIR +"/dev", BRACK(FH_DEV), "\\Device\\Null", 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 "/dev/cons%(0-63)d", BRACK(FHDEV(DEV_CONS_MAJOR, {$1})), "/dev/cons{$1}", exists_console, S_IFCHR, =cons_dev "/dev/console", BRACK(FH_CONSOLE), "/dev/console", exists_console, S_IFCHR, =console_dev "/dev/ptmx", BRACK(FH_PTMX), "/dev/ptmx", exists, S_IFCHR -"/dev/windows", BRACK(FH_WINDOWS), "/dev/windows", exists, S_IFCHR +"/dev/windows", BRACK(FH_WINDOWS), "\\Device\\Null", exists_ntdev, S_IFCHR "/dev/dsp", BRACK(FH_OSS_DSP), "\\Device\\Null", exists_ntdev, S_IFCHR "/dev/conin", BRACK(FH_CONIN), "/dev/conin", exists_console, S_IFCHR "/dev/conout", BRACK(FH_CONOUT), "/dev/conout", exists_console, S_IFCHR diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 478a41862..fe0babc99 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -1,7 +1,7 @@ /* dir.cc: Posix directory-related routines Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. + 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. This file is part of Cygwin. @@ -68,6 +68,9 @@ opendir (const char *name) if (!res && fh) delete fh; + /* Applications calling flock(2) on dirfd(fd) need this... */ + if (!fh->nohandle ()) + fh->set_unique_id (); return res; } diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index b8b984eb4..d2f9758d8 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1045,6 +1045,8 @@ public: void rewinddir (DIR *); fhandler_dev (void *) {} + dev_t get_dev () { return dir_exists ? pc.fs_serial_number () + : get_device (); } void copyto (fhandler_base *x) { @@ -1075,7 +1077,6 @@ class fhandler_cygdrive: public fhandler_disk_file public: fhandler_cygdrive (); int open (int flags, mode_t mode); - int close (); DIR __reg2 *opendir (int fd); int __reg3 readdir (DIR *, dirent *); void rewinddir (DIR *); @@ -1084,6 +1085,7 @@ class fhandler_cygdrive: public fhandler_disk_file int __reg2 fstatvfs (struct statvfs *buf); fhandler_cygdrive (void *) {} + dev_t get_dev () { return get_device (); } void copyto (fhandler_base *x) { @@ -1726,6 +1728,7 @@ class fhandler_windows: public fhandler_base public: fhandler_windows (); int is_windows () { return 1; } + HWND get_hwnd () { return hWnd_; } int open (int flags, mode_t mode = 0); ssize_t __stdcall write (const void *ptr, size_t len); void __reg3 read (void *ptr, size_t& len); @@ -1733,8 +1736,6 @@ class fhandler_windows: public fhandler_base off_t lseek (off_t, int) { return 0; } int close () { return 0; } - void set_close_on_exec (bool val); - void fixup_after_fork (HANDLE parent); select_record *select_read (select_stuff *); select_record *select_write (select_stuff *); select_record *select_except (select_stuff *); diff --git a/winsup/cygwin/fhandler_dev.cc b/winsup/cygwin/fhandler_dev.cc index 48ac0b70f..668d0b480 100644 --- a/winsup/cygwin/fhandler_dev.cc +++ b/winsup/cygwin/fhandler_dev.cc @@ -16,6 +16,7 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "devices.h" +#include "tls_pbuf.h" #define _COMPILING_NEWLIB #include @@ -49,21 +50,27 @@ fhandler_dev::open (int flags, mode_t mode) set_errno (EISDIR); return 0; } - int ret = fhandler_disk_file::open (flags, mode); + /* Filter O_CREAT flag to avoid creating a file called /dev accidentally. */ + int ret = fhandler_disk_file::open (flags & ~O_CREAT, mode); if (!ret) { - flags |= O_DIROPEN; - set_flags (flags); - nohandle (true); + 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 1; + return ret; } int fhandler_dev::close () { - if (nohandle ()) - return 0; return fhandler_disk_file::close (); } @@ -87,25 +94,24 @@ fhandler_dev::fstatvfs (struct statvfs *sfs) int ret = -1, opened = 0; HANDLE fh = get_handle (); - if (!fh && !nohandle ()) + if (!fh) { if (!open (O_RDONLY, 0)) return -1; opened = 1; } - if (!nohandle ()) + if (pc.fs_got_fs ()) + ret = fhandler_disk_file::fstatvfs (sfs); + else { - ret = fhandler_disk_file::fstatvfs (sfs); - goto out; + /* Virtual file system. Just return an empty buffer with a few values + set to something useful similar to Linux. */ + memset (sfs, 0, sizeof (*sfs)); + sfs->f_bsize = sfs->f_frsize = 4096; + sfs->f_flag = ST_RDONLY; + sfs->f_namemax = NAME_MAX; + ret = 0; } - /* Virtual file system. Just return an empty buffer with a few values - set to something useful. Just as on Linux. */ - memset (sfs, 0, sizeof (*sfs)); - sfs->f_bsize = sfs->f_frsize = 4096; - sfs->f_namemax = NAME_MAX; - ret = 0; - -out: if (opened) close (); return ret; @@ -114,13 +120,10 @@ out: DIR * fhandler_dev::opendir (int fd) { - DIR *dir; - DIR *res = NULL; - - dir = fhandler_disk_file::opendir (fd); + DIR *dir = fhandler_disk_file::opendir (fd); if (dir) - return dir; - if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL) + dir_exists = true; + else if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL) set_errno (ENOMEM); else if ((dir->__d_dirent = (struct dirent *) malloc (sizeof (struct dirent))) == NULL) @@ -144,26 +147,28 @@ fhandler_dev::opendir (int fd) if (fd >= 0) dir->__d_fd = fd; + else if (!open (O_RDONLY, 0)) + goto free_dirent; else { cfd = this; dir->__d_fd = cfd; - cfd->nohandle (true); } set_close_on_exec (true); dir->__fh = this; - devidx = dev_storage_scan_start; - res = dir; + dir_exists = false; } - syscall_printf ("%p = opendir (%s)", res, get_name ()); - return res; + devidx = dir_exists ? NULL : dev_storage_scan_start; + + syscall_printf ("%p = opendir (%s)", dir, get_name ()); + return dir; free_dirent: free (dir->__d_dirent); free_dir: free (dir); - return res; + return NULL; } int @@ -226,5 +231,7 @@ void fhandler_dev::rewinddir (DIR *dir) { devidx = dir_exists ? NULL : dev_storage_scan_start; - fhandler_disk_file::rewinddir (dir); + dir->__d_position = 0; + if (dir_exists) + fhandler_disk_file::rewinddir (dir); } diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 3b6f85b66..9ee487dc1 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -1833,11 +1833,17 @@ fhandler_disk_file::opendir (int fd) dir->__d_position = 0; dir->__flags = (get_name ()[0] == '/' && get_name ()[1] == '\0') ? dirent_isroot : 0; - dir->__d_internal = (uintptr_t) new __DIR_mounts (get_name ()); - d_cachepos (dir) = 0; + dir->__d_internal = 0; - if (!pc.iscygdrive ()) + if (pc.iscygdrive ()) { + if (fd < 0 && !open (O_RDONLY, 0)) + goto free_mounts; + } + else + { + dir->__d_internal = (uintptr_t) new __DIR_mounts (get_name ()); + d_cachepos (dir) = 0; if (fd < 0) { /* opendir() case. Initialize with given directory name and @@ -1918,8 +1924,6 @@ fhandler_disk_file::opendir (int fd) time on exit. Nasty, nasty... */ cfd = this; dir->__d_fd = cfd; - if (pc.iscygdrive ()) - cfd->nohandle (true); } set_close_on_exec (true); dir->__fh = this; @@ -2380,16 +2384,16 @@ fhandler_cygdrive::open (int flags, mode_t mode) set_errno (EISDIR); return 0; } - flags |= O_DIROPEN; - set_flags (flags); - nohandle (true); - return 1; -} - -int -fhandler_cygdrive::close () -{ - 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; } void @@ -2416,6 +2420,7 @@ fhandler_cygdrive::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/fhandler_windows.cc b/winsup/cygwin/fhandler_windows.cc index 12ab5265b..34388f76f 100644 --- a/winsup/cygwin/fhandler_windows.cc +++ b/winsup/cygwin/fhandler_windows.cc @@ -1,7 +1,7 @@ /* fhandler_windows.cc: code to access windows message queues. - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2011, 2012 - Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2011, 2012, + 2013 Red Hat, Inc. Written by Sergey S. Okhapkin (sos@prospect.com.ru). Feedback and testing by Andy Piper (andyp@parallax.co.uk). @@ -54,12 +54,9 @@ fhandler_windows::fhandler_windows () } int -fhandler_windows::open (int flags, mode_t) +fhandler_windows::open (int flags, mode_t mode) { - set_flags ((flags & ~O_TEXT) | O_BINARY); - close_on_exec (true); - set_open_status (); - return 1; + return fhandler_base::open ((flags & ~O_TEXT) | O_BINARY, mode); } ssize_t __stdcall @@ -96,10 +93,10 @@ fhandler_windows::read (void *buf, size_t& len) return; } - HANDLE w4[3] = { get_handle (), }; - set_signal_arrived here (w4[1]); - DWORD cnt = 2; - if ((w4[cnt] = pthread::get_cancel_event ()) != NULL) + HANDLE w4[2]; + set_signal_arrived here (w4[0]); + DWORD cnt = 1; + if ((w4[1] = pthread::get_cancel_event ()) != NULL) ++cnt; for (;;) { @@ -109,6 +106,19 @@ fhandler_windows::read (void *buf, size_t& len) MWMO_INPUTAVAILABLE)) { case WAIT_OBJECT_0: + if (_my_tls.call_signal_handler ()) + continue; + len = (size_t) -1; + set_errno (EINTR); + break; + case WAIT_OBJECT_0 + 1: + if (cnt > 1) /* WAIT_OBJECT_0 + 1 is the cancel event object. */ + { + pthread::static_cancel_self (); + break; + } + /*FALLTHRU*/ + case WAIT_OBJECT_0 + 2: if (!PeekMessageW (ptr, hWnd_, 0, 0, PM_REMOVE)) { len = (size_t) -1; @@ -119,15 +129,6 @@ fhandler_windows::read (void *buf, size_t& len) else len = sizeof (MSG); break; - case WAIT_OBJECT_0 + 1: - if (_my_tls.call_signal_handler ()) - continue; - len = (size_t) -1; - set_errno (EINTR); - break; - case WAIT_OBJECT_0 + 2: - pthread::static_cancel_self (); - break; case WAIT_TIMEOUT: len = (size_t) -1; set_errno (EAGAIN); @@ -163,25 +164,3 @@ fhandler_windows::ioctl (unsigned int cmd, void *val) } return 0; } - -void -fhandler_windows::set_close_on_exec (bool val) -{ - if (get_handle ()) - fhandler_base::set_close_on_exec (val); - else - fhandler_base::close_on_exec (val); - void *h = hWnd_; - if (h) - set_no_inheritance (h, val); -} - -void -fhandler_windows::fixup_after_fork (HANDLE parent) -{ - if (get_handle ()) - fhandler_base::fixup_after_fork (parent); - void *h = hWnd_; - if (h) - fork_fixup (parent, h, "hWnd_"); -} diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index d6c386075..5c329e33f 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -380,6 +380,7 @@ 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 (); diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index ab6517cbf..2534c0ee9 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1542,6 +1542,8 @@ peek_windows (select_record *me, bool) MSG m; HANDLE h; set_handle_or_return_if_not_open (h, me); + /* We need the hWnd value, not the io_handle. */ + h = ((fhandler_windows *) me->fh)->get_hwnd (); if (me->read_selected && me->read_ready) return 1; @@ -1576,7 +1578,6 @@ fhandler_windows::select_read (select_stuff *ss) s->peek = peek_windows; s->read_selected = true; s->read_ready = false; - s->h = get_handle (); s->windows_handle = true; return s; } @@ -1591,7 +1592,6 @@ fhandler_windows::select_write (select_stuff *ss) s->verify = verify_ok; } s->peek = peek_windows; - s->h = get_handle (); s->write_selected = true; s->write_ready = true; s->windows_handle = true; @@ -1608,7 +1608,6 @@ fhandler_windows::select_except (select_stuff *ss) s->verify = verify_ok; } s->peek = peek_windows; - s->h = get_handle (); s->except_selected = true; s->except_ready = false; s->windows_handle = true;