docs: Standard C examples, and guestfs-examples(3) man page.
authorRichard W.M. Jones <rjones@redhat.com>
Wed, 24 Nov 2010 17:19:28 +0000 (17:19 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Wed, 24 Nov 2010 20:12:11 +0000 (20:12 +0000)
.gitignore
Makefile.am
examples/LICENSE
examples/Makefile.am
examples/README [deleted file]
examples/create_disk.c [new file with mode: 0644]
examples/guestfs-examples.pod [new file with mode: 0644]
examples/hello.c [deleted file]
examples/inspect_vm.c [new file with mode: 0644]
examples/to-xml.c [deleted file]
src/guestfs.pod

index ac7ebbd..86dc196 100644 (file)
@@ -76,8 +76,10 @@ daemon/stubs.c
 depcomp
 .deps
 emptydisk
-examples/hello
-examples/to-xml
+examples/create_disk
+examples/guestfs-examples.3
+examples/inspect_vm
+examples/stamp-guestfs-examples.pod
 fish/cmds.c
 fish/cmds_gperf.c
 fish/cmds_gperf.gperf
@@ -113,6 +115,7 @@ haskell/Guestfs.hs
 *.hi
 html/guestfish.1.html
 html/guestfs.3.html
+html/guestfs-examples.3.html
 html/guestmount.1.html
 html/recipes.html
 html/virt-cat.1.html
index 94a3017..b154f08 100644 (file)
@@ -102,6 +102,7 @@ html/recipes.html: $(wildcard recipes/*.sh) $(wildcard recipes/*.html) $(wildcar
 
 HTMLFILES = \
        html/guestfs.3.html \
+       html/guestfs-examples.3.html \
        html/guestfish.1.html \
        html/guestmount.1.html \
        html/virt-cat.1.html \
index 5ba695a..ce7b417 100644 (file)
@@ -1,2 +1,2 @@
-All the examples in the examples/ subdirectory may be freely copied
-without any restrictions.
+All the examples in the 'examples' subdirectory may be freely copied,
+modified and distributed without any restrictions.
index 04bbe5e..7f7d8f7 100644 (file)
@@ -1,17 +1,47 @@
-# libguestfs examples
+# libguestfs C examples
+# Copyright (C) 2010 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-include $(top_srcdir)/subdir-rules.mk
+EXTRA_DIST = \
+       LICENSE \
+       guestfs-examples.pod
 
-noinst_PROGRAMS = hello to-xml
+CLEANFILES = stamp-guestfs-examples.pod
 
-hello_SOURCES = hello.c
-hello_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
-hello_LDADD = $(top_builddir)/src/libguestfs.la
+noinst_PROGRAMS = create_disk inspect_vm
 
-to_xml_SOURCES = to-xml.c
-to_xml_CPPFLAGS = \
-  -I$(top_srcdir)/gnulib/lib \
-  -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
-to_xml_LDADD = $(top_builddir)/src/libguestfs.la
+create_disk_SOURCES = create_disk.c
+create_disk_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
+create_disk_LDADD = $(top_builddir)/src/libguestfs.la
 
-CLEANFILES = $(noinst_PROGRAMS)
+inspect_vm_SOURCES = inspect_vm.c
+inspect_vm_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
+inspect_vm_LDADD = $(top_builddir)/src/libguestfs.la
+
+man_MANS = guestfs-examples.3
+noinst_DATA = $(top_builddir)/html/guestfs-examples.3.html
+
+guestfs-examples.3 $(top_builddir)/html/guestfs-examples.3.html: stamp-guestfs-examples.pod
+
+stamp-guestfs-examples.pod: guestfs-examples.pod create_disk.c inspect_vm.c
+       $(top_srcdir)/podwrapper.sh \
+         --section 3 \
+         --man guestfs-examples.3 \
+         --html $(top_builddir)/html/guestfs-examples.3.html \
+         --verbatim create_disk.c:@EXAMPLE1@ \
+         --verbatim inspect_vm.c:@EXAMPLE2@ \
+         $<
+       touch $@
diff --git a/examples/README b/examples/README
deleted file mode 100644 (file)
index 408d6a2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-This directory contains various example programs which use the
-libguestfs API.
-
-As they are examples, these are licensed so they can be freely copied
-and used without any restrictions.
-
-Tips:
-
-(1) To enable verbose messages, set environment variable
-LIBGUESTFS_DEBUG=1
-
-(2) If you haven't installed libguestfs, run the examples like this:
-LIBGUESTFS_PATH=appliance examples/to-xml
-(the path should point to the directory containing vmlinuz.* and
-initramfs.* files).
diff --git a/examples/create_disk.c b/examples/create_disk.c
new file mode 100644 (file)
index 0000000..f4b9044
--- /dev/null
@@ -0,0 +1,122 @@
+/* Example showing how to create a disk image. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <guestfs.h>
+
+int                                                                            
+main (int argc, char *argv[])
+{
+  guestfs_h *g;
+  size_t i;
+
+  g = guestfs_create ();
+  if (g == NULL) {
+    perror ("failed to create libguestfs handle");
+    exit (EXIT_FAILURE);
+ }
+
+  /* Create a raw-format sparse disk image, 512 MB in size. */
+  int fd = open ("disk.img", O_CREAT|O_WRONLY|O_TRUNC|O_NOCTTY, 0666);
+  if (fd == -1) {
+    perror ("disk.img");
+    exit (EXIT_FAILURE);
+  }
+  if (ftruncate (fd, 512 * 1024 * 1024) == -1) {
+    perror ("disk.img: truncate");
+    exit (EXIT_FAILURE);
+  }
+  if (close (fd) == -1) {
+    perror ("disk.img: close");
+    exit (EXIT_FAILURE);
+  }
+
+  /* Set the trace flag so that we can see each libguestfs call. */
+  guestfs_set_trace (g, 1);
+
+  /* Set the autosync flag so that the disk will be synchronized
+   * automatically when the libguestfs handle is closed.
+   */
+  guestfs_set_autosync (g, 1);
+
+  /* Add the disk image to libguestfs. */
+  if (guestfs_add_drive_opts (g, "disk.img",
+        GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", /* raw format */
+        GUESTFS_ADD_DRIVE_OPTS_READONLY, 0, /* for write */
+        -1) /* this marks end of optional arguments */
+      == -1)
+    exit (EXIT_FAILURE);
+
+  /* Run the libguestfs back-end. */
+  if (guestfs_launch (g) == -1)
+    exit (EXIT_FAILURE);
+
+  /* Get the list of devices.  Because we only added one drive
+   * above, we expect that this list should contain a single
+   * element.
+   */
+  char **devices = guestfs_list_devices (g);
+  if (devices == NULL)
+    exit (EXIT_FAILURE);
+  if (devices[0] == NULL || devices[1] != NULL) {
+    fprintf (stderr, "error: expected a single device from list-devices\n");
+    exit (EXIT_FAILURE);
+  }
+
+  /* Partition the disk as one single MBR partition. */
+  if (guestfs_part_disk (g, devices[0], "mbr") == -1)
+    exit (EXIT_FAILURE);
+
+  /* Get the list of partitions.  We expect a single element, which
+   * is the partition we have just created.
+   */
+  char **partitions = guestfs_list_partitions (g);
+  if (partitions == NULL)
+    exit (EXIT_FAILURE);
+  if (partitions[0] == NULL || partitions[1] != NULL) {
+    fprintf (stderr, "error: expected a single partition from list-partitions\n");
+    exit (EXIT_FAILURE);
+  }
+
+  /* Create a filesystem on the partition. */
+  if (guestfs_mkfs (g, "ext4", partitions[0]) == -1)
+    exit (EXIT_FAILURE);
+
+  /* Now mount the filesystem so that we can add files. */
+  if (guestfs_mount_options (g, "", partitions[0], "/") == -1)
+    exit (EXIT_FAILURE);
+
+  /* Create some files and directories. */
+  if (guestfs_touch (g, "/empty") == -1)
+    exit (EXIT_FAILURE);
+  const char *message = "Hello, world\n";
+  if (guestfs_write (g, "/hello", message, strlen (message)) == -1)
+    exit (EXIT_FAILURE);
+  if (guestfs_mkdir (g, "/foo") == -1)
+    exit (EXIT_FAILURE);
+
+  /* This one uploads the local file /etc/resolv.conf into
+   * the disk image.
+   */
+  if (guestfs_upload (g, "/etc/resolv.conf", "/foo/resolv.conf") == -1)
+    exit (EXIT_FAILURE);
+
+  /* Because 'autosync' was set (above) we can just close the handle
+   * and the disk contents will be synchronized.  You can also do
+   * this manually by calling guestfs_umount_all and guestfs_sync.
+   */
+  guestfs_close (g);
+
+  /* Free up the lists. */
+  for (i = 0; devices[i] != NULL; ++i)
+    free (devices[i]);
+  free (devices);
+  for (i = 0; partitions[i] != NULL; ++i)
+    free (partitions[i]);
+  free (partitions);
+
+  exit (EXIT_SUCCESS);
+}
diff --git a/examples/guestfs-examples.pod b/examples/guestfs-examples.pod
new file mode 100644 (file)
index 0000000..858ac61
--- /dev/null
@@ -0,0 +1,63 @@
+=encoding utf8
+
+=head1 NAME
+
+guestfs-examples - Examples of using libguestfs from C
+
+=head1 SYNOPSIS
+
+ #include <guestfs.h>
+ guestfs_h *g = guestfs_create ();
+ guestfs_add_drive_ro (g, "disk.img");
+ guestfs_launch (g);
+
+ cc prog.c -o prog -lguestfs
+or:
+ cc prog.c -o prog `pkg-config libguestfs --cflags --libs`
+
+=head1 DESCRIPTION
+
+This manual page contains examples of calling libguestfs from
+the C programming language.  If you are not familiar with using
+libguestfs, you also need to read L<guestfs(3)>.
+
+=head1 EXAMPLE 1: CREATE A DISK IMAGE
+
+@EXAMPLE1@
+
+=head1 EXAMPLE 2: INSPECT A VIRTUAL MACHINE DISK IMAGE
+
+@EXAMPLE2@
+
+=head1 SEE ALSO
+
+L<guestfs(3)>,
+L<guestfs-ocaml(3)>,
+L<http://libguestfs.org/>,
+L<http://caml.inria.fr/>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones (C<rjones at redhat dot com>)
+
+=head1 COPYRIGHT
+
+Copyright (C) 2010 Red Hat Inc. L<http://libguestfs.org/>
+
+The examples in this manual page may be freely copied, modified and
+distributed without any restrictions.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/examples/hello.c b/examples/hello.c
deleted file mode 100644 (file)
index b3d36e6..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Create a "/hello" file on chosen partition.
- * eg:
- *   hello guest.img /dev/sda1
- *   hello guest.img /dev/VolGroup00/LogVol00
- */
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <guestfs.h>
-
-int
-main (int argc, char *argv[])
-{
-  guestfs_h *g;
-
-  if (argc != 3 || access (argv[1], F_OK) != 0) {
-    fprintf (stderr, "Usage: hello disk-image partition\n");
-    exit (EXIT_FAILURE);
-  }
-
-  if (!(g = guestfs_create ())) exit (EXIT_FAILURE);
-
-  if (guestfs_add_drive_opts (g, argv[1],
-                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
-                              -1) == -1)
-    exit (EXIT_FAILURE);
-
-  if (guestfs_launch (g) == -1) exit (EXIT_FAILURE);
-
-  if (guestfs_mount_options (g, "", argv[2], "/") == -1) exit (EXIT_FAILURE);
-
-  if (guestfs_touch (g, "/hello") == -1) exit (EXIT_FAILURE);
-
-  guestfs_sync (g);
-  guestfs_close (g);
-  return 0;
-}
diff --git a/examples/inspect_vm.c b/examples/inspect_vm.c
new file mode 100644 (file)
index 0000000..4019a01
--- /dev/null
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <guestfs.h>
+
+static int
+compare_keys_len (const void *p1, const void *p2)
+{
+  const char *key1 = * (char * const *) p1;
+  const char *key2 = * (char * const *) p2;
+  return strlen (key1) - strlen (key2);
+}
+
+static int
+count_strings (char *const *argv)
+{
+  int c;
+
+  for (c = 0; argv[c]; ++c)
+    ;
+  return c;
+}
+
+int                                                                            
+main (int argc, char *argv[])
+{
+  guestfs_h *g;
+  const char *disk;
+  char **roots, *root, *str, **mountpoints, **lines;
+  size_t i, j;
+
+  if (argc != 2) {
+    fprintf (stderr, "usage: inspect_vm disk.img\n");
+    exit (EXIT_FAILURE);
+  }
+  disk = argv[1];
+
+  g = guestfs_create ();
+  if (g == NULL) {
+    perror ("failed to create libguestfs handle");
+    exit (EXIT_FAILURE);
+  }
+
+  /* Attach the disk image read-only to libguestfs. */
+  if (guestfs_add_drive_opts (g, disk,
+     /* GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", */
+        GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
+        -1) /* this marks end of optional arguments */
+      == -1)
+    exit (EXIT_FAILURE);
+
+  /* Run the libguestfs back-end. */
+  if (guestfs_launch (g) == -1)
+    exit (EXIT_FAILURE);
+
+  /* Ask libguestfs to inspect for operating systems. */
+  roots = guestfs_inspect_os (g);
+  if (roots == NULL)
+    exit (EXIT_FAILURE);
+  if (roots[0] == NULL) {
+    fprintf (stderr, "inspect_vm: no operating systems found\n");
+    exit (EXIT_FAILURE);
+  }
+
+  for (j = 0; roots[j] != NULL; ++j) {
+    root = roots[j];
+
+    printf ("Root device: %s\n", root);
+
+    /* Print basic information about the operating system. */
+    str = guestfs_inspect_get_product_name (g, root);
+    if (str)
+      printf ("  Product name: %s\n", str);
+    free (str);
+
+    printf ("  Version:      %d.%d\n",
+            guestfs_inspect_get_major_version (g, root),
+            guestfs_inspect_get_minor_version (g, root));
+
+    str = guestfs_inspect_get_type (g, root);
+    if (str)
+      printf ("  Type:         %s\n", str);
+    free (str);
+    str = guestfs_inspect_get_distro (g, root);
+    if (str)
+      printf ("  Distro:       %s\n", str);
+    free (str);
+
+    /* Mount up the disks, like guestfish -i.
+     *
+     * Sort keys by length, shortest first, so that we end up
+     * mounting the filesystems in the correct order.
+     */
+    mountpoints = guestfs_inspect_get_mountpoints (g, root);
+    if (mountpoints == NULL)
+      exit (EXIT_FAILURE);
+
+    qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
+           compare_keys_len);
+    for (i = 0; mountpoints[i] != NULL; i += 2) {
+      if (guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]) == -1)
+        exit (EXIT_FAILURE);
+      free (mountpoints[i]);
+      free (mountpoints[i+1]);
+    }
+    free (mountpoints);
+
+    /* If /etc/issue.net file exists, print up to 3 lines. */
+    if (guestfs_is_file (g, "/etc/issue.net") > 0) {
+      printf ("--- /etc/issue.net ---\n");
+      lines = guestfs_head_n (g, 3, "/etc/issue.net");
+      if (lines == NULL)
+        exit (EXIT_FAILURE);
+      for (i = 0; lines[i] != NULL; ++i) {
+        printf ("%s\n", lines[i]);
+        free (lines[i]);
+      }
+      free (lines);
+    }
+
+    /* Unmount everything. */
+    if (guestfs_umount_all (g) == -1)
+      exit (EXIT_FAILURE);
+
+    free (root);
+  }
+  free (roots);
+
+  guestfs_close (g);
+
+  exit (EXIT_SUCCESS);
+}
diff --git a/examples/to-xml.c b/examples/to-xml.c
deleted file mode 100644 (file)
index 45994cb..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/* 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 ...]
- */
-
-#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>
-
-/* 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 (EXIT_FAILURE);
-
-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[])
-{
-  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 (EXIT_FAILURE);
-  }
-
-  if (!(g = guestfs_create ())) {
-    fprintf (stderr, "Cannot create libguestfs handle.\n");
-    exit (EXIT_FAILURE);
-  }
-
-  for (i = 1; i < argc; ++i)
-    CALL (guestfs_add_drive_opts (g, argv[i],
-                                  GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
-                                  -1), -1);
-
-  CALL (guestfs_launch (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) {
-    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");
-  }
-  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] == '/') {
-        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]);
-      }
-    }
-
-    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 (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") != 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");
-
-  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 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 || isdigit (dev[strlen(dev)-1])) {
-    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) {
-      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");
-    }
-
-    free (parts[i]);
-  }
-  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");
-}
index 7cf4e0b..966fbd1 100644 (file)
@@ -52,6 +52,9 @@ need enough permissions to access the disk images.
 Libguestfs is a large API because it can do many things.  For a gentle
 introduction, please read the L</API OVERVIEW> section next.
 
+There are also some example programs in the L<guestfs-examples(3)>
+manual page.
+
 =head1 API OVERVIEW
 
 This section provides a gentler overview of the libguestfs API.  We
@@ -2083,6 +2086,7 @@ enough.
 
 =head1 SEE ALSO
 
+L<guestfs-examples(3)>,
 L<guestfish(1)>,
 L<guestmount(1)>,
 L<virt-cat(1)>,