diff --git a/buffer.c b/buffer.c index 210a4cc..80afce5 100644 --- a/buffer.c +++ b/buffer.c @@ -1,30 +1,48 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200112L +#include +#include #include #include #include #include +#include #include #include "buffer.h" -static int create_pool_file(size_t size, char **name) { - static const char template[] = "grim-XXXXXX"; - const char *path = getenv("XDG_RUNTIME_DIR"); - if (path == NULL) { - return -1; +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 ts = (path[strlen(path) - 1] == '/'); +static int anonymous_shm_open(void) { + char name[] = "/grim-XXXXXX"; + int retries = 100; - *name = malloc( - strlen(template) + - strlen(path) + - (ts ? 0 : 1) + 1); - sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); + do { + randname(name + strlen(name) - 6); - int fd = mkstemp(*name); + --retries; + // shm_open guarantees that O_CLOEXEC is set + 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; +} + +static int create_shm_file(off_t size) { + int fd = anonymous_shm_open(); if (fd < 0) { - return -1; + return fd; } if (ftruncate(fd, size) < 0) { @@ -39,16 +57,14 @@ struct grim_buffer *create_buffer(struct wl_shm *shm, enum wl_shm_format format, int32_t width, int32_t height, int32_t stride) { size_t size = stride * height; - char *name; - int fd = create_pool_file(size, &name); + int fd = create_shm_file(size); if (fd == -1) { return NULL; } void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { - unlink(name); - free(name); + close(fd); return NULL; } @@ -58,9 +74,6 @@ struct grim_buffer *create_buffer(struct wl_shm *shm, enum wl_shm_format format, wl_shm_pool_destroy(pool); close(fd); - fd = -1; - unlink(name); - free(name); struct grim_buffer *buffer = calloc(1, sizeof(struct grim_buffer)); buffer->wl_buffer = wl_buffer; diff --git a/meson.build b/meson.build index 914c5bc..1837d44 100644 --- a/meson.build +++ b/meson.build @@ -16,11 +16,13 @@ add_project_arguments('-Wno-unused-parameter', language: 'c') grim_inc = include_directories('include') cc = meson.get_compiler('c') + cairo = dependency('cairo') -wayland_client = dependency('wayland-client') -wayland_protos = dependency('wayland-protocols', version: '>=1.14') jpeg = dependency('libjpeg') math = cc.find_library('m') +realtime = cc.find_library('rt') +wayland_client = dependency('wayland-client') +wayland_protos = dependency('wayland-protocols', version: '>=1.14') subdir('protocol') @@ -39,6 +41,7 @@ executable( client_protos, jpeg, math, + realtime, wayland_client, ], include_directories: [grim_inc],