diff --git a/subprojects/libglnx/.gitlab-ci.yml b/subprojects/libglnx/.gitlab-ci.yml index 0d204ba8deea35a9b53ec1a972f3b8481a1d0acc..36638d7400d041e31f998b768518890c4936d395 100644 --- a/subprojects/libglnx/.gitlab-ci.yml +++ b/subprojects/libglnx/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: fedora:rawhide +image: registry.fedoraproject.org/fedora:30 stages: - build diff --git a/subprojects/libglnx/Makefile-libglnx.am b/subprojects/libglnx/Makefile-libglnx.am index 158063c7beee4b71100b5f85e4d2cbd43ffab4d7..957eae977e79ad9eb89f8abe9e2da9bd8e3b20cf 100644 --- a/subprojects/libglnx/Makefile-libglnx.am +++ b/subprojects/libglnx/Makefile-libglnx.am @@ -56,23 +56,25 @@ libglnx_la_LIBADD = $(libglnx_libs) libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros test-libglnx-shutil TESTS += $(libglnx_tests) +libglnx_testlib_sources = $(libglnx_srcpath)/tests/libglnx-testlib.c + check_PROGRAMS += $(libglnx_tests) -test_libglnx_xattrs_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-xattrs.c +test_libglnx_xattrs_SOURCES = $(libglnx_testlib_sources) $(libglnx_srcpath)/tests/test-libglnx-xattrs.c test_libglnx_xattrs_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) test_libglnx_xattrs_LDADD = $(libglnx_libs) libglnx.la -test_libglnx_fdio_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-fdio.c +test_libglnx_fdio_SOURCES = $(libglnx_testlib_sources) $(libglnx_srcpath)/tests/test-libglnx-fdio.c test_libglnx_fdio_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) test_libglnx_fdio_LDADD = $(libglnx_libs) libglnx.la -test_libglnx_errors_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-errors.c +test_libglnx_errors_SOURCES = $(libglnx_testlib_sources) $(libglnx_srcpath)/tests/test-libglnx-errors.c test_libglnx_errors_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) test_libglnx_errors_LDADD = $(libglnx_libs) libglnx.la -test_libglnx_macros_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-macros.c +test_libglnx_macros_SOURCES = $(libglnx_testlib_sources) $(libglnx_srcpath)/tests/test-libglnx-macros.c test_libglnx_macros_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) test_libglnx_macros_LDADD = $(libglnx_libs) libglnx.la -test_libglnx_shutil_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-shutil.c +test_libglnx_shutil_SOURCES = $(libglnx_testlib_sources) $(libglnx_srcpath)/tests/test-libglnx-shutil.c test_libglnx_shutil_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) test_libglnx_shutil_LDADD = $(libglnx_libs) libglnx.la diff --git a/subprojects/libglnx/glnx-fdio.c b/subprojects/libglnx/glnx-fdio.c index 288cc0235f3164eabaec172a13094883d399deaf..31bb15d246c8691ffb5132481d5dcaeb960c794f 100644 --- a/subprojects/libglnx/glnx-fdio.c +++ b/subprojects/libglnx/glnx-fdio.c @@ -278,17 +278,19 @@ glnx_open_tmpfile_linkable_at (int dfd, return open_tmpfile_core (dfd, subpath, flags, out_tmpf, error); } + /* A variant of `glnx_open_tmpfile_linkable_at()` which doesn't support linking. - * Useful for true temporary storage. The fd will be allocated in /var/tmp to - * ensure maximum storage space. + * Useful for true temporary storage. The fd will be allocated in the specified + * directory. */ gboolean -glnx_open_anonymous_tmpfile (int flags, - GLnxTmpfile *out_tmpf, - GError **error) +glnx_open_anonymous_tmpfile_full (int flags, + const char *dir, + GLnxTmpfile *out_tmpf, + GError **error) { /* Add in O_EXCL */ - if (!open_tmpfile_core (AT_FDCWD, "/var/tmp", flags | O_EXCL, out_tmpf, error)) + if (!open_tmpfile_core (AT_FDCWD, dir, flags | O_EXCL, out_tmpf, error)) return FALSE; if (out_tmpf->path) { @@ -300,6 +302,21 @@ glnx_open_anonymous_tmpfile (int flags, return TRUE; } +/* A variant of `glnx_open_tmpfile_linkable_at()` which doesn't support linking. + * Useful for true temporary storage. The fd will be allocated in /var/tmp to + * ensure maximum storage space. + * + * If you need the file on a specific filesystem use glnx_open_anonymous_tmpfile_full() + * which lets you pass a directory. + */ +gboolean +glnx_open_anonymous_tmpfile (int flags, + GLnxTmpfile *out_tmpf, + GError **error) +{ + return glnx_open_anonymous_tmpfile_full (flags, "/var/tmp", out_tmpf, error); +} + /* Use this after calling glnx_open_tmpfile_linkable_at() to give * the file its final name (link into place). */ @@ -347,8 +364,7 @@ glnx_link_tmpfile_at (GLnxTmpfile *tmpf, { /* This case we have O_TMPFILE, so our reference to it is via /proc/self/fd */ char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(tmpf->fd) + 1]; - - sprintf (proc_fd_path, "/proc/self/fd/%i", tmpf->fd); + snprintf (proc_fd_path, sizeof (proc_fd_path), "/proc/self/fd/%i", tmpf->fd); if (replace) { @@ -408,6 +424,45 @@ glnx_link_tmpfile_at (GLnxTmpfile *tmpf, return TRUE; } +/* glnx_tmpfile_reopen_rdonly: + * @tmpf: tmpfile + * @error: Error + * + * Give up write access to the file descriptior. One use + * case for this is fs-verity, which requires a read-only fd. + * It could also be useful to allocate an anonymous tmpfile + * write some sort of caching/indexing data to it, then reopen it + * read-only thereafter. + **/ +gboolean +glnx_tmpfile_reopen_rdonly (GLnxTmpfile *tmpf, + GError **error) +{ + g_return_val_if_fail (tmpf->fd >= 0, FALSE); + g_return_val_if_fail (tmpf->src_dfd == AT_FDCWD || tmpf->src_dfd >= 0, FALSE); + + glnx_fd_close int rdonly_fd = -1; + + if (tmpf->path) + { + if (!glnx_openat_rdonly (tmpf->src_dfd, tmpf->path, FALSE, &rdonly_fd, error)) + return FALSE; + } + else + { + /* This case we have O_TMPFILE, so our reference to it is via /proc/self/fd */ + char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(tmpf->fd) + 1]; + snprintf (proc_fd_path, sizeof (proc_fd_path), "/proc/self/fd/%i", tmpf->fd); + + if (!glnx_openat_rdonly (AT_FDCWD, proc_fd_path, TRUE, &rdonly_fd, error)) + return FALSE; + } + + glnx_close_fd (&tmpf->fd); + tmpf->fd = glnx_steal_fd (&rdonly_fd); + return TRUE; +} + /** * glnx_openat_rdonly: * @dfd: File descriptor for origin directory diff --git a/subprojects/libglnx/glnx-fdio.h b/subprojects/libglnx/glnx-fdio.h index c0a7cc1de847e0bc9ca2f1c3306eb413055701d7..9c57dc5ee290070f69313b8b3b8329de8965016d 100644 --- a/subprojects/libglnx/glnx-fdio.h +++ b/subprojects/libglnx/glnx-fdio.h @@ -83,6 +83,13 @@ glnx_open_anonymous_tmpfile (int flags, GLnxTmpfile *out_tmpf, GError **error); +gboolean +glnx_open_anonymous_tmpfile_full (int flags, + const char *dir, + GLnxTmpfile *out_tmpf, + GError **error); + + gboolean glnx_open_tmpfile_linkable_at (int dfd, const char *subpath, @@ -103,6 +110,10 @@ glnx_link_tmpfile_at (GLnxTmpfile *tmpf, const char *target, GError **error); +gboolean +glnx_tmpfile_reopen_rdonly (GLnxTmpfile *tmpf, + GError **error); + gboolean glnx_openat_rdonly (int dfd, const char *path, diff --git a/subprojects/libglnx/glnx-macros.h b/subprojects/libglnx/glnx-macros.h index 6d8aca93f8a36b49e378c59bc374e169e0991c71..700fc75ceed0ab1248a95e4fe03abb8b8bc6c6e9 100644 --- a/subprojects/libglnx/glnx-macros.h +++ b/subprojects/libglnx/glnx-macros.h @@ -31,6 +31,16 @@ G_BEGIN_DECLS /* All of these are for C only. */ #ifndef __GI_SCANNER__ +/* fixes builds against musl, taken from glibc unistd.h */ +#ifndef TEMP_FAILURE_RETRY +#define TEMP_FAILURE_RETRY(expression) \ + (__extension__ \ + ({ long int __result; \ + do __result = (long int) (expression); \ + while (__result == -1L && errno == EINTR); \ + __result; })) +#endif + /* Taken from https://github.com/systemd/systemd/src/basic/string-util.h * at revision v228-666-gcf6c8c4 */