[Libguestfs] [PATCH 07/12] btrfs: Update btrfs_subvolume_list to take Mountable_or_Path

Matthew Booth mbooth at redhat.com
Thu Feb 7 15:57:53 UTC 2013


btrfs_subvolume_list can now take either the path of a mounted btrfs
filesystem, or a mountable describing the location of a btrfs
filesystem, or one of its volumes. In the latter case, the filesystem
will be automatically mounted outside of /sysroot before running the
btrfs tool, and unmounted afterwards.
---
 daemon/btrfs.c       | 72 ++++++++++++++++++++++++++++++++++++++++++++--------
 generator/actions.ml |  2 +-
 2 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index 81ce5f5..2c30926 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -307,16 +307,49 @@ do_btrfs_subvolume_create (const char *dest)
 }
 
 guestfs_int_btrfssubvolume_list *
-do_btrfs_subvolume_list (const char *fs)
+do_btrfs_subvolume_list (const mountable_t *fs)
 {
   char **lines;
 
   /* Execute 'btrfs subvolume list <fs>', and split the output into lines */
   {
-    CLEANUP_FREE char *fs_buf = sysroot_path (fs);
-    if (fs_buf == NULL) {
-      reply_with_perror ("malloc");
-      return NULL;
+    CLEANUP_FREE char *fs_buf = NULL;
+
+    if (fs->type == MOUNTABLE_PATH) {
+      fs_buf = sysroot_path (fs->device);
+      if (fs_buf == NULL) {
+        reply_with_perror ("malloc");
+
+      cmderror:
+        if (fs->type != MOUNTABLE_PATH && fs_buf) {
+          CLEANUP_FREE char *err = NULL;
+          if (umount_internal (fs_buf, 1, 0, &err) == -1)
+            fprintf (stderr, "%s\n", err);
+
+          if (rmdir (fs_buf) == -1 && errno != ENOENT)
+            fprintf (stderr, "rmdir: %m\n");
+        }
+        return NULL;
+      }
+    }
+
+    else {
+      fs_buf = strdup ("/tmp/btrfs.XXXXXX");
+      if (fs_buf == NULL) {
+        reply_with_perror ("strdup");
+        goto cmderror;
+      }
+
+      if (mkdtemp (fs_buf) == NULL) {
+        reply_with_perror ("mkdtemp");
+        goto cmderror;
+      }
+
+      CLEANUP_FREE char *err = NULL;
+      if (mount_vfs_internal ("", NULL, fs, fs_buf, "<internal>", &err) == -1) {
+        reply_with_error ("%s", err ? err : "malloc");
+        goto cmderror;
+      }
     }
 
     size_t i = 0;
@@ -328,16 +361,33 @@ do_btrfs_subvolume_list (const char *fs)
     ADD_ARG (argv, i, fs_buf);
     ADD_ARG (argv, i, NULL);
 
-    CLEANUP_FREE char *out = NULL, *err = NULL;
-    int r = commandv (&out, &err, argv);
+    CLEANUP_FREE char *out = NULL, *errout = NULL;
+    int r = commandv (&out, &errout, argv);
+
+    if (fs->type != MOUNTABLE_PATH) {
+      CLEANUP_FREE char *err = NULL;
+      if (umount_internal (fs_buf, 1, 0, &err) == -1) {
+        reply_with_error ("%s", err ? err : "malloc");
+        goto cmderror;
+      }
+
+      if (rmdir (fs_buf) == -1 && errno != ENOENT) {
+        reply_with_error ("rmdir: %m\n");
+        goto cmderror;
+      }
+    }
+
     if (r == -1) {
-      reply_with_error ("%s: %s", fs, err);
-      return NULL;
+      CLEANUP_FREE char *fs_desc = mountable_to_string (fs);
+      if (fs_desc == NULL) {
+        fprintf (stderr, "malloc: %m");
+      }
+      reply_with_error ("%s: %s", fs_desc ? fs_desc : "malloc", errout);
+      goto cmderror;
     }
 
     lines = split_lines (out);
-    if (!lines)
-      return NULL;
+    if (!lines) return NULL;
   }
 
   /* Output is:
diff --git a/generator/actions.ml b/generator/actions.ml
index 4f613db..86f58ea 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -9514,7 +9514,7 @@ directory and the name of the snapshot, in the form C</path/to/dest/name>." };
 
   { defaults with
     name = "btrfs_subvolume_list";
-    style = RStructList ("subvolumes", "btrfssubvolume"), [Pathname "fs"], [];
+    style = RStructList ("subvolumes", "btrfssubvolume"), [Mountable_or_Path "fs"], [];
     proc_nr = Some 325;
     optional = Some "btrfs"; camel_name = "BTRFSSubvolumeList";
     tests = [] (* tested in tests/btrfs *);
-- 
1.8.1




More information about the Libguestfs mailing list