From 0428fd87ff1493699359cde20909719ee33f4769 Mon Sep 17 00:00:00 2001 From: Colin Walters <walters@verbum.org> Date: Tue, 12 Sep 2017 14:53:35 -0400 Subject: [PATCH] dirfd: Extend tmpdir API to support optional cleaning We have a use case in libostree's staging dirs where we try to reuse them across multiple ostree txns, but we want the fd-relative bits here. Extend the tmpdir API to make deletion optional. While here, also extend the API to support checking for errors when deleting for projects like libostree that want to do so consistently. Also while here, add a change to set the fd to `-1` after clearing to be extra defensive. --- glnx-dirfd.c | 61 +++++++++++++++++++++++++++++++++++++++++----------- glnx-dirfd.h | 10 +++++++-- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/glnx-dirfd.c b/glnx-dirfd.c index b745e2809..cbc31f9f4 100644 --- a/glnx-dirfd.c +++ b/glnx-dirfd.c @@ -371,25 +371,62 @@ glnx_mkdtemp (const gchar *tmpl, out_tmpdir, error); } -/* Deallocate a tmpdir, closing the fd and (recursively) deleting the path. This - * is normally called by default by the autocleanup attribute, but you can also - * invoke this directly. - */ -void -glnx_tmpdir_clear (GLnxTmpDir *tmpd) +static gboolean +_glnx_tmpdir_free (GLnxTmpDir *tmpd, + gboolean delete_dir, + GCancellable *cancellable, + GError **error) { /* Support being passed NULL so we work nicely in a GPtrArray */ - if (!tmpd) - return; - if (!tmpd->initialized) - return; + if (!(tmpd && tmpd->initialized)) + return TRUE; g_assert_cmpint (tmpd->fd, !=, -1); (void) close (tmpd->fd); + tmpd->fd = -1; g_assert (tmpd->path); g_assert_cmpint (tmpd->src_dfd, !=, -1); - (void) glnx_shutil_rm_rf_at (tmpd->src_dfd, tmpd->path, NULL, NULL); - g_free (tmpd->path); + g_autofree char *path = tmpd->path; /* Take ownership */ tmpd->initialized = FALSE; + if (delete_dir) + { + if (!glnx_shutil_rm_rf_at (tmpd->src_dfd, path, cancellable, error)) + return FALSE; + } + return TRUE; } +/** + * glnx_tmpdir_delete: + * @tmpf: Temporary dir + * @cancellable: Cancellable + * @error: Error + * + * Deallocate a tmpdir, closing the fd and recursively deleting the path. This + * is normally called indirectly via glnx_tmpdir_cleanup() by the autocleanup + * attribute, but you can also invoke this directly. + * + * If an error occurs while deleting the filesystem path, @tmpf will still have + * been deallocated and should not be reused. + * + * See also `glnx_tmpdir_unset` to avoid deleting the path. + */ +gboolean +glnx_tmpdir_delete (GLnxTmpDir *tmpf, GCancellable *cancellable, GError **error) +{ + return _glnx_tmpdir_free (tmpf, TRUE, cancellable, error); +} +/** + * glnx_tmpdir_unset: + * @tmpf: Temporary dir + * @cancellable: Cancellable + * @error: Error + * + * Deallocate a tmpdir, but do not delete the filesystem path. See also + * `glnx_tmpdir_delete()`. + */ +void +glnx_tmpdir_unset (GLnxTmpDir *tmpf) +{ + (void) _glnx_tmpdir_free (tmpf, FALSE, NULL, NULL); +} diff --git a/glnx-dirfd.h b/glnx-dirfd.h index 5e362fab2..11d791e88 100644 --- a/glnx-dirfd.h +++ b/glnx-dirfd.h @@ -119,8 +119,14 @@ typedef struct { int fd; char *path; } GLnxTmpDir; -void glnx_tmpdir_clear (GLnxTmpDir *tmpf); -G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GLnxTmpDir, glnx_tmpdir_clear) +gboolean glnx_tmpdir_delete (GLnxTmpDir *tmpf, GCancellable *cancellable, GError **error); +void glnx_tmpdir_unset (GLnxTmpDir *tmpf); +static inline void +glnx_tmpdir_cleanup (GLnxTmpDir *tmpf) +{ + (void)glnx_tmpdir_delete (tmpf, NULL, NULL); +} +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GLnxTmpDir, glnx_tmpdir_cleanup) gboolean glnx_mkdtempat (int dfd, const char *tmpl, int mode, GLnxTmpDir *out_tmpdir, GError **error); -- GitLab