25ce0e1213
Provide for 128 COM devices since Windows likes to create lots of these over time (one per identifiable device and USB port).
368 lines
9.7 KiB
Plaintext
368 lines
9.7 KiB
Plaintext
%import {
|
|
#include "winsup.h"
|
|
#include "devices.h"
|
|
#include "sys/cygwin.h"
|
|
#include "tty.h"
|
|
#include "pinfo.h"
|
|
#include "shared_info.h"
|
|
#include "path.h"
|
|
#include "fhandler.h"
|
|
#include "ntdll.h"
|
|
|
|
typedef const _device *KR_device_t;
|
|
}
|
|
%type KR_device_t
|
|
%local {
|
|
|
|
static int
|
|
exists_internal (const device&)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static int
|
|
exists (const device&)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/* Check existence of POSIX devices backed by real NT devices. */
|
|
static int
|
|
exists_ntdev (const device& dev)
|
|
{
|
|
WCHAR wpath[MAX_PATH];
|
|
UNICODE_STRING upath;
|
|
OBJECT_ATTRIBUTES attr;
|
|
HANDLE h;
|
|
NTSTATUS status;
|
|
|
|
sys_mbstowcs (wpath, MAX_PATH, dev.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:
|
|
return false;
|
|
case STATUS_SUCCESS:
|
|
NtClose (h);
|
|
default:
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* Don't list via readdir but allow as a direct reference. */
|
|
static int
|
|
exists_ntdev_silent (const device& dev)
|
|
{
|
|
return exists_ntdev (dev) ? -1 : false;
|
|
}
|
|
|
|
static int
|
|
exists_console (const device& dev)
|
|
{
|
|
fh_devices devn = *const_cast<device *> (&dev);
|
|
switch (devn)
|
|
{
|
|
case FH_CONSOLE:
|
|
case FH_CONIN:
|
|
case FH_CONOUT:
|
|
return fhandler_console::exists ();
|
|
default:
|
|
/* Only show my own console device (for now?) */
|
|
return iscons_dev (myself->ctty) && myself->ctty == devn;
|
|
}
|
|
}
|
|
|
|
static int
|
|
exists_pty (const device& dev)
|
|
{
|
|
/* Only existing slave ptys. */
|
|
return cygwin_shared->tty.connect (dev.get_minor ()) != -1;
|
|
}
|
|
|
|
const _device dev_cygdrive_storage =
|
|
{"/cygdrive", {FH_CYGDRIVE}, "", exists};
|
|
|
|
const _device dev_fs_storage =
|
|
{"", {FH_FS}, "", exists};
|
|
|
|
const _device dev_proc_storage =
|
|
{"", {FH_PROC}, "", exists};
|
|
|
|
const _device dev_procnet_storage =
|
|
{"", {FH_PROCNET}, "", exists};
|
|
|
|
const _device dev_procsys_storage =
|
|
{"", {FH_PROCSYS}, "", exists};
|
|
|
|
const _device dev_procsysvipc_storage =
|
|
{"", {FH_PROCSYSVIPC}, "", exists};
|
|
|
|
const _device dev_netdrive_storage =
|
|
{"", {FH_NETDRIVE}, "", exists};
|
|
|
|
const _device dev_registry_storage =
|
|
{"", {FH_REGISTRY}, "", exists_internal};
|
|
|
|
const _device dev_piper_storage =
|
|
{"", {FH_PIPER}, "", exists_internal};
|
|
|
|
const _device dev_pipew_storage =
|
|
{"", {FH_PIPEW}, "", exists_internal};
|
|
|
|
const _device dev_signalfd_storage =
|
|
{"", {FH_SIGNALFD}, "", exists_internal};
|
|
|
|
const _device dev_timerfd_storage =
|
|
{"", {FH_TIMERFD}, "", exists_internal};
|
|
|
|
const _device dev_socket_storage =
|
|
{"", {FH_SOCKET}, "", exists_internal};
|
|
|
|
const _device dev_af_inet_storage =
|
|
{"", {FH_INET}, "", exists_internal};
|
|
|
|
const _device dev_af_unix_storage =
|
|
{"", {FH_UNIX}, "", exists_internal};
|
|
|
|
const _device dev_af_local_storage =
|
|
{"", {FH_LOCAL}, "", exists_internal};
|
|
|
|
const _device dev_bad_storage =
|
|
{"", {FH_NADA}, "", exists_internal};
|
|
|
|
const _device dev_error_storage =
|
|
{"", {FH_ERROR}, "", exists_internal};
|
|
|
|
#define BRACK(x) {devn: x}
|
|
%storage_here
|
|
}
|
|
/* Internal devices below are prefixed with a ":". This moves them out of
|
|
the POSIX namespace. */
|
|
%%
|
|
"/dev", BRACK(FH_DEV), "", exists, S_IFDIR
|
|
"/dev/tty", BRACK(FH_TTY), "/dev/tty", exists, S_IFCHR
|
|
"/dev/pty%(0-127)d", BRACK(FHDEV(DEV_PTYS_MAJOR, {$1})), "/dev/pty{$1}", exists_pty, S_IFCHR, =ptys_dev
|
|
":ptym%(0-127)d", BRACK(FHDEV(DEV_PTYM_MAJOR, {$1})), "/dev/ptym{$1}", exists_internal, S_IFCHR, =ptym_dev
|
|
"/dev/cons%(0-127)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), "\\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
|
|
"/dev/null", BRACK(FH_NULL), "\\Device\\Null", exists_ntdev, S_IFCHR
|
|
"/dev/zero", BRACK(FH_ZERO), "\\Device\\Null", exists_ntdev, S_IFCHR
|
|
"/dev/full", BRACK(FH_FULL), "\\Device\\Null", exists_ntdev, S_IFCHR
|
|
"/dev/random", BRACK(FH_RANDOM), "\\Device\\Null", exists_ntdev, S_IFCHR
|
|
"/dev/urandom", BRACK(FH_URANDOM), "\\Device\\Null", exists_ntdev, S_IFCHR, =urandom_dev
|
|
"/dev/clipboard", BRACK(FH_CLIPBOARD), "\\Device\\Null", exists_ntdev, S_IFCHR
|
|
"/dev/com%(1-16)d", BRACK(FHDEV(DEV_SERIAL_MAJOR, {$1 - 1})), "\\??\\COM{$1}", exists_ntdev_silent, S_IFCHR
|
|
"/dev/ttyS%(0-127)d", BRACK(FHDEV(DEV_SERIAL_MAJOR, {$1})), "\\??\\COM{$1 + 1}", exists_ntdev, S_IFCHR
|
|
":pipe", BRACK(FH_PIPE), "/dev/pipe", exists_internal, S_IFCHR
|
|
":fifo", BRACK(FH_FIFO), "/dev/fifo", exists_internal, S_IFCHR
|
|
"/dev/st%(0-127)d", BRACK(FHDEV(DEV_TAPE_MAJOR, {$1})), "\\Device\\Tape{$1}", exists_ntdev, S_IFBLK
|
|
"/dev/nst%(0-127)d", BRACK(FHDEV(DEV_TAPE_MAJOR, {$1 + 128})), "\\Device\\Tape{$1}", exists_ntdev, S_IFBLK
|
|
"/dev/fd%(0-15)d", BRACK(FHDEV(DEV_FLOPPY_MAJOR, {$1})), "\\Device\\Floppy{$1}", exists_ntdev, S_IFBLK
|
|
"/dev/scd%(0-15)d", BRACK(FHDEV(DEV_CDROM_MAJOR, {$1})), "\\Device\\CdRom{$1}", exists_ntdev, S_IFBLK
|
|
"/dev/sr%(0-15)d", BRACK(FHDEV(DEV_CDROM_MAJOR, {$1})), "\\Device\\CdRom{$1}", exists_ntdev, S_IFBLK
|
|
%other {return NULL;}
|
|
%%
|
|
#undef BRACK
|
|
|
|
const _device *dev_storage_end = dev_storage
|
|
+ (sizeof dev_storage / sizeof dev_storage[0]);
|
|
|
|
/* Convert disk/partition to major/minor */
|
|
static void
|
|
conv_dp_to_mm (int drive, int part, _major_t &major, _minor_t &minor)
|
|
{
|
|
if (part >= 16)
|
|
{
|
|
major = DEV_SD_HIGHPART_START + drive / 5;
|
|
drive %= 5;
|
|
minor = (part - 16) + 48 * drive;
|
|
return;
|
|
}
|
|
if (drive < ('q' - 'a')) /* /dev/sda -to- /dev/sdp */
|
|
major = DEV_SD_MAJOR;
|
|
else if (drive < 32) /* /dev/sdq -to- /dev/sdaf */
|
|
{
|
|
major = DEV_SD1_MAJOR;
|
|
drive -= 'q' - 'a';
|
|
}
|
|
else if (drive < 48) /* /dev/sdag -to- /dev/sdav */
|
|
{
|
|
major = DEV_SD2_MAJOR;
|
|
drive -= 32;
|
|
}
|
|
else if (drive < 64) /* /dev/sdaw -to- /dev/sdbl */
|
|
{
|
|
major = DEV_SD3_MAJOR;
|
|
drive -= 48;
|
|
}
|
|
else if (drive < 80) /* /dev/sdbm -to- /dev/sdcb */
|
|
{
|
|
major = DEV_SD4_MAJOR;
|
|
drive -= 64;
|
|
}
|
|
else if (drive < 96) /* /dev/sdcc -to- /dev/sdcr */
|
|
{
|
|
major = DEV_SD5_MAJOR;
|
|
drive -= 80;
|
|
}
|
|
else if (drive < 112) /* /dev/sdcs -to- /dev/sddh */
|
|
{
|
|
major = DEV_SD6_MAJOR;
|
|
drive -= 96;
|
|
}
|
|
/* NOTE: This will cause multiple /dev/sddx entries in
|
|
/proc/partitions if there are more than 128 devices */
|
|
else /* /dev/sddi -to- /dev/sddx */
|
|
{
|
|
major = DEV_SD7_MAJOR;
|
|
drive -= 112;
|
|
}
|
|
minor = part + (drive * 16);
|
|
}
|
|
|
|
#define DISK_PREFIX "/dev/sd"
|
|
#define DP_LEN (sizeof (DISK_PREFIX) - 1)
|
|
|
|
static const char *hd_pattern = "\\Device\\Harddisk%u\\Partition%u";
|
|
|
|
void
|
|
device::parse (const char *s)
|
|
{
|
|
size_t len = strlen (s);
|
|
const _device *dev = KR_find_keyword (s, len);
|
|
|
|
if (!dev)
|
|
{
|
|
/* /dev/sd* devices have 8192 entries, given that we support 128 disks
|
|
with up to 64 partitions. Handling them with shilka raises the size
|
|
of devices.o from ~250K to ~2 Megs. So we handle them here manually
|
|
to save this space. */
|
|
int drive = 0, part = 0;
|
|
const char *pos = s + DP_LEN;
|
|
|
|
/* Generic check for /dev/sd[a-z] prefix */
|
|
if (len <= DP_LEN || strncmp (s, DISK_PREFIX, DP_LEN)
|
|
|| pos[0] < 'a' || pos[0] > 'z')
|
|
goto no_disk;
|
|
|
|
/* /dev/sdd[a-x]? */
|
|
if (pos[0] == 'd' && pos[1] >= 'a' && pos[1] <= 'x')
|
|
{
|
|
drive = 104 + (pos[1] - 'a');
|
|
++pos;
|
|
}
|
|
/* /dev/sd[a-c][a-z]? */
|
|
else if (pos[0] <= 'c' && pos[1] >= 'a' && pos[1] <= 'z')
|
|
{
|
|
drive = 26 + (pos[0] - 'a') * 26 + (pos[1] - 'a');
|
|
++pos;
|
|
}
|
|
else
|
|
drive = (pos[0] - 'a');
|
|
/* Check next position in string for partition number. */
|
|
++pos;
|
|
/* No partition number, equivalent to Windows partition 0. */
|
|
if (!pos[0])
|
|
;
|
|
/* First digit must not be 0. */
|
|
else if (pos[0] < '1' || pos[0] > '9')
|
|
goto no_disk;
|
|
else if (!pos[1])
|
|
part = (pos[0] - '0');
|
|
else if (pos[1] < '0' || pos[1] > '9' || pos[2] != '\0')
|
|
goto no_disk;
|
|
else
|
|
{
|
|
part = (pos[0] - '0') * 10 + (pos[1] - '0');
|
|
if (part > 63)
|
|
goto no_disk;
|
|
}
|
|
char buf[sizeof *hd_pattern + 32];
|
|
__small_sprintf (buf, hd_pattern, drive, part);
|
|
native (buf, false);
|
|
if (exists_ntdev (*this))
|
|
{
|
|
name (s, true);
|
|
conv_dp_to_mm (drive, part, d.major, d.minor);
|
|
native (buf, true);
|
|
exists_func = exists_ntdev;
|
|
_mode = S_IFBLK;
|
|
lives_in_dev = dev_on_fs = false;
|
|
return;
|
|
}
|
|
no_disk:
|
|
*this = *fs_dev;
|
|
}
|
|
else
|
|
*this = *dev;
|
|
}
|
|
|
|
void
|
|
device::init ()
|
|
{
|
|
/* nothing to do... yet */
|
|
}
|
|
|
|
void
|
|
device::parse (_major_t major, _minor_t minor)
|
|
{
|
|
dev_t devn = FHDEV (major, minor);
|
|
|
|
d.devn = 0;
|
|
|
|
for (const _device *devidx = dev_storage; devidx < dev_storage_end; devidx++)
|
|
if (devidx->d.devn == devn)
|
|
{
|
|
*this = *devidx;
|
|
break;
|
|
}
|
|
|
|
if (!*this)
|
|
d.devn = FHDEV (major, minor);
|
|
}
|
|
|
|
void
|
|
device::parse (dev_t dev)
|
|
{
|
|
parse (_major (dev), _minor (dev));
|
|
}
|
|
|
|
void
|
|
device::parsedisk (int drive, int part)
|
|
{
|
|
char buf[sizeof ("/dev/sddx63")], *bp;
|
|
|
|
conv_dp_to_mm (drive, part, d.major, d.minor);
|
|
bp = stpcpy (buf, "/dev/sd");
|
|
if (drive >= 26)
|
|
{
|
|
drive -= 26;
|
|
*bp++ = drive / 26 + 'a';
|
|
drive %= 26;
|
|
}
|
|
*bp++ = drive + 'a';
|
|
if (part)
|
|
{
|
|
if (part >= 10)
|
|
{
|
|
*bp++ = part / 10 + '0';
|
|
part %= 10;
|
|
}
|
|
*bp++ = part + '0';
|
|
}
|
|
*bp = '\0';
|
|
name (buf, true);
|
|
}
|