summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile.am34
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/augeas.c52
-rw-r--r--daemon/available.c23
-rw-r--r--daemon/configure.ac24
-rw-r--r--daemon/daemon.h17
-rw-r--r--daemon/inotify.c31
-rw-r--r--daemon/lvm.c8
-rw-r--r--daemon/mknod.c18
-rw-r--r--daemon/modprobe.c8
-rw-r--r--daemon/ntfs.c8
-rw-r--r--daemon/scrub.c8
-rw-r--r--daemon/selinux.c21
-rw-r--r--daemon/swap.c19
-rw-r--r--daemon/xattr.c47
-rw-r--r--daemon/zerofree.c8
-rw-r--r--guestfs.pod7
-rw-r--r--po/POTFILES.in1
-rwxr-xr-xsrc/generator.ml200
20 files changed, 388 insertions, 151 deletions
diff --git a/.gitignore b/.gitignore
index b3869c52..3348b979 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,8 @@ daemon/guestfsd
daemon/install-sh
daemon/missing
daemon/names.c
+daemon/optgroups.c
+daemon/optgroups.h
daemon/stubs.c
depcomp
.deps
@@ -65,6 +67,7 @@ guestfish.1
guestfish-actions.pod
guestfs.3
guestfs-actions.pod
+guestfs-availability.pod
guestfs-structs.pod
haskell/Bindtests
haskell/Bindtests.hs
diff --git a/Makefile.am b/Makefile.am
index 9332a10d..bbdb0ed4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,8 +57,9 @@ SUBDIRS += haskell
endif
generator_built = \
- guestfs-structs.pod \
guestfs-actions.pod \
+ guestfs-availability.pod \
+ guestfs-structs.pod \
guestfish-actions.pod
EXTRA_DIST = \
@@ -83,15 +84,23 @@ EXTRA_DIST = \
libguestfs.3
# 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.
+# guestfs-actions.pod, guestfs-availability.pod and guestfs-structs
+# are autogenerated. There is no include mechanism for POD, so we
+# have to do it by hand.
man_MANS = guestfs.3 libguestfs.3 guestfish.1
-guestfs.3: guestfs.pod guestfs-actions.pod guestfs-structs.pod
+guestfs.3: guestfs.pod \
+ guestfs-actions.pod \
+ guestfs-availability.pod \
+ guestfs-structs.pod
sed \
- -e '/@ACTIONS@/rguestfs-actions.pod' -e 's/@ACTIONS@//' \
- -e '/@STRUCTS@/rguestfs-structs.pod' -e 's/@STRUCTS@//' \
+ -e '/@ACTIONS@/rguestfs-actions.pod' \
+ -e 's/@ACTIONS@//' \
+ -e '/@AVAILABILITY@/rguestfs-availability.pod' \
+ -e 's/@AVAILABILITY@//' \
+ -e '/@STRUCTS@/rguestfs-structs.pod' \
+ -e 's/@STRUCTS@//' \
< $< | \
$(POD2MAN) \
--section 3 \
@@ -113,11 +122,18 @@ guestfish.1: guestfish.pod guestfish-actions.pod
noinst_DATA = html/guestfs.3.html html/guestfish.1.html
-html/guestfs.3.html: guestfs.pod guestfs-actions.pod guestfs-structs.pod
+html/guestfs.3.html: guestfs.pod \
+ guestfs-actions.pod \
+ guestfs-availability.pod \
+ guestfs-structs.pod
mkdir -p html
sed \
- -e '/@ACTIONS@/rguestfs-actions.pod' -e 's/@ACTIONS@//' \
- -e '/@STRUCTS@/rguestfs-structs.pod' -e 's/@STRUCTS@//' \
+ -e '/@ACTIONS@/rguestfs-actions.pod' \
+ -e 's/@ACTIONS@//' \
+ -e '/@AVAILABILITY@/rguestfs-availability.pod' \
+ -e 's/@AVAILABILITY@//' \
+ -e '/@STRUCTS@/rguestfs-structs.pod' \
+ -e 's/@STRUCTS@//' \
< $< | \
pod2html \
--css 'pod.css' \
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index d851e527..9fa8ddab 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -81,6 +81,8 @@ guestfsd_SOURCES = \
mount.c \
names.c \
ntfs.c \
+ optgroups.c \
+ optgroups.h \
parted.c \
pingdaemon.c \
proto.c \
diff --git a/daemon/augeas.c b/daemon/augeas.c
index b56012cd..be53d294 100644
--- a/daemon/augeas.c
+++ b/daemon/augeas.c
@@ -29,6 +29,7 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
#ifdef HAVE_AUGEAS
/* The Augeas handle. We maintain a single handle per daemon, which
@@ -45,6 +46,18 @@ static augeas *aug = NULL;
} \
} \
while (0)
+
+int
+optgroup_augeas_available (void)
+{
+ return 1;
+}
+#else /* !HAVE_AUGEAS */
+int
+optgroup_augeas_available (void)
+{
+ return 0;
+}
#endif
/* We need to rewrite the root path so it is based at /sysroot. */
@@ -75,8 +88,7 @@ do_aug_init (const char *root, int flags)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -91,8 +103,7 @@ do_aug_close (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -111,8 +122,7 @@ do_aug_defvar (const char *name, const char *expr)
}
return r;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -133,8 +143,7 @@ do_aug_defnode (const char *name, const char *expr, const char *val)
r.b = created;
return &r;
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -176,8 +185,7 @@ do_aug_get (const char *path)
return v; /* Caller frees. */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
@@ -197,8 +205,7 @@ do_aug_set (const char *path, const char *val)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -218,8 +225,7 @@ do_aug_insert (const char *path, const char *label, int before)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -239,8 +245,7 @@ do_aug_rm (const char *path)
return r;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -260,8 +265,7 @@ do_aug_mv (const char *src, const char *dest)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -295,8 +299,7 @@ do_aug_match (const char *path)
return matches; /* Caller frees. */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
@@ -313,8 +316,7 @@ do_aug_save (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -331,8 +333,7 @@ do_aug_load (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -379,7 +380,6 @@ do_aug_ls (const char *path)
sort_strings (matches, count_strings ((void *) matches));
return matches; /* Caller frees. */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
diff --git a/daemon/available.c b/daemon/available.c
index b43d1820..77fdfa2c 100644
--- a/daemon/available.c
+++ b/daemon/available.c
@@ -29,9 +29,26 @@
int
do_available (char *const *groups)
{
- if (groups[0] != NULL) {
- reply_with_error ("%s: unknown group", groups[0]);
- return -1;
+ int av;
+ size_t i, j;
+
+ for (i = 0; groups[i] != NULL; ++i) {
+ for (j = 0; optgroups[j].group != NULL; ++j) {
+ if (STREQ (groups[i], optgroups[j].group)) {
+ av = optgroups[j].available ();
+ if (!av) {
+ reply_with_error ("%s: group not available", optgroups[j].group);
+ return -1;
+ }
+ break; /* out of for (j) loop */
+ }
+ }
+
+ /* Unknown group? */
+ if (optgroups[j].group == NULL) {
+ reply_with_error ("%s: unknown group", groups[i]);
+ return -1;
+ }
}
return 0;
diff --git a/daemon/configure.ac b/daemon/configure.ac
index a1f54a3b..c6d9d98f 100644
--- a/daemon/configure.ac
+++ b/daemon/configure.ac
@@ -133,7 +133,7 @@ AC_STRUCT_DIRENT_D_TYPE
dnl Check if stat has the required fields.
AC_STRUCT_ST_BLOCKS
AC_CHECK_MEMBER([struct stat.st_blksize],[
- AC_DEFINE([HAVE_STRUCT_STAT_ST_BLKSIZE],[1],[Define to 1 if 'st_blksize' is a member of 'struct stat'])])
+ AC_DEFINE([HAVE_STRUCT_STAT_ST_BLKSIZE],[1],[Define to 1 if 'st_blksize' is a member of 'struct stat'])])
dnl Check for Augeas (now optional).
AC_CHECK_LIB([augeas],[aug_match],[
@@ -164,17 +164,17 @@ AC_CHECK_LIB([portablexdr],[xdrmem_create],[],[
dnl Functions which may not be available in older distributions.
AC_CHECK_FUNCS([\
- futimens \
- getxattr \
- inotify_init1 \
- lgetxattr \
- listxattr \
- llistxattr \
- lsetxattr \
- lremovexattr \
- mknod \
- removexattr \
- setxattr])
+ futimens \
+ getxattr \
+ inotify_init1 \
+ lgetxattr \
+ listxattr \
+ llistxattr \
+ lsetxattr \
+ lremovexattr \
+ mknod \
+ removexattr \
+ setxattr])
dnl Headers.
AC_CHECK_HEADERS([\
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 120c86cc..7ba75990 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -105,6 +105,13 @@ extern guestfs_int_lvm_lv_list *parse_command_line_lvs (void);
/*-- in proto.c --*/
extern void main_loop (int sock) __attribute__((noreturn));
+/*-- in optgroups.c (auto-generated) --*/
+struct optgroup {
+ const char *group; /* Name of the optional group. */
+ int (*available) (void); /* Function to test availability. */
+};
+extern struct optgroup optgroups[];
+
/* ordinary daemon functions use these to indicate errors */
extern void reply_with_error (const char *fs, ...)
__attribute__((format (printf,1,2)));
@@ -225,6 +232,16 @@ extern void reply (xdrproc_t xdrp, char *ret);
} \
while (0)
+/* Marks functions which are not available.
+ * NB. Cannot be used for FileIn functions.
+ */
+#define NOT_AVAILABLE(errcode) \
+ do { \
+ reply_with_error ("%s: function not available", __func__); \
+ return (errcode); \
+ } \
+ while (0)
+
#ifndef __attribute__
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
# define __attribute__(x) /* empty */
diff --git a/daemon/inotify.c b/daemon/inotify.c
index 465d0b6e..24ce76e2 100644
--- a/daemon/inotify.c
+++ b/daemon/inotify.c
@@ -31,6 +31,7 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
#ifdef HAVE_SYS_INOTIFY_H
/* Currently open inotify handle, or -1 if not opened. */
@@ -38,6 +39,18 @@ static int inotify_fd = -1;
static char inotify_buf[64*1024*1024]; /* Event buffer, [0..posn-1] is valid */
static size_t inotify_posn = 0;
+
+int
+optgroup_inotify_available (void)
+{
+ return 1;
+}
+#else /* !HAVE_SYS_INOTIFY_H */
+int
+optgroup_inotify_available (void)
+{
+ return 0;
+}
#endif
/* Because inotify_init does NEED_ROOT, NEED_INOTIFY implies NEED_ROOT. */
@@ -106,8 +119,7 @@ do_inotify_init (int max_events)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -132,8 +144,7 @@ do_inotify_close (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -161,8 +172,7 @@ do_inotify_add_watch (const char *path, int mask)
return r;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -179,8 +189,7 @@ do_inotify_rm_watch (int wd)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -294,8 +303,7 @@ do_inotify_read (void)
free (ret);
return NULL;
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
@@ -371,7 +379,6 @@ do_inotify_files (void)
unlink ("/tmp/inotify");
return NULL;
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 3920e95b..564517c5 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -26,6 +26,14 @@
#include "daemon.h"
#include "c-ctype.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_lvm2_available (void)
+{
+ int r = access ("/sbin/lvm", X_OK);
+ return r == 0;
+}
/* LVM actions. Keep an eye on liblvm, although at the time
* of writing it hasn't progressed very far.
diff --git a/daemon/mknod.c b/daemon/mknod.c
index 6ff88efa..46a18392 100644
--- a/daemon/mknod.c
+++ b/daemon/mknod.c
@@ -29,6 +29,21 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+#ifdef HAVE_MKNOD
+int
+optgroup_mknod_available (void)
+{
+ return 1;
+}
+#else
+int
+optgroup_mknod_available (void)
+{
+ return 0;
+}
+#endif
int
do_mknod (int mode, int devmajor, int devminor, const char *path)
@@ -47,8 +62,7 @@ do_mknod (int mode, int devmajor, int devminor, const char *path)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
diff --git a/daemon/modprobe.c b/daemon/modprobe.c
index 7e3d1b70..ac62b349 100644
--- a/daemon/modprobe.c
+++ b/daemon/modprobe.c
@@ -23,6 +23,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_linuxmodules_available (void)
+{
+ int r = access ("/sbin/modprobe", X_OK);
+ return r == 0;
+}
int
do_modprobe (const char *module)
diff --git a/daemon/ntfs.c b/daemon/ntfs.c
index 85deb654..b3530084 100644
--- a/daemon/ntfs.c
+++ b/daemon/ntfs.c
@@ -25,6 +25,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_ntfs3g_available (void)
+{
+ int r = access ("/bin/ntfs-3g.probe", X_OK);
+ return r == 0;
+}
int
do_ntfs_3g_probe (int rw, const char *device)
diff --git a/daemon/scrub.c b/daemon/scrub.c
index 15c8b6c2..e37a1e11 100644
--- a/daemon/scrub.c
+++ b/daemon/scrub.c
@@ -26,6 +26,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_scrub_available (void)
+{
+ int r = access ("/usr/bin/scrub", X_OK);
+ return r == 0;
+}
int
do_scrub_device (const char *device)
diff --git a/daemon/selinux.c b/daemon/selinux.c
index 3b4b9ba6..e49e657b 100644
--- a/daemon/selinux.c
+++ b/daemon/selinux.c
@@ -29,6 +29,21 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+#if defined(HAVE_LIBSELINUX)
+int
+optgroup_selinux_available (void)
+{
+ return 1;
+}
+#else /* !HAVE_LIBSELINUX */
+int
+optgroup_selinux_available (void)
+{
+ return 0;
+}
+#endif /* !HAVE_LIBSELINUX */
/* setcon is only valid under the following circumstances:
* - single threaded
@@ -45,8 +60,7 @@ do_setcon (const char *context)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -71,7 +85,6 @@ do_getcon (void)
return r; /* caller frees */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
diff --git a/daemon/swap.c b/daemon/swap.c
index bcc5f1b1..2d3d9ff4 100644
--- a/daemon/swap.c
+++ b/daemon/swap.c
@@ -26,6 +26,25 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+/* Convenient place to test for the later version of e2fsprogs
+ * and util-linux which supports -U parameters to specify UUIDs.
+ * (Not supported in RHEL 5).
+ */
+int
+optgroup_linuxfsuuid_available (void)
+{
+ char *err;
+ int av;
+
+ /* Ignore return code - mkswap --help *will* fail. */
+ command (NULL, &err, "/sbin/mkswap", "--help", NULL);
+
+ av = strstr (err, "-U") != NULL;
+ free (err);
+ return av;
+}
static int
mkswap (const char *device, const char *flag, const char *value)
diff --git a/daemon/xattr.c b/daemon/xattr.c
index c218dea1..e58dc7ea 100644
--- a/daemon/xattr.c
+++ b/daemon/xattr.c
@@ -24,16 +24,23 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
#if defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
-#ifdef HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#else
-#ifdef HAVE_SYS_XATTR_H
-#include <sys/xattr.h>
-#endif
-#endif
+# ifdef HAVE_ATTR_XATTR_H
+# include <attr/xattr.h>
+# else
+# ifdef HAVE_SYS_XATTR_H
+# include <sys/xattr.h>
+# endif
+# endif
+
+int
+optgroup_linuxxattrs_available (void)
+{
+ return 1;
+}
static guestfs_int_xattr_list *getxattrs (const char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t (*getxattr) (const char *path, const char *name, void *value, size_t size));
static int _setxattr (const char *xattr, const char *val, int vallen, const char *path, int (*setxattr) (const char *path, const char *name, const void *value, size_t size, int flags));
@@ -442,54 +449,52 @@ do_lxattrlist (const char *path, char *const *names)
}
#else /* no xattr.h */
+int
+optgroup_linuxxattrs_available (void)
+{
+ return 0;
+}
guestfs_int_xattr_list *
do_getxattrs (const char *path)
{
- reply_with_error ("getxattrs: no support for xattrs");
- return NULL;
+ NOT_AVAILABLE (NULL);
}
guestfs_int_xattr_list *
do_lgetxattrs (const char *path)
{
- reply_with_error ("lgetxattrs: no support for xattrs");
- return NULL;
+ NOT_AVAILABLE (NULL);
}
int
do_setxattr (const char *xattr, const char *val, int vallen, const char *path)
{
- reply_with_error ("setxattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
int
do_lsetxattr (const char *xattr, const char *val, int vallen, const char *path)
{
- reply_with_error ("lsetxattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
int
do_removexattr (const char *xattr, const char *path)
{
- reply_with_error ("removexattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
int
do_lremovexattr (const char *xattr, const char *path)
{
- reply_with_error ("lremovexattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
guestfs_int_xattr_list *
do_lxattrlist (const char *path, char *const *names)
{
- reply_with_error ("lxattrlist: no support for xattrs");
- return NULL;
+ NOT_AVAILABLE (NULL);
}
#endif /* no xattr.h */
diff --git a/daemon/zerofree.c b/daemon/zerofree.c
index ffb9b70b..05a547bd 100644
--- a/daemon/zerofree.c
+++ b/daemon/zerofree.c
@@ -26,6 +26,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_zerofree_available (void)
+{
+ int r = access ("/usr/sbin/zerofree", X_OK);
+ return r == 0;
+}
int
do_zerofree (const char *device)
diff --git a/guestfs.pod b/guestfs.pod
index 0e7079c2..4a477330 100644
--- a/guestfs.pod
+++ b/guestfs.pod
@@ -623,6 +623,13 @@ developer to program in confidence against libguestfs.
@STRUCTS@
+=head1 AVAILABILITY
+
+Using L</guestfs_available> you can test availability of
+the following groups of functions:
+
+@AVAILABILITY@
+
=head1 STATE MACHINE AND LOW-LEVEL EVENT API
Internally, libguestfs is implemented by running a virtual machine
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2c7998d7..7707811f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -37,6 +37,7 @@ daemon/modprobe.c
daemon/mount.c
daemon/names.c
daemon/ntfs.c
+daemon/optgroups.c
daemon/parted.c
daemon/pingdaemon.c
daemon/proto.c
diff --git a/src/generator.ml b/src/generator.ml
index cceb1915..08817c12 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -175,6 +175,7 @@ type flags =
| NotInFish (* do not export via guestfish *)
| NotInDocs (* do not add this function to documentation *)
| DeprecatedBy of string (* function is deprecated, use .. instead *)
+ | Optional of string (* function is part of an optional group *)
(* You can supply zero or as many tests as you want per API call.
*
@@ -979,7 +980,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<guestfs_lvs>.");
- ("pvs", (RStringList "physvols", []), 9, [],
+ ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
[InitBasicFSonLVM, Always, TestOutputListOfDevices (
[["pvs"]], ["/dev/sda1"]);
InitEmpty, Always, TestOutputListOfDevices (
@@ -998,7 +999,7 @@ PVs (eg. C</dev/sda2>).
See also C<guestfs_pvs_full>.");
- ("vgs", (RStringList "volgroups", []), 10, [],
+ ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
[InitBasicFSonLVM, Always, TestOutputList (
[["vgs"]], ["VG"]);
InitEmpty, Always, TestOutputList (
@@ -1019,7 +1020,7 @@ detected (eg. C<VolGroup00>).
See also C<guestfs_vgs_full>.");
- ("lvs", (RStringList "logvols", []), 11, [],
+ ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
[InitBasicFSonLVM, Always, TestOutputList (
[["lvs"]], ["/dev/VG/LV"]);
InitEmpty, Always, TestOutputList (
@@ -1043,21 +1044,21 @@ This returns a list of the logical volume device names
See also C<guestfs_lvs_full>.");
- ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
+ ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
[], (* XXX how to test? *)
"list the LVM physical volumes (PVs)",
"\
List all the physical volumes detected. This is the equivalent
of the L<pvs(8)> command. The \"full\" version includes all fields.");
- ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
+ ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
[], (* XXX how to test? *)
"list the LVM volume groups (VGs)",
"\
List all the volumes groups detected. This is the equivalent
of the L<vgs(8)> command. The \"full\" version includes all fields.");
- ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
+ ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
[], (* XXX how to test? *)
"list the LVM logical volumes (LVs)",
"\
@@ -1081,7 +1082,7 @@ Note that this function cannot correctly handle binary files
as end of line). For those you need to use the C<guestfs_read_file>
function which has a more complex interface.");
- ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
+ ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"create a new Augeas handle",
"\
@@ -1132,7 +1133,7 @@ To close the handle, you can call C<guestfs_aug_close>.
To find out more about Augeas, see L<http://augeas.net/>.");
- ("aug_close", (RErr, []), 26, [],
+ ("aug_close", (RErr, []), 26, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"close the current Augeas handle",
"\
@@ -1141,7 +1142,7 @@ used by it. After calling this, you have to call
C<guestfs_aug_init> again before you can use any other
Augeas functions.");
- ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
+ ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"define an Augeas variable",
"\
@@ -1152,7 +1153,7 @@ 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.");
- ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
+ ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"define an Augeas node",
"\
@@ -1167,20 +1168,20 @@ On success this returns a pair containing the
number of nodes in the nodeset, and a boolean flag
if a node was created.");
- ("aug_get", (RString "val", [String "augpath"]), 19, [],
+ ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"look up the value of an Augeas path",
"\
Look up the value associated with C<path>. If C<path>
matches exactly one node, the C<value> is returned.");
- ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
+ ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"set Augeas path to value",
"\
Set the value associated with C<path> to C<value>.");
- ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
+ ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"insert a sibling Augeas node",
"\
@@ -1192,7 +1193,7 @@ C<path> must match exactly one existing node in the tree, and
C<label> must be a label, ie. not contain C</>, C<*> or end
with a bracketed index C<[N]>.");
- ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
+ ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"remove an Augeas path",
"\
@@ -1200,14 +1201,14 @@ Remove C<path> and all of its children.
On success this returns the number of entries which were removed.");
- ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
+ ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"move Augeas node",
"\
Move the node C<src> to C<dest>. C<src> must match exactly
one node. C<dest> is overwritten if it exists.");
- ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
+ ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"return Augeas nodes which match augpath",
"\
@@ -1215,7 +1216,7 @@ 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.");
- ("aug_save", (RErr, []), 25, [],
+ ("aug_save", (RErr, []), 25, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"write all pending Augeas changes to disk",
"\
@@ -1224,7 +1225,7 @@ This writes all pending changes to disk.
The flags which were passed to C<guestfs_aug_init> affect exactly
how files are saved.");
- ("aug_load", (RErr, []), 27, [],
+ ("aug_load", (RErr, []), 27, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"load files into the tree",
"\
@@ -1233,7 +1234,7 @@ Load files into the tree.
See C<aug_load> in the Augeas documentation for the full gory
details.");
- ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
+ ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
[], (* XXX Augeas code needs tests. *)
"list Augeas nodes under augpath",
"\
@@ -1366,7 +1367,7 @@ other objects like files.
See also C<guestfs_stat>.");
- ("pvcreate", (RErr, [Device "device"]), 39, [],
+ ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
[InitEmpty, Always, TestOutputListOfDevices (
[["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
["pvcreate"; "/dev/sda1"];
@@ -1379,7 +1380,7 @@ 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"; DeviceList "physvols"]), 40, [],
+ ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
[InitEmpty, Always, TestOutputList (
[["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
["pvcreate"; "/dev/sda1"];
@@ -1393,7 +1394,7 @@ as C</dev/sda1>.");
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, [],
+ ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
[InitEmpty, Always, TestOutputList (
[["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
["pvcreate"; "/dev/sda1"];
@@ -1544,7 +1545,7 @@ This unmounts all mounted filesystems.
Some internal mounts are not unmounted by this call.");
- ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
+ ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
[],
"remove all LVM LVs, VGs and PVs",
"\
@@ -2035,7 +2036,7 @@ There is no comprehensive help for this command. You have
to look at the file C<daemon/debug.c> in the libguestfs source
to find out what you can do.");
- ("lvremove", (RErr, [Device "device"]), 77, [],
+ ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
[InitEmpty, Always, TestOutputList (
[["part_disk"; "/dev/sda"; "mbr"];
["pvcreate"; "/dev/sda1"];
@@ -2068,7 +2069,7 @@ the path to the LV, such as C</dev/VG/LV>.
You can also remove all LVs in a volume group by specifying
the VG name, C</dev/VG>.");
- ("vgremove", (RErr, [String "vgname"]), 78, [],
+ ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
[InitEmpty, Always, TestOutputList (
[["part_disk"; "/dev/sda"; "mbr"];
["pvcreate"; "/dev/sda1"];
@@ -2092,7 +2093,7 @@ Remove an LVM volume group C<vgname>, (for example C<VG>).
This also forcibly removes all logical volumes in the volume
group (if any).");
- ("pvremove", (RErr, [Device "device"]), 79, [],
+ ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
[InitEmpty, Always, TestOutputListOfDevices (
[["part_disk"; "/dev/sda"; "mbr"];
["pvcreate"; "/dev/sda1"];
@@ -2387,7 +2388,7 @@ The returned strings are transcoded to UTF-8.");
This runs C<hexdump -C> on the given C<path>. The result is
the human-readable, canonical hex dump of the file.");
- ("zerofree", (RErr, [Device "device"]), 97, [],
+ ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
[InitNone, Always, TestOutput (
[["part_disk"; "/dev/sda"; "mbr"];
["mkfs"; "ext3"; "/dev/sda1"];
@@ -2410,7 +2411,7 @@ mounted.
It is possible that using this program can damage the filesystem
or data on the filesystem.");
- ("pvresize", (RErr, [Device "device"]), 98, [],
+ ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
[],
"resize an LVM physical volume",
"\
@@ -2462,7 +2463,7 @@ kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
The result is in human-readable format, and not designed to
be parsed.");
- ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
+ ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
[],
"activate or deactivate all volume groups",
"\
@@ -2474,7 +2475,7 @@ then those devices disappear.
This command is the same as running C<vgchange -a y|n>");
- ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
+ ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
[],
"activate or deactivate some volume groups",
"\
@@ -2489,7 +2490,7 @@ This command is the same as running C<vgchange -a y|n volgroups...>
Note that if C<volgroups> is an empty list then B<all> volume groups
are activated or deactivated.");
- ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
+ ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
[InitNone, Always, TestOutput (
[["part_disk"; "/dev/sda"; "mbr"];
["pvcreate"; "/dev/sda1"];
@@ -2582,7 +2583,7 @@ This command is only needed because of C<guestfs_resize2fs>
"\
Sleep for C<secs> seconds.");
- ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
+ ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
[InitNone, Always, TestOutputInt (
[["part_disk"; "/dev/sda"; "mbr"];
["mkfs"; "ntfs"; "/dev/sda1"];
@@ -2664,7 +2665,7 @@ It is just a wrapper around the C L<glob(3)> function
with flags C<GLOB_MARK|GLOB_BRACE>.
See that manual page for more details.");
- ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
+ ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
[InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
[["scrub_device"; "/dev/sdc"]])],
"scrub (securely wipe) a device",
@@ -2675,7 +2676,7 @@ more difficult.
It is an interface to the L<scrub(1)> program. See that
manual page for more details.");
- ("scrub_file", (RErr, [Pathname "file"]), 115, [],
+ ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
[InitBasicFS, Always, TestRun (
[["write_file"; "/file"; "content"; "0"];
["scrub_file"; "/file"]])],
@@ -2689,7 +2690,7 @@ The file is I<removed> after scrubbing.
It is an interface to the L<scrub(1)> program. See that
manual page for more details.");
- ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
+ ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
[], (* XXX needs testing *)
"scrub (securely wipe) free space",
"\
@@ -2884,7 +2885,7 @@ Note that you cannot attach a swap label to a block device
(eg. C</dev/sda>), just to a partition. This appears to be
a limitation of the kernel or swap tools.");
- ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
+ ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
(let uuid = uuidgen () in
[InitEmpty, Always, TestRun (
[["part_disk"; "/dev/sda"; "mbr"];
@@ -2893,7 +2894,7 @@ a limitation of the kernel or swap tools.");
"\
Create a swap partition on C<device> with UUID C<uuid>.");
- ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
+ ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
[InitBasicFS, Always, TestOutputStruct (
[["mknod"; "0o10777"; "0"; "0"; "/node"];
(* NB: default umask 022 means 0777 -> 0755 in these tests *)
@@ -2911,7 +2912,7 @@ constants. C<devmajor> and C<devminor> are the
device major and minor numbers, only used when creating block
and character special devices.");
- ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
+ ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
[InitBasicFS, Always, TestOutputStruct (
[["mkfifo"; "0o777"; "/node"];
["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
@@ -2921,7 +2922,7 @@ This call creates a FIFO (named pipe) called C<path> with
mode C<mode>. It is just a convenient wrapper around
C<guestfs_mknod>.");
- ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
+ ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
[InitBasicFS, Always, TestOutputStruct (
[["mknod_b"; "0o777"; "99"; "66"; "/node"];
["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
@@ -2931,7 +2932,7 @@ This call creates a block device node called C<path> with
mode C<mode> and device major/minor C<devmajor> and C<devminor>.
It is just a convenient wrapper around C<guestfs_mknod>.");
- ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
+ ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
[InitBasicFS, Always, TestOutputStruct (
[["mknod_c"; "0o777"; "99"; "66"; "/node"];
["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
@@ -3046,7 +3047,7 @@ C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
Since 1.0.63, use C<guestfs_file> instead which can now
process compressed files.");
- ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
+ ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
[],
"list extended attributes of a file or directory",
"\
@@ -3058,7 +3059,7 @@ L<listxattr(2)> and L<getxattr(2)> calls.
See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
- ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
+ ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
[],
"list extended attributes of a file or directory",
"\
@@ -3068,7 +3069,7 @@ of the link itself.");
("setxattr", (RErr, [String "xattr";
String "val"; Int "vallen"; (* will be BufferIn *)
- Pathname "path"]), 143, [],
+ Pathname "path"]), 143, [Optional "linuxxattrs"],
[],
"set extended attribute of a file or directory",
"\
@@ -3080,7 +3081,7 @@ See also: C<guestfs_lsetxattr>, L<attr(5)>.");
("lsetxattr", (RErr, [String "xattr";
String "val"; Int "vallen"; (* will be BufferIn *)
- Pathname "path"]), 144, [],
+ Pathname "path"]), 144, [Optional "linuxxattrs"],
[],
"set extended attribute of a file or directory",
"\
@@ -3088,7 +3089,7 @@ This is the same as C<guestfs_setxattr>, but if C<path>
is a symbolic link, then it sets an extended attribute
of the link itself.");
- ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
+ ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
[],
"remove extended attribute of a file or directory",
"\
@@ -3097,7 +3098,7 @@ of the file C<path>.
See also: C<guestfs_lremovexattr>, L<attr(5)>.");
- ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
+ ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
[],
"remove extended attribute of a file or directory",
"\
@@ -3397,7 +3398,7 @@ See C<guestfs_swapon_device> for other notes.");
This command disables the libguestfs appliance swap on
labeled swap partition.");
- ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
+ ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
(let uuid = uuidgen () in
[InitEmpty, Always, TestRun (
[["mkswap_U"; uuid; "/dev/sdb"];
@@ -3408,7 +3409,7 @@ labeled swap partition.");
This command enables swap to a swap partition with the given UUID.
See C<guestfs_swapon_device> for other notes.");
- ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
+ ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
[], (* XXX tested by swapon_uuid *)
"disable swap on swap partition by UUID",
"\
@@ -3426,7 +3427,7 @@ Create a swap file.
This command just writes a swap file signature to an existing
file. To create the file itself, use something like C<guestfs_fallocate>.");
- ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
+ ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
[InitISOFS, Always, TestRun (
[["inotify_init"; "0"]])],
"create an inotify handle",
@@ -3467,7 +3468,7 @@ as exposed by the Linux kernel, which is roughly what we expose
via libguestfs. Note that there is one global inotify handle
per libguestfs instance.");
- ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
+ ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
[InitBasicFS, Always, TestOutputList (
[["inotify_init"; "0"];
["inotify_add_watch"; "/"; "1073741823"];
@@ -3486,14 +3487,14 @@ Note for non-C or non-Linux callers: the inotify events are
defined by the Linux kernel ABI and are listed in
C</usr/include/sys/inotify.h>.");
- ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
+ ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
[],
"remove an inotify watch",
"\
Remove a previously defined inotify watch.
See C<guestfs_inotify_add_watch>.");
- ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
+ ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
[],
"return list of inotify events",
"\
@@ -3508,7 +3509,7 @@ returns an empty list. The reason is that the call will
read events up to the maximum appliance-to-host message
size and leave remaining events in the queue.");
- ("inotify_files", (RStringList "paths", []), 183, [],
+ ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
[],
"return list of watched files that had events",
"\
@@ -3516,7 +3517,7 @@ This function is a helpful wrapper around C<guestfs_inotify_read>
which just returns a list of pathnames of objects that were
touched. The returned pathnames are sorted and deduplicated.");
- ("inotify_close", (RErr, []), 184, [],
+ ("inotify_close", (RErr, []), 184, [Optional "inotify"],
[],
"close the inotify handle",
"\
@@ -3524,7 +3525,7 @@ This closes the inotify handle which was previously
opened by inotify_init. It removes all watches, throws
away any pending events, and deallocates all resources.");
- ("setcon", (RErr, [String "context"]), 185, [],
+ ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
[],
"set SELinux security context",
"\
@@ -3533,7 +3534,7 @@ to the string C<context>.
See the documentation about SELINUX in L<guestfs(3)>.");
- ("getcon", (RString "context", []), 186, [],
+ ("getcon", (RString "context", []), 186, [Optional "selinux"],
[],
"get SELinux security context",
"\
@@ -3583,7 +3584,7 @@ to the command:
"\
This creates an ext2 external journal on C<device> with label C<label>.");
- ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
+ ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
(let uuid = uuidgen () in
[InitEmpty, Always, TestOutput (
[["sfdiskM"; "/dev/sda"; ",100 ,"];
@@ -3617,7 +3618,7 @@ an external journal on the journal labeled C<label>.
See also C<guestfs_mke2journal_L>.");
- ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
+ ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
[],
"make ext2/3/4 filesystem with external journal",
"\
@@ -3626,7 +3627,7 @@ an external journal on the journal with UUID C<uuid>.
See also C<guestfs_mke2journal_U>.");
- ("modprobe", (RErr, [String "modulename"]), 194, [],
+ ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
[InitNone, Always, TestRun [["modprobe"; "fat"]]],
"load a kernel module",
"\
@@ -3838,7 +3839,7 @@ might cause the protocol message size to be exceeded, causing
this call to fail. The caller must split up such requests
into smaller groups of names.");
- ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
+ ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
[], (* XXX *)
"lgetxattr on multiple files",
"\
@@ -4115,8 +4116,8 @@ The precise libguestfs function groups that may be checked by this
command are listed in L<guestfs(3)/AVAILABILITY>.
The argument C<groups> is a list of API group names, eg:
-C<[\"inotify\", \"part\"]> would check for the availability of
-the C<guestfs_inotify_*> functions and C<guestfs_part_*>
+C<[\"inotify\", \"augeas\"]> would check for the availability of
+the C<guestfs_inotify_*> functions and C<guestfs_aug_*>
(partition editing) functions.
The command returns no error if I<all> requested groups are available.
@@ -4596,6 +4597,26 @@ with correct use of these functions." alt in
with
Not_found -> None
+(* Create list of optional groups. *)
+let optgroups =
+ let h = Hashtbl.create 13 in
+ List.iter (
+ fun (name, _, _, flags, _, _, _) ->
+ List.iter (
+ function
+ | Optional group ->
+ let names = try Hashtbl.find h group with Not_found -> [] in
+ Hashtbl.replace h group (name :: names)
+ | _ -> ()
+ ) flags
+ ) daemon_functions;
+ let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
+ let groups =
+ List.map (
+ fun group -> group, List.sort compare (Hashtbl.find h group)
+ ) groups in
+ List.sort (fun x y -> compare (fst x) (fst y)) groups
+
(* Check function names etc. for consistency. *)
let check_functions () =
let contains_uppercase str =
@@ -4919,6 +4940,21 @@ and generate_structs_pod () =
pr "\n"
) structs
+and generate_availability_pod () =
+ (* Availability documentation. *)
+ pr "=over 4\n";
+ pr "\n";
+ List.iter (
+ fun (group, functions) ->
+ pr "=item B<%s>\n" group;
+ pr "\n";
+ pr "The following functions:\n";
+ List.iter (pr "L</guestfs_%s>\n") functions;
+ pr "\n"
+ ) optgroups;
+ pr "=back\n";
+ pr "\n"
+
(* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
* indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
*
@@ -5934,6 +5970,34 @@ and generate_daemon_names () =
) daemon_functions;
pr "};\n";
+(* Generate the optional groups for the daemon to implement
+ * guestfs_available.
+ *)
+and generate_daemon_optgroups_c () =
+ generate_header CStyle GPLv2;
+
+ pr "#include <config.h>\n";
+ pr "\n";
+ pr "#include \"daemon.h\"\n";
+ pr "#include \"optgroups.h\"\n";
+ pr "\n";
+
+ pr "struct optgroup optgroups[] = {\n";
+ List.iter (
+ fun (group, _) ->
+ pr " { \"%s\", optgroup_%s_available },\n" group group
+ ) optgroups;
+ pr " { NULL, NULL }\n";
+ pr "};\n"
+
+and generate_daemon_optgroups_h () =
+ generate_header CStyle GPLv2;
+
+ List.iter (
+ fun (group, _) ->
+ pr "extern int optgroup_%s_available (void);\n" group
+ ) optgroups
+
(* Generate the tests. *)
and generate_tests () =
generate_header CStyle GPLv2;
@@ -10302,6 +10366,14 @@ Run it from the top source directory using the command
generate_daemon_names ();
close ();
+ let close = output_to "daemon/optgroups.c" in
+ generate_daemon_optgroups_c ();
+ close ();
+
+ let close = output_to "daemon/optgroups.h" in
+ generate_daemon_optgroups_h ();
+ close ();
+
let close = output_to "capitests/tests.c" in
generate_tests ();
close ();
@@ -10326,6 +10398,10 @@ Run it from the top source directory using the command
generate_actions_pod ();
close ();
+ let close = output_to "guestfs-availability.pod" in
+ generate_availability_pod ();
+ close ();
+
let close = output_to "guestfish-actions.pod" in
generate_fish_actions_pod ();
close ();