* 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.
This commit is contained in:
		| @@ -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> | 2011-01-13  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* fhandler_disk_file.cc (fhandler_base::fstat_helper): Always set | 	* fhandler_disk_file.cc (fhandler_base::fstat_helper): Always set | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| /* fhandler_proc.cc: fhandler for /proc virtual filesystem | /* 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. | This file is part of Cygwin. | ||||||
|  |  | ||||||
| @@ -24,9 +24,9 @@ details. */ | |||||||
| #include <sys/utsname.h> | #include <sys/utsname.h> | ||||||
| #include <sys/param.h> | #include <sys/param.h> | ||||||
| #include "ntdll.h" | #include "ntdll.h" | ||||||
| #include <ctype.h> |  | ||||||
| #include <winioctl.h> | #include <winioctl.h> | ||||||
| #include <wchar.h> | #include <wchar.h> | ||||||
|  | #include <wctype.h> | ||||||
| #include "cpuid.h" | #include "cpuid.h" | ||||||
| #include "mount.h" | #include "mount.h" | ||||||
|  |  | ||||||
| @@ -85,7 +85,7 @@ proc_tab_cmp (const void *key, const void *memb) | |||||||
|   return ret; |   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. */ |    against the alpha-sorted virtual file table. */ | ||||||
| virt_tab_t * | virt_tab_t * | ||||||
| virt_tab_search (const char *path, bool prefix, const virt_tab_t *table, | 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) |   if (fileid < PROC_LINK_COUNT && proc_tab[fileid].format_func) | ||||||
|     { |     { | ||||||
|       filesize = proc_tab[fileid].format_func (NULL, filebuf); |       filesize = proc_tab[fileid].format_func (NULL, filebuf); | ||||||
|       return true; |       if (filesize > 0) | ||||||
|  | 	return true; | ||||||
|     } |     } | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
| @@ -550,7 +551,10 @@ format_proc_stat (void *, char *&destbuf) | |||||||
| 		      "status %p", ret); | 		      "status %p", ret); | ||||||
|     } |     } | ||||||
|   if (!NT_SUCCESS (ret)) |   if (!NT_SUCCESS (ret)) | ||||||
|     return 0; |     { | ||||||
|  |       __seterrno_from_nt_status (ret); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   pages_in = spi->PagesRead; |   pages_in = spi->PagesRead; | ||||||
|   pages_out = spi->PagefilePagesWritten + spi->MappedFilePagesWritten; |   pages_out = spi->PagefilePagesWritten + spi->MappedFilePagesWritten; | ||||||
| @@ -1085,15 +1089,15 @@ format_proc_cpuinfo (void *, char *&destbuf) | |||||||
| static _off64_t | static _off64_t | ||||||
| format_proc_partitions (void *, char *&destbuf) | format_proc_partitions (void *, char *&destbuf) | ||||||
| { | { | ||||||
|   char devname[NAME_MAX + 1]; |  | ||||||
|   OBJECT_ATTRIBUTES attr; |   OBJECT_ATTRIBUTES attr; | ||||||
|   HANDLE dirhdl, devhdl; |  | ||||||
|   IO_STATUS_BLOCK io; |   IO_STATUS_BLOCK io; | ||||||
|   NTSTATUS status; |   NTSTATUS status; | ||||||
|  |   HANDLE dirhdl; | ||||||
|   tmp_pathbuf tp; |   tmp_pathbuf tp; | ||||||
|  |  | ||||||
|   char *buf = tp.c_get (); |   char *buf = tp.c_get (); | ||||||
|   char *bufptr = buf; |   char *bufptr = buf; | ||||||
|  |   char *ioctl_buf = tp.c_get (); | ||||||
|  |  | ||||||
|   /* Open \Device object directory. */ |   /* Open \Device object directory. */ | ||||||
|   wchar_t wpath[MAX_PATH] = L"\\Device"; |   wchar_t wpath[MAX_PATH] = L"\\Device"; | ||||||
| @@ -1103,102 +1107,157 @@ format_proc_partitions (void *, char *&destbuf) | |||||||
|   if (!NT_SUCCESS (status)) |   if (!NT_SUCCESS (status)) | ||||||
|     { |     { | ||||||
|       debug_printf ("NtOpenDirectoryObject, status %p", status); |       debug_printf ("NtOpenDirectoryObject, status %p", status); | ||||||
|  |       __seterrno_from_nt_status (status); | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   print ("major minor  #blocks  name\n\n"); |  | ||||||
|   /* Traverse \Device directory ... */ |   /* Traverse \Device directory ... */ | ||||||
|   PDIRECTORY_BASIC_INFORMATION dbi = (PDIRECTORY_BASIC_INFORMATION) |   PDIRECTORY_BASIC_INFORMATION dbi = (PDIRECTORY_BASIC_INFORMATION) | ||||||
| 				     alloca (640); | 				     alloca (640); | ||||||
|   BOOLEAN restart = TRUE; |   BOOLEAN restart = TRUE; | ||||||
|  |   bool got_one = false; | ||||||
|   ULONG context = 0; |   ULONG context = 0; | ||||||
|   while (NT_SUCCESS (NtQueryDirectoryObject (dirhdl, dbi, 640, TRUE, restart, |   while (NT_SUCCESS (NtQueryDirectoryObject (dirhdl, dbi, 640, TRUE, restart, | ||||||
| 					     &context, NULL))) | 					     &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; |       restart = FALSE; | ||||||
|       sys_wcstombs (devname, NAME_MAX + 1, dbi->ObjectName.Buffer, |  | ||||||
| 		    dbi->ObjectName.Length / 2); |  | ||||||
|       /* ... and check for a "Harddisk[0-9]*" entry. */ |       /* ... and check for a "Harddisk[0-9]*" entry. */ | ||||||
|       if (!strncasematch (devname, "Harddisk", 8) |       if (dbi->ObjectName.Length < 18 | ||||||
| 	  || dbi->ObjectName.Length < 18 | 	  || wcsncasecmp (dbi->ObjectName.Buffer, L"Harddisk", 8) != 0 | ||||||
| 	  || !isdigit (devname[8])) | 	  || !iswdigit (dbi->ObjectName.Buffer[8])) | ||||||
| 	continue; | 	continue; | ||||||
|       /* Construct path name for partitions, starting with 0, which is the |       /* Got it.  Now construct the path to the entire disk, which is | ||||||
| 	 whole disk, and try to open. | 	 "\\Device\\HarddiskX\\Partition0", and open the disk with | ||||||
| 	 Note that the correct way to do this would be to open the HarddiskX | 	 minimum permssions. */ | ||||||
| 	 directory and enumerate the Partition entries.  However, while the |       unsigned long drive_num = wcstoul (dbi->ObjectName.Buffer + 8, NULL, 10); | ||||||
| 	 partition entries itself are accessible for query by everyone, the |       wcscpy (wpath, dbi->ObjectName.Buffer); | ||||||
| 	 HarddiskX parent directory is only queryable by SYSTEM and Admins. |       PWCHAR wpart = wpath + dbi->ObjectName.Length / sizeof (WCHAR); | ||||||
| 	 This way we circumvent this nonsensical restriction.  Let's assume |       __small_swprintf (wpart, L"\\Partition0"); | ||||||
| 	 we never have more than 99 partitions per disk for now... */ |       upath.Length = dbi->ObjectName.Length | ||||||
|       for (int part_num = 0; part_num < 99; ++part_num) | 		     + 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); | 	  debug_printf ("NtOpenFile(%S), status %p", &upath, status); | ||||||
| 	  __small_swprintf (wpath + dbi->ObjectName.Length / 2, | 	  __seterrno_from_nt_status (status); | ||||||
| 			    L"\\Partition%d", part_num); | 	  continue; | ||||||
| 	  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); |  | ||||||
| 	} | 	} | ||||||
|  |       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); |   NtClose (dirhdl); | ||||||
|  |  | ||||||
|  |   if (!got_one) | ||||||
|  |     return 0; | ||||||
|  |  | ||||||
|   destbuf = (char *) crealloc_abort (destbuf, bufptr - buf); |   destbuf = (char *) crealloc_abort (destbuf, bufptr - buf); | ||||||
|   memcpy (destbuf, buf, bufptr - buf); |   memcpy (destbuf, buf, bufptr - buf); | ||||||
|   return bufptr - buf; |   return bufptr - buf; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user