summaryrefslogtreecommitdiff
path: root/glnx-dirfd.c
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2016-01-01 17:26:12 -0500
committerColin Walters <walters@verbum.org>2016-01-02 19:42:53 -0500
commit91e060699f5559c49335ce19f4b23ba70dfd6bb3 (patch)
tree78dcfe4ef90591870d54a7a92b905f5fc6872368 /glnx-dirfd.c
parente7f7081054311670411b8ad34f144c99822538c1 (diff)
downloadlibglnx-91e060699f5559c49335ce19f4b23ba70dfd6bb3.tar.gz
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.
Diffstat (limited to 'glnx-dirfd.c')
-rw-r--r--glnx-dirfd.c49
1 files changed, 49 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
*