Include string.h and libintl.h, as needed.
[libguestfs.git] / inspector / virt-inspector.c
index 86d0654..69c4ea9 100644 (file)
@@ -1,5 +1,5 @@
 /* virt-inspector
- * Copyright (C) 2010 Red Hat Inc.
+ * Copyright (C) 2010-2011 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
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <inttypes.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <locale.h>
 #include <assert.h>
+#include <libintl.h>
 
 #include <libxml/xmlIO.h>
 #include <libxml/xmlwriter.h>
@@ -38,6 +41,7 @@
 guestfs_h *g;
 
 int read_only = 1;
+int live = 0;
 int verbose = 0;
 int keys_from_stdin = 0;
 int echo_keys = 0;
@@ -49,6 +53,7 @@ static void output_roots (xmlTextWriterPtr xo, char **roots);
 static void output_root (xmlTextWriterPtr xo, char *root);
 static void output_mountpoints (xmlTextWriterPtr xo, char *root);
 static void output_filesystems (xmlTextWriterPtr xo, char *root);
+static void output_drive_mappings (xmlTextWriterPtr xo, char *root);
 static void output_applications (xmlTextWriterPtr xo, char *root);
 static void canonicalize (char *dev);
 static void free_strings (char **argv);
@@ -118,11 +123,9 @@ main (int argc, char *argv[])
   };
   struct drv *drvs = NULL;
   struct drv *drv;
-  char *p, *file = NULL;
   const char *format = NULL;
   int c;
   int option_index;
-  int next_prepared_drive = 1;
 
   g = guestfs_create ();
   if (g == NULL) {
@@ -228,6 +231,7 @@ main (int argc, char *argv[])
    */
   assert (read_only == 1);
   assert (inspector == 1);
+  assert (live == 0);
 
   /* Must be no extra arguments on the command line. */
   if (optind != argc)
@@ -333,7 +337,7 @@ static void
 output_root (xmlTextWriterPtr xo, char *root)
 {
   char *str;
-  int i;
+  int i, r;
   char buf[32];
   char canonical_root[strlen (root) + 1];
 
@@ -372,6 +376,13 @@ output_root (xmlTextWriterPtr xo, char *root)
       xmlTextWriterWriteElement (xo, BAD_CAST "product_name", BAD_CAST str));
   free (str);
 
+  str = guestfs_inspect_get_product_variant (g, root);
+  if (!str) exit (EXIT_FAILURE);
+  if (STRNEQ (str, "unknown"))
+    XMLERROR (-1,
+      xmlTextWriterWriteElement (xo, BAD_CAST "product_variant", BAD_CAST str));
+  free (str);
+
   i = guestfs_inspect_get_major_version (g, root);
   snprintf (buf, sizeof buf, "%d", i);
   XMLERROR (-1,
@@ -408,11 +419,50 @@ output_root (xmlTextWriterPtr xo, char *root)
                                            BAD_CAST str));
     free (str);
   );
+  DISABLE_GUESTFS_ERRORS_FOR (
+    str = guestfs_inspect_get_windows_current_control_set (g, root);
+    if (str)
+      XMLERROR (-1,
+                xmlTextWriterWriteElement (xo, BAD_CAST "windows_current_control_set",
+                                           BAD_CAST str));
+    free (str);
+  );
+
+  str = guestfs_inspect_get_format (g, root);
+  if (!str) exit (EXIT_FAILURE);
+  if (STRNEQ (str, "unknown"))
+    XMLERROR (-1,
+      xmlTextWriterWriteElement (xo, BAD_CAST "format",
+                                 BAD_CAST str));
+  free (str);
+
+  r = guestfs_inspect_is_live (g, root);
+  if (r > 0) {
+    XMLERROR (-1,
+              xmlTextWriterStartElement (xo, BAD_CAST "live"));
+    XMLERROR (-1, xmlTextWriterEndElement (xo));
+  }
+
+  r = guestfs_inspect_is_netinst (g, root);
+  if (r > 0) {
+    XMLERROR (-1,
+              xmlTextWriterStartElement (xo, BAD_CAST "netinst"));
+    XMLERROR (-1, xmlTextWriterEndElement (xo));
+  }
+
+  r = guestfs_inspect_is_multipart (g, root);
+  if (r > 0) {
+    XMLERROR (-1,
+              xmlTextWriterStartElement (xo, BAD_CAST "multipart"));
+    XMLERROR (-1, xmlTextWriterEndElement (xo));
+  }
 
   output_mountpoints (xo, root);
 
   output_filesystems (xo, root);
 
+  output_drive_mappings (xo, root);
+
   output_applications (xo, root);
 
   XMLERROR (-1, xmlTextWriterEndElement (xo));
@@ -428,6 +478,15 @@ compare_keys (const void *p1, const void *p2)
 }
 
 static int
+compare_keys_nocase (const void *p1, const void *p2)
+{
+  const char *key1 = * (char * const *) p1;
+  const char *key2 = * (char * const *) p2;
+
+  return strcasecmp (key1, key2);
+}
+
+static int
 compare_keys_len (const void *p1, const void *p2)
 {
   const char *key1 = * (char * const *) p1;
@@ -538,6 +597,48 @@ output_filesystems (xmlTextWriterPtr xo, char *root)
 }
 
 static void
+output_drive_mappings (xmlTextWriterPtr xo, char *root)
+{
+  char **drive_mappings = NULL;
+  size_t i;
+
+  DISABLE_GUESTFS_ERRORS_FOR (
+    drive_mappings = guestfs_inspect_get_drive_mappings (g, root);
+  );
+  if (drive_mappings == NULL)
+    return;
+
+  if (drive_mappings[0] == NULL) {
+    free_strings (drive_mappings);
+    return;
+  }
+
+  /* Sort by key. */
+  qsort (drive_mappings,
+         count_strings (drive_mappings) / 2, 2 * sizeof (char *),
+         compare_keys_nocase);
+
+  XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "drive_mappings"));
+
+  for (i = 0; drive_mappings[i] != NULL; i += 2) {
+    canonicalize (drive_mappings[i+1]);
+
+    XMLERROR (-1,
+              xmlTextWriterStartElement (xo, BAD_CAST "drive_mapping"));
+    XMLERROR (-1,
+              xmlTextWriterWriteAttribute (xo, BAD_CAST "name",
+                                           BAD_CAST drive_mappings[i]));
+    XMLERROR (-1,
+              xmlTextWriterWriteString (xo, BAD_CAST drive_mappings[i+1]));
+    XMLERROR (-1, xmlTextWriterEndElement (xo));
+  }
+
+  XMLERROR (-1, xmlTextWriterEndElement (xo));
+
+  free_strings (drive_mappings);
+}
+
+static void
 output_applications (xmlTextWriterPtr xo, char *root)
 {
   struct guestfs_application_list *apps;
@@ -632,7 +733,7 @@ canonicalize (char *dev)
       (dev[5] == 'h' || dev[5] == 'v') &&
       dev[6] == 'd' &&
       c_isalpha (dev[7]) &&
-      c_isdigit (dev[8]))
+      (c_isdigit (dev[8]) || dev[8] == '\0'))
     dev[5] = 's';
 }