[augeas-devel] augeas: master - * src/transform.h: use tree encoded transforms

David Lutterkort lutter at fedoraproject.org
Fri Mar 20 00:04:24 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=accb55e56669fa07f91d900d8952ee1c1932a89f
Commit:        accb55e56669fa07f91d900d8952ee1c1932a89f
Parent:        7bcfdcc32f85cf3a577adedc5794a9c97d1f7310
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Tue Mar 17 22:48:23 2009 -0700
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Thu Mar 19 10:41:40 2009 -0700

* src/transform.h: use tree encoded transforms

---
 src/augeas.c    |   48 ++++++++++++++++-----------
 src/transform.c |   98 ++++++++++++++++++++++++++++++++++++++++++-------------
 src/transform.h |   13 ++++++--
 3 files changed, 114 insertions(+), 45 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 482d13e..1f7073f 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -108,6 +108,9 @@ static struct tree *tree_find(struct tree *origin, const char *path) {
 }
 
 static struct tree *tree_child(struct tree *tree, const char *label) {
+    if (tree == NULL)
+        return NULL;
+
     list_for_each(child, tree->children) {
         if (streqv(label, child->label))
             return child;
@@ -143,36 +146,36 @@ static struct tree *tree_append(struct tree *parent,
     return result;
 }
 
-static int tree_from_transform(struct augeas *aug,
-                               const char *modname,
-                               struct transform *xfm) {
+static struct tree *tree_from_transform(struct augeas *aug,
+                                        const char *modname,
+                                        struct transform *xfm) {
     struct tree *meta = tree_child(aug->origin, "augeas");
     struct tree *load = NULL, *txfm = NULL;
     char *m = NULL, *q = NULL;
 
     if (meta == NULL)
-        return -1;
+        goto error;
 
     load = tree_child(meta, "load");
     if (load == NULL) {
         char *l = strdup("load");
         load = tree_append(meta, l, NULL);
         if (load == NULL)
-            return -1;
+            goto error;
     }
     if (modname != NULL) {
         m = strdup(modname);
         if (m == NULL)
-            return -1;
+            goto error;
     } else {
         m = strdup("_");
     }
     txfm = tree_append(load, m, NULL);
     if (txfm == NULL)
-        return -1;
+        goto error;
 
     if (asprintf(&q, "@%s", modname) < 0)
-        return -1;
+        goto error;
 
     m = strdup("lens");
     tree_append(txfm, m, q);
@@ -181,7 +184,10 @@ static int tree_from_transform(struct augeas *aug,
         char *l = f->include ? strdup("incl") : strdup("excl");
         tree_append(txfm, l, glob);
     }
-    return 0;
+    return txfm;
+ error:
+    tree_unlink(txfm);
+    return NULL;
 }
 
 struct augeas *aug_init(const char *root, const char *loadpath,
@@ -268,10 +274,11 @@ struct augeas *aug_init(const char *root, const char *loadpath,
 
     list_for_each(modl, result->modules) {
         struct transform *xform = modl->autoload;
+        struct tree *txfm = NULL;
         if (xform == NULL)
             continue;
-        tree_from_transform(result, modl->name, xform);
-        transform_load(result, xform);
+        txfm = tree_from_transform(result, modl->name, xform);
+        transform_load(result, txfm);
     }
     tree_clean(result->origin);
 
@@ -624,23 +631,26 @@ int aug_match(const struct augeas *aug, const char *pathin, char ***matches) {
 static int tree_save(struct augeas *aug, struct tree *tree,
                      const char *path) {
     int result = 0;
+    struct tree *meta = tree_child(aug->origin, "augeas");
+    struct tree *load = tree_child(meta, "load");
+
     // FIXME: We need to detect subtrees that aren't saved by anything
 
+    if (load == NULL)
+        return -1;
+
     list_for_each(t, tree) {
         if (t->dirty) {
             char *tpath = NULL;
-            struct transform *transform = NULL;
+            struct tree *transform = NULL;
             if (asprintf(&tpath, "%s/%s", path, t->label) == -1) {
                 result = -1;
                 continue;
             }
-            list_for_each(modl, aug->modules) {
-                struct transform *xform = modl->autoload;
-                if (xform == NULL)
-                    continue;
-                if (transform_applies(xform, tpath)) {
-                    if (transform == NULL || transform == xform) {
-                        transform = xform;
+            list_for_each(xfm, load->children) {
+                if (transform_applies(xfm, tpath)) {
+                    if (transform == NULL || transform == xfm) {
+                        transform = xfm;
                     } else {
                         FIXME("Multiple transforms for %s", path);
                         result = -1;
diff --git a/src/transform.c b/src/transform.c
index 9aa95bc..fbb6dc2 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <selinux/selinux.h>
+#include <stdbool.h>
 
 #include "internal.h"
 #include "memory.h"
@@ -92,7 +93,15 @@ static const char *pathbase(const char *path) {
     return (p == NULL) ? path : p + 1;
 }
 
-static int filter_generate(struct filter *filter, const char *root,
+static bool is_excl(struct tree *f) {
+    return streqv(f->label, "excl") && f->value != NULL;
+}
+
+static bool is_incl(struct tree *f) {
+    return streqv(f->label, "incl") && f->value != NULL;
+}
+
+static int filter_generate(struct tree *xfm, const char *root,
                            int *nmatches, char ***matches) {
     glob_t globbuf;
     int gl_flags = glob_flags;
@@ -102,11 +111,11 @@ static int filter_generate(struct filter *filter, const char *root,
     *nmatches = 0;
     *matches = NULL;
 
-    list_for_each(f, filter) {
+    list_for_each(f, xfm->children) {
         char *globpat = NULL;
-        if (! f->include)
+        if (! is_incl(f))
             continue;
-        pathjoin(&globpat, 2, root, f->glob->str);
+        pathjoin(&globpat, 2, root, f->value);
         r = glob(globpat, gl_flags, NULL, &globbuf);
         free(globpat);
 
@@ -122,14 +131,14 @@ static int filter_generate(struct filter *filter, const char *root,
     globbuf.gl_pathv = NULL;
     globbuf.gl_pathc = 0;
 
-    list_for_each(e, filter) {
-        if (e->include)
+    list_for_each(e, xfm->children) {
+        if (! is_excl(e))
             continue;
         for (int i=0; i < pathc;) {
             const char *path = pathv[i];
-            if (strchr(e->glob->str, SEP) == NULL)
+            if (strchr(e->value, SEP) == NULL)
                 path = pathbase(path);
-            if (fnmatch(e->glob->str, path, fnm_flags) == 0) {
+            if (fnmatch(e->value, path, fnm_flags) == 0) {
                 free(pathv[i]);
                 pathc -= 1;
                 if (i < pathc) {
@@ -152,16 +161,18 @@ static int filter_generate(struct filter *filter, const char *root,
     return ret;
 }
 
-static int filter_matches(struct filter *filter, const char *path) {
+static int filter_matches(struct tree *xfm, const char *path) {
     int found = 0;
-    list_for_each(f, filter) {
-        if (f->include)
-            found |= (fnmatch(f->glob->str, path, fnm_flags) == 0);
+    list_for_each(f, xfm->children) {
+        if (is_incl(f) && fnmatch(f->value, path, fnm_flags) == 0) {
+            found = 1;
+            break;
+        }
     }
     if (! found)
         return 0;
-    list_for_each(f, filter) {
-        if (!f->include && (fnmatch(f->glob->str, path, fnm_flags) == 0))
+    list_for_each(f, xfm->children) {
+        if (is_excl(f) && (fnmatch(f->value, path, fnm_flags) == 0))
             return 0;
     }
     return 1;
@@ -391,28 +402,61 @@ static int load_file(struct augeas *aug, struct lens *lens, char *filename) {
     return result;
 }
 
-int transform_load(struct augeas *aug, struct transform *xform) {
+static struct lens *xfm_lens(struct augeas *aug, struct tree *xfm) {
+    struct tree *l = NULL;
+
+    for (l = xfm->children;
+         l != NULL && !streqv("lens", l->label);
+         l = l->next);
+
+    if (l == NULL || l->value == NULL)
+        return NULL;
+
+    /* 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);
+    }
+}
+
+int transform_load(struct augeas *aug, struct tree *xfm) {
     int nmatches;
     char **matches;
+    struct lens *lens = xfm_lens(aug, xfm);
     int r;
 
-    r = filter_generate(xform->filter, aug->root, &nmatches, &matches);
+    if (lens == NULL) {
+        // FIXME: Record an error and return 0
+        return -1;
+    }
+    r = filter_generate(xfm, aug->root, &nmatches, &matches);
     if (r == -1)
         return -1;
     for (int i=0; i < nmatches; i++) {
-        load_file(aug, xform->lens, matches[i]);
+        load_file(aug, lens, matches[i]);
         free(matches[i]);
     }
-    lens_release(xform->lens);
+    lens_release(lens);
     free(matches);
     return 0;
 }
 
-int transform_applies(struct transform *xform, const char *path) {
+int transform_applies(struct tree *xfm, const char *path) {
     if (STRNEQLEN(path, AUGEAS_FILES_TREE, strlen(AUGEAS_FILES_TREE))
         || path[strlen(AUGEAS_FILES_TREE)] != SEP)
         return 0;
-    return filter_matches(xform->filter, path + strlen(AUGEAS_FILES_TREE));
+    return filter_matches(xfm, path + strlen(AUGEAS_FILES_TREE));
 }
 
 static int transfer_file_attrs(const char *from, const char *to,
@@ -570,7 +614,7 @@ static int file_saved_event(struct augeas *aug, const char *path) {
  *
  * Return 0 on success, -1 on failure.
  */
-int transform_save(struct augeas *aug, struct transform *xform,
+int transform_save(struct augeas *aug, struct tree *xfm,
                    const char *path, struct tree *tree) {
     FILE *fp = NULL;
     char *augnew = NULL, *augorig = NULL, *augsave = NULL;
@@ -582,8 +626,16 @@ int transform_save(struct augeas *aug, struct transform *xform,
     const char *err_status = NULL;
     char *dyn_err_status = NULL;
     struct lns_error *err = NULL;
+    struct lens *lens = xfm_lens(aug, xfm);
     int result = -1, r;
 
+    errno = 0;
+
+    if (lens == NULL) {
+        err_status = "lens_name";
+        goto done;
+    }
+
     copy_if_rename_fails =
         aug_get(aug, AUGEAS_COPY_IF_RENAME_FAILS, NULL) == 1;
 
@@ -636,7 +688,7 @@ int transform_save(struct augeas *aug, struct transform *xform,
     }
 
     if (tree != NULL)
-        lns_put(fp, xform->lens, tree->children, text, &err);
+        lns_put(fp, lens, tree->children, text, &err);
 
     if (ferror(fp)) {
         err_status = "error_augnew";
@@ -723,7 +775,7 @@ int transform_save(struct augeas *aug, struct transform *xform,
         store_error(aug, filename, path, emsg, errno, err);
     }
     free(dyn_err_status);
-    lens_release(xform->lens);
+    lens_release(lens);
     free(text);
     free(augnew);
     if (augorig_canon != augorig)
diff --git a/src/transform.h b/src/transform.h
index cc3396d..78483dc 100644
--- a/src/transform.h
+++ b/src/transform.h
@@ -47,23 +47,30 @@ struct transform {
 struct transform *make_transform(struct lens *lens, struct filter *filter);
 void free_transform(struct transform *xform);
 
+/*
+ * When we pass a tree for a transform, the tree must have exactly one
+ * child with label "lens" whose value is the qualified name of the lens to
+ * use, and any number of children labelled "incl" or "excl" whose values
+ * are glob patterns used to filter which files to transform.
+ */
+
 /* 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
  * about filename underneath "/augeas/files" + filename
  */
-int transform_load(struct augeas *aug, struct transform *transform);
+int transform_load(struct augeas *aug, struct tree *xfm);
 
 /* Return 1 if TRANSFORM applies to PATH, 0 otherwise. The TRANSFORM
  * applies to PATH if (1) PATH starts with "/files/" and (2) the rest of
  * PATH matches the transform's filter
 */
-int transform_applies(struct transform *transform, const char *path);
+int transform_applies(struct tree *xfm, const char *path);
 
 /* Save TREE into the file corresponding to PATH. It is assumed that the
  * TRANSFORM applies to that PATH
  */
-int transform_save(struct augeas *aug, struct transform *transform,
+int transform_save(struct augeas *aug, struct tree *xfm,
                    const char *path, struct tree *tree);
 
 /* Remove the file for TREE, either by moving it to a .augsave file or by




More information about the augeas-devel mailing list