[libglnx] dirfd: Add a public API to ensure a filled dtype



commit 91e060699f5559c49335ce19f4b23ba70dfd6bb3
Author: Colin Walters <walters verbum org>
Date:   Fri Jan 1 17:26:12 2016 -0500

    dirfd: Add a public API to ensure a filled dtype
    
    It's quite common to iterate over a directory recursively, only caring
    about the file type, but not other bits returned by `stat()`.
    
    Good file systems fill in `dt_type`, but not all do.  This function
    papers over that in userspace conveniently.

 glnx-dirfd.c |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 glnx-dirfd.h |    4 ++++
 2 files changed, 53 insertions(+), 0 deletions(-)
---
diff --git a/glnx-dirfd.c b/glnx-dirfd.c
index d126f15..4861ccf 100644
--- a/glnx-dirfd.c
+++ b/glnx-dirfd.c
@@ -168,6 +168,8 @@ glnx_dirfd_iterator_next_dent (GLnxDirFdIterator  *dfd_iter,
   gboolean ret = FALSE;
   GLnxRealDirfdIterator *real_dfd_iter = (GLnxRealDirfdIterator*) dfd_iter;
 
+  g_return_val_if_fail (out_dent, FALSE);
+
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     goto out;
 
@@ -190,6 +192,53 @@ glnx_dirfd_iterator_next_dent (GLnxDirFdIterator  *dfd_iter,
 }
 
 /**
+ * glnx_dirfd_iterator_next_dent_ensure_dtype:
+ * @dfd_iter: A directory iterator
+ * @out_dent: (out) (transfer none): Pointer to dirent; do not free
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * A variant of @glnx_dirfd_iterator_next_dent, which will ensure the
+ * `dent->d_type` member is filled in by calling `fstatat`
+ * automatically if the underlying filesystem type sets `DT_UNKNOWN`.
+ */
+gboolean
+glnx_dirfd_iterator_next_dent_ensure_dtype (GLnxDirFdIterator  *dfd_iter,
+                                            struct dirent     **out_dent,
+                                            GCancellable       *cancellable,
+                                            GError            **error)
+{
+  gboolean ret = FALSE;
+  struct dirent *ret_dent;
+
+  g_return_val_if_fail (out_dent, FALSE);
+
+  if (!glnx_dirfd_iterator_next_dent (dfd_iter, out_dent, cancellable, error))
+    goto out;
+
+  ret_dent = *out_dent;
+
+  if (ret_dent)
+    {
+
+      if (ret_dent->d_type == DT_UNKNOWN)
+        {
+          struct stat stbuf;
+          if (TEMP_FAILURE_RETRY (fstatat (dfd_iter->fd, ret_dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW)) != 
0)
+            {
+              glnx_set_error_from_errno (error);
+              goto out;
+            }
+          ret_dent->d_type = IFTODT (stbuf.st_mode);
+        }
+    }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+/**
  * glnx_dirfd_iterator_clear:
  * @dfd_iter: Iterator, will be de-initialized
  *
diff --git a/glnx-dirfd.h b/glnx-dirfd.h
index 5b7b77a..c13e3dc 100644
--- a/glnx-dirfd.h
+++ b/glnx-dirfd.h
@@ -60,6 +60,10 @@ gboolean glnx_dirfd_iterator_next_dent (GLnxDirFdIterator  *dfd_iter,
                                         struct dirent     **out_dent,
                                         GCancellable       *cancellable,
                                         GError            **error);
+gboolean glnx_dirfd_iterator_next_dent_ensure_dtype (GLnxDirFdIterator  *dfd_iter,
+                                                     struct dirent     **out_dent,
+                                                     GCancellable       *cancellable,
+                                                     GError            **error);
 void glnx_dirfd_iterator_clear (GLnxDirFdIterator *dfd_iter);
 
 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GLnxDirFdIterator, glnx_dirfd_iterator_clear)


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