Instrument Neutral Distributed Interface INDI  2.0.2
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 __HAIKU__
39 #define IMPL_POSIX
40 #endif
41 
42 #ifdef __NetBSD__
43 #define IMPL_POSIX
44 #endif
45 
46 #ifdef __APPLE__
47 #ifdef __MACH__
48 #define IMPL_POSIX
49 #endif
50 #endif
51 
52 #ifdef __sun
53 #define IMPL_POSIX
54 #endif
55 
56 #ifdef __DragonFly__
57 #define IMPL_POSIX
58 #endif
59 
60 #ifdef __GNU__
61 #define IMPL_POSIX
62 #endif
63 
64 #ifdef __OpenBSD__
65 #define IMPL_SHM_MKSTEMP
66 #endif
67 
68 #ifdef __CYGWIN__
69 #define IMPL_POSIX
70 #endif
71 
72 #ifdef IMPL_POSIX
73 #define IMPL_UNLINK_OR_CLOSE
74 #endif
75 
76 #ifdef IMPL_SHM_MKSTEMP
77 #define IMPL_UNLINK_OR_CLOSE
78 #endif
79 
80 #ifdef IMPL_UNLINK_OR_CLOSE
81 static int
82 shm_unlink_or_close(const char *name, int fd)
83 {
84  int save;
85 
86  if (shm_unlink(name) == -1) {
87  save = errno;
88  close(fd);
89  errno = save;
90  return -1;
91  }
92  return fd;
93 }
94 #endif
95 
96 #ifdef IMPL_POSIX
97 int
98 shm_open_anon(void)
99 {
100  char name[16] = "/shm-";
101  struct timespec tv;
102  unsigned long r;
103  char *const limit = name + sizeof(name) - 1;
104  char *start;
105  char *fill;
106  int fd, tries;
107 
108  *limit = 0;
109  start = name + strlen(name);
110  for (tries = 0; tries < 4; tries++) {
111  clock_gettime(CLOCK_REALTIME, &tv);
112  r = (unsigned long)tv.tv_sec + (unsigned long)tv.tv_nsec;
113  for (fill = start; fill < limit; r /= 8)
114  *fill++ = '0' + (r % 8);
115  fd = shm_open(
116  name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
117  if (fd != -1)
118  return shm_unlink_or_close(name, fd);
119  if (errno != EEXIST)
120  break;
121  }
122  return -1;
123 }
124 #endif
125 
126 #ifdef IMPL_SHM_MKSTEMP
127 int
128 shm_open_anon(void)
129 {
130  char name[16] = "/shm-XXXXXXXXXX";
131  int fd;
132 
133  if ((fd = shm_mkstemp(name)) == -1)
134  return -1;
135  return shm_unlink_or_close(name, fd);
136 }
137 #endif
138 
139 #ifdef IMPL_SHM_ANON
140 int
141 shm_open_anon(void)
142 {
143  return shm_open(SHM_ANON, O_RDWR, 0);
144 }
145 #endif
146 
147 #ifdef IMPL_MEMFD
148 int
149 shm_open_anon(void)
150 {
151  return syscall(
152  __NR_memfd_create, "shm_anon", (unsigned int)(MFD_CLOEXEC));
153 }
154 #endif
int errno
int fd
Definition: intelliscope.c:43
int shm_open_anon(void)