`virt-rescue -a disk -i' does the right thing.
---
appliance/init | 12 +++++++--
rescue/Makefile.am | 3 ++-
rescue/rescue.c | 68 ++++++++++++++++++++++++++++++++++++++------------
rescue/virt-rescue.pod | 35 ++++++++++++++++++++++++++
4 files changed, 99 insertions(+), 19 deletions(-)
diff --git a/appliance/init b/appliance/init
index fa42c2b..b951857 100755
--- a/appliance/init
+++ b/appliance/init
@@ -180,6 +180,10 @@ else
# We need a daemon, even in virt-rescue.
$cmd &
+ # XXX This gives a bit of time for virt-rescue to connect to the
+ # daemon and mount any filesystems.
+ sleep 2
+
# Get name of the serial port, from console= passed by libguestfs.
guestfs_serial=$(grep -Eo 'console=[^[:space:]]+' /proc/cmdline |
sed s/console=//)
@@ -208,8 +212,12 @@ else
echo "Welcome to virt-rescue, the libguestfs rescue shell."
echo
echo "Note: The contents of / (root) are the rescue appliance."
- echo "You have to mount the guest's partitions under /sysroot"
- echo "before you can examine them."
+ if ! test -d "/sysroot/dev"; then
+ echo "You have to mount the guest's partitions under /sysroot"
+ echo "before you can examine them."
+ else
+ echo "Use 'cd /sysroot' or 'chroot /sysroot' to see guest
filesystems."
+ fi
echo
run_bash_with_ctty
echo
diff --git a/rescue/Makefile.am b/rescue/Makefile.am
index 99d4b79..c83c434 100644
--- a/rescue/Makefile.am
+++ b/rescue/Makefile.am
@@ -35,7 +35,7 @@ virt_rescue_CPPFLAGS = \
-I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \
-I$(top_srcdir)/lib -I$(top_builddir)/lib \
-I$(top_srcdir)/common/options -I$(top_builddir)/common/options \
- -I$(top_srcdir)/fish \
+ -I$(top_srcdir)/common/windows -I$(top_builddir)/common/windows \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
virt_rescue_CFLAGS = \
@@ -43,6 +43,7 @@ virt_rescue_CFLAGS = \
$(LIBXML2_CFLAGS)
virt_rescue_LDADD = \
+ $(top_builddir)/common/windows/libwindows.la \
$(top_builddir)/common/options/liboptions.la \
$(top_builddir)/common/utils/libutils.la \
$(top_builddir)/lib/libguestfs.la \
diff --git a/rescue/rescue.c b/rescue/rescue.c
index 556c344..6f19634 100644
--- a/rescue/rescue.c
+++ b/rescue/rescue.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
-#include <fcntl.h>
#include <getopt.h>
#include <errno.h>
#include <error.h>
@@ -36,9 +35,11 @@
#include "full-write.h"
#include "getprogname.h"
#include "ignore-value.h"
+#include "nonblocking.h"
#include "xvasprintf.h"
#include "guestfs.h"
+#include "windows.h"
#include "options.h"
#include "display-options.h"
@@ -83,7 +84,9 @@ usage (int status)
" -d|--domain guest Add disks from libvirt guest\n"
" --format[=raw|..] Force disk format for -a option\n"
" --help Display brief help\n"
+ " -i|--inspector Automatically mount filesystems\n"
" -m|--memsize MB Set memory size in megabytes\n"
+ " --mount dev[:mnt[:opts[:fstype]] Mount dev on mnt (if omitted,
/)\n"
" --network Enable network\n"
" -r|--ro Access read-only\n"
" --scratch[=N] Add scratch disk(s)\n"
@@ -112,7 +115,7 @@ main (int argc, char *argv[])
enum { HELP_OPTION = CHAR_MAX + 1 };
- static const char options[] = "a:c:d:m:rvVwx";
+ static const char options[] = "a:c:d:im:rvVwx";
static const struct option long_options[] = {
{ "add", 1, 0, 'a' },
{ "append", 1, 0, 0 },
@@ -120,7 +123,9 @@ main (int argc, char *argv[])
{ "domain", 1, 0, 'd' },
{ "format", 2, 0, 0 },
{ "help", 0, 0, HELP_OPTION },
+ { "inspector", 0, 0, 'i' },
{ "long-options", 0, 0, 0 },
+ { "mount", 1, 0, 0 /* not 'm' because memsize used it earlier */
},
{ "memsize", 1, 0, 'm' },
{ "network", 0, 0, 0 },
{ "ro", 0, 0, 'r' },
@@ -136,6 +141,9 @@ main (int argc, char *argv[])
};
struct drv *drvs = NULL;
struct drv *drv;
+ struct mp *mps = NULL;
+ struct mp *mp;
+ char *p;
const char *format = NULL;
bool format_consumed = true;
int c;
@@ -193,6 +201,8 @@ main (int argc, char *argv[])
_("--scratch parameter '%s' should be >= 1"),
optarg);
add_scratch_disks (n, &drvs);
}
+ } else if (STREQ (long_options[option_index].name, "mount")) {
+ OPTION_m;
} else
error (EXIT_FAILURE, 0,
_("unknown long option: %s (%d)"),
@@ -211,6 +221,10 @@ main (int argc, char *argv[])
OPTION_d;
break;
+ case 'i':
+ OPTION_i;
+ break;
+
case 'm':
if (sscanf (optarg, "%d", &memsize) != 1)
error (EXIT_FAILURE, 0,
@@ -285,7 +299,6 @@ main (int argc, char *argv[])
* options parsing code. Assert here that they have known-good
* values.
*/
- assert (inspector == 0);
assert (keys_from_stdin == 0);
assert (echo_keys == 0);
assert (live == 0);
@@ -329,12 +342,6 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
free (append_full);
- /* Add drives. */
- add_drives (drvs, 'a');
-
- /* Free up data structures, no longer needed after this point. */
- free_drives (drvs);
-
/* Add an event handler to print "log messages". These will be the
* output of the appliance console during launch and shutdown.
* After launch, we will read the console messages directly from the
@@ -344,9 +351,41 @@ main (int argc, char *argv[])
GUESTFS_EVENT_APPLIANCE, 0, NULL) == -1)
exit (EXIT_FAILURE);
- /* Run the appliance. */
+ /* Do the guest drives and mountpoints. */
+ add_drives (drvs, 'a');
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
+ if (inspector)
+ inspect_mount ();
+ mount_mps (mps);
+
+ free_drives (drvs);
+ free_mps (mps);
+
+ /* Also bind-mount /dev etc under /sysroot, if -i was given. */
+ if (inspector) {
+ CLEANUP_FREE_STRING_LIST char **roots;
+ int windows;
+
+ roots = guestfs_inspect_get_roots (g);
+ windows = roots && roots[0] && is_windows (g, roots[0]);
+ if (!windows) {
+ const char *cmd[5] = { "mount", "--rbind", NULL, NULL, NULL };
+ char *r;
+
+ cmd[2] = "/dev"; cmd[3] = "/sysroot/dev";
+ r = guestfs_debug (g, "sh", (char **) cmd);
+ free (r);
+
+ cmd[2] = "/proc"; cmd[3] = "/sysroot/proc";
+ r = guestfs_debug (g, "sh", (char **) cmd);
+ free (r);
+
+ cmd[2] = "/sys"; cmd[3] = "/sysroot/sys";
+ r = guestfs_debug (g, "sh", (char **) cmd);
+ free (r);
+ }
+ }
sock = guestfs_internal_get_console_socket (g);
if (sock == -1)
@@ -367,12 +406,9 @@ main (int argc, char *argv[])
}
/* Try to set all sockets to non-blocking. */
- if (fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1)
- perror ("could not set stdin to non-blocking");
- if (fcntl (STDOUT_FILENO, F_SETFL, O_NONBLOCK) == -1)
- perror ("could not set stdout to non-blocking");
- if (fcntl (sock, F_SETFL, O_NONBLOCK) == -1)
- perror ("could not set console socket to non-blocking");
+ ignore_value (set_nonblocking_flag (STDIN_FILENO, 1));
+ ignore_value (set_nonblocking_flag (STDOUT_FILENO, 1));
+ ignore_value (set_nonblocking_flag (sock, 1));
/* Restore the tty settings when the process exits. */
atexit (restore_tty);
diff --git a/rescue/virt-rescue.pod b/rescue/virt-rescue.pod
index b8aa326..745e540 100644
--- a/rescue/virt-rescue.pod
+++ b/rescue/virt-rescue.pod
@@ -170,6 +170,16 @@ If you have untrusted raw-format guest disk images, you should use
this option to specify the disk format. This avoids a possible
security problem with malicious guests (CVE-2010-3851).
+=item B<-i>
+
+=item B<--inspector>
+
+Using L<virt-inspector(1)> code, inspect the disks looking for
+an operating system and mount filesystems as they would be
+mounted on the real virtual machine.
+
+The filesystems are mounted on F</sysroot> in the rescue environment.
+
=item B<-m> MB
=item B<--memsize> MB
@@ -179,6 +189,31 @@ default is set by libguestfs and is small but adequate for running
system tools. The occasional program might need more memory. The
parameter is specified in megabytes.
+=item B<--mount> dev[:mountpoint[:options[:fstype]]]
+
+Mount the named partition or logical volume on the given mountpoint
+B<in the guest> (this has nothing to do with mountpoints in the host).
+
+If the mountpoint is omitted, it defaults to F</>. You have to mount
+something on F</>.
+
+The filesystems are mounted under F</sysroot> in the rescue environment.
+
+The third (and rarely used) part of the mount parameter is the list of
+mount options used to mount the underlying filesystem. If this is not
+given, then the mount options are either the empty string or C<ro>
+(the latter if the I<--ro> flag is used). By specifying the mount
+options, you override this default choice. Probably the only time you
+would use this is to enable ACLs and/or extended attributes if the
+filesystem can support them:
+
+ -m /dev/sda1:/:acl,user_xattr
+
+The fourth part of the parameter is the filesystem driver to use, such
+as C<ext3> or C<ntfs>. This is rarely needed, but can be useful if
+multiple drivers are valid for a filesystem (eg: C<ext2> and C<ext3>),
+or if libguestfs misidentifies a filesystem.
+
=item B<--network>
Enable QEMU user networking in the guest. See L</NETWORK>.
--
2.9.3