From d68288f697fae3c3cebe1cfa4780b467cf85f13c Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Fri, 1 Apr 2011 19:48:19 +0000 Subject: [PATCH] Implement /proc/sysvipc/* * devices.in (dev_procsysvipc_storage): Add. * devices.cc: Regenerate. * devices.h (fh_devices): Add FH_PROCSYSVIPC. * dtable.cc (build_fh_pc): Add case FH_PROCSYSVIPC. * fhandler.h (class fhandler_procsysvipc): Declare. (fhandler_union): Add __procsysvipc. * fhandler_proc.cc (proc_tab): Add sysvipc virt_directory. * fhandler_procsysvipc.cc: New file. * Makefile.in (DLL_OFILES): Add fhandler_procsysvipc.o. * path.h (isproc_dev): Add FH_PROCSYSVIPC to conditional. --- winsup/cygwin/ChangeLog | 14 ++ winsup/cygwin/Makefile.in | 12 +- winsup/cygwin/devices.cc | 3 + winsup/cygwin/devices.h | 1 + winsup/cygwin/devices.in | 3 + winsup/cygwin/dtable.cc | 3 + winsup/cygwin/fhandler.h | 13 + winsup/cygwin/fhandler_proc.cc | 1 + winsup/cygwin/fhandler_procsysvipc.cc | 347 ++++++++++++++++++++++++++ winsup/cygwin/path.h | 2 +- 10 files changed, 392 insertions(+), 7 deletions(-) create mode 100644 winsup/cygwin/fhandler_procsysvipc.cc diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 660a5eeeb..09aeb6529 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +2011-04-01 Yaakov Selkowitz + + Implement /proc/sysvipc/* + * devices.in (dev_procsysvipc_storage): Add. + * devices.cc: Regenerate. + * devices.h (fh_devices): Add FH_PROCSYSVIPC. + * dtable.cc (build_fh_pc): Add case FH_PROCSYSVIPC. + * fhandler.h (class fhandler_procsysvipc): Declare. + (fhandler_union): Add __procsysvipc. + * fhandler_proc.cc (proc_tab): Add sysvipc virt_directory. + * fhandler_procsysvipc.cc: New file. + * Makefile.in (DLL_OFILES): Add fhandler_procsysvipc.o. + * path.h (isproc_dev): Add FH_PROCSYSVIPC to conditional. + 2011-04-01 Corinna Vinschen * Makefile.in (DLL_OFILES): Add avapi32.o. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 1b5b48806..f80fa3ad6 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -142,12 +142,12 @@ DLL_OFILES:=advapi32.o assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o \ fhandler_disk_file.o fhandler_dsp.o fhandler_fifo.o fhandler_floppy.o \ fhandler_mailslot.o fhandler_mem.o fhandler_netdrive.o fhandler_nodevice.o \ fhandler_proc.o fhandler_process.o fhandler_procnet.o fhandler_procsys.o \ - fhandler_random.o fhandler_raw.o fhandler_registry.o fhandler_serial.o \ - fhandler_socket.o fhandler_tape.o fhandler_termios.o fhandler_tty.o \ - fhandler_virtual.o fhandler_windows.o fhandler_zero.o flock.o fnmatch.o \ - fork.o fts.o ftw.o getopt.o glob.o glob_pattern_p.o globals.o grp.o heap.o \ - hookapi.o inet_addr.o inet_network.o init.o ioctl.o ipc.o kernel32.o \ - libstdcxx_wrapper.o localtime.o lsearch.o malloc_wrapper.o \ + fhandler_procsysvipc.o fhandler_random.o fhandler_raw.o fhandler_registry.o \ + fhandler_serial.o fhandler_socket.o fhandler_tape.o fhandler_termios.o \ + fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \ + flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o glob_pattern_p.o \ + globals.o grp.o heap.o hookapi.o inet_addr.o inet_network.o init.o ioctl.o \ + ipc.o kernel32.o libstdcxx_wrapper.o localtime.o lsearch.o malloc_wrapper.o \ minires-os-if.o minires.o miscfuncs.o mktemp.o mmap.o msg.o \ mount.o net.o netdb.o nfs.o nftw.o nlsfuncs.o ntea.o passwd.o path.o \ pinfo.o pipe.o poll.o posix_ipc.o pseudo-reloc.o pthread.o random.o \ diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index 72c9a04a3..569d239e1 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -27,6 +27,9 @@ const device dev_procnet_storage = const device dev_procsys_storage = {"", {FH_PROCSYS}, ""}; +const device dev_procsysvipc_storage = + {"", {FH_PROCSYSVIPC}, ""}; + const device dev_netdrive_storage = {"", {FH_NETDRIVE}, ""}; diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h index 60c21a714..4441b4436 100644 --- a/winsup/cygwin/devices.h +++ b/winsup/cygwin/devices.h @@ -54,6 +54,7 @@ enum fh_devices FH_PROCNET = FHDEV (0, 244), FH_PROCESSFD = FHDEV (0, 243), FH_PROCSYS = FHDEV (0, 242), + FH_PROCSYSVIPC = FHDEV (0,241), DEV_FLOPPY_MAJOR = 2, FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0), diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index 058e1617f..7ce8994bb 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -23,6 +23,9 @@ const device dev_procnet_storage = const device dev_procsys_storage = {"", {FH_PROCSYS}, ""}; +const device dev_procsysvipc_storage = + {"", {FH_PROCSYSVIPC}, ""}; + const device dev_netdrive_storage = {"", {FH_NETDRIVE}, ""}; diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 6a9d55df1..4529aa906 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -543,6 +543,9 @@ build_fh_pc (path_conv& pc, bool set_name) case FH_PROCSYS: fh = cnew (fhandler_procsys) (); break; + case FH_PROCSYSVIPC: + fh = cnew (fhandler_procsysvipc) (); + break; case FH_NETDRIVE: fh = cnew (fhandler_netdrive) (); break; diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index f223a1151..b833d7133 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1419,6 +1419,18 @@ class fhandler_procsys: public fhandler_virtual bool fill_filebuf (); }; +class fhandler_procsysvipc: public fhandler_proc +{ + pid_t pid; + public: + fhandler_procsysvipc (); + virtual_ftype_t exists(); + int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); + int open (int flags, mode_t mode = 0); + int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); + bool fill_filebuf (); +}; + class fhandler_netdrive: public fhandler_virtual { public: @@ -1517,6 +1529,7 @@ typedef union char __process[sizeof (fhandler_process)]; char __procnet[sizeof (fhandler_procnet)]; char __procsys[sizeof (fhandler_procsys)]; + char __procsysvipc[sizeof (fhandler_procsysvipc)]; char __pty_master[sizeof (fhandler_pty_master)]; char __registry[sizeof (fhandler_registry)]; char __serial[sizeof (fhandler_serial)]; diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc index 6ae7d807d..c46fbbe6f 100644 --- a/winsup/cygwin/fhandler_proc.cc +++ b/winsup/cygwin/fhandler_proc.cc @@ -61,6 +61,7 @@ static const virt_tab_t proc_tab[] = { { _VN ("self"), FH_PROC, virt_symlink, format_proc_self }, { _VN ("stat"), FH_PROC, virt_file, format_proc_stat }, { _VN ("sys"), FH_PROCSYS, virt_directory, NULL }, + { _VN ("sysvipc"), FH_PROCSYSVIPC, virt_directory, NULL }, { _VN ("uptime"), FH_PROC, virt_file, format_proc_uptime }, { _VN ("version"), FH_PROC, virt_file, format_proc_version }, { NULL, 0, 0, virt_none, NULL } diff --git a/winsup/cygwin/fhandler_procsysvipc.cc b/winsup/cygwin/fhandler_procsysvipc.cc new file mode 100644 index 000000000..a486a2944 --- /dev/null +++ b/winsup/cygwin/fhandler_procsysvipc.cc @@ -0,0 +1,347 @@ +/* fhandler_procsysvipc.cc: fhandler for /proc/sysvipc virtual filesystem + + Copyright 2011 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 +#include +#include +#include "cygerrno.h" +#include "cygserver.h" +#include "security.h" +#include "path.h" +#include "fhandler.h" +#include "fhandler_virtual.h" +#include "pinfo.h" +#include "shared_info.h" +#include "dtable.h" +#include "cygheap.h" +#include "ntdll.h" +#include "cygtls.h" +#include "pwdgrp.h" +#include "tls_pbuf.h" +#include +#include + +#define _COMPILING_NEWLIB +#include + +#define _KERNEL +#include +#include +#include +#include + +static _off64_t format_procsysvipc_msg (void *, char *&); +static _off64_t format_procsysvipc_sem (void *, char *&); +static _off64_t format_procsysvipc_shm (void *, char *&); + +static const virt_tab_t procsysvipc_tab[] = +{ + { _VN ("."), FH_PROCSYSVIPC, virt_directory, NULL }, + { _VN (".."), FH_PROCSYSVIPC, virt_directory, NULL }, + { _VN ("msg"), FH_PROCSYSVIPC, virt_file, format_procsysvipc_msg }, + { _VN ("sem"), FH_PROCSYSVIPC, virt_file, format_procsysvipc_sem }, + { _VN ("shm"), FH_PROCSYSVIPC, virt_file, format_procsysvipc_shm }, + { NULL, 0, 0, virt_none, NULL } +}; + +static const int PROCSYSVIPC_LINK_COUNT = + (sizeof (procsysvipc_tab) / sizeof (virt_tab_t)) - 1; + +/* Returns 0 if path doesn't exist, >0 if path is a directory, + * -1 if path is a file. + */ +virtual_ftype_t +fhandler_procsysvipc::exists () +{ + const char *path = get_name (); + debug_printf ("exists (%s)", path); + path += proc_len + 1; + while (*path != 0 && !isdirsep (*path)) + path++; + if (*path == 0) + return virt_rootdir; + + virt_tab_t *entry = virt_tab_search (path + 1, true, procsysvipc_tab, + PROCSYSVIPC_LINK_COUNT); + + cygserver_init(); + + if (entry) + { + if (entry->type == virt_file) + { + if (cygserver_running != CYGSERVER_OK) + return virt_none; + } + fileid = entry - procsysvipc_tab; + return entry->type; + } + return virt_none; +} + +fhandler_procsysvipc::fhandler_procsysvipc (): + fhandler_proc () +{ +} + +int +fhandler_procsysvipc::fstat (struct __stat64 *buf) +{ + fhandler_base::fstat (buf); + buf->st_mode &= ~_IFMT & NO_W; + int file_type = exists (); + switch (file_type) + { + case virt_none: + set_errno (ENOENT); + return -1; + case virt_directory: + case virt_rootdir: + buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + buf->st_nlink = 2; + return 0; + case virt_file: + default: + buf->st_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + return 0; + } +} + +int +fhandler_procsysvipc::readdir (DIR *dir, dirent *de) +{ + int res = ENMFILE; + if (dir->__d_position >= PROCSYSVIPC_LINK_COUNT) + goto out; + { + cygserver_init(); + if (cygserver_running != CYGSERVER_OK) + goto out; + } + strcpy (de->d_name, procsysvipc_tab[dir->__d_position++].name); + dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot; + res = 0; +out: + syscall_printf ("%d = readdir (%p, %p) (%s)", res, dir, de, de->d_name); + return res; +} + +int +fhandler_procsysvipc::open (int flags, mode_t mode) +{ + int res = fhandler_virtual::open (flags, mode); + if (!res) + goto out; + + nohandle (true); + + const char *path; + path = get_name () + proc_len + 1; + pid = atoi (path); + while (*path != 0 && !isdirsep (*path)) + path++; + + if (*path == 0) + { + if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno (EEXIST); + res = 0; + goto out; + } + else if (flags & O_WRONLY) + { + set_errno (EISDIR); + res = 0; + goto out; + } + else + { + flags |= O_DIROPEN; + goto success; + } + } + + virt_tab_t *entry; + entry = virt_tab_search (path + 1, true, procsysvipc_tab, PROCSYSVIPC_LINK_COUNT); + if (!entry) + { + set_errno ((flags & O_CREAT) ? EROFS : ENOENT); + res = 0; + goto out; + } + if (flags & O_WRONLY) + { + set_errno (EROFS); + res = 0; + goto out; + } + + fileid = entry - procsysvipc_tab; + if (!fill_filebuf ()) + { + res = 0; + goto out; + } + + if (flags & O_APPEND) + position = filesize; + else + position = 0; + +success: + res = 1; + set_flags ((flags & ~O_TEXT) | O_BINARY); + set_open_status (); +out: + syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + return res; +} + +bool +fhandler_procsysvipc::fill_filebuf () +{ + if (procsysvipc_tab[fileid].format_func) + { + filesize = procsysvipc_tab[fileid].format_func (NULL, filebuf); + return true; + } + return false; +} + +static _off64_t +format_procsysvipc_msg (void *, char *&destbuf) +{ + tmp_pathbuf tp; + char *buf = tp.c_get (); + char *bufptr = buf; + struct msginfo msginfo; + struct msqid_ds *xmsqids; + size_t xmsqids_len; + + msgctl (0, IPC_INFO, (struct msqid_ds *) &msginfo); + xmsqids_len = sizeof (struct msqid_ds) * msginfo.msgmni; + xmsqids = (struct msqid_ds *) malloc (xmsqids_len); + msgctl (msginfo.msgmni, IPC_INFO, (struct msqid_ds *) xmsqids); + + bufptr += __small_sprintf (bufptr, + " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n"); + + for (int i = 0; i < msginfo.msgmni; i++) { + if (xmsqids[i].msg_qbytes != 0) { + bufptr += sprintf (bufptr, + "%10llu %10u %5o %11lu %10lu %5d %5d %5lu %5lu %5lu %5lu %10ld %10ld %10ld\n", + xmsqids[i].msg_perm.key, + IXSEQ_TO_IPCID(i, xmsqids[i].msg_perm), + xmsqids[i].msg_perm.mode, + xmsqids[i].msg_cbytes, + xmsqids[i].msg_qnum, + xmsqids[i].msg_lspid, + xmsqids[i].msg_lrpid, + xmsqids[i].msg_perm.uid, + xmsqids[i].msg_perm.gid, + xmsqids[i].msg_perm.cuid, + xmsqids[i].msg_perm.cgid, + xmsqids[i].msg_stime, + xmsqids[i].msg_rtime, + xmsqids[i].msg_ctime); + } + } + + destbuf = (char *) crealloc_abort (destbuf, bufptr - buf); + memcpy (destbuf, buf, bufptr - buf); + return bufptr - buf; +} + +static _off64_t +format_procsysvipc_sem (void *, char *&destbuf) +{ + tmp_pathbuf tp; + char *buf = tp.c_get (); + char *bufptr = buf; + union semun semun; + struct seminfo seminfo; + struct semid_ds *xsemids; + size_t xsemids_len; + + semun.buf = (struct semid_ds *) &seminfo; + semctl (0, 0, IPC_INFO, semun); + xsemids_len = sizeof (struct semid_ds) * seminfo.semmni; + xsemids = (struct semid_ds *) malloc (xsemids_len); + semun.buf = xsemids; + semctl (seminfo.semmni, 0, IPC_INFO, semun); + + bufptr += __small_sprintf (bufptr, + " key semid perms nsems uid gid cuid cgid otime ctime\n"); + for (int i = 0; i < seminfo.semmni; i++) { + if ((xsemids[i].sem_perm.mode & SEM_ALLOC) != 0) { + bufptr += sprintf (bufptr, + "%10llu %10u %5o %10d %5lu %5lu %5lu %5lu %10ld %10ld\n", + xsemids[i].sem_perm.key, + IXSEQ_TO_IPCID(i, xsemids[i].sem_perm), + xsemids[i].sem_perm.mode, + xsemids[i].sem_nsems, + xsemids[i].sem_perm.uid, + xsemids[i].sem_perm.gid, + xsemids[i].sem_perm.cuid, + xsemids[i].sem_perm.cgid, + xsemids[i].sem_otime, + xsemids[i].sem_ctime); + } + } + + destbuf = (char *) crealloc_abort (destbuf, bufptr - buf); + memcpy (destbuf, buf, bufptr - buf); + return bufptr - buf; +} + +static _off64_t +format_procsysvipc_shm (void *, char *&destbuf) +{ + tmp_pathbuf tp; + char *buf = tp.c_get (); + char *bufptr = buf; + struct shminfo shminfo; + struct shmid_ds *xshmids; + size_t xshmids_len; + + shmctl (0, IPC_INFO, (struct shmid_ds *) &shminfo); + xshmids_len = sizeof (struct shmid_ds) * shminfo.shmmni; + xshmids = (struct shmid_ds *) malloc (xshmids_len); + shmctl (shminfo.shmmni, IPC_INFO, (struct shmid_ds *) xshmids); + + bufptr += __small_sprintf (bufptr, + " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n"); + for (int i = 0; i < shminfo.shmmni; i++) { + if (xshmids[i].shm_perm.mode & 0x0800) { + bufptr += sprintf (bufptr, + "%10llu %10u %5o %10u %5d %5d %6u %5lu %5lu %5lu %5lu %10ld %10ld %10ld\n", + xshmids[i].shm_perm.key, + IXSEQ_TO_IPCID(i, xshmids[i].shm_perm), + xshmids[i].shm_perm.mode, + xshmids[i].shm_segsz, + xshmids[i].shm_cpid, + xshmids[i].shm_lpid, + xshmids[i].shm_nattch, + xshmids[i].shm_perm.uid, + xshmids[i].shm_perm.gid, + xshmids[i].shm_perm.cuid, + xshmids[i].shm_perm.cgid, + xshmids[i].shm_atime, + xshmids[i].shm_dtime, + xshmids[i].shm_ctime); + } + } + + destbuf = (char *) crealloc_abort (destbuf, bufptr - buf); + memcpy (destbuf, buf, bufptr - buf); + return bufptr - buf; +} diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 1b3807809..038325272 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -19,7 +19,7 @@ details. */ #define isproc_dev(devn) \ (devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS || \ - devn == FH_PROCNET || devn == FH_PROCSYS) + devn == FH_PROCNET || devn == FH_PROCSYS || devn == FH_PROCSYSVIPC) #define isprocsys_dev(devn) (devn == FH_PROCSYS)