[augeas-devel] [PATCH] Validate trees representing a transform before using them
David Lutterkort
lutter at redhat.com
Wed Mar 18 23:04:59 UTC 2009
---
src/augeas.c | 41 +++++++++++----------------
src/internal.h | 2 +
src/transform.c | 79 +++++++++++++++++++++++++++++++++++++++++++----------
src/transform.h | 7 +++++
tests/test-load.c | 35 +++++++++++++++++++++++
5 files changed, 125 insertions(+), 39 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index 42eaac3..a6ac078 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -94,19 +94,6 @@ static struct pathx *parse_user_pathx(const struct augeas *aug,
return NULL;
}
-static struct tree *tree_find(struct tree *origin, const char *path) {
- struct pathx *px = NULL;
- struct tree *result = NULL;
-
- if (pathx_parse(origin, path, &px) != 0)
- return NULL;
-
- pathx_find_one(px, &result);
- free_pathx(px);
-
- return result;
-}
-
static struct tree *tree_child(struct tree *tree, const char *label) {
if (tree == NULL)
return NULL;
@@ -138,8 +125,8 @@ static const char *init_root(const char *root0) {
return root;
}
-static struct tree *tree_append(struct tree *parent,
- char *label, char *value) {
+struct tree *tree_append(struct tree *parent,
+ char *label, char *value) {
struct tree *result = make_tree(label, value, parent, NULL);
if (result != NULL)
list_append(parent->children, result);
@@ -310,7 +297,8 @@ int aug_load(struct augeas *aug) {
tree_unlink_children(files);
list_for_each(xfm, load->children) {
- transform_load(aug, xfm);
+ if (transform_validate(aug, xfm) == 0)
+ transform_load(aug, xfm);
}
tree_clean(aug->origin);
return 0;
@@ -764,28 +752,33 @@ static int unlink_removed_files(struct augeas *aug,
int aug_save(struct augeas *aug) {
int ret = 0;
- struct tree *files;
+ struct tree *meta = tree_child(aug->origin, "augeas");
+ struct tree *meta_files = tree_child(meta, "files");
+ struct tree *files = tree_child(aug->origin, "files");
+ struct tree *load = tree_child(meta, "load");
if (update_save_flags(aug) < 0)
return -1;
- files = tree_find(aug->origin, AUGEAS_FILES_TREE);
if (files == NULL)
return -1;
+ if (meta == NULL || load == NULL)
+ return 0;
+
aug_rm(aug, AUGEAS_EVENTS_SAVED);
+ list_for_each(xfm, load->children)
+ transform_validate(aug, xfm);
+
if (files->dirty) {
list_for_each(t, files->children) {
if (tree_save(aug, t, AUGEAS_FILES_TREE) == -1)
ret = -1;
}
- /* Remove files whose entire subtree was removed. META
- * will be NULL if all files are new
- */
- struct tree *meta = tree_find(aug->origin, AUGEAS_META_FILES);
- if (meta != NULL) {
- if (unlink_removed_files(aug, files, meta) < 0)
+ /* Remove files whose entire subtree was removed. */
+ if (meta_files != NULL) {
+ if (unlink_removed_files(aug, files, meta_files) < 0)
ret = -1;
}
}
diff --git a/src/internal.h b/src/internal.h
index b689677..407f184 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -321,6 +321,8 @@ struct tree *make_tree(char *label, char *value,
struct tree *make_tree_origin(struct tree *root);
int tree_replace(struct tree *origin, const char *path, struct tree *sub);
+/* Make a new tree node and append it to parent's children */
+struct tree *tree_append(struct tree *parent, char *label, char *value);
int tree_rm(struct pathx *p);
int tree_unlink(struct tree *tree);
diff --git a/src/transform.c b/src/transform.c
index fbb6dc2..155a7af 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -402,6 +402,25 @@ static int load_file(struct augeas *aug, struct lens *lens, char *filename) {
return result;
}
+/* The lens for a transform can be referred to in one of two ways:
+ * either by a fully qualified name "Module.lens" or by the special
+ * syntax "@Module"; the latter means we should take the lens from the
+ * autoload transform for Module
+ */
+static struct lens *lens_from_name(struct augeas *aug, const char *name) {
+ if (name[0] == '@') {
+ struct module *modl = NULL;
+ for (modl = aug->modules;
+ modl != NULL && !streqv(modl->name, name + 1);
+ modl = modl->next);
+ if (modl == NULL || modl->autoload == NULL)
+ return NULL;
+ return modl->autoload->lens;
+ } else {
+ return lens_lookup(aug, name);
+ }
+}
+
static struct lens *xfm_lens(struct augeas *aug, struct tree *xfm) {
struct tree *l = NULL;
@@ -411,23 +430,53 @@ static struct lens *xfm_lens(struct augeas *aug, struct tree *xfm) {
if (l == NULL || l->value == NULL)
return NULL;
+ return lens_from_name(aug, l->value);
+}
- /* The lens for a transform can be referred to in one of two ways:
- * either by a fully qualified name "Module.lens" or by the special
- * syntax "@Module"; the latter means we should take the lens from the
- * autoload transform for Module
- */
- if (l->value[0] == '@') {
- struct module *modl = NULL;
- for (modl = aug->modules;
- modl != NULL && !streqv(modl->name, l->value + 1);
- modl = modl->next);
- if (modl == NULL || modl->autoload == NULL)
- return NULL;
- return modl->autoload->lens;
- } else {
- return lens_lookup(aug, l->value);
+static void xfm_error(struct tree *xfm, const char *msg) {
+ char *v = strdup(msg);
+ char *l = strdup("error");
+ struct tree *e = NULL;
+
+ if (l == NULL || v == NULL)
+ return;
+ e = tree_append(xfm, l, v);
+}
+
+int transform_validate(struct augeas *aug, struct tree *xfm) {
+ struct tree *l = NULL;
+
+ for (struct tree *t = xfm->children; t != NULL; ) {
+ if (streqv(t->label, "lens"))
+ l = t;
+ if (streqv(t->label, "error")) {
+ struct tree *del = t;
+ t = del->next;
+ tree_unlink(del);
+ } else {
+ t = t->next;
+ }
+ }
+
+ if (l == NULL) {
+ xfm_error(xfm, "missing a child with label 'lens'");
+ return -1;
}
+ if (l->value == NULL) {
+ xfm_error(xfm, "the 'lens' node does not contain a lens name");
+ return -1;
+ }
+ if (lens_from_name(aug, l->value) == NULL) {
+ char *msg;
+ if (asprintf(&msg, "the lens '%s' does not exist", l->value) < 0) {
+ xfm_error(xfm, "the lens does not exist");
+ } else {
+ xfm_error(xfm, msg);
+ free(msg);
+ }
+ return -1;
+ }
+ return 0;
}
int transform_load(struct augeas *aug, struct tree *xfm) {
diff --git a/src/transform.h b/src/transform.h
index 78483dc..1178f64 100644
--- a/src/transform.h
+++ b/src/transform.h
@@ -54,6 +54,13 @@ void free_transform(struct transform *xform);
* are glob patterns used to filter which files to transform.
*/
+/* Verify that the tree XFM represents a valid transform. If it does not,
+ * add an 'error' child to it.
+ *
+ * Return 0 if XFM is a valid transform, -1 otherwise.
+ */
+int transform_validate(struct augeas *aug, struct tree *xfm);
+
/* Load all files matching the TRANSFORM's filter into the tree in AUG by
* applying the TRANSFORM's lens to their contents and putting the
* resulting tree under "/files" + filename. Also stores some information
diff --git a/tests/test-load.c b/tests/test-load.c
index 3d6fab1..4ca1fce 100644
--- a/tests/test-load.c
+++ b/tests/test-load.c
@@ -99,6 +99,40 @@ static void testNoLoad(CuTest *tc) {
aug_close(aug);
}
+static void invalidLens(CuTest *tc, augeas *aug, const char *lens) {
+ int r, nmatches;
+
+ r = aug_set(aug, "/augeas/load/Junk/lens", lens);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_set(aug, "/augeas/load/Junk/incl", "/dev/null");
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ nmatches = aug_match(aug, "/augeas/load/Junk/error", NULL);
+ CuAssertIntEquals(tc, 1, nmatches);
+}
+
+static void testInvalidLens(CuTest *tc) {
+ augeas *aug = NULL;
+ int r;
+
+ aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
+ CuAssertPtrNotNull(tc, aug);
+
+ r = aug_rm(aug, "/augeas/load/*");
+ CuAssertTrue(tc, r >= 0);
+
+ invalidLens(tc, aug, NULL);
+ invalidLens(tc, aug, "@Nomodule");
+ invalidLens(tc, aug, "@Util");
+ invalidLens(tc, aug, "Nomodule.noelns");
+
+ aug_close(aug);
+}
+
int main(void) {
char *output = NULL;
CuSuite* suite = CuSuiteNew();
@@ -106,6 +140,7 @@ int main(void) {
SUITE_ADD_TEST(suite, testDefault);
SUITE_ADD_TEST(suite, testNoLoad);
+ SUITE_ADD_TEST(suite, testInvalidLens);
abs_top_srcdir = getenv("abs_top_srcdir");
if (abs_top_srcdir == NULL)
--
1.6.0.6
More information about the augeas-devel
mailing list