diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | rt/Makefile | 3 | ||||
-rw-r--r-- | rt/Versions | 3 | ||||
-rw-r--r-- | sysdeps/generic/shm_open.c | 31 | ||||
-rw-r--r-- | sysdeps/generic/shm_unlink.c | 31 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/Versions | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/shm_open.c | 214 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/shm_unlink.c | 1 |
8 files changed, 295 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog index ac5843bcdf..fcecf3613f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2000-04-11 Ulrich Drepper <drepper@redhat.com> + * misc/sys/mman.h: Add prototypes for shm_open and shm_unlink. + * rt/Makefile (librt-routines): Add shm_open and shm_unlink. + * rt/Versions [librt] (GLIBC_2.2): Add shm_open and shm_unlink. + * sysdeps/generic/shm_open.c: New file. + * sysdeps/generic/shm_unlink.c: New file. + * sysdeps/unix/sysv/linux/shm_open.c: New file. + * sysdeps/unix/sysv/linux/shm_unlink.c: New file. + * sysdeps/unix/sysv/linux/Versions [libc] (GLIBC_2.2): Export + __endmntent, __getmntent_r, __setmntent, and __statfs. + * libio/vasprintf.c (_IO_vasprintf): Try to avoid memory fragmentation by allocating new memory at the end instead of reallocating. diff --git a/rt/Makefile b/rt/Makefile index b661edd912..bb07ad0f4e 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -29,7 +29,8 @@ librt-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ aio_notify get_clockfreq clock_getcpuclockid \ clock_getres clock_gettime clock_settime \ timer_create timer_delete timer_getoverr \ - timer_gettime timer_settime + timer_gettime timer_settime \ + shm_open shm_unlink # Make sure that everything is distributed independent of configuration. distribute := aio_misc.h $(librt-routines:=.c) $(librt-map) diff --git a/rt/Versions b/rt/Versions index aec059c06a..b9cb8da0c9 100644 --- a/rt/Versions +++ b/rt/Versions @@ -9,6 +9,9 @@ librt { # c* clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; + # s* + shm_open; shm_unlink; + # t* timer_create; timer_delete; timer_getoverrun; timer_gettime; timer_settime; diff --git a/sysdeps/generic/shm_open.c b/sysdeps/generic/shm_open.c new file mode 100644 index 0000000000..4714ede682 --- /dev/null +++ b/sysdeps/generic/shm_open.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <sys/mman.h> + +/* Open shared memory object. */ +int +shm_open (const char *name, int oflag, mode_t mode) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (shm_open) + +#include <stub-tag.h> diff --git a/sysdeps/generic/shm_unlink.c b/sysdeps/generic/shm_unlink.c new file mode 100644 index 0000000000..9b892efb97 --- /dev/null +++ b/sysdeps/generic/shm_unlink.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <sys/mman.h> + +/* Remove shared memory object. */ +int +shm_unlink (const char *name) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (shm_unlink) + +#include <stub-tag.h> diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index 074938c3da..483e0140ae 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -83,6 +83,9 @@ libc { umount2; } GLIBC_2.2 { + # needed in other libraries. + __endmntent; __getmntent_r; __setmntent; __statfs; + # ipc ctl interface change. semctl; shmctl; msgctl; } diff --git a/sysdeps/unix/sysv/linux/shm_open.c b/sysdeps/unix/sysv/linux/shm_open.c new file mode 100644 index 0000000000..08bdaeadbd --- /dev/null +++ b/sysdeps/unix/sysv/linux/shm_open.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <mntent.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/statfs.h> +#include <bits/libc-lock.h> + + +/* XXX Currently the Linux kernel sources do not define a super magic number + for the shmfs and the kernel assigns the value 0 to f_type. */ +#ifndef SHMFS_SUPER_MAGIC +# define SHMFS_SUPER_MAGIC 0 +#endif + +/* Mount point of the shared memory filesystem. */ +static struct +{ + char *dir; + size_t dirlen; +} mountpoint; + +/* This is the default directory. */ +const char defaultdir[] = "/var/shm/"; + +/* Protect the `mountpoint' variable above. */ +__libc_once_define (static, once); + + +/* Determine where the shmfs is mounted (if at all). */ +static void +where_is_shmfs (void) +{ + char buf[512]; + struct statfs f; + struct mntent resmem; + struct mntent *mp; + FILE *fp; + + /* The canonical place is /var/shm. This is at least what the + documentation tells everybody to do. */ + if (__statfs ("/var/shm", &f) == 0 && f.f_type == SHMFS_SUPER_MAGIC) + { + /* It is in the normal place. */ + mountpoint.dir = (char *) defaultdir; + mountpoint.dirlen = strlen ("/var/shm/"); + + return; + } + + /* OK, do it the hard way. Look through the /proc/mounts file and if + this does not exist through /etc/fstab to find the mount point. */ + fp = __setmntent ("/proc/mounts", "r"); + if (__builtin_expect (fp == NULL, 0)) + { + fp = __setmntent (_PATH_MNTTAB, "r"); + if (__builtin_expect (fp == NULL, 0)) + /* There is nothing we can do. Blind guesses are not helpful. */ + return; + } + + /* Now read the entries. */ + while ((mp = __getmntent_r (fp, &resmem, buf, sizeof buf)) != NULL) + if (strcmp (mp->mnt_type, "shm") == 0) + { + /* Found it. There might be more than one place where the + filesystem is mounted but one is enough for us. */ + size_t namelen = strlen (mp->mnt_dir); + + if (namelen == 0) + /* Hum, maybe some crippled entry. Keep on searching. */ + continue; + + mountpoint.dir = (char *) malloc (namelen + 2); + if (mountpoint.dir != NULL) + { + char *cp = __mempcpy (mountpoint.dir, mp->mnt_dir, namelen); + if (cp[-1] != '/') + *cp++ = '/'; + *cp = '\0'; + mountpoint.dirlen = cp - mountpoint.dir; + } + + break; + } + + /* Close the stream. */ + __endmntent (fp); +} + + +/* Open shared memory object. This implementation assumes the shmfs + implementation introduced in the late 2.3.x kernel series to be + available. Normally the filesystem will be mounted at /var/shm but + we fall back on searching for the actual mount point should opening + such a file fail. */ +int +shm_open (const char *name, int oflag, mode_t mode) +{ + size_t namelen; + char *fname; + + /* Determine where the shmfs is mounted. */ + __libc_once (once, where_is_shmfs); + + /* If we don't know the mount points there is nothing we can do. Ever. */ + if (mountpoint.dir == NULL) + { + __set_errno (ENOSYS); + return -1; + } + + /* Construct the filename. */ + while (name[0] == '/') + ++name; + + if (name[0] == '\0') + { + /* The name "/" is not supported. */ + __set_errno (EINVAL); + return -1; + } + + namelen = strlen (name); + fname = (char *) alloca (mountpoint.dirlen + namelen + 1); + __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen), + name, namelen + 1); + + /* And get the file descriptor. + XXX Maybe we should test each descriptor whether it really is for a + file on the shmfs. If this is what should be done the whole function + should be revamped since we can determine whether shmfs is available + while trying to open the file, all in one turn. */ + return open (fname, oflag, mode); +} + + +/* Unlink a shared memory object. */ +int +shm_unlink (const char *name) +{ + size_t namelen; + char *fname; + + /* Determine where the shmfs is mounted. */ + __libc_once (once, where_is_shmfs); + + if (mountpoint.dir == NULL) + { + /* We cannot find the shmfs. If `name' is really a shared + memory object it must have been created by another process + and we have no idea where that process found the mountpoint. */ + __set_errno (ENOENT); + return -1; + } + + /* Construct the filename. */ + while (name[0] == '/') + ++name; + + if (name[0] == '\0') + { + /* The name "/" is not supported. */ + __set_errno (ENOENT); + return -1; + } + + namelen = strlen (name); + fname = (char *) alloca (mountpoint.dirlen + namelen + 1); + __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen), + name, namelen + 1); + + /* And get the file descriptor. + XXX Maybe we should test each descriptor whether it really is for a + file on the shmfs. If this is what should be done the whole function + should be revamped since we can determine whether shmfs is available + while trying to open the file, all in one turn. */ + return unlink (fname); +} + + +void +freeit (void) +{ + if (mountpoint.dir != NULL && mountpoint.dir != defaultdir) + free (mountpoint.dir); +} + + +/* Make sure the table is freed if we want to free everything before + exiting. */ +text_set_element (__libc_subfreeres, freeit); diff --git a/sysdeps/unix/sysv/linux/shm_unlink.c b/sysdeps/unix/sysv/linux/shm_unlink.c new file mode 100644 index 0000000000..55cece2765 --- /dev/null +++ b/sysdeps/unix/sysv/linux/shm_unlink.c @@ -0,0 +1 @@ +/* This function is for technical reason defined in shm_open.c. */ |