* 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> 2010-09-04 Corinna Vinschen <corinna@vinschen.de>
* mount.cc (mount_info::from_fstab_line): Reorder to make sure all * 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.o fhandler_clipboard.o fhandler_console.o fhandler_disk_file.o \
fhandler_dsp.o fhandler_fifo.o fhandler_floppy.o fhandler_mailslot.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_mem.o fhandler_netdrive.o fhandler_nodevice.o fhandler_proc.o \
fhandler_process.o fhandler_procnet.o fhandler_random.o fhandler_raw.o \ fhandler_process.o fhandler_procnet.o fhandler_procsys.o fhandler_random.o \
fhandler_registry.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \ fhandler_raw.o fhandler_registry.o fhandler_serial.o fhandler_socket.o \
fhandler_termios.o fhandler_tty.o fhandler_virtual.o fhandler_windows.o \ fhandler_tape.o fhandler_termios.o fhandler_tty.o fhandler_virtual.o \
fhandler_zero.o flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o \ fhandler_windows.o fhandler_zero.o flock.o fnmatch.o fork.o fts.o ftw.o \
glob_pattern_p.o globals.o grp.o heap.o hookapi.o inet_addr.o inet_network.o \ getopt.o glob.o glob_pattern_p.o globals.o grp.o heap.o hookapi.o \
init.o ioctl.o ipc.o kernel32.o libstdcxx_wrapper.o localtime.o lsearch.o \ inet_addr.o inet_network.o init.o ioctl.o ipc.o kernel32.o \
malloc_wrapper.o minires-os-if.o minires.o miscfuncs.o mktemp.o mmap.o msg.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 \ 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 \ 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 \ 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 = const device dev_procnet_storage =
{"", {FH_PROCNET}, ""}; {"", {FH_PROCNET}, ""};
const device dev_procsys_storage =
{"", {FH_PROCSYS}, ""};
const device dev_netdrive_storage = const device dev_netdrive_storage =
{"", {FH_NETDRIVE}, ""}; {"", {FH_NETDRIVE}, ""};

View File

@ -1,6 +1,6 @@
/* devices.h /* 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. This file is part of Cygwin.
@ -53,6 +53,7 @@ enum fh_devices
FH_DEV = FHDEV (0, 245), FH_DEV = FHDEV (0, 245),
FH_PROCNET = FHDEV (0, 244), FH_PROCNET = FHDEV (0, 244),
FH_PROCESSFD = FHDEV (0, 243), FH_PROCESSFD = FHDEV (0, 243),
FH_PROCSYS = FHDEV (0, 242),
DEV_FLOPPY_MAJOR = 2, DEV_FLOPPY_MAJOR = 2,
FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0), FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0),

View File

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

View File

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

View File

@ -34,7 +34,9 @@ extern const char *windows_device_names[];
extern struct __cygwin_perfile *perfile_table; extern struct __cygwin_perfile *perfile_table;
#define __fmode (*(user_data->fmode_ptr)) #define __fmode (*(user_data->fmode_ptr))
extern const char proc[]; 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_record;
class select_stuff; class select_stuff;
@ -99,6 +101,20 @@ enum del_lock_called_from {
after_exec 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 class fhandler_base
{ {
friend class dtable; friend class dtable;
@ -1331,7 +1347,7 @@ class fhandler_virtual : public fhandler_base
fhandler_virtual (); fhandler_virtual ();
virtual ~fhandler_virtual(); virtual ~fhandler_virtual();
virtual int exists(); virtual virtual_ftype_t exists();
DIR *opendir (int fd) __attribute__ ((regparm (2))); DIR *opendir (int fd) __attribute__ ((regparm (2)));
long telldir (DIR *); long telldir (DIR *);
void seekdir (DIR *, long); void seekdir (DIR *, long);
@ -1357,7 +1373,7 @@ class fhandler_proc: public fhandler_virtual
{ {
public: public:
fhandler_proc (); fhandler_proc ();
int exists(); virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
static DWORD get_proc_fhandler(const char *path); static DWORD get_proc_fhandler(const char *path);
@ -1366,11 +1382,30 @@ class fhandler_proc: public fhandler_virtual
bool fill_filebuf (); 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 class fhandler_netdrive: public fhandler_virtual
{ {
public: public:
fhandler_netdrive (); fhandler_netdrive ();
int exists(); virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
void seekdir (DIR *, long); void seekdir (DIR *, long);
void rewinddir (DIR *); void rewinddir (DIR *);
@ -1388,7 +1423,7 @@ class fhandler_registry: public fhandler_proc
public: public:
fhandler_registry (); fhandler_registry ();
void set_name (path_conv &pc); void set_name (path_conv &pc);
int exists(); virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
long telldir (DIR *); long telldir (DIR *);
void seekdir (DIR *, long); void seekdir (DIR *, long);
@ -1408,7 +1443,7 @@ class fhandler_process: public fhandler_proc
pid_t pid; pid_t pid;
public: public:
fhandler_process (); fhandler_process ();
int exists(); virtual_ftype_t exists();
DIR *opendir (int fd) __attribute__ ((regparm (2))); DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
@ -1421,7 +1456,7 @@ class fhandler_procnet: public fhandler_proc
pid_t pid; pid_t pid;
public: public:
fhandler_procnet (); fhandler_procnet ();
int exists(); virtual_ftype_t exists();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
@ -1462,6 +1497,8 @@ typedef union
char __pipe[sizeof (fhandler_pipe)]; char __pipe[sizeof (fhandler_pipe)];
char __proc[sizeof (fhandler_proc)]; char __proc[sizeof (fhandler_proc)];
char __process[sizeof (fhandler_process)]; char __process[sizeof (fhandler_process)];
char __procnet[sizeof (fhandler_procnet)];
char __procsys[sizeof (fhandler_procsys)];
char __pty_master[sizeof (fhandler_pty_master)]; char __pty_master[sizeof (fhandler_pty_master)];
char __registry[sizeof (fhandler_registry)]; char __registry[sizeof (fhandler_registry)];
char __serial[sizeof (fhandler_serial)]; char __serial[sizeof (fhandler_serial)];

View File

@ -118,7 +118,7 @@ public:
{ {
found[__DIR_PROC] = true; found[__DIR_PROC] = true;
if (retname) if (retname)
RtlInitUnicodeString (retname, L"proc"); *retname = ro_u_proc;
return 2; return 2;
} }
if (!found[__DIR_CYGDRIVE]) if (!found[__DIR_CYGDRIVE])
@ -407,7 +407,9 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
entry, as in other calls to fstat_helper. */ entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ()) if (pc.is_rep_symlink ())
fi.fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; 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, return fstat_helper (buf,
fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime
: &fi.fbi.LastWriteTime, : &fi.fbi.LastWriteTime,
@ -474,7 +476,9 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
entry, as in other calls to fstat_helper. */ entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ()) if (pc.is_rep_symlink ())
fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; 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, return fstat_helper (buf,
fdi_buf.fdi.ChangeTime.QuadPart fdi_buf.fdi.ChangeTime.QuadPart
? &fdi_buf.fdi.ChangeTime : &fdi_buf.fdi.LastWriteTime, ? &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, /* 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. */ -1 if path is a file, -2 if it's a symlink. */
int virtual_ftype_t
fhandler_netdrive::exists () fhandler_netdrive::exists ()
{ {
char *to; char *to;
const char *from; const char *from;
size_t len = strlen (get_name ()); size_t len = strlen (get_name ());
if (len == 2) if (len == 2)
return 1; return virt_rootdir;
char namebuf[len + 1]; char namebuf[len + 1];
for (to = namebuf, from = get_name (); *from; to++, from++) for (to = namebuf, from = get_name (); *from; to++, from++)
*to = (*from == '/') ? '\\' : *from; *to = (*from == '/') ? '\\' : *from;
@ -166,7 +166,7 @@ fhandler_netdrive::exists ()
&nr, &nh, 0, "WNetOpenEnum"); &nr, &nh, 0, "WNetOpenEnum");
if (nh.dom) if (nh.dom)
WNetCloseEnum (nh.dom); WNetCloseEnum (nh.dom);
return ret != NO_ERROR ? 0 : 1; return ret != NO_ERROR ? virt_none : virt_directory;
} }
fhandler_netdrive::fhandler_netdrive (): fhandler_netdrive::fhandler_netdrive ():

View File

@ -46,23 +46,24 @@ static _off64_t format_proc_filesystems (void *, char *&);
/* names of objects in /proc */ /* names of objects in /proc */
static const virt_tab_t proc_tab[] = { static const virt_tab_t proc_tab[] = {
{ ".", FH_PROC, virt_directory, NULL }, { _VN ("."), FH_PROC, virt_directory, NULL },
{ "..", FH_PROC, virt_directory, NULL }, { _VN (".."), FH_PROC, virt_directory, NULL },
{ "loadavg", FH_PROC, virt_file, format_proc_loadavg }, { _VN ("cpuinfo"), FH_PROC, virt_file, format_proc_cpuinfo },
{ "meminfo", FH_PROC, virt_file, format_proc_meminfo }, { _VN ("filesystems"), FH_PROC, virt_file, format_proc_filesystems },
{ "registry", FH_REGISTRY, virt_directory, NULL }, { _VN ("loadavg"), FH_PROC, virt_file, format_proc_loadavg },
{ "stat", FH_PROC, virt_file, format_proc_stat }, { _VN ("meminfo"), FH_PROC, virt_file, format_proc_meminfo },
{ "version", FH_PROC, virt_file, format_proc_version }, { _VN ("mounts"), FH_PROC, virt_symlink, format_proc_mounts },
{ "uptime", FH_PROC, virt_file, format_proc_uptime }, { _VN ("net"), FH_PROCNET, virt_directory, NULL },
{ "cpuinfo", FH_PROC, virt_file, format_proc_cpuinfo }, { _VN ("partitions"), FH_PROC, virt_file, format_proc_partitions },
{ "partitions", FH_PROC, virt_file, format_proc_partitions }, { _VN ("registry"), FH_REGISTRY, virt_directory, NULL },
{ "self", FH_PROC, virt_symlink, format_proc_self }, { _VN ("registry32"), FH_REGISTRY, virt_directory, NULL },
{ "mounts", FH_PROC, virt_symlink, format_proc_mounts }, { _VN ("registry64"), FH_REGISTRY, virt_directory, NULL },
{ "registry32", FH_REGISTRY, virt_directory, NULL }, { _VN ("self"), FH_PROC, virt_symlink, format_proc_self },
{ "registry64", FH_REGISTRY, virt_directory, NULL }, { _VN ("stat"), FH_PROC, virt_file, format_proc_stat },
{ "net", FH_PROCNET, virt_directory, NULL }, { _VN ("sys"), FH_PROCSYS, virt_directory, NULL },
{ "filesystems", FH_PROC, virt_file, format_proc_filesystems }, { _VN ("uptime"), FH_PROC, virt_file, format_proc_uptime },
{ NULL, 0, virt_none, NULL } { _VN ("version"), FH_PROC, virt_file, format_proc_version },
{ NULL, 0, 0, virt_none, NULL }
}; };
#define PROC_DIR_COUNT 4 #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 */ /* name of the /proc filesystem */
const char proc[] = "/proc"; 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 /* bsearch compare function. */
this is where it would be nice to have pattern matching in C - polymorphism static int
just doesn't cut it. */ 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 DWORD
fhandler_proc::get_proc_fhandler (const char *path) fhandler_proc::get_proc_fhandler (const char *path)
{ {
@ -91,12 +118,10 @@ fhandler_proc::get_proc_fhandler (const char *path)
if (*path == 0) if (*path == 0)
return FH_PROC; return FH_PROC;
for (int i = 0; proc_tab[i].name; i++) virt_tab_t *entry = virt_tab_search (path, true, proc_tab,
{ PROC_LINK_COUNT);
if (path_prefix_p (proc_tab[i].name, path, strlen (proc_tab[i].name), if (entry)
false)) return entry->fhandler;
return proc_tab[i].fhandler;
}
if (pinfo (atoi (path))) if (pinfo (atoi (path)))
return FH_PROCESS; 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, /* 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. */ -1 if path is a file, -2 if it's a symlink. */
int virtual_ftype_t
fhandler_proc::exists () fhandler_proc::exists ()
{ {
const char *path = get_name (); const char *path = get_name ();
@ -128,12 +153,13 @@ fhandler_proc::exists ()
path += proc_len; path += proc_len;
if (*path == 0) if (*path == 0)
return virt_rootdir; return virt_rootdir;
for (int i = 0; proc_tab[i].name; i++) virt_tab_t *entry = virt_tab_search (path + 1, false, proc_tab,
if (!strcmp (path + 1, proc_tab[i].name)) PROC_LINK_COUNT);
{ if (entry)
fileid = i; {
return proc_tab[i].type; fileid = entry - proc_tab;
} return entry->type;
}
return virt_none; return virt_none;
} }
@ -163,21 +189,21 @@ fhandler_proc::fstat (struct __stat64 *buf)
} }
else else
{ {
path++; virt_tab_t *entry = virt_tab_search (path + 1, false, proc_tab,
for (int i = 0; proc_tab[i].name; i++) PROC_LINK_COUNT);
if (!strcmp (path, proc_tab[i].name)) if (entry)
{ {
if (proc_tab[i].type == virt_directory) if (entry->type == virt_directory)
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
else if (proc_tab[i].type == virt_symlink) else if (entry->type == virt_symlink)
buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
else else
{ {
buf->st_mode &= NO_X; buf->st_mode &= NO_X;
buf->st_mode |= S_IFREG; buf->st_mode |= S_IFREG;
} }
return 0; return 0;
} }
} }
set_errno (ENOENT); set_errno (ENOENT);
return -1; return -1;

View File

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

View File

@ -39,10 +39,10 @@ static _off64_t format_procnet_ifinet6 (void *, char *&);
static const virt_tab_t procnet_tab[] = static const virt_tab_t procnet_tab[] =
{ {
{ ".", FH_PROCNET, virt_directory, NULL }, { _VN ("."), FH_PROCNET, virt_directory, NULL },
{ "..", FH_PROCNET, virt_directory, NULL }, { _VN (".."), FH_PROCNET, virt_directory, NULL },
{ "if_inet6", FH_PROCNET, virt_file, format_procnet_ifinet6 }, { _VN ("if_inet6"), FH_PROCNET, virt_file, format_procnet_ifinet6 },
{ NULL, 0, virt_none, NULL } { NULL, 0, 0, virt_none, NULL }
}; };
static const int PROCNET_LINK_COUNT = 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, * -1 if path is a file, -2 if path is a symlink, -3 if path is a pipe,
* -4 if path is a socket. * -4 if path is a socket.
*/ */
int virtual_ftype_t
fhandler_procnet::exists () fhandler_procnet::exists ()
{ {
const char *path = get_name (); const char *path = get_name ();
@ -61,20 +61,21 @@ fhandler_procnet::exists ()
while (*path != 0 && !isdirsep (*path)) while (*path != 0 && !isdirsep (*path))
path++; path++;
if (*path == 0) if (*path == 0)
return 1; return virt_rootdir;
for (int i = 0; procnet_tab[i].name; i++) virt_tab_t *entry = virt_tab_search (path + 1, false, procnet_tab,
if (!strcmp (path + 1, procnet_tab[i].name)) PROCNET_LINK_COUNT);
{ if (entry)
if (procnet_tab[i].type == virt_file) {
{ if (entry->type == virt_file)
if (!wincap.has_gaa_prefixes () {
|| !get_adapters_addresses (NULL, AF_INET6)) if (!wincap.has_gaa_prefixes ()
return virt_none; || !get_adapters_addresses (NULL, AF_INET6))
} return virt_none;
fileid = i; }
return procnet_tab[i].type; fileid = entry - procnet_tab;
} return entry->type;
}
return virt_none; return virt_none;
} }
@ -129,8 +130,6 @@ out:
int int
fhandler_procnet::open (int flags, mode_t mode) fhandler_procnet::open (int flags, mode_t mode)
{ {
int process_file_no = -1;
int res = fhandler_virtual::open (flags, mode); int res = fhandler_virtual::open (flags, mode);
if (!res) if (!res)
goto out; goto out;
@ -163,27 +162,13 @@ fhandler_procnet::open (int flags, mode_t mode)
} }
} }
process_file_no = -1; virt_tab_t *entry;
for (int i = 0; procnet_tab[i].name; i++) entry = virt_tab_search (path + 1, true, procnet_tab, PROCNET_LINK_COUNT);
if (!entry)
{ {
if (path_prefix_p (procnet_tab[i].name, path + 1, set_errno ((flags & O_CREAT) ? EROFS : ENOENT);
strlen (procnet_tab[i].name), false)) res = 0;
process_file_no = i; 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 (flags & O_WRONLY) if (flags & O_WRONLY)
{ {
@ -192,7 +177,7 @@ fhandler_procnet::open (int flags, mode_t mode)
goto out; goto out;
} }
fileid = process_file_no; fileid = entry - procnet_tab;
if (!fill_filebuf ()) if (!fill_filebuf ())
{ {
res = 0; 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 * final component is there. This gets round the problem of not having security access
* to the final key in the path. * to the final key in the path.
*/ */
int virtual_ftype_t
fhandler_registry::exists () 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; DWORD buf_size = NAME_MAX + 1;
LONG error; LONG error;
wchar_t buf[buf_size]; wchar_t buf[buf_size];
@ -285,7 +286,7 @@ fhandler_registry::exists ()
path++; path++;
else else
{ {
file_type = 2; file_type = virt_rootdir;
goto out; goto out;
} }
pathlen = strlen (path); pathlen = strlen (path);
@ -302,7 +303,7 @@ fhandler_registry::exists ()
if (path_prefix_p (registry_listing[i], path, if (path_prefix_p (registry_listing[i], path,
strlen (registry_listing[i]), true)) strlen (registry_listing[i]), true))
{ {
file_type = 1; file_type = virt_directory;
break; break;
} }
} }
@ -317,12 +318,12 @@ fhandler_registry::exists ()
if (!val_only) if (!val_only)
hKey = open_key (path, KEY_READ, wow64, false); hKey = open_key (path, KEY_READ, wow64, false);
if (hKey != (HKEY) INVALID_HANDLE_VALUE || get_errno () == EACCES) if (hKey != (HKEY) INVALID_HANDLE_VALUE || get_errno () == EACCES)
file_type = 1; file_type = virt_directory;
else else
{ {
hKey = open_key (path, KEY_READ, wow64, true); hKey = open_key (path, KEY_READ, wow64, true);
if (hKey == (HKEY) INVALID_HANDLE_VALUE) if (hKey == (HKEY) INVALID_HANDLE_VALUE)
return 0; return virt_none;
if (hKey == HKEY_PERFORMANCE_DATA) if (hKey == HKEY_PERFORMANCE_DATA)
{ {
@ -332,13 +333,14 @@ fhandler_registry::exists ()
So allow access to the generic names and to So allow access to the generic names and to
(blank separated) lists of counter numbers. (blank separated) lists of counter numbers.
Never allow access to "Add", see above comment. */ 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)) if (strcasematch (perf_data_files[i], file))
file_type = -1; file_type = virt_file;
} }
if (file_type == 0 && !file[strspn (file, " 0123456789")]) if (file_type == virt_none && !file[strspn (file, " 0123456789")])
file_type = -1; file_type = virt_file;
goto out; goto out;
} }
@ -351,7 +353,7 @@ fhandler_registry::exists ()
{ {
if (!wcscasecmp (buf, dec_file)) if (!wcscasecmp (buf, dec_file))
{ {
file_type = 1; file_type = virt_directory;
goto out; goto out;
} }
buf_size = NAME_MAX + 1; buf_size = NAME_MAX + 1;
@ -372,7 +374,7 @@ fhandler_registry::exists ()
{ {
if (!wcscasecmp (buf, dec_file)) if (!wcscasecmp (buf, dec_file))
{ {
file_type = -1; file_type = virt_file;
goto out; goto out;
} }
buf_size = NAME_MAX + 1; buf_size = NAME_MAX + 1;
@ -418,32 +420,32 @@ fhandler_registry::fstat (struct __stat64 *buf)
{ {
fhandler_base::fstat (buf); fhandler_base::fstat (buf);
buf->st_mode &= ~_IFMT & NO_W; buf->st_mode &= ~_IFMT & NO_W;
int file_type = exists (); virtual_ftype_t file_type = exists ();
switch (file_type) switch (file_type)
{ {
case 0: case virt_none:
set_errno (ENOENT); set_errno (ENOENT);
return -1; return -1;
case 1: case virt_directory:
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
break; break;
case 2: case virt_rootdir:
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = ROOT_KEY_COUNT; buf->st_nlink = ROOT_KEY_COUNT;
break; break;
default: default:
case -1: case virt_file:
buf->st_mode |= S_IFREG; buf->st_mode |= S_IFREG;
buf->st_mode &= NO_X; buf->st_mode &= NO_X;
break; break;
} }
if (file_type != 0 && file_type != 2) if (file_type != virt_none && file_type != virt_rootdir)
{ {
HKEY hKey; HKEY hKey;
const char *path = get_name () + proc_len + prefix_len + 2; const char *path = get_name () + proc_len + prefix_len + 2;
hKey = hKey =
open_key (path, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, wow64, 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) if (hKey == HKEY_PERFORMANCE_DATA)
/* RegQueryInfoKey () always returns write time 0, /* RegQueryInfoKey () always returns write time 0,
@ -461,7 +463,7 @@ fhandler_registry::fstat (struct __stat64 *buf)
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim); to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
buf->st_ctim = buf->st_birthtim = buf->st_mtim; buf->st_ctim = buf->st_birthtim = buf->st_mtim;
time_as_timestruc_t (&buf->st_atim); time_as_timestruc_t (&buf->st_atim);
if (file_type > 0) if (file_type > virt_none)
buf->st_nlink = subkey_count + 2; buf->st_nlink = subkey_count + 2;
else else
{ {
@ -508,7 +510,7 @@ fhandler_registry::fstat (struct __stat64 *buf)
buf->st_uid = uid; buf->st_uid = uid;
buf->st_gid = gid; buf->st_gid = gid;
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
if (file_type > 0) if (file_type > virt_none)
buf->st_mode |= S_IFDIR; buf->st_mode |= S_IFDIR;
else else
buf->st_mode &= NO_X; buf->st_mode &= NO_X;

View File

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

View File

@ -1,6 +1,6 @@
/* fhandler_virtual.h: Header for virtual fhandlers /* fhandler_virtual.h: Header for virtual fhandlers
Copyright 2009 Red Hat, Inc. Copyright 2009, 2010 Red Hat, Inc.
This file is part of Cygwin. 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 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */ 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 { struct virt_tab_t {
const char *name; const char *name;
size_t name_len;
__dev32_t fhandler; __dev32_t fhandler;
virtual_ftype_t type; virtual_ftype_t type;
_off64_t (*format_func)(void *data, char *&); _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; 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 bypass the mount table. If it's // or //MACHINE, use the netdrive
device. */ device. */
if (src_path[1] == '/') 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) if (dev.devn == FH_BAD)
return ENOENT; return ENOENT;
set_flags (flags, PATH_BINARY); 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; goto out;
} }
/* Check if the cygdrive prefix was specified. If so, just strip /* 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_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022) #define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023) #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_INVALID ((NTSTATUS) 0xc0000033)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034) #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A) #define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
@ -40,6 +41,10 @@
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056) #define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
#define STATUS_DISK_FULL ((NTSTATUS) 0xc000007f) #define STATUS_DISK_FULL ((NTSTATUS) 0xc000007f)
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1) #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_NOT_SUPPORTED ((NTSTATUS) 0xc00000bb)
#define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xc00000be) #define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xc00000be)
#define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xc00000c3) #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_CREATE_SUBDIRECTORY 8
#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|0x0f) #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|0x0f)
#define SYMBOLIC_LINK_QUERY 1
#define EVENT_QUERY_STATE 1 #define EVENT_QUERY_STATE 1
#define SEMAPHORE_QUERY_STATE 1 #define SEMAPHORE_QUERY_STATE 1
@ -927,6 +934,8 @@ extern "C"
NTSTATUS NTAPI NtOpenMutant (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenMutant (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtOpenSemaphore (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 /* WARNING! Don't rely on the timestamp information returned by
NtQueryAttributesFile. Only the DOS file attribute info is reliable. */ NtQueryAttributesFile. Only the DOS file attribute info is reliable. */
NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES, NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES,
@ -956,6 +965,7 @@ extern "C"
NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION, NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, ULONG, PULONG); PSECURITY_DESCRIPTOR, ULONG, PULONG);
NTSTATUS NTAPI NtQuerySymbolicLinkObject (HANDLE, PUNICODE_STRING, PULONG);
NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS, NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS,
PVOID, ULONG, PULONG); PVOID, ULONG, PULONG);
NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *, 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. */ /* FIXME: Calling build_fhandler here is not the right way to handle this. */
fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy); fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy);
int file_type = fh->exists (); virtual_ftype_t file_type = fh->exists ();
if (file_type == -2) if (file_type == virt_symlink)
{ {
fh->fill_filebuf (); fh->fill_filebuf ();
symlen = sym.set (fh->get_filebuf ()); symlen = sym.set (fh->get_filebuf ());
@ -770,31 +770,61 @@ path_conv::check (const char *src, unsigned opt,
delete fh; delete fh;
switch (file_type) switch (file_type)
{ {
case 1: case virt_directory:
case 2: case virt_rootdir:
if (component == 0) if (component == 0)
fileattr = FILE_ATTRIBUTE_DIRECTORY; fileattr = FILE_ATTRIBUTE_DIRECTORY;
break; break;
case -1: case virt_file:
if (component == 0) if (component == 0)
fileattr = 0; fileattr = 0;
break; break;
case -2: /* /proc/self or /proc/<pid>/symlinks */ case virt_symlink:
goto is_virtual_symlink; goto is_virtual_symlink;
case -3: /* /proc/<pid>/fd/pipe:[] */ case virt_pipe:
if (component == 0) if (component == 0)
{ {
fileattr = 0; fileattr = 0;
dev.parse (FH_PIPE); dev.parse (FH_PIPE);
} }
break; break;
case -4: /* /proc/<pid>/fd/socket:[] */ case virt_socket:
if (component == 0) if (component == 0)
{ {
fileattr = 0; fileattr = 0;
dev.parse (FH_TCP); dev.parse (FH_TCP);
} }
break; 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: default:
if (component == 0) if (component == 0)
fileattr = INVALID_FILE_ATTRIBUTES; fileattr = INVALID_FILE_ATTRIBUTES;
@ -841,6 +871,8 @@ path_conv::check (const char *src, unsigned opt,
if (is_msdos) if (is_msdos)
sym.pflags |= PATH_NOPOSIX | PATH_NOACL; sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
is_fs_via_procsys:
symlen = sym.check (full_path, suff, fs, conv_handle); symlen = sym.check (full_path, suff, fs, conv_handle);
is_virtual_symlink: 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 */ if (buf[1] != ':') /* native UNC path */
*(buf += 2) = '\\'; *(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; lsiz = strlen (buf) + 1;
/* TODO: Incoming "." is a special case which leads to a trailing /* TODO: Incoming "." is a special case which leads to a trailing
backslash ".\\" in the Win32 path. That's a result of the 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, quite a bunch of Win32 functions, especially in user32.dll,
apparently, which don't grok long path names at all, not even apparently, which don't grok long path names at all, not even
in the UNICODE API. */ 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; path += 4;
lsiz -= 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. */ /* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */
if (relative && !strcmp ((const char *) from, ".") if (relative && !strcmp ((const char *) from, ".")
&& !wcscmp (path, L".\\")) && !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_POSIX_TO_WIN_A:
case CCP_WIN_A_TO_POSIX: case CCP_WIN_A_TO_POSIX:
case CCP_WIN_W_TO_POSIX: case CCP_WIN_W_TO_POSIX:
strcpy ((char *) to, buf); stpcpy ((char *) to, buf);
break; break;
case CCP_POSIX_TO_WIN_W: case CCP_POSIX_TO_WIN_W:
wcscpy ((PWCHAR) to, path); wcpcpy ((PWCHAR) to, path);
break; break;
} }
return 0; return 0;

View File

@ -18,7 +18,9 @@ details. */
#define isproc_dev(devn) \ #define isproc_dev(devn) \
(devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS || \ (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) \ #define isvirtual_dev(devn) \
(isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE) (isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE)