[PATCH] Introduce xcb_aux_alloc_shm() to create anonymous files in RAM
Alexander Volkov <avolkov-5XX0/9e/aDUTdZ/[email protected]> Fri, 15 Feb 2019 19:08:24 +0300
| Newsgroups | gmane.comp.freedesktop.xcb |
|---|---|
| Message-ID | <[email protected]> |
From: Alexander Volkov <[email protected]> ... which then can be mapped with mmap(). It is intended to be used in conjunction with xcb_shm_attach_fd() to access the created shared memory from a client and the X server. The implementation is based on the code of shm_tmpfile() from X.Org Server. Signed-off-by: Alexander Volkov <[email protected]> --- configure.ac | 4 +++ src/xcb_aux.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/xcb_aux.h | 3 ++ 3 files changed, 98 insertions(+) diff --git a/configure.ac b/configure.ac index 1fe1561..8e31ada 100644 --- a/configure.ac +++ b/configure.ac @@ -7,10 +7,14 @@ AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AC_USE_SYSTEM_EXTENSIONS + XCB_UTIL_COMMON([1.4], [1.6]) AC_CHECK_FUNCS_ONCE(vasprintf) +AC_CHECK_FUNCS(memfd_create mkostemp) + AC_CONFIG_FILES([Makefile src/Makefile xcb-atom.pc diff --git a/src/xcb_aux.c b/src/xcb_aux.c index b6f64f8..bb407fb 100644 --- a/src/xcb_aux.c +++ b/src/xcb_aux.c @@ -33,9 +33,16 @@ #include "config.h" #endif +#include <unistd.h> +#if HAVE_MEMFD_CREATE +#include <sys/mman.h> +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <fcntl.h> +#include <limits.h> #include <xcb/xcb.h> #include "xcb_aux.h" @@ -376,3 +383,87 @@ xcb_aux_clear_window(xcb_connection_t * dpy, { return xcb_clear_area(dpy, 0, w, 0, 0, 0, 0); } + +/* SHM related functions */ + +static int +shm_tmpfile(void) +{ + const char *shmdirs[] = { + "/run/shm", + "/var/tmp", + "/tmp", + }; + const int shmdirs_count = sizeof(shmdirs) / sizeof(shmdirs[0]); + int fd; + +#ifdef HAVE_MEMFD_CREATE + fd = memfd_create("xcb", MFD_CLOEXEC|MFD_ALLOW_SEALING); + if (fd != -1) + return fd; +#endif + +#ifdef O_TMPFILE + for (int i = 0; i < shmdirs_count; i++) { + fd = open(shmdirs[i], O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); + if (fd >= 0) + return fd; + } +#endif + + for (int i = 0; i < shmdirs_count; i++) { + char template[PATH_MAX]; + snprintf(template, sizeof(template), "%s/shmfd-XXXXXX", shmdirs[i]); +#ifdef HAVE_MKOSTEMP + fd = mkostemp(template, O_CLOEXEC); +#else + fd = mkstemp(template); +#endif + if (fd < 0) + continue; + unlink(template); +#ifndef HAVE_MKOSTEMP + int flags = fcntl(fd, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + (void) fcntl(fd, F_SETFD, &flags); + } +#endif + return fd; + } + + return -1; +} + +/** + * xcb_aux_alloc_shm: + * + * Creates an anonymous file of the required size in RAM. + * It enables the close-on-exec flag for the file + * descriptor. The F_SEAL_SHRINK seal is set when + * possible, thus the file cannot be reduced in size. + * This function is intended for use in conjunction with + * xcb_shm_attach_fd(). + * + * Return value: the file descriptor, or -1 on failure + * (in which case, errno will be set as appropriate). + **/ + +int +xcb_aux_alloc_shm(size_t size) +{ + int fd; + + fd = shm_tmpfile(); + if (fd < 0) + return -1; +#if defined(F_ADD_SEALS) && defined(F_SEAL_SHRINK) + (void) fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK); +#endif + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} diff --git a/src/xcb_aux.h b/src/xcb_aux.h index da4fb85..75b6e66 100644 --- a/src/xcb_aux.h +++ b/src/xcb_aux.h @@ -206,6 +206,9 @@ xcb_void_cookie_t xcb_aux_clear_window(xcb_connection_t * dpy, xcb_window_t w); +int +xcb_aux_alloc_shm(size_t size); + #ifdef __cplusplus } #endif -- 2.19.1 _______________________________________________ Xcb mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/xcb