[libglnx] errors: Add new glnx_throw_errno{,_prefix}() APIs



commit 074236b88d0c742965fcca25a235fc79d3f87e48
Author: Colin Walters <walters verbum org>
Date:   Tue Mar 21 10:23:37 2017 -0400

    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);
    ```

 glnx-dirfd.c  |    6 +---
 glnx-errors.c |   35 +++++++++----------------
 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]