diff --git a/.gitignore b/.gitignore index b3869c52b..3348b9795 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 9332a10d3..bbdb0ed41 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 d851e527e..9fa8ddab4 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 b56012cd8..be53d2948 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 b43d18200..77fdfa2c7 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 a1f54a3bb..c6d9d98f7 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 120c86cc7..7ba75990b 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 465d0b6ec..24ce76e20 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 3920e95b8..564517c58 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 6ff88efab..46a183924 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 7e3d1b70c..ac62b349e 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 85deb654e..b35300848 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 15c8b6c26..e37a1e110 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 3b4b9ba61..e49e657bd 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 bcc5f1b13..2d3d9ff41 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 c218dea10..e58dc7ea6 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 -#else -#ifdef HAVE_SYS_XATTR_H -#include -#endif -#endif +# ifdef HAVE_ATTR_XATTR_H +# include +# else +# ifdef HAVE_SYS_XATTR_H +# include +# 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 ffb9b70b5..05a547bd5 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 0e7079c23..4a477330f 100644 --- a/guestfs.pod +++ b/guestfs.pod @@ -623,6 +623,13 @@ developer to program in confidence against libguestfs. @STRUCTS@ +=head1 AVAILABILITY + +Using L 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 2c7998d76..7707811f2 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 cceb19152..08817c127 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 This does not return logical volumes. For that you will need to call C."); - ("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). See also C."); - ("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). See also C."); - ("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."); - ("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 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 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 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. To find out more about Augeas, see L."); - ("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 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, or C<0> if C 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. If C matches exactly one node, the C 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 to C."); - ("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 must match exactly one existing node in the tree, and C