]> sourceware.org Git - newlib-cygwin.git/commitdiff
* fhandler_proc.cc (proc_tab_cmp): Fix typo in comment.
authorCorinna Vinschen <corinna@vinschen.de>
Mon, 17 Jan 2011 13:38:06 +0000 (13:38 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Mon, 17 Jan 2011 13:38:06 +0000 (13:38 +0000)
(fhandler_proc::fill_filebuf): Handle return value of 0 from format
function as error.
(format_proc_stat): Set errno when returning 0 size.
(format_proc_partitions): Rewrite method to fetch partition info.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler_proc.cc

index e5888caff4f1ea39b3467c0dda66bd34cb04ea12..6c0b2a2b234e1d54c17ffa8a3ba6314b68eb2c56 100644 (file)
@@ -1,3 +1,11 @@
+2011-01-17  Corinna Vinschen  <corinna@vinschen.de>
+
+       * fhandler_proc.cc (proc_tab_cmp): Fix typo in comment.
+       (fhandler_proc::fill_filebuf): Handle return value of 0 from format
+       function as error.
+       (format_proc_stat): Set errno when returning 0 size.
+       (format_proc_partitions): Rewrite method to fetch partition info.
+
 2011-01-13  Corinna Vinschen  <corinna@vinschen.de>
 
        * fhandler_disk_file.cc (fhandler_base::fstat_helper): Always set
index df381127aa3bd8f4bb6ffce4a85111fa296baf53..68092775010ca70638b160ffd2f1fb31c51e764d 100644 (file)
@@ -1,6 +1,6 @@
 /* fhandler_proc.cc: fhandler for /proc virtual filesystem
 
-   Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 Red Hat, Inc.
+   Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 Red Hat, Inc.
 
 This file is part of Cygwin.
 
@@ -24,9 +24,9 @@ details. */
 #include <sys/utsname.h>
 #include <sys/param.h>
 #include "ntdll.h"
-#include <ctype.h>
 #include <winioctl.h>
 #include <wchar.h>
+#include <wctype.h>
 #include "cpuid.h"
 #include "mount.h"
 
@@ -85,7 +85,7 @@ proc_tab_cmp (const void *key, const void *memb)
   return ret;
 }
 
-/* Helper function to perform a binary search of  the incoming pathname
+/* 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,
@@ -351,7 +351,8 @@ fhandler_proc::fill_filebuf ()
   if (fileid < PROC_LINK_COUNT && proc_tab[fileid].format_func)
     {
       filesize = proc_tab[fileid].format_func (NULL, filebuf);
-      return true;
+      if (filesize > 0)
+       return true;
     }
   return false;
 }
@@ -550,7 +551,10 @@ format_proc_stat (void *, char *&destbuf)
                      "status %p", ret);
     }
   if (!NT_SUCCESS (ret))
-    return 0;
+    {
+      __seterrno_from_nt_status (ret);
+      return 0;
+    }
 
   pages_in = spi->PagesRead;
   pages_out = spi->PagefilePagesWritten + spi->MappedFilePagesWritten;
@@ -1085,15 +1089,15 @@ format_proc_cpuinfo (void *, char *&destbuf)
 static _off64_t
 format_proc_partitions (void *, char *&destbuf)
 {
-  char devname[NAME_MAX + 1];
   OBJECT_ATTRIBUTES attr;
-  HANDLE dirhdl, devhdl;
   IO_STATUS_BLOCK io;
   NTSTATUS status;
+  HANDLE dirhdl;
   tmp_pathbuf tp;
 
   char *buf = tp.c_get ();
   char *bufptr = buf;
+  char *ioctl_buf = tp.c_get ();
 
   /* Open \Device object directory. */
   wchar_t wpath[MAX_PATH] = L"\\Device";
@@ -1103,102 +1107,157 @@ format_proc_partitions (void *, char *&destbuf)
   if (!NT_SUCCESS (status))
     {
       debug_printf ("NtOpenDirectoryObject, status %p", status);
+      __seterrno_from_nt_status (status);
       return 0;
     }
 
-  print ("major minor  #blocks  name\n\n");
   /* Traverse \Device directory ... */
   PDIRECTORY_BASIC_INFORMATION dbi = (PDIRECTORY_BASIC_INFORMATION)
                                     alloca (640);
   BOOLEAN restart = TRUE;
+  bool got_one = false;
   ULONG context = 0;
   while (NT_SUCCESS (NtQueryDirectoryObject (dirhdl, dbi, 640, TRUE, restart,
                                             &context, NULL)))
     {
+      HANDLE devhdl;
+      PARTITION_INFORMATION_EX *pix = NULL;
+      PARTITION_INFORMATION *pi = NULL;
+      DWORD bytes_read;
+      DWORD part_cnt;
+      unsigned long long size;
+      device dev;
+
       restart = FALSE;
-      sys_wcstombs (devname, NAME_MAX + 1, dbi->ObjectName.Buffer,
-                   dbi->ObjectName.Length / 2);
       /* ... and check for a "Harddisk[0-9]*" entry. */
-      if (!strncasematch (devname, "Harddisk", 8)
-         || dbi->ObjectName.Length < 18
-         || !isdigit (devname[8]))
+      if (dbi->ObjectName.Length < 18
+         || wcsncasecmp (dbi->ObjectName.Buffer, L"Harddisk", 8) != 0
+         || !iswdigit (dbi->ObjectName.Buffer[8]))
        continue;
-      /* Construct path name for partitions, starting with 0, which is the
-        whole disk, and try to open.
-        Note that the correct way to do this would be to open the HarddiskX
-        directory and enumerate the Partition entries.  However, while the
-        partition entries itself are accessible for query by everyone, the
-        HarddiskX parent directory is only queryable by SYSTEM and Admins.
-        This way we circumvent this nonsensical restriction.  Let's assume
-        we never have more than 99 partitions per disk for now... */
-      for (int part_num = 0; part_num < 99; ++part_num)
+      /* Got it.  Now construct the path to the entire disk, which is
+        "\\Device\\HarddiskX\\Partition0", and open the disk with
+        minimum permssions. */
+      unsigned long drive_num = wcstoul (dbi->ObjectName.Buffer + 8, NULL, 10);
+      wcscpy (wpath, dbi->ObjectName.Buffer);
+      PWCHAR wpart = wpath + dbi->ObjectName.Length / sizeof (WCHAR);
+      __small_swprintf (wpart, L"\\Partition0");
+      upath.Length = dbi->ObjectName.Length
+                    + wcslen (wpart) * sizeof (WCHAR);
+      upath.MaximumLength = upath.Length + sizeof (WCHAR);
+      InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
+                                 dirhdl, NULL);
+      /* Up to W2K the handle needs read access to fetch the partition info. */
+      status = NtOpenFile (&devhdl, wincap.has_disk_ex_ioctls ()
+                                   ? READ_CONTROL
+                                   : READ_CONTROL | FILE_READ_DATA,
+                          &attr, &io, FILE_SHARE_VALID_FLAGS, 0);
+      if (!NT_SUCCESS (status))
        {
-         wcscpy (wpath, dbi->ObjectName.Buffer);
-         __small_swprintf (wpath + dbi->ObjectName.Length / 2,
-                           L"\\Partition%d", part_num);
-         upath.Length = 22 + dbi->ObjectName.Length;
-         upath.MaximumLength = upath.Length + 2;
-         InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
-                                     dirhdl, NULL);
-         status = NtOpenFile (&devhdl, READ_CONTROL, &attr, &io,
-                              FILE_SHARE_VALID_FLAGS, 0);
-         if (!NT_SUCCESS (status))
-           {
-             if (status == STATUS_OBJECT_NAME_NOT_FOUND
-                 || status == STATUS_OBJECT_PATH_NOT_FOUND)
-               break;
-             debug_printf ("NtOpenFile(%s), status %p", devname, status);
-             continue;
-           }
-
-         /* Use a buffer since some ioctl buffers aren't fixed size. */
-         char buf[256];
-         PARTITION_INFORMATION *pi = NULL;
-         PARTITION_INFORMATION_EX *pix = NULL;
-         DISK_GEOMETRY *dg = NULL;
-         DWORD bytes;
-         unsigned long drive_number = strtoul (devname + 8, NULL, 10);
-         unsigned long long size;
-
-         if (wincap.has_disk_ex_ioctls ()
-             && DeviceIoControl (devhdl, IOCTL_DISK_GET_PARTITION_INFO_EX,
-                                 NULL, 0, buf, 256, &bytes, NULL))
-           {
-             pix = (PARTITION_INFORMATION_EX *) buf;
-             size = pix->PartitionLength.QuadPart;
-           }
-         else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_PARTITION_INFO,
-                                   NULL, 0, buf, 256, &bytes, NULL))
-           {
-             pi = (PARTITION_INFORMATION *) buf;
-             size = pi->PartitionLength.QuadPart;
-           }
-         else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_DRIVE_GEOMETRY,
-                                   NULL, 0, buf, 256, &bytes, NULL))
-           {
-             dg = (DISK_GEOMETRY *) buf;
-             size = (unsigned long long) dg->Cylinders.QuadPart
-                          * dg->TracksPerCylinder
-                          * dg->SectorsPerTrack
-                          * dg->BytesPerSector;
-           }
-         else
-           size = 0;
-         if (!pi && !pix && !dg)
-           debug_printf ("DeviceIoControl %E");
-         else
-           {
-             device dev;
-             dev.parsedisk (drive_number, part_num);
-             bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n",
-                                        dev.major, dev.minor,
-                                        size >> 10, dev.name + 5);
-           }
-         NtClose (devhdl);
+         debug_printf ("NtOpenFile(%S), status %p", &upath, status);
+         __seterrno_from_nt_status (status);
+         continue;
+       }
+      if (!got_one)
+       {
+         print ("major minor  #blocks  name\n\n");
+         got_one = true;
+       }
+      /* Fetch partition info for the entire disk to get its size. */
+      if (wincap.has_disk_ex_ioctls ()
+         && DeviceIoControl (devhdl, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0,
+                             ioctl_buf, NT_MAX_PATH, &bytes_read, NULL))
+       {
+         pix = (PARTITION_INFORMATION_EX *) ioctl_buf;
+         size = pix->PartitionLength.QuadPart;
        }
+      else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
+                               ioctl_buf, NT_MAX_PATH, &bytes_read, NULL))
+       {
+         pi = (PARTITION_INFORMATION *) ioctl_buf;
+         size = pi->PartitionLength.QuadPart;
+       }
+      else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
+                               ioctl_buf, NT_MAX_PATH, &bytes_read, NULL))
+       {
+         /* NT4 doesn't support to call IOCTL_DISK_GET_PARTITION_INFO for the
+            entire drive. */
+         DISK_GEOMETRY *dg = (DISK_GEOMETRY *) ioctl_buf;
+         size = (unsigned long long) dg->Cylinders.QuadPart
+                                     * dg->TracksPerCylinder
+                                     * dg->SectorsPerTrack
+                                     * dg->BytesPerSector;
+       }
+      else
+       {
+         debug_printf ("DeviceIoControl (%S, "
+                        "IOCTL_DISK_GET_PARTITION_INFO{_EX}) %E", &upath);
+         size = 0;
+       }
+      dev.parsedisk (drive_num, 0);
+      bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n",
+                                dev.major, dev.minor,
+                                size >> 10, dev.name + 5);
+      /* Fetch drive layout info to get size of all partitions on the disk. */
+      if (wincap.has_disk_ex_ioctls ()
+         && DeviceIoControl (devhdl, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
+                             NULL, 0, ioctl_buf, NT_MAX_PATH, &bytes_read, NULL))
+       {
+         PDRIVE_LAYOUT_INFORMATION_EX pdlix = (PDRIVE_LAYOUT_INFORMATION_EX)
+                                              ioctl_buf;
+         part_cnt = pdlix->PartitionCount;
+         pix = pdlix->PartitionEntry;
+       }
+      else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_DRIVE_LAYOUT,
+                               NULL, 0, ioctl_buf, NT_MAX_PATH, &bytes_read, NULL))
+       {
+         PDRIVE_LAYOUT_INFORMATION pdli = (PDRIVE_LAYOUT_INFORMATION) ioctl_buf;
+         part_cnt = pdli->PartitionCount;
+         pi = pdli->PartitionEntry;
+       }
+      else
+       debug_printf ("DeviceIoControl(%S, "
+                     "IOCTL_DISK_GET_DRIVE_LAYOUT{_EX}): %E", &upath);
+      /* Loop over partitions. */
+      if (pix || pi)
+       for (DWORD i = 0; i < part_cnt; ++i)
+         {
+           DWORD part_num;
+
+           if (pix)
+             {
+               size = pix->PartitionLength.QuadPart;
+               part_num = pix->PartitionNumber;
+               ++pix;
+             }
+           else
+             {
+               size = pi->PartitionLength.QuadPart;
+               /* Pre-W2K you can't rely on the partition number info for
+                  unused partitions. */
+               if (pi->PartitionType == PARTITION_ENTRY_UNUSED
+                   || pi->PartitionType == PARTITION_EXTENDED)
+                 part_num = 0;
+               else
+                 part_num = pi->PartitionNumber;
+               ++pi;
+             }
+           /* A partition number of 0 denotes an extended partition or a
+              filler entry as described in fhandler_dev_floppy::lock_partition.
+              Just skip. */
+           if (part_num == 0)
+             continue;
+           dev.parsedisk (drive_num, part_num);
+           bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n",
+                                      dev.major, dev.minor,
+                                      size >> 10, dev.name + 5);
+         }
+      NtClose (devhdl);
     }
   NtClose (dirhdl);
 
+  if (!got_one)
+    return 0;
+
   destbuf = (char *) crealloc_abort (destbuf, bufptr - buf);
   memcpy (destbuf, buf, bufptr - buf);
   return bufptr - buf;
This page took 0.038394 seconds and 5 git commands to generate.