diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-04-12 04:59:33 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-04-12 04:59:33 +0000 |
commit | a63be9f77713b1024335c053dafd58a6cd7075bb (patch) | |
tree | 4f781f03ecbf78f298f5e6aa9e50512e84fe79ca /sysdeps/unix/sysv/linux/shm_open.c | |
parent | 967866f4d7d2ad550836368d40f360c26e82c758 (diff) | |
download | glibc-a63be9f77713b1024335c053dafd58a6cd7075bb.tar.gz glibc-a63be9f77713b1024335c053dafd58a6cd7075bb.tar.xz glibc-a63be9f77713b1024335c053dafd58a6cd7075bb.zip |
Update.
* 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.
Diffstat (limited to 'sysdeps/unix/sysv/linux/shm_open.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/shm_open.c | 214 |
1 files changed, 214 insertions, 0 deletions
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); |