* autoload.cc: Add dynamic load statements for 'ZwQueryInformationProcess' and

'ZwQueryVirtualMemory'.
* fhandler.h: Change type of bufalloc and filesize members of fhandler_virtual
from int to size_t.  Change type of position member from __off32_t to
__off64_t.  Add new fileid member to fhandler_virtual class.  Make seekdir take
an __off64_t argument.  Make lseek take an __off64_t argument.  Add
fill_filebuf method to fhandler_virtual.  Add fill_filebuf method to
fhandler_proc.  Add fill_filebuf method to fhandler_registry.  Add fill_filebuf
method to fhandler_process.  Add saved_pid and saved_p members to
fhandler_process.
* fhandler_proc.cc (proc_listing_array): Add 'loadavg', 'meminfo', and 'stat'.
(proc_fhandlers array): Ditto.
(fhandler_proc::open): Use fill_filebuf to flesh out the file contents.
(fhandler_proc::fill_filebuf): New method.
(fhandler_proc::format_proc_meminfo): Ditto.
(fhandler_proc::format_proc_stat): Ditto.
(fhandler_proc::format_proc_uptime): Ditto.
* fhandler_process.cc (process_listing): Add 'stat' and 'statm'.
(fhandler_process::fstat): Find the _pinfo structure for the process named in
the filename.  Return ENOENT if the process is no longer around.  Set the gid
and uid fields of the stat structure.
(fhandler_process::open): Store pid and pointer to _pinfo structure in
saved_pid and saved_p respectively.  Use fill_filebuf to flesh out file
contents.
(fhandler_proc::fill_filebuf): New method.
(format_process_stat): New function.
(format_process_status): Ditto.
(format_process_statm): Ditto.
(get_process_state): Ditto.
(get_mem_values): Ditto.
* fhandler_registry.cc (fhandler_registry::seekdir): Change argument type from
__off32_t to __off64_t.
(fhandler_registry::fill_filebuf): New method.
* fhandler_virtual.cc (fhandler_virtual::seekdir): Change argument type from
__off32_t to __off64_t.
(fhandler_virtual::lseek): Ditto.
(fhandler_virtual::fill_filebuf): New method.
(fhandler_virtual::fhandler_virtual): Initialise fileid to -1.
* wincap.cc: Set flag has_process_io_counters appropriately.
* wincap.h: Add flag has_process_io_counters.
This commit is contained in:
Christopher Faylor
2002-05-12 01:37:48 +00:00
parent 558ab81ed1
commit 9ba913a56d
10 changed files with 1059 additions and 131 deletions

View File

@ -14,6 +14,7 @@ details. */
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
#include <ntdef.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
@ -24,20 +25,27 @@ details. */
#include "cygheap.h"
#include <assert.h>
#include <sys/utsname.h>
#include "ntdll.h"
#define _COMPILING_NEWLIB
#include <dirent.h>
/* offsets in proc_listing */
static const int PROC_REGISTRY = 2; // /proc/registry
static const int PROC_VERSION = 3; // /proc/version
static const int PROC_UPTIME = 4; // /proc/uptime
static const int PROC_LOADAVG = 2; // /proc/loadavg
static const int PROC_MEMINFO = 3; // /proc/meminfo
static const int PROC_REGISTRY = 4; // /proc/registry
static const int PROC_STAT = 5; // /proc/stat
static const int PROC_VERSION = 6; // /proc/version
static const int PROC_UPTIME = 7; // /proc/uptime
/* names of objects in /proc */
static const char *proc_listing[] = {
".",
"..",
"loadavg",
"meminfo",
"registry",
"stat",
"version",
"uptime",
NULL
@ -48,11 +56,14 @@ static const int PROC_LINK_COUNT = (sizeof(proc_listing) / sizeof(const char *))
/* FH_PROC in the table below means the file/directory is handles by
* fhandler_proc.
*/
static const DWORD proc_fhandlers[] = {
static const DWORD proc_fhandlers[PROC_LINK_COUNT] = {
FH_PROC,
FH_PROC,
FH_PROC,
FH_PROC,
FH_REGISTRY,
FH_PROC,
FH_PROC,
FH_PROC
};
@ -60,6 +71,10 @@ static const DWORD proc_fhandlers[] = {
const char proc[] = "/proc";
const int proc_len = sizeof (proc) - 1;
static off_t format_proc_meminfo (char *destbuf, size_t maxsize);
static off_t format_proc_stat (char *destbuf, size_t maxsize);
static off_t format_proc_uptime (char *destbuf, size_t maxsize);
/* 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
@ -291,33 +306,9 @@ fhandler_proc::open (path_conv *pc, int flags, mode_t mode)
res = 0;
goto out;
}
switch (proc_file_no)
{
case PROC_VERSION:
{
struct utsname uts_name;
uname (&uts_name);
filesize = bufalloc = strlen (uts_name.sysname) + 1 +
strlen (uts_name.release) + 1 + strlen (uts_name.version) + 2;
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc);
__small_sprintf (filebuf, "%s %s %s\n", uts_name.sysname,
uts_name.release, uts_name.version);
break;
}
case PROC_UPTIME:
{
/* GetTickCount() wraps after 49 days - on WinNT/2000/XP, should use
* perfomance counters but I don't know Redhat's policy on
* NT only dependancies.
*/
DWORD ticks = GetTickCount ();
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
__small_sprintf (filebuf, "%d.%02d\n", ticks / 1000,
(ticks / 10) % 100);
filesize = strlen (filebuf);
break;
}
}
fileid = proc_file_no;
fill_filebuf ();
if (flags & O_APPEND)
position = filesize;
@ -332,3 +323,197 @@ out:
syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode);
return res;
}
void
fhandler_proc::fill_filebuf ()
{
switch (fileid)
{
case PROC_VERSION:
{
if (!filebuf)
{
struct utsname uts_name;
uname (&uts_name);
bufalloc = strlen (uts_name.sysname) + 1 + strlen (uts_name.release) +
1 + strlen (uts_name.version) + 2;
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc);
filesize = __small_sprintf (filebuf, "%s %s %s\n", uts_name.sysname,
uts_name.release, uts_name.version);
}
break;
}
case PROC_UPTIME:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 80);
filesize = format_proc_uptime (filebuf, bufalloc);
break;
}
case PROC_STAT:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
filesize = format_proc_stat (filebuf, bufalloc);
break;
}
case PROC_LOADAVG:
{
/*
* not really supported - Windows doesn't keep track of these values
* Windows 95/98/me does have the KERNEL/CPUUsage performance counter
* which is similar.
*/
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 16);
filesize = __small_sprintf (filebuf, "%u.%02u %u.%02u %u.%02u\n",
0, 0, 0, 0, 0, 0);
break;
}
case PROC_MEMINFO:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
filesize = format_proc_meminfo (filebuf, bufalloc);
break;
}
}
}
static
off_t
format_proc_meminfo (char *destbuf, size_t maxsize)
{
unsigned long mem_total = 0UL, mem_free = 0UL, swap_total = 0UL,
swap_free = 0UL;
MEMORYSTATUS memory_status;
GlobalMemoryStatus (&memory_status);
mem_total = memory_status.dwTotalPhys;
mem_free = memory_status.dwAvailPhys;
swap_total = memory_status.dwTotalPageFile;
swap_free = memory_status.dwAvailPageFile;
return __small_sprintf (destbuf, " total: used: free:\n"
"Mem: %10lu %10lu %10lu\n"
"Swap: %10lu %10lu %10lu\n"
"MemTotal: %10lu kB\n"
"MemFree: %10lu kB\n"
"MemShared: 0 kB\n"
"HighTotal: 0 kB\n"
"HighFree: 0 kB\n"
"LowTotal: %10lu kB\n"
"LowFree: %10lu kB\n"
"SwapTotal: %10lu kB\n"
"SwapFree: %10lu kB\n",
mem_total, mem_total - mem_free, mem_free,
swap_total, swap_total - swap_free, swap_free,
mem_total >> 10, mem_free >> 10,
mem_total >> 10, mem_free >> 10,
swap_total >> 10, swap_free >> 10);
}
static
off_t
format_proc_uptime (char *destbuf, size_t maxsize)
{
unsigned long long uptime = 0ULL, idle_time = 0ULL;
SYSTEM_PROCESSOR_TIMES spt;
NTSTATUS ret = ZwQuerySystemInformation (SystemProcessorTimes, (PVOID) &spt,
sizeof spt, NULL);
if (!ret && GetLastError () == ERROR_PROC_NOT_FOUND)
uptime = GetTickCount() / 10;
else if (ret != STATUS_SUCCESS)
{
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
debug_printf("NtQuerySystemInformation: ret = %d, "
"Dos(ret) = %d",
ret, RtlNtStatusToDosError (ret));
return 0;
}
else
{
idle_time = spt.IdleTime.QuadPart / 100000ULL;
uptime = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart +
spt.IdleTime.QuadPart + spt.UserTime.QuadPart +
spt.DpcTime.QuadPart) / 100000ULL;
}
return __small_sprintf (destbuf, "%U.%02u %U.%02u\n",
uptime / 100, long (uptime % 100),
idle_time / 100, long (idle_time % 100));
}
static
off_t
format_proc_stat (char *destbuf, size_t maxsize)
{
unsigned long long user_time = 0ULL, kernel_time = 0ULL, idle_time = 0ULL;
unsigned long pages_in = 0UL, pages_out = 0UL, interrupt_count = 0UL,
context_switches = 0UL, swap_in = 0UL, swap_out = 0UL;
time_t boot_time = 0;
if (wincap.is_winnt ())
{
NTSTATUS ret;
SYSTEM_PROCESSOR_TIMES spt;
SYSTEM_PERFORMANCE_INFORMATION spi;
SYSTEM_TIME_OF_DAY_INFORMATION stodi;
ret = ZwQuerySystemInformation (SystemProcessorTimes,
(PVOID) &spt,
sizeof spt, NULL);
if (ret == STATUS_SUCCESS)
ret = ZwQuerySystemInformation (SystemPerformanceInformation,
(PVOID) &spi,
sizeof spi, NULL);
if (ret == STATUS_SUCCESS)
ret = ZwQuerySystemInformation (SystemTimeOfDayInformation,
(PVOID) &stodi,
sizeof stodi, NULL);
if (ret != STATUS_SUCCESS)
{
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
debug_printf("NtQuerySystemInformation: ret = %d, "
"Dos(ret) = %d",
ret, RtlNtStatusToDosError (ret));
return 0;
}
kernel_time = (spt.KernelTime.QuadPart + spt.InterruptTime.QuadPart + spt.DpcTime.QuadPart) / 100000ULL;
user_time = spt.UserTime.QuadPart / 100000ULL;
idle_time = spt.IdleTime.QuadPart / 100000ULL;
interrupt_count = spt.InterruptCount;
pages_in = spi.PagesRead;
pages_out = spi.PagefilePagesWritten + spi.MappedFilePagesWritten;
/*
* Note: there is no distinction made in this structure between pages
* read from the page file and pages read from mapped files, but there
* is such a distinction made when it comes to writing. Goodness knows
* why. The value of swap_in, then, will obviously be wrong but its our
* best guess.
*/
swap_in = spi.PagesRead;
swap_out = spi.PagefilePagesWritten;
context_switches = spi.ContextSwitches;
boot_time = to_time_t ((FILETIME *) &stodi.BootTime.QuadPart);
}
/*
* else
* {
* There are only two relevant performance counters on Windows 95/98/me,
* VMM/cPageIns and VMM/cPageOuts. The extra effort needed to read these
* counters is by no means worth it.
* }
*/
return __small_sprintf (destbuf, "cpu %U %U %U %U\n"
"page %u %u\n"
"swap %u %u\n"
"intr %u\n"
"ctxt %u\n"
"btime %u\n",
user_time, 0ULL,
kernel_time, idle_time,
pages_in, pages_out,
swap_in, swap_out,
interrupt_count,
context_switches,
boot_time);
}