[Libguestfs] [PATCH 4/6] lib: qemu: improve handling of FILE*

Pino Toscano ptoscano at redhat.com
Mon Mar 6 14:42:49 UTC 2017


Create own blocks for all the parts dealing with FILE*: this way there
is no need to recycle the same FILE* variable for all the operations,
and have each block its own variable automatically cleaned up.

This also fixes a potential undefined behaviour on error: POSIX says
that after a call fclose(), a FILE* cannot be used anymore, not even
on fclose() failure. The previous behaviour for fclose == -1 was to jump
to the error label, which would then try to call fclose() again (since
the FILE* pointer was still non-null).
---
 lib/qemu.c | 104 ++++++++++++++++++++++++++++++-------------------------------
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/lib/qemu.c b/lib/qemu.c
index e61bc3c..d60692f 100644
--- a/lib/qemu.c
+++ b/lib/qemu.c
@@ -80,7 +80,6 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
   struct stat statbuf;
   CLEANUP_FREE char *cachedir = NULL, *qemu_stat_filename = NULL,
     *qemu_help_filename = NULL, *qemu_devices_filename = NULL;
-  FILE *fp;
   int generation;
   uint64_t prev_size, prev_mtime;
 
@@ -101,15 +100,16 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
   debug (g, "checking for previously cached test results of %s, in %s",
          g->hv, cachedir);
 
-  fp = fopen (qemu_stat_filename, "r");
-  if (fp == NULL)
-    goto do_test;
-  if (fscanf (fp, "%d %" SCNu64 " %" SCNu64,
-              &generation, &prev_size, &prev_mtime) != 3) {
-    fclose (fp);
-    goto do_test;
+  {
+    CLEANUP_FCLOSE FILE *fp = NULL;
+    fp = fopen (qemu_stat_filename, "r");
+    if (fp == NULL)
+      goto do_test;
+    if (fscanf (fp, "%d %" SCNu64 " %" SCNu64,
+                &generation, &prev_size, &prev_mtime) != 3) {
+      goto do_test;
+    }
   }
-  fclose (fp);
 
   if (generation == MEMO_GENERATION &&
       (uint64_t) statbuf.st_size == prev_size &&
@@ -153,54 +153,54 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
   /* Now memoize the qemu output in the cache directory. */
   debug (g, "saving test results");
 
-  fp = fopen (qemu_help_filename, "w");
-  if (fp == NULL) {
-  help_error:
-    perrorf (g, "%s", qemu_help_filename);
-    if (fp != NULL) fclose (fp);
-    guestfs_int_free_qemu_data (data);
-    return NULL;
+  {
+    CLEANUP_FCLOSE FILE *fp = NULL;
+    fp = fopen (qemu_help_filename, "w");
+    if (fp == NULL) {
+    help_error:
+      perrorf (g, "%s", qemu_help_filename);
+      guestfs_int_free_qemu_data (data);
+      return NULL;
+    }
+    if (fprintf (fp, "%s", data->qemu_help) == -1)
+      goto help_error;
   }
-  if (fprintf (fp, "%s", data->qemu_help) == -1)
-    goto help_error;
-  if (fclose (fp) == -1)
-    goto help_error;
 
-  fp = fopen (qemu_devices_filename, "w");
-  if (fp == NULL) {
-  devices_error:
-    perrorf (g, "%s", qemu_devices_filename);
-    if (fp != NULL) fclose (fp);
-    guestfs_int_free_qemu_data (data);
-    return NULL;
+  {
+    CLEANUP_FCLOSE FILE *fp = NULL;
+    fp = fopen (qemu_devices_filename, "w");
+    if (fp == NULL) {
+    devices_error:
+      perrorf (g, "%s", qemu_devices_filename);
+      guestfs_int_free_qemu_data (data);
+      return NULL;
+    }
+    if (fprintf (fp, "%s", data->qemu_devices) == -1)
+      goto devices_error;
   }
-  if (fprintf (fp, "%s", data->qemu_devices) == -1)
-    goto devices_error;
-  if (fclose (fp) == -1)
-    goto devices_error;
 
-  /* Write the qemu.stat file last so that its presence indicates that
-   * the qemu.help and qemu.devices files ought to exist.
-   */
-  fp = fopen (qemu_stat_filename, "w");
-  if (fp == NULL) {
-  stat_error:
-    perrorf (g, "%s", qemu_stat_filename);
-    if (fp != NULL) fclose (fp);
-    guestfs_int_free_qemu_data (data);
-    return NULL;
+  {
+    /* Write the qemu.stat file last so that its presence indicates that
+     * the qemu.help and qemu.devices files ought to exist.
+     */
+    CLEANUP_FCLOSE FILE *fp = NULL;
+    fp = fopen (qemu_stat_filename, "w");
+    if (fp == NULL) {
+    stat_error:
+      perrorf (g, "%s", qemu_stat_filename);
+      guestfs_int_free_qemu_data (data);
+      return NULL;
+    }
+    /* The path to qemu is stored for information only, it is not
+     * used when we parse the file.
+     */
+    if (fprintf (fp, "%d %" PRIu64 " %" PRIu64 " %s\n",
+                 MEMO_GENERATION,
+                 (uint64_t) statbuf.st_size,
+                 (uint64_t) statbuf.st_mtime,
+                 g->hv) == -1)
+      goto stat_error;
   }
-  /* The path to qemu is stored for information only, it is not
-   * used when we parse the file.
-   */
-  if (fprintf (fp, "%d %" PRIu64 " %" PRIu64 " %s\n",
-               MEMO_GENERATION,
-               (uint64_t) statbuf.st_size,
-               (uint64_t) statbuf.st_mtime,
-               g->hv) == -1)
-    goto stat_error;
-  if (fclose (fp) == -1)
-    goto stat_error;
 
   return data;
 }
-- 
2.9.3




More information about the Libguestfs mailing list