mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
docs: Standard C examples, and guestfs-examples(3) man page.
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 $@
|
||||
|
||||
@@ -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).
|
||||
122
examples/create_disk.c
Normal file
122
examples/create_disk.c
Normal file
@@ -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);
|
||||
}
|
||||
63
examples/guestfs-examples.pod
Normal file
63
examples/guestfs-examples.pod
Normal file
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
132
examples/inspect_vm.c
Normal file
132
examples/inspect_vm.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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)>,
|
||||
|
||||
Reference in New Issue
Block a user