[libglnx] dirfd: Extend tmpdir API to support optional cleaning



commit 0428fd87ff1493699359cde20909719ee33f4769
Author: Colin Walters <walters verbum org>
Date:   Tue Sep 12 14:53:35 2017 -0400

    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 b745e28..cbc31f9 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 5e362fa..11d791e 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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]