(GetModuleInformation): Add.
(QueryWorkingSet): Add.
* fhandler.h (fhandler_virtual::get_filebuf): New method.
* fhandler_proc.cc (PROC_SELF): Define.
(proc_fhandlers): Change type of self to FH_PROC.
(fhandler_proc::exists): Return -3 if self.
(fhandler_proc::fstat): Handle self as symlink.
(fhandler_proc::fill_filebuf): Handle self.
* fhandler_process.cc: Include psapi.h.
(PROCESS_EXENAME): Remove.
(PROCESS_MAPS): Define.
(PROCESS_ROOT): Define.
(PROCESS_EXE): Define.
(PROCESS_CWD): Define.
(process_listing): Remove "exename", add "maps, "root", "exe" and
"cwd" elements.
(fhandler_process::exists): Return -2 for symlinks.
(fhandler_process::fstat): Handle symlinks.
(fill_filebuf): Evaluate pid if pid is 0. Use exename handling for
exe. Handle maps, root and cwd.
(format_process_maps): New function evaluating "maps".
* path.cc (symlink_info::set): New method to fill symlink_info
with data matching virtual symlinks.
(path_conv::check): Handle virtual symlinks.
* pinfo.cc (_pinfo::commune_recv): Add PICOM_CWD and PICOM_ROOT
handling.
(_pinfo::commune_send): Ditto.
(_pinfo::root): New function.
(_pinfo::cwd): New function.
* pinfo.h (enum picom): Add PICOM_CWD and PICOM_ROOT.
(_pinfo::root): Declare.
(_pinfo::cwd): Declare.
+2005-01-29 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (GetModuleFileNameExA): Add.
+ (GetModuleInformation): Add.
+ (QueryWorkingSet): Add.
+ * fhandler.h (fhandler_virtual::get_filebuf): New method.
+ * fhandler_proc.cc (PROC_SELF): Define.
+ (proc_fhandlers): Change type of self to FH_PROC.
+ (fhandler_proc::exists): Return -3 if self.
+ (fhandler_proc::fstat): Handle self as symlink.
+ (fhandler_proc::fill_filebuf): Handle self.
+ * fhandler_process.cc: Include psapi.h.
+ (PROCESS_EXENAME): Remove.
+ (PROCESS_MAPS): Define.
+ (PROCESS_ROOT): Define.
+ (PROCESS_EXE): Define.
+ (PROCESS_CWD): Define.
+ (process_listing): Remove "exename", add "maps, "root", "exe" and
+ "cwd" elements.
+ (fhandler_process::exists): Return -2 for symlinks.
+ (fhandler_process::fstat): Handle symlinks.
+ (fill_filebuf): Evaluate pid if pid is 0. Use exename handling for
+ exe. Handle maps, root and cwd.
+ (format_process_maps): New function evaluating "maps".
+ * path.cc (symlink_info::set): New method to fill symlink_info
+ with data matching virtual symlinks.
+ (path_conv::check): Handle virtual symlinks.
+ * pinfo.cc (_pinfo::commune_recv): Add PICOM_CWD and PICOM_ROOT
+ handling.
+ (_pinfo::commune_send): Ditto.
+ (_pinfo::root): New function.
+ (_pinfo::cwd): New function.
+ * pinfo.h (enum picom): Add PICOM_CWD and PICOM_ROOT.
+ (_pinfo::root): Declare.
+ (_pinfo::cwd): Declare.
+
2005-01-29 Christopher Faylor <cgf@timesys.com>
* cygthread.cc (new): Add a little more debugging.
LoadDLLfuncEx (RtlIsDosDeviceName_U, 4, ntdll, 1)
LoadDLLfuncEx (EnumProcessModules, 16, psapi, 1)
+LoadDLLfuncEx (GetModuleFileNameExA, 16, psapi, 1)
+LoadDLLfuncEx (GetModuleInformation, 16, psapi, 1)
LoadDLLfuncEx (GetProcessMemoryInfo, 12, psapi, 1)
+LoadDLLfuncEx (QueryWorkingSet, 12, psapi, 1)
LoadDLLfuncEx (LsaDeregisterLogonProcess, 4, secur32, 1)
LoadDLLfuncEx (LsaFreeReturnBuffer, 4, secur32, 1)
int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3)));
virtual bool fill_filebuf ();
+ char *get_filebuf () { return filebuf; }
void fixup_after_exec ();
};
static const int PROC_UPTIME = 7; // /proc/uptime
static const int PROC_CPUINFO = 8; // /proc/cpuinfo
static const int PROC_PARTITIONS = 9; // /proc/partitions
+static const int PROC_SELF = 10; // /proc/self
/* names of objects in /proc */
static const char *proc_listing[] = {
FH_PROC,
FH_PROC,
FH_PROC,
- FH_PROCESS,
+ FH_PROC,
};
/* name of the /proc filesystem */
return 2;
for (int i = 0; proc_listing[i]; i++)
if (pathmatch (path + 1, proc_listing[i]))
- return (proc_fhandlers[i] == FH_PROC) ? -1 : 1;
+ {
+ fileid = i;
+ return (proc_fhandlers[i] == FH_PROC) ? (i == PROC_SELF ? -3 : -1) : 1;
+ }
return 0;
}
{
if (proc_fhandlers[i] != FH_PROC)
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
+ else if (i == PROC_SELF)
+ buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
else
{
buf->st_mode &= NO_X;
filesize = format_proc_partitions (filebuf, bufalloc);
break;
}
+ case PROC_SELF:
+ {
+ filebuf = (char *) realloc (filebuf, bufalloc = 32);
+ filesize = __small_sprintf (filebuf, "%d", getpid ());
+ }
}
return true;
}
#include <sys/param.h>
#include <assert.h>
#include <sys/sysmacros.h>
+#include <psapi.h>
#define _COMPILING_NEWLIB
#include <dirent.h>
static const int PROCESS_PPID = 2;
-static const int PROCESS_EXENAME = 3;
-static const int PROCESS_WINPID = 4;
-static const int PROCESS_WINEXENAME = 5;
-static const int PROCESS_STATUS = 6;
-static const int PROCESS_UID = 7;
-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 int PROCESS_CMDLINE = 14;
+static const int PROCESS_WINPID = 3;
+static const int PROCESS_WINEXENAME = 4;
+static const int PROCESS_STATUS = 5;
+static const int PROCESS_UID = 6;
+static const int PROCESS_GID = 7;
+static const int PROCESS_PGID = 8;
+static const int PROCESS_SID = 9;
+static const int PROCESS_CTTY = 10;
+static const int PROCESS_STAT = 11;
+static const int PROCESS_STATM = 12;
+static const int PROCESS_CMDLINE = 13;
+static const int PROCESS_MAPS = 14;
+/* Keep symlinks always the last entries. */
+static const int PROCESS_ROOT = 15;
+static const int PROCESS_EXE = 16;
+static const int PROCESS_CWD = 17;
+
+/* The position of "root" defines the beginning of symlik entries. */
+#define is_symlink(nr) ((nr) >= PROCESS_ROOT)
static const char * const process_listing[] =
{
".",
"..",
"ppid",
- "exename",
"winpid",
"winexename",
"status",
"stat",
"statm",
"cmdline",
+ "maps",
+ /* Keep symlinks always the last entries. */
+ "root",
+ "exe",
+ "cwd",
NULL
};
static const int PROCESS_LINK_COUNT =
(sizeof (process_listing) / sizeof (const char *)) - 1;
+static _off64_t format_process_maps (_pinfo *p, char *destbuf, size_t maxsize);
static _off64_t format_process_stat (_pinfo *p, char *destbuf, size_t maxsize);
static _off64_t format_process_status (_pinfo *p, char *destbuf, size_t maxsize);
static _off64_t format_process_statm (_pinfo *p, char *destbuf, size_t maxsize);
for (int i = 0; process_listing[i]; i++)
if (pathmatch (path + 1, process_listing[i]))
- return -1;
+ {
+ fileid = i;
+ return is_symlink (i) ? -2 : -1;
+ }
return 0;
}
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = PROCESS_LINK_COUNT;
return 0;
- default:
+ case -2:
+ buf->st_uid = p->uid;
+ buf->st_gid = p->gid;
+ buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
+ return 0;
case -1:
+ default:
buf->st_uid = p->uid;
buf->st_gid = p->gid;
buf->st_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
bool
fhandler_process::fill_filebuf ()
{
+ if (!pid)
+ {
+ const char *path;
+ path = get_name () + proc_len + 1;
+ if (path_prefix_p ("self", path, 4))
+ pid = getpid ();
+ else
+ pid = atoi (path);
+ }
pinfo p (pid);
if (!p)
filesize = strlen (filebuf);
break;
}
+ case PROCESS_ROOT:
+ case PROCESS_CWD:
case PROCESS_CMDLINE:
{
- if (filebuf)
+ if (filebuf)
free (filebuf);
- size_t fs;
- filebuf = p->cmdline (fs);
+ size_t fs;
+ switch (fileid)
+ {
+ case PROCESS_ROOT:
+ filebuf = p->root (fs);
+ break;
+ case PROCESS_CWD:
+ filebuf = p->cwd (fs);
+ break;
+ case PROCESS_CMDLINE:
+ filebuf = p->cmdline (fs);
+ break;
+ }
filesize = fs;
if (!filebuf || !*filebuf)
{
}
break;
}
- case PROCESS_EXENAME:
+ case PROCESS_EXE:
{
filebuf = (char *) realloc (filebuf, bufalloc = CYG_MAX_PATH);
if (p->process_state & PID_EXITED)
filesize = format_process_statm (*p, filebuf, bufalloc);
break;
}
+ case PROCESS_MAPS:
+ {
+ filebuf = (char *) realloc (filebuf, bufalloc = 2048);
+ filesize = format_process_maps (*p, filebuf, bufalloc);
+ break;
+ }
}
return true;
}
+static _off64_t
+format_process_maps (_pinfo *p, char *destbuf, size_t maxsize)
+{
+ if (!wincap.is_winnt ())
+ return 0;
+
+ HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE,
+ p->dwProcessId);
+ if (!proc)
+ return 0;
+
+ _off64_t len = 0;
+ HMODULE *modules;
+ DWORD needed, i;
+ DWORD_PTR wset_size;
+ DWORD_PTR *workingset = NULL;
+ MODULEINFO info;
+ char modname[CYG_MAX_PATH + 1];
+ char posix_modname[CYG_MAX_PATH + 1];
+
+ if (!EnumProcessModules (proc, NULL, 0, &needed))
+ {
+ __seterrno ();
+ len = -1;
+ goto out;
+ }
+ modules = (HMODULE*) alloca (needed);
+ if (!EnumProcessModules (proc, modules, needed, &needed))
+ {
+ __seterrno ();
+ len = -1;
+ goto out;
+ }
+
+ QueryWorkingSet (proc, (void *) &wset_size, sizeof wset_size);
+ if (GetLastError () == ERROR_BAD_LENGTH)
+ {
+ workingset = (DWORD_PTR *) alloca (sizeof (DWORD_PTR) * ++wset_size);
+ if (!QueryWorkingSet (proc, (void *) workingset,
+ sizeof (DWORD_PTR) * wset_size))
+ workingset = NULL;
+ }
+ for (i = 0; i < needed / sizeof (HMODULE); i++)
+ if (GetModuleInformation (proc, modules[i], &info, sizeof info)
+ && GetModuleFileNameEx (proc, modules[i], modname, sizeof modname))
+ {
+ char access[5];
+ strcpy (access, "r--p");
+ cygwin_conv_to_full_posix_path (modname, posix_modname);
+ if (len + strlen (posix_modname) + 50 > maxsize - 1)
+ break;
+ if (workingset)
+ for (unsigned i = 1; i <= wset_size; ++i)
+ {
+ DWORD_PTR addr = workingset[i] & 0xfffff000UL;
+ if ((char *)addr >= info.lpBaseOfDll
+ && (char *)addr < (char *)info.lpBaseOfDll + info.SizeOfImage)
+ {
+ access[0] = (workingset[i] & 0x5) ? 'r' : '-';
+ access[1] = (workingset[i] & 0x4) ? 'w' : '-';
+ access[2] = (workingset[i] & 0x2) ? 'x' : '-';
+ access[3] = (workingset[i] & 0x100) ? 's' : 'p';
+ }
+ }
+ int written = __small_sprintf (destbuf + len,
+ "%08lx-%08lx %s %08lx 00:00 %lu ",
+ info.lpBaseOfDll,
+ (unsigned long)info.lpBaseOfDll
+ + info.SizeOfImage,
+ access,
+ info.EntryPoint,
+ info.SizeOfImage);
+ while (written++ < 49)
+ destbuf[len + written] = ' ';
+ len += written;
+ len += __small_sprintf (destbuf + len, "%s\n", posix_modname);
+ }
+out:
+ CloseHandle (proc);
+ return len;
+}
+
static _off64_t
format_process_stat (_pinfo *p, char *destbuf, size_t maxsize)
{
_minor_t minor;
_mode_t mode;
int check (char *path, const suffix_info *suffixes, unsigned opt);
+ int set (char *path, int type);
bool parse_device (const char *);
bool case_check (char *path);
};
/* FIXME: Calling build_fhandler here is not the right way to handle this. */
fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy);
int file_type = fh->exists ();
+ if (file_type == -2 || file_type == -3)
+ {
+ fh->fill_filebuf ();
+ symlen = sym.set (fh->get_filebuf (), file_type);
+ }
delete fh;
switch (file_type)
{
case -1:
fileattr = 0;
break;
+ case -2: /* /proc/<pid>/symlinks */
+ case -3: /* /proc/self */
+ goto is_virtual_symlink;
default:
fileattr = INVALID_FILE_ATTRIBUTES;
- break;
+ goto virtual_component_retry;
}
goto out;
}
symlen = sym.check (full_path, suff, opt | fs.has_ea ());
+is_virtual_symlink:
+
if (sym.minor || sym.major)
{
dev.parse (sym.major, sym.minor);
/* No existing file found. */
}
+virtual_component_retry:
+
/* Find the new "tail" of the path, e.g. in '/for/bar/baz',
/baz is the tail. */
if (tail != path_end)
return res;
}
+/* "path" is the path in a virtual symlink. Set a symlink_info struct from
+ that and proceed with further path checking afterwards. */
+int
+symlink_info::set (char *path, int type)
+{
+ extern suffix_info stat_suffixes[];
+
+ strcpy (contents, path);
+ pflags = PATH_SYMLINK;
+ if (type == -3) /* /proc/self */
+ {
+ fileattr = FILE_ATTRIBUTE_DIRECTORY;
+ error = 0;
+ }
+ else
+ {
+ /* That's save since a virtual symlink doesn't point to itself. */
+ path_conv pc (contents, PC_SYM_NOFOLLOW | PC_FULL, stat_suffixes);
+ fileattr = pc;
+ error = pc.error;
+ }
+ is_symlink = true;
+ ext_tacked_on = case_clash = false;
+ ext_here = NULL;
+ extn = major = minor = mode = 0;
+ return strlen (path);
+}
+
/* Check the correct case of the last path component (given in DOS style).
Adjust the case in this->path if pcheck_case == PCHECK_ADJUST or return
false if pcheck_case == PCHECK_STRICT.
void
_pinfo::commune_recv ()
{
+ char pathbuf[CYG_MAX_PATH];
DWORD nr;
DWORD code;
HANDLE hp;
}
break;
}
+ case PICOM_CWD:
+ {
+ unsigned int n = strlen (cygheap->cwd.get (pathbuf, 1, 1, CYG_MAX_PATH)) + 1;
+ CloseHandle (__fromthem); __fromthem = NULL;
+ CloseHandle (hp);
+ if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL))
+ sigproc_printf ("WriteFile sizeof argv failed, %E");
+ else if (!WriteFile (__tothem, pathbuf, n, &nr, NULL))
+ sigproc_printf ("WriteFile sizeof argv failed, %E");
+ break;
+ }
+ case PICOM_ROOT:
+ {
+ unsigned int n;
+ if (cygheap->root.exists ())
+ n = strlen (strcpy (pathbuf, cygheap->root.posix_path ())) + 1;
+ else
+ n = strlen (strcpy (pathbuf, "/")) + 1;
+ CloseHandle (__fromthem); __fromthem = NULL;
+ CloseHandle (hp);
+ if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL))
+ sigproc_printf ("WriteFile sizeof argv failed, %E");
+ else if (!WriteFile (__tothem, pathbuf, n, &nr, NULL))
+ sigproc_printf ("WriteFile sizeof argv failed, %E");
+ break;
+ }
case PICOM_FIFO:
{
char path[CYG_MAX_PATH + 1];
switch (code)
{
case PICOM_CMDLINE:
+ case PICOM_CWD:
+ case PICOM_ROOT:
if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n)
{
__seterrno ();
return res;
}
+char *
+_pinfo::root (size_t& n)
+{
+ char *s;
+ if (!this || !pid)
+ return NULL;
+ if (pid != myself->pid)
+ {
+ commune_result cr = commune_send (PICOM_ROOT);
+ s = cr.s;
+ n = cr.n;
+ }
+ else
+ {
+ if (cygheap->root.exists ())
+ s = strdup (cygheap->root.posix_path ());
+ else
+ s = strdup ("/");
+ n = strlen (s) + 1;
+ }
+ return s;
+}
+
+char *
+_pinfo::cwd (size_t& n)
+{
+ char *s;
+ if (!this || !pid)
+ return NULL;
+ if (pid != myself->pid)
+ {
+ commune_result cr = commune_send (PICOM_CWD);
+ s = cr.s;
+ n = cr.n;
+ }
+ else
+ {
+ s = (char *) malloc (CYG_MAX_PATH);
+ cygheap->cwd.get (s, 1, 1, CYG_MAX_PATH);
+ n = strlen (s) + 1;
+ }
+ return s;
+}
+
char *
_pinfo::cmdline (size_t& n)
{
enum picom
{
PICOM_CMDLINE = 1,
- PICOM_FIFO = 2
+ PICOM_FIFO = 2,
+ PICOM_CWD = 3,
+ PICOM_ROOT = 4
};
#define EXITCODE_SET 0x80000000
void commune_recv ();
commune_result commune_send (DWORD, ...);
bool alive ();
+ char *root (size_t &);
+ char *cwd (size_t &);
char *cmdline (size_t &);
void set_ctty (class tty_min *, int, class fhandler_tty_slave *);
bool dup_proc_pipe (HANDLE) __attribute__ ((regparm(2)));