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