]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/shm_open.c
* Fix SH specific compiler warnings which are for integer-pointer
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / shm_open.c
CommitLineData
d4697bc9 1/* Copyright (C) 2000-2014 Free Software Foundation, Inc.
a63be9f7
UD
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
a63be9f7
UD
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
a63be9f7 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
a63be9f7
UD
17
18#include <errno.h>
19#include <fcntl.h>
20#include <mntent.h>
21#include <paths.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/mman.h>
27#include <sys/statfs.h>
28#include <bits/libc-lock.h>
afdda55a 29#include "linux_fsinfo.h"
a63be9f7
UD
30
31
a63be9f7
UD
32/* Mount point of the shared memory filesystem. */
33static struct
34{
35 char *dir;
36 size_t dirlen;
37} mountpoint;
38
39/* This is the default directory. */
301909fb 40static const char defaultdir[] = "/dev/shm/";
a63be9f7
UD
41
42/* Protect the `mountpoint' variable above. */
43__libc_once_define (static, once);
44
45
46/* Determine where the shmfs is mounted (if at all). */
47static void
48where_is_shmfs (void)
49{
50 char buf[512];
51 struct statfs f;
52 struct mntent resmem;
53 struct mntent *mp;
54 FILE *fp;
55
b26a9120 56 /* The canonical place is /dev/shm. This is at least what the
a63be9f7 57 documentation tells everybody to do. */
d674667c
MF
58 if (__statfs (defaultdir, &f) == 0 && (f.f_type == SHMFS_SUPER_MAGIC
59 || f.f_type == RAMFS_MAGIC))
a63be9f7
UD
60 {
61 /* It is in the normal place. */
62 mountpoint.dir = (char *) defaultdir;
480a06df 63 mountpoint.dirlen = sizeof (defaultdir) - 1;
a63be9f7
UD
64
65 return;
66 }
67
68 /* OK, do it the hard way. Look through the /proc/mounts file and if
69 this does not exist through /etc/fstab to find the mount point. */
70 fp = __setmntent ("/proc/mounts", "r");
a1ffb40e 71 if (__glibc_unlikely (fp == NULL))
a63be9f7
UD
72 {
73 fp = __setmntent (_PATH_MNTTAB, "r");
a1ffb40e 74 if (__glibc_unlikely (fp == NULL))
a63be9f7
UD
75 /* There is nothing we can do. Blind guesses are not helpful. */
76 return;
77 }
78
79 /* Now read the entries. */
80 while ((mp = __getmntent_r (fp, &resmem, buf, sizeof buf)) != NULL)
9db02f0b
AJ
81 /* The original name is "shm" but this got changed in early Linux
82 2.4.x to "tmpfs". */
d674667c
MF
83 if (strcmp (mp->mnt_type, "tmpfs") == 0
84 || strcmp (mp->mnt_type, "shm") == 0)
a63be9f7
UD
85 {
86 /* Found it. There might be more than one place where the
87 filesystem is mounted but one is enough for us. */
301909fb
UD
88 size_t namelen;
89
90 /* First make sure this really is the correct entry. At least
91 some versions of the kernel give wrong information because
92 of the implicit mount of the shmfs for SysV IPC. */
d674667c
MF
93 if (__statfs (mp->mnt_dir, &f) != 0 || (f.f_type != SHMFS_SUPER_MAGIC
94 && f.f_type != RAMFS_MAGIC))
301909fb
UD
95 continue;
96
97 namelen = strlen (mp->mnt_dir);
a63be9f7
UD
98
99 if (namelen == 0)
100 /* Hum, maybe some crippled entry. Keep on searching. */
101 continue;
102
103 mountpoint.dir = (char *) malloc (namelen + 2);
104 if (mountpoint.dir != NULL)
105 {
106 char *cp = __mempcpy (mountpoint.dir, mp->mnt_dir, namelen);
107 if (cp[-1] != '/')
108 *cp++ = '/';
109 *cp = '\0';
110 mountpoint.dirlen = cp - mountpoint.dir;
111 }
112
113 break;
114 }
115
116 /* Close the stream. */
117 __endmntent (fp);
118}
119
120
121/* Open shared memory object. This implementation assumes the shmfs
122 implementation introduced in the late 2.3.x kernel series to be
b26a9120 123 available. Normally the filesystem will be mounted at /dev/shm but
a63be9f7
UD
124 we fall back on searching for the actual mount point should opening
125 such a file fail. */
126int
127shm_open (const char *name, int oflag, mode_t mode)
128{
129 size_t namelen;
130 char *fname;
fb125e0c 131 int fd;
a63be9f7
UD
132
133 /* Determine where the shmfs is mounted. */
134 __libc_once (once, where_is_shmfs);
135
136 /* If we don't know the mount points there is nothing we can do. Ever. */
137 if (mountpoint.dir == NULL)
138 {
139 __set_errno (ENOSYS);
140 return -1;
141 }
142
143 /* Construct the filename. */
144 while (name[0] == '/')
145 ++name;
146
5d30d853
OB
147 namelen = strlen (name);
148
149 /* Validate the filename. */
b20de2c3 150 if (name[0] == '\0' || namelen > NAME_MAX || strchr (name, '/') != NULL)
a63be9f7 151 {
a63be9f7
UD
152 __set_errno (EINVAL);
153 return -1;
154 }
155
a63be9f7
UD
156 fname = (char *) alloca (mountpoint.dirlen + namelen + 1);
157 __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen),
158 name, namelen + 1);
159
160 /* And get the file descriptor.
161 XXX Maybe we should test each descriptor whether it really is for a
162 file on the shmfs. If this is what should be done the whole function
163 should be revamped since we can determine whether shmfs is available
164 while trying to open the file, all in one turn. */
74385da5
JM
165 fd = open (fname, oflag | O_CLOEXEC | O_NOFOLLOW, mode);
166 if (fd == -1 && __glibc_unlikely (errno == EISDIR))
ee4e5a3d
UD
167 /* It might be better to fold this error with EINVAL since
168 directory names are just another example for unsuitable shared
169 object names and the standard does not mention EISDIR. */
170 __set_errno (EINVAL);
fb125e0c
UD
171
172 return fd;
a63be9f7
UD
173}
174
175
176/* Unlink a shared memory object. */
177int
178shm_unlink (const char *name)
179{
180 size_t namelen;
181 char *fname;
182
183 /* Determine where the shmfs is mounted. */
184 __libc_once (once, where_is_shmfs);
185
186 if (mountpoint.dir == NULL)
187 {
188 /* We cannot find the shmfs. If `name' is really a shared
189 memory object it must have been created by another process
190 and we have no idea where that process found the mountpoint. */
191 __set_errno (ENOENT);
192 return -1;
193 }
194
195 /* Construct the filename. */
196 while (name[0] == '/')
197 ++name;
198
5d30d853
OB
199 namelen = strlen (name);
200
201 /* Validate the filename. */
b20de2c3 202 if (name[0] == '\0' || namelen > NAME_MAX || strchr (name, '/') != NULL)
a63be9f7 203 {
a63be9f7
UD
204 __set_errno (ENOENT);
205 return -1;
206 }
207
a63be9f7
UD
208 fname = (char *) alloca (mountpoint.dirlen + namelen + 1);
209 __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen),
210 name, namelen + 1);
211
ba334988 212 /* And remove the file. */
f9a06dc1
UD
213 int ret = unlink (fname);
214 if (ret < 0 && errno == EPERM)
215 __set_errno (EACCES);
216 return ret;
a63be9f7
UD
217}
218
219
c877418f
RM
220/* Make sure the table is freed if we want to free everything before
221 exiting. */
222libc_freeres_fn (freeit)
a63be9f7 223{
b26a9120 224 if (mountpoint.dir != defaultdir)
a63be9f7
UD
225 free (mountpoint.dir);
226}