From 9ca7bca3c381d4affa78b450bd7284da9a68ec9b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 29 Mar 2012 18:02:54 +0000 Subject: * Makefile.in (DLL_OFILES): Add fhandler_dev.o. * devices.h (DEV_DEV_MAJOR): Define. (FH_DEV): Redefine in terms of DEV_DEV_MAJOR. (ext_dev_storage): Declare. (dev_storage_size): Declare. (dev_dev_storage): Declare. (dev_dev): Define. (isdev_dev): Define. * devices.in (dev_dev_storage): Activate. (ext_dev_storage): Define as externally available pointer to dev_storage. (dev_storage_size): Define to contain number of dev_storage elements. * dir.cc (rmdir): Handle /dev as always not empty. * dtable.cc (fh_alloc): Handle DEV_DEV_MAJOR. * fhandler.h (fhandler_dev): New class, derived from fhandler_disk_file. (fhandler_union): Add fhandler_dev member. * fhandler_disk_file.cc (class __DIR_mounts): Handle /dev directory to make sure it always exists. * fhandler_dev.cc: New file implementing /dev. * globals.cc (ro_u_dev): New R/O unicode string. * path.cc (path_conv::check): Handle FH_DEV device. --- winsup/cygwin/fhandler_dev.cc | 145 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 winsup/cygwin/fhandler_dev.cc (limited to 'winsup/cygwin/fhandler_dev.cc') diff --git a/winsup/cygwin/fhandler_dev.cc b/winsup/cygwin/fhandler_dev.cc new file mode 100644 index 000000000..ad39961e5 --- /dev/null +++ b/winsup/cygwin/fhandler_dev.cc @@ -0,0 +1,145 @@ +/* fhandler_dev.cc, Implement /dev. + + Copyright 2012 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include +#include "path.h" +#include "fhandler.h" +#include "shared_info.h" +#include "ntdll.h" +#include "devices.h" + +#define _COMPILING_NEWLIB +#include + +#define dev_prefix_len (sizeof ("/dev")) + +static int +device_cmp (const void *a, const void *b) +{ + return strcmp (((const device *) a)->name, + ((const device *) b)->name + dev_prefix_len); +} + +int +fhandler_dev::readdir (DIR *dir, dirent *de) +{ + int ret; + + if (dir_exists && !lastrealpos) + { + while ((ret = fhandler_disk_file::readdir (dir, de)) == 0) + { + /* Avoid to print devices for which users have created files under + /dev already, for instance by using the old script from Igor + Peshansky. */ + device dev; + dev.name = de->d_name; + if (!bsearch (&dev, ext_dev_storage, dev_storage_size, sizeof dev, + device_cmp)) + break; + } + if (ret == ENMFILE) + lastrealpos = dir->__d_position; + } + if (!dir_exists || lastrealpos) + { + ret = ENMFILE; + for (size_t idx = dir->__d_position - lastrealpos + 1; + idx < dev_storage_size; + ++idx) + { + struct __stat64 st; + + ++dir->__d_position; + /* Exclude devices which are only available for internal purposes + and devices which are not really existing at this time. */ + switch (ext_dev_storage[idx].d.major) + { + case 0: + if (ext_dev_storage[idx].d.minor == FH_FIFO + || ext_dev_storage[idx].d.minor == FH_PIPE) + continue; + case DEV_PTYM_MAJOR: + if (ext_dev_storage[idx].d.minor + || !strcmp (ext_dev_storage[idx].name, "/dev/ptm0")) + continue; + break; + case DEV_PTYS_MAJOR: + if (cygwin_shared->tty.connect (ext_dev_storage[idx].d.minor) + == -1) + continue; + break; + case DEV_CONS_MAJOR: + if (!iscons_dev (myself->ctty) + || myself->ctty != ext_dev_storage[idx].d.devn_int) + continue; + break; + case DEV_FLOPPY_MAJOR: + case DEV_TAPE_MAJOR: + case DEV_CDROM_MAJOR: + case DEV_SERIAL_MAJOR: + case DEV_SD_MAJOR: + case DEV_SD1_MAJOR: + case DEV_SD2_MAJOR: + case DEV_SD3_MAJOR: + case DEV_SD4_MAJOR: + case DEV_SD5_MAJOR: + case DEV_SD6_MAJOR: + case DEV_SD7_MAJOR: + { + WCHAR wpath[MAX_PATH]; + UNICODE_STRING upath; + OBJECT_ATTRIBUTES attr; + HANDLE h; + NTSTATUS status; + + sys_mbstowcs (wpath, MAX_PATH, ext_dev_storage[idx].native); + RtlInitUnicodeString (&upath, wpath); + InitializeObjectAttributes (&attr, &upath, + OBJ_CASE_INSENSITIVE, NULL, NULL); + /* The native paths are devices, not symlinks, so we expect + a matching error message. */ + status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY, + &attr); + switch (status) + { + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_OBJECT_PATH_NOT_FOUND: + continue; + case STATUS_SUCCESS: + NtClose (h); + break; + default: + break; + } + } + break; + } + if (!lstat64 (ext_dev_storage[idx].name, &st)) + { + strcpy (de->d_name, ext_dev_storage[idx].name + dev_prefix_len); + de->d_ino = st.st_ino; + de->d_type = S_ISBLK (st.st_mode) ? DT_BLK : DT_CHR; + ret = 0; + break; + } + } + } + return ret; +} + +void +fhandler_dev::rewinddir (DIR *dir) +{ + lastrealpos = 0; + fhandler_disk_file::rewinddir (dir); +} + -- cgit v1.2.3