summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-04-09 13:19:38 +0100
committerRichard Jones <rjones@redhat.com>2009-04-09 13:19:38 +0100
commite7eca50046e9a69dac27c0bee832af0a3014e02c (patch)
tree0d3adfb16768d7068e180dba7cc49c706ece38f3 /daemon
parenta2e1d51acda406fd4193f121ac9f879e60cf4302 (diff)
downloadlibguestfs-e7eca50046e9a69dac27c0bee832af0a3014e02c.tar.gz
libguestfs-e7eca50046e9a69dac27c0bee832af0a3014e02c.tar.xz
libguestfs-e7eca50046e9a69dac27c0bee832af0a3014e02c.zip
Added Augeas support.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am1
-rw-r--r--daemon/actions.h30
-rw-r--r--daemon/augeas.c278
-rw-r--r--daemon/configure.ac7
-rw-r--r--daemon/stubs.c316
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);
}