summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--daemon/actions.h13
-rw-r--r--daemon/daemon.h31
-rw-r--r--daemon/devsparts.c62
-rw-r--r--daemon/dir.c27
-rw-r--r--daemon/file.c74
-rw-r--r--daemon/guestfsd.c88
-rw-r--r--daemon/lvm.c131
-rw-r--r--daemon/mount.c115
-rw-r--r--daemon/proto.c8
-rw-r--r--daemon/stubs.c548
-rw-r--r--daemon/sync.c1
-rw-r--r--fish/cmds.c296
-rw-r--r--fish/fish.c35
-rw-r--r--fish/fish.h3
-rw-r--r--guestfish-actions.pod141
-rw-r--r--guestfs-actions.pod185
-rw-r--r--libguestfs.spec.in4
-rwxr-xr-xmake-initramfs.sh.in4
-rw-r--r--ocaml/guestfs.ml13
-rw-r--r--ocaml/guestfs.mli39
-rw-r--r--ocaml/guestfs_c.c26
-rw-r--r--ocaml/guestfs_c.h2
-rw-r--r--ocaml/guestfs_c_actions.c318
-rw-r--r--perl/Guestfs.xs318
-rw-r--r--perl/lib/Sys/Guestfs.pm169
-rwxr-xr-xsrc/generator.ml1046
-rw-r--r--src/guestfs-actions.c931
-rw-r--r--src/guestfs-actions.h13
-rw-r--r--src/guestfs_protocol.c208
-rw-r--r--src/guestfs_protocol.h132
-rw-r--r--src/guestfs_protocol.x79
-rw-r--r--tests.c3933
33 files changed, 8670 insertions, 325 deletions
diff --git a/Makefile.am b/Makefile.am
index 47954a50..2345018f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -72,6 +72,8 @@ tests_LDADD = $(top_builddir)/src/libguestfs.la
TESTS = $(check_PROGRAMS)
+$(TESTS): $(INITRAMFS) $(VMLINUZ)
+
# Manual pages.
# guestfs-actions.pod and guestfs-structs are autogenerated. There is
# no include mechanism for POD, so we have to do it by hand.
diff --git a/daemon/actions.h b/daemon/actions.h
index 1b35cad1..2a9d3d1d 100644
--- a/daemon/actions.h
+++ b/daemon/actions.h
@@ -56,3 +56,16 @@ extern int do_mkdir (const char *path);
extern int do_mkdir_p (const char *path);
extern int do_chmod (int mode, const char *path);
extern int do_chown (int owner, int group, const char *path);
+extern int do_exists (const char *path);
+extern int do_is_file (const char *path);
+extern int do_is_dir (const char *path);
+extern int do_pvcreate (const char *device);
+extern int do_vgcreate (const char *volgroup, char * const* const physvols);
+extern int do_lvcreate (const char *logvol, const char *volgroup, int mbytes);
+extern int do_mkfs (const char *fstype, const char *device);
+extern int do_sfdisk (const char *device, int cyls, int heads, int sectors, char * const* const lines);
+extern int do_write_file (const char *path, const char *content, int size);
+extern int do_umount (const char *pathordevice);
+extern char **do_mounts (void);
+extern int do_umount_all (void);
+extern int do_lvm_remove_all (void);
diff --git a/daemon/daemon.h b/daemon/daemon.h
index b2396a19..27d86c9b 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -21,6 +21,9 @@
#include <stdarg.h>
#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
@@ -28,16 +31,18 @@
#include "../src/guestfs_protocol.h"
/* in guestfsd.c */
-extern void xwrite (int sock, const void *buf, size_t len);
-extern void xread (int sock, void *buf, size_t len);
+extern int xwrite (int sock, const void *buf, size_t len);
+extern int xread (int sock, void *buf, size_t len);
extern int add_string (char ***argv, int *size, int *alloc, const char *str);
-extern int count_strings (char **argv);
+extern int count_strings (char * const* const argv);
extern void sort_strings (char **argv, int len);
extern void free_strings (char **argv);
extern void free_stringslen (char **argv, int len);
extern int command (char **stdoutput, char **stderror, const char *name, ...);
+extern int commandv (char **stdoutput, char **stderror,
+ char * const* const argv);
/* in proto.c */
extern int proc_nr;
@@ -75,6 +80,19 @@ extern void reply (xdrproc_t xdrp, char *ret);
} \
} while (0)
+#define IS_DEVICE(path,errcode) \
+ do { \
+ struct stat statbuf; \
+ if (strncmp ((path), "/dev/", 5) != 0) { \
+ reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \
+ return (errcode); \
+ } \
+ if (stat ((path), &statbuf) == -1) { \
+ reply_with_perror ("%s: %s", __func__, (path)); \
+ return (errcode); \
+ } \
+ } while (0)
+
/* NB:
* (1) You must match CHROOT_IN and CHROOT_OUT even along error paths.
* (2) You must not change directory! cwd must always be "/", otherwise
@@ -86,4 +104,11 @@ extern void reply (xdrproc_t xdrp, char *ret);
#define CHROOT_OUT \
do { int old_errno = errno; chroot ("."); errno = old_errno; } while (0)
+#define XXX_NOT_IMPL(errcode) \
+ do { \
+ reply_with_error ("%s: function not implemented", __func__); \
+ return (errcode); \
+ } \
+ while (0)
+
#endif /* GUESTFSD_DAEMON_H */
diff --git a/daemon/devsparts.c b/daemon/devsparts.c
index b0d79569..324b8870 100644
--- a/daemon/devsparts.c
+++ b/daemon/devsparts.c
@@ -131,3 +131,65 @@ do_list_partitions (void)
sort_strings (r, size-1);
return r;
}
+
+int
+do_mkfs (const char *fstype, const char *device)
+{
+ char *err;
+ int r;
+
+ IS_DEVICE (device, -1);
+
+ r = command (NULL, &err, "/sbin/mkfs", "-t", fstype, device, NULL);
+ if (r == -1) {
+ reply_with_error ("mkfs: %s", err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
+
+int
+do_sfdisk (const char *device, int cyls, int heads, int sectors,
+ char * const* const lines)
+{
+ FILE *fp;
+ char buf[256];
+ int i;
+
+ IS_DEVICE (device, -1);
+
+ /* Safe because of IS_DEVICE above. */
+ strcpy (buf, "/sbin/sfdisk");
+ if (cyls)
+ sprintf (buf + strlen (buf), " -C %d", cyls);
+ if (heads)
+ sprintf (buf + strlen (buf), " -H %d", heads);
+ if (sectors)
+ sprintf (buf + strlen (buf), " -S %d", sectors);
+ sprintf (buf + strlen (buf), " %s", device);
+
+ fp = popen (buf, "w");
+ if (fp == NULL) {
+ reply_with_perror (buf);
+ return -1;
+ }
+
+ for (i = 0; lines[i] != NULL; ++i) {
+ if (fprintf (fp, "%s\n", lines[i]) < 0) {
+ reply_with_perror (buf);
+ fclose (fp);
+ return -1;
+ }
+ }
+
+ if (fclose (fp) == EOF) {
+ reply_with_perror (buf);
+ fclose (fp);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/daemon/dir.c b/daemon/dir.c
index 7892682f..f7064660 100644
--- a/daemon/dir.c
+++ b/daemon/dir.c
@@ -76,7 +76,7 @@ do_rm_rf (const char *path)
snprintf (buf, len, "/sysroot%s", path);
- r = command (NULL, &err, "rm", "-rf", buf);
+ r = command (NULL, &err, "rm", "-rf", buf, NULL);
free (buf);
/* rm -rf is never supposed to fail. I/O errors perhaps? */
@@ -165,3 +165,28 @@ do_mkdir_p (const char *path)
return 0;
}
+
+int
+do_is_dir (const char *path)
+{
+ int r;
+ struct stat buf;
+
+ NEED_ROOT (-1);
+ ABS_PATH (path, -1);
+
+ CHROOT_IN;
+ r = lstat (path, &buf);
+ CHROOT_OUT;
+
+ if (r == -1) {
+ if (errno != ENOENT && errno != ENOTDIR) {
+ reply_with_perror ("stat: %s", path);
+ return -1;
+ }
+ else
+ return 0; /* Not a directory. */
+ }
+
+ return S_ISDIR (buf.st_mode);
+}
diff --git a/daemon/file.c b/daemon/file.c
index 43c875cc..0b8b463c 100644
--- a/daemon/file.c
+++ b/daemon/file.c
@@ -240,3 +240,77 @@ do_chown (int owner, int group, const char *path)
return 0;
}
+
+int
+do_exists (const char *path)
+{
+ int r;
+
+ NEED_ROOT (-1);
+ ABS_PATH (path, -1);
+
+ CHROOT_IN;
+ r = access (path, F_OK);
+ CHROOT_OUT;
+
+ return r == 0;
+}
+
+int
+do_is_file (const char *path)
+{
+ int r;
+ struct stat buf;
+
+ NEED_ROOT (-1);
+ ABS_PATH (path, -1);
+
+ CHROOT_IN;
+ r = lstat (path, &buf);
+ CHROOT_OUT;
+
+ if (r == -1) {
+ if (errno != ENOENT && errno != ENOTDIR) {
+ reply_with_perror ("stat: %s", path);
+ return -1;
+ }
+ else
+ return 0; /* Not a file. */
+ }
+
+ return S_ISREG (buf.st_mode);
+}
+
+int
+do_write_file (const char *path, const char *content, int size)
+{
+ int fd;
+
+ NEED_ROOT (-1);
+ ABS_PATH (path, -1);
+
+ if (size == 0)
+ size = strlen (content);
+
+ CHROOT_IN;
+ fd = open (path, O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK, 0666);
+ CHROOT_OUT;
+
+ if (fd == -1) {
+ reply_with_perror ("open: %s", path);
+ return -1;
+ }
+
+ if (xwrite (fd, content, size) == -1) {
+ reply_with_perror ("write");
+ close (fd);
+ return -1;
+ }
+
+ if (close (fd) == -1) {
+ reply_with_perror ("close: %s", path);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index a243c0be..c701f194 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -170,7 +170,7 @@ main (int argc, char *argv[])
exit (1);
}
- xwrite (sock, buf, xdr_getpos (&xdr));
+ (void) xwrite (sock, buf, xdr_getpos (&xdr));
xdr_destroy (&xdr);
@@ -188,7 +188,7 @@ main (int argc, char *argv[])
exit (0);
}
-void
+int
xwrite (int sock, const void *buf, size_t len)
{
int r;
@@ -197,14 +197,16 @@ xwrite (int sock, const void *buf, size_t len)
r = write (sock, buf, len);
if (r == -1) {
perror ("write");
- exit (1);
+ return -1;
}
buf += r;
len -= r;
}
+
+ return 0;
}
-void
+int
xread (int sock, void *buf, size_t len)
{
int r;
@@ -213,15 +215,17 @@ xread (int sock, void *buf, size_t len)
r = read (sock, buf, len);
if (r == -1) {
perror ("read");
- exit (1);
+ return -1;
}
if (r == 0) {
- fprintf (stderr, "read: unexpected end of file on comms socket\n");
- exit (1);
+ fprintf (stderr, "read: unexpected end of file on fd %d\n", sock);
+ return -1;
}
buf += r;
len -= r;
}
+
+ return 0;
}
static void
@@ -263,7 +267,7 @@ add_string (char ***argv, int *size, int *alloc, const char *str)
}
int
-count_strings (char **argv)
+count_strings (char * const* const argv)
{
int argc;
@@ -314,15 +318,52 @@ free_stringslen (char **argv, int len)
int
command (char **stdoutput, char **stderror, const char *name, ...)
{
+ va_list args;
+ char **argv;
+ char *s;
+ int i, r;
+
+ /* Collect the command line arguments into an array. */
+ va_start (args, name);
+
+ i = 2;
+ argv = malloc (sizeof (char *) * i);
+ argv[0] = (char *) name;
+ argv[1] = NULL;
+
+ while ((s = va_arg (args, char *)) != NULL) {
+ argv = realloc (argv, sizeof (char *) * (++i));
+ argv[i-2] = s;
+ argv[i-1] = NULL;
+ }
+
+ va_end (args);
+
+ r = commandv (stdoutput, stderror, argv);
+
+ /* NB: Mustn't free the strings which are on the stack. */
+ free (argv);
+
+ return r;
+}
+
+int
+commandv (char **stdoutput, char **stderror, char * const* const argv)
+{
int so_size = 0, se_size = 0;
int so_fd[2], se_fd[2];
- int pid, r, quit;
+ int pid, r, quit, i;
fd_set rset, rset2;
char buf[256];
if (stdoutput) *stdoutput = NULL;
if (stderror) *stderror = NULL;
+ printf ("%s", argv[0]);
+ for (i = 1; argv[i] != NULL; ++i)
+ printf (" %s", argv[i]);
+ printf ("\n");
+
if (pipe (so_fd) == -1 || pipe (se_fd) == -1) {
perror ("pipe");
return -1;
@@ -335,25 +376,6 @@ command (char **stdoutput, char **stderror, const char *name, ...)
}
if (pid == 0) { /* Child process. */
- va_list args;
- char **argv;
- char *s;
- int i;
-
- /* Collect the command line arguments into an array. */
- va_start (args, name);
-
- i = 2;
- argv = malloc (sizeof (char *) * i);
- argv[0] = (char *) name;
- argv[1] = NULL;
-
- while ((s = va_arg (args, char *)) != NULL) {
- argv = realloc (argv, sizeof (char *) * (++i));
- argv[i-2] = s;
- argv[i-1] = NULL;
- }
-
close (0);
close (so_fd[0]);
close (se_fd[0]);
@@ -362,8 +384,8 @@ command (char **stdoutput, char **stderror, const char *name, ...)
close (so_fd[1]);
close (se_fd[1]);
- execvp (name, argv);
- perror (name);
+ execvp (argv[0], argv);
+ perror (argv[0]);
_exit (1);
}
@@ -376,7 +398,7 @@ command (char **stdoutput, char **stderror, const char *name, ...)
FD_SET (se_fd[0], &rset);
quit = 0;
- while (!quit) {
+ while (quit < 2) {
rset2 = rset;
r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL);
if (r == -1) {
@@ -392,7 +414,7 @@ command (char **stdoutput, char **stderror, const char *name, ...)
waitpid (pid, NULL, 0);
return -1;
}
- if (r == 0) quit = 1;
+ if (r == 0) { FD_CLR (so_fd[0], &rset); quit++; }
if (r > 0 && stdoutput) {
so_size += r;
@@ -413,7 +435,7 @@ command (char **stdoutput, char **stderror, const char *name, ...)
waitpid (pid, NULL, 0);
return -1;
}
- if (r == 0) quit = 1;
+ if (r == 0) { FD_CLR (se_fd[0], &rset); quit++; }
if (r > 0 && stderror) {
se_size += r;
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 7f31c84e..55b41f02 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -169,3 +169,134 @@ do_lvs_full (void)
{
return parse_command_line_lvs ();
}
+
+int
+do_pvcreate (const char *device)
+{
+ char *err;
+ int r;
+
+ r = command (NULL, &err,
+ "/sbin/lvm", "pvcreate", device, NULL);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
+
+int
+do_vgcreate (const char *volgroup, char * const* const physvols)
+{
+ char *err;
+ int r, argc, i;
+ const char **argv;
+
+ argc = count_strings (physvols) + 3;
+ argv = malloc (sizeof (char *) * (argc + 1));
+ argv[0] = "/sbin/lvm";
+ argv[1] = "vgcreate";
+ argv[2] = volgroup;
+ for (i = 3; i <= argc; ++i)
+ argv[i] = physvols[i-3];
+
+ r = commandv (NULL, &err, argv);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
+
+int
+do_lvcreate (const char *logvol, const char *volgroup, int mbytes)
+{
+ char *err;
+ int r;
+ char size[64];
+
+ snprintf (size, sizeof size, "%d", mbytes);
+
+ r = command (NULL, &err,
+ "/sbin/lvm", "lvcreate",
+ "-L", size, "-n", logvol, volgroup, NULL);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
+
+/* Super-dangerous command used for testing. It removes all
+ * LVs, VGs and PVs permanently.
+ */
+int
+do_lvm_remove_all (void)
+{
+ char **xs;
+ int i, r;
+ char *err;
+
+ /* Remove LVs. */
+ xs = do_lvs ();
+ if (xs == NULL)
+ return -1;
+
+ for (i = 0; xs[i] != NULL; ++i) {
+ r = command (NULL, &err, "/sbin/lvm", "lvremove", "-f", xs[i], NULL);
+ if (r == -1) {
+ reply_with_error ("lvremove: %s: %s", xs[i], err);
+ free (err);
+ free_strings (xs);
+ return -1;
+ }
+ free (err);
+ }
+ free_strings (xs);
+
+ /* Remove VGs. */
+ xs = do_vgs ();
+ if (xs == NULL)
+ return -1;
+
+ for (i = 0; xs[i] != NULL; ++i) {
+ r = command (NULL, &err, "/sbin/lvm", "vgremove", "-f", xs[i], NULL);
+ if (r == -1) {
+ reply_with_error ("vgremove: %s: %s", xs[i], err);
+ free (err);
+ free_strings (xs);
+ return -1;
+ }
+ free (err);
+ }
+ free_strings (xs);
+
+ /* Remove PVs. */
+ xs = do_pvs ();
+ if (xs == NULL)
+ return -1;
+
+ for (i = 0; xs[i] != NULL; ++i) {
+ r = command (NULL, &err, "/sbin/lvm", "pvremove", "-f", xs[i], NULL);
+ if (r == -1) {
+ reply_with_error ("pvremove: %s: %s", xs[i], err);
+ free (err);
+ free_strings (xs);
+ return -1;
+ }
+ free (err);
+ }
+ free_strings (xs);
+
+ /* There, that was easy, sorry about your data. */
+ return 0;
+}
diff --git a/daemon/mount.c b/daemon/mount.c
index 440ec0de..fd9c8e43 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -74,3 +74,118 @@ do_mount (const char *device, const char *mountpoint)
return 0;
}
+
+/* Again, use the external /bin/umount program, so that /etc/mtab
+ * is kept updated.
+ */
+int
+do_umount (const char *pathordevice)
+{
+ int len, freeit = 0, r;
+ char *buf;
+ char *err;
+
+ if (strncmp (pathordevice, "/dev/", 5) == 0)
+ buf = (char *) pathordevice;
+ else {
+ len = strlen (pathordevice) + 9;
+ freeit = 1;
+ buf = malloc (len);
+ if (buf == NULL) {
+ reply_with_perror ("malloc");
+ return -1;
+ }
+ snprintf (buf, len, "/sysroot%s", pathordevice);
+ }
+
+ r = command (NULL, &err, "umount", buf, NULL);
+ if (freeit) free (buf);
+ if (r == -1) {
+ reply_with_error ("umount: %s: %s", pathordevice, err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+
+ /* update root_mounted? */
+
+ return 0;
+}
+
+char **
+do_mounts (void)
+{
+ char *out, *err;
+ int r;
+ char **ret = NULL;
+ int size = 0, alloc = 0;
+ char *p, *pend, *p2;
+
+ r = command (&out, &err, "mount", NULL);
+ if (r == -1) {
+ reply_with_error ("mount: %s", err);
+ free (out);
+ free (err);
+ return NULL;
+ }
+
+ free (err);
+
+ p = out;
+ while (p) {
+ pend = strchr (p, '\n');
+ if (pend) {
+ *pend = '\0';
+ pend++;
+ }
+
+ /* Lines have the format:
+ * /dev/foo on /mountpoint type ...
+ */
+ p2 = strstr (p, " on /sysroot");
+ if (p2 != NULL) {
+ *p2 = '\0';
+ if (add_string (&ret, &size, &alloc, p) == -1) {
+ free (out);
+ return NULL;
+ }
+ }
+
+ p = pend;
+ }
+
+ free (out);
+
+ if (add_string (&ret, &size, &alloc, NULL) == -1)
+ return NULL;
+
+ return ret;
+}
+
+/* Only unmount stuff under /sysroot */
+int
+do_umount_all (void)
+{
+ char **mounts;
+ int i, r;
+ char *err;
+
+ mounts = do_mounts ();
+ if (mounts == NULL) /* do_mounts has already replied */
+ return -1;
+
+ for (i = 0; mounts[i] != NULL; ++i) {
+ r = command (NULL, &err, "umount", mounts[i], NULL);
+ if (r == -1) {
+ reply_with_error ("umount: %s: %s", mounts[i], err);
+ free (err);
+ free_strings (mounts);
+ return -1;
+ }
+ free (err);
+ }
+
+ free_strings (mounts);
+ return 0;
+}
diff --git a/daemon/proto.c b/daemon/proto.c
index 93d33c2c..42bc6eaa 100644
--- a/daemon/proto.c
+++ b/daemon/proto.c
@@ -206,8 +206,8 @@ send_error (const char *msg)
xdr_uint32_t (&xdr, &len);
xdr_destroy (&xdr);
- xwrite (sock, lenbuf, 4);
- xwrite (sock, buf, len);
+ (void) xwrite (sock, lenbuf, 4);
+ (void) xwrite (sock, buf, len);
}
void
@@ -247,6 +247,6 @@ reply (xdrproc_t xdrp, char *ret)
xdr_uint32_t (&xdr, &len);
xdr_destroy (&xdr);
- xwrite (sock, lenbuf, 4);
- xwrite (sock, buf, len);
+ (void) xwrite (sock, lenbuf, 4);
+ (void) xwrite (sock, buf, len);
}
diff --git a/daemon/stubs.c b/daemon/stubs.c
index 1227fa88..4540ca56 100644
--- a/daemon/stubs.c
+++ b/daemon/stubs.c
@@ -51,10 +51,12 @@ static void mount_stub (XDR *xdr_in)
r = do_mount (device, mountpoint);
if (r == -1)
- /* do_mount has already called reply_with_error, so just return */
- return;
+ /* do_mount has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_mount_args, (char *) &args);
}
static void sync_stub (XDR *xdr_in)
@@ -63,10 +65,11 @@ static void sync_stub (XDR *xdr_in)
r = do_sync ();
if (r == -1)
- /* do_sync has already called reply_with_error, so just return */
- return;
+ /* do_sync has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done: ;
}
static void touch_stub (XDR *xdr_in)
@@ -85,10 +88,12 @@ static void touch_stub (XDR *xdr_in)
r = do_touch (path);
if (r == -1)
- /* do_touch has already called reply_with_error, so just return */
- return;
+ /* do_touch has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
}
static void cat_stub (XDR *xdr_in)
@@ -107,13 +112,15 @@ static void cat_stub (XDR *xdr_in)
r = do_cat (path);
if (r == NULL)
- /* do_cat has already called reply_with_error, so just return */
- return;
+ /* do_cat has already called reply_with_error */
+ goto done;
struct guestfs_cat_ret ret;
ret.content = r;
reply ((xdrproc_t) &xdr_guestfs_cat_ret, (char *) &ret);
free (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_cat_args, (char *) &args);
}
static void ll_stub (XDR *xdr_in)
@@ -132,13 +139,15 @@ static void ll_stub (XDR *xdr_in)
r = do_ll (directory);
if (r == NULL)
- /* do_ll has already called reply_with_error, so just return */
- return;
+ /* do_ll has already called reply_with_error */
+ goto done;
struct guestfs_ll_ret ret;
ret.listing = r;
reply ((xdrproc_t) &xdr_guestfs_ll_ret, (char *) &ret);
free (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_ll_args, (char *) &args);
}
static void ls_stub (XDR *xdr_in)
@@ -157,14 +166,16 @@ static void ls_stub (XDR *xdr_in)
r = do_ls (directory);
if (r == NULL)
- /* do_ls has already called reply_with_error, so just return */
- return;
+ /* do_ls has already called reply_with_error */
+ goto done;
struct guestfs_ls_ret ret;
ret.listing.listing_len = count_strings (r);
ret.listing.listing_val = r;
reply ((xdrproc_t) &xdr_guestfs_ls_ret, (char *) &ret);
free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_ls_args, (char *) &args);
}
static void list_devices_stub (XDR *xdr_in)
@@ -173,14 +184,15 @@ static void list_devices_stub (XDR *xdr_in)
r = do_list_devices ();
if (r == NULL)
- /* do_list_devices has already called reply_with_error, so just return */
- return;
+ /* do_list_devices has already called reply_with_error */
+ goto done;
struct guestfs_list_devices_ret ret;
ret.devices.devices_len = count_strings (r);
ret.devices.devices_val = r;
reply ((xdrproc_t) &xdr_guestfs_list_devices_ret, (char *) &ret);
free_strings (r);
+done: ;
}
static void list_partitions_stub (XDR *xdr_in)
@@ -189,14 +201,15 @@ static void list_partitions_stub (XDR *xdr_in)
r = do_list_partitions ();
if (r == NULL)
- /* do_list_partitions has already called reply_with_error, so just return */
- return;
+ /* do_list_partitions has already called reply_with_error */
+ goto done;
struct guestfs_list_partitions_ret ret;
ret.partitions.partitions_len = count_strings (r);
ret.partitions.partitions_val = r;
reply ((xdrproc_t) &xdr_guestfs_list_partitions_ret, (char *) &ret);
free_strings (r);
+done: ;
}
static void pvs_stub (XDR *xdr_in)
@@ -205,14 +218,15 @@ static void pvs_stub (XDR *xdr_in)
r = do_pvs ();
if (r == NULL)
- /* do_pvs has already called reply_with_error, so just return */
- return;
+ /* do_pvs has already called reply_with_error */
+ goto done;
struct guestfs_pvs_ret ret;
ret.physvols.physvols_len = count_strings (r);
ret.physvols.physvols_val = r;
reply ((xdrproc_t) &xdr_guestfs_pvs_ret, (char *) &ret);
free_strings (r);
+done: ;
}
static void vgs_stub (XDR *xdr_in)
@@ -221,14 +235,15 @@ static void vgs_stub (XDR *xdr_in)
r = do_vgs ();
if (r == NULL)
- /* do_vgs has already called reply_with_error, so just return */
- return;
+ /* do_vgs has already called reply_with_error */
+ goto done;
struct guestfs_vgs_ret ret;
ret.volgroups.volgroups_len = count_strings (r);
ret.volgroups.volgroups_val = r;
reply ((xdrproc_t) &xdr_guestfs_vgs_ret, (char *) &ret);
free_strings (r);
+done: ;
}
static void lvs_stub (XDR *xdr_in)
@@ -237,14 +252,15 @@ static void lvs_stub (XDR *xdr_in)
r = do_lvs ();
if (r == NULL)
- /* do_lvs has already called reply_with_error, so just return */
- return;
+ /* do_lvs has already called reply_with_error */
+ goto done;
struct guestfs_lvs_ret ret;
ret.logvols.logvols_len = count_strings (r);
ret.logvols.logvols_val = r;
reply ((xdrproc_t) &xdr_guestfs_lvs_ret, (char *) &ret);
free_strings (r);
+done: ;
}
static void pvs_full_stub (XDR *xdr_in)
@@ -253,13 +269,14 @@ static void pvs_full_stub (XDR *xdr_in)
r = do_pvs_full ();
if (r == NULL)
- /* do_pvs_full has already called reply_with_error, so just return */
- return;
+ /* do_pvs_full has already called reply_with_error */
+ goto done;
struct guestfs_pvs_full_ret ret;
ret.physvols = *r;
reply ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret);
xdr_free ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret);
+done: ;
}
static void vgs_full_stub (XDR *xdr_in)
@@ -268,13 +285,14 @@ static void vgs_full_stub (XDR *xdr_in)
r = do_vgs_full ();
if (r == NULL)
- /* do_vgs_full has already called reply_with_error, so just return */
- return;
+ /* do_vgs_full has already called reply_with_error */
+ goto done;
struct guestfs_vgs_full_ret ret;
ret.volgroups = *r;
reply ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret);
xdr_free ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret);
+done: ;
}
static void lvs_full_stub (XDR *xdr_in)
@@ -283,13 +301,14 @@ static void lvs_full_stub (XDR *xdr_in)
r = do_lvs_full ();
if (r == NULL)
- /* do_lvs_full has already called reply_with_error, so just return */
- return;
+ /* do_lvs_full has already called reply_with_error */
+ goto done;
struct guestfs_lvs_full_ret ret;
ret.logvols = *r;
reply ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret);
xdr_free ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret);
+done: ;
}
static void read_lines_stub (XDR *xdr_in)
@@ -308,14 +327,16 @@ static void read_lines_stub (XDR *xdr_in)
r = do_read_lines (path);
if (r == NULL)
- /* do_read_lines has already called reply_with_error, so just return */
- return;
+ /* do_read_lines has already called reply_with_error */
+ goto done;
struct guestfs_read_lines_ret ret;
ret.lines.lines_len = count_strings (r);
ret.lines.lines_val = r;
reply ((xdrproc_t) &xdr_guestfs_read_lines_ret, (char *) &ret);
free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_read_lines_args, (char *) &args);
}
static void aug_init_stub (XDR *xdr_in)
@@ -336,10 +357,12 @@ static void aug_init_stub (XDR *xdr_in)
r = do_aug_init (root, flags);
if (r == -1)
- /* do_aug_init has already called reply_with_error, so just return */
- return;
+ /* do_aug_init has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_init_args, (char *) &args);
}
static void aug_close_stub (XDR *xdr_in)
@@ -348,10 +371,11 @@ static void aug_close_stub (XDR *xdr_in)
r = do_aug_close ();
if (r == -1)
- /* do_aug_close has already called reply_with_error, so just return */
- return;
+ /* do_aug_close has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done: ;
}
static void aug_defvar_stub (XDR *xdr_in)
@@ -372,12 +396,14 @@ static void aug_defvar_stub (XDR *xdr_in)
r = do_aug_defvar (name, expr);
if (r == -1)
- /* do_aug_defvar has already called reply_with_error, so just return */
- return;
+ /* do_aug_defvar has already called reply_with_error */
+ goto done;
struct guestfs_aug_defvar_ret ret;
ret.nrnodes = r;
reply ((xdrproc_t) &xdr_guestfs_aug_defvar_ret, (char *) &ret);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_defvar_args, (char *) &args);
}
static void aug_defnode_stub (XDR *xdr_in)
@@ -400,11 +426,13 @@ static void aug_defnode_stub (XDR *xdr_in)
r = do_aug_defnode (name, expr, val);
if (r == NULL)
- /* do_aug_defnode has already called reply_with_error, so just return */
- return;
+ /* do_aug_defnode has already called reply_with_error */
+ goto done;
reply ((xdrproc_t) xdr_guestfs_aug_defnode_ret, (char *) r);
xdr_free ((xdrproc_t) xdr_guestfs_aug_defnode_ret, (char *) r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_defnode_args, (char *) &args);
}
static void aug_get_stub (XDR *xdr_in)
@@ -423,13 +451,15 @@ static void aug_get_stub (XDR *xdr_in)
r = do_aug_get (path);
if (r == NULL)
- /* do_aug_get has already called reply_with_error, so just return */
- return;
+ /* do_aug_get has already called reply_with_error */
+ goto done;
struct guestfs_aug_get_ret ret;
ret.val = r;
reply ((xdrproc_t) &xdr_guestfs_aug_get_ret, (char *) &ret);
free (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_get_args, (char *) &args);
}
static void aug_set_stub (XDR *xdr_in)
@@ -450,10 +480,12 @@ static void aug_set_stub (XDR *xdr_in)
r = do_aug_set (path, val);
if (r == -1)
- /* do_aug_set has already called reply_with_error, so just return */
- return;
+ /* do_aug_set has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_set_args, (char *) &args);
}
static void aug_insert_stub (XDR *xdr_in)
@@ -476,10 +508,12 @@ static void aug_insert_stub (XDR *xdr_in)
r = do_aug_insert (path, label, before);
if (r == -1)
- /* do_aug_insert has already called reply_with_error, so just return */
- return;
+ /* do_aug_insert has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_insert_args, (char *) &args);
}
static void aug_rm_stub (XDR *xdr_in)
@@ -498,12 +532,14 @@ static void aug_rm_stub (XDR *xdr_in)
r = do_aug_rm (path);
if (r == -1)
- /* do_aug_rm has already called reply_with_error, so just return */
- return;
+ /* do_aug_rm has already called reply_with_error */
+ goto done;
struct guestfs_aug_rm_ret ret;
ret.nrnodes = r;
reply ((xdrproc_t) &xdr_guestfs_aug_rm_ret, (char *) &ret);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_rm_args, (char *) &args);
}
static void aug_mv_stub (XDR *xdr_in)
@@ -524,10 +560,12 @@ static void aug_mv_stub (XDR *xdr_in)
r = do_aug_mv (src, dest);
if (r == -1)
- /* do_aug_mv has already called reply_with_error, so just return */
- return;
+ /* do_aug_mv has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_mv_args, (char *) &args);
}
static void aug_match_stub (XDR *xdr_in)
@@ -546,14 +584,16 @@ static void aug_match_stub (XDR *xdr_in)
r = do_aug_match (path);
if (r == NULL)
- /* do_aug_match has already called reply_with_error, so just return */
- return;
+ /* do_aug_match has already called reply_with_error */
+ goto done;
struct guestfs_aug_match_ret ret;
ret.matches.matches_len = count_strings (r);
ret.matches.matches_val = r;
reply ((xdrproc_t) &xdr_guestfs_aug_match_ret, (char *) &ret);
free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_match_args, (char *) &args);
}
static void aug_save_stub (XDR *xdr_in)
@@ -562,10 +602,11 @@ static void aug_save_stub (XDR *xdr_in)
r = do_aug_save ();
if (r == -1)
- /* do_aug_save has already called reply_with_error, so just return */
- return;
+ /* do_aug_save has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done: ;
}
static void aug_load_stub (XDR *xdr_in)
@@ -574,10 +615,11 @@ static void aug_load_stub (XDR *xdr_in)
r = do_aug_load ();
if (r == -1)
- /* do_aug_load has already called reply_with_error, so just return */
- return;
+ /* do_aug_load has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done: ;
}
static void aug_ls_stub (XDR *xdr_in)
@@ -596,14 +638,16 @@ static void aug_ls_stub (XDR *xdr_in)
r = do_aug_ls (path);
if (r == NULL)
- /* do_aug_ls has already called reply_with_error, so just return */
- return;
+ /* do_aug_ls has already called reply_with_error */
+ goto done;
struct guestfs_aug_ls_ret ret;
ret.matches.matches_len = count_strings (r);
ret.matches.matches_val = r;
reply ((xdrproc_t) &xdr_guestfs_aug_ls_ret, (char *) &ret);
free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args);
}
static void rm_stub (XDR *xdr_in)
@@ -622,10 +666,12 @@ static void rm_stub (XDR *xdr_in)
r = do_rm (path);
if (r == -1)
- /* do_rm has already called reply_with_error, so just return */
- return;
+ /* do_rm has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_rm_args, (char *) &args);
}
static void rmdir_stub (XDR *xdr_in)
@@ -644,10 +690,12 @@ static void rmdir_stub (XDR *xdr_in)
r = do_rmdir (path);
if (r == -1)
- /* do_rmdir has already called reply_with_error, so just return */
- return;
+ /* do_rmdir has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_rmdir_args, (char *) &args);
}
static void rm_rf_stub (XDR *xdr_in)
@@ -666,10 +714,12 @@ static void rm_rf_stub (XDR *xdr_in)
r = do_rm_rf (path);
if (r == -1)
- /* do_rm_rf has already called reply_with_error, so just return */
- return;
+ /* do_rm_rf has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_rm_rf_args, (char *) &args);
}
static void mkdir_stub (XDR *xdr_in)
@@ -688,10 +738,12 @@ static void mkdir_stub (XDR *xdr_in)
r = do_mkdir (path);
if (r == -1)
- /* do_mkdir has already called reply_with_error, so just return */
- return;
+ /* do_mkdir has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_mkdir_args, (char *) &args);
}
static void mkdir_p_stub (XDR *xdr_in)
@@ -710,10 +762,12 @@ static void mkdir_p_stub (XDR *xdr_in)
r = do_mkdir_p (path);
if (r == -1)
- /* do_mkdir_p has already called reply_with_error, so just return */
- return;
+ /* do_mkdir_p has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_mkdir_p_args, (char *) &args);
}
static void chmod_stub (XDR *xdr_in)
@@ -734,10 +788,12 @@ static void chmod_stub (XDR *xdr_in)
r = do_chmod (mode, path);
if (r == -1)
- /* do_chmod has already called reply_with_error, so just return */
- return;
+ /* do_chmod has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_chmod_args, (char *) &args);
}
static void chown_stub (XDR *xdr_in)
@@ -760,10 +816,325 @@ static void chown_stub (XDR *xdr_in)
r = do_chown (owner, group, path);
if (r == -1)
- /* do_chown has already called reply_with_error, so just return */
+ /* do_chown has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_chown_args, (char *) &args);
+}
+
+static void exists_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_exists_args args;
+ const char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_exists_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "exists");
return;
+ }
+ path = args.path;
+
+ r = do_exists (path);
+ if (r == -1)
+ /* do_exists has already called reply_with_error */
+ goto done;
+
+ struct guestfs_exists_ret ret;
+ ret.existsflag = r;
+ reply ((xdrproc_t) &xdr_guestfs_exists_ret, (char *) &ret);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_exists_args, (char *) &args);
+}
+
+static void is_file_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_is_file_args args;
+ const char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_is_file_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "is_file");
+ return;
+ }
+ path = args.path;
+
+ r = do_is_file (path);
+ if (r == -1)
+ /* do_is_file has already called reply_with_error */
+ goto done;
+
+ struct guestfs_is_file_ret ret;
+ ret.fileflag = r;
+ reply ((xdrproc_t) &xdr_guestfs_is_file_ret, (char *) &ret);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_is_file_args, (char *) &args);
+}
+
+static void is_dir_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_is_dir_args args;
+ const char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_is_dir_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "is_dir");
+ return;
+ }
+ path = args.path;
+
+ r = do_is_dir (path);
+ if (r == -1)
+ /* do_is_dir has already called reply_with_error */
+ goto done;
+
+ struct guestfs_is_dir_ret ret;
+ ret.dirflag = r;
+ reply ((xdrproc_t) &xdr_guestfs_is_dir_ret, (char *) &ret);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args);
+}
+
+static void pvcreate_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_pvcreate_args args;
+ const char *device;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_pvcreate_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "pvcreate");
+ return;
+ }
+ device = args.device;
+
+ r = do_pvcreate (device);
+ if (r == -1)
+ /* do_pvcreate has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args);
+}
+
+static void vgcreate_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_vgcreate_args args;
+ const char *volgroup;
+ char **physvols;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_vgcreate_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "vgcreate");
+ return;
+ }
+ volgroup = args.volgroup;
+ args.physvols.physvols_val = realloc (args.physvols.physvols_val, sizeof (char *) * (args.physvols.physvols_len+1));
+ args.physvols.physvols_val[args.physvols.physvols_len] = NULL;
+ physvols = args.physvols.physvols_val;
+
+ r = do_vgcreate (volgroup, physvols);
+ if (r == -1)
+ /* do_vgcreate has already called reply_with_error */
+ goto done;
reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_vgcreate_args, (char *) &args);
+}
+
+static void lvcreate_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_lvcreate_args args;
+ const char *logvol;
+ const char *volgroup;
+ int mbytes;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_lvcreate_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "lvcreate");
+ return;
+ }
+ logvol = args.logvol;
+ volgroup = args.volgroup;
+ mbytes = args.mbytes;
+
+ r = do_lvcreate (logvol, volgroup, mbytes);
+ if (r == -1)
+ /* do_lvcreate has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_lvcreate_args, (char *) &args);
+}
+
+static void mkfs_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_mkfs_args args;
+ const char *fstype;
+ const char *device;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_mkfs_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "mkfs");
+ return;
+ }
+ fstype = args.fstype;
+ device = args.device;
+
+ r = do_mkfs (fstype, device);
+ if (r == -1)
+ /* do_mkfs has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_mkfs_args, (char *) &args);
+}
+
+static void sfdisk_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_sfdisk_args args;
+ const char *device;
+ int cyls;
+ int heads;
+ int sectors;
+ char **lines;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_sfdisk_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "sfdisk");
+ return;
+ }
+ device = args.device;
+ cyls = args.cyls;
+ heads = args.heads;
+ sectors = args.sectors;
+ args.lines.lines_val = realloc (args.lines.lines_val, sizeof (char *) * (args.lines.lines_len+1));
+ args.lines.lines_val[args.lines.lines_len] = NULL;
+ lines = args.lines.lines_val;
+
+ r = do_sfdisk (device, cyls, heads, sectors, lines);
+ if (r == -1)
+ /* do_sfdisk has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_sfdisk_args, (char *) &args);
+}
+
+static void write_file_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_write_file_args args;
+ const char *path;
+ const char *content;
+ int size;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_write_file_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "write_file");
+ return;
+ }
+ path = args.path;
+ content = args.content;
+ size = args.size;
+
+ r = do_write_file (path, content, size);
+ if (r == -1)
+ /* do_write_file has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_write_file_args, (char *) &args);
+}
+
+static void umount_stub (XDR *xdr_in)
+{
+ int r;
+ struct guestfs_umount_args args;
+ const char *pathordevice;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_umount_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "umount");
+ return;
+ }
+ pathordevice = args.pathordevice;
+
+ r = do_umount (pathordevice);
+ if (r == -1)
+ /* do_umount has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_umount_args, (char *) &args);
+}
+
+static void mounts_stub (XDR *xdr_in)
+{
+ char **r;
+
+ r = do_mounts ();
+ if (r == NULL)
+ /* do_mounts has already called reply_with_error */
+ goto done;
+
+ struct guestfs_mounts_ret ret;
+ ret.devices.devices_len = count_strings (r);
+ ret.devices.devices_val = r;
+ reply ((xdrproc_t) &xdr_guestfs_mounts_ret, (char *) &ret);
+ free_strings (r);
+done: ;
+}
+
+static void umount_all_stub (XDR *xdr_in)
+{
+ int r;
+
+ r = do_umount_all ();
+ if (r == -1)
+ /* do_umount_all has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done: ;
+}
+
+static void lvm_remove_all_stub (XDR *xdr_in)
+{
+ int r;
+
+ r = do_lvm_remove_all ();
+ if (r == -1)
+ /* do_lvm_remove_all has already called reply_with_error */
+ goto done;
+
+ reply (NULL, NULL);
+done: ;
}
void dispatch_incoming_message (XDR *xdr_in)
@@ -874,6 +1245,45 @@ void dispatch_incoming_message (XDR *xdr_in)
case GUESTFS_PROC_CHOWN:
chown_stub (xdr_in);
break;
+ case GUESTFS_PROC_EXISTS:
+ exists_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_IS_FILE:
+ is_file_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_IS_DIR:
+ is_dir_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_PVCREATE:
+ pvcreate_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_VGCREATE:
+ vgcreate_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_LVCREATE:
+ lvcreate_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_MKFS:
+ mkfs_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_SFDISK:
+ sfdisk_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_WRITE_FILE:
+ write_file_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_UMOUNT:
+ umount_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_MOUNTS:
+ mounts_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_UMOUNT_ALL:
+ umount_all_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_LVM_REMOVE_ALL:
+ lvm_remove_all_stub (xdr_in);
+ break;
default:
reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr);
}
diff --git a/daemon/sync.c b/daemon/sync.c
index 9ade8403..70962dff 100644
--- a/daemon/sync.c
+++ b/daemon/sync.c
@@ -27,6 +27,5 @@ int
do_sync ()
{
sync ();
- fprintf (stderr, "guestfsd: disk synched\n");
return 0;
}
diff --git a/fish/cmds.c b/fish/cmds.c
index cef38ccc..1ab9ea0b 100644
--- a/fish/cmds.c
+++ b/fish/cmds.c
@@ -50,20 +50,28 @@ void list_commands (void)
printf ("%-20s %s\n", "chmod", "change file mode");
printf ("%-20s %s\n", "chown", "change file owner and group");
printf ("%-20s %s\n", "config", "add qemu parameters");
+ printf ("%-20s %s\n", "exists", "test if file or directory exists");
printf ("%-20s %s\n", "get-autosync", "get autosync mode");
printf ("%-20s %s\n", "get-path", "get the search path");
printf ("%-20s %s\n", "get-verbose", "get verbose mode");
+ printf ("%-20s %s\n", "is-dir", "test if file exists");
+ printf ("%-20s %s\n", "is-file", "test if file exists");
printf ("%-20s %s\n", "kill-subprocess", "kill the qemu subprocess");
printf ("%-20s %s\n", "launch", "launch the qemu subprocess");
printf ("%-20s %s\n", "list-devices", "list the block devices");
printf ("%-20s %s\n", "list-partitions", "list the partitions");
printf ("%-20s %s\n", "ll", "list the files in a directory (long format)");
printf ("%-20s %s\n", "ls", "list the files in a directory");
+ printf ("%-20s %s\n", "lvcreate", "create an LVM volume group");
+ printf ("%-20s %s\n", "lvm-remove-all", "remove all LVM LVs, VGs and PVs");
printf ("%-20s %s\n", "lvs", "list the LVM logical volumes (LVs)");
printf ("%-20s %s\n", "lvs-full", "list the LVM logical volumes (LVs)");
printf ("%-20s %s\n", "mkdir", "create a directory");
printf ("%-20s %s\n", "mkdir-p", "create a directory and parents");
+ printf ("%-20s %s\n", "mkfs", "make a filesystem");
printf ("%-20s %s\n", "mount", "mount a guest disk at a position in the filesystem");
+ printf ("%-20s %s\n", "mounts", "show mounted filesystems");
+ printf ("%-20s %s\n", "pvcreate", "create an LVM physical volume");
printf ("%-20s %s\n", "pvs", "list the LVM physical volumes (PVs)");
printf ("%-20s %s\n", "pvs-full", "list the LVM physical volumes (PVs)");
printf ("%-20s %s\n", "read-lines", "read file as lines");
@@ -73,10 +81,15 @@ void list_commands (void)
printf ("%-20s %s\n", "set-autosync", "set autosync mode");
printf ("%-20s %s\n", "set-path", "set the search path");
printf ("%-20s %s\n", "set-verbose", "set verbose mode");
+ printf ("%-20s %s\n", "sfdisk", "create partitions on a block device");
printf ("%-20s %s\n", "sync", "sync disks, writes are flushed through to the disk image");
printf ("%-20s %s\n", "touch", "update file timestamps or create a new file");
+ printf ("%-20s %s\n", "umount", "unmount a filesystem");
+ printf ("%-20s %s\n", "umount-all", "unmount all filesystems");
+ printf ("%-20s %s\n", "vgcreate", "create an LVM volume group");
printf ("%-20s %s\n", "vgs", "list the LVM volume groups (VGs)");
printf ("%-20s %s\n", "vgs-full", "list the LVM volume groups (VGs)");
+ printf ("%-20s %s\n", "write-file", "Create a file");
printf (" Use -h <cmd> / help <cmd> to show detailed help for a command.\n");
}
@@ -220,6 +233,45 @@ void display_command (const char *cmd)
if (strcasecmp (cmd, "chown") == 0)
pod2text ("chown - change file owner and group", " chown <owner> <group> <path>\n\nChange the file owner to C<owner> and group to C<group>.\n\nOnly numeric uid and gid are supported. If you want to use\nnames, you will need to locate and parse the password file\nyourself (Augeas support makes this relatively easy).");
else
+ if (strcasecmp (cmd, "exists") == 0)
+ pod2text ("exists - test if file or directory exists", " exists <path>\n\nThis returns C<true> if and only if there is a file, directory\n(or anything) with the given C<path> name.\n\nSee also C<is_file>, C<is_dir>, C<stat>.");
+ else
+ if (strcasecmp (cmd, "is_file") == 0 || strcasecmp (cmd, "is-file") == 0)
+ pod2text ("is-file - test if file exists", " is-file <path>\n\nThis returns C<true> if and only if there is a file\nwith the given C<path> name. Note that it returns false for\nother objects like directories.\n\nSee also C<stat>.");
+ else
+ if (strcasecmp (cmd, "is_dir") == 0 || strcasecmp (cmd, "is-dir") == 0)
+ pod2text ("is-dir - test if file exists", " is-dir <path>\n\nThis returns C<true> if and only if there is a directory\nwith the given C<path> name. Note that it returns false for\nother objects like files.\n\nSee also C<stat>.");
+ else
+ if (strcasecmp (cmd, "pvcreate") == 0)
+ pod2text ("pvcreate - create an LVM physical volume", " pvcreate <device>\n\nThis creates an LVM physical volume on the named C<device>,\nwhere C<device> should usually be a partition name such\nas C</dev/sda1>.");
+ else
+ if (strcasecmp (cmd, "vgcreate") == 0)
+ pod2text ("vgcreate - create an LVM volume group", " vgcreate <volgroup> <physvols>\n\nThis creates an LVM volume group called C<volgroup>\nfrom the non-empty list of physical volumes C<physvols>.");
+ else
+ if (strcasecmp (cmd, "lvcreate") == 0)
+ pod2text ("lvcreate - create an LVM volume group", " lvcreate <logvol> <volgroup> <mbytes>\n\nThis creates an LVM volume group called C<logvol>\non the volume group C<volgroup>, with C<size> megabytes.");
+ else
+ if (strcasecmp (cmd, "mkfs") == 0)
+ pod2text ("mkfs - make a filesystem", " mkfs <fstype> <device>\n\nThis creates a filesystem on C<device> (usually a partition\nof LVM logical volume). The filesystem type is C<fstype>, for\nexample C<ext3>.");
+ else
+ if (strcasecmp (cmd, "sfdisk") == 0)
+ pod2text ("sfdisk - create partitions on a block device", " sfdisk <device> <cyls> <heads> <sectors> <lines>\n\nThis is a direct interface to the L<sfdisk(8)> program for creating\npartitions on block devices.\n\nC<device> should be a block device, for example C</dev/sda>.\n\nC<cyls>, C<heads> and C<sectors> are the number of cylinders, heads\nand sectors on the device, which are passed directly to sfdisk as\nthe I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any\nof these, then the corresponding parameter is omitted. Usually for\n'large' disks, you can just pass C<0> for these, but for small\n(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work\nout the right geometry and you will need to tell it.\n\nC<lines> is a list of lines that we feed to C<sfdisk>. For more\ninformation refer to the L<sfdisk(8)> manpage.\n\nTo create a single partition occupying the whole disk, you would\npass C<lines> as a single element list, when the single element being\nthe string C<,> (comma).\n\nB<This command is dangerous. Without careful use you\ncan easily destroy all your data>.");
+ else
+ if (strcasecmp (cmd, "write_file") == 0 || strcasecmp (cmd, "write-file") == 0)
+ pod2text ("write-file - Create a file", " write-file <path> <content> <size>\n\nThis call creates a file called C<path>. The contents of the\nfile is the string C<content> (which can contain any 8 bit data),\nwith length C<size>.\n\nAs a special case, if C<size> is C<0>\nthen the length is calculated using C<strlen> (so in this case\nthe content cannot contain embedded ASCII NULs).\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
+ else
+ if (strcasecmp (cmd, "umount") == 0 || strcasecmp (cmd, "unmount") == 0)
+ pod2text ("umount - unmount a filesystem", " umount <pathordevice>\n\nThis unmounts the given filesystem. The filesystem may be\nspecified either by its mountpoint (path) or the device which\ncontains the filesystem.\n\nYou can use 'unmount' as an alias for this command.");
+ else
+ if (strcasecmp (cmd, "mounts") == 0)
+ pod2text ("mounts - show mounted filesystems", " mounts\n\nThis returns the list of currently mounted filesystems. It returns\nthe list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).\n\nSome internal mounts are not shown.");
+ else
+ if (strcasecmp (cmd, "umount_all") == 0 || strcasecmp (cmd, "umount-all") == 0 || strcasecmp (cmd, "unmount-all") == 0)
+ pod2text ("umount-all - unmount all filesystems", " umount-all\n\nThis unmounts all mounted filesystems.\n\nSome internal mounts are not unmounted by this call.\n\nYou can use 'unmount-all' as an alias for this command.");
+ else
+ if (strcasecmp (cmd, "lvm_remove_all") == 0 || strcasecmp (cmd, "lvm-remove-all") == 0)
+ pod2text ("lvm-remove-all - remove all LVM LVs, VGs and PVs", " lvm-remove-all\n\nThis command removes all LVM logical volumes, volume groups\nand physical volumes.\n\nB<This command is dangerous. Without careful use you\ncan easily destroy all your data>.");
+ else
display_builtin_command (cmd);
}
@@ -1020,6 +1072,211 @@ static int run_chown (const char *cmd, int argc, char *argv[])
return r;
}
+static int run_exists (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *path;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ r = guestfs_exists (g, path);
+ if (r == -1) return -1;
+ if (r) printf ("true\n"); else printf ("false\n");
+ return 0;
+}
+
+static int run_is_file (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *path;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ r = guestfs_is_file (g, path);
+ if (r == -1) return -1;
+ if (r) printf ("true\n"); else printf ("false\n");
+ return 0;
+}
+
+static int run_is_dir (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *path;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ r = guestfs_is_dir (g, path);
+ if (r == -1) return -1;
+ if (r) printf ("true\n"); else printf ("false\n");
+ return 0;
+}
+
+static int run_pvcreate (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *device;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ device = argv[0];
+ r = guestfs_pvcreate (g, device);
+ return r;
+}
+
+static int run_vgcreate (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *volgroup;
+ char **physvols;
+ if (argc != 2) {
+ fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ volgroup = argv[0];
+ physvols = parse_string_list (argv[1]);
+ r = guestfs_vgcreate (g, volgroup, physvols);
+ return r;
+}
+
+static int run_lvcreate (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *logvol;
+ const char *volgroup;
+ int mbytes;
+ if (argc != 3) {
+ fprintf (stderr, "%s should have 3 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ logvol = argv[0];
+ volgroup = argv[1];
+ mbytes = atoi (argv[2]);
+ r = guestfs_lvcreate (g, logvol, volgroup, mbytes);
+ return r;
+}
+
+static int run_mkfs (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *fstype;
+ const char *device;
+ if (argc != 2) {
+ fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ fstype = argv[0];
+ device = argv[1];
+ r = guestfs_mkfs (g, fstype, device);
+ return r;
+}
+
+static int run_sfdisk (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *device;
+ int cyls;
+ int heads;
+ int sectors;
+ char **lines;
+ if (argc != 5) {
+ fprintf (stderr, "%s should have 5 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ device = argv[0];
+ cyls = atoi (argv[1]);
+ heads = atoi (argv[2]);
+ sectors = atoi (argv[3]);
+ lines = parse_string_list (argv[4]);
+ r = guestfs_sfdisk (g, device, cyls, heads, sectors, lines);
+ return r;
+}
+
+static int run_write_file (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *path;
+ const char *content;
+ int size;
+ if (argc != 3) {
+ fprintf (stderr, "%s should have 3 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ content = argv[1];
+ size = atoi (argv[2]);
+ r = guestfs_write_file (g, path, content, size);
+ return r;
+}
+
+static int run_umount (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ const char *pathordevice;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ pathordevice = argv[0];
+ r = guestfs_umount (g, pathordevice);
+ return r;
+}
+
+static int run_mounts (const char *cmd, int argc, char *argv[])
+{
+ char **r;
+ if (argc != 0) {
+ fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ r = guestfs_mounts (g);
+ if (r == NULL) return -1;
+ print_strings (r);
+ free_strings (r);
+ return 0;
+}
+
+static int run_umount_all (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ if (argc != 0) {
+ fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ r = guestfs_umount_all (g);
+ return r;
+}
+
+static int run_lvm_remove_all (const char *cmd, int argc, char *argv[])
+{
+ int r;
+ if (argc != 0) {
+ fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ r = guestfs_lvm_remove_all (g);
+ return r;
+}
+
int run_action (const char *cmd, int argc, char *argv[])
{
if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
@@ -1160,6 +1417,45 @@ int run_action (const char *cmd, int argc, char *argv[])
if (strcasecmp (cmd, "chown") == 0)
return run_chown (cmd, argc, argv);
else
+ if (strcasecmp (cmd, "exists") == 0)
+ return run_exists (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "is_file") == 0 || strcasecmp (cmd, "is-file") == 0)
+ return run_is_file (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "is_dir") == 0 || strcasecmp (cmd, "is-dir") == 0)
+ return run_is_dir (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "pvcreate") == 0)
+ return run_pvcreate (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "vgcreate") == 0)
+ return run_vgcreate (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "lvcreate") == 0)
+ return run_lvcreate (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "mkfs") == 0)
+ return run_mkfs (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "sfdisk") == 0)
+ return run_sfdisk (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "write_file") == 0 || strcasecmp (cmd, "write-file") == 0)
+ return run_write_file (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "umount") == 0 || strcasecmp (cmd, "unmount") == 0)
+ return run_umount (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "mounts") == 0)
+ return run_mounts (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "umount_all") == 0 || strcasecmp (cmd, "umount-all") == 0 || strcasecmp (cmd, "unmount-all") == 0)
+ return run_umount_all (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "lvm_remove_all") == 0 || strcasecmp (cmd, "lvm-remove-all") == 0)
+ return run_lvm_remove_all (cmd, argc, argv);
+ else
{
fprintf (stderr, "%s: unknown command\n", cmd);
return -1;
diff --git a/fish/fish.c b/fish/fish.c
index e845e4de..18b8d451 100644
--- a/fish/fish.c
+++ b/fish/fish.c
@@ -18,6 +18,8 @@
#include <config.h>
+#define _GNU_SOURCE // for strchrnul
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -495,7 +497,7 @@ free_strings (char **argv)
}
void
-print_strings (char **argv)
+print_strings (char * const * const argv)
{
int argc;
@@ -513,3 +515,34 @@ is_true (const char *str)
strcasecmp (str, "n") != 0 &&
strcasecmp (str, "no") != 0;
}
+
+/* This is quite inadequate for real use. For example, there is no way
+ * to specify an empty list. We need to use a real parser to allow
+ * quoting, empty lists, etc.
+ */
+char **
+parse_string_list (const char *str)
+{
+ char **argv;
+ const char *p, *pend;
+ int argc, i;
+
+ argc = 1;
+ for (i = 0; str[i]; ++i)
+ if (str[i] == ':') argc++;
+
+ argv = malloc (sizeof (char *) * (argc+1));
+ if (argv == NULL) { perror ("malloc"); exit (1); }
+
+ p = str;
+ i = 0;
+ while (*p) {
+ pend = strchrnul (p, ':');
+ argv[i] = strndup (p, pend-p);
+ i++;
+ p = *pend == ':' ? pend+1 : p;
+ }
+ argv[i] = NULL;
+
+ return argv;
+}
diff --git a/fish/fish.h b/fish/fish.h
index 6d0892fa..3997d6d4 100644
--- a/fish/fish.h
+++ b/fish/fish.h
@@ -30,9 +30,10 @@ extern void pod2text (const char *heading, const char *body);
extern void list_builtin_commands (void);
extern void display_builtin_command (const char *cmd);
extern void free_strings (char **argv);
-extern void print_strings (char **argv);
+extern void print_strings (char * const * const argv);
extern int launch (guestfs_h *);
extern int is_true (const char *str);
+extern char **parse_string_list (const char *str);
/* in cmds.c (auto-generated) */
extern void list_commands (void);
diff --git a/guestfish-actions.pod b/guestfish-actions.pod
index d47e9bf9..50ecfec6 100644
--- a/guestfish-actions.pod
+++ b/guestfish-actions.pod
@@ -193,6 +193,10 @@ Note that this function cannot correctly handle binary files
as end of string). For those you need to use the C<read_file>
function which has a more complex interface.
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=head2 chmod
chmod mode path
@@ -223,6 +227,15 @@ The first character of C<param> string must be a C<-> (dash).
C<value> can be NULL.
+=head2 exists
+
+ exists path
+
+This returns C<true> if and only if there is a file, directory
+(or anything) with the given C<path> name.
+
+See also C<is_file>, C<is_dir>, C<stat>.
+
=head2 get-autosync
get-autosync
@@ -244,6 +257,26 @@ return the default path.
This returns the verbose messages flag.
+=head2 is-dir
+
+ is-dir path
+
+This returns C<true> if and only if there is a directory
+with the given C<path> name. Note that it returns false for
+other objects like files.
+
+See also C<stat>.
+
+=head2 is-file
+
+ is-file path
+
+This returns C<true> if and only if there is a file
+with the given C<path> name. Note that it returns false for
+other objects like directories.
+
+See also C<stat>.
+
=head2 kill-subprocess
kill-subprocess
@@ -300,6 +333,23 @@ hidden files are shown.
This command is mostly useful for interactive sessions. Programs
should probably use C<readdir> instead.
+=head2 lvcreate
+
+ lvcreate logvol volgroup mbytes
+
+This creates an LVM volume group called C<logvol>
+on the volume group C<volgroup>, with C<size> megabytes.
+
+=head2 lvm-remove-all
+
+ lvm-remove-all
+
+This command removes all LVM logical volumes, volume groups
+and physical volumes.
+
+B<This command is dangerous. Without careful use you
+can easily destroy all your data>.
+
=head2 lvs
lvs
@@ -332,6 +382,14 @@ Create a directory named C<path>.
Create a directory named C<path>, creating any parent directories
as necessary. This is like the C<mkdir -p> shell command.
+=head2 mkfs
+
+ mkfs fstype device
+
+This creates a filesystem on C<device> (usually a partition
+of LVM logical volume). The filesystem type is C<fstype>, for
+example C<ext3>.
+
=head2 mount
mount device mountpoint
@@ -353,6 +411,23 @@ on the underlying device.
The filesystem options C<sync> and C<noatime> are set with this
call, in order to improve reliability.
+=head2 mounts
+
+ mounts
+
+This returns the list of currently mounted filesystems. It returns
+the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
+
+Some internal mounts are not shown.
+
+=head2 pvcreate
+
+ pvcreate device
+
+This creates an LVM physical volume on the named C<device>,
+where C<device> should usually be a partition name such
+as C</dev/sda1>.
+
=head2 pvs
pvs
@@ -437,6 +512,33 @@ If C<verbose> is true, this turns on verbose messages (to C<stderr>).
Verbose messages are disabled unless the environment variable
C<LIBGUESTFS_DEBUG> is defined and set to C<1>.
+=head2 sfdisk
+
+ sfdisk device cyls heads sectors lines,...
+
+This is a direct interface to the L<sfdisk(8)> program for creating
+partitions on block devices.
+
+C<device> should be a block device, for example C</dev/sda>.
+
+C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
+and sectors on the device, which are passed directly to sfdisk as
+the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
+of these, then the corresponding parameter is omitted. Usually for
+'large' disks, you can just pass C<0> for these, but for small
+(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
+out the right geometry and you will need to tell it.
+
+C<lines> is a list of lines that we feed to C<sfdisk>. For more
+information refer to the L<sfdisk(8)> manpage.
+
+To create a single partition occupying the whole disk, you would
+pass C<lines> as a single element list, when the single element being
+the string C<,> (comma).
+
+B<This command is dangerous. Without careful use you
+can easily destroy all your data>.
+
=head2 sync
sync
@@ -455,6 +557,29 @@ Touch acts like the L<touch(1)> command. It can be used to
update the timestamps on a file, or, if the file does not exist,
to create a new zero-length file.
+=head2 umount | unmount
+
+ umount pathordevice
+
+This unmounts the given filesystem. The filesystem may be
+specified either by its mountpoint (path) or the device which
+contains the filesystem.
+
+=head2 umount-all | unmount-all
+
+ umount-all
+
+This unmounts all mounted filesystems.
+
+Some internal mounts are not unmounted by this call.
+
+=head2 vgcreate
+
+ vgcreate volgroup physvols,...
+
+This creates an LVM volume group called C<volgroup>
+from the non-empty list of physical volumes C<physvols>.
+
=head2 vgs
vgs
@@ -474,3 +599,19 @@ See also C<vgs_full>.
List all the volumes groups detected. This is the equivalent
of the L<vgs(8)> command. The "full" version includes all fields.
+=head2 write-file
+
+ write-file path content size
+
+This call creates a file called C<path>. The contents of the
+file is the string C<content> (which can contain any 8 bit data),
+with length C<size>.
+
+As a special case, if C<size> is C<0>
+then the length is calculated using C<strlen> (so in this case
+the content cannot contain embedded ASCII NULs).
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
diff --git a/guestfs-actions.pod b/guestfs-actions.pod
index 069ea8f7..310db2e4 100644
--- a/guestfs-actions.pod
+++ b/guestfs-actions.pod
@@ -300,6 +300,18 @@ C<value> can be NULL.
This function returns 0 on success or -1 on error.
+=head2 guestfs_exists
+
+ int guestfs_exists (guestfs_h *handle,
+ const char *path);
+
+This returns C<true> if and only if there is a file, directory
+(or anything) with the given C<path> name.
+
+See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.
+
+This function returns a C truth value on success or -1 on error.
+
=head2 guestfs_get_autosync
int guestfs_get_autosync (guestfs_h *handle);
@@ -328,6 +340,32 @@ This returns the verbose messages flag.
This function returns a C truth value on success or -1 on error.
+=head2 guestfs_is_dir
+
+ int guestfs_is_dir (guestfs_h *handle,
+ const char *path);
+
+This returns C<true> if and only if there is a directory
+with the given C<path> name. Note that it returns false for
+other objects like files.
+
+See also C<guestfs_stat>.
+
+This function returns a C truth value on success or -1 on error.
+
+=head2 guestfs_is_file
+
+ int guestfs_is_file (guestfs_h *handle,
+ const char *path);
+
+This returns C<true> if and only if there is a file
+with the given C<path> name. Note that it returns false for
+other objects like directories.
+
+See also C<guestfs_stat>.
+
+This function returns a C truth value on success or -1 on error.
+
=head2 guestfs_kill_subprocess
int guestfs_kill_subprocess (guestfs_h *handle);
@@ -405,6 +443,30 @@ This function returns a NULL-terminated array of strings
(like L<environ(3)>), or NULL if there was an error.
I<The caller must free the strings and the array after use>.
+=head2 guestfs_lvcreate
+
+ int guestfs_lvcreate (guestfs_h *handle,
+ const char *logvol,
+ const char *volgroup,
+ int mbytes);
+
+This creates an LVM volume group called C<logvol>
+on the volume group C<volgroup>, with C<size> megabytes.
+
+This function returns 0 on success or -1 on error.
+
+=head2 guestfs_lvm_remove_all
+
+ int guestfs_lvm_remove_all (guestfs_h *handle);
+
+This command removes all LVM logical volumes, volume groups
+and physical volumes.
+
+This function returns 0 on success or -1 on error.
+
+B<This command is dangerous. Without careful use you
+can easily destroy all your data>.
+
=head2 guestfs_lvs
char **guestfs_lvs (guestfs_h *handle);
@@ -450,6 +512,18 @@ as necessary. This is like the C<mkdir -p> shell command.
This function returns 0 on success or -1 on error.
+=head2 guestfs_mkfs
+
+ int guestfs_mkfs (guestfs_h *handle,
+ const char *fstype,
+ const char *device);
+
+This creates a filesystem on C<device> (usually a partition
+of LVM logical volume). The filesystem type is C<fstype>, for
+example C<ext3>.
+
+This function returns 0 on success or -1 on error.
+
=head2 guestfs_mount
int guestfs_mount (guestfs_h *handle,
@@ -475,6 +549,30 @@ call, in order to improve reliability.
This function returns 0 on success or -1 on error.
+=head2 guestfs_mounts
+
+ char **guestfs_mounts (guestfs_h *handle);
+
+This returns the list of currently mounted filesystems. It returns
+the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
+
+Some internal mounts are not shown.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
+=head2 guestfs_pvcreate
+
+ int guestfs_pvcreate (guestfs_h *handle,
+ const char *device);
+
+This creates an LVM physical volume on the named C<device>,
+where C<device> should usually be a partition name such
+as C</dev/sda1>.
+
+This function returns 0 on success or -1 on error.
+
=head2 guestfs_pvs
char **guestfs_pvs (guestfs_h *handle);
@@ -589,6 +687,40 @@ C<LIBGUESTFS_DEBUG> is defined and set to C<1>.
This function returns 0 on success or -1 on error.
+=head2 guestfs_sfdisk
+
+ int guestfs_sfdisk (guestfs_h *handle,
+ const char *device,
+ int cyls,
+ int heads,
+ int sectors,
+ char * const* const lines);
+
+This is a direct interface to the L<sfdisk(8)> program for creating
+partitions on block devices.
+
+C<device> should be a block device, for example C</dev/sda>.
+
+C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
+and sectors on the device, which are passed directly to sfdisk as
+the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
+of these, then the corresponding parameter is omitted. Usually for
+'large' disks, you can just pass C<0> for these, but for small
+(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
+out the right geometry and you will need to tell it.
+
+C<lines> is a list of lines that we feed to C<sfdisk>. For more
+information refer to the L<sfdisk(8)> manpage.
+
+To create a single partition occupying the whole disk, you would
+pass C<lines> as a single element list, when the single element being
+the string C<,> (comma).
+
+This function returns 0 on success or -1 on error.
+
+B<This command is dangerous. Without careful use you
+can easily destroy all your data>.
+
=head2 guestfs_sync
int guestfs_sync (guestfs_h *handle);
@@ -612,6 +744,38 @@ to create a new zero-length file.
This function returns 0 on success or -1 on error.
+=head2 guestfs_umount
+
+ int guestfs_umount (guestfs_h *handle,
+ const char *pathordevice);
+
+This unmounts the given filesystem. The filesystem may be
+specified either by its mountpoint (path) or the device which
+contains the filesystem.
+
+This function returns 0 on success or -1 on error.
+
+=head2 guestfs_umount_all
+
+ int guestfs_umount_all (guestfs_h *handle);
+
+This unmounts all mounted filesystems.
+
+Some internal mounts are not unmounted by this call.
+
+This function returns 0 on success or -1 on error.
+
+=head2 guestfs_vgcreate
+
+ int guestfs_vgcreate (guestfs_h *handle,
+ const char *volgroup,
+ char * const* const physvols);
+
+This creates an LVM volume group called C<volgroup>
+from the non-empty list of physical volumes C<physvols>.
+
+This function returns 0 on success or -1 on error.
+
=head2 guestfs_vgs
char **guestfs_vgs (guestfs_h *handle);
@@ -650,3 +814,24 @@ to complete.
This function returns 0 on success or -1 on error.
+=head2 guestfs_write_file
+
+ int guestfs_write_file (guestfs_h *handle,
+ const char *path,
+ const char *content,
+ int size);
+
+This call creates a file called C<path>. The contents of the
+file is the string C<content> (which can contain any 8 bit data),
+with length C<size>.
+
+As a special case, if C<size> is C<0>
+then the length is calculated using C<strlen> (so in this case
+the content cannot contain embedded ASCII NULs).
+
+This function returns 0 on success or -1 on error.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
diff --git a/libguestfs.spec.in b/libguestfs.spec.in
index 29c95ffa..e4dcaef1 100644
--- a/libguestfs.spec.in
+++ b/libguestfs.spec.in
@@ -138,6 +138,10 @@ Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)
make INSTALLDIRS=vendor
+%check
+make check
+
+
%install
rm -rf $RPM_BUILD_ROOT
diff --git a/make-initramfs.sh.in b/make-initramfs.sh.in
index 4579e901..3dbac635 100755
--- a/make-initramfs.sh.in
+++ b/make-initramfs.sh.in
@@ -65,11 +65,13 @@ find initramfs -name '*plymouth*' -print0 | xargs -0 rm -rf
find initramfs -name '*python*' -print0 | xargs -0 rm -rf
# Modules take up nearly half of the image. It's a rough guess that
-# we don't need any drivers (which take up most of the space).
+# we don't need many drivers (which take up most of the space).
find initramfs/lib/modules/*/kernel \
-name '*.ko' \
-a ! -name 'mii.ko' \
-a ! -name '8139cp.ko' \
+ -a ! -name 'ext2.ko' \
+ -a ! -name 'ext4.ko' \
-a -delete
# Pull the kernel out into the current directory. We don't want it in
diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml
index 32a6b82a..58f99dc2 100644
--- a/ocaml/guestfs.ml
+++ b/ocaml/guestfs.ml
@@ -132,3 +132,16 @@ external mkdir : t -> string -> unit = "ocaml_guestfs_mkdir"
external mkdir_p : t -> string -> unit = "ocaml_guestfs_mkdir_p"
external chmod : t -> int -> string -> unit = "ocaml_guestfs_chmod"
external chown : t -> int -> int -> string -> unit = "ocaml_guestfs_chown"
+external exists : t -> string -> bool = "ocaml_guestfs_exists"
+external is_file : t -> string -> bool = "ocaml_guestfs_is_file"
+external is_dir : t -> string -> bool = "ocaml_guestfs_is_dir"
+external pvcreate : t -> string -> unit = "ocaml_guestfs_pvcreate"
+external vgcreate : t -> string -> string array -> unit = "ocaml_guestfs_vgcreate"
+external lvcreate : t -> string -> string -> int -> unit = "ocaml_guestfs_lvcreate"
+external mkfs : t -> string -> string -> unit = "ocaml_guestfs_mkfs"
+external sfdisk : t -> string -> int -> int -> int -> string array -> unit = "ocaml_guestfs_sfdisk_byte" "ocaml_guestfs_sfdisk"
+external write_file : t -> string -> string -> int -> unit = "ocaml_guestfs_write_file"
+external umount : t -> string -> unit = "ocaml_guestfs_umount"
+external mounts : t -> string array = "ocaml_guestfs_mounts"
+external umount_all : t -> unit = "ocaml_guestfs_umount_all"
+external lvm_remove_all : t -> unit = "ocaml_guestfs_lvm_remove_all"
diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli
index ecf86f11..1ce1cab2 100644
--- a/ocaml/guestfs.mli
+++ b/ocaml/guestfs.mli
@@ -235,3 +235,42 @@ val chmod : t -> int -> string -> unit
val chown : t -> int -> int -> string -> unit
(** change file owner and group *)
+val exists : t -> string -> bool
+(** test if file or directory exists *)
+
+val is_file : t -> string -> bool
+(** test if file exists *)
+
+val is_dir : t -> string -> bool
+(** test if file exists *)
+
+val pvcreate : t -> string -> unit
+(** create an LVM physical volume *)
+
+val vgcreate : t -> string -> string array -> unit
+(** create an LVM volume group *)
+
+val lvcreate : t -> string -> string -> int -> unit
+(** create an LVM volume group *)
+
+val mkfs : t -> string -> string -> unit
+(** make a filesystem *)
+
+val sfdisk : t -> string -> int -> int -> int -> string array -> unit
+(** create partitions on a block device *)
+
+val write_file : t -> string -> string -> int -> unit
+(** Create a file *)
+
+val umount : t -> string -> unit
+(** unmount a filesystem *)
+
+val mounts : t -> string array
+(** show mounted filesystems *)
+
+val umount_all : t -> unit
+(** unmount all filesystems *)
+
+val lvm_remove_all : t -> unit
+(** remove all LVM LVs, VGs and PVs *)
+
diff --git a/ocaml/guestfs_c.c b/ocaml/guestfs_c.c
index 600440c9..291c4308 100644
--- a/ocaml/guestfs_c.c
+++ b/ocaml/guestfs_c.c
@@ -119,3 +119,29 @@ ocaml_guestfs_close (value gv)
CAMLreturn (Val_unit);
}
+
+/* Copy string array value. */
+char **
+ocaml_guestfs_strings_val (value sv)
+{
+ CAMLparam1 (sv);
+ char **r;
+ int i;
+
+ r = malloc (sizeof (char *) * (Wosize_val (sv) + 1));
+ for (i = 0; i < Wosize_val (sv); ++i)
+ r[i] = String_val (Field (sv, i));
+ r[i] = NULL;
+
+ CAMLreturnT (char **, r);
+}
+
+/* Free array of strings. */
+void
+ocaml_guestfs_free_strings (char **argv)
+{
+ /* Don't free the actual strings - they are String_vals on
+ * the OCaml heap.
+ */
+ free (argv);
+}
diff --git a/ocaml/guestfs_c.h b/ocaml/guestfs_c.h
index 3da41d05..4fb81881 100644
--- a/ocaml/guestfs_c.h
+++ b/ocaml/guestfs_c.h
@@ -22,5 +22,7 @@
#define Guestfs_val(v) (*((guestfs_h **)Data_custom_val(v)))
extern void ocaml_guestfs_raise_error (guestfs_h *g, const char *func)
Noreturn;
+extern char **ocaml_guestfs_strings_val (value sv);
+extern void ocaml_guestfs_free_strings (char **r);
#endif /* GUESTFS_OCAML_C_H */
diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c
index 6675cf8c..6b1a9f62 100644
--- a/ocaml/guestfs_c_actions.c
+++ b/ocaml/guestfs_c_actions.c
@@ -1347,3 +1347,321 @@ ocaml_guestfs_chown (value gv, value ownerv, value groupv, value pathv)
CAMLreturn (rv);
}
+CAMLprim value
+ocaml_guestfs_exists (value gv, value pathv)
+{
+ CAMLparam2 (gv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("exists: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_exists (g, path);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "exists");
+
+ rv = Val_bool (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_is_file (value gv, value pathv)
+{
+ CAMLparam2 (gv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("is_file: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_is_file (g, path);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "is_file");
+
+ rv = Val_bool (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_is_dir (value gv, value pathv)
+{
+ CAMLparam2 (gv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("is_dir: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_is_dir (g, path);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "is_dir");
+
+ rv = Val_bool (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_pvcreate (value gv, value devicev)
+{
+ CAMLparam2 (gv, devicev);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("pvcreate: used handle after closing it");
+
+ const char *device = String_val (devicev);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_pvcreate (g, device);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "pvcreate");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_vgcreate (value gv, value volgroupv, value physvolsv)
+{
+ CAMLparam3 (gv, volgroupv, physvolsv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("vgcreate: used handle after closing it");
+
+ const char *volgroup = String_val (volgroupv);
+ char **physvols = ocaml_guestfs_strings_val (physvolsv);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_vgcreate (g, volgroup, physvols);
+ caml_leave_blocking_section ();
+ ocaml_guestfs_free_strings (physvols);
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "vgcreate");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_lvcreate (value gv, value logvolv, value volgroupv, value mbytesv)
+{
+ CAMLparam4 (gv, logvolv, volgroupv, mbytesv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("lvcreate: used handle after closing it");
+
+ const char *logvol = String_val (logvolv);
+ const char *volgroup = String_val (volgroupv);
+ int mbytes = Int_val (mbytesv);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_lvcreate (g, logvol, volgroup, mbytes);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "lvcreate");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_mkfs (value gv, value fstypev, value devicev)
+{
+ CAMLparam3 (gv, fstypev, devicev);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("mkfs: used handle after closing it");
+
+ const char *fstype = String_val (fstypev);
+ const char *device = String_val (devicev);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_mkfs (g, fstype, device);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "mkfs");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk (value gv, value devicev, value cylsv, value headsv, value sectorsv, value linesv)
+{
+ CAMLparam5 (gv, devicev, cylsv, headsv, sectorsv);
+ CAMLxparam1 (linesv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("sfdisk: used handle after closing it");
+
+ const char *device = String_val (devicev);
+ int cyls = Int_val (cylsv);
+ int heads = Int_val (headsv);
+ int sectors = Int_val (sectorsv);
+ char **lines = ocaml_guestfs_strings_val (linesv);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_sfdisk (g, device, cyls, heads, sectors, lines);
+ caml_leave_blocking_section ();
+ ocaml_guestfs_free_strings (lines);
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "sfdisk");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk_byte (value *argv, int argn)
+{
+ return ocaml_guestfs_sfdisk (argv[0], argv[0], argv[1], argv[2], argv[3], argv[4]);
+}
+
+CAMLprim value
+ocaml_guestfs_write_file (value gv, value pathv, value contentv, value sizev)
+{
+ CAMLparam4 (gv, pathv, contentv, sizev);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("write_file: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ const char *content = String_val (contentv);
+ int size = Int_val (sizev);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_write_file (g, path, content, size);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "write_file");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_umount (value gv, value pathordevicev)
+{
+ CAMLparam2 (gv, pathordevicev);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("umount: used handle after closing it");
+
+ const char *pathordevice = String_val (pathordevicev);
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_umount (g, pathordevice);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "umount");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_mounts (value gv)
+{
+ CAMLparam1 (gv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("mounts: used handle after closing it");
+
+ int i;
+ char **r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_mounts (g);
+ caml_leave_blocking_section ();
+ if (r == NULL)
+ ocaml_guestfs_raise_error (g, "mounts");
+
+ rv = caml_copy_string_array ((const char **) r);
+ for (i = 0; r[i] != NULL; ++i) free (r[i]);
+ free (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_umount_all (value gv)
+{
+ CAMLparam1 (gv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("umount_all: used handle after closing it");
+
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_umount_all (g);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "umount_all");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_lvm_remove_all (value gv)
+{
+ CAMLparam1 (gv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("lvm_remove_all: used handle after closing it");
+
+ int r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_lvm_remove_all (g);
+ caml_leave_blocking_section ();
+ if (r == -1)
+ ocaml_guestfs_raise_error (g, "lvm_remove_all");
+
+ rv = Val_unit;
+ CAMLreturn (rv);
+}
+
diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs
index d5f1da6b..0f72c282 100644
--- a/perl/Guestfs.xs
+++ b/perl/Guestfs.xs
@@ -73,6 +73,35 @@ error_handler (guestfs_h *g,
last_error = strdup (msg);
}
+/* http://www.perlmonks.org/?node_id=680842 */
+static char **
+XS_unpack_charPtrPtr (SV *arg) {
+ char **ret;
+ AV *av;
+ I32 i;
+
+ if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV) {
+ croak ("array reference expected");
+ }
+
+ av = (AV *)SvRV (arg);
+ ret = (char **)malloc (av_len (av) + 1 + 1);
+
+ for (i = 0; i <= av_len (av); i++) {
+ SV **elem = av_fetch (av, i, 0);
+
+ if (!elem || !*elem) {
+ croak ("missing element in list");
+ }
+
+ ret[i] = SvPV_nolen (*elem);
+ }
+
+ ret[i + 1] = NULL;
+
+ return ret;
+}
+
MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
guestfs_h *
@@ -95,38 +124,43 @@ void
launch (g)
guestfs_h *g;
PPCODE:
- if (guestfs_launch (g) == -1)
+ if (guestfs_launch (g) == -1) {
croak ("launch: %s", last_error);
+ }
void
wait_ready (g)
guestfs_h *g;
PPCODE:
- if (guestfs_wait_ready (g) == -1)
+ if (guestfs_wait_ready (g) == -1) {
croak ("wait_ready: %s", last_error);
+ }
void
kill_subprocess (g)
guestfs_h *g;
PPCODE:
- if (guestfs_kill_subprocess (g) == -1)
+ if (guestfs_kill_subprocess (g) == -1) {
croak ("kill_subprocess: %s", last_error);
+ }
void
add_drive (g, filename)
guestfs_h *g;
char *filename;
PPCODE:
- if (guestfs_add_drive (g, filename) == -1)
+ if (guestfs_add_drive (g, filename) == -1) {
croak ("add_drive: %s", last_error);
+ }
void
add_cdrom (g, filename)
guestfs_h *g;
char *filename;
PPCODE:
- if (guestfs_add_cdrom (g, filename) == -1)
+ if (guestfs_add_cdrom (g, filename) == -1) {
croak ("add_cdrom: %s", last_error);
+ }
void
config (g, qemuparam, qemuvalue)
@@ -134,16 +168,18 @@ config (g, qemuparam, qemuvalue)
char *qemuparam;
char *qemuvalue;
PPCODE:
- if (guestfs_config (g, qemuparam, qemuvalue) == -1)
+ if (guestfs_config (g, qemuparam, qemuvalue) == -1) {
croak ("config: %s", last_error);
+ }
void
set_path (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_set_path (g, path) == -1)
+ if (guestfs_set_path (g, path) == -1) {
croak ("set_path: %s", last_error);
+ }
SV *
get_path (g)
@@ -152,8 +188,9 @@ PREINIT:
const char *path;
CODE:
path = guestfs_get_path (g);
- if (path == NULL)
+ if (path == NULL) {
croak ("get_path: %s", last_error);
+ }
RETVAL = newSVpv (path, 0);
OUTPUT:
RETVAL
@@ -163,8 +200,9 @@ set_autosync (g, autosync)
guestfs_h *g;
int autosync;
PPCODE:
- if (guestfs_set_autosync (g, autosync) == -1)
+ if (guestfs_set_autosync (g, autosync) == -1) {
croak ("set_autosync: %s", last_error);
+ }
SV *
get_autosync (g)
@@ -173,8 +211,9 @@ PREINIT:
int autosync;
CODE:
autosync = guestfs_get_autosync (g);
- if (autosync == -1)
+ if (autosync == -1) {
croak ("get_autosync: %s", last_error);
+ }
RETVAL = newSViv (autosync);
OUTPUT:
RETVAL
@@ -184,8 +223,9 @@ set_verbose (g, verbose)
guestfs_h *g;
int verbose;
PPCODE:
- if (guestfs_set_verbose (g, verbose) == -1)
+ if (guestfs_set_verbose (g, verbose) == -1) {
croak ("set_verbose: %s", last_error);
+ }
SV *
get_verbose (g)
@@ -194,8 +234,9 @@ PREINIT:
int verbose;
CODE:
verbose = guestfs_get_verbose (g);
- if (verbose == -1)
+ if (verbose == -1) {
croak ("get_verbose: %s", last_error);
+ }
RETVAL = newSViv (verbose);
OUTPUT:
RETVAL
@@ -206,23 +247,26 @@ mount (g, device, mountpoint)
char *device;
char *mountpoint;
PPCODE:
- if (guestfs_mount (g, device, mountpoint) == -1)
+ if (guestfs_mount (g, device, mountpoint) == -1) {
croak ("mount: %s", last_error);
+ }
void
sync (g)
guestfs_h *g;
PPCODE:
- if (guestfs_sync (g) == -1)
+ if (guestfs_sync (g) == -1) {
croak ("sync: %s", last_error);
+ }
void
touch (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_touch (g, path) == -1)
+ if (guestfs_touch (g, path) == -1) {
croak ("touch: %s", last_error);
+ }
SV *
cat (g, path)
@@ -232,8 +276,9 @@ PREINIT:
char *content;
CODE:
content = guestfs_cat (g, path);
- if (content == NULL)
+ if (content == NULL) {
croak ("cat: %s", last_error);
+ }
RETVAL = newSVpv (content, 0);
free (content);
OUTPUT:
@@ -247,8 +292,9 @@ PREINIT:
char *listing;
CODE:
listing = guestfs_ll (g, directory);
- if (listing == NULL)
+ if (listing == NULL) {
croak ("ll: %s", last_error);
+ }
RETVAL = newSVpv (listing, 0);
free (listing);
OUTPUT:
@@ -263,8 +309,9 @@ PREINIT:
int i, n;
PPCODE:
listing = guestfs_ls (g, directory);
- if (listing == NULL)
+ if (listing == NULL) {
croak ("ls: %s", last_error);
+ }
for (n = 0; listing[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -281,8 +328,9 @@ PREINIT:
int i, n;
PPCODE:
devices = guestfs_list_devices (g);
- if (devices == NULL)
+ if (devices == NULL) {
croak ("list_devices: %s", last_error);
+ }
for (n = 0; devices[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -299,8 +347,9 @@ PREINIT:
int i, n;
PPCODE:
partitions = guestfs_list_partitions (g);
- if (partitions == NULL)
+ if (partitions == NULL) {
croak ("list_partitions: %s", last_error);
+ }
for (n = 0; partitions[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -317,8 +366,9 @@ PREINIT:
int i, n;
PPCODE:
physvols = guestfs_pvs (g);
- if (physvols == NULL)
+ if (physvols == NULL) {
croak ("pvs: %s", last_error);
+ }
for (n = 0; physvols[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -335,8 +385,9 @@ PREINIT:
int i, n;
PPCODE:
volgroups = guestfs_vgs (g);
- if (volgroups == NULL)
+ if (volgroups == NULL) {
croak ("vgs: %s", last_error);
+ }
for (n = 0; volgroups[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -353,8 +404,9 @@ PREINIT:
int i, n;
PPCODE:
logvols = guestfs_lvs (g);
- if (logvols == NULL)
+ if (logvols == NULL) {
croak ("lvs: %s", last_error);
+ }
for (n = 0; logvols[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -475,8 +527,9 @@ PREINIT:
int i, n;
PPCODE:
lines = guestfs_read_lines (g, path);
- if (lines == NULL)
+ if (lines == NULL) {
croak ("read_lines: %s", last_error);
+ }
for (n = 0; lines[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -491,15 +544,17 @@ aug_init (g, root, flags)
char *root;
int flags;
PPCODE:
- if (guestfs_aug_init (g, root, flags) == -1)
+ if (guestfs_aug_init (g, root, flags) == -1) {
croak ("aug_init: %s", last_error);
+ }
void
aug_close (g)
guestfs_h *g;
PPCODE:
- if (guestfs_aug_close (g) == -1)
+ if (guestfs_aug_close (g) == -1) {
croak ("aug_close: %s", last_error);
+ }
SV *
aug_defvar (g, name, expr)
@@ -510,8 +565,9 @@ PREINIT:
int nrnodes;
CODE:
nrnodes = guestfs_aug_defvar (g, name, expr);
- if (nrnodes == -1)
+ if (nrnodes == -1) {
croak ("aug_defvar: %s", last_error);
+ }
RETVAL = newSViv (nrnodes);
OUTPUT:
RETVAL
@@ -526,8 +582,9 @@ PREINIT:
struct guestfs_int_bool *r;
PPCODE:
r = guestfs_aug_defnode (g, name, expr, val);
- if (r == NULL)
+ if (r == NULL) {
croak ("aug_defnode: %s", last_error);
+ }
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (r->i)));
PUSHs (sv_2mortal (newSViv (r->b)));
@@ -541,8 +598,9 @@ PREINIT:
char *val;
CODE:
val = guestfs_aug_get (g, path);
- if (val == NULL)
+ if (val == NULL) {
croak ("aug_get: %s", last_error);
+ }
RETVAL = newSVpv (val, 0);
free (val);
OUTPUT:
@@ -554,8 +612,9 @@ aug_set (g, path, val)
char *path;
char *val;
PPCODE:
- if (guestfs_aug_set (g, path, val) == -1)
+ if (guestfs_aug_set (g, path, val) == -1) {
croak ("aug_set: %s", last_error);
+ }
void
aug_insert (g, path, label, before)
@@ -564,8 +623,9 @@ aug_insert (g, path, label, before)
char *label;
int before;
PPCODE:
- if (guestfs_aug_insert (g, path, label, before) == -1)
+ if (guestfs_aug_insert (g, path, label, before) == -1) {
croak ("aug_insert: %s", last_error);
+ }
SV *
aug_rm (g, path)
@@ -575,8 +635,9 @@ PREINIT:
int nrnodes;
CODE:
nrnodes = guestfs_aug_rm (g, path);
- if (nrnodes == -1)
+ if (nrnodes == -1) {
croak ("aug_rm: %s", last_error);
+ }
RETVAL = newSViv (nrnodes);
OUTPUT:
RETVAL
@@ -587,8 +648,9 @@ aug_mv (g, src, dest)
char *src;
char *dest;
PPCODE:
- if (guestfs_aug_mv (g, src, dest) == -1)
+ if (guestfs_aug_mv (g, src, dest) == -1) {
croak ("aug_mv: %s", last_error);
+ }
void
aug_match (g, path)
@@ -599,8 +661,9 @@ PREINIT:
int i, n;
PPCODE:
matches = guestfs_aug_match (g, path);
- if (matches == NULL)
+ if (matches == NULL) {
croak ("aug_match: %s", last_error);
+ }
for (n = 0; matches[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -613,15 +676,17 @@ void
aug_save (g)
guestfs_h *g;
PPCODE:
- if (guestfs_aug_save (g) == -1)
+ if (guestfs_aug_save (g) == -1) {
croak ("aug_save: %s", last_error);
+ }
void
aug_load (g)
guestfs_h *g;
PPCODE:
- if (guestfs_aug_load (g) == -1)
+ if (guestfs_aug_load (g) == -1) {
croak ("aug_load: %s", last_error);
+ }
void
aug_ls (g, path)
@@ -632,8 +697,9 @@ PREINIT:
int i, n;
PPCODE:
matches = guestfs_aug_ls (g, path);
- if (matches == NULL)
+ if (matches == NULL) {
croak ("aug_ls: %s", last_error);
+ }
for (n = 0; matches[n] != NULL; ++n) /**/;
EXTEND (SP, n);
for (i = 0; i < n; ++i) {
@@ -647,40 +713,45 @@ rm (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_rm (g, path) == -1)
+ if (guestfs_rm (g, path) == -1) {
croak ("rm: %s", last_error);
+ }
void
rmdir (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_rmdir (g, path) == -1)
+ if (guestfs_rmdir (g, path) == -1) {
croak ("rmdir: %s", last_error);
+ }
void
rm_rf (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_rm_rf (g, path) == -1)
+ if (guestfs_rm_rf (g, path) == -1) {
croak ("rm_rf: %s", last_error);
+ }
void
mkdir (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_mkdir (g, path) == -1)
+ if (guestfs_mkdir (g, path) == -1) {
croak ("mkdir: %s", last_error);
+ }
void
mkdir_p (g, path)
guestfs_h *g;
char *path;
PPCODE:
- if (guestfs_mkdir_p (g, path) == -1)
+ if (guestfs_mkdir_p (g, path) == -1) {
croak ("mkdir_p: %s", last_error);
+ }
void
chmod (g, mode, path)
@@ -688,8 +759,9 @@ chmod (g, mode, path)
int mode;
char *path;
PPCODE:
- if (guestfs_chmod (g, mode, path) == -1)
+ if (guestfs_chmod (g, mode, path) == -1) {
croak ("chmod: %s", last_error);
+ }
void
chown (g, owner, group, path)
@@ -698,6 +770,164 @@ chown (g, owner, group, path)
int group;
char *path;
PPCODE:
- if (guestfs_chown (g, owner, group, path) == -1)
+ if (guestfs_chown (g, owner, group, path) == -1) {
croak ("chown: %s", last_error);
+ }
+
+SV *
+exists (g, path)
+ guestfs_h *g;
+ char *path;
+PREINIT:
+ int existsflag;
+ CODE:
+ existsflag = guestfs_exists (g, path);
+ if (existsflag == -1) {
+ croak ("exists: %s", last_error);
+ }
+ RETVAL = newSViv (existsflag);
+ OUTPUT:
+ RETVAL
+
+SV *
+is_file (g, path)
+ guestfs_h *g;
+ char *path;
+PREINIT:
+ int fileflag;
+ CODE:
+ fileflag = guestfs_is_file (g, path);
+ if (fileflag == -1) {
+ croak ("is_file: %s", last_error);
+ }
+ RETVAL = newSViv (fileflag);
+ OUTPUT:
+ RETVAL
+
+SV *
+is_dir (g, path)
+ guestfs_h *g;
+ char *path;
+PREINIT:
+ int dirflag;
+ CODE:
+ dirflag = guestfs_is_dir (g, path);
+ if (dirflag == -1) {
+ croak ("is_dir: %s", last_error);
+ }
+ RETVAL = newSViv (dirflag);
+ OUTPUT:
+ RETVAL
+
+void
+pvcreate (g, device)
+ guestfs_h *g;
+ char *device;
+ PPCODE:
+ if (guestfs_pvcreate (g, device) == -1) {
+ croak ("pvcreate: %s", last_error);
+ }
+
+void
+vgcreate (g, volgroup, physvols)
+ guestfs_h *g;
+ char *volgroup;
+ char **physvols;
+ PPCODE:
+ if (guestfs_vgcreate (g, volgroup, physvols) == -1) {
+ free (physvols);
+ croak ("vgcreate: %s", last_error);
+ }
+ free (physvols);
+
+void
+lvcreate (g, logvol, volgroup, mbytes)
+ guestfs_h *g;
+ char *logvol;
+ char *volgroup;
+ int mbytes;
+ PPCODE:
+ if (guestfs_lvcreate (g, logvol, volgroup, mbytes) == -1) {
+ croak ("lvcreate: %s", last_error);
+ }
+
+void
+mkfs (g, fstype, device)
+ guestfs_h *g;
+ char *fstype;
+ char *device;
+ PPCODE:
+ if (guestfs_mkfs (g, fstype, device) == -1) {
+ croak ("mkfs: %s", last_error);
+ }
+
+void
+sfdisk (g, device, cyls, heads, sectors, lines)
+ guestfs_h *g;
+ char *device;
+ int cyls;
+ int heads;
+ int sectors;
+ char **lines;
+ PPCODE:
+ if (guestfs_sfdisk (g, device, cyls, heads, sectors, lines) == -1) {
+ free (lines);
+ croak ("sfdisk: %s", last_error);
+ }
+ free (lines);
+
+void
+write_file (g, path, content, size)
+ guestfs_h *g;
+ char *path;
+ char *content;
+ int size;
+ PPCODE:
+ if (guestfs_write_file (g, path, content, size) == -1) {
+ croak ("write_file: %s", last_error);
+ }
+
+void
+umount (g, pathordevice)
+ guestfs_h *g;
+ char *pathordevice;
+ PPCODE:
+ if (guestfs_umount (g, pathordevice) == -1) {
+ croak ("umount: %s", last_error);
+ }
+
+void
+mounts (g)
+ guestfs_h *g;
+PREINIT:
+ char **devices;
+ int i, n;
+ PPCODE:
+ devices = guestfs_mounts (g);
+ if (devices == NULL) {
+ croak ("mounts: %s", last_error);
+ }
+ for (n = 0; devices[n] != NULL; ++n) /**/;
+ EXTEND (SP, n);
+ for (i = 0; i < n; ++i) {
+ PUSHs (sv_2mortal (newSVpv (devices[i], 0)));
+ free (devices[i]);
+ }
+ free (devices);
+
+void
+umount_all (g)
+ guestfs_h *g;
+ PPCODE:
+ if (guestfs_umount_all (g) == -1) {
+ croak ("umount_all: %s", last_error);
+ }
+
+void
+lvm_remove_all (g)
+ guestfs_h *g;
+ PPCODE:
+ if (guestfs_lvm_remove_all (g) == -1) {
+ croak ("lvm_remove_all: %s", last_error);
+ }
diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm
index 50f5d750..c708a29c 100644
--- a/perl/lib/Sys/Guestfs.pm
+++ b/perl/lib/Sys/Guestfs.pm
@@ -91,13 +91,13 @@ sub new {
return $self;
}
-=item $h->add_cdrom (filename);
+=item $h->add_cdrom ($filename);
This function adds a virtual CD-ROM disk image to the guest.
This is equivalent to the qemu parameter C<-cdrom filename>.
-=item $h->add_drive (filename);
+=item $h->add_drive ($filename);
This function adds a virtual machine disk image C<filename> to the
guest. The first time you call this function, the disk appears as IDE
@@ -119,7 +119,7 @@ used by it. After calling this, you have to call
C<$h-E<gt>aug_init> again before you can use any other
Augeas functions.
-=item ($nrnodes, $created) = $h->aug_defnode (name, expr, val);
+=item ($nrnodes, $created) = $h->aug_defnode ($name, $expr, $val);
Defines a variable C<name> whose value is the result of
evaluating C<expr>.
@@ -132,7 +132,7 @@ On success this returns a pair containing the
number of nodes in the nodeset, and a boolean flag
if a node was created.
-=item $nrnodes = $h->aug_defvar (name, expr);
+=item $nrnodes = $h->aug_defvar ($name, $expr);
Defines an Augeas variable C<name> whose value is the result
of evaluating C<expr>. If C<expr> is NULL, then C<name> is
@@ -141,12 +141,12 @@ undefined.
On success this returns the number of nodes in C<expr>, or
C<0> if C<expr> evaluates to something which is not a nodeset.
-=item $val = $h->aug_get (path);
+=item $val = $h->aug_get ($path);
Look up the value associated with C<path>. If C<path>
matches exactly one node, the C<value> is returned.
-=item $h->aug_init (root, flags);
+=item $h->aug_init ($root, $flags);
Create a new Augeas handle for editing configuration files.
If there was any previous Augeas handle associated with this
@@ -195,7 +195,7 @@ To close the handle, you can call C<$h-E<gt>aug_close>.
To find out more about Augeas, see L<http://augeas.net/>.
-=item $h->aug_insert (path, label, before);
+=item $h->aug_insert ($path, $label, $before);
Create a new sibling C<label> for C<path>, inserting it into
the tree before or after C<path> (depending on the boolean
@@ -212,23 +212,23 @@ Load files into the tree.
See C<aug_load> in the Augeas documentation for the full gory
details.
-=item @matches = $h->aug_ls (path);
+=item @matches = $h->aug_ls ($path);
This is just a shortcut for listing C<$h-E<gt>aug_match>
C<path/*> and sorting the resulting nodes into alphabetical order.
-=item @matches = $h->aug_match (path);
+=item @matches = $h->aug_match ($path);
Returns a list of paths which match the path expression C<path>.
The returned paths are sufficiently qualified so that they match
exactly one node in the current tree.
-=item $h->aug_mv (src, dest);
+=item $h->aug_mv ($src, $dest);
Move the node C<src> to C<dest>. C<src> must match exactly
one node. C<dest> is overwritten if it exists.
-=item $nrnodes = $h->aug_rm (path);
+=item $nrnodes = $h->aug_rm ($path);
Remove C<path> and all of its children.
@@ -241,11 +241,11 @@ This writes all pending changes to disk.
The flags which were passed to C<$h-E<gt>aug_init> affect exactly
how files are saved.
-=item $h->aug_set (path, val);
+=item $h->aug_set ($path, $val);
Set the value associated with C<path> to C<value>.
-=item $content = $h->cat (path);
+=item $content = $h->cat ($path);
Return the contents of the file named C<path>.
@@ -258,12 +258,12 @@ Because of the message protocol, there is a transfer limit
of somewhere between 2MB and 4MB. To transfer large files you should use
FTP.
-=item $h->chmod (mode, path);
+=item $h->chmod ($mode, $path);
Change the mode (permissions) of C<path> to C<mode>. Only
numeric modes are supported.
-=item $h->chown (owner, group, path);
+=item $h->chown ($owner, $group, $path);
Change the file owner to C<owner> and group to C<group>.
@@ -271,7 +271,7 @@ Only numeric uid and gid are supported. If you want to use
names, you will need to locate and parse the password file
yourself (Augeas support makes this relatively easy).
-=item $h->config (qemuparam, qemuvalue);
+=item $h->config ($qemuparam, $qemuvalue);
This can be used to add arbitrary qemu command line parameters
of the form C<-param value>. Actually it's not quite arbitrary - we
@@ -282,6 +282,13 @@ The first character of C<param> string must be a C<-> (dash).
C<value> can be NULL.
+=item $existsflag = $h->exists ($path);
+
+This returns C<true> if and only if there is a file, directory
+(or anything) with the given C<path> name.
+
+See also C<$h-E<gt>is_file>, C<$h-E<gt>is_dir>, C<$h-E<gt>stat>.
+
=item $autosync = $h->get_autosync ();
Get the autosync flag.
@@ -297,6 +304,22 @@ return the default path.
This returns the verbose messages flag.
+=item $dirflag = $h->is_dir ($path);
+
+This returns C<true> if and only if there is a directory
+with the given C<path> name. Note that it returns false for
+other objects like files.
+
+See also C<$h-E<gt>stat>.
+
+=item $fileflag = $h->is_file ($path);
+
+This returns C<true> if and only if there is a file
+with the given C<path> name. Note that it returns false for
+other objects like directories.
+
+See also C<$h-E<gt>stat>.
+
=item $h->kill_subprocess ();
This kills the qemu subprocess. You should never need to call this.
@@ -324,7 +347,7 @@ The full partition device names are returned, eg. C</dev/sda1>
This does not return logical volumes. For that you will need to
call C<$h-E<gt>lvs>.
-=item $listing = $h->ll (directory);
+=item $listing = $h->ll ($directory);
List the files in C<directory> (relative to the root directory,
there is no cwd) in the format of 'ls -la'.
@@ -332,7 +355,7 @@ there is no cwd) in the format of 'ls -la'.
This command is mostly useful for interactive sessions. It
is I<not> intended that you try to parse the output string.
-=item @listing = $h->ls (directory);
+=item @listing = $h->ls ($directory);
List the files in C<directory> (relative to the root directory,
there is no cwd). The '.' and '..' entries are not returned, but
@@ -341,6 +364,19 @@ hidden files are shown.
This command is mostly useful for interactive sessions. Programs
should probably use C<$h-E<gt>readdir> instead.
+=item $h->lvcreate ($logvol, $volgroup, $mbytes);
+
+This creates an LVM volume group called C<logvol>
+on the volume group C<volgroup>, with C<size> megabytes.
+
+=item $h->lvm_remove_all ();
+
+This command removes all LVM logical volumes, volume groups
+and physical volumes.
+
+B<This command is dangerous. Without careful use you
+can easily destroy all your data>.
+
=item @logvols = $h->lvs ();
List all the logical volumes detected. This is the equivalent
@@ -356,16 +392,22 @@ See also C<$h-E<gt>lvs_full>.
List all the logical volumes detected. This is the equivalent
of the L<lvs(8)> command. The "full" version includes all fields.
-=item $h->mkdir (path);
+=item $h->mkdir ($path);
Create a directory named C<path>.
-=item $h->mkdir_p (path);
+=item $h->mkdir_p ($path);
Create a directory named C<path>, creating any parent directories
as necessary. This is like the C<mkdir -p> shell command.
-=item $h->mount (device, mountpoint);
+=item $h->mkfs ($fstype, $device);
+
+This creates a filesystem on C<device> (usually a partition
+of LVM logical volume). The filesystem type is C<fstype>, for
+example C<ext3>.
+
+=item $h->mount ($device, $mountpoint);
Mount a guest disk at a position in the filesystem. Block devices
are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
@@ -384,6 +426,19 @@ on the underlying device.
The filesystem options C<sync> and C<noatime> are set with this
call, in order to improve reliability.
+=item @devices = $h->mounts ();
+
+This returns the list of currently mounted filesystems. It returns
+the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
+
+Some internal mounts are not shown.
+
+=item $h->pvcreate ($device);
+
+This creates an LVM physical volume on the named C<device>,
+where C<device> should usually be a partition name such
+as C</dev/sda1>.
+
=item @physvols = $h->pvs ();
List all the physical volumes detected. This is the equivalent
@@ -399,7 +454,7 @@ See also C<$h-E<gt>pvs_full>.
List all the physical volumes detected. This is the equivalent
of the L<pvs(8)> command. The "full" version includes all fields.
-=item @lines = $h->read_lines (path);
+=item @lines = $h->read_lines ($path);
Return the contents of the file named C<path>.
@@ -411,27 +466,27 @@ Note that this function cannot correctly handle binary files
as end of line). For those you need to use the C<$h-E<gt>read_file>
function which has a more complex interface.
-=item $h->rm (path);
+=item $h->rm ($path);
Remove the single file C<path>.
-=item $h->rm_rf (path);
+=item $h->rm_rf ($path);
Remove the file or directory C<path>, recursively removing the
contents if its a directory. This is like the C<rm -rf> shell
command.
-=item $h->rmdir (path);
+=item $h->rmdir ($path);
Remove the single directory C<path>.
-=item $h->set_autosync (autosync);
+=item $h->set_autosync ($autosync);
If C<autosync> is true, this enables autosync. Libguestfs will make a
best effort attempt to run C<$h-E<gt>sync> when the handle is closed
(also if the program exits without closing handles).
-=item $h->set_path (path);
+=item $h->set_path ($path);
Set the path that libguestfs searches for kernel and initrd.img.
@@ -443,13 +498,38 @@ must make sure it remains valid for the lifetime of the handle.
Setting C<path> to C<NULL> restores the default path.
-=item $h->set_verbose (verbose);
+=item $h->set_verbose ($verbose);
If C<verbose> is true, this turns on verbose messages (to C<stderr>).
Verbose messages are disabled unless the environment variable
C<LIBGUESTFS_DEBUG> is defined and set to C<1>.
+=item $h->sfdisk ($device, $cyls, $heads, $sectors, \@lines);
+
+This is a direct interface to the L<sfdisk(8)> program for creating
+partitions on block devices.
+
+C<device> should be a block device, for example C</dev/sda>.
+
+C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
+and sectors on the device, which are passed directly to sfdisk as
+the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
+of these, then the corresponding parameter is omitted. Usually for
+'large' disks, you can just pass C<0> for these, but for small
+(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
+out the right geometry and you will need to tell it.
+
+C<lines> is a list of lines that we feed to C<sfdisk>. For more
+information refer to the L<sfdisk(8)> manpage.
+
+To create a single partition occupying the whole disk, you would
+pass C<lines> as a single element list, when the single element being
+the string C<,> (comma).
+
+B<This command is dangerous. Without careful use you
+can easily destroy all your data>.
+
=item $h->sync ();
This syncs the disk, so that any writes are flushed through to the
@@ -458,12 +538,29 @@ underlying disk image.
You should always call this if you have modified a disk image, before
closing the handle.
-=item $h->touch (path);
+=item $h->touch ($path);
Touch acts like the L<touch(1)> command. It can be used to
update the timestamps on a file, or, if the file does not exist,
to create a new zero-length file.
+=item $h->umount ($pathordevice);
+
+This unmounts the given filesystem. The filesystem may be
+specified either by its mountpoint (path) or the device which
+contains the filesystem.
+
+=item $h->umount_all ();
+
+This unmounts all mounted filesystems.
+
+Some internal mounts are not unmounted by this call.
+
+=item $h->vgcreate ($volgroup, \@physvols);
+
+This creates an LVM volume group called C<volgroup>
+from the non-empty list of physical volumes C<physvols>.
+
=item @volgroups = $h->vgs ();
List all the volumes groups detected. This is the equivalent
@@ -487,6 +584,20 @@ using L<qemu(1)>.
You should call this after C<$h-E<gt>launch> to wait for the launch
to complete.
+=item $h->write_file ($path, $content, $size);
+
+This call creates a file called C<path>. The contents of the
+file is the string C<content> (which can contain any 8 bit data),
+with length C<size>.
+
+As a special case, if C<size> is C<0>
+then the length is calculated using C<strlen> (so in this case
+the content cannot contain embedded ASCII NULs).
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=cut
1;
diff --git a/src/generator.ml b/src/generator.ml
index 06a638e6..6792e07a 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -77,59 +77,74 @@ and args = argt list (* Function parameters, guestfs handle is implicit. *)
and argt =
| String of string (* const char *name, cannot be NULL *)
| OptString of string (* const char *name, may be NULL *)
+ | StringList of string(* list of strings (each string cannot be NULL) *)
| Bool of string (* boolean *)
| Int of string (* int (smallish ints, signed, <= 31 bits) *)
type flags =
| ProtocolLimitWarning (* display warning about protocol size limits *)
+ | DangerWillRobinson (* flags particularly dangerous commands *)
| FishAlias of string (* provide an alias for this cmd in guestfish *)
| FishAction of string (* call this function in guestfish *)
| NotInFish (* do not export via guestfish *)
+let protocol_limit_warning =
+ "Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP."
+
+let danger_will_robinson =
+ "B<This command is dangerous. Without careful use you
+can easily destroy all your data>."
+
(* You can supply zero or as many tests as you want per API call.
*
- * Note that the test environment has 3 block devices, of size 10M, 20M
- * and 30M (respectively /dev/sda, /dev/sdb, /dev/sdc). To run the
- * tests in a reasonable amount of time, the virtual machine and
- * block devices are reused between tests. So don't try testing
- * kill_subprocess :-x
+ * Note that the test environment has 3 block devices, of size 500MB,
+ * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc).
+ * Note for partitioning purposes, the 500MB device has 63 cylinders.
+ *
+ * To be able to run the tests in a reasonable amount of time,
+ * the virtual machine and block devices are reused between tests.
+ * So don't try testing kill_subprocess :-x
+ *
+ * Between each test we umount-all and lvm-remove-all.
*
* Don't assume anything about the previous contents of the block
* devices. Use 'Init*' to create some initial scenarios.
*)
-type tests = test list
+type tests = (test_init * test) list
and test =
(* Run the command sequence and just expect nothing to fail. *)
- | TestRun of test_init * seq
+ | TestRun of seq
(* Run the command sequence and expect the output of the final
* command to be the string.
*)
- | TestOutput of test_init * seq * string
+ | TestOutput of seq * string
(* Run the command sequence and expect the output of the final
* command to be the list of strings.
*)
- | TestOutputList of test_init * seq * string list
+ | TestOutputList of seq * string list
(* Run the command sequence and expect the output of the final
* command to be the integer.
*)
- | TestOutputInt of test_init * seq * int
+ | TestOutputInt of seq * int
(* Run the command sequence and expect the output of the final
* command to be a true value (!= 0 or != NULL).
*)
- | TestOutputTrue of test_init * seq
+ | TestOutputTrue of seq
(* Run the command sequence and expect the output of the final
* command to be a false value (== 0 or == NULL, but not an error).
*)
- | TestOutputFalse of test_init * seq
+ | TestOutputFalse of seq
(* Run the command sequence and expect the output of the final
* command to be a list of the given length (but don't care about
* content).
*)
- | TestOutputLength of test_init * seq * int
+ | TestOutputLength of seq * int
(* Run the command sequence and expect the final command (only)
* to fail.
*)
- | TestLastFail of test_init * seq
+ | TestLastFail of seq
(* Some initial scenarios for testing. *)
and test_init =
@@ -143,7 +158,7 @@ and test_init =
| InitEmpty
(* /dev/sda:
* /dev/sda1 (is a PV):
- * /dev/VG/LV:
+ * /dev/VG/LV (size 8MB):
* formatted as ext2, empty [except for lost+found], mounted on /
* /dev/sdb and /dev/sdc may have random content.
*)
@@ -281,9 +296,8 @@ This returns the verbose messages flag.")
let daemon_functions = [
("mount", (RErr, [String "device"; String "mountpoint"]), 1, [],
- [TestOutput (
- InitNone,
- [["sfdisk"];
+ [InitNone, TestOutput (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
["mkfs"; "ext2"; "/dev/sda1"];
["mount"; "/dev/sda1"; "/"];
["write_file"; "/new"; "new file contents"; "0"];
@@ -308,7 +322,7 @@ The filesystem options C<sync> and C<noatime> are set with this
call, in order to improve reliability.");
("sync", (RErr, []), 2, [],
- [ TestRun (InitNone, [["sync"]])],
+ [ InitNone, TestRun [["sync"]]],
"sync disks, writes are flushed through to the disk image",
"\
This syncs the disk, so that any writes are flushed through to the
@@ -318,8 +332,7 @@ You should always call this if you have modified a disk image, before
closing the handle.");
("touch", (RErr, [String "path"]), 3, [],
- [TestOutputTrue (
- InitEmpty,
+ [InitEmpty, TestOutputTrue (
[["touch"; "/new"];
["exists"; "/new"]])],
"update file timestamps or create a new file",
@@ -329,8 +342,7 @@ update the timestamps on a file, or, if the file does not exist,
to create a new zero-length file.");
("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning],
- [TestOutput (
- InitEmpty,
+ [InitEmpty, TestOutput (
[["write_file"; "/new"; "new file contents"; "0"];
["cat"; "/new"]], "new file contents")],
"list the contents of a file",
@@ -355,8 +367,7 @@ This command is mostly useful for interactive sessions. It
is I<not> intended that you try to parse the output string.");
("ls", (RStringList "listing", [String "directory"]), 6, [],
- [TestOutputList (
- InitEmpty,
+ [InitEmpty, TestOutputList (
[["touch"; "/new"];
["touch"; "/newer"];
["touch"; "/newest"];
@@ -371,8 +382,7 @@ This command is mostly useful for interactive sessions. Programs
should probably use C<guestfs_readdir> instead.");
("list_devices", (RStringList "devices", []), 7, [],
- [TestOutputList (
- InitNone,
+ [InitNone, TestOutputList (
[["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"])],
"list the block devices",
"\
@@ -381,12 +391,10 @@ List all the block devices.
The full block device names are returned, eg. C</dev/sda>");
("list_partitions", (RStringList "partitions", []), 8, [],
- [TestOutputList (
- InitEmpty,
+ [InitEmpty, TestOutputList (
[["list_partitions"]], ["/dev/sda1"]);
- TestOutputList (
- InitEmpty,
- [["sfdisk"];
+ InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
"list the partitions",
"\
@@ -398,12 +406,10 @@ This does not return logical volumes. For that you will need to
call C<guestfs_lvs>.");
("pvs", (RStringList "physvols", []), 9, [],
- [TestOutputList (
- InitEmptyLVM,
+ [InitEmptyLVM, TestOutputList (
[["pvs"]], ["/dev/sda1"]);
- TestOutputList (
- InitNone,
- [["sfdisk"];
+ InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
["pvcreate"; "/dev/sda1"];
["pvcreate"; "/dev/sda2"];
["pvcreate"; "/dev/sda3"];
@@ -419,12 +425,10 @@ PVs (eg. C</dev/sda2>).
See also C<guestfs_pvs_full>.");
("vgs", (RStringList "volgroups", []), 10, [],
- [TestOutputList (
- InitEmptyLVM,
+ [InitEmptyLVM, TestOutputList (
[["vgs"]], ["VG"]);
- TestOutputList (
- InitNone,
- [["sfdisk"];
+ InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
["pvcreate"; "/dev/sda1"];
["pvcreate"; "/dev/sda2"];
["pvcreate"; "/dev/sda3"];
@@ -442,21 +446,19 @@ detected (eg. C<VolGroup00>).
See also C<guestfs_vgs_full>.");
("lvs", (RStringList "logvols", []), 11, [],
- [TestOutputList (
- InitEmptyLVM,
+ [InitEmptyLVM, TestOutputList (
[["lvs"]], ["/dev/VG/LV"]);
- TestOutputList (
- InitNone,
- [["sfdisk"];
+ InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
["pvcreate"; "/dev/sda1"];
["pvcreate"; "/dev/sda2"];
["pvcreate"; "/dev/sda3"];
["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
["vgcreate"; "VG2"; "/dev/sda3"];
- ["lvcreate"; "LV1"; "VG1"; "5000"];
- ["lvcreate"; "LV2"; "VG1"; "5000"];
- ["lvcreate"; "LV3"; "VG2"; "5000"];
- ["lvs"]], ["LV1"; "LV2"; "LV3"])],
+ ["lvcreate"; "LV1"; "VG1"; "50"];
+ ["lvcreate"; "LV2"; "VG1"; "50"];
+ ["lvcreate"; "LV3"; "VG2"; "50"];
+ ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
"list the LVM logical volumes (LVs)",
"\
List all the logical volumes detected. This is the equivalent
@@ -468,8 +470,7 @@ This returns a list of the logical volume device names
See also C<guestfs_lvs_full>.");
("pvs_full", (RPVList "physvols", []), 12, [],
- [TestOutputLength (
- InitEmptyLVM,
+ [InitEmptyLVM, TestOutputLength (
[["pvs"]], 1)],
"list the LVM physical volumes (PVs)",
"\
@@ -477,8 +478,7 @@ List all the physical volumes detected. This is the equivalent
of the L<pvs(8)> command. The \"full\" version includes all fields.");
("vgs_full", (RVGList "volgroups", []), 13, [],
- [TestOutputLength (
- InitEmptyLVM,
+ [InitEmptyLVM, TestOutputLength (
[["pvs"]], 1)],
"list the LVM volume groups (VGs)",
"\
@@ -486,8 +486,7 @@ List all the volumes groups detected. This is the equivalent
of the L<vgs(8)> command. The \"full\" version includes all fields.");
("lvs_full", (RLVList "logvols", []), 14, [],
- [TestOutputLength (
- InitEmptyLVM,
+ [InitEmptyLVM, TestOutputLength (
[["pvs"]], 1)],
"list the LVM logical volumes (LVs)",
"\
@@ -495,12 +494,10 @@ List all the logical volumes detected. This is the equivalent
of the L<lvs(8)> command. The \"full\" version includes all fields.");
("read_lines", (RStringList "lines", [String "path"]), 15, [],
- [TestOutputList (
- InitEmpty,
+ [InitEmpty, TestOutputList (
[["write_file"; "/new"; "line1\r\nline2\nline3"; "0"];
["read_lines"; "/new"]], ["line1"; "line2"; "line3"]);
- TestOutputList (
- InitEmpty,
+ InitEmpty, TestOutputList (
[["write_file"; "/new"; ""; "0"];
["read_lines"; "/new"]], [])],
"read file as lines",
@@ -675,45 +672,38 @@ This is just a shortcut for listing C<guestfs_aug_match>
C<path/*> and sorting the resulting nodes into alphabetical order.");
("rm", (RErr, [String "path"]), 29, [],
- [TestRun (
- InitEmpty,
+ [InitEmpty, TestRun
[["touch"; "/new"];
- ["rm"; "/new"]]);
- TestLastFail (
- InitEmpty,
- [["rm"; "/new"]]);
- TestLastFail (
- InitEmpty,
+ ["rm"; "/new"]];
+ InitEmpty, TestLastFail
+ [["rm"; "/new"]];
+ InitEmpty, TestLastFail
[["mkdir"; "/new"];
- ["rm"; "/new"]])],
+ ["rm"; "/new"]]],
"remove a file",
"\
Remove the single file C<path>.");
("rmdir", (RErr, [String "path"]), 30, [],
- [TestRun (
- InitEmpty,
+ [InitEmpty, TestRun
[["mkdir"; "/new"];
- ["rmdir"; "/new"]]);
- TestLastFail (
- InitEmpty,
- [["rmdir"; "/new"]]);
- TestLastFail (
- InitEmpty,
+ ["rmdir"; "/new"]];
+ InitEmpty, TestLastFail
+ [["rmdir"; "/new"]];
+ InitEmpty, TestLastFail
[["touch"; "/new"];
- ["rmdir"; "/new"]])],
+ ["rmdir"; "/new"]]],
"remove a directory",
"\
Remove the single directory C<path>.");
("rm_rf", (RErr, [String "path"]), 31, [],
- [TestOutputFalse (
- InitEmpty,
+ [InitEmpty, TestOutputFalse
[["mkdir"; "/new"];
["mkdir"; "/new/foo"];
["touch"; "/new/foo/bar"];
["rm_rf"; "/new"];
- ["exists"; "/new"]])],
+ ["exists"; "/new"]]],
"remove a file or directory recursively",
"\
Remove the file or directory C<path>, recursively removing the
@@ -721,27 +711,25 @@ contents if its a directory. This is like the C<rm -rf> shell
command.");
("mkdir", (RErr, [String "path"]), 32, [],
- [TestOutputTrue (
- InitEmpty,
+ [InitEmpty, TestOutputTrue
[["mkdir"; "/new"];
- ["is_dir"; "/new"]])],
+ ["is_dir"; "/new"]];
+ InitEmpty, TestLastFail
+ [["mkdir"; "/new/foo/bar"]]],
"create a directory",
"\
Create a directory named C<path>.");
("mkdir_p", (RErr, [String "path"]), 33, [],
- [TestOutputTrue (
- InitEmpty,
+ [InitEmpty, TestOutputTrue
[["mkdir_p"; "/new/foo/bar"];
- ["is_dir"; "/new/foo/bar"]]);
- TestOutputTrue (
- InitEmpty,
+ ["is_dir"; "/new/foo/bar"]];
+ InitEmpty, TestOutputTrue
[["mkdir_p"; "/new/foo/bar"];
- ["is_dir"; "/new/foo"]]);
- TestOutputTrue (
- InitEmpty,
+ ["is_dir"; "/new/foo"]];
+ InitEmpty, TestOutputTrue
[["mkdir_p"; "/new/foo/bar"];
- ["is_dir"; "/new"]])],
+ ["is_dir"; "/new"]]],
"create a directory and parents",
"\
Create a directory named C<path>, creating any parent directories
@@ -763,6 +751,200 @@ Change the file owner to C<owner> and group to C<group>.
Only numeric uid and gid are supported. If you want to use
names, you will need to locate and parse the password file
yourself (Augeas support makes this relatively easy).");
+
+ ("exists", (RBool "existsflag", [String "path"]), 36, [],
+ [InitEmpty, TestOutputTrue (
+ [["touch"; "/new"];
+ ["exists"; "/new"]]);
+ InitEmpty, TestOutputTrue (
+ [["mkdir"; "/new"];
+ ["exists"; "/new"]])],
+ "test if file or directory exists",
+ "\
+This returns C<true> if and only if there is a file, directory
+(or anything) with the given C<path> name.
+
+See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
+
+ ("is_file", (RBool "fileflag", [String "path"]), 37, [],
+ [InitEmpty, TestOutputTrue (
+ [["touch"; "/new"];
+ ["is_file"; "/new"]]);
+ InitEmpty, TestOutputFalse (
+ [["mkdir"; "/new"];
+ ["is_file"; "/new"]])],
+ "test if file exists",
+ "\
+This returns C<true> if and only if there is a file
+with the given C<path> name. Note that it returns false for
+other objects like directories.
+
+See also C<guestfs_stat>.");
+
+ ("is_dir", (RBool "dirflag", [String "path"]), 38, [],
+ [InitEmpty, TestOutputFalse (
+ [["touch"; "/new"];
+ ["is_dir"; "/new"]]);
+ InitEmpty, TestOutputTrue (
+ [["mkdir"; "/new"];
+ ["is_dir"; "/new"]])],
+ "test if file exists",
+ "\
+This returns C<true> if and only if there is a directory
+with the given C<path> name. Note that it returns false for
+other objects like files.
+
+See also C<guestfs_stat>.");
+
+ ("pvcreate", (RErr, [String "device"]), 39, [],
+ [InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
+ "create an LVM physical volume",
+ "\
+This creates an LVM physical volume on the named C<device>,
+where C<device> should usually be a partition name such
+as C</dev/sda1>.");
+
+ ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
+ [InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
+ ["vgcreate"; "VG2"; "/dev/sda3"];
+ ["vgs"]], ["VG1"; "VG2"])],
+ "create an LVM volume group",
+ "\
+This creates an LVM volume group called C<volgroup>
+from the non-empty list of physical volumes C<physvols>.");
+
+ ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
+ [InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
+ ["vgcreate"; "VG2"; "/dev/sda3"];
+ ["lvcreate"; "LV1"; "VG1"; "50"];
+ ["lvcreate"; "LV2"; "VG1"; "50"];
+ ["lvcreate"; "LV3"; "VG2"; "50"];
+ ["lvcreate"; "LV4"; "VG2"; "50"];
+ ["lvcreate"; "LV5"; "VG2"; "50"];
+ ["lvs"]],
+ ["/dev/VG1/LV1"; "/dev/VG1/LV2";
+ "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
+ "create an LVM volume group",
+ "\
+This creates an LVM volume group called C<logvol>
+on the volume group C<volgroup>, with C<size> megabytes.");
+
+ ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [],
+ [InitNone, TestOutput (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount"; "/dev/sda1"; "/"];
+ ["write_file"; "/new"; "new file contents"; "0"];
+ ["cat"; "/new"]], "new file contents")],
+ "make a filesystem",
+ "\
+This creates a filesystem on C<device> (usually a partition
+of LVM logical volume). The filesystem type is C<fstype>, for
+example C<ext3>.");
+
+ ("sfdisk", (RErr, [String "device";
+ Int "cyls"; Int "heads"; Int "sectors";
+ StringList "lines"]), 43, [DangerWillRobinson],
+ [],
+ "create partitions on a block device",
+ "\
+This is a direct interface to the L<sfdisk(8)> program for creating
+partitions on block devices.
+
+C<device> should be a block device, for example C</dev/sda>.
+
+C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
+and sectors on the device, which are passed directly to sfdisk as
+the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
+of these, then the corresponding parameter is omitted. Usually for
+'large' disks, you can just pass C<0> for these, but for small
+(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
+out the right geometry and you will need to tell it.
+
+C<lines> is a list of lines that we feed to C<sfdisk>. For more
+information refer to the L<sfdisk(8)> manpage.
+
+To create a single partition occupying the whole disk, you would
+pass C<lines> as a single element list, when the single element being
+the string C<,> (comma).");
+
+ ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
+ [InitNone, TestOutput (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount"; "/dev/sda1"; "/"];
+ ["write_file"; "/new"; "new file contents"; "0"];
+ ["cat"; "/new"]], "new file contents")],
+ "Create a file",
+ "\
+This call creates a file called C<path>. The contents of the
+file is the string C<content> (which can contain any 8 bit data),
+with length C<size>.
+
+As a special case, if C<size> is C<0>
+then the length is calculated using C<strlen> (so in this case
+the content cannot contain embedded ASCII NULs).");
+
+ ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
+ [InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount"; "/dev/sda1"; "/"];
+ ["mounts"]], ["/dev/sda1"]);
+ InitNone, TestOutputList (
+ [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount"; "/dev/sda1"; "/"];
+ ["umount"; "/"];
+ ["mounts"]], [])],
+ "unmount a filesystem",
+ "\
+This unmounts the given filesystem. The filesystem may be
+specified either by its mountpoint (path) or the device which
+contains the filesystem.");
+
+ ("mounts", (RStringList "devices", []), 46, [],
+ [InitEmpty, TestOutputList (
+ [["mounts"]], ["/dev/sda1"])],
+ "show mounted filesystems",
+ "\
+This returns the list of currently mounted filesystems. It returns
+the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
+
+Some internal mounts are not shown.");
+
+ ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
+ [InitEmpty, TestOutputList (
+ [["umount_all"];
+ ["mounts"]], [])],
+ "unmount all filesystems",
+ "\
+This unmounts all mounted filesystems.
+
+Some internal mounts are not unmounted by this call.");
+
+ ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
+ [],
+ "remove all LVM LVs, VGs and PVs",
+ "\
+This command removes all LVM logical volumes, volume groups
+and physical volumes.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
@@ -884,6 +1066,17 @@ let rec replace_str s s1 s2 =
s' ^ s2 ^ replace_str s'' s1 s2
)
+let rec string_split sep str =
+ let len = String.length str in
+ let seplen = String.length sep in
+ let i = find str sep in
+ if i = -1 then [str]
+ else (
+ let s' = String.sub str 0 i in
+ let s'' = String.sub str (i+seplen) (len-i-seplen) in
+ s' :: string_split sep s''
+ )
+
let rec find_map f = function
| [] -> raise Not_found
| x :: xs ->
@@ -898,7 +1091,15 @@ let iteri f xs =
in
loop 0 xs
-let name_of_argt = function String n | OptString n | Bool n | Int n -> n
+let mapi f xs =
+ let rec loop i = function
+ | [] -> []
+ | x :: xs -> let r = f i x in r :: loop (i+1) xs
+ in
+ loop 0 xs
+
+let name_of_argt = function
+ | String n | OptString n | StringList n | Bool n | Int n -> n
(* Check function names etc. for consistency. *)
let check_functions () =
@@ -1089,9 +1290,9 @@ I<The caller must call C<guestfs_free_lvm_vg_list> after use>.\n\n"
I<The caller must call C<guestfs_free_lvm_lv_list> after use>.\n\n"
);
if List.mem ProtocolLimitWarning flags then
- pr "Because of the message protocol, there is a transfer limit
-of somewhere between 2MB and 4MB. To transfer large files you should use
-FTP.\n\n";
+ pr "%s\n\n" protocol_limit_warning;
+ if List.mem DangerWillRobinson flags then
+ pr "%s\n\n" danger_will_robinson;
) all_functions_sorted
and generate_structs_pod () =
@@ -1169,6 +1370,7 @@ and generate_xdr () =
function
| String n -> pr " string %s<>;\n" n
| OptString n -> pr " str *%s;\n" n
+ | StringList n -> pr " str %s<>;\n" n
| Bool n -> pr " bool %s;\n" n
| Int n -> pr " int %s;\n" n
) args;
@@ -1427,6 +1629,9 @@ and generate_client_actions () =
pr " args.%s = (char *) %s;\n" n n
| OptString n ->
pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
+ | StringList n ->
+ pr " args.%s.%s_val = (char **) %s;\n" n n n;
+ pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
| Bool n ->
pr " args.%s = %s;\n" n n
| Int n ->
@@ -1556,6 +1761,7 @@ and generate_daemon_actions () =
function
| String n
| OptString n -> pr " const char *%s;\n" n
+ | StringList n -> pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
) args
@@ -1575,6 +1781,10 @@ and generate_daemon_actions () =
function
| String n -> pr " %s = args.%s;\n" n n
| OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
+ | StringList n ->
+ pr " args.%s.%s_val = realloc (args.%s.%s_val, sizeof (char *) * (args.%s.%s_len+1));\n" n n n n n n;
+ pr " args.%s.%s_val[args.%s.%s_len] = NULL;\n" n n n n;
+ pr " %s = args.%s.%s_val;\n" n n n
| Bool n -> pr " %s = args.%s;\n" n n
| Int n -> pr " %s = args.%s;\n" n n
) args;
@@ -1586,8 +1796,8 @@ and generate_daemon_actions () =
pr ";\n";
pr " if (r == %s)\n" error_code;
- pr " /* do_%s has already called reply_with_error, so just return */\n" name;
- pr " return;\n";
+ pr " /* do_%s has already called reply_with_error */\n" name;
+ pr " goto done;\n";
pr "\n";
(match fst style with
@@ -1633,6 +1843,16 @@ and generate_daemon_actions () =
pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
);
+ (* Free the args. *)
+ (match snd style with
+ | [] ->
+ pr "done: ;\n";
+ | _ ->
+ pr "done:\n";
+ pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
+ name
+ );
+
pr "}\n\n";
) daemon_functions;
@@ -1823,20 +2043,459 @@ and generate_daemon_actions () =
and generate_tests () =
generate_header CStyle GPLv2;
- pr "#include <stdio.h>\n";
- pr "#include <stdlib.h>\n";
- pr "#include <string.h>\n";
- pr "\n";
- pr "#include \"guestfs.h\"\n";
+ pr "\
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include \"guestfs.h\"
+
+static guestfs_h *g;
+static int suppress_error = 0;
+
+static void print_error (guestfs_h *g, void *data, const char *msg)
+{
+ if (!suppress_error)
+ fprintf (stderr, \"%%s\\n\", msg);
+}
+
+static void print_strings (char * const * const argv)
+{
+ int argc;
+
+ for (argc = 0; argv[argc] != NULL; ++argc)
+ printf (\"\\t%%s\\n\", argv[argc]);
+}
+
+";
+
+ let test_names =
+ List.map (
+ fun (name, _, _, _, tests, _, _) ->
+ mapi (generate_one_test name) tests
+ ) all_functions in
+ let test_names = List.concat test_names in
+ let nr_tests = List.length test_names in
+
+ pr "\
+int main (int argc, char *argv[])
+{
+ char c = 0;
+ int failed = 0;
+ const char *srcdir;
+ int fd;
+ char buf[256];
+
+ g = guestfs_create ();
+ if (g == NULL) {
+ printf (\"guestfs_create FAILED\\n\");
+ exit (1);
+ }
+
+ guestfs_set_error_handler (g, print_error, NULL);
+
+ srcdir = getenv (\"srcdir\");
+ if (!srcdir) srcdir = \".\";
+ guestfs_set_path (g, srcdir);
+
+ snprintf (buf, sizeof buf, \"%%s/test1.img\", srcdir);
+ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
+ if (fd == -1) {
+ perror (buf);
+ exit (1);
+ }
+ if (lseek (fd, %d, SEEK_SET) == -1) {
+ perror (\"lseek\");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (write (fd, &c, 1) == -1) {
+ perror (\"write\");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (close (fd) == -1) {
+ perror (buf);
+ unlink (buf);
+ exit (1);
+ }
+ if (guestfs_add_drive (g, buf) == -1) {
+ printf (\"guestfs_add_drive %%s FAILED\\n\", buf);
+ exit (1);
+ }
+
+ snprintf (buf, sizeof buf, \"%%s/test2.img\", srcdir);
+ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
+ if (fd == -1) {
+ perror (buf);
+ exit (1);
+ }
+ if (lseek (fd, %d, SEEK_SET) == -1) {
+ perror (\"lseek\");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (write (fd, &c, 1) == -1) {
+ perror (\"write\");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (close (fd) == -1) {
+ perror (buf);
+ unlink (buf);
+ exit (1);
+ }
+ if (guestfs_add_drive (g, buf) == -1) {
+ printf (\"guestfs_add_drive %%s FAILED\\n\", buf);
+ exit (1);
+ }
+
+ snprintf (buf, sizeof buf, \"%%s/test3.img\", srcdir);
+ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
+ if (fd == -1) {
+ perror (buf);
+ exit (1);
+ }
+ if (lseek (fd, %d, SEEK_SET) == -1) {
+ perror (\"lseek\");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (write (fd, &c, 1) == -1) {
+ perror (\"write\");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (close (fd) == -1) {
+ perror (buf);
+ unlink (buf);
+ exit (1);
+ }
+ if (guestfs_add_drive (g, buf) == -1) {
+ printf (\"guestfs_add_drive %%s FAILED\\n\", buf);
+ exit (1);
+ }
+
+ if (guestfs_launch (g) == -1) {
+ printf (\"guestfs_launch FAILED\\n\");
+ exit (1);
+ }
+ if (guestfs_wait_ready (g) == -1) {
+ printf (\"guestfs_wait_ready FAILED\\n\");
+ exit (1);
+ }
+
+" (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024);
+
+ iteri (
+ fun i test_name ->
+ pr " printf (\"%3d/%3d %s\\n\");\n" (i+1) nr_tests test_name;
+ pr " if (%s () == -1) {\n" test_name;
+ pr " printf (\"%s FAILED\\n\");\n" test_name;
+ pr " failed++;\n";
+ pr " }\n";
+ ) test_names;
pr "\n";
+ pr " guestfs_close (g);\n";
+ pr " snprintf (buf, sizeof buf, \"%%s/test1.img\", srcdir);\n";
+ pr " unlink (buf);\n";
+ pr " snprintf (buf, sizeof buf, \"%%s/test2.img\", srcdir);\n";
+ pr " unlink (buf);\n";
+ pr " snprintf (buf, sizeof buf, \"%%s/test3.img\", srcdir);\n";
+ pr " unlink (buf);\n";
+ pr "\n";
+ pr " if (failed > 0) {\n";
+ pr " printf (\"***** %%d / %d tests FAILED *****\\n\", failed);\n"
+ nr_tests;
+ pr " exit (1);\n";
+ pr " }\n";
+ pr "\n";
- pr "int main (int argc, char *argv[])\n";
- pr "{\n";
pr " exit (0);\n";
pr "}\n"
+and generate_one_test name i (init, test) =
+ let test_name = sprintf "test_%s_%d" name i in
+
+ pr "static int %s (void)\n" test_name;
+ pr "{\n";
+
+ (match init with
+ | InitNone ->
+ pr " /* InitNone for %s (%d) */\n" name i;
+ List.iter (generate_test_command_call test_name)
+ [["umount_all"];
+ ["lvm_remove_all"]]
+ | InitEmpty ->
+ pr " /* InitEmpty for %s (%d): create ext2 on /dev/sda1 */\n" name i;
+ List.iter (generate_test_command_call test_name)
+ [["umount_all"];
+ ["lvm_remove_all"];
+ ["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount"; "/dev/sda1"; "/"]]
+ | InitEmptyLVM ->
+ pr " /* InitEmptyLVM for %s (%d): create ext2 on /dev/VG/LV */\n"
+ name i;
+ List.iter (generate_test_command_call test_name)
+ [["umount_all"];
+ ["lvm_remove_all"];
+ ["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV"; "VG"; "8"];
+ ["mkfs"; "ext2"; "/dev/VG/LV"];
+ ["mount"; "/dev/VG/LV"; "/"]]
+ );
+
+ let get_seq_last = function
+ | [] ->
+ failwithf "%s: you cannot use [] (empty list) when expecting a command"
+ test_name
+ | seq ->
+ let seq = List.rev seq in
+ List.rev (List.tl seq), List.hd seq
+ in
+
+ (match test with
+ | TestRun seq ->
+ pr " /* TestRun for %s (%d) */\n" name i;
+ List.iter (generate_test_command_call test_name) seq
+ | TestOutput (seq, expected) ->
+ pr " /* TestOutput for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ let test () =
+ pr " if (strcmp (r, \"%s\") != 0) {\n" (c_quote expected);
+ pr " fprintf (stderr, \"%s: expected \\\"%s\\\" but got \\\"%%s\\\"\\n\", r);\n" test_name (c_quote expected);
+ pr " return -1;\n";
+ pr " }\n"
+ in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call ~test test_name last
+ | TestOutputList (seq, expected) ->
+ pr " /* TestOutputList for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ let test () =
+ iteri (
+ fun i str ->
+ pr " if (!r[%d]) {\n" i;
+ pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
+ pr " print_strings (r);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " if (strcmp (r[%d], \"%s\") != 0) {\n" i (c_quote str);
+ pr " fprintf (stderr, \"%s: expected \\\"%s\\\" but got \\\"%%s\\\"\\n\", r[%d]);\n" test_name (c_quote str) i;
+ pr " return -1;\n";
+ pr " }\n"
+ ) expected;
+ pr " if (r[%d] != NULL) {\n" (List.length expected);
+ pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
+ test_name;
+ pr " print_strings (r);\n";
+ pr " return -1;\n";
+ pr " }\n"
+ in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call ~test test_name last
+ | TestOutputInt (seq, expected) ->
+ pr " /* TestOutputInt for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ let test () =
+ pr " if (r != %d) {\n" expected;
+ pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\", r);\n"
+ test_name expected;
+ pr " return -1;\n";
+ pr " }\n"
+ in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call ~test test_name last
+ | TestOutputTrue seq ->
+ pr " /* TestOutputTrue for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ let test () =
+ pr " if (!r) {\n";
+ pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
+ test_name;
+ pr " return -1;\n";
+ pr " }\n"
+ in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call ~test test_name last
+ | TestOutputFalse seq ->
+ pr " /* TestOutputFalse for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ let test () =
+ pr " if (r) {\n";
+ pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
+ test_name;
+ pr " return -1;\n";
+ pr " }\n"
+ in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call ~test test_name last
+ | TestOutputLength (seq, expected) ->
+ pr " /* TestOutputLength for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ let test () =
+ pr " int j;\n";
+ pr " for (j = 0; j < %d; ++j)\n" expected;
+ pr " if (r[j] == NULL) {\n";
+ pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
+ test_name;
+ pr " print_strings (r);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " if (r[j] != NULL) {\n";
+ pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
+ test_name;
+ pr " print_strings (r);\n";
+ pr " return -1;\n";
+ pr " }\n"
+ in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call ~test test_name last
+ | TestLastFail seq ->
+ pr " /* TestLastFail for %s (%d) */\n" name i;
+ let seq, last = get_seq_last seq in
+ List.iter (generate_test_command_call test_name) seq;
+ generate_test_command_call test_name ~expect_error:true last
+ );
+
+ pr " return 0;\n";
+ pr "}\n";
+ pr "\n";
+ test_name
+
+(* Generate the code to run a command, leaving the result in 'r'.
+ * If you expect to get an error then you should set expect_error:true.
+ *)
+and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
+ match cmd with
+ | [] -> assert false
+ | name :: args ->
+ (* Look up the command to find out what args/ret it has. *)
+ let style =
+ try
+ let _, style, _, _, _, _, _ =
+ List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
+ style
+ with Not_found ->
+ failwithf "%s: in test, command %s was not found" test_name name in
+
+ if List.length (snd style) <> List.length args then
+ failwithf "%s: in test, wrong number of args given to %s"
+ test_name name;
+
+ pr " {\n";
+
+ List.iter (
+ function
+ | String _, _
+ | OptString _, _
+ | Int _, _
+ | Bool _, _ -> ()
+ | StringList n, arg ->
+ pr " char *%s[] = {\n" n;
+ let strs = string_split " " arg in
+ List.iter (
+ fun str -> pr " \"%s\",\n" (c_quote str)
+ ) strs;
+ pr " NULL\n";
+ pr " };\n";
+ ) (List.combine (snd style) args);
+
+ let error_code =
+ match fst style with
+ | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
+ | RConstString _ -> pr " const char *r;\n"; "NULL"
+ | RString _ -> pr " char *r;\n"; "NULL"
+ | RStringList _ ->
+ pr " char **r;\n";
+ pr " int i;\n";
+ "NULL"
+ | RIntBool _ ->
+ pr " struct guestfs_int_bool *r;\n";
+ "NULL"
+ | RPVList _ ->
+ pr " struct guestfs_lvm_pv_list *r;\n";
+ "NULL"
+ | RVGList _ ->
+ pr " struct guestfs_lvm_vg_list *r;\n";
+ "NULL"
+ | RLVList _ ->
+ pr " struct guestfs_lvm_lv_list *r;\n";
+ "NULL" in
+
+ pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
+ pr " r = guestfs_%s (g" name;
+
+ (* Generate the parameters. *)
+ List.iter (
+ function
+ | String _, arg -> pr ", \"%s\"" (c_quote arg)
+ | OptString _, arg ->
+ if arg = "NULL" then pr ", NULL" else pr ", \"%s\"" (c_quote arg)
+ | StringList n, _ ->
+ pr ", %s" n
+ | Int _, arg ->
+ let i =
+ try int_of_string arg
+ with Failure "int_of_string" ->
+ failwithf "%s: expecting an int, but got '%s'" test_name arg in
+ pr ", %d" i
+ | Bool _, arg ->
+ let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
+ ) (List.combine (snd style) args);
+
+ pr ");\n";
+ if not expect_error then
+ pr " if (r == %s)\n" error_code
+ else
+ pr " if (r != %s)\n" error_code;
+ pr " return -1;\n";
+
+ (* Insert the test code. *)
+ (match test with
+ | None -> ()
+ | Some f -> f ()
+ );
+
+ (match fst style with
+ | RErr | RInt _ | RBool _ | RConstString _ -> ()
+ | RString _ -> pr " free (r);\n"
+ | RStringList _ ->
+ pr " for (i = 0; r[i] != NULL; ++i)\n";
+ pr " free (r[i]);\n";
+ pr " free (r);\n"
+ | RIntBool _ ->
+ pr " guestfs_free_int_bool (r);\n"
+ | RPVList _ ->
+ pr " guestfs_free_lvm_pv_list (r);\n"
+ | RVGList _ ->
+ pr " guestfs_free_lvm_vg_list (r);\n"
+ | RLVList _ ->
+ pr " guestfs_free_lvm_lv_list (r);\n"
+ );
+
+ pr " }\n"
+
+and c_quote str =
+ let str = replace_str str "\r" "\\r" in
+ let str = replace_str str "\n" "\\n" in
+ let str = replace_str str "\t" "\\t" in
+ str
+
(* Generate a lot of different functions for guestfish. *)
and generate_fish_cmds () =
generate_header CStyle GPLv2;
@@ -1893,11 +2552,19 @@ and generate_fish_cmds () =
let warnings =
if List.mem ProtocolLimitWarning flags then
- "\n\nBecause of the message protocol, there is a transfer limit
-of somewhere between 2MB and 4MB. To transfer large files you should use
-FTP."
+ ("\n\n" ^ protocol_limit_warning)
else "" in
+ (* For DangerWillRobinson commands, we should probably have
+ * guestfish prompt before allowing you to use them (especially
+ * in interactive mode). XXX
+ *)
+ let warnings =
+ warnings ^
+ if List.mem DangerWillRobinson flags then
+ ("\n\n" ^ danger_will_robinson)
+ else "" in
+
let describe_alias =
if name <> alias then
sprintf "\n\nYou can use '%s' as an alias for this command." alias
@@ -1977,8 +2644,9 @@ FTP."
);
List.iter (
function
- | String n -> pr " const char *%s;\n" n
+ | String n
| OptString n -> pr " const char *%s;\n" n
+ | StringList n -> pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
) (snd style);
@@ -1998,6 +2666,8 @@ FTP."
| OptString name ->
pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
name i i
+ | StringList name ->
+ pr " %s = parse_string_list (argv[%d]);\n" name i
| Bool name ->
pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
| Int name ->
@@ -2115,12 +2785,19 @@ and generate_fish_actions_pod () =
function
| String n -> pr " %s" n
| OptString n -> pr " %s" n
+ | StringList n -> pr " %s,..." n
| Bool _ -> pr " true|false"
| Int n -> pr " %s" n
) (snd style);
pr "\n";
pr "\n";
- pr "%s\n\n" longdesc
+ pr "%s\n\n" longdesc;
+
+ if List.mem ProtocolLimitWarning flags then
+ pr "%s\n\n" protocol_limit_warning;
+
+ if List.mem DangerWillRobinson flags then
+ pr "%s\n\n" danger_will_robinson
) all_functions_sorted
(* Generate a C function prototype. *)
@@ -2169,6 +2846,7 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
function
| String n -> next (); pr "const char *%s" n
| OptString n -> next (); pr "const char *%s" n
+ | StringList n -> next (); pr "char * const* const %s" n
| Bool n -> next (); pr "int %s" n
| Int n -> next (); pr "int %s" n
) (snd style);
@@ -2190,9 +2868,10 @@ and generate_call_args ?handle style =
if !comma then pr ", ";
comma := true;
match arg with
- | String n -> pr "%s" n
- | OptString n -> pr "%s" n
- | Bool n -> pr "%s" n
+ | String n
+ | OptString n
+ | StringList n
+ | Bool n
| Int n -> pr "%s" n
) (snd style);
pr ")"
@@ -2339,18 +3018,23 @@ and generate_ocaml_c () =
List.iter (
fun (name, style, _, _, _, _, _) ->
+ let params =
+ "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
+
pr "CAMLprim value\n";
- pr "ocaml_guestfs_%s (value gv" name;
- List.iter (
- fun arg -> pr ", value %sv" (name_of_argt arg)
- ) (snd style);
+ pr "ocaml_guestfs_%s (value %s" name (List.hd params);
+ List.iter (pr ", value %s") (List.tl params);
pr ")\n";
pr "{\n";
- pr " CAMLparam%d (gv" (1 + (List.length (snd style)));
- List.iter (
- fun arg -> pr ", %sv" (name_of_argt arg)
- ) (snd style);
- pr ");\n";
+
+ (match params with
+ | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
+ pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
+ pr " CAMLxparam%d (%s);\n"
+ (List.length rest) (String.concat ", " rest)
+ | ps ->
+ pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
+ );
pr " CAMLlocal1 (rv);\n";
pr "\n";
@@ -2367,6 +3051,8 @@ and generate_ocaml_c () =
pr " const char *%s =\n" n;
pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
n n
+ | StringList n ->
+ pr " char **%s = ocaml_guestfs_strings_val (%sv);\n" n n
| Bool n ->
pr " int %s = Bool_val (%sv);\n" n n
| Int n ->
@@ -2402,6 +3088,14 @@ and generate_ocaml_c () =
generate_call_args ~handle:"g" style;
pr ";\n";
pr " caml_leave_blocking_section ();\n";
+
+ List.iter (
+ function
+ | StringList n ->
+ pr " ocaml_guestfs_free_strings (%s);\n" n;
+ | String _ | OptString _ | Bool _ | Int _ -> ()
+ ) (snd style);
+
pr " if (r == %s)\n" error_code;
pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
pr "\n";
@@ -2436,7 +3130,18 @@ and generate_ocaml_c () =
pr " CAMLreturn (rv);\n";
pr "}\n";
- pr "\n"
+ pr "\n";
+
+ if List.length params > 5 then (
+ pr "CAMLprim value\n";
+ pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
+ pr "{\n";
+ pr " return ocaml_guestfs_%s (argv[0]" name;
+ iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
+ pr ");\n";
+ pr "}\n";
+ pr "\n"
+ )
) all_functions
and generate_ocaml_lvm_structure_decls () =
@@ -2462,6 +3167,7 @@ and generate_ocaml_prototype ?(is_external = false) name style =
function
| String _ -> pr "string -> "
| OptString _ -> pr "string option -> "
+ | StringList _ -> pr "string array -> "
| Bool _ -> pr "bool -> "
| Int _ -> pr "int -> "
) (snd style);
@@ -2477,7 +3183,12 @@ and generate_ocaml_prototype ?(is_external = false) name style =
| RVGList _ -> pr "lvm_vg array"
| RLVList _ -> pr "lvm_lv array"
);
- if is_external then pr " = \"ocaml_guestfs_%s\"" name;
+ if is_external then (
+ pr " = ";
+ if List.length (snd style) + 1 > 5 then
+ pr "\"ocaml_guestfs_%s_byte\" " name;
+ pr "\"ocaml_guestfs_%s\"" name
+ );
pr "\n"
(* Generate Perl xs code, a sort of crazy variation of C with macros. *)
@@ -2539,6 +3250,35 @@ error_handler (guestfs_h *g,
last_error = strdup (msg);
}
+/* http://www.perlmonks.org/?node_id=680842 */
+static char **
+XS_unpack_charPtrPtr (SV *arg) {
+ char **ret;
+ AV *av;
+ I32 i;
+
+ if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV) {
+ croak (\"array reference expected\");
+ }
+
+ av = (AV *)SvRV (arg);
+ ret = (char **)malloc (av_len (av) + 1 + 1);
+
+ for (i = 0; i <= av_len (av); i++) {
+ SV **elem = av_fetch (av, i, 0);
+
+ if (!elem || !*elem) {
+ croak (\"missing element in list\");
+ }
+
+ ret[i] = SvPV_nolen (*elem);
+ }
+
+ ret[i + 1] = NULL;
+
+ return ret;
+}
+
MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
guestfs_h *
@@ -2581,17 +3321,32 @@ DESTROY (g)
function
| String n -> pr " char *%s;\n" n
| OptString n -> pr " char *%s;\n" n
+ | StringList n -> pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
) (snd style);
+
+ let do_cleanups () =
+ List.iter (
+ function
+ | String _
+ | OptString _
+ | Bool _
+ | Int _ -> ()
+ | StringList n -> pr " free (%s);\n" n
+ ) (snd style)
+ in
+
(* Code. *)
(match fst style with
| RErr ->
pr " PPCODE:\n";
pr " if (guestfs_%s " name;
generate_call_args ~handle:"g" style;
- pr " == -1)\n";
- pr " croak (\"%s: %%s\", last_error);\n" name
+ pr " == -1) {\n";
+ do_cleanups ();
+ pr " croak (\"%s: %%s\", last_error);\n" name;
+ pr " }\n"
| RInt n
| RBool n ->
pr "PREINIT:\n";
@@ -2600,8 +3355,10 @@ DESTROY (g)
pr " %s = guestfs_%s " n name;
generate_call_args ~handle:"g" style;
pr ";\n";
- pr " if (%s == -1)\n" n;
+ pr " if (%s == -1) {\n" n;
+ do_cleanups ();
pr " croak (\"%s: %%s\", last_error);\n" name;
+ pr " }\n";
pr " RETVAL = newSViv (%s);\n" n;
pr " OUTPUT:\n";
pr " RETVAL\n"
@@ -2612,8 +3369,10 @@ DESTROY (g)
pr " %s = guestfs_%s " n name;
generate_call_args ~handle:"g" style;
pr ";\n";
- pr " if (%s == NULL)\n" n;
+ pr " if (%s == NULL) {\n" n;
+ do_cleanups ();
pr " croak (\"%s: %%s\", last_error);\n" name;
+ pr " }\n";
pr " RETVAL = newSVpv (%s, 0);\n" n;
pr " OUTPUT:\n";
pr " RETVAL\n"
@@ -2624,8 +3383,10 @@ DESTROY (g)
pr " %s = guestfs_%s " n name;
generate_call_args ~handle:"g" style;
pr ";\n";
- pr " if (%s == NULL)\n" n;
+ pr " if (%s == NULL) {\n" n;
+ do_cleanups ();
pr " croak (\"%s: %%s\", last_error);\n" name;
+ pr " }\n";
pr " RETVAL = newSVpv (%s, 0);\n" n;
pr " free (%s);\n" n;
pr " OUTPUT:\n";
@@ -2638,8 +3399,10 @@ DESTROY (g)
pr " %s = guestfs_%s " n name;
generate_call_args ~handle:"g" style;
pr ";\n";
- pr " if (%s == NULL)\n" n;
+ pr " if (%s == NULL) {\n" n;
+ do_cleanups ();
pr " croak (\"%s: %%s\", last_error);\n" name;
+ pr " }\n";
pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
pr " EXTEND (SP, n);\n";
pr " for (i = 0; i < n; ++i) {\n";
@@ -2654,8 +3417,10 @@ DESTROY (g)
pr " r = guestfs_%s " name;
generate_call_args ~handle:"g" style;
pr ";\n";
- pr " if (r == NULL)\n";
+ pr " if (r == NULL) {\n";
+ do_cleanups ();
pr " croak (\"%s: %%s\", last_error);\n" name;
+ pr " }\n";
pr " EXTEND (SP, 2);\n";
pr " PUSHs (sv_2mortal (newSViv (r->i)));\n";
pr " PUSHs (sv_2mortal (newSViv (r->b)));\n";
@@ -2667,6 +3432,9 @@ DESTROY (g)
| RLVList n ->
generate_perl_lvm_code "lv" lv_cols name style n;
);
+
+ do_cleanups ();
+
pr "\n"
) all_functions
@@ -2797,9 +3565,9 @@ sub new {
pr "\n\n";
pr "%s\n\n" longdesc;
if List.mem ProtocolLimitWarning flags then
- pr "Because of the message protocol, there is a transfer limit
-of somewhere between 2MB and 4MB. To transfer large files you should use
-FTP.\n\n";
+ pr "%s\n\n" protocol_limit_warning;
+ if List.mem DangerWillRobinson flags then
+ pr "%s\n\n" danger_will_robinson
) all_functions_sorted;
(* End of file. *)
@@ -2844,7 +3612,11 @@ and generate_perl_prototype name style =
fun arg ->
if !comma then pr ", ";
comma := true;
- pr "%s" (name_of_argt arg)
+ match arg with
+ | String n | OptString n | Bool n | Int n ->
+ pr "$%s" n
+ | StringList n ->
+ pr "\\@%s" n
) (snd style);
pr ");"
diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c
index 25892cd0..669ca767 100644
--- a/src/guestfs-actions.c
+++ b/src/guestfs-actions.c
@@ -2540,3 +2540,934 @@ int guestfs_chown (guestfs_h *g,
return 0;
}
+struct exists_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_exists_ret ret;
+};
+
+static void exists_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct exists_rv *rv = (struct exists_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_exists: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_exists: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_exists_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_exists: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_exists (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_exists_args args;
+ struct exists_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_exists called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.path = (char *) path;
+ serial = dispatch (g, GUESTFS_PROC_EXISTS,
+ (xdrproc_t) xdr_guestfs_exists_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = exists_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_exists failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_EXISTS, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return rv.ret.existsflag;
+}
+
+struct is_file_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_is_file_ret ret;
+};
+
+static void is_file_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct is_file_rv *rv = (struct is_file_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_is_file: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_is_file: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_is_file_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_is_file: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_is_file (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_is_file_args args;
+ struct is_file_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_is_file called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.path = (char *) path;
+ serial = dispatch (g, GUESTFS_PROC_IS_FILE,
+ (xdrproc_t) xdr_guestfs_is_file_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = is_file_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_is_file failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_IS_FILE, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return rv.ret.fileflag;
+}
+
+struct is_dir_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_is_dir_ret ret;
+};
+
+static void is_dir_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct is_dir_rv *rv = (struct is_dir_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_is_dir: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_is_dir: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_is_dir_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_is_dir: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_is_dir (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_is_dir_args args;
+ struct is_dir_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_is_dir called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.path = (char *) path;
+ serial = dispatch (g, GUESTFS_PROC_IS_DIR,
+ (xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = is_dir_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_is_dir failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_IS_DIR, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return rv.ret.dirflag;
+}
+
+struct pvcreate_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void pvcreate_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct pvcreate_rv *rv = (struct pvcreate_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_pvcreate: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_pvcreate: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_pvcreate (guestfs_h *g,
+ const char *device)
+{
+ struct guestfs_pvcreate_args args;
+ struct pvcreate_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_pvcreate called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.device = (char *) device;
+ serial = dispatch (g, GUESTFS_PROC_PVCREATE,
+ (xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = pvcreate_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_pvcreate failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_PVCREATE, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct vgcreate_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void vgcreate_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct vgcreate_rv *rv = (struct vgcreate_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_vgcreate: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_vgcreate: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_vgcreate (guestfs_h *g,
+ const char *volgroup,
+ char * const* const physvols)
+{
+ struct guestfs_vgcreate_args args;
+ struct vgcreate_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_vgcreate called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.volgroup = (char *) volgroup;
+ args.physvols.physvols_val = (char **) physvols;
+ for (args.physvols.physvols_len = 0; physvols[args.physvols.physvols_len]; args.physvols.physvols_len++) ;
+ serial = dispatch (g, GUESTFS_PROC_VGCREATE,
+ (xdrproc_t) xdr_guestfs_vgcreate_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = vgcreate_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_vgcreate failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_VGCREATE, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct lvcreate_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void lvcreate_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct lvcreate_rv *rv = (struct lvcreate_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_lvcreate: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_lvcreate: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_lvcreate (guestfs_h *g,
+ const char *logvol,
+ const char *volgroup,
+ int mbytes)
+{
+ struct guestfs_lvcreate_args args;
+ struct lvcreate_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_lvcreate called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.logvol = (char *) logvol;
+ args.volgroup = (char *) volgroup;
+ args.mbytes = mbytes;
+ serial = dispatch (g, GUESTFS_PROC_LVCREATE,
+ (xdrproc_t) xdr_guestfs_lvcreate_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = lvcreate_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_lvcreate failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVCREATE, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct mkfs_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void mkfs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct mkfs_rv *rv = (struct mkfs_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_mkfs: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_mkfs: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_mkfs (guestfs_h *g,
+ const char *fstype,
+ const char *device)
+{
+ struct guestfs_mkfs_args args;
+ struct mkfs_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_mkfs called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.fstype = (char *) fstype;
+ args.device = (char *) device;
+ serial = dispatch (g, GUESTFS_PROC_MKFS,
+ (xdrproc_t) xdr_guestfs_mkfs_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = mkfs_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_mkfs failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MKFS, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct sfdisk_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void sfdisk_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct sfdisk_rv *rv = (struct sfdisk_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_sfdisk: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_sfdisk: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_sfdisk (guestfs_h *g,
+ const char *device,
+ int cyls,
+ int heads,
+ int sectors,
+ char * const* const lines)
+{
+ struct guestfs_sfdisk_args args;
+ struct sfdisk_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_sfdisk called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.device = (char *) device;
+ args.cyls = cyls;
+ args.heads = heads;
+ args.sectors = sectors;
+ args.lines.lines_val = (char **) lines;
+ for (args.lines.lines_len = 0; lines[args.lines.lines_len]; args.lines.lines_len++) ;
+ serial = dispatch (g, GUESTFS_PROC_SFDISK,
+ (xdrproc_t) xdr_guestfs_sfdisk_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = sfdisk_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_sfdisk failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_SFDISK, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct write_file_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void write_file_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct write_file_rv *rv = (struct write_file_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_write_file: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_write_file: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_write_file (guestfs_h *g,
+ const char *path,
+ const char *content,
+ int size)
+{
+ struct guestfs_write_file_args args;
+ struct write_file_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_write_file called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.path = (char *) path;
+ args.content = (char *) content;
+ args.size = size;
+ serial = dispatch (g, GUESTFS_PROC_WRITE_FILE,
+ (xdrproc_t) xdr_guestfs_write_file_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = write_file_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_write_file failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct umount_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void umount_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct umount_rv *rv = (struct umount_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_umount: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_umount: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_umount (guestfs_h *g,
+ const char *pathordevice)
+{
+ struct guestfs_umount_args args;
+ struct umount_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_umount called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.pathordevice = (char *) pathordevice;
+ serial = dispatch (g, GUESTFS_PROC_UMOUNT,
+ (xdrproc_t) xdr_guestfs_umount_args, (char *) &args);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = umount_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_umount failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_UMOUNT, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct mounts_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_mounts_ret ret;
+};
+
+static void mounts_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct mounts_rv *rv = (struct mounts_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_mounts: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_mounts: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_mounts_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_mounts: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+char **guestfs_mounts (guestfs_h *g)
+{
+ struct mounts_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_mounts called from the wrong state, %d != READY",
+ g->state);
+ return NULL;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ serial = dispatch (g, GUESTFS_PROC_MOUNTS, NULL, NULL);
+ if (serial == -1)
+ return NULL;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = mounts_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_mounts failed, see earlier error messages");
+ return NULL;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MOUNTS, serial) == -1)
+ return NULL;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return NULL;
+ }
+
+ /* caller will free this, but we need to add a NULL entry */
+ rv.ret.devices.devices_val = safe_realloc (g, rv.ret.devices.devices_val,
+ sizeof (char *) * (rv.ret.devices.devices_len + 1));
+ rv.ret.devices.devices_val[rv.ret.devices.devices_len] = NULL;
+ return rv.ret.devices.devices_val;
+}
+
+struct umount_all_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void umount_all_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct umount_all_rv *rv = (struct umount_all_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_umount_all: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_umount_all: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_umount_all (guestfs_h *g)
+{
+ struct umount_all_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_umount_all called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ serial = dispatch (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = umount_all_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_umount_all failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct lvm_remove_all_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void lvm_remove_all_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct lvm_remove_all_rv *rv = (struct lvm_remove_all_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_lvm_remove_all: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_lvm_remove_all: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+int guestfs_lvm_remove_all (guestfs_h *g)
+{
+ struct lvm_remove_all_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_lvm_remove_all called from the wrong state, %d != READY",
+ g->state);
+ return -1;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ serial = dispatch (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
+ if (serial == -1)
+ return -1;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = lvm_remove_all_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_lvm_remove_all failed, see earlier error messages");
+ return -1;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1)
+ return -1;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h
index 06f1485b..d40ef150 100644
--- a/src/guestfs-actions.h
+++ b/src/guestfs-actions.h
@@ -66,3 +66,16 @@ extern int guestfs_mkdir (guestfs_h *handle, const char *path);
extern int guestfs_mkdir_p (guestfs_h *handle, const char *path);
extern int guestfs_chmod (guestfs_h *handle, int mode, const char *path);
extern int guestfs_chown (guestfs_h *handle, int owner, int group, const char *path);
+extern int guestfs_exists (guestfs_h *handle, const char *path);
+extern int guestfs_is_file (guestfs_h *handle, const char *path);
+extern int guestfs_is_dir (guestfs_h *handle, const char *path);
+extern int guestfs_pvcreate (guestfs_h *handle, const char *device);
+extern int guestfs_vgcreate (guestfs_h *handle, const char *volgroup, char * const* const physvols);
+extern int guestfs_lvcreate (guestfs_h *handle, const char *logvol, const char *volgroup, int mbytes);
+extern int guestfs_mkfs (guestfs_h *handle, const char *fstype, const char *device);
+extern int guestfs_sfdisk (guestfs_h *handle, const char *device, int cyls, int heads, int sectors, char * const* const lines);
+extern int guestfs_write_file (guestfs_h *handle, const char *path, const char *content, int size);
+extern int guestfs_umount (guestfs_h *handle, const char *pathordevice);
+extern char **guestfs_mounts (guestfs_h *handle);
+extern int guestfs_umount_all (guestfs_h *handle);
+extern int guestfs_lvm_remove_all (guestfs_h *handle);
diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c
index 781c2daf..8e868126 100644
--- a/src/guestfs_protocol.c
+++ b/src/guestfs_protocol.c
@@ -619,6 +619,214 @@ xdr_guestfs_chown_args (XDR *xdrs, guestfs_chown_args *objp)
}
bool_t
+xdr_guestfs_exists_args (XDR *xdrs, guestfs_exists_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_exists_ret (XDR *xdrs, guestfs_exists_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_bool (xdrs, &objp->existsflag))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_is_file_args (XDR *xdrs, guestfs_is_file_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_is_file_ret (XDR *xdrs, guestfs_is_file_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_bool (xdrs, &objp->fileflag))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_is_dir_args (XDR *xdrs, guestfs_is_dir_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_is_dir_ret (XDR *xdrs, guestfs_is_dir_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_bool (xdrs, &objp->dirflag))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_pvcreate_args (XDR *xdrs, guestfs_pvcreate_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->device, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_vgcreate_args (XDR *xdrs, guestfs_vgcreate_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->volgroup, ~0))
+ return FALSE;
+ if (!xdr_array (xdrs, (char **)&objp->physvols.physvols_val, (u_int *) &objp->physvols.physvols_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvcreate_args (XDR *xdrs, guestfs_lvcreate_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->logvol, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->volgroup, ~0))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->mbytes))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_mkfs_args (XDR *xdrs, guestfs_mkfs_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->fstype, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->device, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_args (XDR *xdrs, guestfs_sfdisk_args *objp)
+{
+ register int32_t *buf;
+
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!xdr_string (xdrs, &objp->device, ~0))
+ return FALSE;
+ buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int (xdrs, &objp->cyls))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->heads))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->sectors))
+ return FALSE;
+
+ } else {
+ IXDR_PUT_LONG(buf, objp->cyls);
+ IXDR_PUT_LONG(buf, objp->heads);
+ IXDR_PUT_LONG(buf, objp->sectors);
+ }
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+ } else if (xdrs->x_op == XDR_DECODE) {
+ if (!xdr_string (xdrs, &objp->device, ~0))
+ return FALSE;
+ buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int (xdrs, &objp->cyls))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->heads))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->sectors))
+ return FALSE;
+
+ } else {
+ objp->cyls = IXDR_GET_LONG(buf);
+ objp->heads = IXDR_GET_LONG(buf);
+ objp->sectors = IXDR_GET_LONG(buf);
+ }
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+ }
+
+ if (!xdr_string (xdrs, &objp->device, ~0))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->cyls))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->heads))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->sectors))
+ return FALSE;
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_write_file_args (XDR *xdrs, guestfs_write_file_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->content, ~0))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->size))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_umount_args (XDR *xdrs, guestfs_umount_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->pathordevice, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_mounts_ret (XDR *xdrs, guestfs_mounts_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->devices.devices_val, (u_int *) &objp->devices.devices_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp)
{
register int32_t *buf;
diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h
index 508bc4e3..fedd0074 100644
--- a/src/guestfs_protocol.h
+++ b/src/guestfs_protocol.h
@@ -337,6 +337,95 @@ struct guestfs_chown_args {
};
typedef struct guestfs_chown_args guestfs_chown_args;
+struct guestfs_exists_args {
+ char *path;
+};
+typedef struct guestfs_exists_args guestfs_exists_args;
+
+struct guestfs_exists_ret {
+ bool_t existsflag;
+};
+typedef struct guestfs_exists_ret guestfs_exists_ret;
+
+struct guestfs_is_file_args {
+ char *path;
+};
+typedef struct guestfs_is_file_args guestfs_is_file_args;
+
+struct guestfs_is_file_ret {
+ bool_t fileflag;
+};
+typedef struct guestfs_is_file_ret guestfs_is_file_ret;
+
+struct guestfs_is_dir_args {
+ char *path;
+};
+typedef struct guestfs_is_dir_args guestfs_is_dir_args;
+
+struct guestfs_is_dir_ret {
+ bool_t dirflag;
+};
+typedef struct guestfs_is_dir_ret guestfs_is_dir_ret;
+
+struct guestfs_pvcreate_args {
+ char *device;
+};
+typedef struct guestfs_pvcreate_args guestfs_pvcreate_args;
+
+struct guestfs_vgcreate_args {
+ char *volgroup;
+ struct {
+ u_int physvols_len;
+ str *physvols_val;
+ } physvols;
+};
+typedef struct guestfs_vgcreate_args guestfs_vgcreate_args;
+
+struct guestfs_lvcreate_args {
+ char *logvol;
+ char *volgroup;
+ int mbytes;
+};
+typedef struct guestfs_lvcreate_args guestfs_lvcreate_args;
+
+struct guestfs_mkfs_args {
+ char *fstype;
+ char *device;
+};
+typedef struct guestfs_mkfs_args guestfs_mkfs_args;
+
+struct guestfs_sfdisk_args {
+ char *device;
+ int cyls;
+ int heads;
+ int sectors;
+ struct {
+ u_int lines_len;
+ str *lines_val;
+ } lines;
+};
+typedef struct guestfs_sfdisk_args guestfs_sfdisk_args;
+
+struct guestfs_write_file_args {
+ char *path;
+ char *content;
+ int size;
+};
+typedef struct guestfs_write_file_args guestfs_write_file_args;
+
+struct guestfs_umount_args {
+ char *pathordevice;
+};
+typedef struct guestfs_umount_args guestfs_umount_args;
+
+struct guestfs_mounts_ret {
+ struct {
+ u_int devices_len;
+ str *devices_val;
+ } devices;
+};
+typedef struct guestfs_mounts_ret guestfs_mounts_ret;
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
@@ -373,7 +462,20 @@ enum guestfs_procedure {
GUESTFS_PROC_MKDIR_P = 33,
GUESTFS_PROC_CHMOD = 34,
GUESTFS_PROC_CHOWN = 35,
- GUESTFS_PROC_dummy = 35 + 1,
+ GUESTFS_PROC_EXISTS = 36,
+ GUESTFS_PROC_IS_FILE = 37,
+ GUESTFS_PROC_IS_DIR = 38,
+ GUESTFS_PROC_PVCREATE = 39,
+ GUESTFS_PROC_VGCREATE = 40,
+ GUESTFS_PROC_LVCREATE = 41,
+ GUESTFS_PROC_MKFS = 42,
+ GUESTFS_PROC_SFDISK = 43,
+ GUESTFS_PROC_WRITE_FILE = 44,
+ GUESTFS_PROC_UMOUNT = 45,
+ GUESTFS_PROC_MOUNTS = 46,
+ GUESTFS_PROC_UMOUNT_ALL = 47,
+ GUESTFS_PROC_LVM_REMOVE_ALL = 48,
+ GUESTFS_PROC_dummy = 48 + 1,
};
typedef enum guestfs_procedure guestfs_procedure;
#define GUESTFS_MESSAGE_MAX 4194304
@@ -459,6 +561,20 @@ extern bool_t xdr_guestfs_mkdir_args (XDR *, guestfs_mkdir_args*);
extern bool_t xdr_guestfs_mkdir_p_args (XDR *, guestfs_mkdir_p_args*);
extern bool_t xdr_guestfs_chmod_args (XDR *, guestfs_chmod_args*);
extern bool_t xdr_guestfs_chown_args (XDR *, guestfs_chown_args*);
+extern bool_t xdr_guestfs_exists_args (XDR *, guestfs_exists_args*);
+extern bool_t xdr_guestfs_exists_ret (XDR *, guestfs_exists_ret*);
+extern bool_t xdr_guestfs_is_file_args (XDR *, guestfs_is_file_args*);
+extern bool_t xdr_guestfs_is_file_ret (XDR *, guestfs_is_file_ret*);
+extern bool_t xdr_guestfs_is_dir_args (XDR *, guestfs_is_dir_args*);
+extern bool_t xdr_guestfs_is_dir_ret (XDR *, guestfs_is_dir_ret*);
+extern bool_t xdr_guestfs_pvcreate_args (XDR *, guestfs_pvcreate_args*);
+extern bool_t xdr_guestfs_vgcreate_args (XDR *, guestfs_vgcreate_args*);
+extern bool_t xdr_guestfs_lvcreate_args (XDR *, guestfs_lvcreate_args*);
+extern bool_t xdr_guestfs_mkfs_args (XDR *, guestfs_mkfs_args*);
+extern bool_t xdr_guestfs_sfdisk_args (XDR *, guestfs_sfdisk_args*);
+extern bool_t xdr_guestfs_write_file_args (XDR *, guestfs_write_file_args*);
+extern bool_t xdr_guestfs_umount_args (XDR *, guestfs_umount_args*);
+extern bool_t xdr_guestfs_mounts_ret (XDR *, guestfs_mounts_ret*);
extern bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*);
extern bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*);
extern bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*);
@@ -514,6 +630,20 @@ extern bool_t xdr_guestfs_mkdir_args ();
extern bool_t xdr_guestfs_mkdir_p_args ();
extern bool_t xdr_guestfs_chmod_args ();
extern bool_t xdr_guestfs_chown_args ();
+extern bool_t xdr_guestfs_exists_args ();
+extern bool_t xdr_guestfs_exists_ret ();
+extern bool_t xdr_guestfs_is_file_args ();
+extern bool_t xdr_guestfs_is_file_ret ();
+extern bool_t xdr_guestfs_is_dir_args ();
+extern bool_t xdr_guestfs_is_dir_ret ();
+extern bool_t xdr_guestfs_pvcreate_args ();
+extern bool_t xdr_guestfs_vgcreate_args ();
+extern bool_t xdr_guestfs_lvcreate_args ();
+extern bool_t xdr_guestfs_mkfs_args ();
+extern bool_t xdr_guestfs_sfdisk_args ();
+extern bool_t xdr_guestfs_write_file_args ();
+extern bool_t xdr_guestfs_umount_args ();
+extern bool_t xdr_guestfs_mounts_ret ();
extern bool_t xdr_guestfs_procedure ();
extern bool_t xdr_guestfs_message_direction ();
extern bool_t xdr_guestfs_message_status ();
diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x
index 41116b53..c547d0b3 100644
--- a/src/guestfs_protocol.x
+++ b/src/guestfs_protocol.x
@@ -262,6 +262,72 @@ struct guestfs_chown_args {
string path<>;
};
+struct guestfs_exists_args {
+ string path<>;
+};
+
+struct guestfs_exists_ret {
+ bool existsflag;
+};
+
+struct guestfs_is_file_args {
+ string path<>;
+};
+
+struct guestfs_is_file_ret {
+ bool fileflag;
+};
+
+struct guestfs_is_dir_args {
+ string path<>;
+};
+
+struct guestfs_is_dir_ret {
+ bool dirflag;
+};
+
+struct guestfs_pvcreate_args {
+ string device<>;
+};
+
+struct guestfs_vgcreate_args {
+ string volgroup<>;
+ str physvols<>;
+};
+
+struct guestfs_lvcreate_args {
+ string logvol<>;
+ string volgroup<>;
+ int mbytes;
+};
+
+struct guestfs_mkfs_args {
+ string fstype<>;
+ string device<>;
+};
+
+struct guestfs_sfdisk_args {
+ string device<>;
+ int cyls;
+ int heads;
+ int sectors;
+ str lines<>;
+};
+
+struct guestfs_write_file_args {
+ string path<>;
+ string content<>;
+ int size;
+};
+
+struct guestfs_umount_args {
+ string pathordevice<>;
+};
+
+struct guestfs_mounts_ret {
+ str devices<>;
+};
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
@@ -298,6 +364,19 @@ enum guestfs_procedure {
GUESTFS_PROC_MKDIR_P = 33,
GUESTFS_PROC_CHMOD = 34,
GUESTFS_PROC_CHOWN = 35,
+ GUESTFS_PROC_EXISTS = 36,
+ GUESTFS_PROC_IS_FILE = 37,
+ GUESTFS_PROC_IS_DIR = 38,
+ GUESTFS_PROC_PVCREATE = 39,
+ GUESTFS_PROC_VGCREATE = 40,
+ GUESTFS_PROC_LVCREATE = 41,
+ GUESTFS_PROC_MKFS = 42,
+ GUESTFS_PROC_SFDISK = 43,
+ GUESTFS_PROC_WRITE_FILE = 44,
+ GUESTFS_PROC_UMOUNT = 45,
+ GUESTFS_PROC_MOUNTS = 46,
+ GUESTFS_PROC_UMOUNT_ALL = 47,
+ GUESTFS_PROC_LVM_REMOVE_ALL = 48,
GUESTFS_PROC_dummy
};
diff --git a/tests.c b/tests.c
index 104e6fab..3e0fbd3d 100644
--- a/tests.c
+++ b/tests.c
@@ -22,10 +22,3943 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
#include "guestfs.h"
+static guestfs_h *g;
+static int suppress_error = 0;
+
+static void print_error (guestfs_h *g, void *data, const char *msg)
+{
+ if (!suppress_error)
+ fprintf (stderr, "%s\n", msg);
+}
+
+static void print_strings (char * const * const argv)
+{
+ int argc;
+
+ for (argc = 0; argv[argc] != NULL; ++argc)
+ printf ("\t%s\n", argv[argc]);
+}
+
+static int test_mount_0 (void)
+{
+ /* InitNone for mount (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutput for mount (0) */
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_write_file (g, "/new", "new file contents", 0);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *r;
+ suppress_error = 0;
+ r = guestfs_cat (g, "/new");
+ if (r == NULL)
+ return -1;
+ if (strcmp (r, "new file contents") != 0) {
+ fprintf (stderr, "test_mount_0: expected \"new file contents\" but got \"%s\"\n", r);
+ return -1;
+ }
+ free (r);
+ }
+ return 0;
+}
+
+static int test_sync_0 (void)
+{
+ /* InitNone for sync (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestRun for sync (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_sync (g);
+ if (r == -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_touch_0 (void)
+{
+ /* InitEmpty for touch (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for touch (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_exists (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_touch_0: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_cat_0 (void)
+{
+ /* InitEmpty for cat (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutput for cat (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_write_file (g, "/new", "new file contents", 0);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *r;
+ suppress_error = 0;
+ r = guestfs_cat (g, "/new");
+ if (r == NULL)
+ return -1;
+ if (strcmp (r, "new file contents") != 0) {
+ fprintf (stderr, "test_cat_0: expected \"new file contents\" but got \"%s\"\n", r);
+ return -1;
+ }
+ free (r);
+ }
+ return 0;
+}
+
+static int test_ls_0 (void)
+{
+ /* InitEmpty for ls (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for ls (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/newer");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/newest");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_ls (g, "/");
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_ls_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "lost+found") != 0) {
+ fprintf (stderr, "test_ls_0: expected \"lost+found\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_ls_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "new") != 0) {
+ fprintf (stderr, "test_ls_0: expected \"new\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_ls_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "newer") != 0) {
+ fprintf (stderr, "test_ls_0: expected \"newer\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (!r[3]) {
+ fprintf (stderr, "test_ls_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[3], "newest") != 0) {
+ fprintf (stderr, "test_ls_0: expected \"newest\" but got \"%s\"\n", r[3]);
+ return -1;
+ }
+ if (r[4] != NULL) {
+ fprintf (stderr, "test_ls_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_list_devices_0 (void)
+{
+ /* InitNone for list_devices (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for list_devices (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_list_devices (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_list_devices_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda") != 0) {
+ fprintf (stderr, "test_list_devices_0: expected \"/dev/sda\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_list_devices_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "/dev/sdb") != 0) {
+ fprintf (stderr, "test_list_devices_0: expected \"/dev/sdb\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_list_devices_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "/dev/sdc") != 0) {
+ fprintf (stderr, "test_list_devices_0: expected \"/dev/sdc\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_list_devices_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_list_partitions_0 (void)
+{
+ /* InitEmpty for list_partitions (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for list_partitions (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_list_partitions (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_list_partitions_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_list_partitions_0: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (r[1] != NULL) {
+ fprintf (stderr, "test_list_partitions_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_list_partitions_1 (void)
+{
+ /* InitNone for list_partitions (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for list_partitions (1) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_list_partitions (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_list_partitions_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_list_partitions_1: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_list_partitions_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "/dev/sda2") != 0) {
+ fprintf (stderr, "test_list_partitions_1: expected \"/dev/sda2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_list_partitions_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "/dev/sda3") != 0) {
+ fprintf (stderr, "test_list_partitions_1: expected \"/dev/sda3\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_list_partitions_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_pvs_0 (void)
+{
+ /* InitEmptyLVM for pvs (0): create ext2 on /dev/VG/LV */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV", "VG", 8);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/VG/LV");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/VG/LV", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for pvs (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_pvs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_pvs_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_pvs_0: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (r[1] != NULL) {
+ fprintf (stderr, "test_pvs_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_pvs_1 (void)
+{
+ /* InitNone for pvs (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for pvs (1) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda2");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda3");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_pvs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_pvs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_pvs_1: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_pvs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "/dev/sda2") != 0) {
+ fprintf (stderr, "test_pvs_1: expected \"/dev/sda2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_pvs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "/dev/sda3") != 0) {
+ fprintf (stderr, "test_pvs_1: expected \"/dev/sda3\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_pvs_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_vgs_0 (void)
+{
+ /* InitEmptyLVM for vgs (0): create ext2 on /dev/VG/LV */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV", "VG", 8);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/VG/LV");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/VG/LV", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for vgs (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_vgs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_vgs_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "VG") != 0) {
+ fprintf (stderr, "test_vgs_0: expected \"VG\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (r[1] != NULL) {
+ fprintf (stderr, "test_vgs_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_vgs_1 (void)
+{
+ /* InitNone for vgs (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for vgs (1) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda2");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda3");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ "/dev/sda2",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG1", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda3",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG2", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_vgs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_vgs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "VG1") != 0) {
+ fprintf (stderr, "test_vgs_1: expected \"VG1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_vgs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "VG2") != 0) {
+ fprintf (stderr, "test_vgs_1: expected \"VG2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (r[2] != NULL) {
+ fprintf (stderr, "test_vgs_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_lvs_0 (void)
+{
+ /* InitEmptyLVM for lvs (0): create ext2 on /dev/VG/LV */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV", "VG", 8);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/VG/LV");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/VG/LV", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for lvs (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_lvs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_lvs_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/VG/LV") != 0) {
+ fprintf (stderr, "test_lvs_0: expected \"/dev/VG/LV\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (r[1] != NULL) {
+ fprintf (stderr, "test_lvs_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_lvs_1 (void)
+{
+ /* InitNone for lvs (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for lvs (1) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda2");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda3");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ "/dev/sda2",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG1", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda3",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG2", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV1", "VG1", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV2", "VG1", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV3", "VG2", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_lvs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_lvs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/VG1/LV1") != 0) {
+ fprintf (stderr, "test_lvs_1: expected \"/dev/VG1/LV1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_lvs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "/dev/VG1/LV2") != 0) {
+ fprintf (stderr, "test_lvs_1: expected \"/dev/VG1/LV2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_lvs_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "/dev/VG2/LV3") != 0) {
+ fprintf (stderr, "test_lvs_1: expected \"/dev/VG2/LV3\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_lvs_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_pvs_full_0 (void)
+{
+ /* InitEmptyLVM for pvs_full (0): create ext2 on /dev/VG/LV */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV", "VG", 8);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/VG/LV");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/VG/LV", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputLength for pvs_full (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_pvs (g);
+ if (r == NULL)
+ return -1;
+ int j;
+ for (j = 0; j < 1; ++j)
+ if (r[j] == NULL) {
+ fprintf (stderr, "test_pvs_full_0: short list returned\n");
+ print_strings (r);
+ return -1;
+ }
+ if (r[j] != NULL) {
+ fprintf (stderr, "test_pvs_full_0: long list returned\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_vgs_full_0 (void)
+{
+ /* InitEmptyLVM for vgs_full (0): create ext2 on /dev/VG/LV */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV", "VG", 8);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/VG/LV");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/VG/LV", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputLength for vgs_full (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_pvs (g);
+ if (r == NULL)
+ return -1;
+ int j;
+ for (j = 0; j < 1; ++j)
+ if (r[j] == NULL) {
+ fprintf (stderr, "test_vgs_full_0: short list returned\n");
+ print_strings (r);
+ return -1;
+ }
+ if (r[j] != NULL) {
+ fprintf (stderr, "test_vgs_full_0: long list returned\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_lvs_full_0 (void)
+{
+ /* InitEmptyLVM for lvs_full (0): create ext2 on /dev/VG/LV */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV", "VG", 8);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/VG/LV");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/VG/LV", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputLength for lvs_full (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_pvs (g);
+ if (r == NULL)
+ return -1;
+ int j;
+ for (j = 0; j < 1; ++j)
+ if (r[j] == NULL) {
+ fprintf (stderr, "test_lvs_full_0: short list returned\n");
+ print_strings (r);
+ return -1;
+ }
+ if (r[j] != NULL) {
+ fprintf (stderr, "test_lvs_full_0: long list returned\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_read_lines_0 (void)
+{
+ /* InitEmpty for read_lines (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for read_lines (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_write_file (g, "/new", "line1\r\nline2\nline3", 0);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_read_lines (g, "/new");
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_read_lines_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "line1") != 0) {
+ fprintf (stderr, "test_read_lines_0: expected \"line1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_read_lines_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "line2") != 0) {
+ fprintf (stderr, "test_read_lines_0: expected \"line2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_read_lines_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "line3") != 0) {
+ fprintf (stderr, "test_read_lines_0: expected \"line3\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_read_lines_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_read_lines_1 (void)
+{
+ /* InitEmpty for read_lines (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for read_lines (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_write_file (g, "/new", "", 0);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_read_lines (g, "/new");
+ if (r == NULL)
+ return -1;
+ if (r[0] != NULL) {
+ fprintf (stderr, "test_read_lines_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_rm_0 (void)
+{
+ /* InitEmpty for rm (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestRun for rm (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_rm (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_rm_1 (void)
+{
+ /* InitEmpty for rm (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestLastFail for rm (1) */
+ {
+ int r;
+ suppress_error = 1;
+ r = guestfs_rm (g, "/new");
+ if (r != -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_rm_2 (void)
+{
+ /* InitEmpty for rm (2): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestLastFail for rm (2) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 1;
+ r = guestfs_rm (g, "/new");
+ if (r != -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_rmdir_0 (void)
+{
+ /* InitEmpty for rmdir (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestRun for rmdir (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_rmdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_rmdir_1 (void)
+{
+ /* InitEmpty for rmdir (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestLastFail for rmdir (1) */
+ {
+ int r;
+ suppress_error = 1;
+ r = guestfs_rmdir (g, "/new");
+ if (r != -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_rmdir_2 (void)
+{
+ /* InitEmpty for rmdir (2): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestLastFail for rmdir (2) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 1;
+ r = guestfs_rmdir (g, "/new");
+ if (r != -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_rm_rf_0 (void)
+{
+ /* InitEmpty for rm_rf (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputFalse for rm_rf (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new/foo");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new/foo/bar");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_rm_rf (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_exists (g, "/new");
+ if (r == -1)
+ return -1;
+ if (r) {
+ fprintf (stderr, "test_rm_rf_0: expected false, got true\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_mkdir_0 (void)
+{
+ /* InitEmpty for mkdir (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for mkdir (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_dir (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_mkdir_0: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_mkdir_1 (void)
+{
+ /* InitEmpty for mkdir (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestLastFail for mkdir (1) */
+ {
+ int r;
+ suppress_error = 1;
+ r = guestfs_mkdir (g, "/new/foo/bar");
+ if (r != -1)
+ return -1;
+ }
+ return 0;
+}
+
+static int test_mkdir_p_0 (void)
+{
+ /* InitEmpty for mkdir_p (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for mkdir_p (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir_p (g, "/new/foo/bar");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_dir (g, "/new/foo/bar");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_mkdir_p_0: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_mkdir_p_1 (void)
+{
+ /* InitEmpty for mkdir_p (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for mkdir_p (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir_p (g, "/new/foo/bar");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_dir (g, "/new/foo");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_mkdir_p_1: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_mkdir_p_2 (void)
+{
+ /* InitEmpty for mkdir_p (2): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for mkdir_p (2) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir_p (g, "/new/foo/bar");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_dir (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_mkdir_p_2: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_exists_0 (void)
+{
+ /* InitEmpty for exists (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for exists (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_exists (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_exists_0: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_exists_1 (void)
+{
+ /* InitEmpty for exists (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for exists (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_exists (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_exists_1: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_is_file_0 (void)
+{
+ /* InitEmpty for is_file (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for is_file (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_file (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_is_file_0: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_is_file_1 (void)
+{
+ /* InitEmpty for is_file (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputFalse for is_file (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_file (g, "/new");
+ if (r == -1)
+ return -1;
+ if (r) {
+ fprintf (stderr, "test_is_file_1: expected false, got true\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_is_dir_0 (void)
+{
+ /* InitEmpty for is_dir (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputFalse for is_dir (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_touch (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_dir (g, "/new");
+ if (r == -1)
+ return -1;
+ if (r) {
+ fprintf (stderr, "test_is_dir_0: expected false, got true\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_is_dir_1 (void)
+{
+ /* InitEmpty for is_dir (1): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputTrue for is_dir (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkdir (g, "/new");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_is_dir (g, "/new");
+ if (r == -1)
+ return -1;
+ if (!r) {
+ fprintf (stderr, "test_is_dir_1: expected true, got false\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test_pvcreate_0 (void)
+{
+ /* InitNone for pvcreate (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for pvcreate (0) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda2");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda3");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_pvs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_pvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_pvcreate_0: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_pvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "/dev/sda2") != 0) {
+ fprintf (stderr, "test_pvcreate_0: expected \"/dev/sda2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_pvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "/dev/sda3") != 0) {
+ fprintf (stderr, "test_pvcreate_0: expected \"/dev/sda3\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_pvcreate_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_vgcreate_0 (void)
+{
+ /* InitNone for vgcreate (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for vgcreate (0) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda2");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda3");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ "/dev/sda2",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG1", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda3",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG2", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_vgs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_vgcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "VG1") != 0) {
+ fprintf (stderr, "test_vgcreate_0: expected \"VG1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_vgcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "VG2") != 0) {
+ fprintf (stderr, "test_vgcreate_0: expected \"VG2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (r[2] != NULL) {
+ fprintf (stderr, "test_vgcreate_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_lvcreate_0 (void)
+{
+ /* InitNone for lvcreate (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for lvcreate (0) */
+ {
+ char *lines[] = {
+ ",10",
+ ",20",
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda2");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_pvcreate (g, "/dev/sda3");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda1",
+ "/dev/sda2",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG1", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *physvols[] = {
+ "/dev/sda3",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_vgcreate (g, "VG2", physvols);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV1", "VG1", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV2", "VG1", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV3", "VG2", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV4", "VG2", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvcreate (g, "LV5", "VG2", 50);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_lvs (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_lvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/VG1/LV1") != 0) {
+ fprintf (stderr, "test_lvcreate_0: expected \"/dev/VG1/LV1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_lvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[1], "/dev/VG1/LV2") != 0) {
+ fprintf (stderr, "test_lvcreate_0: expected \"/dev/VG1/LV2\" but got \"%s\"\n", r[1]);
+ return -1;
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_lvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[2], "/dev/VG2/LV3") != 0) {
+ fprintf (stderr, "test_lvcreate_0: expected \"/dev/VG2/LV3\" but got \"%s\"\n", r[2]);
+ return -1;
+ }
+ if (!r[3]) {
+ fprintf (stderr, "test_lvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[3], "/dev/VG2/LV4") != 0) {
+ fprintf (stderr, "test_lvcreate_0: expected \"/dev/VG2/LV4\" but got \"%s\"\n", r[3]);
+ return -1;
+ }
+ if (!r[4]) {
+ fprintf (stderr, "test_lvcreate_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[4], "/dev/VG2/LV5") != 0) {
+ fprintf (stderr, "test_lvcreate_0: expected \"/dev/VG2/LV5\" but got \"%s\"\n", r[4]);
+ return -1;
+ }
+ if (r[5] != NULL) {
+ fprintf (stderr, "test_lvcreate_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_mkfs_0 (void)
+{
+ /* InitNone for mkfs (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutput for mkfs (0) */
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_write_file (g, "/new", "new file contents", 0);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *r;
+ suppress_error = 0;
+ r = guestfs_cat (g, "/new");
+ if (r == NULL)
+ return -1;
+ if (strcmp (r, "new file contents") != 0) {
+ fprintf (stderr, "test_mkfs_0: expected \"new file contents\" but got \"%s\"\n", r);
+ return -1;
+ }
+ free (r);
+ }
+ return 0;
+}
+
+static int test_write_file_0 (void)
+{
+ /* InitNone for write_file (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutput for write_file (0) */
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_write_file (g, "/new", "new file contents", 0);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *r;
+ suppress_error = 0;
+ r = guestfs_cat (g, "/new");
+ if (r == NULL)
+ return -1;
+ if (strcmp (r, "new file contents") != 0) {
+ fprintf (stderr, "test_write_file_0: expected \"new file contents\" but got \"%s\"\n", r);
+ return -1;
+ }
+ free (r);
+ }
+ return 0;
+}
+
+static int test_umount_0 (void)
+{
+ /* InitNone for umount (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for umount (0) */
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_mounts (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_umount_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_umount_0: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (r[1] != NULL) {
+ fprintf (stderr, "test_umount_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_umount_1 (void)
+{
+ /* InitNone for umount (1) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for umount (1) */
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount (g, "/");
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_mounts (g);
+ if (r == NULL)
+ return -1;
+ if (r[0] != NULL) {
+ fprintf (stderr, "test_umount_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_mounts_0 (void)
+{
+ /* InitEmpty for mounts (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for mounts (0) */
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_mounts (g);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_mounts_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ if (strcmp (r[0], "/dev/sda1") != 0) {
+ fprintf (stderr, "test_mounts_0: expected \"/dev/sda1\" but got \"%s\"\n", r[0]);
+ return -1;
+ }
+ if (r[1] != NULL) {
+ fprintf (stderr, "test_mounts_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_umount_all_0 (void)
+{
+ /* InitEmpty for umount_all (0): create ext2 on /dev/sda1 */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char *lines[] = {
+ ",",
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, "ext2", "/dev/sda1");
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, "/dev/sda1", "/");
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for umount_all (0) */
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_mounts (g);
+ if (r == NULL)
+ return -1;
+ if (r[0] != NULL) {
+ fprintf (stderr, "test_umount_all_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
int main (int argc, char *argv[])
{
+ char c = 0;
+ int failed = 0;
+ const char *srcdir;
+ int fd;
+ char buf[256];
+
+ g = guestfs_create ();
+ if (g == NULL) {
+ printf ("guestfs_create FAILED\n");
+ exit (1);
+ }
+
+ guestfs_set_error_handler (g, print_error, NULL);
+
+ srcdir = getenv ("srcdir");
+ if (!srcdir) srcdir = ".";
+ guestfs_set_path (g, srcdir);
+
+ snprintf (buf, sizeof buf, "%s/test1.img", srcdir);
+ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
+ if (fd == -1) {
+ perror (buf);
+ exit (1);
+ }
+ if (lseek (fd, 524288000, SEEK_SET) == -1) {
+ perror ("lseek");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (write (fd, &c, 1) == -1) {
+ perror ("write");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (close (fd) == -1) {
+ perror (buf);
+ unlink (buf);
+ exit (1);
+ }
+ if (guestfs_add_drive (g, buf) == -1) {
+ printf ("guestfs_add_drive %s FAILED\n", buf);
+ exit (1);
+ }
+
+ snprintf (buf, sizeof buf, "%s/test2.img", srcdir);
+ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
+ if (fd == -1) {
+ perror (buf);
+ exit (1);
+ }
+ if (lseek (fd, 52428800, SEEK_SET) == -1) {
+ perror ("lseek");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (write (fd, &c, 1) == -1) {
+ perror ("write");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (close (fd) == -1) {
+ perror (buf);
+ unlink (buf);
+ exit (1);
+ }
+ if (guestfs_add_drive (g, buf) == -1) {
+ printf ("guestfs_add_drive %s FAILED\n", buf);
+ exit (1);
+ }
+
+ snprintf (buf, sizeof buf, "%s/test3.img", srcdir);
+ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
+ if (fd == -1) {
+ perror (buf);
+ exit (1);
+ }
+ if (lseek (fd, 10485760, SEEK_SET) == -1) {
+ perror ("lseek");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (write (fd, &c, 1) == -1) {
+ perror ("write");
+ close (fd);
+ unlink (buf);
+ exit (1);
+ }
+ if (close (fd) == -1) {
+ perror (buf);
+ unlink (buf);
+ exit (1);
+ }
+ if (guestfs_add_drive (g, buf) == -1) {
+ printf ("guestfs_add_drive %s FAILED\n", buf);
+ exit (1);
+ }
+
+ if (guestfs_launch (g) == -1) {
+ printf ("guestfs_launch FAILED\n");
+ exit (1);
+ }
+ if (guestfs_wait_ready (g) == -1) {
+ printf ("guestfs_wait_ready FAILED\n");
+ exit (1);
+ }
+
+ printf (" 1/ 46 test_mount_0\n");
+ if (test_mount_0 () == -1) {
+ printf ("test_mount_0 FAILED\n");
+ failed++;
+ }
+ printf (" 2/ 46 test_sync_0\n");
+ if (test_sync_0 () == -1) {
+ printf ("test_sync_0 FAILED\n");
+ failed++;
+ }
+ printf (" 3/ 46 test_touch_0\n");
+ if (test_touch_0 () == -1) {
+ printf ("test_touch_0 FAILED\n");
+ failed++;
+ }
+ printf (" 4/ 46 test_cat_0\n");
+ if (test_cat_0 () == -1) {
+ printf ("test_cat_0 FAILED\n");
+ failed++;
+ }
+ printf (" 5/ 46 test_ls_0\n");
+ if (test_ls_0 () == -1) {
+ printf ("test_ls_0 FAILED\n");
+ failed++;
+ }
+ printf (" 6/ 46 test_list_devices_0\n");
+ if (test_list_devices_0 () == -1) {
+ printf ("test_list_devices_0 FAILED\n");
+ failed++;
+ }
+ printf (" 7/ 46 test_list_partitions_0\n");
+ if (test_list_partitions_0 () == -1) {
+ printf ("test_list_partitions_0 FAILED\n");
+ failed++;
+ }
+ printf (" 8/ 46 test_list_partitions_1\n");
+ if (test_list_partitions_1 () == -1) {
+ printf ("test_list_partitions_1 FAILED\n");
+ failed++;
+ }
+ printf (" 9/ 46 test_pvs_0\n");
+ if (test_pvs_0 () == -1) {
+ printf ("test_pvs_0 FAILED\n");
+ failed++;
+ }
+ printf (" 10/ 46 test_pvs_1\n");
+ if (test_pvs_1 () == -1) {
+ printf ("test_pvs_1 FAILED\n");
+ failed++;
+ }
+ printf (" 11/ 46 test_vgs_0\n");
+ if (test_vgs_0 () == -1) {
+ printf ("test_vgs_0 FAILED\n");
+ failed++;
+ }
+ printf (" 12/ 46 test_vgs_1\n");
+ if (test_vgs_1 () == -1) {
+ printf ("test_vgs_1 FAILED\n");
+ failed++;
+ }
+ printf (" 13/ 46 test_lvs_0\n");
+ if (test_lvs_0 () == -1) {
+ printf ("test_lvs_0 FAILED\n");
+ failed++;
+ }
+ printf (" 14/ 46 test_lvs_1\n");
+ if (test_lvs_1 () == -1) {
+ printf ("test_lvs_1 FAILED\n");
+ failed++;
+ }
+ printf (" 15/ 46 test_pvs_full_0\n");
+ if (test_pvs_full_0 () == -1) {
+ printf ("test_pvs_full_0 FAILED\n");
+ failed++;
+ }
+ printf (" 16/ 46 test_vgs_full_0\n");
+ if (test_vgs_full_0 () == -1) {
+ printf ("test_vgs_full_0 FAILED\n");
+ failed++;
+ }
+ printf (" 17/ 46 test_lvs_full_0\n");
+ if (test_lvs_full_0 () == -1) {
+ printf ("test_lvs_full_0 FAILED\n");
+ failed++;
+ }
+ printf (" 18/ 46 test_read_lines_0\n");
+ if (test_read_lines_0 () == -1) {
+ printf ("test_read_lines_0 FAILED\n");
+ failed++;
+ }
+ printf (" 19/ 46 test_read_lines_1\n");
+ if (test_read_lines_1 () == -1) {
+ printf ("test_read_lines_1 FAILED\n");
+ failed++;
+ }
+ printf (" 20/ 46 test_rm_0\n");
+ if (test_rm_0 () == -1) {
+ printf ("test_rm_0 FAILED\n");
+ failed++;
+ }
+ printf (" 21/ 46 test_rm_1\n");
+ if (test_rm_1 () == -1) {
+ printf ("test_rm_1 FAILED\n");
+ failed++;
+ }
+ printf (" 22/ 46 test_rm_2\n");
+ if (test_rm_2 () == -1) {
+ printf ("test_rm_2 FAILED\n");
+ failed++;
+ }
+ printf (" 23/ 46 test_rmdir_0\n");
+ if (test_rmdir_0 () == -1) {
+ printf ("test_rmdir_0 FAILED\n");
+ failed++;
+ }
+ printf (" 24/ 46 test_rmdir_1\n");
+ if (test_rmdir_1 () == -1) {
+ printf ("test_rmdir_1 FAILED\n");
+ failed++;
+ }
+ printf (" 25/ 46 test_rmdir_2\n");
+ if (test_rmdir_2 () == -1) {
+ printf ("test_rmdir_2 FAILED\n");
+ failed++;
+ }
+ printf (" 26/ 46 test_rm_rf_0\n");
+ if (test_rm_rf_0 () == -1) {
+ printf ("test_rm_rf_0 FAILED\n");
+ failed++;
+ }
+ printf (" 27/ 46 test_mkdir_0\n");
+ if (test_mkdir_0 () == -1) {
+ printf ("test_mkdir_0 FAILED\n");
+ failed++;
+ }
+ printf (" 28/ 46 test_mkdir_1\n");
+ if (test_mkdir_1 () == -1) {
+ printf ("test_mkdir_1 FAILED\n");
+ failed++;
+ }
+ printf (" 29/ 46 test_mkdir_p_0\n");
+ if (test_mkdir_p_0 () == -1) {
+ printf ("test_mkdir_p_0 FAILED\n");
+ failed++;
+ }
+ printf (" 30/ 46 test_mkdir_p_1\n");
+ if (test_mkdir_p_1 () == -1) {
+ printf ("test_mkdir_p_1 FAILED\n");
+ failed++;
+ }
+ printf (" 31/ 46 test_mkdir_p_2\n");
+ if (test_mkdir_p_2 () == -1) {
+ printf ("test_mkdir_p_2 FAILED\n");
+ failed++;
+ }
+ printf (" 32/ 46 test_exists_0\n");
+ if (test_exists_0 () == -1) {
+ printf ("test_exists_0 FAILED\n");
+ failed++;
+ }
+ printf (" 33/ 46 test_exists_1\n");
+ if (test_exists_1 () == -1) {
+ printf ("test_exists_1 FAILED\n");
+ failed++;
+ }
+ printf (" 34/ 46 test_is_file_0\n");
+ if (test_is_file_0 () == -1) {
+ printf ("test_is_file_0 FAILED\n");
+ failed++;
+ }
+ printf (" 35/ 46 test_is_file_1\n");
+ if (test_is_file_1 () == -1) {
+ printf ("test_is_file_1 FAILED\n");
+ failed++;
+ }
+ printf (" 36/ 46 test_is_dir_0\n");
+ if (test_is_dir_0 () == -1) {
+ printf ("test_is_dir_0 FAILED\n");
+ failed++;
+ }
+ printf (" 37/ 46 test_is_dir_1\n");
+ if (test_is_dir_1 () == -1) {
+ printf ("test_is_dir_1 FAILED\n");
+ failed++;
+ }
+ printf (" 38/ 46 test_pvcreate_0\n");
+ if (test_pvcreate_0 () == -1) {
+ printf ("test_pvcreate_0 FAILED\n");
+ failed++;
+ }
+ printf (" 39/ 46 test_vgcreate_0\n");
+ if (test_vgcreate_0 () == -1) {
+ printf ("test_vgcreate_0 FAILED\n");
+ failed++;
+ }
+ printf (" 40/ 46 test_lvcreate_0\n");
+ if (test_lvcreate_0 () == -1) {
+ printf ("test_lvcreate_0 FAILED\n");
+ failed++;
+ }
+ printf (" 41/ 46 test_mkfs_0\n");
+ if (test_mkfs_0 () == -1) {
+ printf ("test_mkfs_0 FAILED\n");
+ failed++;
+ }
+ printf (" 42/ 46 test_write_file_0\n");
+ if (test_write_file_0 () == -1) {
+ printf ("test_write_file_0 FAILED\n");
+ failed++;
+ }
+ printf (" 43/ 46 test_umount_0\n");
+ if (test_umount_0 () == -1) {
+ printf ("test_umount_0 FAILED\n");
+ failed++;
+ }
+ printf (" 44/ 46 test_umount_1\n");
+ if (test_umount_1 () == -1) {
+ printf ("test_umount_1 FAILED\n");
+ failed++;
+ }
+ printf (" 45/ 46 test_mounts_0\n");
+ if (test_mounts_0 () == -1) {
+ printf ("test_mounts_0 FAILED\n");
+ failed++;
+ }
+ printf (" 46/ 46 test_umount_all_0\n");
+ if (test_umount_all_0 () == -1) {
+ printf ("test_umount_all_0 FAILED\n");
+ failed++;
+ }
+
+ guestfs_close (g);
+ snprintf (buf, sizeof buf, "%s/test1.img", srcdir);
+ unlink (buf);
+ snprintf (buf, sizeof buf, "%s/test2.img", srcdir);
+ unlink (buf);
+ snprintf (buf, sizeof buf, "%s/test3.img", srcdir);
+ unlink (buf);
+
+ if (failed > 0) {
+ printf ("***** %d / 46 tests FAILED *****\n", failed);
+ exit (1);
+ }
+
exit (0);
}