This is the mail archive of the cygwin-developers mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Accessing native NT namespace as filesystem


Hi guys,


for those who want to play with this, I attached a patch which adds the
entire native NT namespace under the /sys directory.  I called it
fhandler_sysfs, and it works nicely afaics.  However, I was wondering if
that's really useful.  I'm also not really sure the name sysfs and the
/sys path is such a good idea.

Anyway, it's kind of fun.  First of all, you can now actually list the
contents of the NT namespace in Cygwin, something you needed the
sysinternals winobj tool for, so far.  Second, it's a neat way to examine
which filesystems you have:

  $ ls -l /sys/Device/Harddisk*

Third, you can easily access filesystems which are not mounted in
Windows via /sys:

  $ ls -l /sys/Device/rddiskVolumeShadowCopy1
  brwxrwx--x 1 Administrators SYSTEM 0, 242 2010-09-02 17:40 /sys/Device/HarddiskVolumeShadowCopy1

  $ ls -l /sys/Device/rddiskVolumeShadowCopy1/
  total 1834666
  drwxrwx---+ 1 Administrators Administrators          0 2010-04-12 11:32 $Recycle.Bin
  drwxr-x---  1 ????????       ????????                0 2009-07-14 04:37 PerfLogs
  drwxrwx---+ 1 ????????       ????????                0 2010-08-03 15:24 Program Files
  [...]
  drwxr-xr-x  1 corinna        Administrators          0 2010-08-23 18:16 cygwin
  -rw-r-----  1 ????????       ????????        804954112 2010-08-24 15:12 hiberfil.sys
  -rw-r-----  1 ????????       ????????       1073741824 2010-08-24 15:12 pagefile.sys

Note the difference between using a trailing backslash or not.  Without
trailing BS it's just a block device.  With the trailing backslash it's
recognized as the root directory of the filesystem on that block device.
That's default NT semantics, and it's quite neat, IMHO.

Due to syntactical checks in mount(2) it's not yet possible to add a
mountpoint to a filesystem in /etc/fstab, but you can use a symlink
if you like:

  $ ln -s /sys/Device/HarddiskVolumeShadowCopy1/ /my_shadow_copy

Here the trailing BS is necessary for the aforementioned reason.

Last but not least I added the ability to open, read and write device
files within /sys as well.  If you have permissions, of course:

  # dd if=/sys/Device/HarddiskVolumeShadowCopy1 bs=512 count=1 | od -c -N 32
  0000000 353   R 220   N   T   F   S                  \0 002  \b  \0  \0
  0000020  \0  \0  \0  \0  \0 370  \0  \0   ?  \0 377  \0  \0   ( 003  \0
  0000040
  1+0 records in
  1+0 records out
  512 bytes (512 B) copied, 0 s, Infinity B/s

Here the device is used as device, so no backspace, please.

Nice would be a way to send Windows ioctl's to devices via Cygwin's
ioctl call.  That shouldn't be too hard to add, too.

So, what do you think?  Useful/Useless/Tasteless/Ridiculous?

Would /sys be ok?  Or what else?  Not /dev, certainly, since that's
reserved for Cygwin/POSIX devices.  /devices, maybe, as on Solaris?


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/Makefile.in,v
retrieving revision 1.237
diff -u -p -r1.237 Makefile.in
--- Makefile.in	21 Aug 2010 18:57:36 -0000	1.237
+++ Makefile.in	2 Sep 2010 16:13:50 -0000
@@ -142,12 +142,13 @@ DLL_OFILES:=assert.o autoload.o bsdlib.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_registry.o fhandler_serial.o fhandler_socket.o fhandler_sysfs.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 \
Index: devices.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/devices.cc,v
retrieving revision 1.31
diff -u -p -r1.31 devices.cc
--- devices.cc	3 Jan 2009 05:12:20 -0000	1.31
+++ devices.cc	2 Sep 2010 16:13:51 -0000
@@ -24,6 +24,9 @@ const device dev_proc_storage =
 const device dev_procnet_storage =
   {"", {FH_PROCNET}, ""};
 
+const device dev_sysfs_storage =
+  {"", {FH_SYSFS}, ""};
+
 const device dev_netdrive_storage =
   {"", {FH_NETDRIVE}, ""};
 
Index: devices.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/devices.h,v
retrieving revision 1.25
diff -u -p -r1.25 devices.h
--- devices.h	20 Jan 2009 17:22:11 -0000	1.25
+++ devices.h	2 Sep 2010 16:13:51 -0000
@@ -53,6 +53,8 @@ enum fh_devices
   FH_DEV     = FHDEV (0, 245),
   FH_PROCNET = FHDEV (0, 244),
   FH_PROCESSFD = FHDEV (0, 243),
+  FH_SYSFS   = FHDEV (0, 242),
+
 
   DEV_FLOPPY_MAJOR = 2,
   FH_FLOPPY  = FHDEV (DEV_FLOPPY_MAJOR, 0),
@@ -287,6 +289,8 @@ extern const device dev_piper_storage;
 extern const device dev_pipew_storage;
 #define pipew_dev (&dev_pipew_storage)
 extern const device dev_proc_storage;
+#define sysfs_dev (&dev_sysfs_storage)
+extern const device dev_sysfs_storage;
 #define proc_dev (&dev_proc_storage)
 extern const device dev_netdrive_storage;
 #define netdrive_dev (&dev_netdrive_storage)
Index: devices.in
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/devices.in,v
retrieving revision 1.22
diff -u -p -r1.22 devices.in
--- devices.in	3 Jan 2009 05:12:20 -0000	1.22
+++ devices.in	2 Sep 2010 16:13:51 -0000
@@ -20,6 +20,9 @@ const device dev_proc_storage =
 const device dev_procnet_storage =
   {"", {FH_PROCNET}, ""};
 
+const device dev_sysfs_storage =
+  {"", {FH_SYSFS}, ""};
+
 const device dev_netdrive_storage =
   {"", {FH_NETDRIVE}, ""};
 
Index: dir.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dir.cc,v
retrieving revision 1.126
diff -u -p -r1.126 dir.cc
--- dir.cc	5 Jul 2010 16:59:51 -0000	1.126
+++ dir.cc	2 Sep 2010 16:13:51 -0000
@@ -144,7 +144,7 @@ readdir_worker (DIR *dir, dirent *de)
 		  ((fhandler_base *) dir->__fh)->pc.get_nt_native_path ();
 	      DWORD devn = ((fhandler_base *) dir->__fh)->get_device ();
 	      /* Paths below /proc don't have a Win32 pendant. */
-	      if (isproc_dev (devn))
+	      if (isproc_dev (devn) || issysfs_dev (devn))
 		de->d_ino = hash_path_name (de->d_ino, L"/");
 	      else if (w32name->Buffer[w32name->Length / sizeof (WCHAR) - 1]
 		       != L'\\')
Index: dtable.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dtable.cc,v
retrieving revision 1.216
diff -u -p -r1.216 dtable.cc
--- dtable.cc	15 Jun 2010 12:05:14 -0000	1.216
+++ dtable.cc	2 Sep 2010 16:13:51 -0000
@@ -540,6 +540,9 @@ build_fh_pc (path_conv& pc, bool set_nam
 	case FH_PROCNET:
 	  fh = cnew (fhandler_procnet) ();
 	  break;
+	case FH_SYSFS:
+	  fh = cnew (fhandler_sysfs) ();
+	  break;
 	case FH_NETDRIVE:
 	  fh = cnew (fhandler_netdrive) ();
 	  break;
Index: fhandler.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v
retrieving revision 1.403
diff -u -p -r1.403 fhandler.h
--- fhandler.h	5 Jul 2010 16:59:55 -0000	1.403
+++ fhandler.h	2 Sep 2010 16:13:51 -0000
@@ -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 sysfs[];
+extern const size_t sysfs_len;
 
 class select_record;
 class select_stuff;
@@ -99,6 +101,22 @@ 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 SYSFS */
+  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_dir_nobs = 3,	/* Directory, strip trailing backslash */
+  virt_fsdir = 4,	/* FS-based directory via SYSFS */
+  virt_fsdir_nobs = 5	/* Ditto, strip trailing backslash */
+};
+
 class fhandler_base
 {
   friend class dtable;
@@ -1331,7 +1349,7 @@ class fhandler_virtual : public fhandler
   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 +1375,7 @@ class fhandler_proc: public fhandler_vir
 {
  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 +1384,30 @@ class fhandler_proc: public fhandler_vir
   bool fill_filebuf ();
 };
 
+class fhandler_sysfs: public fhandler_virtual
+{
+ public:
+  fhandler_sysfs ();
+  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 +1425,7 @@ class fhandler_registry: public fhandler
  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 +1445,7 @@ class fhandler_process: public fhandler_
   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 +1458,7 @@ class fhandler_procnet: public fhandler_
   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)));
Index: fhandler_disk_file.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_disk_file.cc,v
retrieving revision 1.334
diff -u -p -r1.334 fhandler_disk_file.cc
--- fhandler_disk_file.cc	20 Aug 2010 11:18:58 -0000	1.334
+++ fhandler_disk_file.cc	2 Sep 2010 16:13:51 -0000
@@ -36,11 +36,12 @@ class __DIR_mounts
   const char	*parent_dir;
   int		 parent_dir_len;
   UNICODE_STRING mounts[MAX_MOUNTS];
-  bool		 found[MAX_MOUNTS + 2];
+  bool		 found[MAX_MOUNTS + 3];
   UNICODE_STRING cygdrive;
 
 #define __DIR_PROC	(MAX_MOUNTS)
-#define __DIR_CYGDRIVE	(MAX_MOUNTS+1)
+#define __DIR_SYS	(MAX_MOUNTS+1)
+#define __DIR_CYGDRIVE	(MAX_MOUNTS+2)
 
   __ino64_t eval_ino (int idx)
     {
@@ -84,6 +85,11 @@ public:
 	      found[__DIR_PROC] = true;
 	      return 2;
 	    }
+	  if (RtlEqualUnicodeString (fname, &ro_u_sysfs, FALSE))
+	    {
+	      found[__DIR_SYS] = true;
+	      return 2;
+	    }
 	  if (fname->Length / sizeof (WCHAR) == mount_table->cygdrive_len - 2
 	      && RtlEqualUnicodeString (fname, &cygdrive, FALSE))
 	    {
@@ -118,7 +124,14 @@ public:
 	    {
 	      found[__DIR_PROC] = true;
 	      if (retname)
-		RtlInitUnicodeString (retname, L"proc");
+		*retname = ro_u_proc;
+	      return 2;
+	    }
+	  if (!found[__DIR_SYS])
+	    {
+	      found[__DIR_SYS] = true;
+	      if (retname)
+		*retname = ro_u_sysfs;
 	      return 2;
 	    }
 	  if (!found[__DIR_CYGDRIVE])
@@ -474,7 +487,10 @@ fhandler_base::fstat_by_name (struct __s
      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);
+  /* If basename.Length is 0, the file is a virtual directory.  The attributes
+     from fdi_buf are incorrect, so don't copy. */
+  if (basename.Length > 0)
+    pc.file_attributes (fdi_buf.fdi.FileAttributes);
   return fstat_helper (buf,
 		       fdi_buf.fdi.ChangeTime.QuadPart
 		       ? &fdi_buf.fdi.ChangeTime : &fdi_buf.fdi.LastWriteTime,
Index: fhandler_netdrive.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_netdrive.cc,v
retrieving revision 1.29
diff -u -p -r1.29 fhandler_netdrive.cc
--- fhandler_netdrive.cc	1 Sep 2010 18:24:10 -0000	1.29
+++ fhandler_netdrive.cc	2 Sep 2010 16:13:51 -0000
@@ -145,14 +145,14 @@ create_thread_and_wait (int what, PVOID 
 
 /* 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 ():
Index: fhandler_proc.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_proc.cc,v
retrieving revision 1.92
diff -u -p -r1.92 fhandler_proc.cc
--- fhandler_proc.cc	27 Aug 2010 09:08:32 -0000	1.92
+++ fhandler_proc.cc	2 Sep 2010 16:13:52 -0000
@@ -71,7 +71,7 @@ static const int PROC_LINK_COUNT = (size
 
 /* 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
@@ -120,7 +120,7 @@ fhandler_proc::get_proc_fhandler (const 
 
 /* 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 ();
Index: fhandler_process.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_process.cc,v
retrieving revision 1.91
diff -u -p -r1.91 fhandler_process.cc
--- fhandler_process.cc	18 May 2010 14:30:50 -0000	1.91
+++ fhandler_process.cc	2 Sep 2010 16:13:52 -0000
@@ -90,7 +90,7 @@ static bool get_mem_values (DWORD dwProc
  * -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,7 +99,7 @@ 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++)
     {
Index: fhandler_procnet.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_procnet.cc,v
retrieving revision 1.11
diff -u -p -r1.11 fhandler_procnet.cc
--- fhandler_procnet.cc	20 Jan 2009 18:04:32 -0000	1.11
+++ fhandler_procnet.cc	2 Sep 2010 16:13:52 -0000
@@ -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,7 +61,7 @@ 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))
Index: fhandler_registry.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_registry.cc,v
retrieving revision 1.62
diff -u -p -r1.62 fhandler_registry.cc
--- fhandler_registry.cc	1 Sep 2010 10:30:52 -0000	1.62
+++ fhandler_registry.cc	2 Sep 2010 16:13:52 -0000
@@ -268,10 +268,11 @@ multi_wcstombs (char *dst, size_t len, c
  * 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 __stat6
 {
   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 __stat6
 	      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 __stat6
 		  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;
Index: fhandler_sysfs.cc
===================================================================
RCS file: fhandler_sysfs.cc
diff -N fhandler_sysfs.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fhandler_sysfs.cc	2 Sep 2010 16:13:52 -0000
@@ -0,0 +1,431 @@
+/* fhandler_sysfs.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>
+
+/* name of the /sys filesystem */
+const char sysfs[] = "/sys";
+const size_t sysfs_len = sizeof (sysfs) - 1;
+
+#define mk_unicode_path(p) \
+	WCHAR namebuf[strlen (get_name ()) + 1]; \
+	{ \
+	  const char *from; \
+	  PWCHAR to; \
+	  for (to = namebuf, from = get_name () + sysfs_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_sysfs::exists (struct __stat64 *buf)
+{
+  UNICODE_STRING path; \
+  OBJECT_ATTRIBUTES attr;
+  IO_STATUS_BLOCK io;
+  NTSTATUS status;
+  HANDLE h;
+  FILE_BASIC_INFORMATION fbi;
+  bool strip_bs = false;
+  virtual_ftype_t file_type = virt_chr;
+
+  if (strlen (get_name ()) == sysfs_len)
+    return virt_rootdir;
+  mk_unicode_path (&path);
+  /* First try to open as file/device to get more info. */
+  InitializeObjectAttributes (&attr, &path, 0, 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_NAME_INVALID
+      && path.Buffer[path.Length / sizeof (WCHAR) - 1] == L'\\')
+    {
+      /* Strip the trailing backslash and try again. */
+      strip_bs = true;
+      path.Length -= sizeof (WCHAR);
+      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_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)
+	       ? (strip_bs ? virt_fsdir_nobs : 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 SYSFS. */
+      status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
+				       FileBasicInformation);
+      NtClose (h);
+      if (NT_SUCCESS (dev_stat))
+	{
+	  if (ffdi.DeviceType == FILE_DEVICE_NAMED_PIPE)
+	    {
+	      if (path.Buffer[path.Length / sizeof (WCHAR) - 1] == L'\\')
+		return virt_fsdir;
+	      file_type = virt_pipe;
+	    }
+	  else if (NT_SUCCESS (status))
+	    file_type = (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+			? (strip_bs ? virt_fsdir_nobs : virt_fsdir)
+			: virt_fsfile;
+	  else if (ffdi.DeviceType == FILE_DEVICE_DISK
+		   || ffdi.DeviceType == FILE_DEVICE_CD_ROM
+		   || 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 strip_bs ? virt_dir_nobs : virt_directory;
+    }
+  else if (status == STATUS_ACCESS_DENIED)
+    return strip_bs ? virt_dir_nobs : virt_directory;
+  /* Give up.  Just treat as character device. */
+  return file_type;
+}
+
+virtual_ftype_t
+fhandler_sysfs::exists ()
+{
+  return exists (NULL);
+}
+
+fhandler_sysfs::fhandler_sysfs ():
+  fhandler_virtual ()
+{
+}
+
+bool
+fhandler_sysfs::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, 0, 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, sysfs_len + len + 1);
+  sys_wcstombs (fnamep = stpcpy (filebuf, sysfs), len + 1, target.Buffer,
+		target.Length / sizeof (WCHAR));
+  while ((fnamep = strchr (fnamep, '\\')))
+    *fnamep = '/';
+  return true;
+}
+
+int
+fhandler_sysfs::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_dir_nobs:
+    case virt_fsdir:
+    case virt_fsdir_nobs:
+      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_sysfs::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, 0, 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_sysfs::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_sysfs::telldir (DIR *dir)
+{
+  return dir->__d_position;
+}
+
+void
+fhandler_sysfs::seekdir (DIR *dir, long pos)
+{
+  dir->__d_position = pos;
+}
+
+int
+fhandler_sysfs::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_sysfs::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_sysfs::write (const void *ptr, size_t len)
+{
+  return fhandler_base::raw_write (ptr, len);
+}
+
+int
+fhandler_sysfs::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, NULL, NULL);
+  switch (exists ())
+    {
+    case virt_directory:
+    case virt_rootdir:
+    case virt_dir_nobs:
+      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_sysfs::open (%p, %d)", res, flags, mode);
+  return res;
+}
+
+int
+fhandler_sysfs::close ()
+{
+  if (!nohandle ())
+    NtClose (get_handle ());
+  return fhandler_virtual::close ();
+}
Index: fhandler_virtual.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_virtual.cc,v
retrieving revision 1.52
diff -u -p -r1.52 fhandler_virtual.cc
--- fhandler_virtual.cc	5 Jul 2010 16:59:56 -0000	1.52
+++ fhandler_virtual.cc	2 Sep 2010 16:13:52 -0000
@@ -225,10 +225,10 @@ fhandler_virtual::open (int flags, mode_
   return 1;
 }
 
-int
+virtual_ftype_t
 fhandler_virtual::exists ()
 {
-  return 0;
+  return virt_none;
 }
 
 bool
Index: fhandler_virtual.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_virtual.h,v
retrieving revision 1.1
diff -u -p -r1.1 fhandler_virtual.h
--- fhandler_virtual.h	20 Jan 2009 17:22:11 -0000	1.1
+++ fhandler_virtual.h	2 Sep 2010 16:13:52 -0000
@@ -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,16 +8,6 @@ This software is a copyrighted work lice
 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;
   __dev32_t fhandler;
Index: globals.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/globals.cc,v
retrieving revision 1.21
diff -u -p -r1.21 globals.cc
--- globals.cc	30 Aug 2010 01:57:36 -0000	1.21
+++ globals.cc	2 Sep 2010 16:13:52 -0000
@@ -99,6 +99,7 @@ UNICODE_STRING _RDATA ro_u_com = _ROU (L
 UNICODE_STRING _RDATA ro_u_scr = _ROU (L".scr");
 UNICODE_STRING _RDATA ro_u_sys = _ROU (L".sys");
 UNICODE_STRING _RDATA ro_u_proc = _ROU (L"proc");
+UNICODE_STRING _RDATA ro_u_sysfs = _ROU (L"sys");
 UNICODE_STRING _RDATA ro_u_pmem = _ROU (L"\\device\\physicalmemory");
 UNICODE_STRING _RDATA ro_u_natp = _ROU (L"\\??\\");
 UNICODE_STRING _RDATA ro_u_uncp = _ROU (L"\\??\\UNC\\");
Index: mount.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/mount.cc,v
retrieving revision 1.64
diff -u -p -r1.64 mount.cc
--- mount.cc	25 Aug 2010 09:20:11 -0000	1.64
+++ mount.cc	2 Sep 2010 16:13:52 -0000
@@ -45,6 +45,9 @@ details. */
 #define isproc(path) \
   (path_prefix_p (proc, (path), proc_len, false))
 
+#define issysfs(path) \
+  (path_prefix_p (sysfs, (path), sysfs_len, false))
+
 bool NO_COPY mount_info::got_usr_bin;
 bool NO_COPY mount_info::got_usr_lib;
 int NO_COPY mount_info::root_idx = -1;
@@ -520,7 +523,7 @@ mount_info::conv_to_win32_path (const ch
     }
 
   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] == '/')
@@ -553,6 +556,13 @@ mount_info::conv_to_win32_path (const ch
       strcpy (dst, src_path);
       goto out;
     }
+  else if (issysfs (src_path))
+    {
+      dev = *sysfs_dev;
+      set_flags (flags, PATH_BINARY);
+      backslashify (src_path + sysfs_len, dst, 0);
+      goto out;
+    }
   /* Check if the cygdrive prefix was specified.  If so, just strip
      off the prefix and transform it into an MS-DOS path. */
   else if (iscygdrive (src_path))
Index: ntdll.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/ntdll.h,v
retrieving revision 1.101
diff -u -p -r1.101 ntdll.h
--- ntdll.h	27 Aug 2010 17:58:43 -0000	1.101
+++ ntdll.h	2 Sep 2010 16:13:52 -0000
@@ -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_INFORMA
 #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 *,
Index: path.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/path.cc,v
retrieving revision 1.605
diff -u -p -r1.605 path.cc
--- path.cc	31 Aug 2010 13:48:04 -0000	1.605
+++ path.cc	2 Sep 2010 16:13:53 -0000
@@ -760,9 +760,15 @@ path_conv::check (const char *src, unsig
 	  else if (isvirtual_dev (dev.devn))
 	    {
 	      /* FIXME: Calling build_fhandler here is not the right way to handle this. */
+	      char *end = NULL;
+	      if (need_directory && issysfs_dev (dev.devn))
+		{
+		  end = strchr (path_copy, '\0');
+		  stpcpy (end, "/");
+		}
 	      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 +776,67 @@ path_conv::check (const char *src, unsig
 	      delete fh;
 	      switch (file_type)
 		{
-		  case 1:
-		  case 2:
+		  case virt_dir_nobs:
+		    if (end)
+		      *end = '\0';
+		    /*FALLTHRU*/
+		  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:
+		    dev.parse (FH_FS);
+		    if (need_directory)
+		      strcat (full_path, "\\");
+		    goto is_fs_via_sysfs;
+		  case virt_fsdir_nobs:
+		    if (end)
+		      *end = '\0';
+		    /*FALLTHRU*/
+		  case virt_fsfile:
+		    dev.parse (FH_FS);
+		    goto is_fs_via_sysfs;
+		  case virt_blk:
+		    /* If it's a component, and if it has been recognized as
+		       block special device, the target path is definitely
+		       a FS_based path.  So we convert this to a FH_FS device.
+		       The current component path is also lacking the trailing
+		       backslash which converts it from a block device to a
+		       file system's root directory. */
+		    if (component)
+		      {
+			dev.parse (FH_FS);
+			strcat (full_path, "\\");
+			goto is_fs_via_sysfs;
+		      }
+		  case virt_chr:
+		    if (component == 0)
+		      {
+			dev.parse (FH_SYSFS);
+			fileattr = 0;
+		      }
+		    break;
 		  default:
 		    if (component == 0)
 		      fileattr = INVALID_FILE_ATTRIBUTES;
@@ -841,6 +883,8 @@ path_conv::check (const char *src, unsig
 	  if (is_msdos)
 	    sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
 
+is_fs_via_sysfs:
+
 	  symlen = sym.check (full_path, suff, fs, conv_handle);
 
 is_virtual_symlink:
@@ -2471,6 +2515,8 @@ restart:
 			}
 		      fileattr = 0;
 		    }
+		  else if (basename.Length == 0)
+		    fileattr = FILE_ATTRIBUTE_DIRECTORY;
 		  else
 		    fileattr = fdi_buf.fdi.FileAttributes;
 		}
Index: path.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/path.h,v
retrieving revision 1.145
diff -u -p -r1.145 path.h
--- path.h	4 Jul 2010 17:12:26 -0000	1.145
+++ path.h	2 Sep 2010 16:13:53 -0000
@@ -20,8 +20,11 @@ details. */
   (devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS || \
    devn == FH_PROCNET)
 
+#define issysfs_dev(devn) (devn == FH_SYSFS)
+
 #define isvirtual_dev(devn) \
-  (isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE)
+  (isproc_dev (devn) || issysfs_dev (devn) || \
+   devn == FH_CYGDRIVE || devn == FH_NETDRIVE)
 
 inline bool
 has_attribute (DWORD attributes, DWORD attribs_to_test)
Index: syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.565
diff -u -p -r1.565 syscalls.cc
--- syscalls.cc	25 Aug 2010 08:51:41 -0000	1.565
+++ syscalls.cc	2 Sep 2010 16:13:53 -0000
@@ -688,7 +688,7 @@ unlink (const char *ourname)
     }
 
   devn = win32_name.get_devn ();
-  if (isproc_dev (devn))
+  if (isproc_dev (devn) || issysfs_dev (devn))
     {
       set_errno (EROFS);
       goto done;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]