X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=fish%2Finspect.c;h=f93367b309ebf84854127b3afc9f6507d17263ae;hb=0ef30bbb316b50beba511a5eb4bd7174671fa1ca;hp=8e56553d9685cc4b394079f1a232b021ae91c1ae;hpb=c66d6f215e8303d4eaf8ccfdb6a58cff04ccc485;p=libguestfs.git diff --git a/fish/inspect.c b/fish/inspect.c index 8e56553..f93367b 100644 --- a/fish/inspect.c +++ b/fish/inspect.c @@ -13,7 +13,7 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -22,6 +22,8 @@ #include #include +#include "c-ctype.h" + #include "guestfs.h" #include "options.h" @@ -41,14 +43,14 @@ free_strings (char **argv) free (argv); } -static int +static size_t count_strings (char *const *argv) { - int c; + size_t i; - for (c = 0; argv[c]; ++c) + for (i = 0; argv[i]; ++i) ; - return c; + return i; } static int @@ -71,25 +73,69 @@ compare_keys (const void *p1, const void *p2) void inspect_mount (void) { + if (live) { + fprintf (stderr, _("%s: don't use --live and -i options together\n"), + program_name); + exit (EXIT_FAILURE); + } + + inspect_do_decrypt (); + char **roots = guestfs_inspect_os (g); if (roots == NULL) exit (EXIT_FAILURE); if (roots[0] == NULL) { - fprintf (stderr, _("%s: no operating system was found on this disk\n"), + fprintf (stderr, + _("%s: no operating system was found on this disk\n" + "\n" + "If using guestfish '-i' option, remove this option and instead\n" + "use the commands 'run' followed by 'list-filesystems'.\n" + "You can then mount filesystems you want by hand using the\n" + "'mount' or 'mount-ro' command.\n" + "\n" + "If using guestmount '-i', remove this option and choose the\n" + "filesystem(s) you want to see by manually adding '-m' option(s).\n" + "Use 'virt-filesystems' to see what filesystems are available.\n" + "\n" + "If using other virt tools, this disk image won't work\n" + "with these tools. Use the guestfish equivalent commands\n" + "(see the virt tool manual page).\n"), program_name); + free_strings (roots); exit (EXIT_FAILURE); } if (roots[1] != NULL) { - fprintf (stderr, _("%s: multi-boot operating systems are not supported by the -i option\n"), + fprintf (stderr, + _("%s: multi-boot operating systems are not supported\n" + "\n" + "If using guestfish '-i' option, remove this option and instead\n" + "use the commands 'run' followed by 'list-filesystems'.\n" + "You can then mount filesystems you want by hand using the\n" + "'mount' or 'mount-ro' command.\n" + "\n" + "If using guestmount '-i', remove this option and choose the\n" + "filesystem(s) you want to see by manually adding '-m' option(s).\n" + "Use 'virt-filesystems' to see what filesystems are available.\n" + "\n" + "If using other virt tools, multi-boot operating systems won't work\n" + "with these tools. Use the guestfish equivalent commands\n" + "(see the virt tool manual page).\n"), program_name); + free_strings (roots); exit (EXIT_FAILURE); } root = roots[0]; free (roots); + inspect_mount_root (root); +} + +void +inspect_mount_root (const char *root) +{ char **mountpoints = guestfs_inspect_get_mountpoints (g, root); if (mountpoints == NULL) exit (EXIT_FAILURE); @@ -101,17 +147,28 @@ inspect_mount (void) compare_keys_len); size_t i; + size_t mount_errors = 0; for (i = 0; mountpoints[i] != NULL; i += 2) { int r; if (!read_only) r = guestfs_mount_options (g, "", mountpoints[i+1], mountpoints[i]); else r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]); - if (r == -1) - exit (EXIT_FAILURE); + if (r == -1) { + /* If the "/" filesystem could not be mounted, give up, else + * just count the errors and print a warning. + */ + if (STREQ (mountpoints[i], "/")) + exit (EXIT_FAILURE); + mount_errors++; + } } free_strings (mountpoints); + + if (mount_errors) + fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"), + program_name); } /* This function is called only if the above function was called, @@ -121,7 +178,7 @@ void print_inspect_prompt (void) { char *name = guestfs_inspect_get_product_name (g, root); - if (STRNEQ (name, "unknown")) + if (name && STRNEQ (name, "unknown")) printf (_("Operating system: %s\n"), name); free (name); @@ -139,3 +196,74 @@ print_inspect_prompt (void) free_strings (mountpoints); } + +/* Make a LUKS map name from the partition name, + * eg "/dev/vda2" => "luksvda2" + */ +static void +make_mapname (const char *device, char *mapname, size_t len) +{ + size_t i = 0; + + if (len < 5) + abort (); + strcpy (mapname, "luks"); + mapname += 4; + len -= 4; + + if (STRPREFIX (device, "/dev/")) + i = 5; + + for (; device[i] != '\0' && len >= 1; ++i) { + if (c_isalnum (device[i])) { + *mapname++ = device[i]; + len--; + } + } + + *mapname = '\0'; +} + +/* Simple implementation of decryption: look for any crypto_LUKS + * partitions and decrypt them, then rescan for VGs. This only works + * for Fedora whole-disk encryption. WIP to make this work for other + * encryption schemes. + */ +void +inspect_do_decrypt (void) +{ + char **partitions = guestfs_list_partitions (g); + if (partitions == NULL) + exit (EXIT_FAILURE); + + int need_rescan = 0; + size_t i; + for (i = 0; partitions[i] != NULL; ++i) { + char *type = guestfs_vfs_type (g, partitions[i]); + if (type && STREQ (type, "crypto_LUKS")) { + char mapname[32]; + make_mapname (partitions[i], mapname, sizeof mapname); + + char *key = read_key (partitions[i]); + /* XXX Should we call guestfs_luks_open_ro if readonly flag + * is set? This might break 'mount_ro'. + */ + if (guestfs_luks_open (g, partitions[i], key, mapname) == -1) + exit (EXIT_FAILURE); + + free (key); + + need_rescan = 1; + } + free (type); + } + + free_strings (partitions); + + if (need_rescan) { + if (guestfs_vgscan (g) == -1) + exit (EXIT_FAILURE); + if (guestfs_vg_activate_all (g, 1) == -1) + exit (EXIT_FAILURE); + } +}