change strncmp(...) != 0 to STRNEQLEN(...)
[libguestfs.git] / examples / to-xml.c
index eba3a7a..f48d1ca 100644 (file)
@@ -7,10 +7,16 @@
  *   to-xml guest.img [guest.img ...]
  */
 
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include <guestfs.h>
 
@@ -23,6 +29,7 @@
 
 static void display_partition (guestfs_h *g, const char *dev);
 static void display_partitions (guestfs_h *g, const char *dev);
+static void display_ext234 (guestfs_h *g, const char *dev, const char *fstype);
 
 int
 main (int argc, char *argv[])
@@ -44,7 +51,6 @@ main (int argc, char *argv[])
     CALL (guestfs_add_drive (g, argv[i]), -1);
 
   CALL (guestfs_launch (g), -1);
-  CALL (guestfs_wait_ready (g), -1);
 
   printf ("<guestfs-system>\n");
 
@@ -55,8 +61,10 @@ main (int argc, char *argv[])
   CALL (devices = guestfs_list_devices (g), NULL);
   printf ("<devices>\n");
   for (i = 0; devices[i] != NULL; ++i) {
-    printf ("<device dev=\"%s\">\n", devices[i]);
-    display_partition (g, devices[i]);
+    int64_t size;
+    CALL (size = guestfs_blockdev_getsize64 (g, devices[i]), -1);
+    printf ("<device dev=\"%s\" size=\"%" PRIi64 "\">\n", devices[i], size);
+    display_partitions (g, devices[i]);
     free (devices[i]);
     printf ("</device>\n");
   }
@@ -80,12 +88,14 @@ main (int argc, char *argv[])
     int j;
     for (j = 0; lvs[j] != NULL; ++j) {
       if (strncmp (lvs[j], "/dev/", 5) == 0 &&
-         strncmp (&lvs[j][5], vgs[i], len) == 0 &&
-         lvs[j][len+5] == '/') {
-       printf ("<logvol name=\"%s\">\n", lvs[j]);
-       display_partition (g, lvs[j]);
-       printf ("</logvol>\n");
-       free (lvs[j]);
+          strncmp (&lvs[j][5], vgs[i], len) == 0 &&
+          lvs[j][len+5] == '/') {
+        int64_t size;
+        CALL (size = guestfs_blockdev_getsize64 (g, lvs[j]), -1);
+        printf ("<logvol name=\"%s\" size=\"%" PRIi64 "\">\n", lvs[j], size);
+        display_partition (g, lvs[j]);
+        printf ("</logvol>\n");
+        free (lvs[j]);
       }
     }
 
@@ -110,14 +120,21 @@ display_partition (guestfs_h *g, const char *dev)
 
   CALL (what = guestfs_file (g, dev), NULL);
 
-  if (strstr (what, "boot sector") != NULL)
+  if (strcmp (what, "x86 boot sector") == 0)
+    /* This is what 'file' program shows for Windows/NTFS partitions. */
+    printf ("<windows/>\n");
+  else if (strstr (what, "boot sector") != NULL)
     display_partitions (g, dev);
   else if (strncmp (what, "LVM2", 4) == 0)
     printf ("<physvol/>\n");
-  else if (strstr (what, "ext2 filesystem data") == 0)
-    printf ("<fs type=\"ext2\"/>\n");
-  else if (strstr (what, "ext3 filesystem data") == 0)
-    printf ("<fs type=\"ext3\"/>\n");
+  else if (strstr (what, "ext2 filesystem data") != NULL)
+    display_ext234 (g, dev, "ext2");
+  else if (strstr (what, "ext3 filesystem data") != NULL)
+    display_ext234 (g, dev, "ext3");
+  else if (strstr (what, "ext4 filesystem data") != NULL)
+    display_ext234 (g, dev, "ext4");
+  else if (strstr (what, "Linux/i386 swap file") != NULL)
+    printf ("<linux-swap/>\n");
   else
     printf ("<unknown/>\n");
 
@@ -128,11 +145,11 @@ display_partition (guestfs_h *g, const char *dev)
 static void
 display_partitions (guestfs_h *g, const char *dev)
 {
-  /* We can't look into a boot sector which is an LV.  That's
-   * a limitation of sorts of the Linux kernel.  (Actually, we
-   * could do this if we add the kpartx program to libguestfs).
+  /* We can't look into a boot sector which is an LV or partition.
+   * That's a limitation of sorts of the Linux kernel.  (Actually,
+   * we could do this if we add the kpartx program to libguestfs).
    */
-  if (strncmp (dev, "/dev/sd", 7) != 0) {
+  if (STRNEQLEN (dev, "/dev/sd", 7) || isdigit (dev[strlen(dev)-1])) {
     printf ("<vm-image dev=\"%s\"/>\n", dev);
     return;
   }
@@ -146,7 +163,9 @@ display_partitions (guestfs_h *g, const char *dev)
   for (i = 0; parts[i] != NULL; ++i) {
     /* Only display partition if it's in the device. */
     if (strncmp (parts[i], dev, len) == 0) {
-      printf ("<partition dev=\"%s\">\n", parts[i]);
+      int64_t size;
+      CALL (size = guestfs_blockdev_getsize64 (g, parts[i]), -1);
+      printf ("<partition dev=\"%s\" size=\"%" PRIi64 "\">\n", parts[i], size);
       display_partition (g, parts[i]);
       printf ("</partition>\n");
     }
@@ -156,3 +175,30 @@ display_partitions (guestfs_h *g, const char *dev)
   free (parts);
   printf ("</partitions>\n");
 }
+
+/* Display some details on the ext2/3/4 filesystem on dev. */
+static void
+display_ext234 (guestfs_h *g, const char *dev, const char *fstype)
+{
+  char **sbfields;
+  int i;
+
+  printf ("<fs type=\"%s\">\n", fstype);
+  CALL (sbfields = guestfs_tune2fs_l (g, dev), NULL);
+
+  for (i = 0; sbfields[i] != NULL; i += 2) {
+    /* Just pick out a few important fields to display.  There
+     * is much more that could be displayed here.
+     */
+    if (strcmp (sbfields[i], "Filesystem UUID") == 0)
+      printf ("<uuid>%s</uuid>\n", sbfields[i+1]);
+    else if (strcmp (sbfields[i], "Block size") == 0)
+      printf ("<blocksize>%s</blocksize>\n", sbfields[i+1]);
+
+    free (sbfields[i]);
+    free (sbfields[i+1]);
+  }
+  free (sbfields);
+
+  printf ("</fs>\n");
+}