diff -U 3 -p -b -B -N -x *.d cygwin.bak/Makefile.in cygwin/Makefile.in --- cygwin.bak/Makefile.in Mon Feb 4 22:18:37 2002 +++ cygwin/Makefile.in Thu Feb 7 22:43:29 2002 @@ -123,7 +123,8 @@ DLL_OFILES:=assert.o autoload.o cygheap. fhandler_disk_file.o fhandler_dsp.o fhandler_floppy.o fhandler_mem.o \ fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_socket.o \ fhandler_tape.o fhandler_termios.o fhandler_tty.o fhandler_windows.o \ - fhandler_zero.o fnmatch.o \ + fhandler_zero.o fhandler_proc.o fhandler_registry.o fhandler_process.o \ + fhandler_virtual.o fnmatch.o \ fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o \ malloc.o miscfuncs.o mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o \ poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o registry.o \ diff -U 3 -p -b -B -N -x *.d cygwin.bak/dtable.cc cygwin/dtable.cc --- cygwin.bak/dtable.cc Mon Feb 4 22:18:36 2002 +++ cygwin/dtable.cc Thu Feb 7 22:26:24 2002 @@ -335,6 +335,15 @@ dtable::build_fhandler (int fd, DWORD de case FH_OSS_DSP: fh = cnew (fhandler_dev_dsp) (); break; + case FH_PROC: + fh = cnew (fhandler_proc) (); + break; + case FH_REGISTRY: + fh = cnew (fhandler_registry) (); + break; + case FH_PROCESS: + fh = cnew (fhandler_process) (); + break; default: system_printf ("internal error -- unknown device - %p", dev); fh = NULL; diff -U 3 -p -b -B -N -x *.d cygwin.bak/fhandler.h cygwin/fhandler.h --- cygwin.bak/fhandler.h Mon Feb 4 22:18:36 2002 +++ cygwin/fhandler.h Fri Feb 8 11:37:28 2002 @@ -70,8 +70,11 @@ enum FH_CLIPBOARD = 0x00000017, /* is a clipboard device */ FH_OSS_DSP = 0x00000018, /* is a dsp audio device */ FH_CYGDRIVE= 0x00000019, /* /cygdrive/x */ + FH_PROC = 0x0000001a, /* /proc */ + FH_REGISTRY =0x0000001b, /* /proc/registry */ + FH_PROCESS = 0x0000001c, /* /proc/ */ - FH_NDEV = 0x0000001a, /* Maximum number of devices */ + FH_NDEV = 0x0000001d, /* Maximum number of devices */ FH_DEVMASK = 0x00000fff, /* devices live here */ FH_BAD = 0xffffffff }; @@ -100,6 +103,9 @@ enum extern const char *windows_device_names[]; extern struct __cygwin_perfile *perfile_table; #define __fmode (*(user_data->fmode_ptr)) +extern const char *proc; +extern const int proc_len; + class select_record; class path_conv; @@ -1024,6 +1030,79 @@ class fhandler_dev_dsp : public fhandler void fixup_after_exec (HANDLE); }; +class fhandler_virtual : public fhandler_base +{ + protected: + char normalized_path[MAX_PATH]; + char *filebuf; + int bufalloc, filesize, position; + + /* 0 = not exist, >0 = dir, <0 = file */ + virtual int exists(const char *path); + public: + + fhandler_virtual (DWORD devtype); + virtual ~fhandler_virtual(); + + DIR *opendir (path_conv& pc); + virtual DIR *opendir(const char *path); + off_t telldir (DIR *); + void seekdir (DIR *, off_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))); + off_t lseek (off_t, int); + int dup (fhandler_base * child); + int open (path_conv *, int flags, mode_t mode = 0); + virtual int open(const char *path, int flags, mode_t mode); + int close (void); + virtual int fstat (const char *path, struct stat *buf); + int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (3))); +}; + +class fhandler_proc: public fhandler_virtual +{ + protected: + int exists(const char *path); + public: + fhandler_proc (); + fhandler_proc (DWORD devtype); + struct dirent *readdir (DIR *); + int fstat (const char *path, struct stat *buf); + int open(const char *path, int flags, mode_t mode); + + static DWORD get_proc_fhandler(const char *path); +}; + +class fhandler_registry: public fhandler_proc +{ + protected: + int exists(const char *path); + public: + fhandler_registry (); + struct dirent *readdir (DIR *); + off_t telldir (DIR *); + void seekdir (DIR *, off_t); + void rewinddir (DIR *); + int closedir (DIR *); + virtual int fstat (const char *path, struct stat *buf); + int open (const char *path, int flags, mode_t mode = 0); + + static HKEY open_key(const char *name, REGSAM access = KEY_READ, bool isValue = false); +}; + +class fhandler_process: public fhandler_proc +{ + protected: + int exists(const char *path); + public: + fhandler_process (); + struct dirent *readdir (DIR *); + virtual int fstat (const char *path, struct stat *buf); + int open (const char *path, int flags, mode_t mode = 0); +}; + typedef union { char base[sizeof(fhandler_base)]; @@ -1039,7 +1118,10 @@ typedef union char dev_zero[sizeof(fhandler_dev_zero)]; char disk_file[sizeof(fhandler_disk_file)]; char pipe[sizeof(fhandler_pipe)]; + char proc[sizeof(fhandler_proc)]; + char process[sizeof(fhandler_process)]; char pty_master[sizeof(fhandler_pty_master)]; + char registry[sizeof(fhandler_registry)]; char serial[sizeof(fhandler_serial)]; char socket[sizeof(fhandler_socket)]; char termios[sizeof(fhandler_termios)]; diff -U 3 -p -b -B -N -x *.d cygwin.bak/fhandler_proc.cc cygwin/fhandler_proc.cc --- cygwin.bak/fhandler_proc.cc Thu Jan 1 00:00:00 1970 +++ cygwin/fhandler_proc.cc Sat Feb 9 22:53:35 2002 @@ -0,0 +1,291 @@ +/* fhandler_proc.cc */ +/* + (C) Copyright Christopher January 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "winsup.h" +#include +#include +#include +#include +#include +#include "cygerrno.h" +#include "security.h" +#include "fhandler.h" +#include "path.h" +#include "sigproc.h" +#include "pinfo.h" +#include +#include + +#define _COMPILING_NEWLIB +#include + +/* offsets in proc_listing */ +static const int PROC_REGISTRY = 0; /* /proc/registry */ +static const int PROC_VERSION = 1; /* /proc/version */ +static const int PROC_UPTIME = 2; /* /proc/uptime */ +static const int PROC_LINK_COUNT = 3; + +/* names of objects in /proc */ +static const char *proc_listing[PROC_LINK_COUNT] = { "registry", + "version", + "uptime" }; +/* FH_PROC in the table below means the file/directory is handles by fhandler_proc + * at present, there are no files in /proc so fhandler_proc does not have support for opening/closing + * files. + */ +static DWORD proc_fhandlers[PROC_LINK_COUNT] = { FH_REGISTRY , + FH_PROC, + FH_PROC }; + +const char *proc = "/proc"; +const int proc_len = strlen(proc); + +/* 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 + */ +DWORD +fhandler_proc::get_proc_fhandler(const char *path) +{ + path += proc_len; + while (SLASH_P(*path)) + path++; + + if (*path == 0) + return FH_PROC; + for (int i=0;ipid == pid) + return FH_PROCESS; + } + return FH_PROC; +} + +int +fhandler_proc::exists(const char *path) +{ + debug_printf ("exists (%s)", path); + path += proc_len; + if (*path == 0) + return 2; + for (int i=0;ist_mode = S_IFDIR | 0555; + buf->st_nlink = PROC_LINK_COUNT; + return 0; + } + else + { + for (int i=0;ist_mode = (proc_fhandlers[i] == FH_PROC)?(S_IFREG | 0444):(S_IFDIR | 0555); + buf->st_nlink = 1; + return 0; + } + } + set_errno(ENOENT); + return -1; +} + +struct dirent * +fhandler_proc::readdir (DIR *dir) +{ + if (dir->__d_position >= PROC_LINK_COUNT) + { + winpids pids; + int found = 0; + for (unsigned i = 0; i < pids.npids; i++) + { + _pinfo *p = pids[i]; + + if (!proc_exists (p)) + continue; + + if (found == dir->__d_position - PROC_LINK_COUNT) + { + __small_sprintf(dir->__d_dirent->d_name, "%d", p->pid); + dir->__d_position++; + return dir->__d_dirent; + } + found++; + } + return NULL; + } + + strcpy(dir->__d_dirent->d_name, proc_listing[dir->__d_position++]); + syscall_printf ("%p = readdir (%p) (%s)", &dir->__d_dirent, dir, + dir->__d_dirent->d_name); + return dir->__d_dirent; +} + +int +fhandler_proc::open (const char *path, int flags, mode_t mode) +{ + int proc_file_no = -1; + + int res = fhandler_virtual::open(path, flags, mode); + if (!res) + goto out; + + path += proc_len; + + if (*path == 0) + { + if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno(EEXIST); + res = 0; + goto out; + } + else if (mode & O_WRONLY) + { + set_errno(EISDIR); + res = 0; + goto out; + } + else + { + flags |= O_DIROPEN; + goto success; + } + } + + proc_file_no = -1; + for (int i=0;i +#include +#include +#include +#include +#include "cygerrno.h" +#include "security.h" +#include "fhandler.h" +#include "sigproc.h" +#include "pinfo.h" +#include "path.h" +#include "shared_info.h" +#include + +#define _COMPILING_NEWLIB +#include + +static const int PROCESS_PPID = 0; +static const int PROCESS_EXENAME = 1; +static const int PROCESS_WINPID = 2; +static const int PROCESS_WINEXENAME = 3; +static const int PROCESS_STATUS = 4; +static const int PROCESS_UID = 5; +static const int PROCESS_GID = 6; +static const int PROCESS_PGID = 7; +static const int PROCESS_SID = 8; +static const int PROCESS_CTTY = 9; +static const int PROCESS_LINK_COUNT = 10; + +static const char *process_listing[PROCESS_LINK_COUNT] = { "ppid", + "exename", + "winpid", + "winexename", + "status", + "uid", + "gid", + "pgid", + "sid", + "ctty" }; + +int +fhandler_process::exists(const char *path) +{ + debug_printf ("exists (%s)", path); + path += proc_len + 1; + while (*path != 0 && !SLASH_P(*path)) + path++; + if (*path == 0) + return 2; + + for (int i=0;ist_mode = S_IFDIR | 0555; + buf->st_nlink = 1; + return 0; + case 2: + buf->st_mode = S_IFDIR | 0555; + buf->st_nlink = PROCESS_LINK_COUNT; + return 0; + case -1: + buf->st_mode = S_IFREG | 0444; + buf->st_nlink = 1; + return 0; + } +} + +struct dirent * +fhandler_process::readdir (DIR *dir) +{ + if (dir->__d_position >= PROCESS_LINK_COUNT) + return NULL; + strcpy(dir->__d_dirent->d_name, process_listing[dir->__d_position++]); + syscall_printf ("%p = readdir (%p) (%s)", &dir->__d_dirent, dir, + dir->__d_dirent->d_name); + return dir->__d_dirent; +} + +int +fhandler_process::open (const char *path, int flags, mode_t mode) +{ + int process_file_no = -1, pid; + winpids pids; + _pinfo *p; + + int res = fhandler_virtual::open(path, flags, mode); + if (!res) + goto out; + + path += proc_len + 1; + pid = atoi(path); + while (*path != 0 && !SLASH_P(*path)) + path++; + + if (*path == 0) + { + if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno(EEXIST); + res = 0; + goto out; + } + else if (mode & O_WRONLY) + { + set_errno(EISDIR); + res = 0; + goto out; + } + else + { + flags |= O_DIROPEN; + goto success; + } + } + + process_file_no = -1; + for (int i=0;ipid == pid) + goto found; + } + set_errno(ENOENT); + 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 = new char[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; + case PROCESS_CTTY: + num = p->ctty; break; + } + __small_sprintf(filebuf, "%d\n", num); + filesize = strlen(filebuf); + break; + } + case PROCESS_EXENAME: + { + filebuf = new char[bufalloc = MAX_PATH]; + if (p->process_state & (PID_ZOMBIE | PID_EXITED)) + strcpy(filebuf, ""); + 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 = new char[bufalloc = 40]; + __small_sprintf(filebuf, "%d\n", p->dwProcessId); + filesize = strlen(filebuf); + break; + } + case PROCESS_WINEXENAME: + { + int len = strlen(p->progname); + filebuf = new char[len + 2]; + strcpy(filebuf, p->progname); + filebuf[len] = '\n'; + filesize = len + 1; + break; + } + case PROCESS_STATUS: + { + filebuf = new char[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; + } + } + + if (flags & O_APPEND) + position = filesize; + else + position = 0; + +success: + res = 1; + set_open_status (); + set_flags(flags); +out: + syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + return res; +} diff -U 3 -p -b -B -N -x *.d cygwin.bak/fhandler_registry.cc cygwin/fhandler_registry.cc --- cygwin.bak/fhandler_registry.cc Thu Jan 1 00:00:00 1970 +++ cygwin/fhandler_registry.cc Sat Feb 9 22:53:51 2002 @@ -0,0 +1,502 @@ +/* fhandler_registry.cc */ +/* + (C) Copyright Christopher January 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* access permissions are ignored at the moment... */ +/* use splipath ? */ + +#include "winsup.h" +#include +#include +#include +#include +#include +#include "cygerrno.h" +#include "security.h" +#include "fhandler.h" +#include "path.h" +#include + +#define _COMPILING_NEWLIB +#include + +const int registry_len = strlen("registry"); +/* if this bit is set in __d_position then we are enumerating values, + * else sub-keys. keeping track of where we are is horribly messy + * the bottom 16 bits are the absolute position and the top 15 bits + * make up the value index if we are enuerating values. + */ +const off_t REG_ENUM_VALUES_MASK = 0x8000000; + +const int ROOT_KEY_COUNT = 7; + +/* root keys in /proc/registry + * possibly we should filter out those not relevant to the flavour of Windows + * cygwin is running on + */ +static const char *registry_listing[ROOT_KEY_COUNT] = { "HKEY_CLASSES_ROOT", + "HKEY_CURRENT_CONFIG", + "HKEY_CURRENT_USER", + "HKEY_LOCAL_MACHINE", + "HKEY_USERS", + "HKEY_DYN_DATA", // 95/98/Me + "HKEY_PERFOMANCE_DATA" }; // NT/2000/XP +static HKEY registry_keys[ROOT_KEY_COUNT] = { HKEY_CLASSES_ROOT, + HKEY_CURRENT_CONFIG, + HKEY_CURRENT_USER, + HKEY_LOCAL_MACHINE, + HKEY_USERS, + HKEY_DYN_DATA, + HKEY_PERFORMANCE_DATA }; + +const char *DEFAULT_VALUE_NAME = "@"; + +/* we open the last key but one and then enum it's sub-keys and values to see if the + * final component is there. this gets round the problem of not having security access + * to the final key in the path. + */ + +int fhandler_registry::exists(const char *path) +{ + int file_type = 0, index = 0, pathlen; + DWORD buf_size = MAX_PATH; + LONG error; + char buf[buf_size]; + const char *file; + HKEY hKey = (HKEY)INVALID_HANDLE_VALUE; + + debug_printf ("exists (%s)", path); + path += proc_len + 1 + registry_len; + if (*path == 0) + { + file_type = 2; + goto out; + } + + path++; + pathlen = strlen(path); + file = path + pathlen - 1; + if (SLASH_P(*file) && pathlen > 1) + file--; + while (!SLASH_P(*file)) + file--; + file++; + + if (file == path) + { + for (int i=0;ist_mode = S_IFDIR | 0555; + buf->st_nlink = 1; + return 0; + case 2: + buf->st_mode = S_IFDIR | 0555; + buf->st_nlink = ROOT_KEY_COUNT; + return 0; + case -1: + buf->st_mode = S_IFREG | 0444; + buf->st_nlink = 1; + return 0; + } +} + +struct dirent * +fhandler_registry::readdir (DIR *dir) +{ + DWORD buf_size = MAX_PATH; + char buf[buf_size]; + HANDLE handle; + struct dirent *res = NULL; + const char *path = dir->__d_dirname + proc_len + 1 + registry_len; + LONG error; + + if (*path == 0) + { + if (dir->__d_position >= ROOT_KEY_COUNT) + goto out; + strcpy(dir->__d_dirent->d_name, registry_listing[dir->__d_position++]); + res = dir->__d_dirent; + goto out; + } + + if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE + && dir->__d_position == 0) + { + handle = open_key(path + 1); + dir->__d_u.__d_data.__handle = handle; + } + if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE) + goto out; +retry: + if (dir->__d_position & REG_ENUM_VALUES_MASK) + /* for the moment, the type of key is ignored here. when write access is added, + * maybe add an extension for the type of each value? + */ + error = RegEnumValue((HKEY)dir->__d_u.__d_data.__handle, + (dir->__d_position & ~REG_ENUM_VALUES_MASK) >> 16, + buf, &buf_size, NULL, NULL, NULL, NULL); + else + error = RegEnumKeyEx((HKEY)dir->__d_u.__d_data.__handle, dir->__d_position, buf, + &buf_size, NULL, NULL, NULL, NULL); + if (error == ERROR_NO_MORE_ITEMS && (dir->__d_position & REG_ENUM_VALUES_MASK) == 0) + { + /* if we're finished with sub-keys, start on values under this key */ + dir->__d_position |= REG_ENUM_VALUES_MASK; + buf_size = MAX_PATH; + goto retry; + } + if (error != ERROR_SUCCESS && error != ERROR_MORE_DATA) + { + RegCloseKey ((HKEY)dir->__d_u.__d_data.__handle); + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + if (error != ERROR_NO_MORE_ITEMS) + seterrno_from_win_error (__FILE__, __LINE__, error); + goto out; + } + + /* We get here if `buf' contains valid data. */ + if (*buf == 0) + strcpy (dir->__d_dirent->d_name, DEFAULT_VALUE_NAME); + else + strcpy (dir->__d_dirent->d_name, buf); + + dir->__d_position++; + if (dir->__d_position & REG_ENUM_VALUES_MASK) + dir->__d_position += 0x10000; + res = dir->__d_dirent; +out: + syscall_printf ("%p = readdir (%p) (%s)", + &dir->__d_dirent, dir, buf); + return res; +} + +off_t +fhandler_registry::telldir (DIR *dir) +{ + return dir->__d_position & REG_ENUM_VALUES_MASK; +} + +void +fhandler_registry::seekdir (DIR *dir, off_t loc) +{ + /* unfortunately cannot just set __d_position due to transition from sub-keys to + * values. + */ + rewinddir (dir); + while (loc > dir->__d_position) + if (!readdir (dir)) + break; +} + +void +fhandler_registry::rewinddir (DIR *dir) +{ + if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE) + { + (void) RegCloseKey ((HKEY)dir->__d_u.__d_data.__handle); + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + } + dir->__d_position = 0; + return; +} + +int +fhandler_registry::closedir (DIR *dir) +{ + int res = 0; + if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE && + RegCloseKey ((HKEY)dir->__d_u.__d_data.__handle) != ERROR_SUCCESS) + { + __seterrno (); + res = -1; + } + syscall_printf ("%d = closedir (%p)", res, dir); + return 0; +} + +int +fhandler_registry::open (const char *path, int flags, mode_t mode) +{ + DWORD type, size; + LONG error; + HKEY hKey = (HKEY)INVALID_HANDLE_VALUE; + int pathlen; + const char *file; + + int res = fhandler_virtual::open(path, flags, mode); + if (!res) + goto out; + + path += proc_len + 1 + registry_len; + if (*path == 0) + { + if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno(EEXIST); + res = 0; + goto out; + } + else if (mode & O_WRONLY) + { + set_errno(EISDIR); + res = 0; + goto out; + } + else + { + flags |= O_DIROPEN; + goto success; + } + } + path++; + pathlen = strlen(path); + file = path + pathlen - 1; + if (SLASH_P(*file) && pathlen > 1) + file--; + while (!SLASH_P(*file)) + file--; + file++; + + if (file == path) + { + for (int i=0;i +#include +#include +#include +#include +#include "cygerrno.h" +#include "security.h" +#include "fhandler.h" +#include "path.h" +#include "dtable.h" +#include "cygheap.h" +#include "shared_info.h" +#include + +#define _COMPILING_NEWLIB +#include + +fhandler_virtual::fhandler_virtual (DWORD devtype) : + fhandler_base (devtype), filebuf(NULL), bufalloc(-1) +{ +} +fhandler_virtual::~fhandler_virtual() +{ + if (filebuf) + delete filebuf; filebuf = NULL; +} + +DIR * +fhandler_virtual::opendir (const char *path) +{ + DIR *dir; + DIR *res = NULL; + size_t len; + + if (exists(path) <= 0) + set_errno (ENOTDIR); + else if ((len = strlen (path))> MAX_PATH - 3) + set_errno (ENAMETOOLONG); + else if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL) + set_errno (ENOMEM); + else if ((dir->__d_dirname = (char *) malloc (len + 3)) == NULL) + { + free (dir); + set_errno (ENOMEM); + } + else if ((dir->__d_dirent = + (struct dirent *) malloc (sizeof (struct dirent))) == NULL) + { + free (dir); + set_errno (ENOMEM); + } + else + { + strcpy(dir->__d_dirname, path); + dir->__d_dirent->d_version = __DIRENT_VERSION; + cygheap_fdnew fd; + fd = this; + fd->set_nohandle (true); + dir->__d_dirent->d_fd = fd; + dir->__d_u.__d_data.__fh = this; + dir->__d_cookie = __DIRENT_COOKIE; + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + dir->__d_position = 0; + dir->__d_dirhash = get_namehash (); + + res = dir; + } + + syscall_printf ("%p = opendir (%s)", res, get_name ()); + return res; +} + + +DIR * +fhandler_virtual::opendir (path_conv& real_name) +{ + normalize_posix_path(get_name(), normalized_path); + return opendir(normalized_path); +} + +off_t +fhandler_virtual::telldir (DIR *dir) +{ + return dir->__d_position; +} + +void +fhandler_virtual::seekdir (DIR *dir, off_t loc) +{ + dir->__d_position = loc; + return; +} + +void +fhandler_virtual::rewinddir (DIR *dir) +{ + dir->__d_position = 0; + return; +} + +int +fhandler_virtual::closedir (DIR *dir) +{ + return 0; +} + +off_t +fhandler_virtual::lseek (off_t offset, int whence) +{ + switch (whence) + { + case SEEK_SET: + position = offset; + break; + case SEEK_CUR: + position += offset; + break; + case SEEK_END: + position = filesize + offset; + break; + default: + set_errno(EINVAL); + return (off_t)-1; + } +} + +int +fhandler_virtual::dup (fhandler_base *child) +{ + fhandler_virtual *fhproc_child = (fhandler_virtual *)child; + fhproc_child->filebuf = new char[filesize]; + fhproc_child->bufalloc = fhproc_child->filesize = filesize; + fhproc_child->position = position; + return 0; +} + +int +fhandler_virtual::close () +{ + if (filebuf) + delete [] filebuf; filebuf = NULL; bufalloc = -1; + cygwin_shared->delqueue.process_queue (); + return 0; +} + +int +fhandler_virtual::read (void *ptr, size_t len) +{ + if (len == 0) + return 0; + if (openflags & O_DIROPEN) { + set_errno(EISDIR); + return -1; + } + if (!filebuf) + return 0; + int read = max(0, min(len, filesize - position)); + if (read >= 0) + memcpy(ptr, filebuf + position, read); + position += read; + return read; +} + +int +fhandler_virtual::write (const void *ptr, size_t len) +{ + set_errno(EROFS); + return -1; +} + +/* low-level open for all proc files */ +int +fhandler_virtual::open (const char *normalized_path, int flags, mode_t mode) +{ + set_r_binary (1); + set_w_binary (1); + + set_has_acls (false); + set_isremote (false); + + /* what to do about symlinks? */ + set_symlink_p (false); + set_execable_p (not_executable); + set_socket_p (false); + + set_flags(flags); + + return 1; +} + +int +fhandler_virtual::open (path_conv *real_path, int flags, mode_t mode) +{ + normalize_posix_path(get_name(), normalized_path); + return open(normalized_path, flags, mode); +} + +int +fhandler_virtual::fstat (struct stat *buf, path_conv *pc) +{ + normalize_posix_path(get_name(), normalized_path); + return fstat(normalized_path, buf); +} + +int +fhandler_virtual::fstat(const char *path, struct stat *buf) +{ + set_errno(ENOENT); + return -1; +} + +int +fhandler_virtual::exists(const char *path) +{ + return 0; +} diff -U 3 -p -b -B -N -x *.d cygwin.bak/path.cc cygwin/path.cc --- cygwin.bak/path.cc Mon Feb 4 22:18:37 2002 +++ cygwin/path.cc Sat Feb 9 22:17:09 2002 @@ -118,6 +118,12 @@ int pcheck_case = PCHECK_RELAXED; /* Det (isdirsep(path[mount_table->cygdrive_len + 1]) || \ !path[mount_table->cygdrive_len + 1])) +#define isproc(path) \ + (path_prefix_p (proc, (path), proc_len)) + +#define isvirtual_dev(devn) \ + (devn == FH_CYGDRIVE || devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS) + /* Return non-zero if PATH1 is a prefix of PATH2. Both are assumed to be of the same path style and / vs \ usage. Neither may be "". @@ -490,6 +496,11 @@ path_conv::check (const char *src, unsig } goto out; } + else if (isvirtual_dev(devn)) + { + fileattr = 0; + return; + } /* devn should not be a device. If it is, then stop parsing now. */ else if (devn != FH_BAD) { @@ -1405,10 +1416,17 @@ mount_info::conv_to_win32_path (const ch else if (mount_table->cygdrive_len > 1) return ENOENT; } + if (isproc (pathbuf)) + { + devn = fhandler_proc::get_proc_fhandler(pathbuf); + debug_printf("returned %d\n", devn); + dst[0] = '\0'; + goto out; + } int chrooted_path_len; chrooted_path_len = 0; - /* Check the mount table for prefix matches. */ + /* Check the mount table for prefix matches */ for (i = 0; i < nmounts; i++) { const char *path; @@ -1472,7 +1490,7 @@ mount_info::conv_to_win32_path (const ch *flags = mi->flags; } - if (devn != FH_CYGDRIVE) + if (!isvirtual_dev(devn)) win32_device_name (src_path, dst, devn, unit); out: @@ -3233,7 +3251,8 @@ chdir (const char *in_dir) path.get_win32 ()[3] = '\0'; } int res; - if (path.get_devn () != FH_CYGDRIVE) + int devn = path.get_devn(); + if (!isvirtual_dev(devn)) res = SetCurrentDirectory (native_dir) ? 0 : -1; else { diff -U 3 -p -b -B -N -x *.d cygwin.bak/path.h cygwin/path.h --- cygwin.bak/path.h Mon Feb 4 22:18:37 2002 +++ cygwin/path.h Fri Feb 8 12:17:10 2002 @@ -178,3 +178,6 @@ has_exec_chars (const char *buf, int len int pathmatch (const char *path1, const char *path2) __attribute__ ((regparm (2))); int pathnmatch (const char *path1, const char *path2, int len) __attribute__ ((regparm (2))); + +int path_prefix_p (const char *path1, const char *path2, int len1) __attribute__ ((regparm (3))); +int normalize_posix_path (const char *src, char *dst);