bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: System V Shared Memory


From: Jon Arney
Subject: Re: System V Shared Memory
Date: Sat, 23 Mar 2002 16:10:12 -0700

Marcus, Roland,

> Neal did something on this before.

Here's what I've done.  I started with Neal's code and for the most part
the ipcs and ipcrm utilities did not need any changes.  I took the
shmat/shmget/shmctl routines and re-worked them, replacing the need for
a new translator with existing __file and __io calls.  For the most
part,
everything seems to be supported now with the following exceptions:

* PID's in the shmctl(fd, SHM_STAT, &buf) call are not reliable since
they
  are set using the '_file_chflags' RPC which may not be supported on
  all translators.

* Creator uid uses the '_file_chauthor' RPC which may not be supported
on
  all translators.

* The 'nattach' number is not supported because this information is not
  generally available.  If we decide to support this information, I
could
  envision a generic (but optional) '__file_users()' RPC which would
  return the number of users currently using the file (or port).  I
  think this might be useful for things besides shared memory anyway.

>From Roland:
> I am strongly in favor of an approach where using any vanilla filesystem
> directory for /var/run/sysvshm works in a pinch (and maybe loses on some
> obscure point of shm behavior).  

I think the above deficiencies fit the bill of Roland's description.
i.e. new methods would make the system more standards compliant but
are not required for basic operation.

Some of the information is "overloaded" in the '__io_stat' structure.
For example, the 'st_mtime' corresponds to the detach time and
the 'st_atime' corresponds to the attach time.  This seems to be
a pretty good plan except that it is possible for a third party to
come along and corrupt those nodes.  I don't think this is a big
problem because if you go playing around with the shared memory nodes,
you deserve what you get, and file permissions should take care of most
of these problems for you.

Bugs in 'tmpfs' are not relevant because this code does not require any
particular translator to do it's job.  (In fact, a similar
implementation
might even make sense in 'glibc/generic' in addition to
'glibc/sysdeps/mach/hurd').

At any rate, I offer a 'glibc' patch and a 'hurd' patch to support SYSV
shared memory.

The patch includes 'hurd/hurd/paths.h' which defines _HURD_SYSVIPC_SHM
"/tmp"
and Neal's pretty much original 'ipcs' and 'ipcrm' utilities under
'hurd/utils/...'

In 'glibc' the code amounts to shmget.c, shmat.c shmdt.c and shmctl.c
which
implement the required functionality in terms of mmap, __file* and
__io*.

I settled on the mapping shared memory ID = file inode as obtained from
stat.

As far as testing goes, I ran Neal's tests as well as a few others I
cooked up.  I also managed to run the Gimp and created an image or few
to convince myself that it was really working properly and cleaning
up the nodes on exit, etc.

Roland McGrath wrote:
> 
> Neal did something on this before.  Look through the bug-hurd and
> hurd-devel archives for "System V Shared Memory" (or just google for that
> plus hurd).  I think the conclusion of that was he had a proposal that used
> existing filesystem calls to implement almost everything.  I don't recall
> the details at the moment, but digging them up and reviving the discussion
> would be a good thing.  I don't think there is very much work involved in
> making it all work.

-- 
------------------------------------------------------------------------
Jonathan S. Arney
Software Engineer
jarney1@cox.net
------------------------------------------------------------------------
diff --exclude=*~ -Ncr glibc-2.2.5/sysdeps/mach/hurd.new/shmat.c 
glibc-2.2.5/sysdeps/mach/hurd/shmat.c
*** glibc-2.2.5/sysdeps/mach/hurd.new/shmat.c   Thu Jan  1 00:00:00 1970
--- glibc-2.2.5/sysdeps/mach/hurd/shmat.c       Sat Mar 23 15:01:22 2002
***************
*** 0 ****
--- 1,89 ----
+ /* Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+ 
+    The GNU C Library 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
+    Lesser General Public License for more details.
+ 
+    You should have received a copy of the GNU Lesser General Public
+    License along with the GNU C Library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+ 
+ #include <sys/mman.h>
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ #include <sys/time.h>
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <hurd.h>
+ #include "list.h"
+ #include "sysvipc-shared.h"
+ 
+ __ptr_t __shmat ( int shmid, const __ptr_t shmaddr, int shmflg )
+ {
+   sysvipc_shm_t *shm;
+   __ptr_t addr;
+   struct stat statbuf;
+   struct timeval the_times[2];
+   error_t err;
+ 
+   __sysvipc_init();
+ 
+   shm = __sysvipc_lookup_id(shmid);
+   if (!shm) {
+     return (__ptr_t)__hurd_fail(EINVAL);
+   }
+ 
+   /*
+    * If we've already attached, use that instead.
+    */
+   if (shm->fd != -1) {
+     return (__ptr_t)shm->addr;
+   }
+ 
+   shm->fd = open(shm->pathname, shmflg & SHM_RDONLY ? O_RDONLY : O_RDWR);
+   if (shm->fd == -1) {
+     return (__ptr_t)__hurd_fail(EINVAL);
+   }
+ 
+   err = stat(shm->pathname, &statbuf);
+   if (err) {
+     return (__ptr_t)__hurd_fail(errno);
+   }
+ 
+  /*XXX We're overloading these fields*/
+   gettimeofday(&the_times[0], NULL);
+ 
+   the_times[1].tv_sec = statbuf.st_mtime;
+   the_times[1].tv_usec = statbuf.st_mtime_usec;
+   err = utimes(shm->pathname, &the_times[0]);
+   if (err == -1) {
+     close(shm->fd);
+     return (__ptr_t)__hurd_fail(errno);
+   }
+ 
+   addr = mmap(shmaddr, shm->length,
+             PROT_READ | ((shmflg & SHM_RDONLY) ? 0 : PROT_WRITE),
+             MAP_SHARED,
+             shm->fd, 0);
+   if (addr == (__ptr_t)-1) {
+     close(shm->fd);
+     return (__ptr_t)(unsigned int)__hurd_fail(errno);
+   }
+   shm->addr = addr;
+ 
+   return addr;
+ }
+ 
+ weak_alias(__shmat, shmat)
+ 
diff --exclude=*~ -Ncr glibc-2.2.5/sysdeps/mach/hurd.new/shmctl.c 
glibc-2.2.5/sysdeps/mach/hurd/shmctl.c
*** glibc-2.2.5/sysdeps/mach/hurd.new/shmctl.c  Thu Jan  1 00:00:00 1970
--- glibc-2.2.5/sysdeps/mach/hurd/shmctl.c      Sat Mar 23 15:01:30 2002
***************
*** 0 ****
--- 1,139 ----
+ /* Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+ 
+    The GNU C Library 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
+    Lesser General Public License for more details.
+ 
+    You should have received a copy of the GNU Lesser General Public
+    License along with the GNU C Library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+ 
+ #define _GNU_SOURCE
+ #include <hurd.h>
+ #include <unistd.h>
+ #include <hurd.h>
+ #include <sys/mman.h>
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ #include <sys/stat.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include "list.h"
+ #include "sysvipc-shared.h"
+ 
+ int __shmctl(int shmid, int cmd, struct shmid_ds *buf)
+ {
+   error_t err = 0;
+   sysvipc_shm_t *shm;
+   struct stat statbuf;
+   file_t file;
+ 
+   __sysvipc_init();
+ 
+   shm = __sysvipc_lookup_id(shmid);
+   if (!shm) {
+     return __hurd_fail(EINVAL);
+   }
+ 
+   switch (cmd) {
+   case IPC_STAT:
+     file = __file_name_lookup(shm->pathname, O_RDWR, 0666);
+     if (file == MACH_PORT_NULL) {
+       return __hurd_fail(EINVAL); /* is this correct? or perhaps ENOENT?*/
+     }
+ 
+     err = __io_stat(file, &statbuf);
+     __mach_port_deallocate(__mach_task_self(), file);
+     if (err) {
+       return __hurd_fail(err);
+     }
+ 
+     /* shmid_ds contains: */
+     /* Map file stats into shm stats */
+     buf->shm_perm.__key = shm->key;
+     buf->shm_perm.uid = statbuf.st_uid;
+     buf->shm_perm.gid = statbuf.st_gid;
+     buf->shm_perm.cuid = statbuf.st_author;
+ /* Does this really make sense? */
+     buf->shm_perm.cgid = statbuf.st_gid;
+ 
+     buf->shm_perm.mode = statbuf.st_mode;
+     buf->shm_perm.__seq = statbuf.st_ino;
+     buf->shm_segsz = statbuf.st_size;
+ 
+ /* Hijack access time */
+     buf->shm_atime = statbuf.st_atime;
+ 
+ /* Hijack modification time */
+     buf->shm_dtime = statbuf.st_mtime;
+ 
+     buf->shm_ctime = statbuf.st_ctime;
+ 
+ /* Hijack low 16 bits of flags */
+     buf->shm_cpid = statbuf.st_flags & 0xffff;
+ 
+ /* Hijack high 16 bits of flags */
+     buf->shm_lpid = statbuf.st_flags >> 16 & 0xffff;
+ 
+     buf->shm_nattch = 0; /* XXX Don't have this info! */
+     break;
+   case IPC_SET:
+     file = __file_name_lookup(shm->pathname, O_RDWR, 0666);
+     if (file == MACH_PORT_NULL) {
+       return __hurd_fail(EINVAL);
+     }
+ 
+     err = __file_chown (file, buf->shm_perm.uid, buf->shm_perm.gid);
+     if (err) {
+       __mach_port_deallocate(mach_task_self(), file);
+       return __hurd_fail(err);
+     }
+     
+     err = __file_chmod (file, buf->shm_perm.mode);
+     if (err) {
+       __mach_port_deallocate(mach_task_self(), file);
+       return __hurd_fail(err);
+     }
+ 
+     err = __file_chauthor(file, buf->shm_perm.cuid);
+ #ifdef CARE_ABOUT_SYSVIPC_ACCOUNTING
+     if (err) { __mach_port_deallocate(mach_task_self(), file);
+        return __hurd_fail(err);
+     }
+ #endif
+ 
+     err = __file_chflags(file, getpid());
+     __mach_port_deallocate(mach_task_self(), file);
+ #ifdef CARE_ABOUT_SYSVIPC_ACCOUNTING
+     if (err) {
+       return __hurd_fail(err);
+     }
+ #endif
+     break;
+   case IPC_RMID:
+     /*
+      * This removes the node.  All users can still
+      * use it if the FD is still open.
+      */
+     err = __unlink(shm->pathname);
+     if (err == -1) {
+       return __hurd_fail(errno);
+     }
+     break;
+   default:
+     __hurd_fail(EINVAL);
+   }
+ 
+   return 0;
+ }
+ 
+ weak_alias(__shmctl, shmctl)
diff --exclude=*~ -Ncr glibc-2.2.5/sysdeps/mach/hurd.new/shmdt.c 
glibc-2.2.5/sysdeps/mach/hurd/shmdt.c
*** glibc-2.2.5/sysdeps/mach/hurd.new/shmdt.c   Thu Jan  1 00:00:00 1970
--- glibc-2.2.5/sysdeps/mach/hurd/shmdt.c       Sat Mar 23 15:01:26 2002
***************
*** 0 ****
--- 1,94 ----
+ /* Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+ 
+    The GNU C Library 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
+    Lesser General Public License for more details.
+ 
+    You should have received a copy of the GNU Lesser General Public
+    License along with the GNU C Library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+ 
+ #include <sys/mman.h>
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ #include <sys/time.h>
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <hurd.h>
+ #include "list.h"
+ #include "sysvipc-shared.h"
+ 
+ int __shmdt(const __ptr_t shmaddr)
+ {
+   sysvipc_shm_t *shm;
+   error_t err;
+   struct stat statbuf;
+   struct timeval the_times[2];
+ 
+   __sysvipc_init();
+ 
+   shm = __sysvipc_lookup_addr(shmaddr);
+   if (!shm) {
+     return __hurd_fail(EINVAL);
+   }
+ 
+   if (shm->fd == -1) {
+     return __hurd_fail(EINVAL);
+   }
+ 
+   err = munmap(shm->addr, shm->length);
+   if (err == -1) {
+     return __hurd_fail(errno);
+   }
+   err = close(shm->fd);
+   if (err == -1) {
+     return __hurd_fail(errno);
+   }
+ 
+   err = stat(shm->pathname, &statbuf);
+   if (err == -1) {
+     /*
+      * It's ok if we've deleted it already,
+      * there's nothing left to update the
+      * detach time.  This is "normal".
+      */
+     if (errno == ENOENT) return 0;
+     return __hurd_fail(errno);
+   }
+ 
+  /*XXX We're overloading these fields SHM.*/
+   gettimeofday(&the_times[1], NULL);
+ 
+   the_times[0].tv_sec = statbuf.st_atime;
+   the_times[0].tv_usec = statbuf.st_atime_usec;
+ 
+   err = utimes(shm->pathname, &the_times[0]);
+   if (err == -1) {
+     /*
+      * It's ok if we've deleted it already,
+      * there's nothing left to update the
+      * detach time.  This is "normal".
+      */
+     return __hurd_fail(errno);
+   }
+ 
+   __sysvipc_delete(shm);
+ 
+   return err;
+ }
+ 
+ weak_alias(__shmdt, shmdt)
+ 
+ 
+ 
diff --exclude=*~ -Ncr glibc-2.2.5/sysdeps/mach/hurd.new/shmget.c 
glibc-2.2.5/sysdeps/mach/hurd/shmget.c
*** glibc-2.2.5/sysdeps/mach/hurd.new/shmget.c  Thu Jan  1 00:00:00 1970
--- glibc-2.2.5/sysdeps/mach/hurd/shmget.c      Sat Mar 23 15:01:17 2002
***************
*** 0 ****
--- 1,237 ----
+ /* Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+ 
+    The GNU C Library 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
+    Lesser General Public License for more details.
+ 
+    You should have received a copy of the GNU Lesser General Public
+    License along with the GNU C Library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+ 
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #include <sys/ipc.h>
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <dirent.h>
+ #include <hurd.h>
+ #include <hurd/paths.h>
+ #include <hurd/fd.h>
+ #include "list.h"
+ #include "sysvipc-shared.h"
+ 
+ /*
+  * Each process does some accounting
+  * on the shm segments so that it
+  * can manage them.
+  */
+ static struct list_head head;
+ static int initialized;
+ 
+ void __sysvipc_init(void)
+ {
+   if (!initialized++) {
+     INIT_LIST_HEAD(&head);
+   }
+ }
+ 
+ static void __sysvipc_shm_add(sysvipc_shm_t *shm)
+ {
+   list_add_tail(&shm->list, &head);
+ }
+ 
+ sysvipc_shm_t *__sysvipc_lookup_id(int id)
+ {
+   struct list_head *tmp;
+   sysvipc_shm_t *shm = NULL;
+   DIR *d;
+   struct dirent *de;
+   key_t key;
+   struct stat statbuf;
+   int err;
+ 
+ /*
+  * Look in our cache first.
+  */
+   list_for_each(tmp, &head) {
+     shm = list_entry(tmp, sysvipc_shm_t, list);
+     if (!shm) break;
+     if (shm->id == id) return shm;
+   }
+ /*
+  * If we don't have it, create a handle for it
+  * by looking for it in the directory listing.
+  *
+  * What is below works, but "should"? be written
+  * with Hurdish functions instead of libc functions.
+  * I guess.
+  */
+   d = opendir(_HURD_SYSVIPC_SHM);
+   if (!d) {
+     return NULL;
+   }
+   while (de = readdir(d)) {
+     if (!strstr(de->d_name, "shm-")) continue;
+     shm = (sysvipc_shm_t *)malloc(sizeof(sysvipc_shm_t));
+     if (!shm) {
+       errno = ENOMEM;
+       closedir(d);
+       return NULL;
+     }
+     sscanf(de->d_name, "shm-%lx", &key);
+     __sysvipc_shmpath(shm->pathname, key);
+     err = stat(shm->pathname, &statbuf);
+     if (err) {
+       free(shm);
+       return NULL;
+     }
+ 
+     if (statbuf.st_ino == id) { 
+       shm->key = key;
+       shm->id = id;
+       shm->fd = -1; /* Not until we open it */
+       shm->length = statbuf.st_size;
+       __sysvipc_shm_add(shm);
+       break;
+     }
+     free(shm);
+   }
+   closedir(d);
+   return shm;
+ }
+ 
+ sysvipc_shm_t *__sysvipc_lookup_addr(const void *addr)
+ {
+   struct list_head *tmp;
+   sysvipc_shm_t *shm;
+ 
+   list_for_each(tmp, &head) {
+     shm = list_entry(tmp, sysvipc_shm_t, list);
+     if (!shm) return NULL;
+     if (shm->addr == addr) return shm;
+   }
+   return NULL;
+ }
+ 
+ /* XXX HACK!!! */
+ void __sysvipc_shmpath(char *pathname, key_t key)
+ {
+   sprintf(pathname, _HURD_SYSVIPC_SHM "shm-%lx", key);
+ }
+ 
+ void __sysvipc_delete(sysvipc_shm_t *shm)
+ {
+   /* Unlink ourselves from list and free */
+   list_del(&shm->list);
+   free(shm);
+ }
+ 
+ int __shmget(key_t key, int size, int shmflag)
+ {
+   char data = 0;
+   int nbytes;
+   off_t offset;
+   file_t fd;
+   error_t err;
+   sysvipc_shm_t *shm;
+   struct stat statbuf;
+ 
+   __sysvipc_init();
+ 
+   shm = (sysvipc_shm_t *)malloc(sizeof (sysvipc_shm_t));
+   if (!shm) {
+     return __hurd_fail(ENOMEM);
+   }
+ 
+   __sysvipc_shmpath(shm->pathname, key);
+   fd = __file_name_lookup(shm->pathname, 
+           O_RDWR | 
+           ((shmflag & IPC_CREAT) ? O_CREAT : 0) | 
+           ((shmflag & IPC_EXCL) ? O_EXCL : 0),
+           (shmflag & 0777));
+   if (fd == MACH_PORT_NULL) {
+     free(shm);
+     return __hurd_fail(ENOENT);
+   }
+ 
+   /*
+    * If we're creating the file, zero fill it for
+    * the specified length.
+    */
+   if (shmflag & IPC_CREAT) {
+     if (err = __io_seek (fd, size-1, SEEK_SET, &offset)) {
+       mach_port_deallocate(mach_task_self(), fd);
+       unlink(shm->pathname);
+       free(shm);
+       return __hurd_fail (err);
+     }
+     
+     if (err = __io_write (fd, &data, 1, size-1, &nbytes)) {
+       mach_port_deallocate(mach_task_self(), fd);
+       unlink(shm->pathname);
+       free(shm);
+       return __hurd_fail (err);
+     }
+   /* If either of these fail, it's not a big deal
+    * since they only exist to provide additional
+    * information through 'shmctl(id, SHM_STAT,...)'
+    * Thus either of these failing is NOT a reason
+    * to abort our operations.  We simply lose a little
+    * bit of accounting if the underlying translator
+    * for this node doesn't understand us.
+    */  
+     err = __file_chauthor (fd, getuid());
+ #ifdef CARE_ABOUT_SYSVIPC_ACCOUNTING
+     if (err) {
+       mach_port_deallocate(mach_task_self(), fd);
+       unlink(shm->pathname);
+       free(shm);
+       return __hurd_fail (err);
+     }
+     else err = 0;
+ #endif
+ 
+     err = __file_chflags (fd, getpid());
+ #ifdef CARE_ABOUT_SYSVIPC_ACCOUNTING
+     if (err) {
+       mach_port_deallocate(mach_task_self(), fd);
+       unlink(shm->pathname);
+       free(shm);
+       return __hurd_fail (err);
+     }
+     else err = 0;
+ #endif
+   }
+ 
+   if (err = __io_stat (fd, &statbuf)) {
+     mach_port_deallocate(mach_task_self(), fd);
+     unlink(shm->pathname);
+     free(shm);
+     return __hurd_fail(err);
+   }
+ 
+   mach_port_deallocate(mach_task_self(), fd);
+ 
+   shm->key = key;
+   shm->id = statbuf.st_ino;
+   shm->fd = -1; /* Not until we open it */
+   shm->length = size;
+   __sysvipc_shm_add(shm);
+ 
+   return shm->id;
+ }
+ 
+ weak_alias(__shmget, shmget)
diff --exclude=*~ -Ncr glibc-2.2.5/sysdeps/mach/hurd.new/sysvipc-shared.h 
glibc-2.2.5/sysdeps/mach/hurd/sysvipc-shared.h
*** glibc-2.2.5/sysdeps/mach/hurd.new/sysvipc-shared.h  Thu Jan  1 00:00:00 1970
--- glibc-2.2.5/sysdeps/mach/hurd/sysvipc-shared.h      Sat Mar 23 15:01:40 2002
***************
*** 0 ****
--- 1,35 ----
+ /* Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+ 
+    The GNU C Library 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
+    Lesser General Public License for more details.
+ 
+    You should have received a copy of the GNU Lesser General Public
+    License along with the GNU C Library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+ 
+ typedef struct sysvipc_shm_st sysvipc_shm_t;
+ 
+ struct sysvipc_shm_st {
+   int id;
+   key_t key;
+   int fd; /* FD to our instance */
+   size_t length;
+   __ptr_t *addr;
+   struct list_head list;
+   char pathname[32]; /* Name of the descriptor */
+ };
+ 
+ void __sysvipc_init(void);
+ sysvipc_shm_t *__sysvipc_lookup_id(int id);
+ sysvipc_shm_t *__sysvipc_lookup_addr(const void *addr);
+ int __sysvipc_key_to_id(key_t key);
+ void __sysvipc_delete(sysvipc_shm_t *shm);
diff --exclude=*~ -Ncr glibc-2.2.5/sysdeps/mach/hurd.new/list.h 
glibc-2.2.5/sysdeps/mach/hurd/list.h
*** glibc-2.2.5/sysdeps/mach/hurd.new/list.h    Thu Jan  1 00:00:00 1970
--- glibc-2.2.5/sysdeps/mach/hurd/list.h        Sat Mar 23 14:51:44 2002
***************
*** 0 ****
--- 1,151 ----
+ #ifndef _LINUX_LIST_H
+ #define _LINUX_LIST_H
+ 
+ /*
+  * Simple doubly linked list implementation.
+  *
+  * Some of the internal functions ("__xxx") are useful when
+  * manipulating whole lists rather than single entries, as
+  * sometimes we already know the next/prev entries and we can
+  * generate better code by using them directly rather than
+  * using the generic single-entry routines.
+  */
+ 
+ struct list_head {
+       struct list_head *next, *prev;
+ };
+ 
+ #define LIST_HEAD_INIT(name) { &(name), &(name) }
+ 
+ #define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+ 
+ #define INIT_LIST_HEAD(ptr) do { \
+       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+ } while (0)
+ 
+ /*
+  * Insert a new entry between two known consecutive entries. 
+  *
+  * This is only for internal list manipulation where we know
+  * the prev/next entries already!
+  */
+ static __inline__ void __list_add(struct list_head * new,
+       struct list_head * prev,
+       struct list_head * next)
+ {
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+ }
+ 
+ /**
+  * list_add - add a new entry
+  * @new: new entry to be added
+  * @head: list head to add it after
+  *
+  * Insert a new entry after the specified head.
+  * This is good for implementing stacks.
+  */
+ static __inline__ void list_add(struct list_head *new, struct list_head *head)
+ {
+       __list_add(new, head, head->next);
+ }
+ 
+ /**
+  * list_add_tail - add a new entry
+  * @new: new entry to be added
+  * @head: list head to add it before
+  *
+  * Insert a new entry before the specified head.
+  * This is useful for implementing queues.
+  */
+ static __inline__ void list_add_tail(struct list_head *new, struct list_head 
*head)
+ {
+       __list_add(new, head->prev, head);
+ }
+ 
+ /*
+  * Delete a list entry by making the prev/next entries
+  * point to each other.
+  *
+  * This is only for internal list manipulation where we know
+  * the prev/next entries already!
+  */
+ static __inline__ void __list_del(struct list_head * prev,
+                                 struct list_head * next)
+ {
+       next->prev = prev;
+       prev->next = next;
+ }
+ 
+ /**
+  * list_del - deletes entry from list.
+  * @entry: the element to delete from the list.
+  * Note: list_empty on entry does not return true after this, the entry is in 
an undefined state.
+  */
+ static __inline__ void list_del(struct list_head *entry)
+ {
+       __list_del(entry->prev, entry->next);
+       entry->prev = entry->next = entry;
+ }
+ 
+ /**
+  * list_del_init - deletes entry from list and reinitialize it.
+  * @entry: the element to delete from the list.
+  */
+ static __inline__ void list_del_init(struct list_head *entry)
+ {
+       __list_del(entry->prev, entry->next);
+       INIT_LIST_HEAD(entry); 
+ }
+ 
+ /**
+  * list_empty - tests whether a list is empty
+  * @head: the list to test.
+  */
+ static __inline__ int list_empty(struct list_head *head)
+ {
+       return head->next == head;
+ }
+ 
+ /**
+  * list_splice - join two lists
+  * @list: the new list to add.
+  * @head: the place to add it in the first list.
+  */
+ static __inline__ void list_splice(struct list_head *list, struct list_head 
*head)
+ {
+       struct list_head *first = list->next;
+ 
+       if (first != list) {
+               struct list_head *last = list->prev;
+               struct list_head *at = head->next;
+ 
+               first->prev = head;
+               head->next = first;
+ 
+               last->next = at;
+               at->prev = last;
+       }
+ }
+ 
+ /**
+  * list_entry - get the struct for this entry
+  * @ptr:      the &struct list_head pointer.
+  * @type:     the type of the struct this is embedded in.
+  * @member:   the name of the list_struct within the struct.
+  */
+ #define list_entry(ptr, type, member) \
+       ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+ 
+ /**
+  * list_for_each      -       iterate over a list
+  * @pos:      the &struct list_head to use as a loop counter.
+  * @head:     the head for your list.
+  */
+ #define list_for_each(pos, head) \
+       for (pos = (head)->next; pos != (head); pos = pos->next)
+ 
+ #endif
diff --exclude=CVS -Ncr hurd/utils.orig/Makefile hurd/utils/Makefile
*** hurd/utils.orig/Makefile    Fri Mar  1 04:14:13 2002
--- hurd/utils/Makefile Sat Mar 23 14:55:41 2002
***************
*** 21,34 ****
  targets = shd ps settrans showtrans syncfs fsysopts \
        storeinfo login w uptime ids loginpr sush vmstat portinfo \
        devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \
!       storeread ping msgport rpctrace mount gcore
  special-targets = loginpr sush uptime
  SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \
        fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \
        uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \
        parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \
        unsu.c ftpcp.c ftpdir.c storeread.c storecat.c ping.c msgport.c \
!       rpctrace.c mount.c gcore.c
  LCLHDRS = psout.h parse.h pids.h frobauth.h
  
  OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
--- 21,34 ----
  targets = shd ps settrans showtrans syncfs fsysopts \
        storeinfo login w uptime ids loginpr sush vmstat portinfo \
        devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \
!       storeread ping msgport rpctrace mount gcore ipcs ipcrm
  special-targets = loginpr sush uptime
  SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \
        fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \
        uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \
        parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \
        unsu.c ftpcp.c ftpdir.c storeread.c storecat.c ping.c msgport.c \
!       rpctrace.c mount.c gcore.c ipcs.c ipcrm.c
  LCLHDRS = psout.h parse.h pids.h frobauth.h
  
  OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
diff --exclude=CVS -Ncr hurd/utils.orig/ipcrm.c hurd/utils/ipcrm.c
*** hurd/utils.orig/ipcrm.c     Thu Jan  1 00:00:00 1970
--- hurd/utils/ipcrm.c  Sat Mar 23 14:55:17 2002
***************
*** 0 ****
--- 1,133 ----
+ /* SUSv2 compliant ipcs
+    Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+    Written by Neal H Walfield <<A 
HREF="mailto:neal@cs.uml.edu";>neal@cs.uml.edu</A>>
+ 
+    This file is part of the GNU Hurd.
+ 
+    The GNU Hurd 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, or (at your option)
+    any later version.
+ 
+    The GNU Hurd 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 the GNU Hurd; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ 
+ #include <argp.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <errno.h>
+ #include <error.h>
+ #include <sys/shm.h>
+ 
+ static const struct argp_option options[] = {
+   {"msgid", 'q', "MSGID", 0,
+    "Remove the messages queue named by the given id"},
+   {"msgkey",'Q', "MSGKEY", 0,
+    "Remove the messages queue named by the given key"},
+   {"shmid", 'm', "SHMID", 0,
+    "Remove the shared memory object named by the given id"},
+   {"shmkey",'M', "SHMKEY", 0,
+    "Remove the shared memory object named by the given key"},
+   {"semid", 's', "SEMID", 0,
+    "Remove the semaphores named by the given id"},
+   {"semkey",'S', "SEMKEY", 0,
+    "Remove the semaphores named by the given key"},
+   {0}
+ };
+ 
+ static const char *args_doc = "";
+ static const char *doc = "Remove a System V IPC object.\
+ \vMultiple objects may be specified.";
+ 
+ int
+ main (int argc, char *argv[])
+ {
+   error_t rt = 0;
+   int warn_sem = 0;
+   int warn_msg = 0;
+ 
+   error_t
+     parse_opt (int key, char *arg, struct argp_state *state)
+       {
+         int iskey = 0;  /* 0 = ID; 1 = KEY  */
+ 
+         switch (key)
+         {
+         case ARGP_KEY_ARG:
+           argp_usage (state);
+ 
+         case 'Q':
+         case 'q':
+           if (! warn_msg)
+             {
+               warn_msg = 1;
+               printf ("Message queues not yet implemented.\n");
+             }
+           break;
+ 
+         case 'S':
+         case 's':
+           if (! warn_sem)
+             {
+               warn_sem = 1;
+               printf ("Semaphores not yet implemented.\n");
+             }
+           break;
+ 
+         case 'M':
+           iskey = 1;
+         case 'm':
+           {
+             error_t err;
+             int id;
+             char *end;
+ 
+             id = strtol (arg, &end, 0);
+             if (! end || *end != '\0')
+               {
+                 printf ("Invalid identifier: `%s'.\n", arg);
+                 if (! rt)
+                   rt = 2;
+                 break;
+               }
+ 
+             if (iskey)
+               {
+                 id = shmget (id, 0, 0);
+                 if (id == -1)
+                   {
+                     error (0, errno, "shmget");
+                     rt = 1;
+                     break;
+                   }
+               }
+ 
+               err = shmctl (id, IPC_RMID, NULL);
+               if (err == -1)
+                 {
+                   rt = 1;
+                   error (0, errno, "removing %d", id);
+                 }
+ 
+             break;
+           }
+ 
+         default:
+           return ARGP_ERR_UNKNOWN;
+         }
+       return 0;
+       }
+ 
+   const struct argp argp = { options, parse_opt, args_doc, doc };
+   argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
+ 
+   return rt;
+ }
+ 
diff --exclude=CVS -Ncr hurd/utils.orig/ipcs.c hurd/utils/ipcs.c
*** hurd/utils.orig/ipcs.c      Thu Jan  1 00:00:00 1970
--- hurd/utils/ipcs.c   Sat Mar 23 14:57:15 2002
***************
*** 0 ****
--- 1,284 ----
+ /* SUSv2 compliant ipcs
+    Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+    Written by Neal H Walfield neal@cs.uml.edu
+    Tweaked by Jon Arney--slightly different approach to shm calls.
+ 
+    This file is part of the GNU Hurd.
+ 
+    The GNU Hurd 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, or (at your option)
+    any later version.
+ 
+    The GNU Hurd 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 the GNU Hurd; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ #include <argp.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <error.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <time.h>
+ #include <hurd.h>
+ #include <sys/shm.h>
+ #include <dirent.h>
+ #include <hurd/paths.h>
+ 
+ static const struct argp_option options[] = {
+   {"shm",     'm', 0, 0, "Shared memory objects", 0},
+   {"sem",     's', 0, 0, "Semaphores", 0},
+   {"msg",     'q', 0, 0, "Messages queues", 0},
+ 
+   {"all",     'a', 0, 0, "Print all statistics", 1},
+   {"limits",  'b', 0, 0, "Print maximun allowable sizes", 1},
+   {"creator", 'c', 0, 0, "Print creator's user name and group", 1},
+   {"out",     'o', 0, 0, "Print outstanding usage", 1},
+   {"process", 'p', 0, 0, "Print process information", 1},
+   {"time",    't', 0, 0, "Print time information", 1},
+   {0}
+ };
+ 
+ static const char *args_doc = "[ID...]";
+ static const char *doc = "Get System V IPC statistics.";
+ 
+ /* What to print.  */
+ #define B (1 << 0)
+ #define C (1 << 1)
+ #define O (1 << 2)
+ #define P (1 << 3)
+ #define T (1 << 4)
+ #define A (B | C | O | P | T)
+ 
+ void intro (void)
+ {
+   time_t t;
+   extern char *localhost (void);
+   char hostname[64];
+ 
+   strcpy(hostname, "localhost");
+   gethostname(hostname, sizeof(hostname));
+ 
+   t = time (NULL);
+   printf ("IPC status from %s:%s as of %s", hostname, "/tmp",
+         ctime (&t));
+ }
+ 
+ int
+ msg_report (int print)
+ {
+   printf ("Message queues facility not in system.\n");
+   return 1;
+ }
+ 
+ int
+ shm_report (int print)
+ {
+   error_t err;
+   DIR *d;
+   struct dirent *de;
+ 
+   d = opendir("/tmp");
+ 
+   printf ("Shared Memory:\n");
+ 
+   printf ("T ID       KEY          MODE        OWNER    GROUP    ");
+   if (print & C)
+     printf ("CREATOR  CGROUP   ");
+   if (print & O)
+     printf ("NATTCH  ");
+   if (print & B)
+     printf ("SEGSZ    ");
+   if (print & P)
+     printf ("CPID     LPID     ");
+   if (print & T)
+     printf ("ATIME     DTIME");
+   printf ("\n");
+ 
+   while (de = readdir(d)) {
+     struct shmid_ds *ds;
+     struct shmid_ds dsreal;
+ 
+     struct passwd *u;
+     struct group *g;
+     key_t key;
+     int id;
+ 
+     if (!strstr(de->d_name, "shm-")) continue;
+ 
+     sscanf(de->d_name, "shm-%lx", &key);
+ 
+     id = shmget(key, 0, 0);
+     if (id == -1) {
+       fprintf(stderr, "Get -1\n");
+       perror("shmget");
+       continue;
+     }
+     shmctl(id, IPC_STAT, &dsreal);
+     ds = &dsreal;
+ 
+     printf ("m %-9d0x%-11lx--%c%c-%c%c-%c%c- ", id,
+           key,
+           S_IRUSR & ds->shm_perm.mode ? 'r' : '-',
+           S_IWUSR & ds->shm_perm.mode ? 'w' : '-',
+           S_IRGRP & ds->shm_perm.mode ? 'r' : '-',
+           S_IWGRP & ds->shm_perm.mode ? 'w' : '-',
+           S_IROTH & ds->shm_perm.mode ? 'r' : '-',
+           S_IWOTH & ds->shm_perm.mode ? 'w' : '-');
+ 
+       u = getpwuid (ds->shm_perm.uid);
+       if (u)
+       printf ("%-9s", u->pw_name);
+       else
+       printf ("%-9d", ds->shm_perm.uid);
+ 
+       g = getgrgid (ds->shm_perm.gid);
+       if (g)
+       printf ("%-9s", g->gr_name);
+       else
+       printf ("%-9d", ds->shm_perm.gid);
+ 
+       if (print & C)
+       {
+         u = getpwuid (ds->shm_perm.cuid);
+         if (u)
+           printf ("%-9s", u->pw_name);
+         else
+           printf ("%-9d", ds->shm_perm.cuid);
+ 
+         g = getgrgid (ds->shm_perm.cgid);
+         if (g)
+           printf ("%-9s", g->gr_name);
+         else
+           printf ("%-9d", ds->shm_perm.cgid);
+       }
+ 
+       if (print & O)
+       printf ("%-8d", ds->shm_nattch);
+ 
+       if (print & B)
+       printf ("%-8d", ds->shm_segsz);
+ 
+       if (print & P)
+       printf ("%-8d %-8d", ds->shm_cpid, ds->shm_lpid);
+ 
+       if (print & T)
+       {
+         if (ds->shm_atime)
+           {
+             struct tm *tm;
+             char buffer[10];
+             tm = localtime (&ds->shm_atime);
+             strftime (buffer, sizeof (buffer), "%H:%M:%S", tm);
+             printf ("%s ", buffer);
+           }
+         else
+           printf (" no-entry ");
+ 
+         if (ds->shm_dtime)
+           {
+             struct tm *tm;
+             char buffer[10];
+             tm = localtime (&ds->shm_dtime);
+             strftime (buffer, sizeof (buffer), "%H:%M:%S", tm);
+             printf ("%s", buffer);
+           }
+         else
+           printf (" no-entry");
+       }
+ 
+       printf ("\n");
+     }
+ 
+   closedir(d);
+ 
+   return 0;
+ }
+ 
+ int
+ sem_report (int print)
+ {
+   printf ("Semaphore facility not in system.\n");
+   return 1;
+ }
+ 
+ int
+ main (int argc, char *argv[])
+ {
+   int output = 0;  /* What to print: bit wise or of B, C, O, P, T.  */
+ 
+   int do_shm = 1;
+   int do_sem = 1;
+   int do_msg = 1;
+ 
+   int rt = 0;
+ 
+   error_t
+     parse_opt (int key, char *arg, struct argp_state *state)
+       {
+         switch (key)
+         {
+         case 'm':
+           do_shm = 1;
+           do_sem = 0;
+           do_msg = 0;
+           break;
+         case 's':
+           do_shm = 0;
+           do_sem = 1;
+           do_msg = 0;
+           break;
+         case 'q':
+           do_shm = 0;
+           do_sem = 0;
+           do_msg = 1;
+           break;
+ 
+         case 'a':
+           output = A;
+           break;
+         case 'b':
+           output |= B;
+           break;
+         case 'c':
+           output |= C;
+           break;
+         case 'o':
+           output |= O;
+           break;
+         case 'p':
+           output |= P;
+           break;
+         case 't':
+           output |= T;
+           break;
+ 
+         case ARGP_KEY_NO_ARGS:
+           intro ();
+           if (do_msg)
+             rt |= (msg_report (output) & 1) << 0;
+           if (do_shm)
+             rt |= (shm_report (output) & 1) << 1;
+           if (do_sem)
+             rt |= (sem_report (output) & 1) << 2;
+           break;
+ 
+         default:
+           return ARGP_ERR_UNKNOWN;
+         }
+       return 0;
+       }
+ 
+   const struct argp argp = { options, parse_opt, args_doc, doc };
+ 
+   argp_parse (&argp, argc, argv, 0, 0, 0);
+ 
+   return rt;
+ }
diff --exclude=CVS -Ncr hurd/utils.orig/Makefile hurd/utils/Makefile
*** hurd/hurd/paths.h.orig      Sat Mar 23 07:59:15 2002
--- hurd/hurd/paths.h   Sat Mar 23 07:57:30 2002
***************
*** 52,55 ****
--- 52,58 ----
  #define       _HURD_FIFO      _HURD "fifo" /* S_IFIFO */
  #define       _HURD_IFSOCK    _HURD "ifsock" /* S_IFSOCK */
  
+ #define _HURD_SYSVIPC "/tmp/"
+ #define _HURD_SYSVIPC_SHM _HURD_SYSVIPC
+ 
  #endif        /* hurd/paths.h */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]