mirror of
https://github.com/flatpak/flatpak.git
synced 2026-03-28 11:54:01 -04:00
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.
This commit is contained in:
49
glnx-dirfd.c
49
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;
|
||||
|
||||
@@ -189,6 +191,53 @@ glnx_dirfd_iterator_next_dent (GLnxDirFdIterator *dfd_iter,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user