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 ...]
23 /* Note that if any API call fails, we can just exit. The
24 * standard error handler will have printed the error message
27 #define CALL(call,errcode) \
28 if ((call) == (errcode)) exit (EXIT_FAILURE);
30 static void display_partition (guestfs_h *g, const char *dev);
31 static void display_partitions (guestfs_h *g, const char *dev);
32 static void display_ext234 (guestfs_h *g, const char *dev, const char *fstype);
35 main (int argc, char *argv[])
40 if (argc < 2 || access (argv[1], F_OK) != 0) {
41 fprintf (stderr, "Usage: to-xml guest.img [guest.img ...]\n");
45 if (!(g = guestfs_create ())) {
46 fprintf (stderr, "Cannot create libguestfs handle.\n");
50 for (i = 1; i < argc; ++i)
51 CALL (guestfs_add_drive_opts (g, argv[i],
52 GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
55 CALL (guestfs_launch (g), -1);
57 printf ("<guestfs-system>\n");
59 /* list-devices should return the devices that we just attached?
60 * Better to find out what the kernel thinks are devices anyway ...
63 CALL (devices = guestfs_list_devices (g), NULL);
64 printf ("<devices>\n");
65 for (i = 0; devices[i] != NULL; ++i) {
67 CALL (size = guestfs_blockdev_getsize64 (g, devices[i]), -1);
68 printf ("<device dev=\"%s\" size=\"%" PRIi64 "\">\n", devices[i], size);
69 display_partitions (g, devices[i]);
71 printf ("</device>\n");
74 printf ("</devices>\n");
76 /* Now do the same for VGs and LVs. Note that a VG may span
77 * multiple PVs / block devices, in arbitrary ways, which is
78 * why VGs are in a separate top-level XML class.
82 printf ("<volgroups>\n");
83 CALL (vgs = guestfs_vgs (g), NULL);
84 CALL (lvs = guestfs_lvs (g), NULL);
85 for (i = 0; vgs[i] != NULL; ++i) {
86 printf ("<volgroup name=\"%s\">\n", vgs[i]);
88 /* Just the LVs in this VG. */
89 int len = strlen (vgs[i]);
91 for (j = 0; lvs[j] != NULL; ++j) {
92 if (strncmp (lvs[j], "/dev/", 5) == 0 &&
93 strncmp (&lvs[j][5], vgs[i], len) == 0 &&
94 lvs[j][len+5] == '/') {
96 CALL (size = guestfs_blockdev_getsize64 (g, lvs[j]), -1);
97 printf ("<logvol name=\"%s\" size=\"%" PRIi64 "\">\n", lvs[j], size);
98 display_partition (g, lvs[j]);
99 printf ("</logvol>\n");
105 printf ("</volgroup>\n");
109 printf ("</volgroups>\n");
112 printf ("</guestfs-system>\n");
117 /* Display a partition or LV. */
119 display_partition (guestfs_h *g, const char *dev)
123 CALL (what = guestfs_file (g, dev), NULL);
125 if (strcmp (what, "x86 boot sector") == 0)
126 /* This is what 'file' program shows for Windows/NTFS partitions. */
127 printf ("<windows/>\n");
128 else if (strstr (what, "boot sector") != NULL)
129 display_partitions (g, dev);
130 else if (strncmp (what, "LVM2", 4) == 0)
131 printf ("<physvol/>\n");
132 else if (strstr (what, "ext2 filesystem data") != NULL)
133 display_ext234 (g, dev, "ext2");
134 else if (strstr (what, "ext3 filesystem data") != NULL)
135 display_ext234 (g, dev, "ext3");
136 else if (strstr (what, "ext4 filesystem data") != NULL)
137 display_ext234 (g, dev, "ext4");
138 else if (strstr (what, "Linux/i386 swap file") != NULL)
139 printf ("<linux-swap/>\n");
141 printf ("<unknown/>\n");
146 /* Display an MBR-formatted boot sector. */
148 display_partitions (guestfs_h *g, const char *dev)
150 /* We can't look into a boot sector which is an LV or partition.
151 * That's a limitation of sorts of the Linux kernel. (Actually,
152 * we could do this if we add the kpartx program to libguestfs).
154 if (strncmp (dev, "/dev/sd", 7) != 0 || isdigit (dev[strlen(dev)-1])) {
155 printf ("<vm-image dev=\"%s\"/>\n", dev);
161 CALL (parts = guestfs_list_partitions (g), NULL);
162 printf ("<partitions>\n");
165 for (i = 0; parts[i] != NULL; ++i) {
166 /* Only display partition if it's in the device. */
167 if (strncmp (parts[i], dev, len) == 0) {
169 CALL (size = guestfs_blockdev_getsize64 (g, parts[i]), -1);
170 printf ("<partition dev=\"%s\" size=\"%" PRIi64 "\">\n", parts[i], size);
171 display_partition (g, parts[i]);
172 printf ("</partition>\n");
178 printf ("</partitions>\n");
181 /* Display some details on the ext2/3/4 filesystem on dev. */
183 display_ext234 (guestfs_h *g, const char *dev, const char *fstype)
188 printf ("<fs type=\"%s\">\n", fstype);
189 CALL (sbfields = guestfs_tune2fs_l (g, dev), NULL);
191 for (i = 0; sbfields[i] != NULL; i += 2) {
192 /* Just pick out a few important fields to display. There
193 * is much more that could be displayed here.
195 if (strcmp (sbfields[i], "Filesystem UUID") == 0)
196 printf ("<uuid>%s</uuid>\n", sbfields[i+1]);
197 else if (strcmp (sbfields[i], "Block size") == 0)
198 printf ("<blocksize>%s</blocksize>\n", sbfields[i+1]);
201 free (sbfields[i+1]);