(Interim checkin while we work on this)
* devices.cc: Regenerate. * devices.h (device::noexpose): New field. (device::dev_on_fs): Make a bit field. (get_major): Use proper type for declaration. (expose): New field. (ext_dev_storage): Delete declaration. (dev_storage_size): Ditto. (dev_storage): New declaration. (dev_storage_end): Ditto. * devices.in: Mark /dev/ptym*, /dev/com*, /dev/pipe, /dev/fifo, and "/dev" as "no expose". * fhandler.h (fhandler_dev::lastrealpos): Delete declaration. (fhandler_dev::devidx): Declare new field. * fhandler_disk_file.cc: Move fhandler_dev functions into fhandler_dev.cc. * fhandler_dev.cc: Add includes needed for functions moved from fhandler_disk_file.cc. (dev_storage_scan_start): Define place to start listing devices. (dev_storage_size): Define size of array to scan. (fhandler_dev::fhandler_dev): Move here from fhandler_disk_file.cc. (fhandler_dev::opendir): Ditto. (fhandler_dev::readdir): Just check devidx for non-NULL to determine when to go to disk for /dev content. Use dev_storage rather than ext_dev_storage. Iterate over dev_storage using devidx pointer. Use accessor functions rather than raw references to the device struct. Only increment dir->__d_position when we are actually going to be returning something. Add debug_printf for exit. (fhandler_dev::rewinddir): Set devidx as appropriate depending on whether there's a /dev on disk or not. * gendevices: Don't mark dev_storage static but do put it in the _RDATA section. * path.cc (path_conv::check): Use new "device::expose()" function to decide to forbid programs from referencing internal device types.
This commit is contained in:
@@ -14,12 +14,16 @@ details. */
|
||||
#include "fhandler.h"
|
||||
#include "shared_info.h"
|
||||
#include "ntdll.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "devices.h"
|
||||
|
||||
#define _COMPILING_NEWLIB
|
||||
#include <dirent.h>
|
||||
|
||||
#define dev_prefix_len (sizeof ("/dev"))
|
||||
#define dev_storage_scan_start (dev_storage + 1)
|
||||
#define dev_storage_size (dev_storage_end - dev_storage_scan_start)
|
||||
|
||||
static int
|
||||
device_cmp (const void *a, const void *b)
|
||||
@@ -28,13 +32,73 @@ device_cmp (const void *a, const void *b)
|
||||
((const device *) b)->name + dev_prefix_len);
|
||||
}
|
||||
|
||||
fhandler_dev::fhandler_dev () :
|
||||
fhandler_disk_file (), devidx (NULL), dir_exists (true)
|
||||
{
|
||||
}
|
||||
|
||||
DIR *
|
||||
fhandler_dev::opendir (int fd)
|
||||
{
|
||||
DIR *dir;
|
||||
DIR *res = NULL;
|
||||
|
||||
dir = fhandler_disk_file::opendir (fd);
|
||||
if (dir)
|
||||
return dir;
|
||||
if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL)
|
||||
set_errno (ENOMEM);
|
||||
else if ((dir->__d_dirent =
|
||||
(struct dirent *) malloc (sizeof (struct dirent))) == NULL)
|
||||
{
|
||||
set_errno (ENOMEM);
|
||||
goto free_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
cygheap_fdnew cfd;
|
||||
if (cfd < 0 && fd < 0)
|
||||
goto free_dirent;
|
||||
|
||||
dir->__d_dirname = NULL;
|
||||
dir->__d_dirent->__d_version = __DIRENT_VERSION;
|
||||
dir->__d_cookie = __DIRENT_COOKIE;
|
||||
dir->__handle = INVALID_HANDLE_VALUE;
|
||||
dir->__d_position = 0;
|
||||
dir->__flags = 0;
|
||||
dir->__d_internal = 0;
|
||||
|
||||
if (fd >= 0)
|
||||
dir->__d_fd = fd;
|
||||
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;
|
||||
}
|
||||
|
||||
syscall_printf ("%p = opendir (%s)", res, get_name ());
|
||||
return res;
|
||||
|
||||
free_dirent:
|
||||
free (dir->__d_dirent);
|
||||
free_dir:
|
||||
free (dir);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev::readdir (DIR *dir, dirent *de)
|
||||
{
|
||||
int ret;
|
||||
device dev;
|
||||
|
||||
if (dir_exists && !lastrealpos)
|
||||
if (!devidx)
|
||||
{
|
||||
while ((ret = fhandler_disk_file::readdir (dir, de)) == 0)
|
||||
{
|
||||
@@ -42,153 +106,139 @@ fhandler_dev::readdir (DIR *dir, dirent *de)
|
||||
/dev already, for instance by using the old script from Igor
|
||||
Peshansky. */
|
||||
dev.name = de->d_name;
|
||||
if (!bsearch (&dev, ext_dev_storage, dev_storage_size, sizeof dev,
|
||||
device_cmp))
|
||||
if (!bsearch (&dev, dev_storage_scan_start, dev_storage_size, sizeof dev,
|
||||
device_cmp))
|
||||
break;
|
||||
}
|
||||
if (ret == ENMFILE)
|
||||
lastrealpos = dir->__d_position;
|
||||
devidx = dev_storage_scan_start;
|
||||
else
|
||||
goto out;
|
||||
}
|
||||
if (!dir_exists || lastrealpos)
|
||||
{
|
||||
ret = ENMFILE;
|
||||
for (size_t idx = dir->__d_position - lastrealpos + 1;
|
||||
idx < dev_storage_size;
|
||||
++idx)
|
||||
{
|
||||
++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 DEV_VIRTFS_MAJOR:
|
||||
/* Drop /dev/fifo and /dev/pipe since they are internal only. */
|
||||
switch (ext_dev_storage[idx].d.devn)
|
||||
{
|
||||
case FH_FIFO:
|
||||
case FH_PIPE:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case DEV_PTYM_MAJOR:
|
||||
/* Only /dev/ptmx is user-visible. */
|
||||
if (strcmp (ext_dev_storage[idx].name + dev_prefix_len, "ptmx"))
|
||||
continue;
|
||||
break;
|
||||
case DEV_PTYS_MAJOR:
|
||||
/* Show only existing slave ptys. */
|
||||
if (cygwin_shared->tty.connect (ext_dev_storage[idx].d.minor)
|
||||
== -1)
|
||||
continue;
|
||||
break;
|
||||
case DEV_CONS_MAJOR:
|
||||
/* Show only the one console which is our controlling tty
|
||||
right now. */
|
||||
if (!iscons_dev (myself->ctty)
|
||||
|| myself->ctty != ext_dev_storage[idx].d.devn_int)
|
||||
continue;
|
||||
break;
|
||||
case DEV_TTY_MAJOR:
|
||||
/* Show con{in,out,sole} only if we're running in a console. */
|
||||
switch (ext_dev_storage[idx].d.devn)
|
||||
{
|
||||
case FH_CONIN:
|
||||
case FH_CONOUT:
|
||||
case FH_CONSOLE:
|
||||
if (!iscons_dev (myself->ctty))
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case DEV_SERIAL_MAJOR:
|
||||
/* Ignore comX devices, only print ttySx. */
|
||||
if (ext_dev_storage[idx].name[dev_prefix_len] == 'c')
|
||||
continue;
|
||||
/*FALLTHRU*/
|
||||
case DEV_FLOPPY_MAJOR:
|
||||
case DEV_TAPE_MAJOR:
|
||||
case DEV_CDROM_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:
|
||||
/* Check existence of POSIX devices backed by real NT devices. */
|
||||
{
|
||||
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);
|
||||
/* Except for the serial IO devices, the native paths are
|
||||
direct device paths, not symlinks, so every status code
|
||||
except for "NOT_FOUND" means the device exists. */
|
||||
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;
|
||||
}
|
||||
strcpy (de->d_name, ext_dev_storage[idx].name + dev_prefix_len);
|
||||
de->d_ino = hash_path_name (0, ext_dev_storage[idx].native);
|
||||
switch (ext_dev_storage[idx].d.major)
|
||||
/* Now start processing our internal dev table. */
|
||||
ret = ENMFILE;
|
||||
while (devidx < dev_storage_end)
|
||||
{
|
||||
const device& thisdev = *devidx++;
|
||||
if (!thisdev.expose ())
|
||||
continue;
|
||||
int devn = *const_cast<device *> (&thisdev);
|
||||
/* Exclude devices which are only available for internal purposes
|
||||
and devices which are not really existing at this time. */
|
||||
switch (thisdev.get_major ())
|
||||
{
|
||||
case DEV_PTYS_MAJOR:
|
||||
/* Show only existing slave ptys. */
|
||||
if (cygwin_shared->tty.connect (thisdev.get_minor ()) == -1)
|
||||
continue;
|
||||
break;
|
||||
case DEV_CONS_MAJOR:
|
||||
/* Show only the one console which is our controlling tty
|
||||
right now. */
|
||||
if (!iscons_dev (myself->ctty)
|
||||
|| myself->ctty != devn)
|
||||
continue;
|
||||
break;
|
||||
case DEV_TTY_MAJOR:
|
||||
/* Show con{in,out,sole} only if we're running in a console. */
|
||||
switch (devn)
|
||||
{
|
||||
case DEV_FLOPPY_MAJOR:
|
||||
case DEV_TAPE_MAJOR:
|
||||
case DEV_CDROM_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:
|
||||
de->d_type = DT_BLK;
|
||||
break;
|
||||
case DEV_TTY_MAJOR:
|
||||
switch (ext_dev_storage[idx].d.devn)
|
||||
{
|
||||
case FH_CONIN:
|
||||
case FH_CONOUT:
|
||||
case FH_CONSOLE:
|
||||
dev.parse (myself->ctty);
|
||||
de->d_ino = hash_path_name (0, dev.native);
|
||||
break;
|
||||
}
|
||||
/*FALLTHRU*/
|
||||
default:
|
||||
de->d_type = DT_CHR;
|
||||
case FH_CONIN:
|
||||
case FH_CONOUT:
|
||||
case FH_CONSOLE:
|
||||
if (!iscons_dev (myself->ctty))
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case DEV_SERIAL_MAJOR:
|
||||
case DEV_FLOPPY_MAJOR:
|
||||
case DEV_TAPE_MAJOR:
|
||||
case DEV_CDROM_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:
|
||||
/* Check existence of POSIX devices backed by real NT devices. */
|
||||
{
|
||||
WCHAR wpath[MAX_PATH];
|
||||
UNICODE_STRING upath;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
HANDLE h;
|
||||
NTSTATUS status;
|
||||
|
||||
sys_mbstowcs (wpath, MAX_PATH, thisdev.native);
|
||||
RtlInitUnicodeString (&upath, wpath);
|
||||
InitializeObjectAttributes (&attr, &upath,
|
||||
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
/* Except for the serial IO devices, the native paths are
|
||||
direct device paths, not symlinks, so every status code
|
||||
except for "NOT_FOUND" means the device exists. */
|
||||
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;
|
||||
}
|
||||
++dir->__d_position;
|
||||
strcpy (de->d_name, thisdev.name + dev_prefix_len);
|
||||
de->d_ino = hash_path_name (0, thisdev.native);
|
||||
switch (thisdev.get_major ())
|
||||
{
|
||||
case DEV_FLOPPY_MAJOR:
|
||||
case DEV_TAPE_MAJOR:
|
||||
case DEV_CDROM_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:
|
||||
de->d_type = DT_BLK;
|
||||
break;
|
||||
case DEV_TTY_MAJOR:
|
||||
switch (devn)
|
||||
{
|
||||
case FH_CONIN:
|
||||
case FH_CONOUT:
|
||||
case FH_CONSOLE:
|
||||
dev.parse (myself->ctty);
|
||||
de->d_ino = hash_path_name (0, dev.native);
|
||||
break;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
/*FALLTHRU*/
|
||||
default:
|
||||
de->d_type = DT_CHR;
|
||||
break;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
debug_printf ("returning %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_dev::rewinddir (DIR *dir)
|
||||
{
|
||||
lastrealpos = 0;
|
||||
devidx = dir_exists ? NULL : dev_storage_scan_start;
|
||||
fhandler_disk_file::rewinddir (dir);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user