==> src/shm.c <==1/* shm.rs: memfd_create (Linux) / shm_open + unlink (macOS), ftruncate, mmap. */
2#include "mesh/shm.h"
3#include "mesh/text.h"
4
5#include "mesh/abi/base.h"
6
7#include <errno.h>
8#include <fcntl.h>
9#include <stdatomic.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/mman.h>
13#include <unistd.h>
14
15static char *os_error(int e) { return mesh_fmt("%s (os error %d)", strerror(e), e); }
16
17static int create(char **err) {
18#if defined(__linux__)
19 int fd = memfd_create("meshd-mailbox", MFD_CLOEXEC);
20 if (fd < 0) {
21 char *e = os_error(errno);
22 mesh_errf(err, "mailbox: memfd_create: %s", e);
23 free(e);
24 }
25 return fd;
26#else
27 static atomic_uint n;
28 /* Names are at most 31 bytes on macOS (PSHMNAMLEN). */
29 char name[32];
30 snprintf(name, sizeof name, "/meshd.%d.%u", (int)getpid(), atomic_fetch_add(&n, 1));
31 int fd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0600);
32 if (fd < 0) {
33 char *e = os_error(errno);
34 mesh_errf(err, "mailbox: shm_open \"%s\": %s", name, e);
35 free(e);
36 return -1;
37 }
38 shm_unlink(name);
39 fcntl(fd, F_SETFD, FD_CLOEXEC);
40 return fd;
41#endif
42}
43
44bool mesh_shm_with_len(size_t len, mesh_shm *out, char **err) {
45 int fd = create(err);
46 if (fd < 0) return false;
47 if (ftruncate(fd, (off_t)len) != 0) {
48 char *e = os_error(errno);
49 close(fd);
50 mesh_errf(err, "mailbox: ftruncate %zu: %s", len, e);
51 free(e);
52 return false;
53 }
54 void *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
55 if (p == MAP_FAILED) {
56 char *e = os_error(errno);
57 close(fd);
58 mesh_errf(err, "mailbox: mmap: %s", e);
59 free(e);
60 return false;
61 }
62 *out = (mesh_shm){p, len, fd};
63 return true;
64}
65
66bool mesh_shm_new(mesh_shm *out, char **err) { return mesh_shm_with_len(MESH_MAILBOX_BYTES, out, err); }
67
68char *mesh_shm_path(const mesh_shm *s) { return mesh_fmt("/proc/%d/fd/%d", (int)getpid(), s->fd); }
69
70void mesh_shm_close(mesh_shm *s) {
71 if (s->base) munmap(s->base, s->len);
72 if (s->fd >= 0) close(s->fd);
73 *s = (mesh_shm){NULL, 0, -1};
74}