[Libguestfs] [PATCH 05/12] mountable: Implement Mountable_or_Path

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


A Mountable_or_Path argument is passed as a mountable_t. A new type is
added to mountable_t to handle already mounted paths.
---
 daemon/daemon.h     | 45 +++++++++++++++++++++++++++++++++------------
 daemon/guestfsd.c   | 26 ++++++++++++++++++++++++++
 generator/c.ml      |  6 +++---
 generator/daemon.ml | 14 +++++++-------
 4 files changed, 69 insertions(+), 22 deletions(-)

diff --git a/daemon/daemon.h b/daemon/daemon.h
index 502e0eb..a94c338 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -32,6 +32,20 @@
 
 #include "guestfs-internal-all.h"
 
+/* Mountables */
+
+typedef enum {
+  MOUNTABLE_DEVICE,     /* A bare device */
+  MOUNTABLE_BTRFSVOL,   /* A btrfs subvolume: device + volume */
+  MOUNTABLE_PATH        /* An already mounted path: device = path */
+} mountable_type_t;
+
+typedef struct {
+  mountable_type_t type;
+  const char *device;
+  const char *volume;
+} mountable_t;
+
 /*-- in guestfsd.c --*/
 extern int verbose;
 
@@ -49,18 +63,7 @@ extern int xwrite (int sock, const void *buf, size_t len)
 extern int xread (int sock, void *buf, size_t len)
   __attribute__((__warn_unused_result__));
 
-/* Mountables */
-
-typedef enum {
-  MOUNTABLE_DEVICE,
-  MOUNTABLE_BTRFSVOL
-} mountable_type_t;
-
-typedef struct {
-  mountable_type_t type;
-  const char *device;
-  const char *volume;
-} mountable_t;
+extern char *mountable_to_string (const mountable_t *mountable);
 
 /* Growable strings buffer. */
 struct stringsbuf {
@@ -391,6 +394,24 @@ is_zero (const char *buffer, size_t size)
     }									\
   } while (0)
 
+/* Helper for functions which need either an absolute path in the
+ * mounted filesystem, OR a valid mountable description.
+ */
+#define REQUIRE_ROOT_OR_RESOLVE_MOUNTABLE(string, mountable,            \
+                                          cancel_stmt, fail_stmt)       \
+  do {                                                                  \
+    if (STREQLEN ((string), "/dev/", strlen ("/dev/")) || (string)[0] != '/') {\
+      RESOLVE_MOUNTABLE (string, mountable, cancel_stmt, fail_stmt);    \
+    }                                                                   \
+                                                                        \
+    else {                                                              \
+      NEED_ROOT (cancel_stmt, fail_stmt);                               \
+      (mountable).type = MOUNTABLE_PATH;                                \
+      (mountable).device = (string);                                    \
+    }                                                                   \
+  } while (0)                                                           \
+
+
 /* NB:
  * (1) You must match CHROOT_IN and CHROOT_OUT even along error paths.
  * (2) You must not change directory!  cwd must always be "/", otherwise
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 02454e3..74c7dfc 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -1221,6 +1221,32 @@ parse_btrfsvol (char *desc, mountable_t *mountable)
   return 0;
 }
 
+/* Convert a mountable_t back to its string representation
+ *
+ * This function can be used in an error path, and must not call
+ * reply_with_error().
+ */
+char *
+mountable_to_string (const mountable_t *mountable)
+{
+  char *desc;
+
+  switch (mountable->type) {
+    case MOUNTABLE_DEVICE:
+    case MOUNTABLE_PATH:
+      return strdup (mountable->device);
+
+    case MOUNTABLE_BTRFSVOL:
+      if (asprintf(&desc, "btrfsvol:%s/%s",
+                   mountable->device, mountable->volume) == -1)
+        return NULL;
+      return desc;
+
+    default:
+      return NULL;
+  }
+}
+
 /* Check program exists and is executable on $PATH.  Actually, we
  * just assume PATH contains the default entries (see main() above).
  */
diff --git a/generator/c.ml b/generator/c.ml
index d42b5b1..ad4ee44 100644
--- a/generator/c.ml
+++ b/generator/c.ml
@@ -121,13 +121,13 @@ let rec generate_prototype ?(extern = true) ?(static = false)
     List.iter (
       function
       | Pathname n
-      | Device n | Dev_or_Path n | Mountable_or_Path n
+      | Device n | Dev_or_Path n
       | String n
       | OptString n
       | Key n ->
           next ();
           pr "const char *%s" n
-      | Mountable n ->
+      | Mountable n | Mountable_or_Path n ->
           next();
           if in_daemon then
             pr "const mountable_t *%s" n
@@ -183,7 +183,7 @@ and generate_c_call_args ?handle ?(implicit_size_ptr = "&size")
     | BufferIn n ->
         next ();
         pr "%s, %s_size" n n
-    | Mountable n ->
+    | Mountable n | Mountable_or_Path n ->
         next ();
         pr (if in_daemon then "&%s" else "%s") n
     | arg ->
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 1d2f9fb..704deb6 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -112,12 +112,9 @@ and generate_daemon_actions () =
         pr "  struct guestfs_%s_args args;\n" name;
         List.iter (
           function
-          | Device n | Dev_or_Path n | Mountable_or_Path n
-          | Pathname n
-          | String n
-          | Key n
-          | OptString n -> pr "  char *%s;\n" n
-          | Mountable n -> pr "  mountable_t %s;\n" n
+          | Device n | Dev_or_Path n
+          | Pathname n | String n | Key n | OptString n -> pr "  char *%s;\n" n
+          | Mountable n | Mountable_or_Path n -> pr "  mountable_t %s;\n" n
           | StringList n | DeviceList n -> pr "  char **%s;\n" n
           | Bool n -> pr "  int %s;\n" n
           | Int n -> pr "  int %s;\n" n
@@ -214,10 +211,13 @@ and generate_daemon_actions () =
           | Mountable n ->
               pr "  RESOLVE_MOUNTABLE(args.%s, %s, %s, goto done);\n"
                 n n (if is_filein then "cancel_receive ()" else "");
-          | Dev_or_Path n | Mountable_or_Path n ->
+          | Dev_or_Path n ->
               pr_args n;
               pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
                 n (if is_filein then "cancel_receive ()" else "");
+          | Mountable_or_Path n ->
+              pr "  REQUIRE_ROOT_OR_RESOLVE_MOUNTABLE(args.%s, %s, %s, goto done);\n"
+                n n (if is_filein then "cancel_receive ()" else "");
           | String n | Key n -> pr_args n
           | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
           | StringList n ->
-- 
1.8.1




More information about the Libguestfs mailing list