Coverity: Check guestfs_inspect_get_product_name() != NULL before using.
[libguestfs.git] / fish / inspect.c
index 8e56553..07af818 100644 (file)
@@ -22,6 +22,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "c-ctype.h"
+
 #include "guestfs.h"
 
 #include "options.h"
@@ -71,6 +73,14 @@ 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);
@@ -90,6 +100,12 @@ inspect_mount (void)
   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,6 +117,7 @@ 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)
@@ -108,10 +125,14 @@ inspect_mount (void)
     else
       r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
     if (r == -1)
-      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 +142,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 +160,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);
+  }
+}