* 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:
parent
d6d9c269e4
commit
483e9d0022
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue