12.08.2020 18:36, Andrey Shinkevich wrote:
For the appliance of the QCOW2 format, get the UUID of the disk by
reading the first 256k bytes with 'qemu-img dd' command. Then pass the
read block to the 'file' command. In case of failure, run the 'file'
command again directly.

Suggested-by: Denis V. Lunev <[email protected]>
Signed-off-by: Andrey Shinkevich <[email protected]>
---
v2:
   01: The order of the function calls to direct <file> command on the appliance
       and the indirect one (through the temporary file) has been swapped.

  lib/appliance-kcmdline.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++-
  1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/lib/appliance-kcmdline.c b/lib/appliance-kcmdline.c
index fbeb4f4..c78524b 100644
--- a/lib/appliance-kcmdline.c
+++ b/lib/appliance-kcmdline.c
@@ -71,7 +71,7 @@ read_uuid (guestfs_h *g, void *retv, const char *line, size_t 
len)
   * The L<file(1)> command does the hard work.
   */
  static char *
-get_root_uuid (guestfs_h *g, const char *appliance)
+do_get_root_uuid (guestfs_h *g, const char *appliance)
  {
    CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
    char *ret = NULL;
@@ -96,6 +96,74 @@ get_root_uuid (guestfs_h *g, const char *appliance)
  }
/**
+ * Read the first 256k bytes of the in_file with L<qemu-img(1)> command
+ * and write them into the out_file. That may be useful to get UUID of
+ * the QCOW2 disk image with further L<file(1)> command.
+ * The function returns zero if successful, otherwise -1.
+ */
+static int
+run_qemu_img_dd (guestfs_h *g, const char *in_file, char *out_file)
+{
+  CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
+  int r;
+
+  guestfs_int_cmd_add_arg (cmd, "qemu-img");
+  guestfs_int_cmd_add_arg (cmd, "dd");
+  guestfs_int_cmd_add_arg_format (cmd, "if=%s", in_file);
+  guestfs_int_cmd_add_arg_format (cmd, "of=%s", out_file);
+  guestfs_int_cmd_add_arg (cmd, "bs=256k");
+  guestfs_int_cmd_add_arg (cmd, "count=1");
+
+  r = guestfs_int_cmd_run (cmd);
+  if (r == -1) {
+    error (g, "Failed to run qemu-img");
+    return -1;
+  }
+  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
+    guestfs_int_external_command_failed (g, r, "qemu-img dd", NULL);
+    return -1;
+  }
+
+  return 0;
+}
+
+/**
+ * Get the UUID from the appliance disk image.
+ */
+static char *
+get_root_uuid (guestfs_h *g, const char *appliance)
+{
+  char *uuid = NULL;
+  int ret;
+  char tmp_file[] = "/tmp/libguestfsXXXXXX";
+
+  uuid = do_get_root_uuid (g, appliance);
+  if (uuid) {
+      return uuid;
+  }
+
+  if (!mktemp (tmp_file)) {
+    error (g, "get_root_uuid: mktemp failed");
+    return NULL;
+  }
+
+  ret = run_qemu_img_dd (g, appliance, tmp_file);
+  if (ret == 0) {
+    uuid = do_get_root_uuid (g, tmp_file);
+    if (uuid) {
+      goto out;
+    }
+  }
+
+  /* We get here in case of failure to extract UUID from the temporary file. */

Or if qemu-img dd failed (which is already reported).

A bit more native here seems to check error instead for checking success:

  ret = run_qemu_img_dd (g, appliance, tmp_file);
  if (ret < 0) {
    goto out;
  }

  uuid = do_get_root_uuid (g, tmp_file);
  if (!uuid) {
    error (g, "Failed to get the appliance UUID");
  }

out:
  unlink (tmp_file);
  return uuid;
}


+  error (g, "Failed to get the appliance UUID");
+
+out:
+  unlink (tmp_file);
+  return uuid;
+}
+
+/**
   * Construct the Linux command line passed to the appliance.  This is
   * used by the C<direct> and C<libvirt> backends, and is simply
   * located in this file because it's a convenient place for this


Still, good enough for me, and I was going to put Reviewed-by here, but noted 
new reply from Pino, so, you'll have to resend anyway.


--
Best regards,
Vladimir

_______________________________________________
Libguestfs mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libguestfs

Reply via email to