From 79cdf81e2fb717ea4372a55170d16800cdbddf23 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Wed, 22 Apr 2009 21:02:49 +0100 Subject: [PATCH] Generated code for new mount_* commands. --- daemon/actions.h | 3 + daemon/stubs.c | 93 +++++++++++ fish/cmds.c | 75 +++++++++ fish/completion.c | 3 + guestfish-actions.pod | 23 +++ guestfs-actions.pod | 38 +++++ java/com/redhat/et/libguestfs/GuestFS.java | 56 +++++++ java/com_redhat_et_libguestfs_GuestFS.c | 69 ++++++++ ocaml/guestfs.ml | 3 + ocaml/guestfs.mli | 9 ++ ocaml/guestfs_c_actions.c | 75 +++++++++ perl/Guestfs.xs | 39 +++++ perl/lib/Sys/Guestfs.pm | 17 ++ python/guestfs-py.c | 84 ++++++++++ python/guestfs.py | 20 +++ ruby/ext/guestfs/_guestfs.c | 93 +++++++++++ src/guestfs-actions.c | 252 +++++++++++++++++++++++++++++ src/guestfs-actions.h | 3 + src/guestfs_protocol.c | 42 +++++ src/guestfs_protocol.h | 32 +++- src/guestfs_protocol.x | 21 +++ tests.c | 162 ++++++++++++++++++- 22 files changed, 1210 insertions(+), 2 deletions(-) diff --git a/daemon/actions.h b/daemon/actions.h index d55f493..2cd7f3d 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -93,3 +93,6 @@ extern int do_tar_in (const char *directory); extern int do_tar_out (const char *directory); extern int do_tgz_in (const char *directory); extern int do_tgz_out (const char *directory); +extern int do_mount_ro (const char *device, const char *mountpoint); +extern int do_mount_options (const char *options, const char *device, const char *mountpoint); +extern int do_mount_vfs (const char *options, const char *vfstype, const char *device, const char *mountpoint); diff --git a/daemon/stubs.c b/daemon/stubs.c index 8201641..e9d9f59 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -1757,6 +1757,90 @@ done: xdr_free ((xdrproc_t) xdr_guestfs_tgz_out_args, (char *) &args); } +static void mount_ro_stub (XDR *xdr_in) +{ + int r; + struct guestfs_mount_ro_args args; + const char *device; + const char *mountpoint; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_mount_ro_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "mount_ro"); + return; + } + device = args.device; + mountpoint = args.mountpoint; + + r = do_mount_ro (device, mountpoint); + if (r == -1) + /* do_mount_ro has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_mount_ro_args, (char *) &args); +} + +static void mount_options_stub (XDR *xdr_in) +{ + int r; + struct guestfs_mount_options_args args; + const char *options; + const char *device; + const char *mountpoint; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_mount_options_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "mount_options"); + return; + } + options = args.options; + device = args.device; + mountpoint = args.mountpoint; + + r = do_mount_options (options, device, mountpoint); + if (r == -1) + /* do_mount_options has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_mount_options_args, (char *) &args); +} + +static void mount_vfs_stub (XDR *xdr_in) +{ + int r; + struct guestfs_mount_vfs_args args; + const char *options; + const char *vfstype; + const char *device; + const char *mountpoint; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_mount_vfs_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "mount_vfs"); + return; + } + options = args.options; + vfstype = args.vfstype; + device = args.device; + mountpoint = args.mountpoint; + + r = do_mount_vfs (options, vfstype, device, mountpoint); + if (r == -1) + /* do_mount_vfs has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_mount_vfs_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -1976,6 +2060,15 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_TGZ_OUT: tgz_out_stub (xdr_in); break; + case GUESTFS_PROC_MOUNT_RO: + mount_ro_stub (xdr_in); + break; + case GUESTFS_PROC_MOUNT_OPTIONS: + mount_options_stub (xdr_in); + break; + case GUESTFS_PROC_MOUNT_VFS: + mount_vfs_stub (xdr_in); + break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr); } diff --git a/fish/cmds.c b/fish/cmds.c index 6c66f0a..ff20c82 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -92,6 +92,9 @@ void list_commands (void) printf ("%-20s %s\n", "mkdir-p", "create a directory and parents"); printf ("%-20s %s\n", "mkfs", "make a filesystem"); printf ("%-20s %s\n", "mount", "mount a guest disk at a position in the filesystem"); + printf ("%-20s %s\n", "mount-options", "mount a guest disk with mount options"); + printf ("%-20s %s\n", "mount-ro", "mount a guest disk, read-only"); + printf ("%-20s %s\n", "mount-vfs", "mount a guest disk with mount options and vfstype"); printf ("%-20s %s\n", "mounts", "show mounted filesystems"); printf ("%-20s %s\n", "pvcreate", "create an LVM physical volume"); printf ("%-20s %s\n", "pvs", "list the LVM physical volumes (PVs)"); @@ -396,6 +399,15 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "tgz_out") == 0 || strcasecmp (cmd, "tgz-out") == 0) pod2text ("tgz-out - pack directory into compressed tarball", " tgz-out \n\nThis command packs the contents of C and downloads\nit to local file C.\n\nTo download an uncompressed tarball, use C."); else + if (strcasecmp (cmd, "mount_ro") == 0 || strcasecmp (cmd, "mount-ro") == 0) + pod2text ("mount-ro - mount a guest disk, read-only", " mount-ro \n\nThis is the same as the C command, but it\nmounts the filesystem with the read-only (I<-o ro>) flag."); + else + if (strcasecmp (cmd, "mount_options") == 0 || strcasecmp (cmd, "mount-options") == 0) + pod2text ("mount-options - mount a guest disk with mount options", " mount-options \n\nThis is the same as the C command, but it\nallows you to set the mount options as for the\nL I<-o> flag."); + else + if (strcasecmp (cmd, "mount_vfs") == 0 || strcasecmp (cmd, "mount-vfs") == 0) + pod2text ("mount-vfs - mount a guest disk with mount options and vfstype", " mount-vfs \n\nThis is the same as the C command, but it\nallows you to set both the mount options and the vfstype\nas for the L I<-o> and I<-t> flags."); + else display_builtin_command (cmd); } @@ -1917,6 +1929,60 @@ static int run_tgz_out (const char *cmd, int argc, char *argv[]) return r; } +static int run_mount_ro (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *device; + const char *mountpoint; + if (argc != 2) { + fprintf (stderr, "%s should have 2 parameter(s)\n", cmd); + fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd); + return -1; + } + device = argv[0]; + mountpoint = argv[1]; + r = guestfs_mount_ro (g, device, mountpoint); + return r; +} + +static int run_mount_options (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *options; + const char *device; + const char *mountpoint; + if (argc != 3) { + fprintf (stderr, "%s should have 3 parameter(s)\n", cmd); + fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd); + return -1; + } + options = argv[0]; + device = argv[1]; + mountpoint = argv[2]; + r = guestfs_mount_options (g, options, device, mountpoint); + return r; +} + +static int run_mount_vfs (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *options; + const char *vfstype; + const char *device; + const char *mountpoint; + if (argc != 4) { + fprintf (stderr, "%s should have 4 parameter(s)\n", cmd); + fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd); + return -1; + } + options = argv[0]; + vfstype = argv[1]; + device = argv[2]; + mountpoint = argv[3]; + r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint); + return r; +} + int run_action (const char *cmd, int argc, char *argv[]) { if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0) @@ -2189,6 +2255,15 @@ int run_action (const char *cmd, int argc, char *argv[]) if (strcasecmp (cmd, "tgz_out") == 0 || strcasecmp (cmd, "tgz-out") == 0) return run_tgz_out (cmd, argc, argv); else + if (strcasecmp (cmd, "mount_ro") == 0 || strcasecmp (cmd, "mount-ro") == 0) + return run_mount_ro (cmd, argc, argv); + else + if (strcasecmp (cmd, "mount_options") == 0 || strcasecmp (cmd, "mount-options") == 0) + return run_mount_options (cmd, argc, argv); + else + if (strcasecmp (cmd, "mount_vfs") == 0 || strcasecmp (cmd, "mount-vfs") == 0) + return run_mount_vfs (cmd, argc, argv); + else { fprintf (stderr, "%s: unknown command\n", cmd); return -1; diff --git a/fish/completion.c b/fish/completion.c index e1603f1..8c4f3ad 100644 --- a/fish/completion.c +++ b/fish/completion.c @@ -98,6 +98,9 @@ static const char *commands[] = { "mkdir-p", "mkfs", "mount", + "mount-options", + "mount-ro", + "mount-vfs", "mounts", "path", "pvcreate", diff --git a/guestfish-actions.pod b/guestfish-actions.pod index 4ff574f..7cf78d0 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -678,6 +678,29 @@ on the underlying device. The filesystem options C and C are set with this call, in order to improve reliability. +=head2 mount-options + + mount-options options device mountpoint + +This is the same as the C command, but it +allows you to set the mount options as for the +L I<-o> flag. + +=head2 mount-ro + + mount-ro device mountpoint + +This is the same as the C command, but it +mounts the filesystem with the read-only (I<-o ro>) flag. + +=head2 mount-vfs + + mount-vfs options vfstype device mountpoint + +This is the same as the C command, but it +allows you to set both the mount options and the vfstype +as for the L I<-o> and I<-t> flags. + =head2 mounts mounts diff --git a/guestfs-actions.pod b/guestfs-actions.pod index b964876..dcc8b50 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -889,6 +889,44 @@ call, in order to improve reliability. This function returns 0 on success or -1 on error. +=head2 guestfs_mount_options + + int guestfs_mount_options (guestfs_h *handle, + const char *options, + const char *device, + const char *mountpoint); + +This is the same as the C command, but it +allows you to set the mount options as for the +L I<-o> flag. + +This function returns 0 on success or -1 on error. + +=head2 guestfs_mount_ro + + int guestfs_mount_ro (guestfs_h *handle, + const char *device, + const char *mountpoint); + +This is the same as the C command, but it +mounts the filesystem with the read-only (I<-o ro>) flag. + +This function returns 0 on success or -1 on error. + +=head2 guestfs_mount_vfs + + int guestfs_mount_vfs (guestfs_h *handle, + const char *options, + const char *vfstype, + const char *device, + const char *mountpoint); + +This is the same as the C command, but it +allows you to set both the mount options and the vfstype +as for the L I<-o> and I<-t> flags. + +This function returns 0 on success or -1 on error. + =head2 guestfs_mounts char **guestfs_mounts (guestfs_h *handle); diff --git a/java/com/redhat/et/libguestfs/GuestFS.java b/java/com/redhat/et/libguestfs/GuestFS.java index 119a2df..bb6c8d7 100644 --- a/java/com/redhat/et/libguestfs/GuestFS.java +++ b/java/com/redhat/et/libguestfs/GuestFS.java @@ -2130,4 +2130,60 @@ public class GuestFS { private native void _tgz_out (long g, String directory, String tarball) throws LibGuestFSException; + /** + * mount a guest disk, read-only + * + * This is the same as the "g.mount" command, but it mounts + * the filesystem with the read-only (*-o ro*) flag. + * + * @throws LibGuestFSException + */ + public void mount_ro (String device, String mountpoint) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("mount_ro: handle is closed"); + _mount_ro (g, device, mountpoint); + } + private native void _mount_ro (long g, String device, String mountpoint) + throws LibGuestFSException; + + /** + * mount a guest disk with mount options + * + * This is the same as the "g.mount" command, but it allows + * you to set the mount options as for the mount(8) *-o* + * flag. + * + * @throws LibGuestFSException + */ + public void mount_options (String options, String device, String mountpoint) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("mount_options: handle is closed"); + _mount_options (g, options, device, mountpoint); + } + private native void _mount_options (long g, String options, String device, String mountpoint) + throws LibGuestFSException; + + /** + * mount a guest disk with mount options and vfstype + * + * This is the same as the "g.mount" command, but it allows + * you to set both the mount options and the vfstype as for + * the mount(8) *-o* and *-t* flags. + * + * @throws LibGuestFSException + */ + public void mount_vfs (String options, String vfstype, String device, String mountpoint) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("mount_vfs: handle is closed"); + _mount_vfs (g, options, vfstype, device, mountpoint); + } + private native void _mount_vfs (long g, String options, String vfstype, String device, String mountpoint) + throws LibGuestFSException; + } diff --git a/java/com_redhat_et_libguestfs_GuestFS.c b/java/com_redhat_et_libguestfs_GuestFS.c index 550568b..6d39f38 100644 --- a/java/com_redhat_et_libguestfs_GuestFS.c +++ b/java/com_redhat_et_libguestfs_GuestFS.c @@ -2161,3 +2161,72 @@ Java_com_redhat_et_libguestfs_GuestFS__1tgz_1out } } +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1mount_1ro + (JNIEnv *env, jobject obj, jlong jg, jstring jdevice, jstring jmountpoint) +{ + guestfs_h *g = (guestfs_h *) jg; + int r; + const char *device; + const char *mountpoint; + + device = (*env)->GetStringUTFChars (env, jdevice, NULL); + mountpoint = (*env)->GetStringUTFChars (env, jmountpoint, NULL); + r = guestfs_mount_ro (g, device, mountpoint); + (*env)->ReleaseStringUTFChars (env, jdevice, device); + (*env)->ReleaseStringUTFChars (env, jmountpoint, mountpoint); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return ; + } +} + +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1mount_1options + (JNIEnv *env, jobject obj, jlong jg, jstring joptions, jstring jdevice, jstring jmountpoint) +{ + guestfs_h *g = (guestfs_h *) jg; + int r; + const char *options; + const char *device; + const char *mountpoint; + + options = (*env)->GetStringUTFChars (env, joptions, NULL); + device = (*env)->GetStringUTFChars (env, jdevice, NULL); + mountpoint = (*env)->GetStringUTFChars (env, jmountpoint, NULL); + r = guestfs_mount_options (g, options, device, mountpoint); + (*env)->ReleaseStringUTFChars (env, joptions, options); + (*env)->ReleaseStringUTFChars (env, jdevice, device); + (*env)->ReleaseStringUTFChars (env, jmountpoint, mountpoint); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return ; + } +} + +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1mount_1vfs + (JNIEnv *env, jobject obj, jlong jg, jstring joptions, jstring jvfstype, jstring jdevice, jstring jmountpoint) +{ + guestfs_h *g = (guestfs_h *) jg; + int r; + const char *options; + const char *vfstype; + const char *device; + const char *mountpoint; + + options = (*env)->GetStringUTFChars (env, joptions, NULL); + vfstype = (*env)->GetStringUTFChars (env, jvfstype, NULL); + device = (*env)->GetStringUTFChars (env, jdevice, NULL); + mountpoint = (*env)->GetStringUTFChars (env, jmountpoint, NULL); + r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint); + (*env)->ReleaseStringUTFChars (env, joptions, options); + (*env)->ReleaseStringUTFChars (env, jvfstype, vfstype); + (*env)->ReleaseStringUTFChars (env, jdevice, device); + (*env)->ReleaseStringUTFChars (env, jmountpoint, mountpoint); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return ; + } +} + diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index 1cfe921..96ec6e3 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -208,3 +208,6 @@ external tar_in : t -> string -> string -> unit = "ocaml_guestfs_tar_in" external tar_out : t -> string -> string -> unit = "ocaml_guestfs_tar_out" external tgz_in : t -> string -> string -> unit = "ocaml_guestfs_tgz_in" external tgz_out : t -> string -> string -> unit = "ocaml_guestfs_tgz_out" +external mount_ro : t -> string -> string -> unit = "ocaml_guestfs_mount_ro" +external mount_options : t -> string -> string -> string -> unit = "ocaml_guestfs_mount_options" +external mount_vfs : t -> string -> string -> string -> string -> unit = "ocaml_guestfs_mount_vfs" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 766c3e0..a332f0b 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -403,3 +403,12 @@ val tgz_in : t -> string -> string -> unit val tgz_out : t -> string -> string -> unit (** pack directory into compressed tarball *) +val mount_ro : t -> string -> string -> unit +(** mount a guest disk, read-only *) + +val mount_options : t -> string -> string -> string -> unit +(** mount a guest disk with mount options *) + +val mount_vfs : t -> string -> string -> string -> string -> unit +(** mount a guest disk with mount options and vfstype *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index b0f9cdc..acf8f92 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -2533,3 +2533,78 @@ ocaml_guestfs_tgz_out (value gv, value directoryv, value tarballv) CAMLreturn (rv); } +CAMLprim value +ocaml_guestfs_mount_ro (value gv, value devicev, value mountpointv) +{ + CAMLparam3 (gv, devicev, mountpointv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("mount_ro: used handle after closing it"); + + const char *device = String_val (devicev); + const char *mountpoint = String_val (mountpointv); + int r; + + caml_enter_blocking_section (); + r = guestfs_mount_ro (g, device, mountpoint); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "mount_ro"); + + rv = Val_unit; + CAMLreturn (rv); +} + +CAMLprim value +ocaml_guestfs_mount_options (value gv, value optionsv, value devicev, value mountpointv) +{ + CAMLparam4 (gv, optionsv, devicev, mountpointv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("mount_options: used handle after closing it"); + + const char *options = String_val (optionsv); + const char *device = String_val (devicev); + const char *mountpoint = String_val (mountpointv); + int r; + + caml_enter_blocking_section (); + r = guestfs_mount_options (g, options, device, mountpoint); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "mount_options"); + + rv = Val_unit; + CAMLreturn (rv); +} + +CAMLprim value +ocaml_guestfs_mount_vfs (value gv, value optionsv, value vfstypev, value devicev, value mountpointv) +{ + CAMLparam5 (gv, optionsv, vfstypev, devicev, mountpointv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("mount_vfs: used handle after closing it"); + + const char *options = String_val (optionsv); + const char *vfstype = String_val (vfstypev); + const char *device = String_val (devicev); + const char *mountpoint = String_val (mountpointv); + int r; + + caml_enter_blocking_section (); + r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "mount_vfs"); + + rv = Val_unit; + CAMLreturn (rv); +} + diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index 657a0ba..fe2c81c 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -1429,3 +1429,42 @@ PREINIT: if (r == -1) croak ("tgz_out: %s", guestfs_last_error (g)); +void +mount_ro (g, device, mountpoint) + guestfs_h *g; + char *device; + char *mountpoint; +PREINIT: + int r; + PPCODE: + r = guestfs_mount_ro (g, device, mountpoint); + if (r == -1) + croak ("mount_ro: %s", guestfs_last_error (g)); + +void +mount_options (g, options, device, mountpoint) + guestfs_h *g; + char *options; + char *device; + char *mountpoint; +PREINIT: + int r; + PPCODE: + r = guestfs_mount_options (g, options, device, mountpoint); + if (r == -1) + croak ("mount_options: %s", guestfs_last_error (g)); + +void +mount_vfs (g, options, vfstype, device, mountpoint) + guestfs_h *g; + char *options; + char *vfstype; + char *device; + char *mountpoint; +PREINIT: + int r; + PPCODE: + r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint); + if (r == -1) + croak ("mount_vfs: %s", guestfs_last_error (g)); + diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm index 273e4fe..ea82659 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -647,6 +647,23 @@ on the underlying device. The filesystem options C and C are set with this call, in order to improve reliability. +=item $h->mount_options ($options, $device, $mountpoint); + +This is the same as the C<$h-Emount> command, but it +allows you to set the mount options as for the +L I<-o> flag. + +=item $h->mount_ro ($device, $mountpoint); + +This is the same as the C<$h-Emount> command, but it +mounts the filesystem with the read-only (I<-o ro>) flag. + +=item $h->mount_vfs ($options, $vfstype, $device, $mountpoint); + +This is the same as the C<$h-Emount> command, but it +allows you to set both the mount options and the vfstype +as for the L I<-o> and I<-t> flags. + =item @devices = $h->mounts (); This returns the list of currently mounted filesystems. It returns diff --git a/python/guestfs-py.c b/python/guestfs-py.c index d647014..59f0b6e 100644 --- a/python/guestfs-py.c +++ b/python/guestfs-py.c @@ -2714,6 +2714,87 @@ py_guestfs_tgz_out (PyObject *self, PyObject *args) return py_r; } +static PyObject * +py_guestfs_mount_ro (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *device; + const char *mountpoint; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_mount_ro", + &py_g, &device, &mountpoint)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mount_ro (g, device, mountpoint); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_mount_options (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *options; + const char *device; + const char *mountpoint; + + if (!PyArg_ParseTuple (args, (char *) "Osss:guestfs_mount_options", + &py_g, &options, &device, &mountpoint)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mount_options (g, options, device, mountpoint); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_mount_vfs (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *options; + const char *vfstype; + const char *device; + const char *mountpoint; + + if (!PyArg_ParseTuple (args, (char *) "Ossss:guestfs_mount_vfs", + &py_g, &options, &vfstype, &device, &mountpoint)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + static PyMethodDef methods[] = { { (char *) "create", py_guestfs_create, METH_VARARGS, NULL }, { (char *) "close", py_guestfs_close, METH_VARARGS, NULL }, @@ -2810,6 +2891,9 @@ static PyMethodDef methods[] = { { (char *) "tar_out", py_guestfs_tar_out, METH_VARARGS, NULL }, { (char *) "tgz_in", py_guestfs_tgz_in, METH_VARARGS, NULL }, { (char *) "tgz_out", py_guestfs_tgz_out, METH_VARARGS, NULL }, + { (char *) "mount_ro", py_guestfs_mount_ro, METH_VARARGS, NULL }, + { (char *) "mount_options", py_guestfs_mount_options, METH_VARARGS, NULL }, + { (char *) "mount_vfs", py_guestfs_mount_vfs, METH_VARARGS, NULL }, { NULL, NULL, 0, NULL } }; diff --git a/python/guestfs.py b/python/guestfs.py index e5f43d1..7515aa7 100644 --- a/python/guestfs.py +++ b/python/guestfs.py @@ -1055,3 +1055,23 @@ class GuestFS: """ return libguestfsmod.tgz_out (self._o, directory, tarball) + def mount_ro (self, device, mountpoint): + u"""This is the same as the "g.mount" command, but it mounts + the filesystem with the read-only (*-o ro*) flag. + """ + return libguestfsmod.mount_ro (self._o, device, mountpoint) + + def mount_options (self, options, device, mountpoint): + u"""This is the same as the "g.mount" command, but it allows + you to set the mount options as for the mount(8) *-o* + flag. + """ + return libguestfsmod.mount_options (self._o, options, device, mountpoint) + + def mount_vfs (self, options, vfstype, device, mountpoint): + u"""This is the same as the "g.mount" command, but it allows + you to set both the mount options and the vfstype as for + the mount(8) *-o* and *-t* flags. + """ + return libguestfsmod.mount_vfs (self._o, options, vfstype, device, mountpoint) + diff --git a/ruby/ext/guestfs/_guestfs.c b/ruby/ext/guestfs/_guestfs.c index 4e1a2d4..89eb6af 100644 --- a/ruby/ext/guestfs/_guestfs.c +++ b/ruby/ext/guestfs/_guestfs.c @@ -2231,6 +2231,93 @@ static VALUE ruby_guestfs_tgz_out (VALUE gv, VALUE directoryv, VALUE tarballv) return Qnil; } +static VALUE ruby_guestfs_mount_ro (VALUE gv, VALUE devicev, VALUE mountpointv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mount_ro"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "mount_ro"); + const char *mountpoint = StringValueCStr (mountpointv); + if (!mountpoint) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "mountpoint", "mount_ro"); + + int r; + + r = guestfs_mount_ro (g, device, mountpoint); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_mount_options (VALUE gv, VALUE optionsv, VALUE devicev, VALUE mountpointv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mount_options"); + + const char *options = StringValueCStr (optionsv); + if (!options) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "options", "mount_options"); + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "mount_options"); + const char *mountpoint = StringValueCStr (mountpointv); + if (!mountpoint) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "mountpoint", "mount_options"); + + int r; + + r = guestfs_mount_options (g, options, device, mountpoint); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_mount_vfs (VALUE gv, VALUE optionsv, VALUE vfstypev, VALUE devicev, VALUE mountpointv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mount_vfs"); + + const char *options = StringValueCStr (optionsv); + if (!options) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "options", "mount_vfs"); + const char *vfstype = StringValueCStr (vfstypev); + if (!vfstype) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "vfstype", "mount_vfs"); + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "mount_vfs"); + const char *mountpoint = StringValueCStr (mountpointv); + if (!mountpoint) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "mountpoint", "mount_vfs"); + + int r; + + r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + /* Initialize the module. */ void Init__guestfs () { @@ -2427,4 +2514,10 @@ void Init__guestfs () ruby_guestfs_tgz_in, 2); rb_define_method (c_guestfs, "tgz_out", ruby_guestfs_tgz_out, 2); + rb_define_method (c_guestfs, "mount_ro", + ruby_guestfs_mount_ro, 2); + rb_define_method (c_guestfs, "mount_options", + ruby_guestfs_mount_options, 3); + rb_define_method (c_guestfs, "mount_vfs", + ruby_guestfs_mount_vfs, 4); } diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index efc556e..ae8afcf 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -6137,3 +6137,255 @@ int guestfs_tgz_out (guestfs_h *g, return 0; } +struct mount_ro_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = send called, + * 1001 = reply called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; +}; + +static void mount_ro_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct mount_ro_ctx *ctx = (struct mount_ro_ctx *) data; + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_mount_ro"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_mount_ro"); + return; + } + goto done; + } + done: + ctx->cb_sequence = 1001; +} + +int guestfs_mount_ro (guestfs_h *g, + const char *device, + const char *mountpoint) +{ + struct guestfs_mount_ro_args args; + struct mount_ro_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_mount_ro") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.device = (char *) device; + args.mountpoint = (char *) mountpoint; + serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_RO, + (xdrproc_t) xdr_guestfs_mount_ro_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, mount_ro_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1001) { + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_ro"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_RO, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return 0; +} + +struct mount_options_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = send called, + * 1001 = reply called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; +}; + +static void mount_options_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct mount_options_ctx *ctx = (struct mount_options_ctx *) data; + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_mount_options"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_mount_options"); + return; + } + goto done; + } + done: + ctx->cb_sequence = 1001; +} + +int guestfs_mount_options (guestfs_h *g, + const char *options, + const char *device, + const char *mountpoint) +{ + struct guestfs_mount_options_args args; + struct mount_options_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_mount_options") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.options = (char *) options; + args.device = (char *) device; + args.mountpoint = (char *) mountpoint; + serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_OPTIONS, + (xdrproc_t) xdr_guestfs_mount_options_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, mount_options_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1001) { + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_options"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_OPTIONS, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return 0; +} + +struct mount_vfs_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = send called, + * 1001 = reply called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; +}; + +static void mount_vfs_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct mount_vfs_ctx *ctx = (struct mount_vfs_ctx *) data; + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_mount_vfs"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_mount_vfs"); + return; + } + goto done; + } + done: + ctx->cb_sequence = 1001; +} + +int guestfs_mount_vfs (guestfs_h *g, + const char *options, + const char *vfstype, + const char *device, + const char *mountpoint) +{ + struct guestfs_mount_vfs_args args; + struct mount_vfs_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_mount_vfs") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.options = (char *) options; + args.vfstype = (char *) vfstype; + args.device = (char *) device; + args.mountpoint = (char *) mountpoint; + serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_VFS, + (xdrproc_t) xdr_guestfs_mount_vfs_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, mount_vfs_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1001) { + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_vfs"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_VFS, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return 0; +} + diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h index 68184ba..756b678 100644 --- a/src/guestfs-actions.h +++ b/src/guestfs-actions.h @@ -112,3 +112,6 @@ extern int guestfs_tar_in (guestfs_h *handle, const char *tarfile, const char *d extern int guestfs_tar_out (guestfs_h *handle, const char *directory, const char *tarfile); extern int guestfs_tgz_in (guestfs_h *handle, const char *tarball, const char *directory); extern int guestfs_tgz_out (guestfs_h *handle, const char *directory, const char *tarball); +extern int guestfs_mount_ro (guestfs_h *handle, const char *device, const char *mountpoint); +extern int guestfs_mount_options (guestfs_h *handle, const char *options, const char *device, const char *mountpoint); +extern int guestfs_mount_vfs (guestfs_h *handle, const char *options, const char *vfstype, const char *device, const char *mountpoint); diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c index 8b88ad9..65eb5fc 100644 --- a/src/guestfs_protocol.c +++ b/src/guestfs_protocol.c @@ -1269,6 +1269,48 @@ xdr_guestfs_tgz_out_args (XDR *xdrs, guestfs_tgz_out_args *objp) } bool_t +xdr_guestfs_mount_ro_args (XDR *xdrs, guestfs_mount_ro_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->mountpoint, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_mount_options_args (XDR *xdrs, guestfs_mount_options_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->options, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->mountpoint, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_mount_vfs_args (XDR *xdrs, guestfs_mount_vfs_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->options, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->vfstype, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->mountpoint, ~0)) + return FALSE; + return TRUE; +} + +bool_t xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp) { register int32_t *buf; diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h index 55e6241..8803b3d 100644 --- a/src/guestfs_protocol.h +++ b/src/guestfs_protocol.h @@ -657,6 +657,27 @@ struct guestfs_tgz_out_args { }; typedef struct guestfs_tgz_out_args guestfs_tgz_out_args; +struct guestfs_mount_ro_args { + char *device; + char *mountpoint; +}; +typedef struct guestfs_mount_ro_args guestfs_mount_ro_args; + +struct guestfs_mount_options_args { + char *options; + char *device; + char *mountpoint; +}; +typedef struct guestfs_mount_options_args guestfs_mount_options_args; + +struct guestfs_mount_vfs_args { + char *options; + char *vfstype; + char *device; + char *mountpoint; +}; +typedef struct guestfs_mount_vfs_args guestfs_mount_vfs_args; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -730,7 +751,10 @@ enum guestfs_procedure { GUESTFS_PROC_TAR_OUT = 70, GUESTFS_PROC_TGZ_IN = 71, GUESTFS_PROC_TGZ_OUT = 72, - GUESTFS_PROC_NR_PROCS = 72 + 1, + GUESTFS_PROC_MOUNT_RO = 73, + GUESTFS_PROC_MOUNT_OPTIONS = 74, + GUESTFS_PROC_MOUNT_VFS = 75, + GUESTFS_PROC_NR_PROCS = 75 + 1, }; typedef enum guestfs_procedure guestfs_procedure; #define GUESTFS_MESSAGE_MAX 4194304 @@ -881,6 +905,9 @@ extern bool_t xdr_guestfs_tar_in_args (XDR *, guestfs_tar_in_args*); extern bool_t xdr_guestfs_tar_out_args (XDR *, guestfs_tar_out_args*); extern bool_t xdr_guestfs_tgz_in_args (XDR *, guestfs_tgz_in_args*); extern bool_t xdr_guestfs_tgz_out_args (XDR *, guestfs_tgz_out_args*); +extern bool_t xdr_guestfs_mount_ro_args (XDR *, guestfs_mount_ro_args*); +extern bool_t xdr_guestfs_mount_options_args (XDR *, guestfs_mount_options_args*); +extern bool_t xdr_guestfs_mount_vfs_args (XDR *, guestfs_mount_vfs_args*); extern bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*); extern bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*); extern bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*); @@ -990,6 +1017,9 @@ extern bool_t xdr_guestfs_tar_in_args (); extern bool_t xdr_guestfs_tar_out_args (); extern bool_t xdr_guestfs_tgz_in_args (); extern bool_t xdr_guestfs_tgz_out_args (); +extern bool_t xdr_guestfs_mount_ro_args (); +extern bool_t xdr_guestfs_mount_options_args (); +extern bool_t xdr_guestfs_mount_vfs_args (); extern bool_t xdr_guestfs_procedure (); extern bool_t xdr_guestfs_message_direction (); extern bool_t xdr_guestfs_message_status (); diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x index 7f98269..3cf4df3 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -508,6 +508,24 @@ struct guestfs_tgz_out_args { string directory<>; }; +struct guestfs_mount_ro_args { + string device<>; + string mountpoint<>; +}; + +struct guestfs_mount_options_args { + string options<>; + string device<>; + string mountpoint<>; +}; + +struct guestfs_mount_vfs_args { + string options<>; + string vfstype<>; + string device<>; + string mountpoint<>; +}; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -581,6 +599,9 @@ enum guestfs_procedure { GUESTFS_PROC_TAR_OUT = 70, GUESTFS_PROC_TGZ_IN = 71, GUESTFS_PROC_TGZ_OUT = 72, + GUESTFS_PROC_MOUNT_RO = 73, + GUESTFS_PROC_MOUNT_OPTIONS = 74, + GUESTFS_PROC_MOUNT_VFS = 75, GUESTFS_PROC_NR_PROCS }; diff --git a/tests.c b/tests.c index da8b409..9c102cd 100644 --- a/tests.c +++ b/tests.c @@ -105,6 +105,154 @@ static void no_test_warnings (void) fprintf (stderr, "warning: \"guestfs_blockdev_setbsz\" has no tests\n"); fprintf (stderr, "warning: \"guestfs_tar_out\" has no tests\n"); fprintf (stderr, "warning: \"guestfs_tgz_out\" has no tests\n"); + fprintf (stderr, "warning: \"guestfs_mount_options\" has no tests\n"); + fprintf (stderr, "warning: \"guestfs_mount_vfs\" has no tests\n"); +} + +static int test_mount_ro_0 (void) +{ + /* InitBasicFS for mount_ro (0): create ext2 on /dev/sda1 */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + { + char *lines[] = { + ",", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mkfs (g, "ext2", "/dev/sda1"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mount (g, "/dev/sda1", "/"); + if (r == -1) + return -1; + } + /* TestLastFail for mount_ro (0) */ + { + int r; + suppress_error = 0; + r = guestfs_umount (g, "/"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mount_ro (g, "/dev/sda1", "/"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 1; + r = guestfs_touch (g, "/new"); + if (r != -1) + return -1; + } + return 0; +} + +static int test_mount_ro_1 (void) +{ + /* InitBasicFS for mount_ro (1): create ext2 on /dev/sda1 */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + { + char *lines[] = { + ",", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mkfs (g, "ext2", "/dev/sda1"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mount (g, "/dev/sda1", "/"); + if (r == -1) + return -1; + } + /* TestOutput for mount_ro (1) */ + { + int r; + suppress_error = 0; + r = guestfs_write_file (g, "/new", "data", 0); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_umount (g, "/"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mount_ro (g, "/dev/sda1", "/"); + if (r == -1) + return -1; + } + { + char *r; + suppress_error = 0; + r = guestfs_cat (g, "/new"); + if (r == NULL) + return -1; + if (strcmp (r, "data") != 0) { + fprintf (stderr, "test_mount_ro_1: expected \"data\" but got \"%s\"\n", r); + return -1; + } + free (r); + } + return 0; } static int test_tgz_in_0 (void) @@ -5294,9 +5442,21 @@ int main (int argc, char *argv[]) exit (1); } - nr_tests = 75; + nr_tests = 77; test_num++; + printf ("%3d/%3d test_mount_ro_0\n", test_num, nr_tests); + if (test_mount_ro_0 () == -1) { + printf ("test_mount_ro_0 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_mount_ro_1\n", test_num, nr_tests); + if (test_mount_ro_1 () == -1) { + printf ("test_mount_ro_1 FAILED\n"); + failed++; + } + test_num++; printf ("%3d/%3d test_tgz_in_0\n", test_num, nr_tests); if (test_tgz_in_0 () == -1) { printf ("test_tgz_in_0 FAILED\n"); -- 1.8.3.1