398 lines
10 KiB
Plaintext
398 lines
10 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"
|
|
#include "dtable.h"
|
|
#include "cygheap.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 BOOL CALLBACK
|
|
enum_cons_dev (HWND hw, LPARAM lp)
|
|
{
|
|
unsigned long *bitmask = (unsigned long *) lp;
|
|
HANDLE h = NULL;
|
|
fhandler_console::console_state *cs;
|
|
if ((cs = fhandler_console::open_shared_console (hw, h)))
|
|
{
|
|
*bitmask |= (1UL << cs->tty_min_state.getntty ());
|
|
UnmapViewOfFile ((void *) cs);
|
|
CloseHandle (h);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
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 cygheap && cygheap->ctty && cygheap->ctty->is_console ()
|
|
&& fhandler_console::exists ();
|
|
default:
|
|
if (dev.get_minor () < MAX_CONS_DEV)
|
|
{
|
|
unsigned long bitmask = 0;
|
|
EnumWindows (enum_cons_dev, (LPARAM) &bitmask);
|
|
return bitmask & (1UL << dev.get_minor ());
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
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_mqueue_storage =
|
|
{"", {FH_MQUEUE}, "", 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
|
|
"/dev/fd", BRACK(FH_DEV_FD), "/proc/self/fd", exists, S_IFLNK
|
|
"/dev/stdin", BRACK(FH_DEV_FD), "/proc/self/fd/0", exists, S_IFLNK
|
|
"/dev/stdout", BRACK(FH_DEV_FD), "/proc/self/fd/1", exists, S_IFLNK
|
|
"/dev/stderr", BRACK(FH_DEV_FD), "/proc/self/fd/2", exists, S_IFLNK
|
|
%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);
|
|
}
|