diff options
author | Richard Jones <rjones@redhat.com> | 2009-04-15 12:34:18 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-04-15 12:34:18 +0100 |
commit | 7fe2b338e4102a23ecd2f89b447b7618f0e93312 (patch) | |
tree | 025cf20aad2f85c568fbda1edb76d3cc7c0f3a37 /examples/to-xml.c | |
parent | 197f0ceeac625a20b923b274c6025eb0ccaeaed1 (diff) | |
download | libguestfs-7fe2b338e4102a23ecd2f89b447b7618f0e93312.tar.gz libguestfs-7fe2b338e4102a23ecd2f89b447b7618f0e93312.tar.xz libguestfs-7fe2b338e4102a23ecd2f89b447b7618f0e93312.zip |
Added to-xml program.
Diffstat (limited to 'examples/to-xml.c')
-rw-r--r-- | examples/to-xml.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/examples/to-xml.c b/examples/to-xml.c new file mode 100644 index 00000000..eba3a7a3 --- /dev/null +++ b/examples/to-xml.c @@ -0,0 +1,158 @@ +/* This inspects a block device and produces an XML representation of + * the partitions, LVM, filesystems that we find there. This could be + * useful as example code of how to do this sort of probing, or to + * feed the XML to other programs. + * + * Usage: + * to-xml guest.img [guest.img ...] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <guestfs.h> + +/* Note that if any API call fails, we can just exit. The + * standard error handler will have printed the error message + * to stderr already. + */ +#define CALL(call,errcode) \ + if ((call) == (errcode)) exit (1); + +static void display_partition (guestfs_h *g, const char *dev); +static void display_partitions (guestfs_h *g, const char *dev); + +int +main (int argc, char *argv[]) +{ + guestfs_h *g; + int i; + + if (argc < 2 || access (argv[1], F_OK) != 0) { + fprintf (stderr, "Usage: to-xml guest.img [guest.img ...]\n"); + exit (1); + } + + if (!(g = guestfs_create ())) { + fprintf (stderr, "Cannot create libguestfs handle.\n"); + exit (1); + } + + for (i = 1; i < argc; ++i) + CALL (guestfs_add_drive (g, argv[i]), -1); + + CALL (guestfs_launch (g), -1); + CALL (guestfs_wait_ready (g), -1); + + printf ("<guestfs-system>\n"); + + /* list-devices should return the devices that we just attached? + * Better to find out what the kernel thinks are devices anyway ... + */ + char **devices; + 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]); + free (devices[i]); + printf ("</device>\n"); + } + free (devices); + printf ("</devices>\n"); + + /* Now do the same for VGs and LVs. Note that a VG may span + * multiple PVs / block devices, in arbitrary ways, which is + * why VGs are in a separate top-level XML class. + */ + char **vgs; + char **lvs; + printf ("<volgroups>\n"); + CALL (vgs = guestfs_vgs (g), NULL); + CALL (lvs = guestfs_lvs (g), NULL); + for (i = 0; vgs[i] != NULL; ++i) { + printf ("<volgroup name=\"%s\">\n", vgs[i]); + + /* Just the LVs in this VG. */ + int len = strlen (vgs[i]); + 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]); + } + } + + free (vgs[i]); + printf ("</volgroup>\n"); + } + free (vgs); + free (lvs); + printf ("</volgroups>\n"); + + guestfs_close (g); + printf ("</guestfs-system>\n"); + + return 0; +} + +/* Display a partition or LV. */ +static void +display_partition (guestfs_h *g, const char *dev) +{ + char *what; + + CALL (what = guestfs_file (g, dev), NULL); + + 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 + printf ("<unknown/>\n"); + + free (what); +} + +/* Display an MBR-formatted boot sector. */ +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). + */ + if (strncmp (dev, "/dev/sd", 7) != 0) { + printf ("<vm-image dev=\"%s\"/>\n", dev); + return; + } + + char **parts; + int i, len; + CALL (parts = guestfs_list_partitions (g), NULL); + printf ("<partitions>\n"); + + len = strlen (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]); + display_partition (g, parts[i]); + printf ("</partition>\n"); + } + + free (parts[i]); + } + free (parts); + printf ("</partitions>\n"); +} |