[libglnx] dirfd: Add a public API to ensure a filled dtype
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libglnx] dirfd: Add a public API to ensure a filled dtype
- Date: Sun, 3 Jan 2016 12:59:13 +0000 (UTC)
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]