add new files
This commit is contained in:
		
							
								
								
									
										313
									
								
								winsup/cygwin/fhandler_proc.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								winsup/cygwin/fhandler_proc.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,313 @@ | ||||
| /* fhandler_proc.cc: fhandler for /proc virtual filesystem | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
| #include <sys/fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/cygwin.h> | ||||
| #include "cygerrno.h" | ||||
| #include "security.h" | ||||
| #include "fhandler.h" | ||||
| #include "path.h" | ||||
| #include "sigproc.h" | ||||
| #include "pinfo.h" | ||||
| #include <assert.h> | ||||
| #include <sys/utsname.h> | ||||
|  | ||||
| #define _COMPILING_NEWLIB | ||||
| #include <dirent.h> | ||||
|  | ||||
| /* 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 | ||||
|  | ||||
| /* names of objects in /proc */ | ||||
| static const char *proc_listing[] = { | ||||
|   "registry", | ||||
|   "version", | ||||
|   "uptime", | ||||
|   NULL | ||||
| }; | ||||
|  | ||||
| static const int PROC_LINK_COUNT = (sizeof(proc_listing) / sizeof(const char *)) - 1; | ||||
|  | ||||
| /* FH_PROC in the table below means the file/directory is handles by | ||||
|  * fhandler_proc. | ||||
|  */ | ||||
| static const DWORD proc_fhandlers[] = { | ||||
|   FH_REGISTRY, | ||||
|   FH_PROC, | ||||
|   FH_PROC | ||||
| }; | ||||
|  | ||||
| /* name of the /proc filesystem */ | ||||
| const char proc[] = "/proc"; | ||||
| const int proc_len = sizeof (proc) - 1; | ||||
|  | ||||
| /* 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) | ||||
| { | ||||
|   debug_printf ("get_proc_fhandler(%s)", path); | ||||
|   path += proc_len; | ||||
|   /* Since this method is called from path_conv::check we can't rely on | ||||
|    * it being normalised and therefore the path may have runs of slashes | ||||
|    * in it. | ||||
|    */ | ||||
|   while (SLASH_P (*path)) | ||||
|     path++; | ||||
|  | ||||
|   /* Check if this is the root of the virtual filesystem (i.e. /proc).  */ | ||||
|   if (*path == 0) | ||||
|     return FH_PROC; | ||||
|  | ||||
|   for (int i = 0; proc_listing[i]; i++) | ||||
|     { | ||||
|       if (path_prefix_p (proc_listing[i], path, strlen (proc_listing[i]))) | ||||
|         return proc_fhandlers[i]; | ||||
|     } | ||||
|  | ||||
|   int pid = atoi (path); | ||||
|   winpids pids; | ||||
|   for (unsigned i = 0; i < pids.npids; i++) | ||||
|     { | ||||
|       _pinfo *p = pids[i]; | ||||
|  | ||||
|       if (!proc_exists (p)) | ||||
|         continue; | ||||
|  | ||||
|       if (p->pid == pid) | ||||
|         return FH_PROCESS; | ||||
|     } | ||||
|   return FH_BAD; | ||||
| } | ||||
|  | ||||
| /* Returns 0 if path doesn't exist, >0 if path is a directory, | ||||
|  * <0 if path is a file. | ||||
|  */ | ||||
| int | ||||
| fhandler_proc::exists (const char *path) | ||||
| { | ||||
|   debug_printf ("exists (%s)", path); | ||||
|   path += proc_len; | ||||
|   if (*path == 0) | ||||
|     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; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| fhandler_proc::fhandler_proc (): | ||||
|   fhandler_virtual (FH_PROC) | ||||
| { | ||||
| } | ||||
|  | ||||
| fhandler_proc::fhandler_proc (DWORD devtype): | ||||
|   fhandler_virtual (devtype) | ||||
| { | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_proc::fstat (struct __stat64 *buf, path_conv *pc) | ||||
| { | ||||
|   debug_printf ("fstat (%s)", (char *) *pc); | ||||
|   const char *path = get_name (); | ||||
|   path += proc_len; | ||||
|   (void) fhandler_base::fstat (buf, pc); | ||||
|  | ||||
|   buf->st_mode &= ~_IFMT & NO_W; | ||||
|  | ||||
|   if (!*path) | ||||
|     { | ||||
|       buf->st_nlink = PROC_LINK_COUNT; | ||||
|       buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; | ||||
|       return 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       path++; | ||||
|       for (int i = 0; proc_listing[i]; i++) | ||||
|         if (pathmatch (path, proc_listing[i])) | ||||
|           { | ||||
| 	    if (proc_fhandlers[i] != FH_PROC) | ||||
| 	      buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; | ||||
| 	    else | ||||
| 	      { | ||||
| 		buf->st_mode &= NO_X; | ||||
| 		buf->st_mode |= S_IFREG; | ||||
| 	      } | ||||
|             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 (path_conv *pc, int flags, mode_t mode) | ||||
| { | ||||
|   int proc_file_no = -1; | ||||
|  | ||||
|   int res = fhandler_virtual::open (pc, flags, mode); | ||||
|   if (!res) | ||||
|     goto out; | ||||
|  | ||||
|   const char *path; | ||||
|  | ||||
|   path = (char *) *pc + proc_len; | ||||
|  | ||||
|   if (!*path) | ||||
|     { | ||||
|       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; proc_listing[i]; i++) | ||||
|     if (path_prefix_p (proc_listing[i], path + 1, strlen (proc_listing[i]))) | ||||
|       { | ||||
|         proc_file_no = i; | ||||
|         if (proc_fhandlers[i] != FH_PROC) | ||||
|           { | ||||
|             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; | ||||
|               } | ||||
|           } | ||||
|       } | ||||
|  | ||||
|   if (proc_file_no == -1) | ||||
|     { | ||||
|       if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | ||||
|         { | ||||
|           set_errno (EROFS); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           set_errno (ENOENT); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|     } | ||||
|   if (mode & O_WRONLY) | ||||
|     { | ||||
|       set_errno (EROFS); | ||||
|       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 = new char[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 = new char[bufalloc = 40]; | ||||
|         __small_sprintf (filebuf, "%d.%02d\n", ticks / 1000, | ||||
|                          (ticks / 10) % 100); | ||||
|         filesize = strlen (filebuf); | ||||
|         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; | ||||
| } | ||||
							
								
								
									
										294
									
								
								winsup/cygwin/fhandler_process.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								winsup/cygwin/fhandler_process.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,294 @@ | ||||
| /* fhandler_process.cc: fhandler for /proc/<pid> virtual filesystem | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
| #include <sys/fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/cygwin.h> | ||||
| #include "cygerrno.h" | ||||
| #include "security.h" | ||||
| #include "fhandler.h" | ||||
| #include "sigproc.h" | ||||
| #include "pinfo.h" | ||||
| #include "path.h" | ||||
| #include "shared_info.h" | ||||
| #include <assert.h> | ||||
|  | ||||
| #define _COMPILING_NEWLIB | ||||
| #include <dirent.h> | ||||
|  | ||||
| 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 char *process_listing[] = { | ||||
|   "ppid", | ||||
|   "exename", | ||||
|   "winpid", | ||||
|   "winexename", | ||||
|   "status", | ||||
|   "uid", | ||||
|   "gid", | ||||
|   "pgid", | ||||
|   "sid", | ||||
|   "ctty", | ||||
|   NULL | ||||
| }; | ||||
|  | ||||
| static const int PROCESS_LINK_COUNT = (sizeof(process_listing) / sizeof(const char *)) - 1; | ||||
|  | ||||
| /* Returns 0 if path doesn't exist, >0 if path is a directory, | ||||
|  * <0 if path is a file. | ||||
|  */ | ||||
| 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; process_listing[i]; i++) | ||||
|     if (pathmatch (path + 1, process_listing[i])) | ||||
|       return -1; | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| fhandler_process::fhandler_process (): | ||||
|   fhandler_proc (FH_PROCESS) | ||||
| { | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_process::fstat (struct __stat64 *buf, path_conv *path) | ||||
| { | ||||
|   int file_type = exists ((const char *) get_name ()); | ||||
|   switch (file_type) | ||||
|     { | ||||
|     case 0: | ||||
|       set_errno (ENOENT); | ||||
|       return -1; | ||||
|     case 1: | ||||
|       buf->st_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; | ||||
|     default: | ||||
|     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 (path_conv *pc, int flags, mode_t mode) | ||||
| { | ||||
|   int process_file_no = -1, pid; | ||||
|   winpids pids; | ||||
|   _pinfo *p; | ||||
|  | ||||
|   int res = fhandler_virtual::open (pc, flags, mode); | ||||
|   if (!res) | ||||
|     goto out; | ||||
|  | ||||
|   const char *path; | ||||
|   path = (const char *) *pc + 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; process_listing[i]; i++) | ||||
|     { | ||||
|       if (path_prefix_p | ||||
|           (process_listing[i], path + 1, strlen (process_listing[i]))) | ||||
|         process_file_no = i; | ||||
|     } | ||||
|   if (process_file_no == -1) | ||||
|     { | ||||
|       if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | ||||
|         { | ||||
|           set_errno (EROFS); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           set_errno (ENOENT); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|     } | ||||
|   if (mode & O_WRONLY) | ||||
|     { | ||||
|       set_errno (EROFS); | ||||
|       res = 0; | ||||
|       goto out; | ||||
|     } | ||||
|   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); | ||||
|   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; | ||||
| 	  default: | ||||
|           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, "<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 = 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; | ||||
| } | ||||
							
								
								
									
										511
									
								
								winsup/cygwin/fhandler_registry.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										511
									
								
								winsup/cygwin/fhandler_registry.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,511 @@ | ||||
| /* fhandler_registry.cc: fhandler for /proc/registry virtual filesystem | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| /* FIXME: Access permissions are ignored at the moment.  */ | ||||
|  | ||||
| #include "winsup.h" | ||||
| #include <sys/fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/cygwin.h> | ||||
| #include "cygerrno.h" | ||||
| #include "security.h" | ||||
| #include "fhandler.h" | ||||
| #include "path.h" | ||||
| #include <assert.h> | ||||
|  | ||||
| #define _COMPILING_NEWLIB | ||||
| #include <dirent.h> | ||||
|  | ||||
| static const int registry_len = sizeof ("registry") - 1; | ||||
| /* 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. | ||||
|  */ | ||||
| static const __off32_t REG_ENUM_VALUES_MASK = 0x8000000; | ||||
|  | ||||
| /* List of 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[] = { | ||||
|   "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 | ||||
|   NULL | ||||
| }; | ||||
|  | ||||
| static const HKEY registry_keys[] = { | ||||
|   HKEY_CLASSES_ROOT, | ||||
|   HKEY_CURRENT_CONFIG, | ||||
|   HKEY_CURRENT_USER, | ||||
|   HKEY_LOCAL_MACHINE, | ||||
|   HKEY_USERS, | ||||
|   HKEY_DYN_DATA, | ||||
|   HKEY_PERFORMANCE_DATA | ||||
| }; | ||||
|  | ||||
| static const int ROOT_KEY_COUNT = sizeof(registry_keys) / sizeof(HKEY); | ||||
|  | ||||
| /* Name given to default values */ | ||||
| static const char *DEFAULT_VALUE_NAME = "@"; | ||||
|  | ||||
| /* Returns 0 if path doesn't exist, >0 if path is a directory, | ||||
|  * <0 if path is a file. | ||||
|  * | ||||
|  * 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; | ||||
|  | ||||
|   while (SLASH_P (*path)) | ||||
|     path++; | ||||
|   if (*path == 0) | ||||
|     { | ||||
|       file_type = 2; | ||||
|       goto out; | ||||
|     } | ||||
|   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; registry_listing[i]; i++) | ||||
|         if (path_prefix_p | ||||
|             (registry_listing[i], path, strlen (registry_listing[i]))) | ||||
|           { | ||||
|             file_type = 1; | ||||
|             goto out; | ||||
|           } | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   hKey = open_key (path, KEY_READ, true); | ||||
|   if (hKey == (HKEY) INVALID_HANDLE_VALUE) | ||||
|     return 0; | ||||
|  | ||||
|   while (ERROR_SUCCESS == | ||||
|          (error = RegEnumKeyEx (hKey, index++, buf, &buf_size, NULL, NULL, | ||||
|                                 NULL, NULL)) || (error == ERROR_MORE_DATA)) | ||||
|     { | ||||
|       if (pathmatch (buf, file)) | ||||
|         { | ||||
|           file_type = 1; | ||||
|           goto out; | ||||
|         } | ||||
|       buf_size = MAX_PATH; | ||||
|     } | ||||
|   if (error != ERROR_NO_MORE_ITEMS) | ||||
|     { | ||||
|       seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
|       goto out; | ||||
|     } | ||||
|   index = 0; | ||||
|   buf_size = MAX_PATH; | ||||
|   while (ERROR_SUCCESS == | ||||
|          (error = RegEnumValue (hKey, index++, buf, &buf_size, NULL, NULL, | ||||
|                                 NULL, NULL)) || (error == ERROR_MORE_DATA)) | ||||
|     { | ||||
|       if (pathmatch (buf, file) || (buf[0] == '\0' && | ||||
|                                     pathmatch (file, DEFAULT_VALUE_NAME))) | ||||
|         { | ||||
|           file_type = -1; | ||||
|           goto out; | ||||
|         } | ||||
|       buf_size = MAX_PATH; | ||||
|     } | ||||
|   if (error != ERROR_NO_MORE_ITEMS) | ||||
|     { | ||||
|       seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
|       goto out; | ||||
|     } | ||||
| out: | ||||
|   if (hKey != (HKEY) INVALID_HANDLE_VALUE) | ||||
|     RegCloseKey (hKey); | ||||
|   return file_type; | ||||
| } | ||||
|  | ||||
| fhandler_registry::fhandler_registry (): | ||||
|   fhandler_proc (FH_REGISTRY) | ||||
| { | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_registry::fstat (struct __stat64 *buf, path_conv *path) | ||||
| { | ||||
|   this->fhandler_base::fstat (buf, path); | ||||
|   buf->st_mode &= ~_IFMT & NO_W; | ||||
|   int file_type = exists (get_name ()); | ||||
|   switch (file_type) | ||||
|     { | ||||
|     case 0: | ||||
|       set_errno (ENOENT); | ||||
|       return -1; | ||||
|     case 1: | ||||
|       buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; | ||||
|       break; | ||||
|     case 2: | ||||
|       buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; | ||||
|       buf->st_nlink = ROOT_KEY_COUNT; | ||||
|       break; | ||||
|     default: | ||||
|     case -1: | ||||
|       buf->st_mode |= S_IFREG; | ||||
|       buf->st_mode &= NO_X; | ||||
|       break; | ||||
|     } | ||||
|   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; | ||||
| } | ||||
|  | ||||
| __off64_t | ||||
| fhandler_registry::telldir (DIR * dir) | ||||
| { | ||||
|   return dir->__d_position & REG_ENUM_VALUES_MASK; | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_registry::seekdir (DIR * dir, __off32_t loc) | ||||
| { | ||||
|   /* Unfortunately cannot simply 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 (path_conv *pc, 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 (pc, flags, mode); | ||||
|   if (!res) | ||||
|     goto out; | ||||
|  | ||||
|   const char *path; | ||||
|   path = (const char *) *pc + proc_len + 1 + registry_len; | ||||
|   if (!*path) | ||||
|     { | ||||
|       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; registry_listing[i]; i++) | ||||
|         if (path_prefix_p | ||||
|             (registry_listing[i], path, strlen (registry_listing[i]))) | ||||
|           { | ||||
|             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; | ||||
|               } | ||||
|           } | ||||
|  | ||||
|       if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | ||||
|         { | ||||
|           set_errno (EROFS); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           set_errno (ENOENT); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   hKey = open_key (path, KEY_READ, true); | ||||
|   if (hKey == (HKEY) INVALID_HANDLE_VALUE) | ||||
|     { | ||||
|       res = 0; | ||||
|       goto out; | ||||
|     } | ||||
|   if (mode & O_WRONLY) | ||||
|     { | ||||
|       set_errno (EROFS); | ||||
|       res = 0; | ||||
|       goto out; | ||||
|     } | ||||
|   if (pathmatch (file, DEFAULT_VALUE_NAME)) | ||||
|     file = ""; | ||||
|  | ||||
|   if (hKey != HKEY_PERFORMANCE_DATA) | ||||
|     { | ||||
|       error = RegQueryValueEx (hKey, file, NULL, &type, NULL, &size); | ||||
|       if (error != ERROR_SUCCESS) | ||||
|         { | ||||
|           seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
|           res = -1; | ||||
|           goto out; | ||||
|         } | ||||
|       bufalloc = size; | ||||
|       filebuf = new char[bufalloc]; | ||||
|       error = | ||||
|         RegQueryValueEx (hKey, file, NULL, NULL, (BYTE *) filebuf, &size); | ||||
|       if (error != ERROR_SUCCESS) | ||||
|         { | ||||
|           seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
|           res = 0; | ||||
|           goto out; | ||||
|         } | ||||
|       filesize = size; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       bufalloc = 0; | ||||
|       do | ||||
|         { | ||||
|           bufalloc += 1000; | ||||
|           if (filebuf) | ||||
|             { | ||||
|               delete filebuf; | ||||
|               filebuf = new char[bufalloc]; | ||||
|             } | ||||
|           error = | ||||
|             RegQueryValueEx (hKey, file, NULL, &type, (BYTE *) filebuf, | ||||
|                              &size); | ||||
|           if (error != ERROR_SUCCESS && res != ERROR_MORE_DATA) | ||||
|             { | ||||
|               seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
|               res = 0; | ||||
|               goto out; | ||||
|             } | ||||
|         } | ||||
|       while (error == ERROR_MORE_DATA); | ||||
|       filesize = size; | ||||
|     } | ||||
|  | ||||
|   if (flags & O_APPEND) | ||||
|     position = filesize; | ||||
|   else | ||||
|     position = 0; | ||||
|  | ||||
| success: | ||||
|   res = 1; | ||||
|   set_open_status (); | ||||
|   set_flags (flags); | ||||
| out: | ||||
|   if (hKey != (HKEY) INVALID_HANDLE_VALUE) | ||||
|     RegCloseKey (hKey); | ||||
|   syscall_printf ("%d = fhandler_registry::open (%p, %d)", res, flags, mode); | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| /* Auxillary member function to open registry keys.  */ | ||||
| HKEY | ||||
| fhandler_registry::open_key (const char *name, REGSAM access, bool isValue) | ||||
| { | ||||
|   HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|   HKEY hParentKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|   bool parentOpened = false; | ||||
|   char component[MAX_PATH]; | ||||
|  | ||||
|   while (*name) | ||||
|     { | ||||
|       const char *anchor = name; | ||||
|       while (*name && !SLASH_P (*name)) | ||||
|         name++; | ||||
|       strncpy (component, anchor, name - anchor); | ||||
|       component[name - anchor] = '\0'; | ||||
|       if (*name) | ||||
|         name++; | ||||
|       if (*name == 0 && isValue == true) | ||||
|         goto out; | ||||
|  | ||||
|       if (hParentKey != (HKEY) INVALID_HANDLE_VALUE) | ||||
|         { | ||||
|           hKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|           LONG error = RegOpenKeyEx (hParentKey, component, 0, access, &hKey); | ||||
|           if (hKey == (HKEY) INVALID_HANDLE_VALUE) | ||||
|             { | ||||
|               seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
|               return hKey; | ||||
|             } | ||||
|           if (parentOpened) | ||||
|             RegCloseKey (hParentKey); | ||||
|           hParentKey = hKey; | ||||
|           parentOpened = true; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           for (int i = 0; registry_listing[i]; i++) | ||||
|             if (pathmatch (component, registry_listing[i])) | ||||
|               hKey = registry_keys[i]; | ||||
|           if (hKey == (HKEY) INVALID_HANDLE_VALUE) | ||||
|             return hKey; | ||||
|           hParentKey = hKey; | ||||
|         } | ||||
|     } | ||||
| out: | ||||
|   return hKey; | ||||
| } | ||||
							
								
								
									
										207
									
								
								winsup/cygwin/fhandler_virtual.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								winsup/cygwin/fhandler_virtual.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| /* fhandler_virtual.cc: base fhandler class for virtual filesystems | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
| #include <sys/fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/cygwin.h> | ||||
| #include "cygerrno.h" | ||||
| #include "security.h" | ||||
| #include "fhandler.h" | ||||
| #include "path.h" | ||||
| #include "dtable.h" | ||||
| #include "cygheap.h" | ||||
| #include "shared_info.h" | ||||
| #include <assert.h> | ||||
|  | ||||
| #define _COMPILING_NEWLIB | ||||
| #include <dirent.h> | ||||
|  | ||||
| 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 (path_conv& pc) | ||||
| { | ||||
|   DIR *dir; | ||||
|   DIR *res = NULL; | ||||
|   size_t len; | ||||
|  | ||||
|   if (exists (pc) <= 0) | ||||
|     set_errno (ENOTDIR); | ||||
|   else if ((len = strlen (pc)) > 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, pc); | ||||
|       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; | ||||
| } | ||||
|  | ||||
| __off64_t fhandler_virtual::telldir (DIR * dir) | ||||
| { | ||||
|   return dir->__d_position; | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_virtual::seekdir (DIR * dir, __off32_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; | ||||
| } | ||||
|  | ||||
| __off64_t | ||||
| fhandler_virtual::lseek (__off32_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 (__off32_t) -1; | ||||
|     } | ||||
|   return position; | ||||
| } | ||||
|  | ||||
| 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 = len; | ||||
|   if (read > filesize - position) | ||||
|     read = filesize - position; | ||||
|   if (read < 0) | ||||
|     read = 0; | ||||
|   else | ||||
|     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 (path_conv *, 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::exists (const char *path) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user