X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=fish%2Finspect.c;h=cc3916b1bc171cda4a35b0fa941690cd77060808;hp=d17496f9419f998530fc90749d42cf2d354360cc;hb=6283982e36eeb3d19940618dc0aec88da08c7516;hpb=4440e22f4f7ebffe0728a8c019319d1a2b260cf5 diff --git a/fish/inspect.c b/fish/inspect.c index d17496f..cc3916b 100644 --- a/fish/inspect.c +++ b/fish/inspect.c @@ -1,4 +1,4 @@ -/* guestfish - the filesystem interactive shell +/* libguestfs - guestfish and guestmount shared option parsing * Copyright (C) 2010 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify @@ -22,13 +22,39 @@ #include #include -#include "fish.h" +#include "c-ctype.h" + +#include "guestfs.h" + +#include "options.h" + +static void do_decrypt (void); /* Global that saves the root device between inspect_mount and * print_inspect_prompt. */ static char *root = NULL; +static void +free_strings (char **argv) +{ + int argc; + + for (argc = 0; argv[argc] != NULL; ++argc) + free (argv[argc]); + free (argv); +} + +static int +count_strings (char *const *argv) +{ + int c; + + for (c = 0; argv[c]; ++c) + ; + return c; +} + static int compare_keys_len (const void *p1, const void *p2) { @@ -49,17 +75,21 @@ compare_keys (const void *p1, const void *p2) void inspect_mount (void) { + do_decrypt (); + char **roots = guestfs_inspect_os (g); if (roots == NULL) exit (EXIT_FAILURE); if (roots[0] == NULL) { - fprintf (stderr, _("guestfish: no operating system was found on this disk\n")); + fprintf (stderr, _("%s: no operating system was found on this disk\n"), + program_name); exit (EXIT_FAILURE); } if (roots[1] != NULL) { - fprintf (stderr, _("guestfish: multi-boot operating systems are not supported by the -i option\n")); + fprintf (stderr, _("%s: multi-boot operating systems are not supported by the -i option\n"), + program_name); exit (EXIT_FAILURE); } @@ -115,3 +145,73 @@ 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. + */ +static void +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_strings (partitions); + + if (need_rescan) { + if (guestfs_vgscan (g) == -1) + exit (EXIT_FAILURE); + if (guestfs_vg_activate_all (g, 1) == -1) + exit (EXIT_FAILURE); + } +}