Some of the oldest and most core APIs, reimplemented.
This also moves the strange ‘mount_vfs_nochroot’ function into
btrfs.c.
---
daemon/Makefile.am | 2 +
daemon/btrfs.c | 43 ++++++++++++++++++++
daemon/daemon.h | 6 ---
daemon/mount.c | 99 -----------------------------------------------
daemon/mount.ml | 62 +++++++++++++++++++++++++++++
daemon/mount.mli | 22 +++++++++++
generator/actions_core.ml | 4 ++
generator/daemon.ml | 3 +-
8 files changed, 135 insertions(+), 106 deletions(-)
create mode 100644 daemon/mount.ml
create mode 100644 daemon/mount.mli
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 215c7d694..c8e58ea20 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -258,6 +258,7 @@ SOURCES_MLI = \
file.mli \
is.mli \
link.mli \
+ mount.mli \
mountable.mli \
unix_utils.mli \
utils.mli
@@ -276,6 +277,7 @@ SOURCES_ML = \
file.ml \
is.ml \
link.ml \
+ mount.ml \
callbacks.ml \
daemon.ml
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index ae2310b53..f8c200112 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -37,6 +37,7 @@ GUESTFSD_EXT_CMD(str_btrfs, btrfs);
GUESTFSD_EXT_CMD(str_btrfstune, btrfstune);
GUESTFSD_EXT_CMD(str_btrfsck, btrfsck);
GUESTFSD_EXT_CMD(str_mkfs_btrfs, mkfs.btrfs);
+GUESTFSD_EXT_CMD(str_mount, mount);
GUESTFSD_EXT_CMD(str_umount, umount);
GUESTFSD_EXT_CMD(str_btrfsimage, btrfs-image);
@@ -387,6 +388,48 @@ do_btrfs_subvolume_create (const char *dest, const char *qgroupid)
return 0;
}
+static int
+mount_vfs_nochroot (const char *options, const char *vfstype,
+ const mountable_t *mountable,
+ const char *mp, const char *user_mp)
+{
+ CLEANUP_FREE char *options_plus = NULL;
+ const char *device = mountable->device;
+ if (mountable->type == MOUNTABLE_BTRFSVOL) {
+ if (options && strlen (options) > 0) {
+ if (asprintf (&options_plus, "subvol=%s,%s",
+ mountable->volume, options) == -1) {
+ reply_with_perror ("asprintf");
+ return -1;
+ }
+ }
+ else {
+ if (asprintf (&options_plus, "subvol=%s", mountable->volume) ==
-1) {
+ reply_with_perror ("asprintf");
+ return -1;
+ }
+ }
+ }
+
+ CLEANUP_FREE char *error = NULL;
+ int r;
+ if (vfstype)
+ r = command (NULL, &error,
+ str_mount, "-o", options_plus ? options_plus : options,
+ "-t", vfstype, device, mp, NULL);
+ else
+ 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, user_mp, options, error);
+ return -1;
+ }
+
+ return 0;
+}
+
static char *
mount (const mountable_t *fs)
{
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 42b77f0ca..151909a82 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -76,12 +76,6 @@ 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_nochroot (const char *options, const char *vfstype,
- const mountable_t *mountable,
- const char *mp, const char *user_mp);
-
/* Growable strings buffer. */
struct stringsbuf {
char **argv;
diff --git a/daemon/mount.c b/daemon/mount.c
index 0ad9626a7..962b86079 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -111,105 +111,6 @@ is_device_mounted (const char *device)
return 0;
}
-/* The "simple mount" call offers no complex options, you can just
- * mount a device on a mountpoint. The variations like mount_ro,
- * mount_options and mount_vfs let you set progressively more things.
- *
- * It's tempting to try a direct mount(2) syscall, but that doesn't
- * do any autodetection, so we are better off calling out to
- * /bin/mount.
- */
-
-int
-do_mount_vfs (const char *options, const char *vfstype,
- const mountable_t *mountable, const char *mountpoint)
-{
- CLEANUP_FREE char *mp = NULL;
- struct stat statbuf;
-
- ABS_PATH (mountpoint, 0, return -1);
-
- mp = sysroot_path (mountpoint);
- if (!mp) {
- reply_with_perror ("malloc");
- return -1;
- }
-
- /* Check the mountpoint exists and is a directory. */
- 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;
- }
-
- return mount_vfs_nochroot (options, vfstype, mountable, mp, mountpoint);
-}
-
-int
-mount_vfs_nochroot (const char *options, const char *vfstype,
- const mountable_t *mountable,
- const char *mp, const char *user_mp)
-{
- CLEANUP_FREE char *options_plus = NULL;
- const char *device = mountable->device;
- if (mountable->type == MOUNTABLE_BTRFSVOL) {
- if (options && strlen (options) > 0) {
- if (asprintf (&options_plus, "subvol=%s,%s",
- mountable->volume, options) == -1) {
- reply_with_perror ("asprintf");
- return -1;
- }
- }
-
- else {
- if (asprintf (&options_plus, "subvol=%s", mountable->volume) ==
-1) {
- reply_with_perror ("asprintf");
- return -1;
- }
- }
- }
-
- CLEANUP_FREE char *error = NULL;
- int r;
- if (vfstype)
- r = command (NULL, &error,
- str_mount, "-o", options_plus ? options_plus : options,
- "-t", vfstype, device, mp, NULL);
- else
- 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, user_mp, options, error);
- return -1;
- }
-
- return 0;
-}
-
-int
-do_mount (const mountable_t *mountable, const char *mountpoint)
-{
- return do_mount_vfs ("", NULL, mountable, mountpoint);
-}
-
-int
-do_mount_ro (const mountable_t *mountable, const char *mountpoint)
-{
- return do_mount_vfs ("ro", NULL, mountable, mountpoint);
-}
-
-int
-do_mount_options (const char *options, const mountable_t *mountable,
- const char *mountpoint)
-{
- return do_mount_vfs (options, NULL, mountable, mountpoint);
-}
-
/* Takes optional arguments, consult optargs_bitmask. */
int
do_umount (const char *pathordevice,
diff --git a/daemon/mount.ml b/daemon/mount.ml
new file mode 100644
index 000000000..665e79ae5
--- /dev/null
+++ b/daemon/mount.ml
@@ -0,0 +1,62 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Common_utils
+
+open Mountable
+open Utils
+
+let mount_vfs options vfs mountable mountpoint =
+ let mp = Sysroot.sysroot () // mountpoint in
+
+ (* Check the mountpoint exists and is a directory. *)
+ if not (is_directory mp) then
+ failwithf "mount: %s: mount point is not a directory" mountpoint;
+
+ let args = ref [] in
+
+ (* -o options *)
+ (match options, mountable.m_type with
+ | (None | Some ""), (MountableDevice | MountablePath) -> ()
+ | Some options, (MountableDevice | MountablePath) ->
+ push_back args "-o";
+ push_back args options
+ | (None | Some ""), MountableBtrfsVol subvol ->
+ push_back args "-o";
+ push_back args ("subvol=" ^ subvol)
+ | Some options, MountableBtrfsVol subvol ->
+ push_back args "-o";
+ push_back args ("subvol=" ^ subvol ^ "," ^ options)
+ );
+
+ (* -t vfs *)
+ (match vfs with
+ | None | Some "" -> ()
+ | Some t ->
+ push_back args "-t";
+ push_back args t
+ );
+
+ push_back args mountable.m_device;
+ push_back args mp;
+
+ ignore (command "mount" !args)
+
+let mount = mount_vfs None None
+let mount_ro = mount_vfs (Some "ro") None
+let mount_options options = mount_vfs (Some options) None
diff --git a/daemon/mount.mli b/daemon/mount.mli
new file mode 100644
index 000000000..e43d97c42
--- /dev/null
+++ b/daemon/mount.mli
@@ -0,0 +1,22 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+val mount : Mountable.t -> string -> unit
+val mount_ro : Mountable.t -> string -> unit
+val mount_options : string -> Mountable.t -> string -> unit
+val mount_vfs : string option -> string option -> Mountable.t -> string ->
unit
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index 7d6755fdc..f33bc5320 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -1739,6 +1739,7 @@ let daemon_functions = [
{ defaults with
name = "mount"; added = (0, 0, 3);
style = RErr, [String (Mountable, "mountable"); String (PlainString,
"mountpoint")], [];
+ impl = OCaml "Mount.mount";
tests = [
InitEmpty, Always, TestResultString (
[["part_disk"; "/dev/sda"; "mbr"];
@@ -2922,6 +2923,7 @@ If set to true, POSIX ACLs are saved in the output tar.
{ defaults with
name = "mount_ro"; added = (1, 0, 10);
style = RErr, [String (Mountable, "mountable"); String (PlainString,
"mountpoint")], [];
+ impl = OCaml "Mount.mount_ro";
tests = [
InitBasicFS, Always, TestLastFail (
[["umount"; "/"; "false"; "false"];
@@ -2941,6 +2943,7 @@ mounts the filesystem with the read-only (I<-o ro>)
flag." };
{ defaults with
name = "mount_options"; added = (1, 0, 10);
style = RErr, [String (PlainString, "options"); String (Mountable,
"mountable"); String (PlainString, "mountpoint")], [];
+ impl = OCaml "Mount.mount_options";
shortdesc = "mount a guest disk with mount options";
longdesc = "\
This is the same as the C<guestfs_mount> command, but it
@@ -2954,6 +2957,7 @@ the filesystem uses)." };
{ defaults with
name = "mount_vfs"; added = (1, 0, 10);
style = RErr, [String (PlainString, "options"); String (PlainString,
"vfstype"); String (Mountable, "mountable"); String (PlainString,
"mountpoint")], [];
+ impl = OCaml "Mount.mount_vfs";
shortdesc = "mount a guest disk with mount options and vfstype";
longdesc = "\
This is the same as the C<guestfs_mount> command, but it
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 060ab547e..65e49a9a1 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -685,7 +685,8 @@ return_string_list (value retv)
pr "\n";
(match ret with
- | RErr -> assert false
+ | RErr ->
+ pr " CAMLreturnT (int, 0);\n"
| RInt _ ->
pr " CAMLreturnT (int, Int_val (retv));\n"
| RInt64 _ -> assert false
--
2.13.0