[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