diff options
author | Colin Walters <walters@verbum.org> | 2017-03-21 10:23:37 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2017-03-22 11:03:32 -0400 |
commit | 074236b88d0c742965fcca25a235fc79d3f87e48 (patch) | |
tree | 426e615726098628392b701e51389f5dd6752c2a | |
parent | c83ec7f213bd2e435043a435906e46aa9c0a2b6a (diff) | |
download | libglnx-074236b88d0c742965fcca25a235fc79d3f87e48.tar.gz |
errors: Add new glnx_throw_errno{,_prefix}() APIs
We have a *lot* of code of the form:
```
if (unlinkat (fd, pathname) < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
```
After conversion to `return FALSE style` which is in progress, it's way shorter,
and clearer like this:
```
if (unlinkat (fd, pathname) < 0)
return glnx_throw_errno (error);
```
-rw-r--r-- | glnx-dirfd.c | 6 | ||||
-rw-r--r-- | glnx-errors.c | 35 | ||||
-rw-r--r-- | glnx-errors.h | 79 |
3 files changed, 80 insertions, 40 deletions
diff --git a/glnx-dirfd.c b/glnx-dirfd.c index 11388c1..08d9007 100644 --- a/glnx-dirfd.c +++ b/glnx-dirfd.c @@ -68,8 +68,7 @@ glnx_opendirat (int dfd, int ret = glnx_opendirat_with_errno (dfd, path, follow); if (ret == -1) { - glnx_set_prefix_error_from_errno (error, "%s", "openat"); - return FALSE; + return glnx_throw_errno_prefix (error, "openat"); } *out_fd = ret; return TRUE; @@ -339,8 +338,7 @@ glnx_mkdtempat (int dfd, /* Any other error will apply also to other names we might * try, and there are 2^32 or so of them, so give up now. */ - glnx_set_prefix_error_from_errno (error, "%s", "mkdirat"); - return FALSE; + return glnx_throw_errno_prefix (error, "mkdirat"); } return TRUE; diff --git a/glnx-errors.c b/glnx-errors.c index ab7bc0a..edbce20 100644 --- a/glnx-errors.c +++ b/glnx-errors.c @@ -24,30 +24,21 @@ #include <glnx-errors.h> void -glnx_real_set_prefix_error_from_errno (GError **error, - gint errsv, - const char *format, - ...) +glnx_real_set_prefix_error_from_errno_va (GError **error, + gint errsv, + const char *format, + va_list args) { if (!error) return; - else - { - GString *buf = g_string_new (""); - va_list args; - - va_start (args, format); - g_string_append_vprintf (buf, format, args); - va_end (args); - g_string_append (buf, ": "); - g_string_append (buf, g_strerror (errsv)); - - g_set_error_literal (error, - G_IO_ERROR, - g_io_error_from_errno (errsv), - buf->str); - g_string_free (buf, TRUE); - errno = errsv; - } + /* TODO - enhance GError to have a "set and take ownership" API */ + g_autoptr(GString) buf = g_string_new (""); + g_string_append_vprintf (buf, format, args); + g_string_append (buf, ": "); + g_string_append (buf, g_strerror (errsv)); + g_set_error_literal (error, + G_IO_ERROR, + g_io_error_from_errno (errsv), + buf->str); } diff --git a/glnx-errors.h b/glnx-errors.h index fffef6c..7bf53d3 100644 --- a/glnx-errors.h +++ b/glnx-errors.h @@ -25,25 +25,76 @@ G_BEGIN_DECLS +/* Set @error using the value of `g_strerror (errno)`. + * + * This function returns %FALSE so it can be used conveniently in a single + * statement: + * + * `` + * if (unlinkat (fd, somepathname) < 0) + * return glnx_throw_errno (error); + * ``` + */ +static inline gboolean +glnx_throw_errno (GError **error) +{ + /* Save the value of errno, in case one of the + * intermediate function calls happens to set it. + */ + int errsv = errno; + g_set_error_literal (error, G_IO_ERROR, + g_io_error_from_errno (errsv), + g_strerror (errsv)); + /* We also restore the value of errno, since that's + * what was done in a long-ago libgsystem commit + * https://git.gnome.org/browse/libgsystem/commit/?id=ed106741f7a0596dc8b960b31fdae671d31d666d + * but I certainly can't remember now why I did that. + */ + errno = errsv; + return FALSE; +} + +/* Implementation detail of glnx_throw_errno_prefix() */ +void glnx_real_set_prefix_error_from_errno_va (GError **error, + gint errsv, + const char *format, + va_list args) G_GNUC_PRINTF (3,0); + +/* Set @error using the value of `$prefix: g_strerror (errno)` where `$prefix` + * is computed via printf @fmt. + * + * This function returns %FALSE so it can be used conveniently in a single + * statement: + * + * ``` + * return glnx_throw_errno_prefix (error, "unlinking %s", pathname); + * ``` + */ +static inline gboolean G_GNUC_PRINTF (2,3) +glnx_throw_errno_prefix (GError **error, const char *fmt, ...) +{ + int errsv = errno; + va_list args; + va_start (args, fmt); + glnx_real_set_prefix_error_from_errno_va (error, errsv, fmt, args); + va_end (args); + /* See comment above about preserving errno */ + errno = errsv; + return FALSE; +} + +/* BEGIN LEGACY APIS */ + #define glnx_set_error_from_errno(error) \ do { \ - int errsv = errno; \ - g_set_error_literal (error, G_IO_ERROR, \ - g_io_error_from_errno (errsv), \ - g_strerror (errsv)); \ - errno = errsv; \ + glnx_throw_errno (error); \ } while (0); -#define glnx_set_prefix_error_from_errno(error, format, args...) \ - do { \ - int errsv = errno; \ - glnx_real_set_prefix_error_from_errno (error, errsv, format, args); \ - errno = errsv; \ +#define glnx_set_prefix_error_from_errno(error, format, args...) \ + do { \ + glnx_set_error_from_errno (error); \ + g_prefix_error (error, format, args); \ } while (0); -void glnx_real_set_prefix_error_from_errno (GError **error, - gint errsv, - const char *format, - ...) G_GNUC_PRINTF (3,4); G_END_DECLS |