diff options
author | Jonathan Lebon <jlebon@redhat.com> | 2017-03-02 13:55:30 -0500 |
---|---|---|
committer | Jonathan Lebon <jlebon@redhat.com> | 2017-03-23 10:57:48 -0400 |
commit | 0c52d85e69310c6499a70a360a03fba2b4532677 (patch) | |
tree | 21a821222f1edbddfd4d3c328dae9bcf1da69e57 | |
parent | 602fdd93cb7a339c6b5749eee73df926429a5ab8 (diff) | |
download | libglnx-0c52d85e69310c6499a70a360a03fba2b4532677.tar.gz |
glnx-errors.h: add glnx_null_throw[_*] variants
These are equivalent to the non-null throw, except that the returned
value is a NULL pointer. They can be used in functions where one wants
to return a pointer. E.g.:
GKeyFile *foo(GError **error) {
return glnx_null_throw (error, "foobar");
}
The function call redirections are wrapped around a compound statement
expression[1] so that they represent a single top-level expression. This
allows us to avoid -Wunused-value warnings vs using a comma operator if
the return value isn't used.
I made the 'args...' absorb the fmt argument as well so that callers can
still use it without always having to specify at least one additional
variadic argument. I had to check to be sure that the expansion is all
done by the preprocessor, so we don't need to worry about stack
intricacies.
[1] https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
-rw-r--r-- | glnx-errors.h | 11 | ||||
-rw-r--r-- | glnx-fdio.c | 11 | ||||
-rw-r--r-- | tests/test-libglnx-errors.c | 48 |
3 files changed, 62 insertions, 8 deletions
diff --git a/glnx-errors.h b/glnx-errors.h index 8f9cad8..b891f96 100644 --- a/glnx-errors.h +++ b/glnx-errors.h @@ -49,6 +49,9 @@ glnx_throw (GError **error, const char *fmt, ...) return FALSE; } +/* Like glnx_throw(), but yields a NULL pointer. */ +#define glnx_null_throw(error, args...) \ + ({glnx_throw (error, args); NULL;}) /* Set @error using the value of `g_strerror (errno)`. * @@ -79,6 +82,10 @@ glnx_throw_errno (GError **error) return FALSE; } +/* Like glnx_throw_errno(), but yields a NULL pointer. */ +#define glnx_null_throw_errno(error) \ + ({glnx_throw_errno (error); NULL;}) + /* Implementation detail of glnx_throw_errno_prefix() */ void glnx_real_set_prefix_error_from_errno_va (GError **error, gint errsv, @@ -108,6 +115,10 @@ glnx_throw_errno_prefix (GError **error, const char *fmt, ...) return FALSE; } +/* Like glnx_throw_errno_prefix(), but yields a NULL pointer. */ +#define glnx_null_throw_errno_prefix(error, args...) \ + ({glnx_throw_errno_prefix (error, args); NULL;}) + /* BEGIN LEGACY APIS */ #define glnx_set_error_from_errno(error) \ diff --git a/glnx-fdio.c b/glnx-fdio.c index 68704cb..de3955c 100644 --- a/glnx-fdio.c +++ b/glnx-fdio.c @@ -555,25 +555,20 @@ glnx_readlinkat_malloc (int dfd, for (;;) { - char *c; + g_autofree char *c = NULL; ssize_t n; c = g_malloc (l); n = TEMP_FAILURE_RETRY (readlinkat (dfd, subpath, c, l-1)); if (n < 0) - { - glnx_set_error_from_errno (error); - g_free (c); - return FALSE; - } + return glnx_null_throw_errno (error); if ((size_t) n < l-1) { c[n] = 0; - return c; + return g_steal_pointer (&c); } - g_free (c); l *= 2; } diff --git a/tests/test-libglnx-errors.c b/tests/test-libglnx-errors.c index 8d109cd..7c7459c 100644 --- a/tests/test-libglnx-errors.c +++ b/tests/test-libglnx-errors.c @@ -33,6 +33,19 @@ test_error_throw (void) g_assert (!glnx_throw (&error, "foo: %s %d", "hello", 42)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); g_assert_cmpstr (error->message, ==, "foo: hello 42"); + g_clear_error (&error); + + gpointer dummy = glnx_null_throw (&error, "literal foo"); + g_assert (dummy == NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_assert_cmpstr (error->message, ==, "literal foo"); + g_clear_error (&error); + + gpointer dummy2 = glnx_null_throw (&error, "foo: %s %d", "hola", 24); + g_assert (dummy2 == NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_assert_cmpstr (error->message, ==, "foo: hola 24"); + g_clear_error (&error); } static void @@ -55,6 +68,17 @@ test_error_errno (void) fd = open (noent_path, O_RDONLY); if (fd < 0) { + gpointer dummy = glnx_null_throw_errno (&error); + g_assert (dummy == NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + g_clear_error (&error); + } + else + g_assert_cmpint (fd, ==, -1); + + fd = open (noent_path, O_RDONLY); + if (fd < 0) + { g_assert (!glnx_throw_errno_prefix (&error, "Failed to open %s", noent_path)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); g_assert (g_str_has_prefix (error->message, glnx_strjoina ("Failed to open ", noent_path))); @@ -62,6 +86,30 @@ test_error_errno (void) } else g_assert_cmpint (fd, ==, -1); + + fd = open (noent_path, O_RDONLY); + if (fd < 0) + { + gpointer dummy = glnx_null_throw_errno_prefix (&error, "Failed to open file"); + g_assert (dummy == NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + g_assert (g_str_has_prefix (error->message, "Failed to open file")); + g_clear_error (&error); + } + else + g_assert_cmpint (fd, ==, -1); + + fd = open (noent_path, O_RDONLY); + if (fd < 0) + { + gpointer dummy = glnx_null_throw_errno_prefix (&error, "Failed to open %s", noent_path); + g_assert (dummy == NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + g_assert (g_str_has_prefix (error->message, glnx_strjoina ("Failed to open ", noent_path))); + g_clear_error (&error); + } + else + g_assert_cmpint (fd, ==, -1); } int main (int argc, char **argv) |