1 /* This inspects a block device and produces an XML representation of
2 * the partitions, LVM, filesystems that we find there. This could be
3 * useful as example code of how to do this sort of probing, or to
4 * feed the XML to other programs.
7 * to-xml guest.img [guest.img ...]
17 /* Note that if any API call fails, we can just exit. The
18 * standard error handler will have printed the error message
21 #define CALL(call,errcode) \
22 if ((call) == (errcode)) exit (1);
24 static void display_partition (guestfs_h *g, const char *dev);
25 static void display_partitions (guestfs_h *g, const char *dev);
28 main (int argc, char *argv[])
33 if (argc < 2 || access (argv[1], F_OK) != 0) {
34 fprintf (stderr, "Usage: to-xml guest.img [guest.img ...]\n");
38 if (!(g = guestfs_create ())) {
39 fprintf (stderr, "Cannot create libguestfs handle.\n");
43 for (i = 1; i < argc; ++i)
44 CALL (guestfs_add_drive (g, argv[i]), -1);
46 CALL (guestfs_launch (g), -1);
47 CALL (guestfs_wait_ready (g), -1);
49 printf ("<guestfs-system>\n");
51 /* list-devices should return the devices that we just attached?
52 * Better to find out what the kernel thinks are devices anyway ...
55 CALL (devices = guestfs_list_devices (g), NULL);
56 printf ("<devices>\n");
57 for (i = 0; devices[i] != NULL; ++i) {
58 printf ("<device dev=\"%s\">\n", devices[i]);
59 display_partition (g, devices[i]);
61 printf ("</device>\n");
64 printf ("</devices>\n");
66 /* Now do the same for VGs and LVs. Note that a VG may span
67 * multiple PVs / block devices, in arbitrary ways, which is
68 * why VGs are in a separate top-level XML class.
72 printf ("<volgroups>\n");
73 CALL (vgs = guestfs_vgs (g), NULL);
74 CALL (lvs = guestfs_lvs (g), NULL);
75 for (i = 0; vgs[i] != NULL; ++i) {
76 printf ("<volgroup name=\"%s\">\n", vgs[i]);
78 /* Just the LVs in this VG. */
79 int len = strlen (vgs[i]);
81 for (j = 0; lvs[j] != NULL; ++j) {
82 if (strncmp (lvs[j], "/dev/", 5) == 0 &&
83 strncmp (&lvs[j][5], vgs[i], len) == 0 &&
84 lvs[j][len+5] == '/') {
85 printf ("<logvol name=\"%s\">\n", lvs[j]);
86 display_partition (g, lvs[j]);
87 printf ("</logvol>\n");
93 printf ("</volgroup>\n");
97 printf ("</volgroups>\n");
100 printf ("</guestfs-system>\n");
105 /* Display a partition or LV. */
107 display_partition (guestfs_h *g, const char *dev)
111 CALL (what = guestfs_file (g, dev), NULL);
113 if (strstr (what, "boot sector") != NULL)
114 display_partitions (g, dev);
115 else if (strncmp (what, "LVM2", 4) == 0)
116 printf ("<physvol/>\n");
117 else if (strstr (what, "ext2 filesystem data") == 0)
118 printf ("<fs type=\"ext2\"/>\n");
119 else if (strstr (what, "ext3 filesystem data") == 0)
120 printf ("<fs type=\"ext3\"/>\n");
122 printf ("<unknown/>\n");
127 /* Display an MBR-formatted boot sector. */
129 display_partitions (guestfs_h *g, const char *dev)
131 /* We can't look into a boot sector which is an LV. That's
132 * a limitation of sorts of the Linux kernel. (Actually, we
133 * could do this if we add the kpartx program to libguestfs).
135 if (strncmp (dev, "/dev/sd", 7) != 0) {
136 printf ("<vm-image dev=\"%s\"/>\n", dev);
142 CALL (parts = guestfs_list_partitions (g), NULL);
143 printf ("<partitions>\n");
146 for (i = 0; parts[i] != NULL; ++i) {
147 /* Only display partition if it's in the device. */
148 if (strncmp (parts[i], dev, len) == 0) {
149 printf ("<partition dev=\"%s\">\n", parts[i]);
150 display_partition (g, parts[i]);
151 printf ("</partition>\n");
157 printf ("</partitions>\n");