* 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:
parent
558ab81ed1
commit
9ba913a56d
@ -1,4 +1,47 @@
|
||||
2002-05-09 Christopher Faylor <cgf@redhat.com>
|
||||
2002-05-10 Christopher January <chris@atomice.net>
|
||||
|
||||
* 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.
|
||||
|
||||
2002-05-09 Christopher Faylor <cgf@redhat.com>
|
||||
|
||||
* syscalls.cc (_write): Change error to EBADF if attempt to write to a
|
||||
non-writable fd.
|
||||
|
@ -381,6 +381,8 @@ LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
|
||||
LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
|
||||
LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
|
||||
LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1)
|
||||
LoadDLLfuncEx (ZwQueryInformationProcess, 20, ntdll, 1)
|
||||
LoadDLLfuncEx (ZwQueryVirtualMemory, 24, ntdll, 1)
|
||||
|
||||
LoadDLLfuncEx (GetProcessMemoryInfo, 12, psapi, 1)
|
||||
|
||||
|
@ -1043,8 +1043,9 @@ class fhandler_virtual : public fhandler_base
|
||||
{
|
||||
protected:
|
||||
char *filebuf;
|
||||
int bufalloc, filesize;
|
||||
__off32_t position;
|
||||
size_t bufalloc, filesize;
|
||||
__off64_t position;
|
||||
int fileid; // unique within each class
|
||||
public:
|
||||
|
||||
fhandler_virtual (DWORD devtype);
|
||||
@ -1053,16 +1054,17 @@ class fhandler_virtual : public fhandler_base
|
||||
virtual int exists(const char *path);
|
||||
DIR *opendir (path_conv& pc);
|
||||
__off64_t telldir (DIR *);
|
||||
void seekdir (DIR *, __off32_t);
|
||||
void seekdir (DIR *, __off64_t);
|
||||
void rewinddir (DIR *);
|
||||
int closedir (DIR *);
|
||||
int write (const void *ptr, size_t len);
|
||||
int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3)));
|
||||
__off64_t lseek (__off32_t, int);
|
||||
__off64_t lseek (__off64_t, int);
|
||||
int dup (fhandler_base * child);
|
||||
int open (path_conv *, int flags, mode_t mode = 0);
|
||||
int close (void);
|
||||
int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (3)));
|
||||
virtual void fill_filebuf ();
|
||||
};
|
||||
|
||||
class fhandler_proc: public fhandler_virtual
|
||||
@ -1076,6 +1078,7 @@ class fhandler_proc: public fhandler_virtual
|
||||
|
||||
int open (path_conv *real_path, int flags, mode_t mode = 0);
|
||||
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
|
||||
void fill_filebuf ();
|
||||
};
|
||||
|
||||
class fhandler_registry: public fhandler_proc
|
||||
@ -1085,23 +1088,29 @@ class fhandler_registry: public fhandler_proc
|
||||
int exists(const char *path);
|
||||
struct dirent *readdir (DIR *);
|
||||
__off64_t telldir (DIR *);
|
||||
void seekdir (DIR *, __off32_t);
|
||||
void seekdir (DIR *, __off64_t);
|
||||
void rewinddir (DIR *);
|
||||
int closedir (DIR *);
|
||||
|
||||
int open (path_conv *real_path, int flags, mode_t mode = 0);
|
||||
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
|
||||
HKEY open_key(const char *name, REGSAM access = KEY_READ, bool isValue = false);
|
||||
void fill_filebuf ();
|
||||
};
|
||||
|
||||
struct _pinfo;
|
||||
class fhandler_process: public fhandler_proc
|
||||
{
|
||||
private:
|
||||
pid_t saved_pid;
|
||||
_pinfo *saved_p;
|
||||
public:
|
||||
fhandler_process ();
|
||||
int exists(const char *path);
|
||||
struct dirent *readdir (DIR *);
|
||||
int open (path_conv *real_path, int flags, mode_t mode = 0);
|
||||
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
|
||||
void fill_filebuf ();
|
||||
};
|
||||
|
||||
typedef union
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
@ -23,6 +24,7 @@ details. */
|
||||
#include "shared_info.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "ntdll.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define _COMPILING_NEWLIB
|
||||
@ -38,6 +40,8 @@ static const int PROCESS_GID = 8;
|
||||
static const int PROCESS_PGID = 9;
|
||||
static const int PROCESS_SID = 10;
|
||||
static const int PROCESS_CTTY = 11;
|
||||
static const int PROCESS_STAT = 12;
|
||||
static const int PROCESS_STATM = 13;
|
||||
|
||||
static const char *process_listing[] = {
|
||||
".",
|
||||
@ -52,11 +56,20 @@ static const char *process_listing[] = {
|
||||
"pgid",
|
||||
"sid",
|
||||
"ctty",
|
||||
"stat",
|
||||
"statm",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const int PROCESS_LINK_COUNT = (sizeof(process_listing) / sizeof(const char *)) - 1;
|
||||
|
||||
static off_t format_process_stat (_pinfo *p, char *destbuf, size_t maxsize);
|
||||
static off_t format_process_status (_pinfo *p, char *destbuf, size_t maxsize);
|
||||
static off_t format_process_statm (_pinfo *p, char *destbuf, size_t maxsize);
|
||||
static int get_process_state (DWORD dwProcessId);
|
||||
static bool get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext,
|
||||
unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare);
|
||||
|
||||
/* Returns 0 if path doesn't exist, >0 if path is a directory,
|
||||
* <0 if path is a file.
|
||||
*/
|
||||
@ -84,8 +97,26 @@ fhandler_process::fhandler_process ():
|
||||
int
|
||||
fhandler_process::fstat (struct __stat64 *buf, path_conv *pc)
|
||||
{
|
||||
int file_type = exists (get_name ());
|
||||
const char *path = get_name ();
|
||||
int file_type = exists (path);
|
||||
(void) fhandler_base::fstat (buf, pc);
|
||||
path += proc_len + 1;
|
||||
int pid = atoi (path);
|
||||
winpids pids;
|
||||
_pinfo *p;
|
||||
for (unsigned i = 0; i < pids.npids; i++)
|
||||
{
|
||||
p = pids[i];
|
||||
|
||||
if (!proc_exists (p))
|
||||
continue;
|
||||
|
||||
if (p->pid == pid)
|
||||
goto found;
|
||||
}
|
||||
set_errno(ENOENT);
|
||||
return -1;
|
||||
found:
|
||||
buf->st_mode &= ~_IFMT & NO_W;
|
||||
|
||||
switch (file_type)
|
||||
@ -97,12 +128,18 @@ fhandler_process::fstat (struct __stat64 *buf, path_conv *pc)
|
||||
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
return 0;
|
||||
case 2:
|
||||
buf->st_ctime = buf->st_mtime = p->start_time;
|
||||
buf->st_atime = time(NULL);
|
||||
buf->st_uid = p->uid;
|
||||
buf->st_gid = p->gid;
|
||||
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
buf->st_nlink = PROCESS_LINK_COUNT;
|
||||
return 0;
|
||||
default:
|
||||
case -1:
|
||||
buf->st_mode |= S_IFREG;
|
||||
buf->st_uid = p->uid;
|
||||
buf->st_gid = p->gid;
|
||||
buf->st_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -198,91 +235,10 @@ fhandler_process::open (path_conv *pc, int flags, mode_t mode)
|
||||
res = 0;
|
||||
goto out;
|
||||
found:
|
||||
switch (process_file_no)
|
||||
{
|
||||
case PROCESS_UID:
|
||||
case PROCESS_GID:
|
||||
case PROCESS_PGID:
|
||||
case PROCESS_SID:
|
||||
case PROCESS_CTTY:
|
||||
case PROCESS_PPID:
|
||||
{
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
|
||||
int num;
|
||||
switch (process_file_no)
|
||||
{
|
||||
case PROCESS_PPID:
|
||||
num = p->ppid;
|
||||
break;
|
||||
case PROCESS_UID:
|
||||
num = p->uid;
|
||||
break;
|
||||
case PROCESS_PGID:
|
||||
num = p->pgid;
|
||||
break;
|
||||
case PROCESS_SID:
|
||||
num = p->sid;
|
||||
break;
|
||||
default:
|
||||
case PROCESS_CTTY:
|
||||
num = p->ctty;
|
||||
break;
|
||||
}
|
||||
__small_sprintf (filebuf, "%d\n", num);
|
||||
filesize = strlen (filebuf);
|
||||
break;
|
||||
}
|
||||
case PROCESS_EXENAME:
|
||||
{
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = MAX_PATH);
|
||||
if (p->process_state & (PID_ZOMBIE | PID_EXITED))
|
||||
strcpy (filebuf, "<defunct>");
|
||||
else
|
||||
{
|
||||
mount_table->conv_to_posix_path (p->progname, filebuf, 1);
|
||||
int len = strlen (filebuf);
|
||||
if (len > 4)
|
||||
{
|
||||
char *s = filebuf + len - 4;
|
||||
if (strcasecmp (s, ".exe") == 0)
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
filesize = strlen (filebuf);
|
||||
break;
|
||||
}
|
||||
case PROCESS_WINPID:
|
||||
{
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
|
||||
__small_sprintf (filebuf, "%d\n", p->dwProcessId);
|
||||
filesize = strlen (filebuf);
|
||||
break;
|
||||
}
|
||||
case PROCESS_WINEXENAME:
|
||||
{
|
||||
int len = strlen (p->progname);
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = (len + 2));
|
||||
strcpy (filebuf, p->progname);
|
||||
filebuf[len] = '\n';
|
||||
filesize = len + 1;
|
||||
break;
|
||||
}
|
||||
case PROCESS_STATUS:
|
||||
{
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 3);
|
||||
filebuf[0] = ' ';
|
||||
filebuf[1] = '\n';
|
||||
filebuf[2] = 0;
|
||||
if (p->process_state & PID_STOPPED)
|
||||
filebuf[0] = 'S';
|
||||
else if (p->process_state & PID_TTYIN)
|
||||
filebuf[0] = 'I';
|
||||
else if (p->process_state & PID_TTYOU)
|
||||
filebuf[0] = 'O';
|
||||
filesize = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fileid = process_file_no;
|
||||
saved_pid = pid;
|
||||
saved_p = p;
|
||||
fill_filebuf ();
|
||||
|
||||
if (flags & O_APPEND)
|
||||
position = filesize;
|
||||
@ -297,3 +253,501 @@ out:
|
||||
syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode);
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_process::fill_filebuf ()
|
||||
{
|
||||
// has this process gone away?
|
||||
if (!proc_exists (saved_p) || saved_p->pid != saved_pid)
|
||||
{
|
||||
if (filebuf)
|
||||
cfree(filebuf);
|
||||
filesize = 0; bufalloc = (size_t) -1;
|
||||
}
|
||||
switch (fileid)
|
||||
{
|
||||
case PROCESS_UID:
|
||||
case PROCESS_GID:
|
||||
case PROCESS_PGID:
|
||||
case PROCESS_SID:
|
||||
case PROCESS_CTTY:
|
||||
case PROCESS_PPID:
|
||||
{
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
|
||||
int num;
|
||||
switch (fileid)
|
||||
{
|
||||
case PROCESS_PPID:
|
||||
num = saved_p->ppid;
|
||||
break;
|
||||
case PROCESS_UID:
|
||||
num = saved_p->uid;
|
||||
break;
|
||||
case PROCESS_PGID:
|
||||
num = saved_p->pgid;
|
||||
break;
|
||||
case PROCESS_SID:
|
||||
num = saved_p->sid;
|
||||
break;
|
||||
case PROCESS_GID:
|
||||
num = saved_p->gid;
|
||||
break;
|
||||
case PROCESS_CTTY:
|
||||
num = saved_p->ctty;
|
||||
break;
|
||||
default: // what's this here for?
|
||||
num = 0;
|
||||
break;
|
||||
}
|
||||
__small_sprintf (filebuf, "%d\n", num);
|
||||
filesize = strlen (filebuf);
|
||||
break;
|
||||
}
|
||||
case PROCESS_EXENAME:
|
||||
{
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = MAX_PATH);
|
||||
if (saved_p->process_state & (PID_ZOMBIE | PID_EXITED))
|
||||
strcpy (filebuf, "<defunct>");
|
||||
else
|
||||
{
|
||||
mount_table->conv_to_posix_path (saved_p->progname, filebuf, 1);
|
||||
int len = strlen (filebuf);
|
||||
if (len > 4)
|
||||
{
|
||||
char *s = filebuf + len - 4;
|
||||
if (strcasecmp (s, ".exe") == 0)
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
filesize = strlen (filebuf);
|
||||
break;
|
||||
}
|
||||
case PROCESS_WINPID:
|
||||
{
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
|
||||
__small_sprintf (filebuf, "%d\n", saved_p->dwProcessId);
|
||||
filesize = strlen (filebuf);
|
||||
break;
|
||||
}
|
||||
case PROCESS_WINEXENAME:
|
||||
{
|
||||
int len = strlen (saved_p->progname);
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = (len + 2));
|
||||
strcpy (filebuf, saved_p->progname);
|
||||
filebuf[len] = '\n';
|
||||
filesize = len + 1;
|
||||
break;
|
||||
}
|
||||
case PROCESS_STATUS:
|
||||
{
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
|
||||
filesize = format_process_status (saved_p, filebuf, bufalloc);
|
||||
break;
|
||||
}
|
||||
case PROCESS_STAT:
|
||||
{
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
|
||||
filesize = format_process_stat (saved_p, filebuf, bufalloc);
|
||||
break;
|
||||
}
|
||||
case PROCESS_STATM:
|
||||
{
|
||||
if (!filebuf)
|
||||
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
|
||||
filesize = format_process_statm (saved_p, filebuf, bufalloc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
off_t
|
||||
format_process_stat (_pinfo *p, char *destbuf, size_t maxsize)
|
||||
{
|
||||
char cmd[MAX_PATH];
|
||||
int state = 'R';
|
||||
unsigned long fault_count = 0UL,
|
||||
utime = 0UL, stime = 0UL,
|
||||
start_time = 0UL,
|
||||
vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL;
|
||||
int priority = 0;
|
||||
if (p->process_state & (PID_ZOMBIE | PID_EXITED))
|
||||
strcpy (cmd, "<defunct");
|
||||
else
|
||||
{
|
||||
strcpy(cmd, p->progname);
|
||||
char *last_slash = strrchr (cmd, '\\');
|
||||
if (last_slash != NULL)
|
||||
strcpy (cmd, last_slash + 1);
|
||||
int len = strlen (cmd);
|
||||
if (len > 4)
|
||||
{
|
||||
char *s = cmd + len - 4;
|
||||
if (strcasecmp (s, ".exe") == 0)
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Note: under Windows, a _process_ is always running - it's only _threads_
|
||||
* that get suspended. Therefore the default state is R (runnable).
|
||||
*/
|
||||
if (p->process_state & PID_ZOMBIE)
|
||||
state = 'Z';
|
||||
else if (p->process_state & PID_STOPPED)
|
||||
state = 'T';
|
||||
else if (wincap.is_winnt ())
|
||||
state = get_process_state (p->dwProcessId);
|
||||
if (wincap.is_winnt ())
|
||||
{
|
||||
NTSTATUS ret;
|
||||
HANDLE hProcess;
|
||||
VM_COUNTERS vmc;
|
||||
KERNEL_USER_TIMES put;
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
QUOTA_LIMITS ql;
|
||||
SYSTEM_TIME_OF_DAY_INFORMATION stodi;
|
||||
SYSTEM_PROCESSOR_TIMES spt;
|
||||
hProcess = OpenProcess (PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
|
||||
FALSE, p->dwProcessId);
|
||||
if (hProcess != NULL)
|
||||
{
|
||||
ret = ZwQueryInformationProcess (hProcess,
|
||||
ProcessVmCounters,
|
||||
(PVOID) &vmc,
|
||||
sizeof vmc, NULL);
|
||||
if (ret == STATUS_SUCCESS)
|
||||
ret = ZwQueryInformationProcess (hProcess,
|
||||
ProcessTimes,
|
||||
(PVOID) &put,
|
||||
sizeof put, NULL);
|
||||
if (ret == STATUS_SUCCESS)
|
||||
ret = ZwQueryInformationProcess (hProcess,
|
||||
ProcessBasicInformation,
|
||||
(PVOID) &pbi,
|
||||
sizeof pbi, NULL);
|
||||
if (ret == STATUS_SUCCESS)
|
||||
ret = ZwQueryInformationProcess (hProcess,
|
||||
ProcessQuotaLimits,
|
||||
(PVOID) &ql,
|
||||
sizeof ql, NULL);
|
||||
CloseHandle (hProcess);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
__seterrno_from_win_error (error);
|
||||
debug_printf("OpenProcess: ret = %d",
|
||||
error);
|
||||
return 0;
|
||||
}
|
||||
if (ret == STATUS_SUCCESS)
|
||||
ret = ZwQuerySystemInformation (SystemTimeOfDayInformation,
|
||||
(PVOID) &stodi,
|
||||
sizeof stodi, NULL);
|
||||
if (ret == STATUS_SUCCESS)
|
||||
ret = ZwQuerySystemInformation (SystemProcessorTimes,
|
||||
(PVOID) &spt,
|
||||
sizeof spt, NULL);
|
||||
if (ret != STATUS_SUCCESS)
|
||||
{
|
||||
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
|
||||
debug_printf("NtQueryInformationProcess: ret = %d, "
|
||||
"Dos(ret) = %d",
|
||||
ret, RtlNtStatusToDosError (ret));
|
||||
return 0;
|
||||
}
|
||||
fault_count = vmc.PageFaultCount;
|
||||
utime = put.UserTime.QuadPart / 100000ULL;
|
||||
stime = put.KernelTime.QuadPart / 100000ULL;
|
||||
if (stodi.CurrentTime.QuadPart > put.CreateTime.QuadPart)
|
||||
start_time = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart +
|
||||
spt.IdleTime.QuadPart + spt.UserTime.QuadPart +
|
||||
spt.DpcTime.QuadPart - stodi.CurrentTime.QuadPart +
|
||||
put.CreateTime.QuadPart) / 100000ULL;
|
||||
else
|
||||
/*
|
||||
* sometimes stodi.CurrentTime is a bit behind
|
||||
* Note: some older versions of procps are broken and can't cope
|
||||
* with process start times > time(NULL).
|
||||
*/
|
||||
start_time = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart +
|
||||
spt.IdleTime.QuadPart + spt.UserTime.QuadPart +
|
||||
spt.DpcTime.QuadPart) / 100000ULL;
|
||||
priority = pbi.BasePriority;
|
||||
unsigned page_size = getpagesize();
|
||||
vmsize = vmc.VirtualSize;
|
||||
vmrss = vmc.WorkingSetSize / page_size;
|
||||
vmmaxrss = ql.MaximumWorkingSetSize / page_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
start_time = (GetTickCount() / 1000 - time(NULL) + p->start_time) * 100;
|
||||
}
|
||||
return __small_sprintf (destbuf, "%d (%s) %c "
|
||||
"%d %d %d %d %d "
|
||||
"%lu %lu %lu %lu %lu %lu %lu "
|
||||
"%ld %ld %ld %ld %ld %ld "
|
||||
"%lu %lu "
|
||||
"%ld "
|
||||
"%lu",
|
||||
p->pid, cmd,
|
||||
state,
|
||||
p->ppid, p->pgid, p->sid, p->ctty, -1,
|
||||
0, fault_count, fault_count, 0, 0, utime, stime,
|
||||
utime, stime, priority, 0, 0, 0,
|
||||
start_time, vmsize,
|
||||
vmrss, vmmaxrss
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
off_t
|
||||
format_process_status (_pinfo *p, char *destbuf, size_t maxsize)
|
||||
{
|
||||
char cmd[MAX_PATH];
|
||||
int state = 'R';
|
||||
const char *state_str = "unknown";
|
||||
unsigned long vmsize = 0UL, vmrss = 0UL, vmdata = 0UL, vmlib = 0UL, vmtext = 0UL,
|
||||
vmshare = 0UL;
|
||||
if (p->process_state & (PID_ZOMBIE | PID_EXITED))
|
||||
strcpy (cmd, "<defunct>");
|
||||
else
|
||||
{
|
||||
strcpy(cmd, p->progname);
|
||||
char *last_slash = strrchr (cmd, '\\');
|
||||
if (last_slash != NULL)
|
||||
strcpy (cmd, last_slash + 1);
|
||||
int len = strlen (cmd);
|
||||
if (len > 4)
|
||||
{
|
||||
char *s = cmd + len - 4;
|
||||
if (strcasecmp (s, ".exe") == 0)
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Note: under Windows, a _process_ is always running - it's only _threads_
|
||||
* that get suspended. Therefore the default state is R (runnable).
|
||||
*/
|
||||
if (p->process_state & PID_ZOMBIE)
|
||||
state = 'Z';
|
||||
else if (p->process_state & PID_STOPPED)
|
||||
state = 'T';
|
||||
else if (wincap.is_winnt ())
|
||||
state = get_process_state (p->dwProcessId);
|
||||
switch (state)
|
||||
{
|
||||
case 'O':
|
||||
state_str = "running";
|
||||
break;
|
||||
case 'D':
|
||||
case 'S':
|
||||
state_str = "sleeping";
|
||||
break;
|
||||
case 'R':
|
||||
state_str = "runnable";
|
||||
break;
|
||||
case 'Z':
|
||||
state_str = "zombie";
|
||||
break;
|
||||
case 'T':
|
||||
state_str = "stopped";
|
||||
break;
|
||||
}
|
||||
if (wincap.is_winnt ())
|
||||
{
|
||||
if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare))
|
||||
return 0;
|
||||
unsigned page_size = getpagesize();
|
||||
vmsize *= page_size; vmrss *= page_size; vmdata *= page_size;
|
||||
vmtext *= page_size; vmlib *= page_size;
|
||||
}
|
||||
return __small_sprintf (destbuf, "Name: %s\n"
|
||||
"State: %c (%s)\n"
|
||||
"Tgid: %d\n"
|
||||
"Pid: %d\n"
|
||||
"PPid: %d\n"
|
||||
"Uid: %d %d %d %d\n"
|
||||
"Gid: %d %d %d %d\n"
|
||||
"VmSize: %8d kB\n"
|
||||
"VmLck: %8d kB\n"
|
||||
"VmRSS: %8d kB\n"
|
||||
"VmData: %8d kB\n"
|
||||
"VmStk: %8d kB\n"
|
||||
"VmExe: %8d kB\n"
|
||||
"VmLib: %8d kB\n"
|
||||
"SigPnd: %016x\n"
|
||||
"SigBlk: %016x\n"
|
||||
"SigIgn: %016x\n",
|
||||
cmd,
|
||||
state, state_str,
|
||||
p->pgid,
|
||||
p->pid,
|
||||
p->ppid,
|
||||
p->uid, cygheap->user.real_uid, cygheap->user.real_uid, p->uid,
|
||||
p->gid, cygheap->user.real_gid, cygheap->user.real_gid, p->gid,
|
||||
vmsize >> 10, 0, vmrss >> 10, vmdata >> 10, 0, vmtext >> 10, vmlib >> 10,
|
||||
0, 0, p->getsigmask ()
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
off_t
|
||||
format_process_statm (_pinfo *p, char *destbuf, size_t maxsize)
|
||||
{
|
||||
unsigned long vmsize = 0UL, vmrss = 0UL, vmtext = 0UL, vmdata = 0UL, vmlib = 0UL,
|
||||
vmshare = 0UL;
|
||||
if (wincap.is_winnt ())
|
||||
{
|
||||
if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare))
|
||||
return 0;
|
||||
}
|
||||
return __small_sprintf (destbuf, "%ld %ld %ld %ld %ld %ld %ld",
|
||||
vmsize, vmrss, vmshare, vmtext, vmlib, vmdata, 0
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
get_process_state (DWORD dwProcessId)
|
||||
{
|
||||
/*
|
||||
* This isn't really heavy magic - just go through the processes'
|
||||
* threads one by one and return a value accordingly
|
||||
* Errors are silently ignored.
|
||||
*/
|
||||
NTSTATUS ret;
|
||||
SYSTEM_PROCESSES *sp;
|
||||
ULONG n = 0x1000;
|
||||
PULONG p = new ULONG[n];
|
||||
int state =' ';
|
||||
while (STATUS_INFO_LENGTH_MISMATCH ==
|
||||
(ret = ZwQuerySystemInformation (SystemProcessesAndThreadsInformation,
|
||||
(PVOID) p,
|
||||
n * sizeof *p, NULL)))
|
||||
delete [] p, p = new ULONG[n *= 2];
|
||||
if (ret != STATUS_SUCCESS)
|
||||
{
|
||||
debug_printf("NtQuerySystemInformation: ret = %d, "
|
||||
"Dos(ret) = %d",
|
||||
ret, RtlNtStatusToDosError (ret));
|
||||
goto out;
|
||||
}
|
||||
state = 'Z';
|
||||
sp = (SYSTEM_PROCESSES *) p;
|
||||
for (;;)
|
||||
{
|
||||
if (sp->ProcessId == dwProcessId)
|
||||
{
|
||||
SYSTEM_THREADS *st;
|
||||
if (wincap.has_process_io_counters ())
|
||||
/*
|
||||
* Windows 2000 and XP have an extra member in SYSTEM_PROCESSES
|
||||
* which means the offset of the first SYSTEM_THREADS entry is
|
||||
* different on these operating systems compared to NT 4.
|
||||
*/
|
||||
st = &sp->Threads[0];
|
||||
else
|
||||
/*
|
||||
* 136 is the offset of the first SYSTEM_THREADS entry on
|
||||
* Windows NT 4.
|
||||
*/
|
||||
st = (SYSTEM_THREADS *) ((char *) sp + 136);
|
||||
state = 'S';
|
||||
for (unsigned i = 0; i < sp->ThreadCount; i++)
|
||||
{
|
||||
if (st->State == StateRunning ||
|
||||
st->State == StateReady)
|
||||
{
|
||||
state = 'R';
|
||||
goto out;
|
||||
}
|
||||
st++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!sp->NextEntryDelta)
|
||||
break;
|
||||
sp = (SYSTEM_PROCESSES *) ((char *) sp + sp->NextEntryDelta);
|
||||
}
|
||||
out:
|
||||
delete [] p;
|
||||
return state;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext,
|
||||
unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare)
|
||||
{
|
||||
bool res = true;
|
||||
NTSTATUS ret;
|
||||
HANDLE hProcess;
|
||||
VM_COUNTERS vmc;
|
||||
MEMORY_WORKING_SET_LIST *mwsl;
|
||||
ULONG n = 0x1000, length;
|
||||
PULONG p = new ULONG[n];
|
||||
unsigned page_size = getpagesize();
|
||||
hProcess = OpenProcess (PROCESS_QUERY_INFORMATION,
|
||||
FALSE, dwProcessId);
|
||||
if (hProcess == NULL)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
__seterrno_from_win_error (error);
|
||||
debug_printf("OpenProcess: ret = %d",
|
||||
error);
|
||||
return false;
|
||||
}
|
||||
while ((ret = ZwQueryVirtualMemory (hProcess, 0,
|
||||
MemoryWorkingSetList,
|
||||
(PVOID) p,
|
||||
n * sizeof *p, &length)),
|
||||
(ret == STATUS_SUCCESS || ret == STATUS_INFO_LENGTH_MISMATCH) &&
|
||||
length >= n * sizeof *p)
|
||||
delete [] p, p = new ULONG[n *= 2];
|
||||
if (ret != STATUS_SUCCESS)
|
||||
{
|
||||
debug_printf("NtQueryVirtualMemory: ret = %d, "
|
||||
"Dos(ret) = %d",
|
||||
ret, RtlNtStatusToDosError (ret));
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
mwsl = (MEMORY_WORKING_SET_LIST *) p;
|
||||
for (unsigned long i = 0; i < mwsl->NumberOfPages; i++)
|
||||
{
|
||||
++*vmrss;
|
||||
unsigned flags = mwsl->WorkingSetList[i] & 0x0FFF;
|
||||
if (flags & (WSLE_PAGE_EXECUTE | WSLE_PAGE_SHAREABLE) == (WSLE_PAGE_EXECUTE | WSLE_PAGE_SHAREABLE))
|
||||
++*vmlib;
|
||||
else if (flags & WSLE_PAGE_SHAREABLE)
|
||||
++*vmshare;
|
||||
else if (flags & WSLE_PAGE_EXECUTE)
|
||||
++*vmtext;
|
||||
else
|
||||
++*vmdata;
|
||||
}
|
||||
ret = ZwQueryInformationProcess (hProcess,
|
||||
ProcessVmCounters,
|
||||
(PVOID) &vmc,
|
||||
sizeof vmc, NULL);
|
||||
if (ret != STATUS_SUCCESS)
|
||||
{
|
||||
debug_printf("NtQueryInformationProcess: ret = %d, "
|
||||
"Dos(ret) = %d",
|
||||
ret, RtlNtStatusToDosError (ret));
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
*vmsize = vmc.VirtualSize / page_size;
|
||||
out:
|
||||
delete [] p;
|
||||
CloseHandle (hProcess);
|
||||
return res;
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ fhandler_registry::telldir (DIR * dir)
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_registry::seekdir (DIR * dir, __off32_t loc)
|
||||
fhandler_registry::seekdir (DIR * dir, __off64_t loc)
|
||||
{
|
||||
/* Unfortunately cannot simply set __d_position due to transition from sub-keys to
|
||||
* values.
|
||||
@ -490,6 +490,11 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_registry::fill_filebuf ()
|
||||
{
|
||||
}
|
||||
|
||||
/* Auxillary member function to open registry keys. */
|
||||
HKEY
|
||||
fhandler_registry::open_key (const char *name, REGSAM access, bool isValue)
|
||||
|
@ -27,7 +27,8 @@ details. */
|
||||
#include <dirent.h>
|
||||
|
||||
fhandler_virtual::fhandler_virtual (DWORD devtype):
|
||||
fhandler_base (devtype), filebuf (NULL), bufalloc (-1)
|
||||
fhandler_base (devtype), filebuf (NULL), bufalloc ((size_t) -1),
|
||||
fileid (-1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -89,7 +90,7 @@ __off64_t fhandler_virtual::telldir (DIR * dir)
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_virtual::seekdir (DIR * dir, __off32_t loc)
|
||||
fhandler_virtual::seekdir (DIR * dir, __off64_t loc)
|
||||
{
|
||||
dir->__d_position = loc;
|
||||
return;
|
||||
@ -109,8 +110,13 @@ fhandler_virtual::closedir (DIR * dir)
|
||||
}
|
||||
|
||||
__off64_t
|
||||
fhandler_virtual::lseek (__off32_t offset, int whence)
|
||||
fhandler_virtual::lseek (__off64_t offset, int whence)
|
||||
{
|
||||
/*
|
||||
* On Linux, when you lseek within a /proc file,
|
||||
* the contents of the file are updated.
|
||||
*/
|
||||
fill_filebuf ();
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
@ -124,7 +130,7 @@ fhandler_virtual::lseek (__off32_t offset, int whence)
|
||||
break;
|
||||
default:
|
||||
set_errno (EINVAL);
|
||||
return (__off32_t) -1;
|
||||
return (__off64_t) -1;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
@ -214,3 +220,8 @@ fhandler_virtual::exists (const char *path)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_virtual::fill_filebuf ()
|
||||
{
|
||||
}
|
||||
|
@ -10,11 +10,28 @@
|
||||
|
||||
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
|
||||
#define FILE_SYNCHRONOUS_IO_NONALERT 32
|
||||
#define PDI_MODULES 0x01
|
||||
#define PDI_HEAPS 0x04
|
||||
#define LDRP_IMAGE_DLL 0x00000004
|
||||
#define WSLE_PAGE_READONLY 0x001
|
||||
#define WSLE_PAGE_EXECUTE 0x002
|
||||
#define WSLE_PAGE_EXECUTE_READ 0x003
|
||||
#define WSLE_PAGE_READWRITE 0x004
|
||||
#define WSLE_PAGE_WRITECOPY 0x005
|
||||
#define WSLE_PAGE_EXECUTE_READWRITE 0x006
|
||||
#define WSLE_PAGE_EXECUTE_WRITECOPY 0x007
|
||||
#define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0
|
||||
#define WSLE_PAGE_SHAREABLE 0x100
|
||||
|
||||
typedef ULONG KAFFINITY;
|
||||
|
||||
typedef enum _SYSTEM_INFORMATION_CLASS
|
||||
{
|
||||
SystemBasicInformation = 0,
|
||||
SystemPerformanceInformation = 2,
|
||||
SystemTimeOfDayInformation = 3,
|
||||
SystemProcessesAndThreadsInformation = 5,
|
||||
SystemProcessorTimes = 8,
|
||||
/* There are a lot more of these... */
|
||||
} SYSTEM_INFORMATION_CLASS;
|
||||
|
||||
@ -30,9 +47,19 @@ typedef struct _SYSTEM_BASIC_INFORMATION
|
||||
ULONG LowestUserAddress;
|
||||
ULONG HighestUserAddress;
|
||||
ULONG ActiveProcessors;
|
||||
ULONG NumberProcessors;
|
||||
UCHAR NumberProcessors;
|
||||
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_PROCESSOR_TIMES
|
||||
{
|
||||
LARGE_INTEGER IdleTime;
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
LARGE_INTEGER DpcTime;
|
||||
LARGE_INTEGER InterruptTime;
|
||||
ULONG InterruptCount;
|
||||
} SYSTEM_PROCESSOR_TIMES, *PSYSTEM_PROCESSOR_TIMES;
|
||||
|
||||
typedef LONG KPRIORITY;
|
||||
typedef struct _VM_COUNTERS
|
||||
{
|
||||
@ -112,12 +139,13 @@ typedef struct _SYSTEM_THREADS
|
||||
ULONG ContextSwitchCount;
|
||||
THREAD_STATE State;
|
||||
KWAIT_REASON WaitReason;
|
||||
DWORD Reserved;
|
||||
} SYSTEM_THREADS, *PSYSTEM_THREADS;
|
||||
|
||||
typedef struct _SYSTEM_PROCESSES
|
||||
{
|
||||
ULONG NextEntryDelta;
|
||||
ULONG Threadcount;
|
||||
ULONG ThreadCount;
|
||||
ULONG Reserved1[6];
|
||||
LARGE_INTEGER CreateTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
@ -139,6 +167,180 @@ typedef struct _IO_STATUS_BLOCK
|
||||
ULONG Information;
|
||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||
|
||||
typedef struct _SYSTEM_PERFORMANCE_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER IdleTime;
|
||||
LARGE_INTEGER ReadTransferCount;
|
||||
LARGE_INTEGER WriteTransferCount;
|
||||
LARGE_INTEGER OtherTransferCount;
|
||||
ULONG ReadOperationCount;
|
||||
ULONG WriteOperationCount;
|
||||
ULONG OtherOperationCount;
|
||||
ULONG AvailablePages;
|
||||
ULONG TotalCommittedPages;
|
||||
ULONG TotalCommitLimit;
|
||||
ULONG PeakCommitment;
|
||||
ULONG PageFaults;
|
||||
ULONG WriteCopyFaults;
|
||||
ULONG TransitionFaults;
|
||||
ULONG Reserved1;
|
||||
ULONG DemandZeroFaults;
|
||||
ULONG PagesRead;
|
||||
ULONG PageReadIos;
|
||||
ULONG Reserved2[2];
|
||||
ULONG PagefilePagesWritten;
|
||||
ULONG PagefilePageWriteIos;
|
||||
ULONG MappedFilePagesWritten;
|
||||
ULONG MappedFilePageWriteIos;
|
||||
ULONG PagedPoolUsage;
|
||||
ULONG NonPagedPoolUsage;
|
||||
ULONG PagedPoolAllocs;
|
||||
ULONG PagedPoolFrees;
|
||||
ULONG NonPagedPoolAllocs;
|
||||
ULONG NonPagedPoolFrees;
|
||||
ULONG TotalFreeSystemPtes;
|
||||
ULONG SystemCodePage;
|
||||
ULONG TotalSystemDriverPages;
|
||||
ULONG TotalSystemCodePages;
|
||||
ULONG SmallNonPagedLookasideListAllocateHits;
|
||||
ULONG SmallPagedLookasideListAllocateHits;
|
||||
ULONG Reserved3;
|
||||
ULONG MmSystemCachePage;
|
||||
ULONG PagedPoolPage;
|
||||
ULONG SystemDriverPage;
|
||||
ULONG FastReadNoWait;
|
||||
ULONG FastReadWait;
|
||||
ULONG FastReadResourceMiss;
|
||||
ULONG FastReadNotPossible;
|
||||
ULONG FastMdlReadNoWait;
|
||||
ULONG FastMdlReadWait;
|
||||
ULONG FastMdlReadResourceMiss;
|
||||
ULONG FastMdlReadNotPossible;
|
||||
ULONG MapDataNoWait;
|
||||
ULONG MapDataWait;
|
||||
ULONG MapDataNoWaitMiss;
|
||||
ULONG MapDataWaitMiss;
|
||||
ULONG PinMappedDataCount;
|
||||
ULONG PinReadNoWait;
|
||||
ULONG PinReadWait;
|
||||
ULONG PinReadNoWaitMiss;
|
||||
ULONG PinReadWaitMiss;
|
||||
ULONG CopyReadNoWait;
|
||||
ULONG CopyReadWait;
|
||||
ULONG CopyReadNoWaitMiss;
|
||||
ULONG CopyReadWaitMiss;
|
||||
ULONG MdlReadNoWait;
|
||||
ULONG MdlReadWait;
|
||||
ULONG MdlReadNoWaitMiss;
|
||||
ULONG MdlReadWaitMiss;
|
||||
ULONG ReadAheadIos;
|
||||
ULONG LazyWriteIos;
|
||||
ULONG LazyWritePages;
|
||||
ULONG DataFlushes;
|
||||
ULONG DataPages;
|
||||
ULONG ContextSwitches;
|
||||
ULONG FirstLevelTbFills;
|
||||
ULONG SecondLevelTbFills;
|
||||
ULONG SystemCalls;
|
||||
} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_TIME_OF_DAY_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER BootTime;
|
||||
LARGE_INTEGER CurrentTime;
|
||||
LARGE_INTEGER TimeZoneBias;
|
||||
ULONG CurrentTimeZoneId;
|
||||
} SYSTEM_TIME_OF_DAY_INFORMATION, *PSYSTEM_TIME_OF_DAY_INFORMATION;
|
||||
|
||||
typedef enum _PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0,
|
||||
ProcessQuotaLimits = 1,
|
||||
ProcessVmCounters = 3,
|
||||
ProcessTimes =4,
|
||||
} PROCESSINFOCLASS;
|
||||
|
||||
typedef struct _DEBUG_BUFFER
|
||||
{
|
||||
HANDLE SectionHandle;
|
||||
PVOID SectionBase;
|
||||
PVOID RemoteSectionBase;
|
||||
ULONG SectionBaseDelta;
|
||||
HANDLE EventPairHandle;
|
||||
ULONG Unknown[2];
|
||||
HANDLE RemoteThreadHandle;
|
||||
ULONG InfoClassMask;
|
||||
ULONG SizeOfInfo;
|
||||
ULONG AllocatedSize;
|
||||
ULONG SectionSize;
|
||||
PVOID ModuleInformation;
|
||||
PVOID BackTraceInformation;
|
||||
PVOID HeapInformation;
|
||||
PVOID LockInformation;
|
||||
PVOID Reserved[9];
|
||||
} DEBUG_BUFFER, *PDEBUG_BUFFER;
|
||||
|
||||
typedef struct _DEBUG_HEAP_INFORMATION
|
||||
{
|
||||
ULONG Base;
|
||||
ULONG Flags;
|
||||
USHORT Granularity;
|
||||
USHORT Unknown;
|
||||
ULONG Allocated;
|
||||
ULONG Committed;
|
||||
ULONG TagCount;
|
||||
ULONG BlockCount;
|
||||
ULONG Reserved[7];
|
||||
PVOID Tags;
|
||||
PVOID Blocks;
|
||||
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;
|
||||
|
||||
typedef struct _DEBUG_MODULE_INFORMATION
|
||||
{
|
||||
ULONG Reserved[2];
|
||||
ULONG Base;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
USHORT Index;
|
||||
USHORT Unknown;
|
||||
USHORT LoadCount;
|
||||
USHORT ModuleNameOffset;
|
||||
CHAR ImageName[256];
|
||||
} DEBUG_MODULE_INFORMATION, *PDEBUG_MODULE_INFORMATION;
|
||||
|
||||
typedef struct _KERNEL_USER_TIMES
|
||||
{
|
||||
LARGE_INTEGER CreateTime;
|
||||
LARGE_INTEGER ExitTime;
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES;
|
||||
|
||||
typedef void *PPEB;
|
||||
|
||||
typedef struct _PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
PPEB PebBaseAddress;
|
||||
KAFFINITY AffinityMask;
|
||||
KPRIORITY BasePriority;
|
||||
ULONG UniqueProcessId;
|
||||
ULONG InheritedFromUniqueProcessId;
|
||||
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
|
||||
|
||||
typedef enum _MEMORY_INFORMATION_CLASS
|
||||
{
|
||||
MemoryBasicInformation,
|
||||
MemoryWorkingSetList,
|
||||
MemorySectionName,
|
||||
MemoryBaiscVlmInformation
|
||||
} MEMORY_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _MEMORY_WORKING_SET_LIST {
|
||||
ULONG NumberOfPages;
|
||||
ULONG WorkingSetList[1];
|
||||
} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;
|
||||
|
||||
/* Function declarations for ntdll.dll. These don't appear in any
|
||||
standard Win32 header. */
|
||||
extern "C"
|
||||
@ -162,4 +364,8 @@ extern "C"
|
||||
NTSTATUS NTAPI ZwQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS,
|
||||
IN OUT PVOID, IN ULONG,
|
||||
OUT PULONG);
|
||||
NTSTATUS NTAPI ZwQueryInformationProcess (IN HANDLE, IN PROCESSINFOCLASS,
|
||||
OUT PVOID, IN ULONG, OUT PULONG);
|
||||
NTSTATUS NTAPI ZwQueryVirtualMemory (IN HANDLE, IN PVOID, IN MEMORY_INFORMATION_CLASS,
|
||||
OUT PVOID, IN ULONG, OUT PULONG);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ static NO_COPY wincaps wincap_unknown = {
|
||||
has_raw_devices:false,
|
||||
has_valid_processorlevel:false,
|
||||
has_64bit_file_access:false,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_95 = {
|
||||
@ -83,6 +84,7 @@ static NO_COPY wincaps wincap_95 = {
|
||||
has_raw_devices:false,
|
||||
has_valid_processorlevel:false,
|
||||
has_64bit_file_access:false,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_95osr2 = {
|
||||
@ -120,6 +122,7 @@ static NO_COPY wincaps wincap_95osr2 = {
|
||||
has_raw_devices:false,
|
||||
has_valid_processorlevel:false,
|
||||
has_64bit_file_access:false,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_98 = {
|
||||
@ -157,6 +160,7 @@ static NO_COPY wincaps wincap_98 = {
|
||||
has_raw_devices:false,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:false,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_98se = {
|
||||
@ -194,6 +198,7 @@ static NO_COPY wincaps wincap_98se = {
|
||||
has_raw_devices:false,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:false,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_me = {
|
||||
@ -231,6 +236,7 @@ static NO_COPY wincaps wincap_me = {
|
||||
has_raw_devices:false,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:false,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_nt3 = {
|
||||
@ -268,6 +274,7 @@ static NO_COPY wincaps wincap_nt3 = {
|
||||
has_raw_devices:true,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:true,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_nt4 = {
|
||||
@ -305,6 +312,7 @@ static NO_COPY wincaps wincap_nt4 = {
|
||||
has_raw_devices:true,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:true,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_nt4sp4 = {
|
||||
@ -342,6 +350,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
|
||||
has_raw_devices:true,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:true,
|
||||
has_process_io_counters:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_2000 = {
|
||||
@ -379,6 +388,7 @@ static NO_COPY wincaps wincap_2000 = {
|
||||
has_raw_devices:true,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:true,
|
||||
has_process_io_counters:true,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_xp = {
|
||||
@ -416,6 +426,7 @@ static NO_COPY wincaps wincap_xp = {
|
||||
has_raw_devices:true,
|
||||
has_valid_processorlevel:true,
|
||||
has_64bit_file_access:true,
|
||||
has_process_io_counters:true,
|
||||
};
|
||||
|
||||
wincapc NO_COPY wincap;
|
||||
|
@ -47,6 +47,7 @@ struct wincaps
|
||||
unsigned has_raw_devices : 1;
|
||||
unsigned has_valid_processorlevel : 1;
|
||||
unsigned has_64bit_file_access : 1;
|
||||
unsigned has_process_io_counters : 1;
|
||||
};
|
||||
|
||||
class wincapc
|
||||
@ -99,6 +100,7 @@ public:
|
||||
bool IMPLEMENT (has_raw_devices)
|
||||
bool IMPLEMENT (has_valid_processorlevel)
|
||||
bool IMPLEMENT (has_64bit_file_access)
|
||||
bool IMPLEMENT (has_process_io_counters)
|
||||
|
||||
#undef IMPLEMENT
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user