diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-05-13 22:53:01 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-05-13 22:53:01 +0100 |
commit | 46b6766156ace142443b36e20e55074c544ae6cc (patch) | |
tree | a2f0918a8f10b690147388963cf33722e6f602d1 /examples | |
parent | 7201a48d18d03bf3b16141bcff8c56e842d3b1c1 (diff) | |
download | libguestfs-46b6766156ace142443b36e20e55074c544ae6cc.tar.gz libguestfs-46b6766156ace142443b36e20e55074c544ae6cc.tar.xz libguestfs-46b6766156ace142443b36e20e55074c544ae6cc.zip |
examples: Add an example of using the mount-local API from C.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile.am | 15 | ||||
-rw-r--r-- | examples/mount_local.c | 156 |
2 files changed, 171 insertions, 0 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am index b6d9a865..81f22747 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -37,6 +37,9 @@ endif if HAVE_HIVEX noinst_PROGRAMS += virt-dhcp-address endif +if HAVE_FUSE +noinst_PROGRAMS += mount_local +endif if HAVE_LIBVIRT copy_over_SOURCES = copy_over.c @@ -75,6 +78,18 @@ inspect_vm_CFLAGS = \ inspect_vm_LDADD = \ $(top_builddir)/src/libguestfs.la +if HAVE_FUSE +mount_local_SOURCES = mount_local.c +mount_local_CFLAGS = \ + -DGUESTFS_WARN_DEPRECATED=1 \ + -I$(top_srcdir)/src -I$(top_builddir)/src \ + $(FUSE_CFLAGS) \ + $(WARN_CFLAGS) $(WERROR_CFLAGS) +mount_local_LDADD = \ + $(FUSE_LIBS) -lulockmgr \ + $(top_builddir)/src/libguestfs.la +endif + if HAVE_HIVEX virt_dhcp_address_SOURCES = virt-dhcp-address.c virt_dhcp_address_CFLAGS = \ diff --git a/examples/mount_local.c b/examples/mount_local.c new file mode 100644 index 00000000..526e426f --- /dev/null +++ b/examples/mount_local.c @@ -0,0 +1,156 @@ +/* Demonstrate the use of the 'mount-local' API. + * + * Run this program as (eg) mount_local /tmp/test.img. Note that + * '/tmp/test.img' is created or overwritten. Follow the instructions + * on screen. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/wait.h> + +#include <guestfs.h> + +static void +usage (void) +{ + fprintf (stderr, + "Usage: mount_local disk.img\n" + "\n" + "NOTE: disk.img will be created or overwritten.\n" + "\n"); +} + +int +main (int argc, char *argv[]) +{ + guestfs_h *g; + int fd; + char tempdir[] = "/tmp/mlXXXXXX"; + pid_t pid; + char *shell; + + if (argc != 2) { + usage (); + exit (EXIT_FAILURE); + } + + printf ("\n" + "This is the 'mount-local' demonstration program. Follow the\n" + "instructions on screen.\n" + "\n" + "Creating and formatting the disk image, please wait a moment ...\n"); + fflush (stdout); + + /* Create the output disk image: 512 MB raw sparse. */ + fd = open (argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644); + if (fd == -1) { + perror (argv[1]); + exit (EXIT_FAILURE); + } + if (ftruncate (fd, 512 * 1024 * 1024) == -1) { + perror ("truncate"); + close (fd); + exit (EXIT_FAILURE); + } + if (close (fd) == -1) { + perror ("close"); + exit (EXIT_FAILURE); + } + + /* Open the disk image and format it with a partition and a filesystem. */ + g = guestfs_create (); + if (g == NULL) { + perror ("could not create libguestfs handle"); + 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_part_disk (g, "/dev/sda", "mbr") == -1) + exit (EXIT_FAILURE); + + if (guestfs_mkfs (g, "ext2", "/dev/sda1") == -1) + exit (EXIT_FAILURE); + + /* Mount the empty filesystem. */ + if (guestfs_mount (g, "/dev/sda1", "/") == -1) + exit (EXIT_FAILURE); + + /* Create a temporary mount directory. */ + if (mkdtemp (tempdir) == NULL) { + perror ("mkdtemp"); + exit (EXIT_FAILURE); + } + + /* Mount the filesystem. */ + if (guestfs_mount_local (g, tempdir, -1) == -1) + exit (EXIT_FAILURE); + + /* Fork the shell for the user. */ + pid = fork (); + if (pid == -1) { + perror ("fork"); + exit (EXIT_FAILURE); + } + + if (pid == 0) { /* Child. */ + if (chdir (tempdir) == -1) { + perror (tempdir); + _exit (EXIT_FAILURE); + } + + printf ("\n" + "The _current directory_ is a FUSE filesystem backed by the disk\n" + "image which is managed by libguestfs. Any files or directories\n" + "you copy into here (up to 512 MB) will be saved into the disk\n" + "image. You can also delete files, create certain special files\n" + "and so on.\n" + "\n" + "When you have finished adding files, hit ^D or exit to exit the\n" + "shell and return to the mount-local program.\n" + "\n"); + + shell = getenv ("SHELL"); + system (shell ? : "/bin/sh"); + + chdir ("/"); + guestfs_umount_local (g, GUESTFS_UMOUNT_LOCAL_RETRY, 1, -1); + _exit (EXIT_SUCCESS); + } + + /* Note that we are *not* waiting for the child yet. We want to + * run the FUSE code in parallel with the subshell. + */ + if (guestfs_mount_local_run (g) == -1) + exit (EXIT_FAILURE); + + waitpid (pid, NULL, 0); + + /* Unmount and close. */ + if (guestfs_umount (g, "/") == -1) + exit (EXIT_FAILURE); + + guestfs_close (g); + + printf ("\n" + "Any files or directories that you copied in have been saved into\n" + "the disk image called '%s'.\n" + "\n" + "Try opening the disk image with guestfish to see those files:\n" + "\n" + " guestfish -a %s -m /dev/sda1\n" + "\n", + argv[1], argv[1]); + + exit (EXIT_SUCCESS); +} |