/*
* augeas.c: the core data structure for storing key/value pairs
*
- * Copyright (C) 2007-2016 David Lutterkort
+ * Copyright (C) 2007-2017 David Lutterkort
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#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";
static const char *const s_excl = "excl";
static const char *const s_incl = "incl";
-#define TREE_HIDDEN(tree) ((tree)->label == NULL)
-
#define AUGEAS_META_PATHX_FUNC AUGEAS_META_TREE "/version/pathx/functions"
static const char *const static_nodes[][2] = {
return result;
}
-static int to_xml_span(xmlNodePtr elem, const char *pfor, int start, int end) {
- int r;
- char *buf;
- xmlAttrPtr prop;
- xmlNodePtr span_elem;
-
- span_elem = xmlNewChild(elem, NULL, BAD_CAST "span", NULL);
- if (span_elem == NULL)
- return -1;
-
- prop = xmlSetProp(span_elem, BAD_CAST "for", BAD_CAST pfor);
- if (prop == NULL)
- return -1;
-
- /* Format and set the start property */
- r = xasprintf(&buf, "%d", start);
- if (r < 0)
- return -1;
-
- prop = xmlSetProp(span_elem, BAD_CAST "start", BAD_CAST buf);
- FREE(buf);
- if (prop == NULL)
- return -1;
-
- /* Format and set the end property */
- r = xasprintf(&buf, "%d", end);
- if (r < 0)
- return -1;
-
- prop = xmlSetProp(span_elem, BAD_CAST "end", BAD_CAST buf);
- FREE(buf);
- if (prop == NULL)
- return -1;
-
- return 0;
-}
-
-static int to_xml_one(xmlNodePtr elem, const struct tree *tree,
- const char *pathin) {
- xmlNodePtr value;
- xmlAttrPtr prop;
- int r;
-
- prop = xmlSetProp(elem, BAD_CAST "label", BAD_CAST tree->label);
- if (prop == NULL)
- goto error;
-
- if (tree->span) {
- struct span *span = tree->span;
-
- prop = xmlSetProp(elem, BAD_CAST "file",
- BAD_CAST span->filename->str);
- if (prop == NULL)
- goto error;
-
- r = to_xml_span(elem, "label", span->label_start, span->label_end);
- if (r < 0)
- goto error;
-
- r = to_xml_span(elem, "value", span->value_start, span->value_end);
- if (r < 0)
- goto error;
-
- r = to_xml_span(elem, "node", span->span_start, span->span_end);
- if (r < 0)
- 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;
- 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;
-
- list_for_each(tree, start->children) {
- if (TREE_HIDDEN(tree))
- continue;
- r = to_xml_rec(elem, tree, NULL);
- if (r < 0)
- goto error;
- }
-
- return 0;
- error:
- 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 = xmlNewNode(NULL, BAD_CAST "augeas");
- if (*xml == NULL)
- goto error;
- expr = xmlSetProp(*xml, BAD_CAST "match", 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_text_store(augeas *aug, const char *lens, const char *node,
const char *path) {
return -1;
}
-int aug_to_xml(const struct augeas *aug, const char *pathin,
- xmlNode **xmldoc, unsigned int flags) {
- struct pathx *p = NULL;
- int result = -1;
-
- api_entry(aug);
-
- ARG_CHECK(flags != 0, aug, "aug_to_xml: FLAGS must be 0");
- ARG_CHECK(xmldoc == NULL, aug, "aug_to_xml: XMLDOC must be non-NULL");
-
- *xmldoc = NULL;
-
- if (pathin == NULL || strlen(pathin) == 0 || strcmp(pathin, "/") == 0) {
- 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);
-error:
- free_pathx(p);
- api_exit(aug);
-
- return result;
-}
-
int aug_transform(struct augeas *aug, const char *lens,
const char *file, int excl) {
struct tree *meta = tree_child_cr(aug->origin, s_augeas);
return result;
}
+static char *
+tree_source(const augeas *aug, struct tree *tree) {
+ char *result = NULL;
+
+ while (!(ROOT_P(tree) || tree->file))
+ tree = tree->parent;
+
+ if (tree->file) {
+ if (tree->span == NULL) {
+ int r;
+ r = ALLOC(tree->span);
+ ERR_NOMEM(r < 0, aug);
+ tree->span->filename = make_string(path_of_tree(tree));
+ ERR_NOMEM(tree->span->filename == NULL, aug);
+ }
+ result = strdup(tree->span->filename->str);
+ ERR_NOMEM(result == NULL, aug);
+ }
+ error:
+ return result;
+}
+
+int aug_source(const augeas *aug, const char *path, char **file_path) {
+ int result = -1, r;
+ struct pathx *p = NULL;
+ struct tree *match;
+
+ api_entry(aug);
+
+ ARG_CHECK(file_path == NULL, aug,
+ "aug_source_file: FILE_PATH must not be NULL");
+ *file_path = NULL;
+
+ p = pathx_aug_parse(aug, aug->origin, tree_root_ctx(aug), path, true);
+ ERR_BAIL(aug);
+
+ r = pathx_find_one(p, &match);
+ ERR_BAIL(aug);
+ ERR_THROW(r > 1, aug, AUG_EMMATCH, "There are %d nodes matching %s",
+ r, path);
+ ERR_THROW(r == 0, aug, AUG_ENOMATCH, "There is no node matching %s",
+ path);
+
+ *file_path = tree_source(aug, match);
+ ERR_BAIL(aug);
+
+ result = 0;
+ error:
+ free_pathx(p);
+ api_exit(aug);
+ return result;
+}
+
void aug_close(struct augeas *aug) {
if (aug == NULL)
return;
return t1 == t2;
}
+int aug_ns_attr(const augeas* aug, const char *var, int i,
+ const char **value, const char **label, char **file_path) {
+ int result = -1;
+
+ if (value != NULL)
+ *value = NULL;
+
+ if (label != NULL)
+ *label = NULL;
+
+ if (file_path != NULL)
+ *file_path = NULL;
+
+ api_entry(aug);
+
+ struct tree *tree = pathx_symtab_get_tree(aug->symtab, var, i);
+ ERR_THROW(tree == NULL, aug, AUG_ENOMATCH,
+ "Node %s[%d] does not exist", var, i);
+
+ if (file_path != NULL) {
+ *file_path = tree_source(aug, tree);
+ ERR_BAIL(aug);
+ }
+
+ if (value != NULL)
+ *value = tree->value;
+
+ if (label != NULL)
+ *label = tree->label;
+
+ result = 1;
+
+ error:
+ api_exit(aug);
+ return result;
+}
+
+int aug_ns_label(const augeas* aug, const char *var, int i,
+ const char **label, int *index) {
+ int result = -1;
+
+ if (label != NULL)
+ *label = NULL;
+
+ if (index != NULL)
+ *index = -1;
+
+ api_entry(aug);
+
+ struct tree *tree = pathx_symtab_get_tree(aug->symtab, var, i);
+ ERR_THROW(tree == NULL, aug, AUG_ENOMATCH,
+ "Node %s[%d] does not exist", var, i);
+
+ if (label != NULL)
+ *label = tree->label;
+
+ if (index != NULL) {
+ *index = tree_sibling_index(tree);
+ }
+
+ result = 1;
+
+ error:
+ api_exit(aug);
+ return result;
+}
+
+int aug_ns_value(const augeas* aug, const char *var, int i,
+ const char **value) {
+ int result = -1;
+
+ if (value != NULL)
+ *value = NULL;
+
+ api_entry(aug);
+
+ struct tree *tree = pathx_symtab_get_tree(aug->symtab, var, i);
+ ERR_THROW(tree == NULL, aug, AUG_ENOMATCH,
+ "Node %s[%d] does not exist", var, i);
+
+ if (value != NULL)
+ *value = tree->value;
+
+ result = 1;
+
+ error:
+ api_exit(aug);
+ return result;
+}
+
+int aug_ns_count(const augeas *aug, const char *var) {
+ int result = -1;
+
+ api_entry(aug);
+
+ result = pathx_symtab_count(aug->symtab, var);
+
+ api_exit(aug);
+
+ return result;
+}
+
+int aug_ns_path(const augeas *aug, const char *var, int i, char **path) {
+ int result = -1;
+
+ *path = NULL;
+
+ api_entry(aug);
+
+ struct tree *tree = pathx_symtab_get_tree(aug->symtab, var, i);
+ ERR_THROW(tree == NULL, aug, AUG_ENOMATCH,
+ "Node %s[%d] does not exist", var, i);
+
+ *path = path_of_tree(tree);
+
+ result = 0;
+
+ error:
+ api_exit(aug);
+ return result;
+}
+
/*
* Error reporting API
*/