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