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

* devices.h (enum fh_devices): Add FH_PROCSYS.
	* devices.in (dev_procsys_storage): New device.
	* devices.cc: Regenerate.
	* dtable.cc (build_fh_pc): Add code to allocate fhandler_procsys.
	* fhandler.h (proc_len): Convert to size_t.
	(procsys): Declare.
	(procsys_len): Declare.
	(enum virtual_ftype_t): Move here from fhandler_virtual.h.
	Add members supported by fhandler_procsys.
	(fhandler_virtual::exists): Return virtual_ftype_t.  Change
	in all derived classes.
	(class fhandler_procsys): New class.
	(fhandler_union): Add fhandler_procnet and fhandler_procsys members.
	* fhandler_disk_file.cc (__DIR_mounts::check_missing_mount): Use
	ro_u_proc.
	(fhandler_base::fstat_by_handle): Don't copy attributes if file is an
	NT device.
	(fhandler_base::fstat_by_name): Ditto.
	* fhandler_netdrive.cc (fhandler_netdrive::exists): Return
	virtual_ftype_t.
	* fhandler_proc.cc (proc_tab): Sort alphabetically.  Use _VN macro
	to store length.
	(proc_len): Change to size_t.
	(proc_tab_cmp): New static function.
	(virt_tab_search): New function to search entry in virt_tab_t
	arrays.  Use throughout in /proc and sibling classes instead of
	loop.
	(fhandler_proc::exists): Return virtual_ftype_t.
	* fhandler_process.cc (process_tab): Sort alphabetically.  Use _VN
	macro to store length.
	(fhandler_process::exists): Return virtual_ftype_t.
	(fhandler_process::open): Simplify code.
	* fhandler_procnet.cc (procnet_tab): Sort alphabetically.  Use _VN
	macro to store length.
	(fhandler_procnet::exists): Return virtual_ftype_t.
	(fhandler_procnet::open): Simplify.
	* fhandler_procsys.cc: New file.
	* fhandler_registry.cc (fhandler_registry::exists): Return
	virtual_ftype_t.
	* fhandler_virtual.cc (fhandler_virtual::exists): Ditto.
	* fhandler_virtual.h (enum virtual_ftype_t): Move to fhandler.h.
	(virt_tab_t): Add name_len member.
	(_VN): New macro.
	(virt_tab_search): Declare.
	* mount.cc (mount_info::conv_to_win32_path): Fix comment.  Backslashify
	isprocsys_dev paths.
	* ntdll.h (STATUS_OBJECT_TYPE_MISMATCH): Define
	(STATUS_INSTANCE_NOT_AVAILABLE): Define.
	(STATUS_PIPE_NOT_AVAILABLE): Define.
	(STATUS_INVALID_PIPE_STATE): Define.
	(STATUS_PIPE_BUSY): Define.
	(SYMBOLIC_LINK_QUERY): Define.
	(NtOpenSymbolicLinkObject): Declare.
	(NtQuerySymbolicLinkObject): Declare.
	* path.cc (path_conv::check): Accommodate fact that exists method
	returns virtual_ftype_t now.  Add cases for new virtual_ftype_t
	types.
	(cygwin_conv_path): Add GLOBALROOT prefix to native device paths.
	Make sure to strip \\?\ prefix only for actual filesystem-based
	paths, not for all paths.
	* path.h (isproc_dev): Add FH_PROCSYS.
	(isprocsys_dev): Define.
This commit is contained in:
Corinna Vinschen 2010-09-06 09:47:01 +00:00
parent 0de488378f
commit 43f65cdd7d
20 changed files with 816 additions and 216 deletions

View File

@ -1,3 +1,69 @@
2010-09-06 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (DLL_OFILES): Add fhandler_procsys.o.
* devices.h (enum fh_devices): Add FH_PROCSYS.
* devices.in (dev_procsys_storage): New device.
* devices.cc: Regenerate.
* dtable.cc (build_fh_pc): Add code to allocate fhandler_procsys.
* fhandler.h (proc_len): Convert to size_t.
(procsys): Declare.
(procsys_len): Declare.
(enum virtual_ftype_t): Move here from fhandler_virtual.h.
Add members supported by fhandler_procsys.
(fhandler_virtual::exists): Return virtual_ftype_t. Change
in all derived classes.
(class fhandler_procsys): New class.
(fhandler_union): Add fhandler_procnet and fhandler_procsys members.
* fhandler_disk_file.cc (__DIR_mounts::check_missing_mount): Use
ro_u_proc.
(fhandler_base::fstat_by_handle): Don't copy attributes if file is an
NT device.
(fhandler_base::fstat_by_name): Ditto.
* fhandler_netdrive.cc (fhandler_netdrive::exists): Return
virtual_ftype_t.
* fhandler_proc.cc (proc_tab): Sort alphabetically. Use _VN macro
to store length.
(proc_len): Change to size_t.
(proc_tab_cmp): New static function.
(virt_tab_search): New function to search entry in virt_tab_t
arrays. Use throughout in /proc and sibling classes instead of
loop.
(fhandler_proc::exists): Return virtual_ftype_t.
* fhandler_process.cc (process_tab): Sort alphabetically. Use _VN
macro to store length.
(fhandler_process::exists): Return virtual_ftype_t.
(fhandler_process::open): Simplify code.
* fhandler_procnet.cc (procnet_tab): Sort alphabetically. Use _VN
macro to store length.
(fhandler_procnet::exists): Return virtual_ftype_t.
(fhandler_procnet::open): Simplify.
* fhandler_procsys.cc: New file.
* fhandler_registry.cc (fhandler_registry::exists): Return
virtual_ftype_t.
* fhandler_virtual.cc (fhandler_virtual::exists): Ditto.
* fhandler_virtual.h (enum virtual_ftype_t): Move to fhandler.h.
(virt_tab_t): Add name_len member.
(_VN): New macro.
(virt_tab_search): Declare.
* mount.cc (mount_info::conv_to_win32_path): Fix comment. Backslashify
isprocsys_dev paths.
* ntdll.h (STATUS_OBJECT_TYPE_MISMATCH): Define
(STATUS_INSTANCE_NOT_AVAILABLE): Define.
(STATUS_PIPE_NOT_AVAILABLE): Define.
(STATUS_INVALID_PIPE_STATE): Define.
(STATUS_PIPE_BUSY): Define.
(SYMBOLIC_LINK_QUERY): Define.
(NtOpenSymbolicLinkObject): Declare.
(NtQuerySymbolicLinkObject): Declare.
* path.cc (path_conv::check): Accommodate fact that exists method
returns virtual_ftype_t now. Add cases for new virtual_ftype_t
types.
(cygwin_conv_path): Add GLOBALROOT prefix to native device paths.
Make sure to strip \\?\ prefix only for actual filesystem-based
paths, not for all paths.
* path.h (isproc_dev): Add FH_PROCSYS.
(isprocsys_dev): Define.
2010-09-04 Corinna Vinschen <corinna@vinschen.de>
* mount.cc (mount_info::from_fstab_line): Reorder to make sure all

View File

@ -141,13 +141,14 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.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_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 \
fhandler_process.o fhandler_procnet.o fhandler_procsys.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 \

View File

@ -24,6 +24,9 @@ const device dev_proc_storage =
const device dev_procnet_storage =
{"", {FH_PROCNET}, ""};
const device dev_procsys_storage =
{"", {FH_PROCSYS}, ""};
const device dev_netdrive_storage =
{"", {FH_NETDRIVE}, ""};

View File

@ -1,6 +1,6 @@
/* devices.h
Copyright 2002, 2003, 2004, 2005 Red Hat, Inc.
Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@ -53,6 +53,7 @@ enum fh_devices
FH_DEV = FHDEV (0, 245),
FH_PROCNET = FHDEV (0, 244),
FH_PROCESSFD = FHDEV (0, 243),
FH_PROCSYS = FHDEV (0, 242),
DEV_FLOPPY_MAJOR = 2,
FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0),

View File

@ -20,6 +20,9 @@ const device dev_proc_storage =
const device dev_procnet_storage =
{"", {FH_PROCNET}, ""};
const device dev_procsys_storage =
{"", {FH_PROCSYS}, ""};
const device dev_netdrive_storage =
{"", {FH_NETDRIVE}, ""};

View File

@ -540,6 +540,9 @@ build_fh_pc (path_conv& pc, bool set_name)
case FH_PROCNET:
fh = cnew (fhandler_procnet) ();
break;
case FH_PROCSYS:
fh = cnew (fhandler_procsys) ();
break;
case FH_NETDRIVE:
fh = cnew (fhandler_netdrive) ();
break;

View File

@ -34,7 +34,9 @@ extern const char *windows_device_names[];
extern struct __cygwin_perfile *perfile_table;
#define __fmode (*(user_data->fmode_ptr))
extern const char proc[];
extern const int proc_len;
extern const size_t proc_len;
extern const char procsys[];
extern const size_t procsys_len;
class select_record;
class select_stuff;
@ -99,6 +101,20 @@ enum del_lock_called_from {
after_exec
};
enum virtual_ftype_t {
virt_blk = -7, /* Block special */
virt_chr = -6, /* Character special */
virt_fsfile = -5, /* FS-based file via /proc/sys */
virt_socket = -4, /* Socket */
virt_pipe = -3, /* Pipe */
virt_symlink = -2, /* Symlink */
virt_file = -1, /* Regular file */
virt_none = 0, /* Invalid, Error */
virt_directory = 1, /* Directory */
virt_rootdir = 2, /* Root directory of virtual FS */
virt_fsdir = 3, /* FS-based directory via /proc/sys */
};
class fhandler_base
{
friend class dtable;
@ -1331,7 +1347,7 @@ class fhandler_virtual : public fhandler_base
fhandler_virtual ();
virtual ~fhandler_virtual();
virtual int exists();
virtual virtual_ftype_t exists();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
long telldir (DIR *);
void seekdir (DIR *, long);
@ -1357,7 +1373,7 @@ class fhandler_proc: public fhandler_virtual
{
public:
fhandler_proc ();
int exists();
virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
static DWORD get_proc_fhandler(const char *path);
@ -1366,11 +1382,30 @@ class fhandler_proc: public fhandler_virtual
bool fill_filebuf ();
};
class fhandler_procsys: public fhandler_virtual
{
public:
fhandler_procsys ();
virtual_ftype_t exists(struct __stat64 *buf) __attribute__ ((regparm (2)));
virtual_ftype_t exists();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
long telldir (DIR *);
void seekdir (DIR *, long);
int closedir (DIR *);
int open (int flags, mode_t mode = 0);
int close ();
void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3)));
ssize_t __stdcall write (const void *ptr, size_t len);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
bool fill_filebuf ();
};
class fhandler_netdrive: public fhandler_virtual
{
public:
fhandler_netdrive ();
int exists();
virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
void seekdir (DIR *, long);
void rewinddir (DIR *);
@ -1388,7 +1423,7 @@ class fhandler_registry: public fhandler_proc
public:
fhandler_registry ();
void set_name (path_conv &pc);
int exists();
virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
long telldir (DIR *);
void seekdir (DIR *, long);
@ -1408,7 +1443,7 @@ class fhandler_process: public fhandler_proc
pid_t pid;
public:
fhandler_process ();
int exists();
virtual_ftype_t exists();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0);
@ -1421,7 +1456,7 @@ class fhandler_procnet: public fhandler_proc
pid_t pid;
public:
fhandler_procnet ();
int exists();
virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
@ -1462,6 +1497,8 @@ typedef union
char __pipe[sizeof (fhandler_pipe)];
char __proc[sizeof (fhandler_proc)];
char __process[sizeof (fhandler_process)];
char __procnet[sizeof (fhandler_procnet)];
char __procsys[sizeof (fhandler_procsys)];
char __pty_master[sizeof (fhandler_pty_master)];
char __registry[sizeof (fhandler_registry)];
char __serial[sizeof (fhandler_serial)];

View File

@ -118,7 +118,7 @@ public:
{
found[__DIR_PROC] = true;
if (retname)
RtlInitUnicodeString (retname, L"proc");
*retname = ro_u_proc;
return 2;
}
if (!found[__DIR_CYGDRIVE])
@ -407,7 +407,9 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
fi.fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (fi.fbi.FileAttributes);
/* Only copy attributes if not a device root dir. */
if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE))
pc.file_attributes (fi.fbi.FileAttributes);
return fstat_helper (buf,
fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime
: &fi.fbi.LastWriteTime,
@ -474,7 +476,9 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (fdi_buf.fdi.FileAttributes);
/* Only copy attributes if not a device root dir. */
if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE))
pc.file_attributes (fdi_buf.fdi.FileAttributes);
return fstat_helper (buf,
fdi_buf.fdi.ChangeTime.QuadPart
? &fdi_buf.fdi.ChangeTime : &fdi_buf.fdi.LastWriteTime,

View File

@ -145,14 +145,14 @@ create_thread_and_wait (int what, PVOID in, PVOID out, DWORD outsize,
/* Returns 0 if path doesn't exist, >0 if path is a directory,
-1 if path is a file, -2 if it's a symlink. */
int
virtual_ftype_t
fhandler_netdrive::exists ()
{
char *to;
const char *from;
size_t len = strlen (get_name ());
if (len == 2)
return 1;
return virt_rootdir;
char namebuf[len + 1];
for (to = namebuf, from = get_name (); *from; to++, from++)
*to = (*from == '/') ? '\\' : *from;
@ -166,7 +166,7 @@ fhandler_netdrive::exists ()
&nr, &nh, 0, "WNetOpenEnum");
if (nh.dom)
WNetCloseEnum (nh.dom);
return ret != NO_ERROR ? 0 : 1;
return ret != NO_ERROR ? virt_none : virt_directory;
}
fhandler_netdrive::fhandler_netdrive ():

View File

@ -46,23 +46,24 @@ static _off64_t format_proc_filesystems (void *, char *&);
/* names of objects in /proc */
static const virt_tab_t proc_tab[] = {
{ ".", FH_PROC, virt_directory, NULL },
{ "..", FH_PROC, virt_directory, NULL },
{ "loadavg", FH_PROC, virt_file, format_proc_loadavg },
{ "meminfo", FH_PROC, virt_file, format_proc_meminfo },
{ "registry", FH_REGISTRY, virt_directory, NULL },
{ "stat", FH_PROC, virt_file, format_proc_stat },
{ "version", FH_PROC, virt_file, format_proc_version },
{ "uptime", FH_PROC, virt_file, format_proc_uptime },
{ "cpuinfo", FH_PROC, virt_file, format_proc_cpuinfo },
{ "partitions", FH_PROC, virt_file, format_proc_partitions },
{ "self", FH_PROC, virt_symlink, format_proc_self },
{ "mounts", FH_PROC, virt_symlink, format_proc_mounts },
{ "registry32", FH_REGISTRY, virt_directory, NULL },
{ "registry64", FH_REGISTRY, virt_directory, NULL },
{ "net", FH_PROCNET, virt_directory, NULL },
{ "filesystems", FH_PROC, virt_file, format_proc_filesystems },
{ NULL, 0, virt_none, NULL }
{ _VN ("."), FH_PROC, virt_directory, NULL },
{ _VN (".."), FH_PROC, virt_directory, NULL },
{ _VN ("cpuinfo"), FH_PROC, virt_file, format_proc_cpuinfo },
{ _VN ("filesystems"), FH_PROC, virt_file, format_proc_filesystems },
{ _VN ("loadavg"), FH_PROC, virt_file, format_proc_loadavg },
{ _VN ("meminfo"), FH_PROC, virt_file, format_proc_meminfo },
{ _VN ("mounts"), FH_PROC, virt_symlink, format_proc_mounts },
{ _VN ("net"), FH_PROCNET, virt_directory, NULL },
{ _VN ("partitions"), FH_PROC, virt_file, format_proc_partitions },
{ _VN ("registry"), FH_REGISTRY, virt_directory, NULL },
{ _VN ("registry32"), FH_REGISTRY, virt_directory, NULL },
{ _VN ("registry64"), FH_REGISTRY, virt_directory, NULL },
{ _VN ("self"), FH_PROC, virt_symlink, format_proc_self },
{ _VN ("stat"), FH_PROC, virt_file, format_proc_stat },
{ _VN ("sys"), FH_PROCSYS, virt_directory, NULL },
{ _VN ("uptime"), FH_PROC, virt_file, format_proc_uptime },
{ _VN ("version"), FH_PROC, virt_file, format_proc_version },
{ NULL, 0, 0, virt_none, NULL }
};
#define PROC_DIR_COUNT 4
@ -71,11 +72,37 @@ static const int PROC_LINK_COUNT = (sizeof (proc_tab) / sizeof (virt_tab_t)) - 1
/* name of the /proc filesystem */
const char proc[] = "/proc";
const int proc_len = sizeof (proc) - 1;
const size_t proc_len = sizeof (proc) - 1;
/* Auxillary function that returns the fhandler associated with the given path
this is where it would be nice to have pattern matching in C - polymorphism
just doesn't cut it. */
/* bsearch compare function. */
static int
proc_tab_cmp (const void *key, const void *memb)
{
int ret = strncmp (((virt_tab_t *) key)->name, ((virt_tab_t *) memb)->name,
((virt_tab_t *) memb)->name_len);
if (!ret && ((virt_tab_t *) key)->name[((virt_tab_t *) memb)->name_len] != '\0' && ((virt_tab_t *) key)->name[((virt_tab_t *) memb)->name_len] != '/')
return 1;
return ret;
}
/* Helper function to perform a binary search of the incoming pathname
against the alpha-sorted virtual file table. */
virt_tab_t *
virt_tab_search (const char *path, bool prefix, const virt_tab_t *table,
size_t nelem)
{
virt_tab_t key = { path, 0, 0, virt_none, NULL };
virt_tab_t *entry = (virt_tab_t *) bsearch (&key, table, nelem,
sizeof (virt_tab_t),
proc_tab_cmp);
if (entry && (path[entry->name_len] == '\0'
|| (prefix && path[entry->name_len] == '/')))
return entry;
return NULL;
}
/* Auxillary function that returns the fhandler associated with the given
path. */
DWORD
fhandler_proc::get_proc_fhandler (const char *path)
{
@ -91,12 +118,10 @@ fhandler_proc::get_proc_fhandler (const char *path)
if (*path == 0)
return FH_PROC;
for (int i = 0; proc_tab[i].name; i++)
{
if (path_prefix_p (proc_tab[i].name, path, strlen (proc_tab[i].name),
false))
return proc_tab[i].fhandler;
}
virt_tab_t *entry = virt_tab_search (path, true, proc_tab,
PROC_LINK_COUNT);
if (entry)
return entry->fhandler;
if (pinfo (atoi (path)))
return FH_PROCESS;
@ -120,7 +145,7 @@ fhandler_proc::get_proc_fhandler (const char *path)
/* Returns 0 if path doesn't exist, >0 if path is a directory,
-1 if path is a file, -2 if it's a symlink. */
int
virtual_ftype_t
fhandler_proc::exists ()
{
const char *path = get_name ();
@ -128,12 +153,13 @@ fhandler_proc::exists ()
path += proc_len;
if (*path == 0)
return virt_rootdir;
for (int i = 0; proc_tab[i].name; i++)
if (!strcmp (path + 1, proc_tab[i].name))
{
fileid = i;
return proc_tab[i].type;
}
virt_tab_t *entry = virt_tab_search (path + 1, false, proc_tab,
PROC_LINK_COUNT);
if (entry)
{
fileid = entry - proc_tab;
return entry->type;
}
return virt_none;
}
@ -163,21 +189,21 @@ fhandler_proc::fstat (struct __stat64 *buf)
}
else
{
path++;
for (int i = 0; proc_tab[i].name; i++)
if (!strcmp (path, proc_tab[i].name))
{
if (proc_tab[i].type == virt_directory)
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
else if (proc_tab[i].type == virt_symlink)
buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
else
{
buf->st_mode &= NO_X;
buf->st_mode |= S_IFREG;
}
return 0;
}
virt_tab_t *entry = virt_tab_search (path + 1, false, proc_tab,
PROC_LINK_COUNT);
if (entry)
{
if (entry->type == virt_directory)
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
else if (entry->type == virt_symlink)
buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
else
{
buf->st_mode &= NO_X;
buf->st_mode |= S_IFREG;
}
return 0;
}
}
set_errno (ENOENT);
return -1;

View File

@ -53,28 +53,28 @@ static _off64_t format_process_mounts (void *, char *&);
static const virt_tab_t process_tab[] =
{
{ ".", FH_PROCESS, virt_directory, NULL },
{ "..", FH_PROCESS, virt_directory, NULL },
{ "ppid", FH_PROCESS, virt_file, format_process_ppid },
{ "winpid", FH_PROCESS, virt_file, format_process_winpid },
{ "winexename", FH_PROCESS, virt_file, format_process_winexename },
{ "status", FH_PROCESS, virt_file, format_process_status },
{ "uid", FH_PROCESS, virt_file, format_process_uid },
{ "gid", FH_PROCESS, virt_file, format_process_gid },
{ "pgid", FH_PROCESS, virt_file, format_process_pgid },
{ "sid", FH_PROCESS, virt_file, format_process_sid },
{ "ctty", FH_PROCESS, virt_file, format_process_ctty },
{ "stat", FH_PROCESS, virt_file, format_process_stat },
{ "statm", FH_PROCESS, virt_file, format_process_statm },
{ "cmdline", FH_PROCESS, virt_file, format_process_cmdline },
{ "maps", FH_PROCESS, virt_file, format_process_maps },
{ "fd", FH_PROCESSFD, virt_directory, format_process_fd },
{ "exename", FH_PROCESS, virt_file, format_process_exename },
{ "root", FH_PROCESS, virt_symlink, format_process_root },
{ "exe", FH_PROCESS, virt_symlink, format_process_exename },
{ "cwd", FH_PROCESS, virt_symlink, format_process_cwd },
{ "mounts", FH_PROCESS, virt_file, format_process_mounts },
{ NULL, 0, virt_none, NULL }
{ _VN ("."), FH_PROCESS, virt_directory, NULL },
{ _VN (".."), FH_PROCESS, virt_directory, NULL },
{ _VN ("cmdline"), FH_PROCESS, virt_file, format_process_cmdline },
{ _VN ("ctty"), FH_PROCESS, virt_file, format_process_ctty },
{ _VN ("cwd"), FH_PROCESS, virt_symlink, format_process_cwd },
{ _VN ("exe"), FH_PROCESS, virt_symlink, format_process_exename },
{ _VN ("exename"), FH_PROCESS, virt_file, format_process_exename },
{ _VN ("fd"), FH_PROCESSFD, virt_directory, format_process_fd },
{ _VN ("gid"), FH_PROCESS, virt_file, format_process_gid },
{ _VN ("maps"), FH_PROCESS, virt_file, format_process_maps },
{ _VN ("mounts"), FH_PROCESS, virt_file, format_process_mounts },
{ _VN ("pgid"), FH_PROCESS, virt_file, format_process_pgid },
{ _VN ("ppid"), FH_PROCESS, virt_file, format_process_ppid },
{ _VN ("root"), FH_PROCESS, virt_symlink, format_process_root },
{ _VN ("sid"), FH_PROCESS, virt_file, format_process_sid },
{ _VN ("stat"), FH_PROCESS, virt_file, format_process_stat },
{ _VN ("statm"), FH_PROCESS, virt_file, format_process_statm },
{ _VN ("status"), FH_PROCESS, virt_file, format_process_status },
{ _VN ("uid"), FH_PROCESS, virt_file, format_process_uid },
{ _VN ("winexename"), FH_PROCESS, virt_file, format_process_winexename },
{ _VN ("winpid"), FH_PROCESS, virt_file, format_process_winpid },
{ NULL, 0, 0, virt_none, NULL }
};
static const int PROCESS_LINK_COUNT =
@ -90,7 +90,7 @@ static bool get_mem_values (DWORD dwProcessId, unsigned long *vmsize,
* -1 if path is a file, -2 if path is a symlink, -3 if path is a pipe,
* -4 if path is a socket.
*/
int
virtual_ftype_t
fhandler_process::exists ()
{
const char *path = get_name ();
@ -99,21 +99,20 @@ fhandler_process::exists ()
while (*path != 0 && !isdirsep (*path))
path++;
if (*path == 0)
return 2;
return virt_rootdir;
for (int i = 0; process_tab[i].name; i++)
virt_tab_t *entry = virt_tab_search (path + 1, true, process_tab,
PROCESS_LINK_COUNT);
if (entry)
{
if (!strcmp (path + 1, process_tab[i].name))
if (!path[entry->name_len + 1])
{
fileid = i;
return process_tab[i].type;
fileid = entry - process_tab;
return entry->type;
}
if (process_tab[i].type == virt_directory
&& !strncmp (path + 1, process_tab[i].name,
strlen (process_tab[i].name))
&& path[1 + strlen (process_tab[i].name)] == '/')
if (entry->type == virt_directory)
{
fileid = i;
fileid = entry - process_tab;
if (fill_filebuf ())
return virt_symlink;
/* Check for nameless device entries. */
@ -232,8 +231,6 @@ out:
int
fhandler_process::open (int flags, mode_t mode)
{
int process_file_no = -1;
int res = fhandler_virtual::open (flags, mode);
if (!res)
goto out;
@ -267,29 +264,15 @@ fhandler_process::open (int flags, mode_t mode)
}
}
process_file_no = -1;
for (int i = 0; process_tab[i].name; i++)
virt_tab_t *entry;
entry = virt_tab_search (path + 1, true, process_tab, PROCESS_LINK_COUNT);
if (!entry)
{
if (path_prefix_p (process_tab[i].name, path + 1,
strlen (process_tab[i].name), false))
process_file_no = i;
set_errno ((flags & O_CREAT) ? EROFS : ENOENT);
res = 0;
goto out;
}
if (process_file_no == -1)
{
if (flags & O_CREAT)
{
set_errno (EROFS);
res = 0;
goto out;
}
else
{
set_errno (ENOENT);
res = 0;
goto out;
}
}
if (process_tab[process_file_no].fhandler == FH_PROCESSFD)
if (entry->fhandler == FH_PROCESSFD)
{
flags |= O_DIROPEN;
goto success;
@ -301,7 +284,7 @@ fhandler_process::open (int flags, mode_t mode)
goto out;
}
fileid = process_file_no;
fileid = entry - process_tab;
if (!fill_filebuf ())
{
res = 0;

View File

@ -39,10 +39,10 @@ static _off64_t format_procnet_ifinet6 (void *, char *&);
static const virt_tab_t procnet_tab[] =
{
{ ".", FH_PROCNET, virt_directory, NULL },
{ "..", FH_PROCNET, virt_directory, NULL },
{ "if_inet6", FH_PROCNET, virt_file, format_procnet_ifinet6 },
{ NULL, 0, virt_none, NULL }
{ _VN ("."), FH_PROCNET, virt_directory, NULL },
{ _VN (".."), FH_PROCNET, virt_directory, NULL },
{ _VN ("if_inet6"), FH_PROCNET, virt_file, format_procnet_ifinet6 },
{ NULL, 0, 0, virt_none, NULL }
};
static const int PROCNET_LINK_COUNT =
@ -52,7 +52,7 @@ static const int PROCNET_LINK_COUNT =
* -1 if path is a file, -2 if path is a symlink, -3 if path is a pipe,
* -4 if path is a socket.
*/
int
virtual_ftype_t
fhandler_procnet::exists ()
{
const char *path = get_name ();
@ -61,20 +61,21 @@ fhandler_procnet::exists ()
while (*path != 0 && !isdirsep (*path))
path++;
if (*path == 0)
return 1;
return virt_rootdir;
for (int i = 0; procnet_tab[i].name; i++)
if (!strcmp (path + 1, procnet_tab[i].name))
{
if (procnet_tab[i].type == virt_file)
{
if (!wincap.has_gaa_prefixes ()
|| !get_adapters_addresses (NULL, AF_INET6))
return virt_none;
}
fileid = i;
return procnet_tab[i].type;
}
virt_tab_t *entry = virt_tab_search (path + 1, false, procnet_tab,
PROCNET_LINK_COUNT);
if (entry)
{
if (entry->type == virt_file)
{
if (!wincap.has_gaa_prefixes ()
|| !get_adapters_addresses (NULL, AF_INET6))
return virt_none;
}
fileid = entry - procnet_tab;
return entry->type;
}
return virt_none;
}
@ -129,8 +130,6 @@ out:
int
fhandler_procnet::open (int flags, mode_t mode)
{
int process_file_no = -1;
int res = fhandler_virtual::open (flags, mode);
if (!res)
goto out;
@ -163,27 +162,13 @@ fhandler_procnet::open (int flags, mode_t mode)
}
}
process_file_no = -1;
for (int i = 0; procnet_tab[i].name; i++)
virt_tab_t *entry;
entry = virt_tab_search (path + 1, true, procnet_tab, PROCNET_LINK_COUNT);
if (!entry)
{
if (path_prefix_p (procnet_tab[i].name, path + 1,
strlen (procnet_tab[i].name), false))
process_file_no = i;
}
if (process_file_no == -1)
{
if (flags & O_CREAT)
{
set_errno (EROFS);
res = 0;
goto out;
}
else
{
set_errno (ENOENT);
res = 0;
goto out;
}
set_errno ((flags & O_CREAT) ? EROFS : ENOENT);
res = 0;
goto out;
}
if (flags & O_WRONLY)
{
@ -192,7 +177,7 @@ fhandler_procnet::open (int flags, mode_t mode)
goto out;
}
fileid = process_file_no;
fileid = entry - procnet_tab;
if (!fill_filebuf ())
{
res = 0;

View File

@ -0,0 +1,422 @@
/* fhandler_procsys.cc: fhandler for native NT namespace.
Copyright 2010 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 "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include <winioctl.h>
#include "ntdll.h"
#include "tls_pbuf.h"
#include <dirent.h>
/* Path of the /proc/sys filesystem */
const char procsys[] = "/proc/sys";
const size_t procsys_len = sizeof (procsys) - 1;
#define mk_unicode_path(p) \
WCHAR namebuf[strlen (get_name ()) + 1]; \
{ \
const char *from; \
PWCHAR to; \
for (to = namebuf, from = get_name () + procsys_len; *from; \
to++, from++) \
/* The NT device namespace is ASCII only. */ \
*to = (*from == '/') ? L'\\' : (WCHAR) *from; \
if (to == namebuf) \
*to++ = L'\\'; \
*to = L'\0'; \
RtlInitUnicodeString ((p), namebuf); \
}
/* Returns 0 if path doesn't exist, >0 if path is a directory,
-1 if path is a file, -2 if it's a symlink. */
virtual_ftype_t
fhandler_procsys::exists (struct __stat64 *buf)
{
UNICODE_STRING path; \
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE h;
FILE_BASIC_INFORMATION fbi;
virtual_ftype_t file_type = virt_chr;
if (strlen (get_name ()) == procsys_len)
return virt_rootdir;
mk_unicode_path (&path);
/* First try to open as file/device to get more info. */
InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
if (status == STATUS_OBJECT_PATH_NOT_FOUND)
return virt_none;
/* If the name isn't found, or we get this dreaded sharing violation, let
the caller try again as normal file. */
if (status == STATUS_OBJECT_NAME_NOT_FOUND
|| status == STATUS_NO_MEDIA_IN_DEVICE
|| status == STATUS_SHARING_VIOLATION)
return virt_fsfile; /* Just try again as normal file. */
/* Check for pipe errors, which make a good hint... */
if (status >= STATUS_PIPE_NOT_AVAILABLE && status <= STATUS_PIPE_BUSY)
file_type = virt_pipe;
else if (status == STATUS_ACCESS_DENIED)
{
/* Check if this is just some file or dir on a real FS to circumvent
most permission problems. */
status = NtQueryAttributesFile (&attr, &fbi);
if (NT_SUCCESS (status))
return (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
? virt_fsdir : virt_fsfile;
}
else if (NT_SUCCESS (status))
{
NTSTATUS dev_stat;
FILE_FS_DEVICE_INFORMATION ffdi;
/* If requested, check permissions. */
if (buf)
get_object_attribute (h, &buf->st_uid, &buf->st_gid, &buf->st_mode);
/* Check for the device type. */
dev_stat = NtQueryVolumeInformationFile (h, &io, &ffdi, sizeof ffdi,
FileFsDeviceInformation);
/* And check for file attributes. If we get them, we peeked into
a real FS through /proc/sys. */
status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
FileBasicInformation);
NtClose (h);
if (NT_SUCCESS (dev_stat))
{
if (ffdi.DeviceType == FILE_DEVICE_NAMED_PIPE)
file_type = NT_SUCCESS (status) ? virt_pipe : virt_blk;
else if (NT_SUCCESS (status))
file_type = (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
? virt_fsdir : virt_fsfile;
else if (ffdi.DeviceType == FILE_DEVICE_DISK
|| ffdi.DeviceType == FILE_DEVICE_CD_ROM
|| ffdi.DeviceType == FILE_DEVICE_DFS
|| ffdi.DeviceType == FILE_DEVICE_VIRTUAL_DISK)
file_type = virt_blk;
}
}
/* Then check if it's a symlink. */
status = NtOpenSymbolicLinkObject (&h, READ_CONTROL | SYMBOLIC_LINK_QUERY,
&attr);
if (NT_SUCCESS (status))
{
/* If requested, check permissions. */
if (buf)
get_object_attribute (h, &buf->st_uid, &buf->st_gid, &buf->st_mode);
NtClose (h);
return virt_symlink;
}
/* Eventually, test if it's an object directory. */
status = NtOpenDirectoryObject (&h, READ_CONTROL | DIRECTORY_QUERY, &attr);
if (NT_SUCCESS (status))
{
/* If requested, check permissions. */
if (buf)
get_object_attribute (h, &buf->st_uid, &buf->st_gid, &buf->st_mode);
NtClose (h);
return virt_directory;
}
else if (status == STATUS_ACCESS_DENIED)
return virt_directory;
/* Give up. Just treat as character device. */
return file_type;
}
virtual_ftype_t
fhandler_procsys::exists ()
{
return exists (NULL);
}
fhandler_procsys::fhandler_procsys ():
fhandler_virtual ()
{
}
bool
fhandler_procsys::fill_filebuf ()
{
/* The NT device namespace is ASCII only. */
char *fnamep;
UNICODE_STRING path, target;
OBJECT_ATTRIBUTES attr;
NTSTATUS status;
HANDLE h;
tmp_pathbuf tp;
mk_unicode_path (&path);
if (path.Buffer[path.Length / sizeof (WCHAR) - 1] == L'\\')
path.Length -= sizeof (WCHAR);
InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY, &attr);
if (!NT_SUCCESS (status))
return false;
RtlInitEmptyUnicodeString (&target, tp.w_get (),
(NT_MAX_PATH - 1) * sizeof (WCHAR));
status = NtQuerySymbolicLinkObject (h, &target, NULL);
NtClose (h);
if (!NT_SUCCESS (status))
return false;
size_t len = sys_wcstombs (NULL, 0, target.Buffer,
target.Length / sizeof (WCHAR));
filebuf = (char *) crealloc_abort (filebuf, procsys_len + len + 1);
sys_wcstombs (fnamep = stpcpy (filebuf, procsys), len + 1, target.Buffer,
target.Length / sizeof (WCHAR));
while ((fnamep = strchr (fnamep, '\\')))
*fnamep = '/';
return true;
}
int
fhandler_procsys::fstat (struct __stat64 *buf)
{
const char *path = get_name ();
debug_printf ("fstat (%s)", path);
fhandler_base::fstat (buf);
/* Best bet. */
buf->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
buf->st_uid = 544;
buf->st_gid = 18;
buf->st_dev = buf->st_rdev = dev ().devn;
buf->st_ino = get_ino ();
switch (exists (buf))
{
case virt_directory:
case virt_rootdir:
case virt_fsdir:
buf->st_mode |= S_IFDIR;
if (buf->st_mode & S_IRUSR)
buf->st_mode |= S_IXUSR;
if (buf->st_mode & S_IRGRP)
buf->st_mode |= S_IXGRP;
if (buf->st_mode & S_IROTH)
buf->st_mode |= S_IXOTH;
break;
case virt_file:
case virt_fsfile:
buf->st_mode |= S_IFREG;
break;
case virt_symlink:
buf->st_mode |= S_IFLNK;
break;
case virt_pipe:
buf->st_mode |= S_IFIFO;
break;
case virt_socket:
buf->st_mode |= S_IFSOCK;
break;
case virt_chr:
buf->st_mode |= S_IFCHR;
break;
case virt_blk:
buf->st_mode |= S_IFBLK;
break;
default:
set_errno (ENOENT);
return -1;
}
return 0;
}
DIR *
fhandler_procsys::opendir (int fd)
{
UNICODE_STRING path;
OBJECT_ATTRIBUTES attr;
NTSTATUS status;
HANDLE h;
DIR *dir = fhandler_virtual::opendir (fd);
mk_unicode_path (&path);
InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenDirectoryObject (&h, DIRECTORY_QUERY, &attr);
if (!NT_SUCCESS (status))
{
free (dir);
__seterrno_from_nt_status (status);
return NULL;
}
dir->__handle = h;
return dir;
}
int
fhandler_procsys::readdir (DIR *dir, dirent *de)
{
NTSTATUS status;
struct fdbi
{
DIRECTORY_BASIC_INFORMATION dbi;
WCHAR buf[2][NAME_MAX + 1];
} f;
int res = EBADF;
if (dir->__handle != INVALID_HANDLE_VALUE)
{
BOOLEAN restart = dir->__d_position ? FALSE : TRUE;
status = NtQueryDirectoryObject (dir->__handle, &f, sizeof f, TRUE,
restart, (PULONG) &dir->__d_position,
NULL);
if (!NT_SUCCESS (status))
res = ENMFILE;
else
{
sys_wcstombs (de->d_name, NAME_MAX + 1, f.dbi.ObjectName.Buffer,
f.dbi.ObjectName.Length / sizeof (WCHAR));
de->d_ino = hash_path_name (get_ino (), de->d_name);
de->d_type = 0;
res = 0;
}
}
syscall_printf ("%d = readdir (%p, %p)", res, dir, de);
return res;
}
long
fhandler_procsys::telldir (DIR *dir)
{
return dir->__d_position;
}
void
fhandler_procsys::seekdir (DIR *dir, long pos)
{
dir->__d_position = pos;
}
int
fhandler_procsys::closedir (DIR *dir)
{
if (dir->__handle != INVALID_HANDLE_VALUE)
{
NtClose (dir->__handle);
dir->__handle = INVALID_HANDLE_VALUE;
}
return fhandler_virtual::closedir (dir);
}
void __stdcall
fhandler_procsys::read (void *ptr, size_t& len)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
LARGE_INTEGER off = { QuadPart:0LL };
status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, ptr, len,
&off, NULL);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
len = -1;
}
else
len = io.Information;
}
ssize_t __stdcall
fhandler_procsys::write (const void *ptr, size_t len)
{
return fhandler_base::raw_write (ptr, len);
}
int
fhandler_procsys::open (int flags, mode_t mode)
{
UNICODE_STRING path;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE h;
ULONG access;
ULONG options = FILE_OPEN_FOR_BACKUP_INTENT;
int res = fhandler_virtual::open (flags, mode);
if (!res)
goto out;
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) || (flags & O_TRUNC))
{
set_errno (EINVAL);
res = 0;
goto out;
}
mk_unicode_path (&path);
InitializeObjectAttributes (&attr, &path, OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
NULL, NULL);
switch (exists ())
{
case virt_directory:
case virt_rootdir:
if ((flags & O_ACCMODE) != O_RDONLY)
{
set_errno (EISDIR);
res = 0;
goto out;
}
nohandle (true);
res = 1;
goto out;
default:
break;
}
if ((flags & O_ACCMODE) == O_RDONLY)
access = GENERIC_READ;
else if ((flags & O_ACCMODE) == O_WRONLY)
access = GENERIC_WRITE | READ_CONTROL | FILE_READ_ATTRIBUTES;
else
access = GENERIC_READ | GENERIC_WRITE;
if (flags & O_SYNC)
options |= FILE_WRITE_THROUGH;
if (flags & O_DIRECT)
options |= FILE_NO_INTERMEDIATE_BUFFERING;
if (!(flags & O_NONBLOCK))
{
access |= SYNCHRONIZE;
options |= FILE_SYNCHRONOUS_IO_NONALERT;
}
status = NtOpenFile (&h, access, &attr, &io, FILE_SHARE_VALID_FLAGS, options);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
res = 0;
goto out;
}
set_io_handle (h);
set_open_status ();
res = 1;
out:
syscall_printf ("%d = fhandler_procsys::open (%p, %d)", res, flags, mode);
return res;
}
int
fhandler_procsys::close ()
{
if (!nohandle ())
NtClose (get_handle ());
return fhandler_virtual::close ();
}
#if 0
int
fhandler_procsys::ioctl (unsigned int cmd, void *)
{
}
#endif

View File

@ -268,10 +268,11 @@ multi_wcstombs (char *dst, size_t len, const wchar_t *src, size_t nwc)
* final component is there. This gets round the problem of not having security access
* to the final key in the path.
*/
int
virtual_ftype_t
fhandler_registry::exists ()
{
int file_type = 0, index = 0, pathlen;
virtual_ftype_t file_type = virt_none;
int index = 0, pathlen;
DWORD buf_size = NAME_MAX + 1;
LONG error;
wchar_t buf[buf_size];
@ -285,7 +286,7 @@ fhandler_registry::exists ()
path++;
else
{
file_type = 2;
file_type = virt_rootdir;
goto out;
}
pathlen = strlen (path);
@ -302,7 +303,7 @@ fhandler_registry::exists ()
if (path_prefix_p (registry_listing[i], path,
strlen (registry_listing[i]), true))
{
file_type = 1;
file_type = virt_directory;
break;
}
}
@ -317,12 +318,12 @@ fhandler_registry::exists ()
if (!val_only)
hKey = open_key (path, KEY_READ, wow64, false);
if (hKey != (HKEY) INVALID_HANDLE_VALUE || get_errno () == EACCES)
file_type = 1;
file_type = virt_directory;
else
{
hKey = open_key (path, KEY_READ, wow64, true);
if (hKey == (HKEY) INVALID_HANDLE_VALUE)
return 0;
return virt_none;
if (hKey == HKEY_PERFORMANCE_DATA)
{
@ -332,13 +333,14 @@ fhandler_registry::exists ()
So allow access to the generic names and to
(blank separated) lists of counter numbers.
Never allow access to "Add", see above comment. */
for (int i = 0; i < PERF_DATA_FILE_COUNT && file_type == 0; i++)
for (int i = 0; i < PERF_DATA_FILE_COUNT
&& file_type == virt_none; i++)
{
if (strcasematch (perf_data_files[i], file))
file_type = -1;
file_type = virt_file;
}
if (file_type == 0 && !file[strspn (file, " 0123456789")])
file_type = -1;
if (file_type == virt_none && !file[strspn (file, " 0123456789")])
file_type = virt_file;
goto out;
}
@ -351,7 +353,7 @@ fhandler_registry::exists ()
{
if (!wcscasecmp (buf, dec_file))
{
file_type = 1;
file_type = virt_directory;
goto out;
}
buf_size = NAME_MAX + 1;
@ -372,7 +374,7 @@ fhandler_registry::exists ()
{
if (!wcscasecmp (buf, dec_file))
{
file_type = -1;
file_type = virt_file;
goto out;
}
buf_size = NAME_MAX + 1;
@ -418,32 +420,32 @@ fhandler_registry::fstat (struct __stat64 *buf)
{
fhandler_base::fstat (buf);
buf->st_mode &= ~_IFMT & NO_W;
int file_type = exists ();
virtual_ftype_t file_type = exists ();
switch (file_type)
{
case 0:
case virt_none:
set_errno (ENOENT);
return -1;
case 1:
case virt_directory:
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
break;
case 2:
case virt_rootdir:
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = ROOT_KEY_COUNT;
break;
default:
case -1:
case virt_file:
buf->st_mode |= S_IFREG;
buf->st_mode &= NO_X;
break;
}
if (file_type != 0 && file_type != 2)
if (file_type != virt_none && file_type != virt_rootdir)
{
HKEY hKey;
const char *path = get_name () + proc_len + prefix_len + 2;
hKey =
open_key (path, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, wow64,
(file_type < 0) ? true : false);
(file_type < virt_none) ? true : false);
if (hKey == HKEY_PERFORMANCE_DATA)
/* RegQueryInfoKey () always returns write time 0,
@ -461,7 +463,7 @@ fhandler_registry::fstat (struct __stat64 *buf)
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
buf->st_ctim = buf->st_birthtim = buf->st_mtim;
time_as_timestruc_t (&buf->st_atim);
if (file_type > 0)
if (file_type > virt_none)
buf->st_nlink = subkey_count + 2;
else
{
@ -508,7 +510,7 @@ fhandler_registry::fstat (struct __stat64 *buf)
buf->st_uid = uid;
buf->st_gid = gid;
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
if (file_type > 0)
if (file_type > virt_none)
buf->st_mode |= S_IFDIR;
else
buf->st_mode &= NO_X;

View File

@ -225,10 +225,10 @@ fhandler_virtual::open (int flags, mode_t mode)
return 1;
}
int
virtual_ftype_t
fhandler_virtual::exists ()
{
return 0;
return virt_none;
}
bool

View File

@ -1,6 +1,6 @@
/* fhandler_virtual.h: Header for virtual fhandlers
Copyright 2009 Red Hat, Inc.
Copyright 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@ -8,20 +8,15 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
enum virtual_ftype_t {
virt_socket = -4,
virt_pipe = -3,
virt_symlink = -2,
virt_file = -1,
virt_none = 0,
virt_directory = 1,
virt_rootdir = 2
};
struct virt_tab_t {
const char *name;
size_t name_len;
__dev32_t fhandler;
virtual_ftype_t type;
_off64_t (*format_func)(void *data, char *&);
};
#define _VN(s) s, sizeof (s) - 1
extern virt_tab_t *virt_tab_search (const char *, bool, const virt_tab_t *,
size_t);

View File

@ -520,7 +520,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
}
MALLOC_CHECK;
/* If the path is on a network drive or a //./ resp.//?/ path prefix,
/* If the path is on a network drive or a //./ resp. //?/ path prefix,
bypass the mount table. If it's // or //MACHINE, use the netdrive
device. */
if (src_path[1] == '/')
@ -550,7 +550,16 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
if (dev.devn == FH_BAD)
return ENOENT;
set_flags (flags, PATH_BINARY);
strcpy (dst, src_path);
if (isprocsys_dev (dev.devn))
{
if (src_path[procsys_len])
backslashify (src_path + procsys_len, dst, 0);
else /* Avoid empty NT path. */
stpcpy (dst, "\\");
set_flags (flags, (unsigned) cygdrive_flags);
}
else
strcpy (dst, src_path);
goto out;
}
/* Check if the cygdrive prefix was specified. If so, just strip

View File

@ -28,6 +28,7 @@
#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
#define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xc0000024)
#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xc0000033)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
@ -40,6 +41,10 @@
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
#define STATUS_DISK_FULL ((NTSTATUS) 0xc000007f)
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
#define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS) 0xc00000ab)
#define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS) 0xc00000ac)
#define STATUS_INVALID_PIPE_STATE ((NTSTATUS) 0xc00000ad)
#define STATUS_PIPE_BUSY ((NTSTATUS) 0xc00000ae)
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xc00000bb)
#define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xc00000be)
#define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xc00000c3)
@ -208,6 +213,8 @@ typedef struct _FILE_ID_BOTH_DIR_INFORMATION
#define DIRECTORY_CREATE_SUBDIRECTORY 8
#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|0x0f)
#define SYMBOLIC_LINK_QUERY 1
#define EVENT_QUERY_STATE 1
#define SEMAPHORE_QUERY_STATE 1
@ -927,6 +934,8 @@ extern "C"
NTSTATUS NTAPI NtOpenMutant (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtOpenSemaphore (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtOpenSymbolicLinkObject (PHANDLE, ACCESS_MASK,
POBJECT_ATTRIBUTES);
/* WARNING! Don't rely on the timestamp information returned by
NtQueryAttributesFile. Only the DOS file attribute info is reliable. */
NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES,
@ -956,6 +965,7 @@ extern "C"
NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, ULONG, PULONG);
NTSTATUS NTAPI NtQuerySymbolicLinkObject (HANDLE, PUNICODE_STRING, PULONG);
NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *,

View File

@ -761,8 +761,8 @@ path_conv::check (const char *src, unsigned opt,
{
/* FIXME: Calling build_fhandler here is not the right way to handle this. */
fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy);
int file_type = fh->exists ();
if (file_type == -2)
virtual_ftype_t file_type = fh->exists ();
if (file_type == virt_symlink)
{
fh->fill_filebuf ();
symlen = sym.set (fh->get_filebuf ());
@ -770,31 +770,61 @@ path_conv::check (const char *src, unsigned opt,
delete fh;
switch (file_type)
{
case 1:
case 2:
case virt_directory:
case virt_rootdir:
if (component == 0)
fileattr = FILE_ATTRIBUTE_DIRECTORY;
break;
case -1:
case virt_file:
if (component == 0)
fileattr = 0;
break;
case -2: /* /proc/self or /proc/<pid>/symlinks */
case virt_symlink:
goto is_virtual_symlink;
case -3: /* /proc/<pid>/fd/pipe:[] */
case virt_pipe:
if (component == 0)
{
fileattr = 0;
dev.parse (FH_PIPE);
}
break;
case -4: /* /proc/<pid>/fd/socket:[] */
case virt_socket:
if (component == 0)
{
fileattr = 0;
dev.parse (FH_TCP);
}
break;
case virt_fsdir:
case virt_fsfile:
/* Access to real file or directory via block device
entry in /proc/sys. Convert to real file and go with
the flow. */
dev.parse (FH_FS);
goto is_fs_via_procsys;
case virt_blk:
/* Block special device. If the trailing slash has been
requested, the target is the root directory of the
filesystem on this block device. So we convert this to
a real file and attach the backslash. */
if (component || need_directory)
{
dev.parse (FH_FS);
if (component == 0)
{
strcat (full_path, "\\");
fileattr = FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_DEVICE;
}
else
fileattr = 0;
goto out;
}
/*FALLTHRU*/
case virt_chr:
if (component == 0)
fileattr = FILE_ATTRIBUTE_DEVICE;
break;
default:
if (component == 0)
fileattr = INVALID_FILE_ATTRIBUTES;
@ -841,6 +871,8 @@ path_conv::check (const char *src, unsigned opt,
if (is_msdos)
sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
is_fs_via_procsys:
symlen = sym.check (full_path, suff, fs, conv_handle);
is_virtual_symlink:
@ -2850,6 +2882,14 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
if (buf[1] != ':') /* native UNC path */
*(buf += 2) = '\\';
}
else if (*buf == '\\')
{
/* Device name points to somewhere else in the NT namespace.
Use GLOBALROOT prefix to convert to Win32 path. */
char *p = stpcpy (buf, "\\\\.\\GLOBALROOT");
sys_wcstombs (p, NT_MAX_PATH - (p - buf),
up->Buffer, up->Length / sizeof (WCHAR));
}
lsiz = strlen (buf) + 1;
/* TODO: Incoming "." is a special case which leads to a trailing
backslash ".\\" in the Win32 path. That's a result of the
@ -2891,7 +2931,8 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
quite a bunch of Win32 functions, especially in user32.dll,
apparently, which don't grok long path names at all, not even
in the UNICODE API. */
if (lsiz <= MAX_PATH + 4 || (path[5] != L':' && lsiz <= MAX_PATH + 6))
if ((path[5] == L':' && lsiz <= MAX_PATH + 4)
|| (!wcsncmp (path + 4, L"UNC\\", 4) && lsiz <= MAX_PATH + 6))
{
path += 4;
lsiz -= 4;
@ -2902,6 +2943,13 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
}
}
}
else if (*path == L'\\')
{
/* Device name points to somewhere else in the NT namespace.
Use GLOBALROOT prefix to convert to Win32 path. */
to = (void *) wcpcpy ((wchar_t *) to, L"\\\\.\\GLOBALROOT");
lsiz += sizeof ("\\\\.\\GLOBALROOT") - 1;
}
/* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */
if (relative && !strcmp ((const char *) from, ".")
&& !wcscmp (path, L".\\"))
@ -2943,10 +2991,10 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
case CCP_POSIX_TO_WIN_A:
case CCP_WIN_A_TO_POSIX:
case CCP_WIN_W_TO_POSIX:
strcpy ((char *) to, buf);
stpcpy ((char *) to, buf);
break;
case CCP_POSIX_TO_WIN_W:
wcscpy ((PWCHAR) to, path);
wcpcpy ((PWCHAR) to, path);
break;
}
return 0;

View File

@ -18,7 +18,9 @@ details. */
#define isproc_dev(devn) \
(devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS || \
devn == FH_PROCNET)
devn == FH_PROCNET || devn == FH_PROCSYS)
#define isprocsys_dev(devn) (devn == FH_PROCSYS)
#define isvirtual_dev(devn) \
(isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE)