[augeas-devel] [PATCH] Add aug_to_xml public API call. Add print-xml command to augtool.

Raphaël Pinson raphink at gmail.com
Mon Oct 31 14:51:56 UTC 2011


Hi all,


Some time ago, I had made a patch to add an aug_to_xml call to Augeas [0].
I wanted to wait to be done with xml_to_aug before committing it, but this
is taking too long, so here is aug_to_xml, rebased on the dev branch.

The patch makes Augeas depend on libxml2 as had been discussed back then.
It adds an aug_to_xml public call, as well as a print-xml command in
augtool.


Raphaël


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

---
 configure.ac           |    3 +
 src/Makefile.am        |    6 +-
 src/augeas.c           |  127
++++++++++++++++++++++++++++++++++++++++++++++++
 src/augeas.h           |   24 +++++++++
 src/augeas_sym.version |    5 ++
 src/augrun.c           |   39 +++++++++++++++
 tests/Makefile.am      |   14 +++---
 7 files changed, 208 insertions(+), 10 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 35721fc..159c927 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";
@@ -1446,6 +1447,132 @@ 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(struct augeas *aug, const char *pathin,
+               xmlNode **xmldoc, unsigned int flags) {
+    struct pathx *p;
+    int result;
+
+    api_entry(aug);
+
+    if (pathin == NULL || strlen(pathin) == 0) {
+        pathin = "/*";
+    }
+
+    p = pathx_aug_parse(aug, aug->origin, 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 0a148ac..1c56656 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,29 @@ 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(augeas *aug, const char *path, xmlNode **xmldoc,
+               unsigned int flags);
+
+/* Function: aug_from_xml
+ *
+ * Import an xmlNodePtr structure back into the Augeas tree.
+ *
+ * Returns:
+ * 0 on success, or a negative value on failure
+ *
+ */
+int aug_from_xml(augeas *aug, 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 901c150..3a5ac77 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)
@@ -797,6 +798,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);
@@ -900,6 +938,7 @@ static const struct command_def const *commands[] = {
     &cmd_match_def,
     &cmd_mv_def,
     &cmd_print_def,
+    &cmd_print_xml_def,
     &cmd_rm_def,
     &cmd_save_def,
     &cmd_set_def,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5588303..cb981ad 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 \
@@ -162,22 +162,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.0.4
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/augeas-devel/attachments/20111031/adec3e04/attachment.htm>


More information about the augeas-devel mailing list