diff options
Diffstat (limited to 'winsup/cygwin/fhandler_dev.cc')
-rw-r--r-- | winsup/cygwin/fhandler_dev.cc | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/winsup/cygwin/fhandler_dev.cc b/winsup/cygwin/fhandler_dev.cc index c79d4c3ec..28b0e3cf0 100644 --- a/winsup/cygwin/fhandler_dev.cc +++ b/winsup/cygwin/fhandler_dev.cc @@ -25,8 +25,8 @@ details. */ static int device_cmp (const void *a, const void *b) { - return strcmp (((const device *) a)->name, - ((const device *) b)->name + dev_prefix_len); + return strcmp (((const device *) a)->name (), + ((const device *) b)->name () + dev_prefix_len); } fhandler_dev::fhandler_dev () : @@ -147,6 +147,7 @@ fhandler_dev::opendir (int fd) set_close_on_exec (true); dir->__fh = this; dir_exists = false; + drive = part = 0; } devidx = dir_exists ? NULL : dev_storage_scan_start; @@ -161,11 +162,13 @@ free_dir: return NULL; } +static const WCHAR *hd_pattern = L"\\Device\\Harddisk%u\\Partition%u"; + int fhandler_dev::readdir (DIR *dir, dirent *de) { int ret; - const device *curdev; + const _device *curdev; device dev; if (!devidx) @@ -175,7 +178,7 @@ fhandler_dev::readdir (DIR *dir, dirent *de) /* Avoid to print devices for which users have created files under /dev already, for instance by using the old script from Igor Peshansky. */ - dev.name = de->d_name; + dev.name (de->d_name); if (!bsearch (&dev, dev_storage_scan_start, dev_storage_size, sizeof dev, device_cmp)) break; @@ -192,25 +195,63 @@ fhandler_dev::readdir (DIR *dir, dirent *de) /* If exists returns < 0 it means that the device can be used by a program but its use is deprecated and, so, it is not returned by readdir((). */ - if (curdev->exists () <= 0) + device *cdev = (device *) curdev; + if (cdev->exists () <= 0) continue; ++dir->__d_position; - strcpy (de->d_name, curdev->name + dev_prefix_len); - if (curdev->get_major () == DEV_TTY_MAJOR - && (curdev->is_device (FH_CONIN) - || curdev->is_device (FH_CONOUT) - || curdev->is_device (FH_CONSOLE))) + strcpy (de->d_name, cdev->name () + dev_prefix_len); + if (cdev->get_major () == DEV_TTY_MAJOR + && (cdev->is_device (FH_CONIN) + || cdev->is_device (FH_CONOUT) + || cdev->is_device (FH_CONSOLE))) { /* Make sure conin, conout, and console have the same inode number as the current consX. */ de->d_ino = myself->ctty; } else - de->d_ino = curdev->get_device (); - de->d_type = curdev->type (); + de->d_ino = cdev->get_device (); + de->d_type = cdev->type (); ret = 0; break; } + /* Last but not least, scan for existing disks/partitions. */ + if (ret) + { + UNICODE_STRING upath; + WCHAR buf[(sizeof *hd_pattern + 32) / sizeof (wchar_t)]; + OBJECT_ATTRIBUTES attr; + FILE_BASIC_INFORMATION fbi; + NTSTATUS status; + + InitializeObjectAttributes (&attr, &upath, 0, NULL, NULL); + while (drive < 128) + { + while (part < 64) + { + USHORT len = __small_swprintf (buf, hd_pattern, drive, part); + RtlInitCountedUnicodeString (&upath, buf, len * sizeof (WCHAR)); + status = NtQueryAttributesFile (&attr, &fbi); + debug_printf ("%S %y", &upath, status); + if (status != STATUS_OBJECT_NAME_NOT_FOUND + && status != STATUS_OBJECT_PATH_NOT_FOUND) + { + device dev (drive, part); + strcpy (de->d_name, dev.name () + 5); + de->d_ino = dev.get_device (); + de->d_type = DT_BLK; + ++part; + ret = 0; + goto out; + } + if (part == 0) + break; + ++part; + } + part = 0; + ++drive; + } + } out: debug_printf ("returning %d", ret); |