[augeas-devel] [PATCH] Add aug_to_xml to the public API.

Raphaël Pinson raphink at gmail.com
Tue Nov 29 08:19:38 UTC 2011


Hello,


This patch adds aug_to_xml to the public API.

This is a revision of the patch previously sent to the list [0], which didn't apply properly.


Cheers

Raphaël


[0] https://www.redhat.com/archives/augeas-devel/2011-October/msg00068.html

---
 configure.ac           |    3 +
 src/Makefile.am        |    6 +-
 src/augeas.c           |  125 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/augeas.h           |   13 +++++
 src/augeas_sym.version |    5 ++
 src/augrun.c           |   39 +++++++++++++++
 src/augtool.c          |    2 +-
 tests/Makefile.am      |   14 +++---
 8 files changed, 196 insertions(+), 11 deletions(-)

diff --git a/configure.ac b/configure.ac
index 7a839dc..dfb79c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -104,6 +104,9 @@ AM_CONDITIONAL([USE_VERSION_SCRIPT], [test -n "$VERSION_SCRIPT_FLAGS"])
 
 gl_INIT
 
+PKG_PROG_PKG_CONFIG
+PKG_CHECK_MODULES([LIBXML], [libxml-2.0])
+
 AC_CHECK_FUNCS([strerror_r fsync])
 
 AC_OUTPUT(Makefile \
diff --git a/src/Makefile.am b/src/Makefile.am
index 24f122e..e0be7ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
 GNULIB= ../gnulib/lib/libgnu.la
 GNULIB_CFLAGS= -I $(top_srcdir)/gnulib/lib
 
-AM_CFLAGS = @AUGEAS_CFLAGS@ @WARN_CFLAGS@ $(GNULIB_CFLAGS)
+AM_CFLAGS = @AUGEAS_CFLAGS@ @WARN_CFLAGS@ $(GNULIB_CFLAGS) $(LIBXML_CFLAGS)
 
 AM_YFLAGS=-d -p spec_
 
@@ -38,10 +38,10 @@ libaugeas_la_LDFLAGS = $(AUGEAS_VERSION_SCRIPT) \
 libaugeas_la_LIBADD = liblexer.la libfa.la $(LIB_SELINUX) $(GNULIB)
 
 augtool_SOURCES = augtool.c
-augtool_LDADD = libaugeas.la $(READLINE_LIBS) $(GNULIB)
+augtool_LDADD = libaugeas.la $(READLINE_LIBS) $(LIBXML_LIBS) $(GNULIB)
 
 augparse_SOURCES = augparse.c
-augparse_LDADD = libaugeas.la $(GNULIB)
+augparse_LDADD = libaugeas.la $(LIBXML_LIBS) $(GNULIB)
 
 libfa_la_SOURCES = fa.c fa.h hash.c hash.h memory.c memory.h ref.h ref.c
 libfa_la_LIBADD = $(LIB_SELINUX) $(GNULIB)
diff --git a/src/augeas.c b/src/augeas.c
index bd66041..789ef95 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <locale.h>
+#include <libxml/tree.h>
 
 /* Some popular labels that we use in /augeas */
 static const char *const s_augeas = "augeas";
@@ -1492,6 +1493,130 @@ int dump_tree(FILE *out, struct tree *tree) {
     return result;
 }
 
+static int to_xml_one(xmlNodePtr elem, const struct tree *tree,
+                      const char *pathin) {
+    xmlNodePtr value;
+    xmlAttrPtr prop;
+
+    prop = xmlSetProp(elem, BAD_CAST "label", BAD_CAST tree->label);
+    if (prop == NULL)
+        goto error;
+
+    if (tree->span) {
+        prop = xmlSetProp(elem, BAD_CAST "file",
+                          BAD_CAST tree->span->filename->str);
+        if (prop == NULL)
+            goto error;
+    }
+
+    if (pathin != NULL) {
+        prop = xmlSetProp(elem, BAD_CAST "path", BAD_CAST pathin);
+        if (prop == NULL)
+            goto error;
+    }
+    if (tree->value != NULL) {
+        value = xmlNewTextChild(elem, NULL, BAD_CAST "value",
+                                BAD_CAST tree->value);
+        if (value == NULL)
+            goto error;
+    }
+    return 0;
+ error:
+    return -1;
+}
+
+static int to_xml_rec(xmlNodePtr pnode, struct tree *start,
+                      const char *pathin) {
+    int r;
+    char *path = NULL, *ppath = NULL;
+    xmlNodePtr elem;
+
+    elem = xmlNewChild(pnode, NULL, BAD_CAST "node", NULL);
+    if (elem == NULL)
+        goto error;
+    r = to_xml_one(elem, start, pathin);
+    if (r < 0)
+        goto error;
+
+    ppath = path_of_tree(start);
+    list_for_each(tree, start->children) {
+        if (TREE_HIDDEN(tree))
+            continue;
+        path = path_expand(tree, ppath);
+        if (path == NULL)
+            goto error;
+        r = to_xml_rec(elem, tree, NULL);
+        FREE(path);
+        if (r < 0)
+            goto error;
+    }
+
+    free(ppath);
+    return 0;
+ error:
+    free(path);
+    free(ppath);
+    return -1;
+}
+
+static int tree_to_xml(struct pathx *p, xmlNode **xml, const char *pathin) {
+    char *path = NULL;
+    struct tree *tree;
+    xmlAttrPtr expr;
+    int r;
+
+    *xml = NULL;
+
+    *xml = xmlNewNode(NULL, BAD_CAST "augeas");
+    if (*xml == NULL)
+        goto error;
+    expr = xmlSetProp(*xml, BAD_CAST "path", BAD_CAST pathin);
+    if (expr == NULL)
+        goto error;
+
+    for (tree = pathx_first(p); tree != NULL; tree = pathx_next(p)) {
+        if (TREE_HIDDEN(tree))
+            continue;
+        path = path_of_tree(tree);
+        if (path == NULL)
+            goto error;
+        r = to_xml_rec(*xml, tree, path);
+        if (r < 0)
+            goto error;
+        FREE(path);
+    }
+    return 0;
+ error:
+    free(path);
+    xmlFree(*xml);
+    *xml = NULL;
+    return -1;
+}
+
+int aug_to_xml(const struct augeas *aug, const char *pathin,
+               xmlNode **xmldoc, unsigned int flags) {
+    struct pathx *p;
+    int result;
+
+    api_entry(aug);
+
+    if (pathin == NULL || strlen(pathin) == 1) {
+        pathin = "/*";
+    }
+
+    p = pathx_aug_parse(aug, aug->origin, tree_root_ctx(aug), pathin, true);
+    ERR_BAIL(aug);
+    result = tree_to_xml(p, xmldoc, pathin);
+    ERR_THROW(result < 0, aug, AUG_ENOMEM, NULL);
+    free_pathx(p);
+    api_exit(aug);
+
+    return result;
+ error:
+    api_exit(aug);
+    return -1;
+}
+
 int aug_print(const struct augeas *aug, FILE *out, const char *pathin) {
     struct pathx *p;
     int result;
diff --git a/src/augeas.h b/src/augeas.h
index 4ae8176..284be76 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -21,6 +21,7 @@
  */
 
 #include <stdio.h>
+#include <libxml/tree.h>
 
 #ifndef AUGEAS_H_
 #define AUGEAS_H_
@@ -298,6 +299,18 @@ int aug_load(augeas *aug);
  */
 int aug_print(const augeas *aug, FILE *out, const char *path);
 
+/* Function: aug_to_xml
+ *
+ * Turn the Augeas tree into a libxml2 xmlNodePtr structure.
+ *
+ * Returns:
+ * 0 on success, or a negative value on failure
+ *
+ * In case of failure, *xmldoc is set to NULL
+ */
+int aug_to_xml(const augeas *aug, const char *path, xmlNode **xmldoc,
+               unsigned int flags);
+
 /*
  * Function: aug_srun
  *
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index 3fc9172..5c29ab7 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -46,3 +46,8 @@ AUGEAS_0.14.0 {
       __aug_init_memstream;
       __aug_close_memstream;
 } AUGEAS_0.12.0;
+
+AUGEAS_0.15.0 {
+    global:
+      aug_to_xml;
+} AUGEAS_0.14.0;
diff --git a/src/augrun.c b/src/augrun.c
index f73205a..2cee8ae 100644
--- a/src/augrun.c
+++ b/src/augrun.c
@@ -27,6 +27,7 @@
 #include "errcode.h"
 
 #include <ctype.h>
+#include <libxml/tree.h>
 
 static char *cleanstr(char *path, const char sep) {
     if (path == NULL || strlen(path) == 0)
@@ -808,6 +809,43 @@ static const struct command_def cmd_print_def = {
     .help = "Print entries in the tree.  If PATH is given, printing starts there,\n otherwise the whole tree is printed"
 };
 
+static void cmd_print_xml(struct command *cmd) {
+    const char *path = arg_value(cmd, "path");
+    const char *filename = arg_value(cmd, "filename");
+    xmlNodePtr xmldoc;
+    int r;
+
+    r = aug_to_xml(cmd->aug, path, &xmldoc, 0);
+    if (r < 0)
+        ERR_REPORT(cmd, AUG_ECMDRUN,
+                   "XML export of path %s to file %s failed", path, filename);
+
+    xmlElemDump(stdout, NULL, xmldoc);
+    printf("\n");
+
+    if (filename != NULL) {
+        printf("Saving to %s\n", filename);
+    }
+
+    xmlFreeNode(xmldoc);
+}
+
+static const struct command_opt_def cmd_print_xml_opts[] = {
+    { .type = CMD_PATH, .name = "path", .optional = true,
+      .help = "print this subtree" },
+    { .type = CMD_NONE, .name = "filename", .optional = true,
+      .help = "save to this file" },
+    CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_print_xml_def = {
+    .name = "print-xml",
+    .opts = cmd_print_xml_opts,
+    .handler = cmd_print_xml,
+    .synopsis = "print a subtree as XML",
+    .help = "Export entries in the tree as XML. If PATH is given, printing starts there,\n otherwise the whole tree is printed.\n  If FILENAME is given, the XML is saved to the given file."
+};
+
 static void cmd_save(struct command *cmd) {
     int r;
     r = aug_save(cmd->aug);
@@ -924,6 +962,7 @@ static const struct command_def const *commands[] = {
     &cmd_mv_def,
     &cmd_move_def,
     &cmd_print_def,
+    &cmd_print_xml_def,
     &cmd_rm_def,
     &cmd_save_def,
     &cmd_set_def,
diff --git a/src/augtool.c b/src/augtool.c
index ee2f99c..59268dd 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -167,7 +167,7 @@ static char *readline_command_generator(const char *text, int state) {
     static const char *const commands[] = {
         "quit", "clear", "defnode", "defvar",
         "get", "ins", "load", "ls", "match",
-        "mv", "print", "rm", "save", "set", "setm",
+        "mv", "print", "print-xml", "rm", "save", "set", "setm",
         "clearm", "span", "help", NULL };
 
     static int current = 0;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8ecdb59..2372257 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,7 +2,7 @@ GNULIB= ../gnulib/lib/libgnu.la
 GNULIB_CFLAGS= -I $(top_srcdir)/gnulib/lib
 
 AM_CFLAGS = $(AUGEAS_CFLAGS) $(WARN_CFLAGS) $(GNULIB_CFLAGS) \
-	-I $(top_builddir)/src
+	 $(LIBXML_CFLAGS) -I $(top_builddir)/src
 
 valgrind:
 	make check \
@@ -175,22 +175,22 @@ TESTS = $(check_SCRIPTS) $(check_PROGRAMS)
 INCLUDES = -I$(top_srcdir)/src
 
 fatest_SOURCES = fatest.c cutest.c cutest.h $(top_srcdir)/src/memory.c $(top_srcdir)/src/memory.h
-fatest_LDADD = $(top_builddir)/src/libaugeas.la $(GNULIB)
+fatest_LDADD = $(top_builddir)/src/libaugeas.la $(LIBXML_CFLAGS) $(GNULIB)
 
 test_xpath_SOURCES = test-xpath.c $(top_srcdir)/src/memory.c
-test_xpath_LDADD = $(top_builddir)/src/libaugeas.la $(GNULIB)
+test_xpath_LDADD = $(top_builddir)/src/libaugeas.la $(LIBXML_CFLAGS) $(GNULIB)
 
 test_load_SOURCES = test-load.c cutest.c cutest.h $(top_srcdir)/src/memory.c $(top_srcdir)/src/memory.h
-test_load_LDADD = $(top_builddir)/src/libaugeas.la $(GNULIB)
+test_load_LDADD = $(top_builddir)/src/libaugeas.la $(LIBXML_CFLAGS) $(GNULIB)
 
 test_save_SOURCES = test-save.c cutest.c cutest.h $(top_srcdir)/src/memory.c $(top_srcdir)/src/memory.h
-test_save_LDADD = $(top_builddir)/src/libaugeas.la $(GNULIB)
+test_save_LDADD = $(top_builddir)/src/libaugeas.la $(LIBXML_CFLAGS) $(GNULIB)
 
 test_api_SOURCES = test-api.c cutest.c cutest.h $(top_srcdir)/src/memory.c $(top_srcdir)/src/memory.h
-test_api_LDADD = $(top_builddir)/src/libaugeas.la $(GNULIB)
+test_api_LDADD = $(top_builddir)/src/libaugeas.la $(LIBXML_CFLAGS) $(GNULIB)
 
 test_run_SOURCES = test-run.c cutest.c cutest.h $(top_srcdir)/src/memory.c $(top_srcdir)/src/memory.h
-test_run_LDADD = $(top_builddir)/src/libaugeas.la $(GNULIB)
+test_run_LDADD = $(top_builddir)/src/libaugeas.la $(LIBXML_CFLAGS) $(GNULIB)
 
 FAILMALLOC_START ?= 1
 FAILMALLOC_REP   ?= 20
-- 
1.7.5.4




More information about the augeas-devel mailing list