Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog66
-rw-r--r--winsup/cygwin/Makefile.in15
-rw-r--r--winsup/cygwin/devices.cc3
-rw-r--r--winsup/cygwin/devices.h3
-rw-r--r--winsup/cygwin/devices.in3
-rw-r--r--winsup/cygwin/dtable.cc3
-rw-r--r--winsup/cygwin/fhandler.h51
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc10
-rw-r--r--winsup/cygwin/fhandler_netdrive.cc6
-rw-r--r--winsup/cygwin/fhandler_proc.cc124
-rw-r--r--winsup/cygwin/fhandler_process.cc97
-rw-r--r--winsup/cygwin/fhandler_procnet.cc67
-rw-r--r--winsup/cygwin/fhandler_procsys.cc422
-rw-r--r--winsup/cygwin/fhandler_registry.cc44
-rw-r--r--winsup/cygwin/fhandler_virtual.cc4
-rw-r--r--winsup/cygwin/fhandler_virtual.h17
-rw-r--r--winsup/cygwin/mount.cc13
-rw-r--r--winsup/cygwin/ntdll.h10
-rw-r--r--winsup/cygwin/path.cc70
-rw-r--r--winsup/cygwin/path.h4
20 files changed, 816 insertions, 216 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 49d85a0ed..83992f750 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index c48914805..59f229c01 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -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 \
diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc
index 1f4bb9529..66fe020ff 100644
--- a/winsup/cygwin/devices.cc
+++ b/winsup/cygwin/devices.cc
@@ -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}, ""};
diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h
index d1a76a4ff..60c21a714 100644
--- a/winsup/cygwin/devices.h
+++ b/winsup/cygwin/devices.h
@@ -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),
diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in
index bbe829683..591225e20 100644
--- a/winsup/cygwin/devices.in
+++ b/winsup/cygwin/devices.in
@@ -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}, ""};
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index 332bc7105..6a9d55df1 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 54e9d0694..3fcfe1cef 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -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)];
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 02ce90e61..1d7675c34 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -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,
diff --git a/winsup/cygwin/fhandler_netdrive.cc b/winsup/cygwin/fhandler_netdrive.cc
index 47971526a..94071de00 100644
--- a/winsup/cygwin/fhandler_netdrive.cc
+++ b/winsup/cygwin/fhandler_netdrive.cc
@@ -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 ():
diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc
index 3289acb15..df381127a 100644
--- a/winsup/cygwin/fhandler_proc.cc
+++ b/winsup/cygwin/fhandler_proc.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index 83b69b84a..b2fa5f771 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -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++)
- {
- if (path_prefix_p (process_tab[i].name, path + 1,
- strlen (process_tab[i].name), false))
- process_file_no = i;
- }
- if (process_file_no == -1)
+ virt_tab_t *entry;
+ entry = virt_tab_search (path + 1, true, process_tab, PROCESS_LINK_COUNT);
+ if (!entry)
{
- 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 (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;
diff --git a/winsup/cygwin/fhandler_procnet.cc b/winsup/cygwin/fhandler_procnet.cc
index 3cf29dd6c..607c9d4ff 100644
--- a/winsup/cygwin/fhandler_procnet.cc
+++ b/winsup/cygwin/fhandler_procnet.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler_procsys.cc b/winsup/cygwin/fhandler_procsys.cc
new file mode 100644
index 000000000..aa0b6b699
--- /dev/null
+++ b/winsup/cygwin/fhandler_procsys.cc
@@ -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
diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc
index 478b9cca4..b9c9a8ea5 100644
--- a/winsup/cygwin/fhandler_registry.cc
+++ b/winsup/cygwin/fhandler_registry.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc
index 3becf03e9..6d515a3a7 100644
--- a/winsup/cygwin/fhandler_virtual.cc
+++ b/winsup/cygwin/fhandler_virtual.cc
@@ -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
diff --git a/winsup/cygwin/fhandler_virtual.h b/winsup/cygwin/fhandler_virtual.h
index de914eacd..f2f211727 100644
--- a/winsup/cygwin/fhandler_virtual.h
+++ b/winsup/cygwin/fhandler_virtual.h
@@ -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);
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index da0e744de..0117b43b1 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -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
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 94b17ee51..5c6eb53c2 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -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 *,
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index fe81acd8b..4b8179c8e 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -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;
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 947e83530..3650f7688 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -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)