These 2 internal functions allow mounting and unmounting of mountables
outside /sysroot.
---
daemon/daemon.h | 8 +++++
daemon/mount.c | 103 +++++++++++++++++++++++++++++++++++++++-----------------
2 files changed, 81 insertions(+), 30 deletions(-)
diff --git a/daemon/daemon.h b/daemon/daemon.h
index a94c338..78591a0 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -65,6 +65,14 @@ extern int xread (int sock, void *buf, size_t len)
extern char *mountable_to_string (const mountable_t *mountable);
+/*-- in mount.c --*/
+
+extern int mount_vfs_internal (const char *options, const char *vfstype,
+ const mountable_t *mountable,
+ const char *mp, const char *user_mp, char **err);
+extern int umount_internal (const char *pathordevice,
+ int force, int lazyunmount, char **err);
+
/* Growable strings buffer. */
struct stringsbuf {
char **argv;
diff --git a/daemon/mount.c b/daemon/mount.c
index 484e45c..34510bd 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -126,31 +126,44 @@ int
do_mount_vfs (const char *options, const char *vfstype,
const mountable_t *mountable, const char *mountpoint)
{
- int r;
- CLEANUP_FREE char *mp = NULL;
- CLEANUP_FREE char *error = NULL;
- struct stat statbuf;
-
ABS_PATH (mountpoint, , return -1);
- mp = sysroot_path (mountpoint);
+ CLEANUP_FREE char *mp = sysroot_path (mountpoint);
if (!mp) {
reply_with_perror ("malloc");
return -1;
}
/* Check the mountpoint exists and is a directory. */
+ struct stat statbuf;
if (stat (mp, &statbuf) == -1) {
reply_with_perror ("mount: %s", mountpoint);
return -1;
}
+
if (!S_ISDIR (statbuf.st_mode)) {
reply_with_perror ("mount: %s: mount point is not a directory",
mountpoint);
return -1;
}
+ CLEANUP_FREE char *err = NULL;
+ int r = mount_vfs_internal (options, vfstype, mountable,
+ mp, mountpoint, &err);
+
+ if (r == -1) {
+ reply_with_error ("%s", err ? err : "malloc");
+ }
+
+ return r;
+}
+
+int
+mount_vfs_internal (const char *options, const char *vfstype,
+ const mountable_t *mountable,
+ const char *mp, const char *user_mp,
+ char **err)
+{
CLEANUP_FREE char *options_plus = NULL;
- const char *device = mountable->device;
switch (mountable->type) {
case MOUNTABLE_DEVICE:
break;
@@ -160,24 +173,34 @@ do_mount_vfs (const char *options, const char *vfstype,
if (asprintf (&options_plus, "subvol=%s,%s",
mountable->volume, options) == -1)
{
- reply_with_perror ("asprintf");
+ /* No point trying to allocate more memory for an error message */
+ fprintf (stderr, "asprintf: %m\n");
return -1;
}
}
else {
if (asprintf (&options_plus, "subvol=%s", mountable->volume) ==
-1) {
- reply_with_perror ("asprintf");
+ /* No point trying to allocate more memory for an error message */
+ fprintf (stderr, "asprintf: %m\n");
return -1;
}
}
break;
default:
- reply_with_error ("Invalid mountable type: %i", mountable->type);
+ if (asprintf (err, "Invalid mountable type: %i", mountable->type) ==
-1)
+ {
+ /* No point trying to allocate more memory for an error message */
+ fprintf (stderr, "Invalid mountable type: %i", mountable->type);
+ fprintf (stderr, "asprintf: %m\n");
+ }
return -1;
}
+ CLEANUP_FREE char *error = NULL;
+ const char *device = mountable->device;
+ int r;
if (vfstype)
r = command (NULL, &error,
str_mount, "-o", options_plus ? options_plus : options,
@@ -186,9 +209,17 @@ do_mount_vfs (const char *options, const char *vfstype,
r = command (NULL, &error,
str_mount, "-o", options_plus ? options_plus : options,
device, mp, NULL);
+
if (r == -1) {
- reply_with_error ("%s on %s (options: '%s'): %s",
- device, mountpoint, options, error);
+ if (asprintf (err, "%s on %s (options: '%s'): %s",
+ device, user_mp, options_plus ? options_plus : options,
+ error) == -1)
+ {
+ /* No point trying to allocate more memory for an error message */
+ fprintf (stderr, "%s on %s (options: '%s'): %s",
+ device, user_mp, options_plus ? options_plus : options, error);
+ fprintf (stderr, "asprintf: %m\n");
+ }
return -1;
}
@@ -216,28 +247,35 @@ do_mount_options (const char *options, const mountable_t
*mountable,
/* Takes optional arguments, consult optargs_bitmask. */
int
-do_umount (const char *pathordevice,
- int force, int lazyunmount)
+do_umount (const char *pathordevice, int force, int lazyunmount)
{
- int r;
- CLEANUP_FREE char *err = NULL;
- CLEANUP_FREE char *buf = NULL;
- int is_dev;
- const char *argv[MAX_ARGS];
- size_t i = 0;
+ CLEANUP_FREE char *buf = STREQLEN (pathordevice, "/dev/", 5) ?
+ strdup (pathordevice) : sysroot_path (pathordevice);
- is_dev = STREQLEN (pathordevice, "/dev/", 5);
- buf = is_dev ? strdup (pathordevice)
- : sysroot_path (pathordevice);
if (buf == NULL) {
reply_with_perror ("malloc");
return -1;
}
- if (!(optargs_bitmask & GUESTFS_UMOUNT_FORCE_BITMASK))
- force = 0;
- if (!(optargs_bitmask & GUESTFS_UMOUNT_LAZYUNMOUNT_BITMASK))
- lazyunmount = 0;
+ if (!(optargs_bitmask & GUESTFS_UMOUNT_FORCE_BITMASK)) force = 0;
+ if (!(optargs_bitmask & GUESTFS_UMOUNT_LAZYUNMOUNT_BITMASK)) lazyunmount = 0;
+
+ CLEANUP_FREE char *err = NULL;
+ int r = umount_internal (buf, force, lazyunmount, &err);
+
+ if (r == -1) {
+ reply_with_error ("%s", err ? err : "malloc");
+ }
+
+ return r;
+}
+
+int
+umount_internal (const char *pathordevice, int force, int lazyunmount,
+ char **err)
+{
+ const char *argv[MAX_ARGS];
+ size_t i = 0;
/* Use the external /bin/umount program, so that /etc/mtab is kept
* updated.
@@ -249,13 +287,18 @@ do_umount (const char *pathordevice,
if (lazyunmount)
ADD_ARG (argv, i, "-l");
- ADD_ARG (argv, i, buf);
+ ADD_ARG (argv, i, pathordevice);
ADD_ARG (argv, i, NULL);
- r = commandv (NULL, &err, argv);
+ CLEANUP_FREE char *errout = NULL;
+ int r = commandv (NULL, &errout, argv);
if (r == -1) {
- reply_with_error ("%s: %s", pathordevice, err);
+ if (asprintf (err, "%s: %s", pathordevice, errout) == -1) {
+ /* No point trying to allocate more memory for an error message */
+ fprintf (stderr, "%s: %s\n", pathordevice, errout);
+ fprintf (stderr, "asprintf: %m\n");
+ }
return -1;
}
--
1.8.1