diff options
author | Roland McGrath <roland@hack.frob.com> | 2014-12-11 14:15:51 -0800 |
---|---|---|
committer | Roland McGrath <roland@hack.frob.com> | 2014-12-11 16:19:11 -0800 |
commit | 78e21c5df674e037d06e86c5d4cb95818c8f6b8c (patch) | |
tree | 41b2d0b9e5fcb5cb2709a24a93364e172306740a /sysdeps/unix | |
parent | f82c43af8aebc5a270c8be06055ee5a38063bac3 (diff) | |
download | glibc-78e21c5df674e037d06e86c5d4cb95818c8f6b8c.tar.gz glibc-78e21c5df674e037d06e86c5d4cb95818c8f6b8c.tar.xz glibc-78e21c5df674e037d06e86c5d4cb95818c8f6b8c.zip |
Refactor shm_{open,unlink} code to separate Linux-specific directory choice from POSIX-generic code.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/shm-directory.c | 144 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/shm_open.c | 226 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/shm_unlink.c | 1 |
3 files changed, 144 insertions, 227 deletions
diff --git a/sysdeps/unix/sysv/linux/shm-directory.c b/sysdeps/unix/sysv/linux/shm-directory.c new file mode 100644 index 0000000000..9340f9c331 --- /dev/null +++ b/sysdeps/unix/sysv/linux/shm-directory.c @@ -0,0 +1,144 @@ +/* Determine directory for shm/sem files. Linux version. + Copyright (C) 2000-2014 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, see + <http://www.gnu.org/licenses/>. */ + +#include "shm-directory.h" + +#include <errno.h> +#include <mntent.h> +#include <paths.h> +#include <stdio.h> +#include <string.h> +#include <sys/statfs.h> +#include <bits/libc-lock.h> +#include "linux_fsinfo.h" + + +/* Mount point of the shared memory filesystem. */ +static struct +{ + char *dir; + size_t dirlen; +} mountpoint; + +/* This is the default directory. */ +static const char defaultdir[] = "/dev/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 /dev/shm. This is at least what the + documentation tells everybody to do. */ + if (__statfs (defaultdir, &f) == 0 && (f.f_type == SHMFS_SUPER_MAGIC + || f.f_type == RAMFS_MAGIC)) + { + /* It is in the normal place. */ + mountpoint.dir = (char *) defaultdir; + mountpoint.dirlen = sizeof (defaultdir) - 1; + + 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 (__glibc_unlikely (fp == NULL)) + { + fp = __setmntent (_PATH_MNTTAB, "r"); + if (__glibc_unlikely (fp == NULL)) + /* 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) + /* The original name is "shm" but this got changed in early Linux + 2.4.x to "tmpfs". */ + if (strcmp (mp->mnt_type, "tmpfs") == 0 + || 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; + + /* First make sure this really is the correct entry. At least + some versions of the kernel give wrong information because + of the implicit mount of the shmfs for SysV IPC. */ + if (__statfs (mp->mnt_dir, &f) != 0 || (f.f_type != SHMFS_SUPER_MAGIC + && f.f_type != RAMFS_MAGIC)) + continue; + + 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); +} + + +const char * +__shm_directory (size_t *len) +{ + /* 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 (__glibc_unlikely (mountpoint.dir == NULL)) + { + __set_errno (ENOSYS); + return NULL; + } + + *len = mountpoint.dirlen; + return mountpoint.dir; +} + + +/* Make sure the table is freed if we want to free everything before + exiting. */ +libc_freeres_fn (freeit) +{ + if (mountpoint.dir != defaultdir) + free (mountpoint.dir); +} diff --git a/sysdeps/unix/sysv/linux/shm_open.c b/sysdeps/unix/sysv/linux/shm_open.c deleted file mode 100644 index a0fa958c68..0000000000 --- a/sysdeps/unix/sysv/linux/shm_open.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2000-2014 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, see - <http://www.gnu.org/licenses/>. */ - -#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> -#include "linux_fsinfo.h" - - -/* Mount point of the shared memory filesystem. */ -static struct -{ - char *dir; - size_t dirlen; -} mountpoint; - -/* This is the default directory. */ -static const char defaultdir[] = "/dev/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 /dev/shm. This is at least what the - documentation tells everybody to do. */ - if (__statfs (defaultdir, &f) == 0 && (f.f_type == SHMFS_SUPER_MAGIC - || f.f_type == RAMFS_MAGIC)) - { - /* It is in the normal place. */ - mountpoint.dir = (char *) defaultdir; - mountpoint.dirlen = sizeof (defaultdir) - 1; - - 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 (__glibc_unlikely (fp == NULL)) - { - fp = __setmntent (_PATH_MNTTAB, "r"); - if (__glibc_unlikely (fp == NULL)) - /* 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) - /* The original name is "shm" but this got changed in early Linux - 2.4.x to "tmpfs". */ - if (strcmp (mp->mnt_type, "tmpfs") == 0 - || 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; - - /* First make sure this really is the correct entry. At least - some versions of the kernel give wrong information because - of the implicit mount of the shmfs for SysV IPC. */ - if (__statfs (mp->mnt_dir, &f) != 0 || (f.f_type != SHMFS_SUPER_MAGIC - && f.f_type != RAMFS_MAGIC)) - continue; - - 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 /dev/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; - int fd; - - /* 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; - - namelen = strlen (name); - - /* Validate the filename. */ - if (name[0] == '\0' || namelen > NAME_MAX || strchr (name, '/') != NULL) - { - __set_errno (EINVAL); - return -1; - } - - 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. */ - fd = open (fname, oflag | O_CLOEXEC | O_NOFOLLOW, mode); - if (fd == -1 && __glibc_unlikely (errno == EISDIR)) - /* It might be better to fold this error with EINVAL since - directory names are just another example for unsuitable shared - object names and the standard does not mention EISDIR. */ - __set_errno (EINVAL); - - return fd; -} - - -/* 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; - - namelen = strlen (name); - - /* Validate the filename. */ - if (name[0] == '\0' || namelen > NAME_MAX || strchr (name, '/') != NULL) - { - __set_errno (ENOENT); - return -1; - } - - fname = (char *) alloca (mountpoint.dirlen + namelen + 1); - __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen), - name, namelen + 1); - - /* And remove the file. */ - int ret = unlink (fname); - if (ret < 0 && errno == EPERM) - __set_errno (EACCES); - return ret; -} - - -/* Make sure the table is freed if we want to free everything before - exiting. */ -libc_freeres_fn (freeit) -{ - if (mountpoint.dir != defaultdir) - free (mountpoint.dir); -} diff --git a/sysdeps/unix/sysv/linux/shm_unlink.c b/sysdeps/unix/sysv/linux/shm_unlink.c deleted file mode 100644 index 55cece2765..0000000000 --- a/sysdeps/unix/sysv/linux/shm_unlink.c +++ /dev/null @@ -1 +0,0 @@ -/* This function is for technical reason defined in shm_open.c. */ |