diff options
author | emersion <contact@emersion.fr> | 2018-10-26 18:38:23 +0200 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-10-28 22:39:54 +0100 |
commit | 346ec21c4c9007e98c84b67e4f5e4b9a67bbbce7 (patch) | |
tree | 12574c950607634c72be6a00204772d25bc4c78b /util/shm.c | |
parent | f668e49faeeb06bf71e8b0d21f745e0f68aab4ba (diff) |
util: use shm_open for in-memory files
shm_open is a POSIX function creating an in-memory file. Using it simplifies
the code and removes the dependency on XDG_RUNTIME_DIR. The only downside is
that we need to generate a random name for the shm file.
Diffstat (limited to 'util/shm.c')
-rw-r--r-- | util/shm.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/util/shm.c b/util/shm.c new file mode 100644 index 00000000..3783e473 --- /dev/null +++ b/util/shm.c @@ -0,0 +1,67 @@ +#define _POSIX_C_SOURCE 200112L +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/mman.h> +#include <time.h> +#include <unistd.h> +#include <wlr/config.h> +#include "util/shm.h" + +static void randname(char *buf) { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long r = ts.tv_nsec; + for (int i = 0; i < 6; ++i) { + buf[i] = 'A'+(r&15)+(r&16)*2; + r >>= 5; + } +} + +int create_shm_file(void) { + int retries = 100; + do { + char name[] = "/wlroots-XXXXXX"; + randname(name + strlen(name) - 6); + + --retries; + // CLOEXEC is guaranteed to be set by shm_open + int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd >= 0) { + shm_unlink(name); + return fd; + } + } while (retries > 0 && errno == EEXIST); + + return -1; +} + +int allocate_shm_file(size_t size) { + int fd = create_shm_file(); + if (fd < 0) { + return -1; + } + +#ifdef WLR_HAS_POSIX_FALLOCATE + int ret; + do { + ret = posix_fallocate(fd, 0, size); + } while (ret == EINTR); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + int ret; + do { + ret = ftruncate(fd, size); + } while (ret < 0 && errno == EINTR); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} |