mirror of
https://github.com/flatpak/flatpak.git
synced 2026-03-28 20:02:36 -04:00
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`.
This commit is contained in:
38
glnx-fdio.h
38
glnx-fdio.h
@@ -295,6 +295,44 @@ glnx_fstatat (int dfd,
|
||||
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:
|
||||
*
|
||||
|
||||
@@ -189,6 +189,27 @@ test_stdio_file (void)
|
||||
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 ret;
|
||||
@@ -199,6 +220,7 @@ int main (int argc, char **argv)
|
||||
g_test_add_func ("/stdio-file", test_stdio_file);
|
||||
g_test_add_func ("/renameat2-noreplace", test_renameat2_noreplace);
|
||||
g_test_add_func ("/renameat2-exchange", test_renameat2_exchange);
|
||||
g_test_add_func ("/fstat", test_fstatat);
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user