Skip to content
Snippets Groups Projects
Commit 627d4e2f authored by Colin Walters's avatar Colin Walters
Browse files

fdio: Add glnx_fstatat_allow_noent()

This is a very common pattern in both ostree/rpm-ostree. Make a better API for
this. I thought a lot about simply zeroing out `struct stat` but that feels
dangerous; none of the values have seem obviously `cannot be zero`.
parent 47d81632
No related branches found
No related tags found
No related merge requests found
...@@ -295,6 +295,44 @@ glnx_fstatat (int dfd, ...@@ -295,6 +295,44 @@ glnx_fstatat (int dfd,
return TRUE; return TRUE;
} }
/**
* glnx_fstatat_allow_noent:
* @dfd: Directory FD to stat beneath
* @path: Path to stat beneath @dfd
* @buf: (out caller-allocates): Return location for stat details
* @flags: Flags to pass to fstatat()
* @error: Return location for a #GError, or %NULL
*
* Like glnx_fstatat(), but handles `ENOENT` in a non-error way. Instead,
* on success `errno` will be zero, otherwise it will be preserved. Hence
* you can test `if (errno == 0)` to conditionalize on the file existing,
* or `if (errno == ENOENT)` for non-existence.
*
* Returns: %TRUE on success, %FALSE otherwise (errno is preserved)
* Since: UNRELEASED
*/
static inline gboolean
glnx_fstatat_allow_noent (int dfd,
const char *path,
struct stat *out_buf,
int flags,
GError **error)
{
if (TEMP_FAILURE_RETRY (fstatat (dfd, path, out_buf, flags)) != 0)
{
if (errno != ENOENT)
{
int errsv = errno;
(void) glnx_throw_errno_prefix (error, "fstatat(%s)", path);
errno = errsv;
return FALSE;
}
}
else
errno = 0;
return TRUE;
}
/** /**
* glnx_renameat: * glnx_renameat:
* *
......
...@@ -189,6 +189,27 @@ test_stdio_file (void) ...@@ -189,6 +189,27 @@ test_stdio_file (void)
g_assert_no_error (local_error); g_assert_no_error (local_error);
} }
static void
test_fstatat (void)
{
g_autoptr(GError) local_error = NULL;
GError **error = &local_error;
struct stat stbuf = { 0, };
if (!glnx_fstatat_allow_noent (AT_FDCWD, ".", &stbuf, 0, error))
goto out;
g_assert_cmpint (errno, ==, 0);
g_assert_no_error (local_error);
g_assert (S_ISDIR (stbuf.st_mode));
if (!glnx_fstatat_allow_noent (AT_FDCWD, "nosuchfile", &stbuf, 0, error))
goto out;
g_assert_cmpint (errno, ==, ENOENT);
g_assert_no_error (local_error);
out:
g_assert_no_error (local_error);
}
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
int ret; int ret;
...@@ -199,6 +220,7 @@ int main (int argc, char **argv) ...@@ -199,6 +220,7 @@ int main (int argc, char **argv)
g_test_add_func ("/stdio-file", test_stdio_file); g_test_add_func ("/stdio-file", test_stdio_file);
g_test_add_func ("/renameat2-noreplace", test_renameat2_noreplace); g_test_add_func ("/renameat2-noreplace", test_renameat2_noreplace);
g_test_add_func ("/renameat2-exchange", test_renameat2_exchange); g_test_add_func ("/renameat2-exchange", test_renameat2_exchange);
g_test_add_func ("/fstat", test_fstatat);
ret = g_test_run(); ret = g_test_run();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment