1#include <sys/mman.h>
2#include <errno.h>
3#include <fcntl.h>
4#include <unistd.h>
5#include <string.h>
6#include <limits.h>
7#include <pthread.h>
8
9char *__strchrnul(const char *, int);
10
11char *__shm_mapname(const char *name, char *buf)
12{
13	char *p;
14	while (*name == '/') name++;
15	if (*(p = __strchrnul(name, '/')) || p==name ||
16	    (p-name <= 2 && name[0]=='.' && p[-1]=='.')) {
17		errno = EINVAL;
18		return 0;
19	}
20	if (p-name > NAME_MAX) {
21		errno = ENAMETOOLONG;
22		return 0;
23	}
24	memcpy(buf, "/dev/shm/", 9);
25	memcpy(buf+9, name, p-name+1);
26	return buf;
27}
28
29int shm_open(const char *name, int flag, mode_t mode)
30{
31	int cs;
32	char buf[NAME_MAX+10];
33	if (!(name = __shm_mapname(name, buf))) return -1;
34	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
35	int fd = open(name, flag|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK, mode);
36	pthread_setcancelstate(cs, 0);
37	return fd;
38}
39
40int shm_unlink(const char *name)
41{
42	char buf[NAME_MAX+10];
43	if (!(name = __shm_mapname(name, buf))) return -1;
44	return unlink(name);
45}
46