From 00adeb472c65e30fd2e55599b14d9b2eec2a873d Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 4 Mar 2017 15:35:09 +0000 Subject: [PATCH 07/10] rescue: Move --suggest code to separate file. Just code motion. (cherry picked from commit 5ea17e97e4413c3db4449ded72b9677cce09444f) --- rescue/Makefile.am | 3 +- rescue/rescue.c | 144 ------------------------------------------- rescue/rescue.h | 5 ++ rescue/suggest.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 145 deletions(-) create mode 100644 rescue/suggest.c diff --git a/rescue/Makefile.am b/rescue/Makefile.am index eb60bafa4..d478c8e3d 100644 --- a/rescue/Makefile.am +++ b/rescue/Makefile.am @@ -28,7 +28,8 @@ bin_PROGRAMS = virt-rescue virt_rescue_SOURCES = \ escape.c \ rescue.c \ - rescue.h + rescue.h \ + suggest.c virt_rescue_CPPFLAGS = \ -DGUESTFS_WARN_DEPRECATED=1 \ diff --git a/rescue/rescue.c b/rescue/rescue.c index 5281b1161..a1aac53e4 100644 --- a/rescue/rescue.c +++ b/rescue/rescue.c @@ -55,7 +55,6 @@ static void restore_tty (void); static void tstp_handler (int sig); static void cont_handler (int sig); static void add_scratch_disks (int n, struct drv **drvs); -static void do_suggestion (struct drv *drvs); /* Currently open libguestfs handle. */ guestfs_h *g; @@ -654,149 +653,6 @@ cont_handler (int sig) raw_tty (); } -static void suggest_filesystems (void); - -static int -compare_keys_len (const void *p1, const void *p2) -{ - const char *key1 = * (char * const *) p1; - const char *key2 = * (char * const *) p2; - return strlen (key1) - strlen (key2); -} - -/* virt-rescue --suggest flag does a kind of inspection on the - * drives and suggests mount commands that you should use. - */ -static void -do_suggestion (struct drv *drvs) -{ - CLEANUP_FREE_STRING_LIST char **roots = NULL; - size_t i; - - /* For inspection, force add_drives to add the drives read-only. */ - read_only = 1; - - /* Add drives. */ - add_drives (drvs); - - /* Free up data structures, no longer needed after this point. */ - free_drives (drvs); - - printf (_("Inspecting the virtual machine or disk image ...\n\n")); - fflush (stdout); - - if (guestfs_launch (g) == -1) - exit (EXIT_FAILURE); - - /* Don't use inspect_mount, since for virt-rescue we should allow - * arbitrary disks and disks with more than one OS on them. Let's - * do this using the basic API instead. - */ - roots = guestfs_inspect_os (g); - if (roots == NULL) - exit (EXIT_FAILURE); - - if (roots[0] == NULL) { - suggest_filesystems (); - return; - } - - printf (_("This disk contains one or more operating systems. You can use these mount\n" - "commands in virt-rescue (at the > prompt) to mount the filesystems.\n\n")); - - for (i = 0; roots[i] != NULL; ++i) { - CLEANUP_FREE_STRING_LIST char **mps = NULL; - CLEANUP_FREE char *type = NULL, *distro = NULL, *product_name = NULL; - int major, minor; - size_t j; - - type = guestfs_inspect_get_type (g, roots[i]); - distro = guestfs_inspect_get_distro (g, roots[i]); - product_name = guestfs_inspect_get_product_name (g, roots[i]); - major = guestfs_inspect_get_major_version (g, roots[i]); - minor = guestfs_inspect_get_minor_version (g, roots[i]); - - printf (_("# %s is the root of a %s operating system\n" - "# type: %s, distro: %s, version: %d.%d\n" - "# %s\n\n"), - roots[i], type ? : "unknown", - type ? : "unknown", distro ? : "unknown", major, minor, - product_name ? : ""); - - mps = guestfs_inspect_get_mountpoints (g, roots[i]); - if (mps == NULL) - exit (EXIT_FAILURE); - - /* Sort by key length, shortest key first, so that we end up - * mounting the filesystems in the correct order. - */ - qsort (mps, guestfs_int_count_strings (mps) / 2, 2 * sizeof (char *), - compare_keys_len); - - for (j = 0; mps[j] != NULL; j += 2) - printf ("mount %s /sysroot%s\n", mps[j+1], mps[j]); - - /* If it's Linux, print the bind-mounts and a chroot command. */ - if (type && STREQ (type, "linux")) { - printf ("mount --rbind /dev /sysroot/dev\n"); - printf ("mount --rbind /proc /sysroot/proc\n"); - printf ("mount --rbind /sys /sysroot/sys\n"); - printf ("\n"); - printf ("cd /sysroot\n"); - printf ("chroot /sysroot\n"); - } - - printf ("\n"); - } -} - -/* Inspection failed, so it doesn't contain any OS that we recognise. - * However there might still be filesystems so print some suggestions - * for those. - */ -static void -suggest_filesystems (void) -{ - size_t i, count; - - CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g); - if (fses == NULL) - exit (EXIT_FAILURE); - - /* Count how many are not swap or unknown. Possibly we should try - * mounting to see which are mountable, but that has a high - * probability of breaking. - */ -#define TEST_MOUNTABLE(fs) STRNEQ ((fs), "swap") && STRNEQ ((fs), "unknown") - count = 0; - for (i = 0; fses[i] != NULL; i += 2) { - if (TEST_MOUNTABLE (fses[i+1])) - count++; - } - - if (count == 0) { - printf (_("This disk contains no mountable filesystems that we recognize.\n\n" - "However you can still use virt-rescue on the disk image, to try to mount\n" - "filesystems that are not recognized by libguestfs, or to create partitions,\n" - "logical volumes and filesystems on a blank disk.\n")); - return; - } - - printf (_("This disk contains one or more filesystems, but we don't recognize any\n" - "operating system. You can use these mount commands in virt-rescue (at the\n" - "> prompt) to mount these filesystems.\n\n")); - - for (i = 0; fses[i] != NULL; i += 2) { - printf (_("# %s has type '%s'\n"), fses[i], fses[i+1]); - - if (TEST_MOUNTABLE (fses[i+1])) - printf ("mount %s /sysroot\n", fses[i]); - - printf ("\n"); - } -#undef TEST_MOUNTABLE -} - static void add_scratch_disk (struct drv **drvs); static void diff --git a/rescue/rescue.h b/rescue/rescue.h index ccffb5eb3..4f5a04a71 100644 --- a/rescue/rescue.h +++ b/rescue/rescue.h @@ -23,6 +23,8 @@ #include "guestfs.h" +#include "options.h" + extern guestfs_h *g; extern int read_only; extern int live; @@ -44,4 +46,7 @@ extern bool process_escapes (struct escape_state *state, char *buf, size_t *len) extern int parse_escape_key (const char *); extern void print_escape_key_help (void); +/* suggest.c */ +extern void do_suggestion (struct drv *drvs); + #endif /* RESCUE_H */ diff --git a/rescue/suggest.c b/rescue/suggest.c new file mode 100644 index 000000000..13141ccc2 --- /dev/null +++ b/rescue/suggest.c @@ -0,0 +1,175 @@ +/* virt-rescue + * Copyright (C) 2010-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. + */ + +#include + +#include +#include +#include +#include +#include + +#include "guestfs.h" +#include "guestfs-internal-frontend.h" + +#include "options.h" + +#include "rescue.h" + +static void suggest_filesystems (void); + +static int +compare_keys_len (const void *p1, const void *p2) +{ + const char *key1 = * (char * const *) p1; + const char *key2 = * (char * const *) p2; + return strlen (key1) - strlen (key2); +} + +/* virt-rescue --suggest flag does a kind of inspection on the + * drives and suggests mount commands that you should use. + */ +void +do_suggestion (struct drv *drvs) +{ + CLEANUP_FREE_STRING_LIST char **roots = NULL; + size_t i; + + /* For inspection, force add_drives to add the drives read-only. */ + read_only = 1; + + /* Add drives. */ + add_drives (drvs); + + /* Free up data structures, no longer needed after this point. */ + free_drives (drvs); + + printf (_("Inspecting the virtual machine or disk image ...\n\n")); + fflush (stdout); + + if (guestfs_launch (g) == -1) + exit (EXIT_FAILURE); + + /* Don't use inspect_mount, since for virt-rescue we should allow + * arbitrary disks and disks with more than one OS on them. Let's + * do this using the basic API instead. + */ + roots = guestfs_inspect_os (g); + if (roots == NULL) + exit (EXIT_FAILURE); + + if (roots[0] == NULL) { + suggest_filesystems (); + return; + } + + printf (_("This disk contains one or more operating systems. You can use these mount\n" + "commands in virt-rescue (at the > prompt) to mount the filesystems.\n\n")); + + for (i = 0; roots[i] != NULL; ++i) { + CLEANUP_FREE_STRING_LIST char **mps = NULL; + CLEANUP_FREE char *type = NULL, *distro = NULL, *product_name = NULL; + int major, minor; + size_t j; + + type = guestfs_inspect_get_type (g, roots[i]); + distro = guestfs_inspect_get_distro (g, roots[i]); + product_name = guestfs_inspect_get_product_name (g, roots[i]); + major = guestfs_inspect_get_major_version (g, roots[i]); + minor = guestfs_inspect_get_minor_version (g, roots[i]); + + printf (_("# %s is the root of a %s operating system\n" + "# type: %s, distro: %s, version: %d.%d\n" + "# %s\n\n"), + roots[i], type ? : "unknown", + type ? : "unknown", distro ? : "unknown", major, minor, + product_name ? : ""); + + mps = guestfs_inspect_get_mountpoints (g, roots[i]); + if (mps == NULL) + exit (EXIT_FAILURE); + + /* Sort by key length, shortest key first, so that we end up + * mounting the filesystems in the correct order. + */ + qsort (mps, guestfs_int_count_strings (mps) / 2, 2 * sizeof (char *), + compare_keys_len); + + for (j = 0; mps[j] != NULL; j += 2) + printf ("mount %s /sysroot%s\n", mps[j+1], mps[j]); + + /* If it's Linux, print the bind-mounts and a chroot command. */ + if (type && STREQ (type, "linux")) { + printf ("mount --rbind /dev /sysroot/dev\n"); + printf ("mount --rbind /proc /sysroot/proc\n"); + printf ("mount --rbind /sys /sysroot/sys\n"); + printf ("\n"); + printf ("cd /sysroot\n"); + printf ("chroot /sysroot\n"); + } + + printf ("\n"); + } +} + +/* Inspection failed, so it doesn't contain any OS that we recognise. + * However there might still be filesystems so print some suggestions + * for those. + */ +static void +suggest_filesystems (void) +{ + size_t i, count; + + CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g); + if (fses == NULL) + exit (EXIT_FAILURE); + + /* Count how many are not swap or unknown. Possibly we should try + * mounting to see which are mountable, but that has a high + * probability of breaking. + */ +#define TEST_MOUNTABLE(fs) STRNEQ ((fs), "swap") && STRNEQ ((fs), "unknown") + count = 0; + for (i = 0; fses[i] != NULL; i += 2) { + if (TEST_MOUNTABLE (fses[i+1])) + count++; + } + + if (count == 0) { + printf (_("This disk contains no mountable filesystems that we recognize.\n\n" + "However you can still use virt-rescue on the disk image, to try to mount\n" + "filesystems that are not recognized by libguestfs, or to create partitions,\n" + "logical volumes and filesystems on a blank disk.\n")); + return; + } + + printf (_("This disk contains one or more filesystems, but we don't recognize any\n" + "operating system. You can use these mount commands in virt-rescue (at the\n" + "> prompt) to mount these filesystems.\n\n")); + + for (i = 0; fses[i] != NULL; i += 2) { + printf (_("# %s has type '%s'\n"), fses[i], fses[i+1]); + + if (TEST_MOUNTABLE (fses[i+1])) + printf ("mount %s /sysroot\n", fses[i]); + + printf ("\n"); + } +#undef TEST_MOUNTABLE +} -- 2.13.2