diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2012-03-29 18:02:54 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2012-03-29 18:02:54 +0000 |
commit | 9ca7bca3c381d4affa78b450bd7284da9a68ec9b (patch) | |
tree | b411492e1997760f201f1bac335296211e5ddec3 /winsup/cygwin/fhandler_dev.cc | |
parent | d46ed263afc680ce6a7f84114a3014b84e447987 (diff) | |
download | cygnal-9ca7bca3c381d4affa78b450bd7284da9a68ec9b.tar.gz cygnal-9ca7bca3c381d4affa78b450bd7284da9a68ec9b.tar.bz2 cygnal-9ca7bca3c381d4affa78b450bd7284da9a68ec9b.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/fhandler_dev.cc')
-rw-r--r-- | winsup/cygwin/fhandler_dev.cc | 145 |
1 files changed, 145 insertions, 0 deletions
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 <stdlib.h> +#include "path.h" +#include "fhandler.h" +#include "shared_info.h" +#include "ntdll.h" +#include "devices.h" + +#define _COMPILING_NEWLIB +#include <dirent.h> + +#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); +} + |