diff options
author | Richard Jones <rjones@redhat.com> | 2009-04-09 13:19:38 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-04-09 13:19:38 +0100 |
commit | e7eca50046e9a69dac27c0bee832af0a3014e02c (patch) | |
tree | 0d3adfb16768d7068e180dba7cc49c706ece38f3 /daemon | |
parent | a2e1d51acda406fd4193f121ac9f879e60cf4302 (diff) | |
download | libguestfs-e7eca50046e9a69dac27c0bee832af0a3014e02c.tar.gz libguestfs-e7eca50046e9a69dac27c0bee832af0a3014e02c.tar.xz libguestfs-e7eca50046e9a69dac27c0bee832af0a3014e02c.zip |
Added Augeas support.
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/actions.h | 30 | ||||
-rw-r--r-- | daemon/augeas.c | 278 | ||||
-rw-r--r-- | daemon/configure.ac | 7 | ||||
-rw-r--r-- | daemon/stubs.c | 316 |
5 files changed, 613 insertions, 19 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 4d56034d..bdeeacfe 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 01fe68d6..6a41c7d0 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 00000000..2b273875 --- /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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <augeas.h> + +#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 af0a78af..7ce03ab5 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 fab115c0..38aea33f 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); } |