From e7eca50046e9a69dac27c0bee832af0a3014e02c Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 9 Apr 2009 13:19:38 +0100 Subject: [PATCH] Added Augeas support. --- README | 2 + configure.ac | 14 +- daemon/Makefile.am | 1 + daemon/actions.h | 30 +- daemon/augeas.c | 278 +++++++++++++++ daemon/configure.ac | 7 +- daemon/stubs.c | 316 ++++++++++++++++- fish/cmds.c | 276 +++++++++++++++ guestfish-actions.pod | 152 ++++++++ guestfs-actions.pod | 203 ++++++++++- libguestfs.spec.in | 3 +- make-initramfs.sh.in | 4 +- ocaml/guestfs.ml | 12 + ocaml/guestfs.mli | 36 ++ ocaml/guestfs_c_actions.c | 293 +++++++++++++++- perl/Guestfs.xs | 138 ++++++++ perl/lib/Sys/Guestfs.pm | 128 +++++++ src/generator.ml | 410 +++++++++++++++++----- src/guestfs-actions.c | 862 ++++++++++++++++++++++++++++++++++++++++++++++ src/guestfs-actions.h | 12 + src/guestfs-structs.h | 5 + src/guestfs.c | 6 + src/guestfs.h | 1 + src/guestfs_protocol.c | 159 +++++++++ src/guestfs_protocol.h | 124 ++++++- src/guestfs_protocol.x | 107 ++++-- 26 files changed, 3441 insertions(+), 138 deletions(-) create mode 100644 daemon/augeas.c diff --git a/README b/README index f90bf46..ecb5362 100644 --- a/README +++ b/README @@ -35,6 +35,8 @@ Requirements - XDR, rpcgen +- Augeas (http://augeas.net/) + - perldoc (pod2man, pod2text) to generate the manual pages and other documentation. diff --git a/configure.ac b/configure.ac index 0e1df67..7c533eb 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -AC_INIT([libguestfs],[0.6]) +AC_INIT([libguestfs],[0.7]) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) @@ -90,6 +90,18 @@ AC_DEFINE_UNQUOTED([REPO],["$REPO"],[Name of Fedora repository.]) AC_DEFINE_UNQUOTED([host_cpu],["$host_cpu"],[Host architecture.]) +dnl --with-updates to specify a Fedora updates repository. +AC_ARG_WITH([updates], + [AS_HELP_STRING([--with-updates], + [set name of Fedora updates repository @<:@default=updates-released-f10@:>@])], + [], + [with_updates=updates-released-f10]) +UPDATES="$with_updates" +AC_SUBST(UPDATES) +AC_DEFINE_UNQUOTED([UPDATES],["$UPDATES"],[Name of Fedora updates repository.]) + +AC_DEFINE_UNQUOTED([host_cpu],["$host_cpu"],[Host architecture.]) + dnl --with-mirror to specify a local Fedora mirror. AC_ARG_WITH([mirror], [AS_HELP_STRING([--with-mirror], diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 4d56034..bdeeacf 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -20,6 +20,7 @@ ACLOCAL_AMFLAGS = -I m4 noinst_PROGRAMS = guestfsd guestfsd_SOURCES = \ actions.h \ + augeas.c \ daemon.h \ devsparts.c \ file.c \ diff --git a/daemon/actions.h b/daemon/actions.h index 01fe68d..6a41c7d 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -22,17 +22,29 @@ #include "../src/guestfs_protocol.h" extern int do_mount (const char *device, const char *mountpoint); -extern int do_sync (); +extern int do_sync (void); extern int do_touch (const char *path); extern char *do_cat (const char *path); extern char *do_ll (const char *directory); extern char **do_ls (const char *directory); -extern char **do_list_devices (); -extern char **do_list_partitions (); -extern char **do_pvs (); -extern char **do_vgs (); -extern char **do_lvs (); -extern guestfs_lvm_int_pv_list *do_pvs_full (); -extern guestfs_lvm_int_vg_list *do_vgs_full (); -extern guestfs_lvm_int_lv_list *do_lvs_full (); +extern char **do_list_devices (void); +extern char **do_list_partitions (void); +extern char **do_pvs (void); +extern char **do_vgs (void); +extern char **do_lvs (void); +extern guestfs_lvm_int_pv_list *do_pvs_full (void); +extern guestfs_lvm_int_vg_list *do_vgs_full (void); +extern guestfs_lvm_int_lv_list *do_lvs_full (void); extern char **do_read_lines (const char *path); +extern int do_aug_init (const char *root, int flags); +extern int do_aug_close (void); +extern int do_aug_defvar (const char *name, const char *expr); +extern guestfs_aug_defnode_ret *do_aug_defnode (const char *name, const char *expr, const char *val); +extern char *do_aug_get (const char *path); +extern int do_aug_set (const char *path, const char *val); +extern int do_aug_insert (const char *path, const char *label, int before); +extern int do_aug_rm (const char *path); +extern int do_aug_mv (const char *src, const char *dest); +extern char **do_aug_match (const char *path); +extern int do_aug_save (void); +extern int do_aug_load (void); diff --git a/daemon/augeas.c b/daemon/augeas.c new file mode 100644 index 0000000..2b27387 --- /dev/null +++ b/daemon/augeas.c @@ -0,0 +1,278 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include +#include +#include + +#include "daemon.h" +#include "actions.h" + +/* The Augeas handle. We maintain a single handle per daemon, which + * is all that is necessary and reduces the complexity of the API + * considerably. + */ +static augeas *aug = NULL; + +#define NEED_AUG(errcode) \ + do { \ + if (!aug) { \ + reply_with_error ("%s: you must call 'aug-init' first to initialize Augeas", __func__); \ + return (errcode); \ + } \ + } \ + while (0) + +/* We need to rewrite the root path so it is based at /sysroot. */ +int +do_aug_init (const char *root, int flags) +{ + char *buf; + int len; + + NEED_ROOT (-1); + ABS_PATH (root, -1); + + if (aug) { + aug_close (aug); + aug = NULL; + } + + len = strlen (root) + 8; + buf = malloc (len); + if (!buf) { + reply_with_perror ("malloc"); + return -1; + } + snprintf (buf, len, "/sysroot%s", root); + + aug = aug_init (buf, NULL, flags); + free (buf); + + if (!aug) { + reply_with_error ("Augeas initialization failed"); + return -1; + } + + return 0; +} + +int +do_aug_close (void) +{ + NEED_AUG(-1); + + aug_close (aug); + aug = NULL; + + return 0; +} + +int +do_aug_defvar (const char *name, const char *expr) +{ + int r; + + NEED_AUG (-1); + + r = aug_defvar (aug, name, expr); + if (r == -1) { + reply_with_error ("Augeas defvar failed"); + return -1; + } + return r; +} + +guestfs_aug_defnode_ret * +do_aug_defnode (const char *name, const char *expr, const char *val) +{ + static guestfs_aug_defnode_ret r; + int created; + + NEED_AUG (NULL); + + r.nrnodes = aug_defnode (aug, name, expr, val, &created); + if (r.nrnodes == -1) { + reply_with_error ("Augeas defnode failed"); + return NULL; + } + r.created = created; + return &r; +} + +char * +do_aug_get (const char *path) +{ + const char *value = NULL; + char *v; + int r; + + NEED_AUG (NULL); + + r = aug_get (aug, path, &value); + if (r == 0) { + reply_with_error ("no matching node"); + return NULL; + } + if (r != 1) { + reply_with_error ("Augeas get failed"); + return NULL; + } + + /* value can still be NULL here, eg. try with path == "/augeas". + * I don't understand this case, and it seems to contradict the + * documentation. + */ + if (value == NULL) { + reply_with_error ("Augeas returned NULL match"); + return NULL; + } + + /* The value is an internal Augeas string, so we must copy it. GC FTW. */ + v = strdup (value); + if (v == NULL) { + reply_with_perror ("strdup"); + return NULL; + } + + return v; /* Caller frees. */ +} + +int +do_aug_set (const char *path, const char *val) +{ + int r; + + NEED_AUG (-1); + + r = aug_set (aug, path, val); + if (r == -1) { + reply_with_error ("Augeas set failed"); + return -1; + } + + return 0; +} + +int +do_aug_insert (const char *path, const char *label, int before) +{ + int r; + + NEED_AUG (-1); + + r = aug_insert (aug, path, label, before); + if (r == -1) { + reply_with_error ("Augeas insert failed"); + return -1; + } + + return 0; +} + +int +do_aug_rm (const char *path) +{ + int r; + + NEED_AUG (-1); + + r = aug_rm (aug, path); + if (r == -1) { + reply_with_error ("Augeas rm failed"); + return -1; + } + + return r; +} + +int +do_aug_mv (const char *src, const char *dest) +{ + int r; + + NEED_AUG (-1); + + r = aug_mv (aug, src, dest); + if (r == -1) { + reply_with_error ("Augeas mv failed"); + return -1; + } + + return 0; +} + +char ** +do_aug_match (const char *path) +{ + char **matches = NULL; + void *vp; + int r; + + NEED_AUG (NULL); + + r = aug_match (aug, path, &matches); + if (r == -1) { + reply_with_error ("Augeas match failed"); + return NULL; + } + + /* This returns an array of length r, which we must extend + * and add a terminating NULL. + */ + vp = realloc (matches, sizeof (char *) * (r+1)); + if (vp == NULL) { + reply_with_perror ("realloc"); + free (vp); + return NULL; + } + matches = vp; + matches[r] = NULL; + + return matches; /* Caller frees. */ +} + +int +do_aug_save (void) +{ + NEED_AUG (-1); + + if (aug_save (aug) == -1) { + reply_with_error ("Augeas save failed"); + return -1; + } + + return 0; +} + +int +do_aug_load (void) +{ + NEED_AUG (-1); + + if (aug_load (aug) == -1) { + reply_with_error ("Augeas load failed"); + return -1; + } + + return 0; +} diff --git a/daemon/configure.ac b/daemon/configure.ac index af0a78a..7ce03ab 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -AC_INIT([libguestfs-daemon],[0.2]) +AC_INIT([libguestfs-daemon],[0.7]) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) @@ -37,6 +37,11 @@ test "x$U" != "x" && AC_MSG_ERROR([Compiler not ANSI compliant]) AC_PROG_CC_C_O +dnl Check for Augeas. +AC_CHECK_LIB([augeas],[aug_match],,[ + AC_MSG_ERROR([Augeas library not found]) + ]) + dnl Check for XDR library. AC_CHECK_LIB([portablexdr],[xdrmem_create],[],[ AC_SEARCH_LIBS([xdrmem_create],[rpc xdr nsl]) diff --git a/daemon/stubs.c b/daemon/stubs.c index fab115c..38aea33 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -43,7 +43,7 @@ static void mount_stub (XDR *xdr_in) memset (&args, 0, sizeof args); if (!xdr_guestfs_mount_args (xdr_in, &args)) { - reply_with_error ("mount: daemon failed to decode procedure arguments"); + reply_with_error ("%s: daemon failed to decode procedure arguments", "mount"); return; } device = args.device; @@ -78,7 +78,7 @@ static void touch_stub (XDR *xdr_in) memset (&args, 0, sizeof args); if (!xdr_guestfs_touch_args (xdr_in, &args)) { - reply_with_error ("touch: daemon failed to decode procedure arguments"); + reply_with_error ("%s: daemon failed to decode procedure arguments", "touch"); return; } path = args.path; @@ -100,7 +100,7 @@ static void cat_stub (XDR *xdr_in) memset (&args, 0, sizeof args); if (!xdr_guestfs_cat_args (xdr_in, &args)) { - reply_with_error ("cat: daemon failed to decode procedure arguments"); + reply_with_error ("%s: daemon failed to decode procedure arguments", "cat"); return; } path = args.path; @@ -125,7 +125,7 @@ static void ll_stub (XDR *xdr_in) memset (&args, 0, sizeof args); if (!xdr_guestfs_ll_args (xdr_in, &args)) { - reply_with_error ("ll: daemon failed to decode procedure arguments"); + reply_with_error ("%s: daemon failed to decode procedure arguments", "ll"); return; } directory = args.directory; @@ -150,7 +150,7 @@ static void ls_stub (XDR *xdr_in) memset (&args, 0, sizeof args); if (!xdr_guestfs_ls_args (xdr_in, &args)) { - reply_with_error ("ls: daemon failed to decode procedure arguments"); + reply_with_error ("%s: daemon failed to decode procedure arguments", "ls"); return; } directory = args.directory; @@ -258,7 +258,7 @@ static void pvs_full_stub (XDR *xdr_in) struct guestfs_pvs_full_ret ret; ret.physvols = *r; - reply ((xdrproc_t) &xdr_guestfs_pvs_full_ret, (char *) &ret); + reply ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret); xdr_free ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret); } @@ -273,7 +273,7 @@ static void vgs_full_stub (XDR *xdr_in) struct guestfs_vgs_full_ret ret; ret.volgroups = *r; - reply ((xdrproc_t) &xdr_guestfs_vgs_full_ret, (char *) &ret); + reply ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret); xdr_free ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret); } @@ -288,7 +288,7 @@ static void lvs_full_stub (XDR *xdr_in) struct guestfs_lvs_full_ret ret; ret.logvols = *r; - reply ((xdrproc_t) &xdr_guestfs_lvs_full_ret, (char *) &ret); + reply ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret); xdr_free ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret); } @@ -301,7 +301,7 @@ static void read_lines_stub (XDR *xdr_in) memset (&args, 0, sizeof args); if (!xdr_guestfs_read_lines_args (xdr_in, &args)) { - reply_with_error ("read_lines: daemon failed to decode procedure arguments"); + reply_with_error ("%s: daemon failed to decode procedure arguments", "read_lines"); return; } path = args.path; @@ -318,6 +318,268 @@ static void read_lines_stub (XDR *xdr_in) free_strings (r); } +static void aug_init_stub (XDR *xdr_in) +{ + int r; + struct guestfs_aug_init_args args; + const char *root; + int flags; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_init_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_init"); + return; + } + root = args.root; + flags = args.flags; + + r = do_aug_init (root, flags); + if (r == -1) + /* do_aug_init has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void aug_close_stub (XDR *xdr_in) +{ + int r; + + r = do_aug_close (); + if (r == -1) + /* do_aug_close has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void aug_defvar_stub (XDR *xdr_in) +{ + int r; + struct guestfs_aug_defvar_args args; + const char *name; + const char *expr; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_defvar_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_defvar"); + return; + } + name = args.name; + expr = args.expr ? *args.expr : NULL; + + r = do_aug_defvar (name, expr); + if (r == -1) + /* do_aug_defvar has already called reply_with_error, so just return */ + return; + + struct guestfs_aug_defvar_ret ret; + ret.nrnodes = r; + reply ((xdrproc_t) &xdr_guestfs_aug_defvar_ret, (char *) &ret); +} + +static void aug_defnode_stub (XDR *xdr_in) +{ + guestfs_aug_defnode_ret *r; + struct guestfs_aug_defnode_args args; + const char *name; + const char *expr; + const char *val; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_defnode_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_defnode"); + return; + } + name = args.name; + expr = args.expr; + val = args.val; + + r = do_aug_defnode (name, expr, val); + if (r == NULL) + /* do_aug_defnode has already called reply_with_error, so just return */ + return; + + reply ((xdrproc_t) xdr_guestfs_aug_defnode_ret, (char *) r); + xdr_free ((xdrproc_t) xdr_guestfs_aug_defnode_ret, (char *) r); +} + +static void aug_get_stub (XDR *xdr_in) +{ + char *r; + struct guestfs_aug_get_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_get_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_get"); + return; + } + path = args.path; + + r = do_aug_get (path); + if (r == NULL) + /* do_aug_get has already called reply_with_error, so just return */ + return; + + struct guestfs_aug_get_ret ret; + ret.val = r; + reply ((xdrproc_t) &xdr_guestfs_aug_get_ret, (char *) &ret); + free (r); +} + +static void aug_set_stub (XDR *xdr_in) +{ + int r; + struct guestfs_aug_set_args args; + const char *path; + const char *val; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_set_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_set"); + return; + } + path = args.path; + val = args.val; + + r = do_aug_set (path, val); + if (r == -1) + /* do_aug_set has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void aug_insert_stub (XDR *xdr_in) +{ + int r; + struct guestfs_aug_insert_args args; + const char *path; + const char *label; + int before; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_insert_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_insert"); + return; + } + path = args.path; + label = args.label; + before = args.before; + + r = do_aug_insert (path, label, before); + if (r == -1) + /* do_aug_insert has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void aug_rm_stub (XDR *xdr_in) +{ + int r; + struct guestfs_aug_rm_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_rm_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_rm"); + return; + } + path = args.path; + + r = do_aug_rm (path); + if (r == -1) + /* do_aug_rm has already called reply_with_error, so just return */ + return; + + struct guestfs_aug_rm_ret ret; + ret.nrnodes = r; + reply ((xdrproc_t) &xdr_guestfs_aug_rm_ret, (char *) &ret); +} + +static void aug_mv_stub (XDR *xdr_in) +{ + int r; + struct guestfs_aug_mv_args args; + const char *src; + const char *dest; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_mv_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_mv"); + return; + } + src = args.src; + dest = args.dest; + + r = do_aug_mv (src, dest); + if (r == -1) + /* do_aug_mv has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void aug_match_stub (XDR *xdr_in) +{ + char **r; + struct guestfs_aug_match_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_aug_match_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_match"); + return; + } + path = args.path; + + r = do_aug_match (path); + if (r == NULL) + /* do_aug_match has already called reply_with_error, so just return */ + return; + + 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); +} + +static void aug_save_stub (XDR *xdr_in) +{ + int r; + + r = do_aug_save (); + if (r == -1) + /* do_aug_save has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void aug_load_stub (XDR *xdr_in) +{ + int r; + + r = do_aug_load (); + if (r == -1) + /* do_aug_load has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -366,6 +628,42 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_READ_LINES: read_lines_stub (xdr_in); break; + case GUESTFS_PROC_AUG_INIT: + aug_init_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_CLOSE: + aug_close_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_DEFVAR: + aug_defvar_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_DEFNODE: + aug_defnode_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_GET: + aug_get_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_SET: + aug_set_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_INSERT: + aug_insert_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_RM: + aug_rm_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_MV: + aug_mv_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_MATCH: + aug_match_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_SAVE: + aug_save_stub (xdr_in); + break; + case GUESTFS_PROC_AUG_LOAD: + aug_load_stub (xdr_in); + break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr); } diff --git a/fish/cmds.c b/fish/cmds.c index aaf97a8..5c7d553 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -33,6 +33,18 @@ void list_commands (void) list_builtin_commands (); printf ("%-20s %s\n", "add-cdrom", "add a CD-ROM disk image to examine"); printf ("%-20s %s\n", "add-drive", "add an image to examine or modify"); + printf ("%-20s %s\n", "aug-close", "close the current Augeas handle"); + printf ("%-20s %s\n", "aug-defnode", "define an Augeas node"); + printf ("%-20s %s\n", "aug-defvar", "define an Augeas variable"); + printf ("%-20s %s\n", "aug-get", "look up the value of an Augeas path"); + printf ("%-20s %s\n", "aug-init", "create a new Augeas handle"); + printf ("%-20s %s\n", "aug-insert", "insert a sibling Augeas node"); + printf ("%-20s %s\n", "aug-load", "load files into the tree"); + printf ("%-20s %s\n", "aug-match", "return Augeas nodes which match path"); + printf ("%-20s %s\n", "aug-mv", "move Augeas node"); + printf ("%-20s %s\n", "aug-rm", "remove an Augeas path"); + printf ("%-20s %s\n", "aug-save", "write all pending Augeas changes to disk"); + printf ("%-20s %s\n", "aug-set", "set Augeas path to value"); printf ("%-20s %s\n", "cat", "list the contents of a file"); printf ("%-20s %s\n", "config", "add qemu parameters"); printf ("%-20s %s\n", "get-autosync", "get autosync mode"); @@ -140,6 +152,42 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "read_lines") == 0 || strcasecmp (cmd, "read-lines") == 0) pod2text ("read-lines - read file as lines", " read-lines \n\nReturn the contents of the file named C.\n\nThe file contents are returned as a list of lines. Trailing\nC and C character sequences are I returned.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of line). For those you need to use the C\nfunction which has a more complex interface."); else + if (strcasecmp (cmd, "aug_init") == 0 || strcasecmp (cmd, "aug-init") == 0) + pod2text ("aug-init - create a new Augeas handle", " aug-init \n\nCreate a new Augeas handle for editing configuration files.\nIf there was any previous Augeas handle associated with this\nguestfs session, then it is closed.\n\nYou must call this before using any other C\ncommands.\n\nC is the filesystem root. C must not be NULL,\nuse C instead.\n\nThe flags are the same as the flags defined in\nEaugeas.hE, the logical I of the following\nintegers:\n\n=over 4\n\n=item 1 C\n\nKeep the original file with a C<.augsave> extension.\n\n=item 2 C\n\nSave changes into a file with extension C<.augnew>, and\ndo not overwrite original. Overrides C.\n\n=item 4 C\n\nTypecheck lenses (can be expensive).\n\n=item 8 C\n\nDo not use standard load path for modules.\n\n=item 16 C\n\nMake save a no-op, just record what would have been changed.\n\n=item 32 C\n\nDo not load the tree in C.\n\n=back\n\nTo close the handle, you can call C.\n\nTo find out more about Augeas, see L."); + else + if (strcasecmp (cmd, "aug_close") == 0 || strcasecmp (cmd, "aug-close") == 0) + pod2text ("aug-close - close the current Augeas handle", " aug-close\n\nClose the current Augeas handle and free up any resources\nused by it. After calling this, you have to call\nC again before you can use any other\nAugeas functions."); + else + if (strcasecmp (cmd, "aug_defvar") == 0 || strcasecmp (cmd, "aug-defvar") == 0) + pod2text ("aug-defvar - define an Augeas variable", " aug-defvar \n\nDefines an Augeas variable C whose value is the result\nof evaluating C. If C is NULL, then C is\nundefined.\n\nOn success this returns the number of nodes in C, or\nC<0> if C evaluates to something which is not a nodeset."); + else + if (strcasecmp (cmd, "aug_defnode") == 0 || strcasecmp (cmd, "aug-defnode") == 0) + pod2text ("aug-defnode - define an Augeas node", " aug-defnode \n\nDefines a variable C whose value is the result of\nevaluating C.\n\nIf C evaluates to an empty nodeset, a node is created,\nequivalent to calling C C, C.\nC will be the nodeset containing that single node.\n\nOn success this returns a pair containing the\nnumber of nodes in the nodeset, and a boolean flag\nif a node was created."); + else + if (strcasecmp (cmd, "aug_get") == 0 || strcasecmp (cmd, "aug-get") == 0) + pod2text ("aug-get - look up the value of an Augeas path", " aug-get \n\nLook up the value associated with C. If C\nmatches exactly one node, the C is returned."); + else + if (strcasecmp (cmd, "aug_set") == 0 || strcasecmp (cmd, "aug-set") == 0) + pod2text ("aug-set - set Augeas path to value", " aug-set \n\nSet the value associated with C to C."); + else + if (strcasecmp (cmd, "aug_insert") == 0 || strcasecmp (cmd, "aug-insert") == 0) + pod2text ("aug-insert - insert a sibling Augeas node", " aug-insert