* Makefile.in (DLL_OFILES): Add fhandler_dev.o.

* devices.h (DEV_DEV_MAJOR): Define.
	(FH_DEV): Redefine in terms of DEV_DEV_MAJOR.
	(ext_dev_storage): Declare.
	(dev_storage_size): Declare.
	(dev_dev_storage): Declare.
	(dev_dev): Define.
	(isdev_dev): Define.
	* devices.in (dev_dev_storage): Activate.
	(ext_dev_storage): Define as externally available pointer to
	dev_storage.
	(dev_storage_size): Define to contain number of dev_storage elements.
	* dir.cc (rmdir): Handle /dev as always not empty.
	* dtable.cc (fh_alloc): Handle DEV_DEV_MAJOR.
	* fhandler.h (fhandler_dev): New class, derived from fhandler_disk_file.
	(fhandler_union): Add fhandler_dev member.
	* fhandler_disk_file.cc (class __DIR_mounts): Handle /dev directory
	to make sure it always exists.
	* fhandler_dev.cc: New file implementing /dev.
	* globals.cc (ro_u_dev): New R/O unicode string.
	* path.cc (path_conv::check): Handle FH_DEV device.
This commit is contained in:
Corinna Vinschen 2012-03-29 18:02:54 +00:00
parent d46ed263af
commit 9ca7bca3c3
12 changed files with 325 additions and 37 deletions

View File

@ -1,3 +1,27 @@
2012-03-29 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (DLL_OFILES): Add fhandler_dev.o.
* devices.h (DEV_DEV_MAJOR): Define.
(FH_DEV): Redefine in terms of DEV_DEV_MAJOR.
(ext_dev_storage): Declare.
(dev_storage_size): Declare.
(dev_dev_storage): Declare.
(dev_dev): Define.
(isdev_dev): Define.
* devices.in (dev_dev_storage): Activate.
(ext_dev_storage): Define as externally available pointer to
dev_storage.
(dev_storage_size): Define to contain number of dev_storage elements.
* dir.cc (rmdir): Handle /dev as always not empty.
* dtable.cc (fh_alloc): Handle DEV_DEV_MAJOR.
* fhandler.h (fhandler_dev): New class, derived from fhandler_disk_file.
(fhandler_union): Add fhandler_dev member.
* fhandler_disk_file.cc (class __DIR_mounts): Handle /dev directory
to make sure it always exists.
* fhandler_dev.cc: New file implementing /dev.
* globals.cc (ro_u_dev): New R/O unicode string.
* path.cc (path_conv::check): Handle FH_DEV device.
2012-03-29 Christopher Faylor <me.cygwin2012@cgf.cx>
* fhandler_console.cc (fhandler_console::set_unit): Don't succeed

View File

@ -139,25 +139,25 @@ DLL_OFILES:=advapi32.o assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o \
cygthread.o cygtls.o cygxdr.o dcrt0.o debug.o devices.o dir.o dlfcn.o \
dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \
fcntl.o fenv.o fhandler.o fhandler_clipboard.o fhandler_console.o \
fhandler_disk_file.o fhandler_dsp.o fhandler_fifo.o fhandler_floppy.o \
fhandler_mailslot.o fhandler_mem.o fhandler_netdrive.o fhandler_nodevice.o \
fhandler_proc.o fhandler_process.o fhandler_procnet.o fhandler_procsys.o \
fhandler_procsysvipc.o fhandler_random.o fhandler_raw.o fhandler_registry.o \
fhandler_serial.o fhandler_socket.o fhandler_tape.o fhandler_termios.o \
fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \
flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o glob_pattern_p.o \
globals.o grp.o heap.o hookapi.o inet_addr.o inet_network.o init.o ioctl.o \
ipc.o kernel32.o libstdcxx_wrapper.o localtime.o lsearch.o malloc_wrapper.o \
minires-os-if.o minires.o miscfuncs.o mktemp.o mmap.o msg.o \
mount.o net.o netdb.o nfs.o nftw.o nlsfuncs.o ntea.o passwd.o path.o \
pinfo.o pipe.o poll.o posix_ipc.o pseudo-reloc.o pthread.o random.o \
regcomp.o regerror.o regexec.o regfree.o registry.o resource.o rexec.o \
rcmd.o scandir.o sched.o sec_acl.o sec_auth.o sec_helper.o security.o \
select.o sem.o setlsapwd.o shared.o shm.o sigfe.o signal.o sigproc.o \
smallprint.o spawn.o strace.o strfmon.o strfuncs.o strptime.o strsep.o \
strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \
timer.o times.o tls_pbuf.o tty.o uinfo.o uname.o wait.o wincap.o \
window.o winf.o wow64.o xsique.o \
fhandler_dev.o fhandler_disk_file.o fhandler_dsp.o fhandler_fifo.o \
fhandler_floppy.o fhandler_mailslot.o fhandler_mem.o fhandler_netdrive.o \
fhandler_nodevice.o fhandler_proc.o fhandler_process.o fhandler_procnet.o \
fhandler_procsys.o fhandler_procsysvipc.o fhandler_random.o fhandler_raw.o \
fhandler_registry.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \
fhandler_termios.o fhandler_tty.o fhandler_virtual.o fhandler_windows.o \
fhandler_zero.o flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o \
glob_pattern_p.o globals.o grp.o heap.o hookapi.o inet_addr.o \
inet_network.o init.o ioctl.o ipc.o kernel32.o libstdcxx_wrapper.o \
localtime.o lsearch.o malloc_wrapper.o minires-os-if.o minires.o \
miscfuncs.o mktemp.o mmap.o msg.o mount.o net.o netdb.o nfs.o nftw.o \
nlsfuncs.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o posix_ipc.o \
pseudo-reloc.o pthread.o random.o regcomp.o regerror.o regexec.o regfree.o \
registry.o resource.o rexec.o rcmd.o scandir.o sched.o sec_acl.o \
sec_auth.o sec_helper.o security.o select.o sem.o setlsapwd.o shared.o \
shm.o sigfe.o signal.o sigproc.o smallprint.o spawn.o strace.o strfmon.o \
strfuncs.o strptime.o strsep.o strsig.o sync.o syscalls.o sysconf.o \
syslog.o termios.o thread.o timer.o times.o tls_pbuf.o tty.o uinfo.o \
uname.o wait.o wincap.o window.o winf.o wow64.o xsique.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
EXCLUDE_STATIC_OFILES:=$(addprefix --exclude=,\

View File

@ -33,10 +33,8 @@ const device dev_procsysvipc_storage =
const device dev_netdrive_storage =
{"", {FH_NETDRIVE}, ""};
#if 0
const device dev_dev_storage =
{"/dev", {FH_DEV}, "/dev"};
#endif
const device dev_registry_storage =
{"", {FH_REGISTRY}, ""};
@ -46531,6 +46529,10 @@ return NULL;
#undef BRACK
const device *ext_dev_storage = dev_storage;
const size_t dev_storage_size = sizeof dev_storage / sizeof dev_storage[0];
void
device::parse (const char *s)
{

View File

@ -1,6 +1,6 @@
/* devices.h
Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010, 2011 Red Hat, Inc.
Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010, 2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
@ -68,7 +68,6 @@ enum fh_devices
FH_FIFO = FHDEV (0, 196),
FH_FS = FHDEV (0, 195), /* filesystem based device */
FH_NETDRIVE= FHDEV (0, 194),
FH_DEV = FHDEV (0, 193),
DEV_FLOPPY_MAJOR = 2,
FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0),
@ -243,6 +242,9 @@ enum fh_devices
DEV_CYGDRIVE_MAJOR = 98,
FH_CYGDRIVE= FHDEV (DEV_CYGDRIVE_MAJOR, 0),
DEV_DEV_MAJOR = 99,
FH_DEV= FHDEV (DEV_DEV_MAJOR, 0),
DEV_TCP_MAJOR = 30,
FH_TCP = FHDEV (DEV_TCP_MAJOR, 36),
FH_UDP = FHDEV (DEV_TCP_MAJOR, 39),
@ -316,6 +318,9 @@ struct device
inline bool is_fs_special () const {return dev_on_fs && d.devn != FH_FS;}
};
extern const device *ext_dev_storage;
extern const size_t dev_storage_size;
extern const device *console_dev;
extern const device *ptmx_dev;
extern const device *ptys_dev;
@ -336,6 +341,8 @@ extern const device dev_pipew_storage;
#define pipew_dev (&dev_pipew_storage)
extern const device dev_proc_storage;
#define proc_dev (&dev_proc_storage)
extern const device dev_dev_storage;
#define dev_dev (&dev_dev_storage)
extern const device dev_netdrive_storage;
#define netdrive_dev (&dev_netdrive_storage)
extern const device dev_cygdrive_storage;
@ -348,6 +355,8 @@ extern const device dev_fs_storage;
#define isproc_dev(devn) \
(devn >= FH_PROC_MIN_MINOR && devn <= FH_PROC_MAX_MINOR)
#define isdev_dev(devn) (devn == FH_DEV)
#define isprocsys_dev(devn) (devn == FH_PROCSYS)
#define isvirtual_dev(devn) \

View File

@ -29,10 +29,8 @@ const device dev_procsysvipc_storage =
const device dev_netdrive_storage =
{"", {FH_NETDRIVE}, ""};
#if 0
const device dev_dev_storage =
{"/dev", {FH_DEV}, "/dev"};
#endif
const device dev_registry_storage =
{"", {FH_REGISTRY}, ""};
@ -108,6 +106,10 @@ const device dev_error_storage =
%other {return NULL;}
%%
#undef BRACK
const device *ext_dev_storage = dev_storage;
const size_t dev_storage_size = sizeof dev_storage / sizeof dev_storage[0];
void
device::parse (const char *s)
{

View File

@ -347,6 +347,11 @@ rmdir (const char *dir)
set_errno (ENOENT);
else if (has_dot_last_component (dir, false))
set_errno (EINVAL);
else if (isdev_dev (fh->dev ()))
{
set_errno (ENOTEMPTY);
goto done;
}
else if (!fh->rmdir ())
res = 0;

View File

@ -459,6 +459,9 @@ fh_alloc (path_conv& pc)
case DEV_CYGDRIVE_MAJOR:
fh = cnew (fhandler_cygdrive);
break;
case DEV_DEV_MAJOR:
fh = cnew (fhandler_dev);
break;
case DEV_FLOPPY_MAJOR:
case DEV_CDROM_MAJOR:
case DEV_SD_MAJOR:

View File

@ -1016,6 +1016,34 @@ class fhandler_disk_file: public fhandler_base
}
};
class fhandler_dev: public fhandler_disk_file
{
int lastrealpos;
bool dir_exists;
public:
fhandler_dev ();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
void rewinddir (DIR *);
fhandler_dev (void *) {}
void copyto (fhandler_base *x)
{
x->pc.free_strings ();
*reinterpret_cast<fhandler_dev *> (x) = *this;
x->reset (this);
}
fhandler_dev *clone (cygheap_types malloc_type = HEAP_FHANDLER)
{
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev));
fhandler_dev *fh = new (ptr) fhandler_dev (ptr);
copyto (fh);
return fh;
}
};
class fhandler_cygdrive: public fhandler_disk_file
{
enum
@ -2093,6 +2121,7 @@ typedef union
{
char __base[sizeof (fhandler_base)];
char __console[sizeof (fhandler_console)];
char __dev[sizeof (fhandler_dev)];
char __cygdrive[sizeof (fhandler_cygdrive)];
char __dev_clipboard[sizeof (fhandler_dev_clipboard)];
char __dev_dsp[sizeof (fhandler_dev_dsp)];

View File

@ -0,0 +1,145 @@
/* fhandler_dev.cc, Implement /dev.
Copyright 2012 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <stdlib.h>
#include "path.h"
#include "fhandler.h"
#include "shared_info.h"
#include "ntdll.h"
#include "devices.h"
#define _COMPILING_NEWLIB
#include <dirent.h>
#define dev_prefix_len (sizeof ("/dev"))
static int
device_cmp (const void *a, const void *b)
{
return strcmp (((const device *) a)->name,
((const device *) b)->name + dev_prefix_len);
}
int
fhandler_dev::readdir (DIR *dir, dirent *de)
{
int ret;
if (dir_exists && !lastrealpos)
{
while ((ret = fhandler_disk_file::readdir (dir, de)) == 0)
{
/* Avoid to print devices for which users have created files under
/dev already, for instance by using the old script from Igor
Peshansky. */
device dev;
dev.name = de->d_name;
if (!bsearch (&dev, ext_dev_storage, dev_storage_size, sizeof dev,
device_cmp))
break;
}
if (ret == ENMFILE)
lastrealpos = dir->__d_position;
}
if (!dir_exists || lastrealpos)
{
ret = ENMFILE;
for (size_t idx = dir->__d_position - lastrealpos + 1;
idx < dev_storage_size;
++idx)
{
struct __stat64 st;
++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 0:
if (ext_dev_storage[idx].d.minor == FH_FIFO
|| ext_dev_storage[idx].d.minor == FH_PIPE)
continue;
case DEV_PTYM_MAJOR:
if (ext_dev_storage[idx].d.minor
|| !strcmp (ext_dev_storage[idx].name, "/dev/ptm0"))
continue;
break;
case DEV_PTYS_MAJOR:
if (cygwin_shared->tty.connect (ext_dev_storage[idx].d.minor)
== -1)
continue;
break;
case DEV_CONS_MAJOR:
if (!iscons_dev (myself->ctty)
|| myself->ctty != ext_dev_storage[idx].d.devn_int)
continue;
break;
case DEV_FLOPPY_MAJOR:
case DEV_TAPE_MAJOR:
case DEV_CDROM_MAJOR:
case DEV_SERIAL_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:
{
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);
/* The native paths are devices, not symlinks, so we expect
a matching error message. */
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;
}
if (!lstat64 (ext_dev_storage[idx].name, &st))
{
strcpy (de->d_name, ext_dev_storage[idx].name + dev_prefix_len);
de->d_ino = st.st_ino;
de->d_type = S_ISBLK (st.st_mode) ? DT_BLK : DT_CHR;
ret = 0;
break;
}
}
}
return ret;
}
void
fhandler_dev::rewinddir (DIR *dir)
{
lastrealpos = 0;
fhandler_disk_file::rewinddir (dir);
}

View File

@ -26,6 +26,7 @@ details. */
#include "pwdgrp.h"
#include <winioctl.h>
#include <lm.h>
#include "devices.h"
#define _COMPILING_NEWLIB
#include <dirent.h>
@ -36,11 +37,12 @@ class __DIR_mounts
const char *parent_dir;
int parent_dir_len;
UNICODE_STRING mounts[MAX_MOUNTS];
bool found[MAX_MOUNTS + 2];
bool found[MAX_MOUNTS + 3];
UNICODE_STRING cygdrive;
#define __DIR_PROC (MAX_MOUNTS)
#define __DIR_CYGDRIVE (MAX_MOUNTS+1)
#define __DIR_DEV (MAX_MOUNTS+2)
__ino64_t eval_ino (int idx)
{
@ -84,6 +86,11 @@ public:
found[__DIR_PROC] = true;
return 2;
}
if (RtlEqualUnicodeString (fname, &ro_u_dev, FALSE))
{
found[__DIR_DEV] = true;
return 2;
}
if (fname->Length / sizeof (WCHAR) == mount_table->cygdrive_len - 2
&& RtlEqualUnicodeString (fname, &cygdrive, FALSE))
{
@ -121,6 +128,13 @@ public:
*retname = ro_u_proc;
return 2;
}
if (!found[__DIR_DEV])
{
found[__DIR_DEV] = true;
if (retname)
*retname = ro_u_dev;
return 2;
}
if (!found[__DIR_CYGDRIVE])
{
found[__DIR_CYGDRIVE] = true;
@ -2351,6 +2365,66 @@ fhandler_disk_file::closedir (DIR *dir)
return res;
}
fhandler_dev::fhandler_dev () :
fhandler_disk_file (), lastrealpos (0), 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;
dir_exists = false;
res = dir;
}
syscall_printf ("%p = opendir (%s)", res, get_name ());
return res;
free_dirent:
free (dir->__d_dirent);
free_dir:
free (dir);
return res;
}
fhandler_cygdrive::fhandler_cygdrive () :
fhandler_disk_file (), ndrives (0), pdrive (NULL)
{

View File

@ -96,6 +96,7 @@ UNICODE_STRING _RDATA ro_u_com = _ROU (L".com");
UNICODE_STRING _RDATA ro_u_scr = _ROU (L".scr");
UNICODE_STRING _RDATA ro_u_sys = _ROU (L".sys");
UNICODE_STRING _RDATA ro_u_proc = _ROU (L"proc");
UNICODE_STRING _RDATA ro_u_dev = _ROU (L"dev");
UNICODE_STRING _RDATA ro_u_pmem = _ROU (L"\\Device\\PhysicalMemory");
UNICODE_STRING _RDATA ro_u_natp = _ROU (L"\\??\\");
UNICODE_STRING _RDATA ro_u_uncp = _ROU (L"\\??\\UNC\\");

View File

@ -730,17 +730,9 @@ path_conv::check (const char *src, unsigned opt,
}
goto out;
}
else if (dev == FH_DEV)
else if (isdev_dev (dev))
{
dev = FH_FS;
#if 0
fileattr = getfileattr (THIS_path, sym.pflags & MOUNT_NOPOSIX);
if (!component && fileattr == INVALID_FILE_ATTRIBUTES)
{
fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY;
goto out;
}
#endif
/* Just make sure that the path handling goes on as with FH_FS. */
}
else if (isvirtual_dev (dev))
{
@ -879,7 +871,9 @@ is_virtual_symlink:
if (!component)
{
fileattr = sym.fileattr;
/* Make sure that /dev always exists. */
fileattr = isdev_dev (dev) ? FILE_ATTRIBUTE_DIRECTORY
: sym.fileattr;
path_flags = sym.pflags;
}