Instrument Neutral Distributed Interface INDI 2.2.5
shm_open_anon.c
Go to the documentation of this file.
1// Copyright 2019 Lassi Kortela
2// SPDX-License-Identifier: ISC
3
4#ifdef __linux__
5#ifndef _GNU_SOURCE
6#define _GNU_SOURCE
7#endif
8#include <linux/memfd.h>
9#include <linux/unistd.h>
10#endif
11
12#include <sys/types.h>
13
14#include <sys/mman.h>
15
16#include <errno.h>
17#include <fcntl.h>
18#include <string.h>
19#include <time.h>
20#include <unistd.h>
21
22#undef IMPL_MEMFD
23#undef IMPL_POSIX
24#undef IMPL_SHM_ANON
25#undef IMPL_SHM_MKSTEMP
26#undef IMPL_UNLINK_OR_CLOSE
27
28#ifdef __linux__
29#ifdef __NR_memfd_create
30#define IMPL_MEMFD
31#endif
32#endif
33
34#ifdef __FreeBSD__
35#define IMPL_SHM_ANON
36#endif
37
38#ifdef __OpenBSD__
39#define IMPL_SHM_MKSTEMP
40#endif
41
42#if !defined(IMPL_MEMFD) && !defined(IMPL_SHM_ANON) && \
43 !defined(IMPL_SHM_MKSTEMP)
44#define IMPL_POSIX
45#endif
46
47#if defined(IMPL_POSIX) || defined(IMPL_SHM_MKSTEMP)
48#define IMPL_UNLINK_OR_CLOSE
49#endif
50
51#ifdef IMPL_UNLINK_OR_CLOSE
52static int
53shm_unlink_or_close(const char *name, int fd)
54{
55 int save;
56
57 if (shm_unlink(name) == -1) {
58 save = errno;
59 close(fd);
60 errno = save;
61 return -1;
62 }
63 return fd;
64}
65#endif
66
67#ifdef IMPL_POSIX
68int
70{
71 char name[16] = "/shm-";
72 struct timespec tv;
73 unsigned long r;
74 char *const limit = name + sizeof(name) - 1;
75 char *start;
76 char *fill;
77 int fd, tries;
78
79 *limit = 0;
80 start = name + strlen(name);
81 for (tries = 0; tries < 4; tries++) {
82 clock_gettime(CLOCK_REALTIME, &tv);
83 r = (unsigned long)tv.tv_sec + (unsigned long)tv.tv_nsec;
84 for (fill = start; fill < limit; r /= 8)
85 *fill++ = '0' + (r % 8);
86#ifdef O_NOFOLLOW
87 fd = shm_open(
88 name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
89#else
90 fd = shm_open(
91 name, O_RDWR | O_CREAT | O_EXCL, 0600);
92#endif
93 if (fd != -1)
94 return shm_unlink_or_close(name, fd);
95 if (errno != EEXIST)
96 break;
97 }
98 return -1;
99}
100#endif
101
102#ifdef IMPL_SHM_MKSTEMP
103int
104shm_open_anon(void)
105{
106 char name[16] = "/shm-XXXXXXXXXX";
107 int fd;
108
109 if ((fd = shm_mkstemp(name)) == -1)
110 return -1;
111 return shm_unlink_or_close(name, fd);
112}
113#endif
114
115#ifdef IMPL_SHM_ANON
116int
117shm_open_anon(void)
118{
119 return shm_open(SHM_ANON, O_RDWR, 0);
120}
121#endif
122
123#ifdef IMPL_MEMFD
124int
125shm_open_anon(void)
126{
127 return syscall(
128 __NR_memfd_create, "shm_anon", (unsigned int)(MFD_CLOEXEC));
129}
130#endif
int errno
int fd
int shm_open_anon(void)