From 990690655ca59784c81430e7d258fd9a2231b6cb Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 16 Oct 2001 14:53:26 +0000 Subject: [PATCH] * autoload.cc: Add load statement for `NtOpenFile'. * fhandler.h (fhandler_dev_raw::get_unit): New method. (fhandler_dev_tape::norewind): Eliminate. (fhandler_dev_tape::is_rewind_device): New method. * fhandler_raw.cc (fhandler_dev_raw::open): Open new fixed device name devices using NT internal method. Keep calling fhandler_base::open() for old mount table device mapping compatibility devices. (fhandler_dev_raw::fstat): Eliminate. Settings are done by fhandler_base::fstat() already. * fhandler_tape.cc: Remove `norewind' usage throughout. * ntdll.h: Define FILE_SYNCHRONOUS_IO_NONALERT. Define struct _IO_STATUS_BLOCK. Declare NtOpenFile(). * path.cc (get_raw_device_number): Add new approach for using fixed device names. (win32_device_name): Ditto. (get_device_number): Ditto. Require POSIX path to begin with "/dev/". (mount_info::conv_to_win32_path): Call win32_device_name() instead of get_device_number() after evaluating mount points to allow changing the win32 destination path again. * security.cc (str2buf2uni): Remove `static' to be able to call function from fhandler_dev_raw::open(). * wincap.cc: Set flag has_raw_devices appropriately. * wincap.h: Add flag has_raw_devices. --- winsup/cygwin/ChangeLog | 29 ++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/fhandler.h | 7 +- winsup/cygwin/fhandler_raw.cc | 74 ++++++++++---- winsup/cygwin/fhandler_tape.cc | 7 +- winsup/cygwin/ntdll.h | 9 ++ winsup/cygwin/path.cc | 171 ++++++++++++++++++++++++++------- winsup/cygwin/security.cc | 2 +- winsup/cygwin/wincap.cc | 11 +++ winsup/cygwin/wincap.h | 2 + 10 files changed, 253 insertions(+), 60 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index d9847efa7..e733ff758 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,32 @@ +2001-10-16 Corinna Vinschen + + * autoload.cc: Add load statement for `NtOpenFile'. + * fhandler.h (fhandler_dev_raw::get_unit): New method. + (fhandler_dev_tape::norewind): Eliminate. + (fhandler_dev_tape::is_rewind_device): New method. + * fhandler_raw.cc (fhandler_dev_raw::open): Open new + fixed device name devices using NT internal method. + Keep calling fhandler_base::open() for old mount table + device mapping compatibility devices. + (fhandler_dev_raw::fstat): Eliminate. Settings are done + by fhandler_base::fstat() already. + * fhandler_tape.cc: Remove `norewind' usage throughout. + * ntdll.h: Define FILE_SYNCHRONOUS_IO_NONALERT. + Define struct _IO_STATUS_BLOCK. + Declare NtOpenFile(). + * path.cc (get_raw_device_number): Add new approach for + using fixed device names. + (win32_device_name): Ditto. + (get_device_number): Ditto. Require POSIX path to begin + with "/dev/". + (mount_info::conv_to_win32_path): Call win32_device_name() + instead of get_device_number() after evaluating mount points + to allow changing the win32 destination path again. + * security.cc (str2buf2uni): Remove `static' to be able to + call function from fhandler_dev_raw::open(). + * wincap.cc: Set flag has_raw_devices appropriately. + * wincap.h: Add flag has_raw_devices. + 2001-10-16 Christopher Faylor * cygheap.h (cygheap_fdget::cygheap_fdget): Remove debugging operation diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 196276899..259e3b4cd 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -373,6 +373,7 @@ LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) +LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1) LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1) LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 4b19af296..2335484c3 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -476,14 +476,14 @@ protected: public: ~fhandler_dev_raw (void); + int get_unit () { return unit; } + int open (path_conv *, int flags, mode_t mode = 0); int close (void); int raw_read (void *ptr, size_t ulen); int raw_write (const void *ptr, size_t ulen); - int __stdcall fstat (struct stat *buf, path_conv *) __attribute__ ((regparm (2))); - int dup (fhandler_base *child); int ioctl (unsigned int cmd, void *buf); @@ -511,9 +511,10 @@ public: class fhandler_dev_tape: public fhandler_dev_raw { - int norewind; int lasterr; + bool is_rewind_device () { return get_unit () < 128; } + protected: virtual void clear (void); diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index a31e73904..3e73850e2 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -16,6 +16,7 @@ #include #include +#include #include "cygerrno.h" #include "perprocess.h" #include "security.h" @@ -23,6 +24,7 @@ #include "path.h" #include "dtable.h" #include "cygheap.h" +#include "ntdll.h" /* static wrapper functions to hide the effect of media changes and bus resets which occurs after a new media is inserted. This is @@ -132,22 +134,69 @@ fhandler_dev_raw::~fhandler_dev_raw (void) } int -fhandler_dev_raw::open (path_conv *, int flags, mode_t) +fhandler_dev_raw::open (path_conv *real_path, int flags, mode_t) { - int ret; + if (!wincap.has_raw_devices ()) + { + set_errno (ENOENT); + debug_printf("%s is accessible under NT/W2K only",real_path->get_win32()); + return 0; + } + + /* Check for illegal flags. */ + if (flags & (O_APPEND | O_EXCL)) + { + set_errno (EINVAL); + return 0; + } /* Always open a raw device existing and binary. */ flags &= ~(O_CREAT | O_TRUNC); flags |= O_BINARY; - ret = fhandler_base::open (NULL, flags); - if (ret) + + if (get_device () == FH_FLOPPY && get_unit () >= 224) { - if (devbufsiz > 1L) - devbuf = new char [devbufsiz]; + /* Compatibility mode for old mount table device mapping. */ + if (!fhandler_base::open (real_path, flags)) + return 0; } else - devbufsiz = 0; - return ret; + { + DWORD access = GENERIC_READ | SYNCHRONIZE; + if (get_device () == FH_TAPE + || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY + || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDWR) + access |= GENERIC_WRITE; + + extern void str2buf2uni (UNICODE_STRING &, WCHAR *, const char *); + UNICODE_STRING dev; + WCHAR devname[MAX_PATH + 1]; + str2buf2uni (dev, devname, real_path->get_win32 ()); + OBJECT_ATTRIBUTES attr; + InitializeObjectAttributes(&attr, &dev, OBJ_CASE_INSENSITIVE, NULL, NULL); + + HANDLE h; + IO_STATUS_BLOCK io; + NTSTATUS status = NtOpenFile (&h, access, &attr, &io, wincap.shared (), + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS (status)) + { + set_errno (RtlNtStatusToDosError (status)); + debug_printf ("NtOpenFile: NTSTATUS: %d, Win32: %E", status); + return 0; + } + + set_io_handle (h); + set_flags (flags); + } + + set_r_binary (O_BINARY); + set_w_binary (O_BINARY); + + if (devbufsiz > 1L) + devbuf = new char [devbufsiz]; + + return 1; } int @@ -156,15 +205,6 @@ fhandler_dev_raw::close (void) return fhandler_base::close (); } -int -fhandler_dev_raw::fstat (struct stat *buf, path_conv *pc) -{ - this->fhandler_base::fstat (buf, pc); - buf->st_blksize = devbuf ? devbufsiz : 1; - - return 0; -} - int fhandler_dev_raw::raw_read (void *ptr, size_t ulen) { diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc index 2aabcf9be..35ff99900 100644 --- a/winsup/cygwin/fhandler_tape.cc +++ b/winsup/cygwin/fhandler_tape.cc @@ -29,7 +29,6 @@ details. */ void fhandler_dev_tape::clear (void) { - norewind = 0; lasterr = 0; fhandler_dev_raw::clear (); } @@ -66,7 +65,6 @@ fhandler_dev_tape::open (path_conv *real_path, int flags, mode_t) { int ret; - norewind = (real_path->get_unitn () >= 128); devbufsiz = 1L; ret = fhandler_dev_raw::open (real_path, flags); @@ -132,7 +130,7 @@ fhandler_dev_tape::close (void) // To protected reads on signaling (e.g. Ctrl-C) eof_detected = 1; - if (! norewind) + if (is_rewind_device ()) { debug_printf ("rewinding\n"); op.mt_op = MTREW; @@ -153,7 +151,7 @@ fhandler_dev_tape::fstat (struct stat *buf, path_conv *pc) { int ret; - if (!(ret = fhandler_dev_raw::fstat (buf, pc))) + if (!(ret = fhandler_base::fstat (buf, pc))) { struct mtget get; @@ -227,7 +225,6 @@ fhandler_dev_tape::dup (fhandler_base *child) { fhandler_dev_tape *fhc = (fhandler_dev_tape *) child; - fhc->norewind = norewind; fhc->lasterr = lasterr; return fhandler_dev_raw::dup (child); } diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 6dd617c60..e1ec33bc1 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -9,6 +9,7 @@ details. */ #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004) +#define FILE_SYNCHRONOUS_IO_NONALERT 32 typedef enum _SYSTEM_INFORMATION_CLASS { @@ -132,6 +133,12 @@ typedef struct _SYSTEM_PROCESSES SYSTEM_THREADS Threads[1]; } SYSTEM_PROCESSES, *PSYSTEM_PROCESSES; +typedef struct _IO_STATUS_BLOCK +{ + NTSTATUS Status; + ULONG Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + /* Function declarations for ntdll.dll. These don't appear in any standard Win32 header. */ extern "C" @@ -144,6 +151,8 @@ extern "C" NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG, PLARGE_INTEGER, PULONG, SECTION_INHERIT, ULONG, ULONG); + NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, + PIO_STATUS_BLOCK, ULONG, ULONG); NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index de5899ac4..e0d39b8dc 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -854,31 +854,112 @@ get_devn (const char *name, int &unit) return devn; } +/* + major minor POSIX filename NT filename + ----- ----- -------------- ------------------------- + FH_TAPE 0 /dev/st0 \device\tape0 + FH_TAPE 1 /dev/st1 \device\tape1 + ... + FH_TAPE 128 /dev/nst0 \device\tape0 + FH_TAPE 129 /dev/nst1 \device\tape1 + ... + + FH_FLOPPY 0 /dev/fd0 \device\floppy0 + FH_FLOPPY 1 /dev/fd1 \device\floppy1 + ... + + FH_FLOPPY 16 /dev/scd0 \device\cdrom0 + FH_FLOPPY 17 /dev/scd0 \device\cdrom1 + ... + + FH_FLOPPY 32 /dev/sda \device\harddisk0\partition0 + FH_FLOPPY 33 /dev/sda1 \device\harddisk0\partition1 + ... + FH_FLOPPY 47 /dev/sda15 \device\harddisk0\partition15 + + FH_FLOPPY 48 /dev/sdb \device\harddisk1\partition0 + FH_FLOPPY 33 /dev/sdb1 \device\harddisk1\partition1 + ... + FH_FLOPPY 208 /dev/sdl \device\harddisk11\partition0 + ... + FH_FLOPPY 223 /dev/sdl15 \device\harddisk11\partition15 + + The following are needed to maintain backward compatibility with + the old Win32 partitioning scheme on W2K/XP. + + FH_FLOPPY 224 from mount tab \\.\A: + ... + FH_FLOPPY 250 from mount tab \\.\Z: +*/ static int -get_raw_device_number (const char *unix_path, const char *w32_path, int &unit) +get_raw_device_number (const char *name, const char *w32_path, int &unit) { - int devn; - w32_path += 4; - if (wdeveqn ("tape", 4)) + DWORD devn = FH_BAD; + + if (!w32_path) /* New approach using fixed device names. */ { - unit = digits (w32_path + 4); - // norewind tape devices have leading n in name - if (udeveqn ("/dev/n", 6)) - unit += 128; - devn = FH_TAPE; + if (deveqn ("st", 2)) + { + unit = digits (name + 2); + if (unit >= 0 && unit < 128) + devn = FH_TAPE; + } + else if (deveqn ("nst", 3)) + { + unit = digits (name + 3) + 128; + if (unit >= 128 && unit < 256) + devn = FH_TAPE; + } + else if (deveqn ("fd", 2)) + { + unit = digits (name + 2); + if (unit >= 0 && unit < 16) + devn = FH_FLOPPY; + } + else if (deveqn ("scd", 3)) + { + unit = digits (name + 3) + 16; + if (unit >= 16 && unit < 32) + devn = FH_FLOPPY; + } + else if (deveqn ("sd", 2) && isalpha (name[2])) + { + unit = (cyg_tolower (name[2]) - 'a') * 16 + 32; + if (unit >= 32 && unit < 224) + if (!name[3]) + devn = FH_FLOPPY; + else + { + int d = digits (name + 3); + if (d >= 1 && d < 16) + { + unit += d; + devn = FH_FLOPPY; + } + } + } } - else if (isdrive (w32_path)) + else /* Backward compatible checking of mount table device mapping. */ { - unit = cyg_tolower (w32_path[0]) - 'a'; - devn = FH_FLOPPY; + if (wdeveqn ("tape", 4)) + { + unit = digits (w32_path + 4); + /* Norewind tape devices have leading n in name. */ + if (deveqn ("n", 1)) + unit += 128; + devn = FH_TAPE; + } + else if (wdeveqn ("physicaldrive", 13)) + { + unit = digits (w32_path + 13) * 16 + 32; + devn = FH_FLOPPY; + } + else if (isdrive (w32_path)) + { + unit = cyg_tolower (w32_path[0]) - 'a' + 224; + devn = FH_FLOPPY; + } } - else if (wdeveqn ("physicaldrive", 13)) - { - unit = digits (w32_path + 13) + 128; - devn = FH_FLOPPY; - } - else - devn = FH_BAD; return devn; } @@ -892,15 +973,18 @@ get_device_number (const char *unix_path, const char *w32_path, int &unit) unit = 0; if (*unix_path == '/' && udeveqn ("/dev/", 5)) - devn = get_devn (unix_path, unit); - if (devn == FH_BAD && *w32_path == '\\' && wdeveqn ("\\dev\\", 5)) - devn = get_devn (w32_path, unit); - if (devn == FH_BAD && udeveqn ("com", 3) - && (unit = digits (unix_path + 3)) >= 0) - devn = FH_SERIAL; - else if (strncmp (w32_path, "\\\\.\\", 4) == 0) - devn = get_raw_device_number (unix_path, w32_path, unit); - + { + devn = get_devn (unix_path, unit); + if (devn == FH_BAD && *w32_path == '\\' && wdeveqn ("\\dev\\", 5)) + devn = get_devn (w32_path, unit); + if (devn == FH_BAD && udeveqn ("com", 3) + && (unit = digits (unix_path + 3)) >= 0) + devn = FH_SERIAL; + if (devn == FH_BAD && wdeveqn ("\\\\.\\", 4)) + devn = get_raw_device_number (unix_path + 5, w32_path + 4, unit); + if (devn == FH_BAD) + devn = get_raw_device_number (unix_path + 5, NULL, unit); + } return devn; } @@ -913,17 +997,36 @@ win32_device_name (const char *src_path, char *win32_path, { const char *devfmt; - devn = get_device_number (src_path, "", unit); + devn = get_device_number (src_path, win32_path, unit); if (devn == FH_BAD) return FALSE; if ((devfmt = windows_device_names[FHDEVN (devn)]) == NULL) return FALSE; - if (devn == FH_RANDOM) - __small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u"); - else - __small_sprintf (win32_path, devfmt, unit); + switch (devn) + { + case FH_RANDOM: + __small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u"); + break; + case FH_TAPE: + __small_sprintf (win32_path, "\\device\\tape%d", unit % 128); + break; + case FH_FLOPPY: + if (unit < 16) + __small_sprintf (win32_path, "\\device\\floppy%d", unit); + else if (unit < 32) + __small_sprintf (win32_path, "\\device\\cdrom%d", unit - 16); + else if (unit < 224) + __small_sprintf (win32_path, "\\device\\harddisk%d\\partition%d", + (unit - 32) / 16, unit % 16); + else + __small_sprintf (win32_path, "\\\\.\\%c:", unit - 224 + 'A'); + break; + default: + __small_sprintf (win32_path, devfmt, unit); + break; + } return TRUE; } @@ -1335,7 +1438,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, *flags = mi->flags; } - devn = get_device_number (src_path, dst, unit); + win32_device_name (src_path, dst, devn, unit); out: MALLOC_CHECK; diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index d4dd03c70..40081fbef 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -157,7 +157,7 @@ str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr) memcpy(buf, srcstr, tgt.MaximumLength); } -static void +void str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr) { tgt.Length = strlen (srcstr) * sizeof (WCHAR); diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index d0f9c6dff..ad1459b07 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -43,6 +43,7 @@ static NO_COPY wincaps wincap_unknown = { has_negative_pids:false, has_unreliable_pipes:false, has_try_enter_critical_section:false, + has_raw_devices:false, has_valid_processorlevel:false, }; @@ -78,6 +79,7 @@ static NO_COPY wincaps wincap_95 = { has_negative_pids:true, has_unreliable_pipes:true, has_try_enter_critical_section:false, + has_raw_devices:false, has_valid_processorlevel:false, }; @@ -113,6 +115,7 @@ static NO_COPY wincaps wincap_95osr2 = { has_negative_pids:true, has_unreliable_pipes:true, has_try_enter_critical_section:false, + has_raw_devices:false, has_valid_processorlevel:false, }; @@ -148,6 +151,7 @@ static NO_COPY wincaps wincap_98 = { has_negative_pids:true, has_unreliable_pipes:true, has_try_enter_critical_section:false, + has_raw_devices:false, has_valid_processorlevel:true, }; @@ -183,6 +187,7 @@ static NO_COPY wincaps wincap_98se = { has_negative_pids:true, has_unreliable_pipes:true, has_try_enter_critical_section:false, + has_raw_devices:false, has_valid_processorlevel:true, }; @@ -218,6 +223,7 @@ static NO_COPY wincaps wincap_me = { has_negative_pids:true, has_unreliable_pipes:true, has_try_enter_critical_section:false, + has_raw_devices:false, has_valid_processorlevel:true, }; @@ -253,6 +259,7 @@ static NO_COPY wincaps wincap_nt3 = { has_negative_pids:false, has_unreliable_pipes:false, has_try_enter_critical_section:false, + has_raw_devices:true, has_valid_processorlevel:true, }; @@ -288,6 +295,7 @@ static NO_COPY wincaps wincap_nt4 = { has_negative_pids:false, has_unreliable_pipes:false, has_try_enter_critical_section:true, + has_raw_devices:true, has_valid_processorlevel:true, }; @@ -323,6 +331,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { has_negative_pids:false, has_unreliable_pipes:false, has_try_enter_critical_section:true, + has_raw_devices:true, has_valid_processorlevel:true, }; @@ -358,6 +367,7 @@ static NO_COPY wincaps wincap_2000 = { has_negative_pids:false, has_unreliable_pipes:false, has_try_enter_critical_section:true, + has_raw_devices:true, has_valid_processorlevel:true, }; @@ -393,6 +403,7 @@ static NO_COPY wincaps wincap_xp = { has_negative_pids:false, has_unreliable_pipes:false, has_try_enter_critical_section:true, + has_raw_devices:true, has_valid_processorlevel:true, }; diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 2bb391454..6687e932d 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -44,6 +44,7 @@ struct wincaps unsigned has_negative_pids : 1; unsigned has_unreliable_pipes : 1; unsigned has_try_enter_critical_section : 1; + unsigned has_raw_devices : 1; unsigned has_valid_processorlevel : 1; }; @@ -93,6 +94,7 @@ public: bool IMPLEMENT (has_negative_pids) bool IMPLEMENT (has_unreliable_pipes) bool IMPLEMENT (has_try_enter_critical_section) + bool IMPLEMENT (has_raw_devices) bool IMPLEMENT (has_valid_processorlevel) #undef IMPLEMENT