summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gsystem-file-utils.c94
-rw-r--r--src/gsystem-file-utils.h22
2 files changed, 116 insertions, 0 deletions
diff --git a/src/gsystem-file-utils.c b/src/gsystem-file-utils.c
index 30ccc9d..0528a13 100644
--- a/src/gsystem-file-utils.c
+++ b/src/gsystem-file-utils.c
@@ -1761,3 +1761,97 @@ gs_file_set_all_xattrs (GFile *file,
{
return set_all_xattrs_for_path (gs_file_get_path_cached (file), xattrs, cancellable, error);
}
+
+struct GsRealDirfdIterator
+{
+ gboolean initialized;
+ int fd;
+ DIR *d;
+};
+typedef struct GsRealDirfdIterator GsRealDirfdIterator;
+
+gboolean
+gs_dirfd_iterator_init_at (int dfd,
+ const char *path,
+ gboolean follow,
+ GSDirFdIterator *dfd_iter,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int fd = -1;
+
+ if (!gs_opendirat (dfd, path, follow, &fd, error))
+ goto out;
+
+ if (!gs_dirfd_iterator_init_take_fd (fd, dfd_iter, error))
+ goto out;
+ /* Transfer value */
+ fd = -1;
+
+ ret = TRUE;
+ out:
+ if (fd != -1) (void) close (fd);
+ return ret;
+}
+
+gboolean
+gs_dirfd_iterator_init_take_fd (int dfd,
+ GSDirFdIterator *dfd_iter,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GsRealDirfdIterator *real_dfd_iter = (GsRealDirfdIterator*) dfd_iter;
+ DIR *d = NULL;
+
+ d = fdopendir (dfd);
+ if (!d)
+ {
+ _set_error_from_errno ("fdopendir", error);
+ goto out;
+ }
+
+ real_dfd_iter->fd = dfd;
+ real_dfd_iter->d = d;
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+gs_dirfd_iterator_next_dent (GSDirFdIterator *dfd_iter,
+ struct dirent **out_dent,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GsRealDirfdIterator *real_dfd_iter = (GsRealDirfdIterator*) dfd_iter;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ goto out;
+
+ do
+ {
+ errno = 0;
+ *out_dent = readdir (real_dfd_iter->d);
+ if (*out_dent == NULL && errno != 0)
+ {
+ _set_error_from_errno ("fdopendir", error);
+ goto out;
+ }
+ } while (*out_dent &&
+ (strcmp ((*out_dent)->d_name, ".") == 0 ||
+ strcmp ((*out_dent)->d_name, "..") == 0));
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+void
+gs_dirfd_iterator_clear (GSDirFdIterator *dfd_iter)
+{
+ GsRealDirfdIterator *real_dfd_iter = (GsRealDirfdIterator*) dfd_iter;
+ /* fd is owned by dfd_iter */
+ (void) closedir (real_dfd_iter->d);
+}
diff --git a/src/gsystem-file-utils.h b/src/gsystem-file-utils.h
index 82b7070..32fa0cc 100644
--- a/src/gsystem-file-utils.h
+++ b/src/gsystem-file-utils.h
@@ -30,6 +30,28 @@ const char *gs_file_get_path_cached (GFile *file);
const char *gs_file_get_basename_cached (GFile *file);
+struct GSDirFdIterator {
+ gboolean initialized;
+ int fd;
+ gpointer padding_data[4];
+};
+
+typedef struct GSDirFdIterator GSDirFdIterator;
+gboolean gs_dirfd_iterator_init_at (int dfd, const char *path,
+ gboolean follow,
+ GSDirFdIterator *dfd_iter, GError **error);
+gboolean gs_dirfd_iterator_init_take_fd (int dfd, GSDirFdIterator *dfd_iter, GError **error);
+#ifndef __GI_SCANNER__
+gboolean gs_dirfd_iterator_next_dent (GSDirFdIterator *dfd_iter,
+ struct dirent **out_dent,
+ GCancellable *cancellable,
+ GError **error);
+#endif
+void gs_dirfd_iterator_clear (GSDirFdIterator *dfd_iter);
+
+#define gs_dirfd_iterator_cleanup __attribute__((cleanup(gs_dirfd_iterator_clear)))
+
+
gboolean gs_file_enumerator_iterate (GFileEnumerator *direnum,
GFileInfo **out_info,
GFile **out_child,