[augeas-devel] [PATCH] Preserve parse errors under /augeas//error

lutter at redhat.com lutter at redhat.com
Thu Sep 23 23:47:56 UTC 2010


From: David Lutterkort <lutter at redhat.com>

With the changes in commit 5ee81630, a subtree in /augeas/files that is
dirty after trying to load all files indicates a file that was loaded
before, but is not loaded anymore (e.g., because the set of lenses changed
since the last time we loaded) In that situation, both the subtree in
/augeas/files as well as the corresponding subtree in /files is deleted.

The code in store_error, which is called by load_file when a parse error
happens, would leave that subtree in /augeas/files dirty. This commit fixes
that by making sure we mark the error entries as clean. It also revamps
store_error to use the lighter-weight tree_xxx functions instead of the
aug_xxx functions.

Fixes bug #138
---
 src/transform.c   |   71 +++++++++++++++++++++++++++++++---------------------
 tests/test-load.c |   28 +++++++++++++++++++++
 2 files changed, 70 insertions(+), 29 deletions(-)

diff --git a/src/transform.c b/src/transform.c
index f449471..521414b 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -296,30 +296,29 @@ static char *err_path(const char *filename) {
 }
 
 ATTRIBUTE_FORMAT(printf, 4, 5)
-static int err_set(struct augeas *aug, char **ep, const char *sub,
-                   const char *format, ...) {
+static void err_set(struct augeas *aug,
+                    struct tree *err_info, const char *sub,
+                    const char *format, ...) {
     int r;
     va_list ap;
-    size_t ep_len = strlen(*ep);
     char *value = NULL;
-
-    r = pathjoin(ep, 1, sub);
-    if (r < 0)
-        goto error;
+    struct tree *tree = NULL;
 
     va_start(ap, format);
     r = vasprintf(&value, format, ap);
     va_end(ap);
-    if (r < 0) {
+    if (r < 0)
         value = NULL;
-        goto error;
-    }
+    ERR_NOMEM(r < 0, aug);
+
+    tree = tree_child_cr(err_info, sub);
+    ERR_NOMEM(tree == NULL, aug);
+
+    r = tree_set_value(tree, value);
+    ERR_NOMEM(r < 0, aug);
 
-    r = aug_set(aug, *ep, value);
  error:
     free(value);
-    (*ep)[ep_len] = '\0';
-    return (r < 0) ? -1 : 0;
 }
 
 /* Record an error in the tree. The error will show up underneath
@@ -331,51 +330,65 @@ static int store_error(struct augeas *aug,
                        const char *filename, const char *path,
                        const char *status, int errnum,
                        const struct lns_error *err, const char *text) {
-    char *ep = err_path(filename);
+    struct tree *err_info = NULL, *finfo = NULL;
+    char *fip = NULL;
     int r;
     int result = -1;
 
-    if (ep == NULL)
-        return -1;
+    r = pathjoin(&fip, 2, AUGEAS_META_FILES, filename);
+    ERR_NOMEM(r < 0, aug);
+
+    finfo = tree_find_cr(aug, fip);
+    ERR_BAIL(aug);
 
-    aug_rm(aug, ep);
     if (status != NULL) {
-        r = aug_set(aug, ep, status);
-        if (r < 0)
-            goto done;
+        err_info = tree_child_cr(finfo, s_error);
+        ERR_NOMEM(err_info == NULL, aug);
+
+        r = tree_set_value(err_info, status);
+        ERR_NOMEM(r < 0, aug);
 
         /* Errors from err_set are ignored on purpose. We try
          * to report as much as we can */
         if (err != NULL) {
             if (err->pos >= 0) {
                 size_t line, ofs;
-                err_set(aug, &ep, s_pos, "%d", err->pos);
+                err_set(aug, err_info, s_pos, "%d", err->pos);
                 if (text != NULL) {
                     calc_line_ofs(text, err->pos, &line, &ofs);
-                    err_set(aug, &ep, s_line, "%zd", line);
-                    err_set(aug, &ep, s_char, "%zd", ofs);
+                    err_set(aug, err_info, s_line, "%zd", line);
+                    err_set(aug, err_info, s_char, "%zd", ofs);
                 }
             }
             if (err->path != NULL) {
-                err_set(aug, &ep, s_path, "%s%s", path, err->path);
+                err_set(aug, err_info, s_path, "%s%s", path, err->path);
             }
             if (err->lens != NULL) {
                 char *fi = format_info(err->lens->info);
                 if (fi != NULL) {
-                    err_set(aug, &ep, s_lens, "%s", fi);
+                    err_set(aug, err_info, s_lens, "%s", fi);
                     free(fi);
                 }
             }
-            err_set(aug, &ep, s_message, "%s", err->message);
+            err_set(aug, err_info, s_message, "%s", err->message);
         } else if (errnum != 0) {
             const char *msg = strerror(errnum);
-            err_set(aug, &ep, s_message, "%s", msg);
+            err_set(aug, err_info, s_message, "%s", msg);
+        }
+    } else {
+        /* No error, nuke the error node if it exists */
+        err_info = tree_child(finfo, s_error);
+        if (err_info != NULL) {
+            tree_unlink_children(aug, err_info);
+            pathx_symtab_remove_descendants(aug->symtab, err_info);
+            tree_unlink(err_info);
         }
     }
 
+    tree_clean(finfo);
     result = 0;
- done:
-    free(ep);
+ error:
+    free(fip);
     return result;
 }
 
diff --git a/tests/test-load.c b/tests/test-load.c
index f11b86f..6110ebc 100644
--- a/tests/test-load.c
+++ b/tests/test-load.c
@@ -457,6 +457,33 @@ static void testReloadExternalMod(CuTest *tc) {
     CuAssertIntEquals(tc, 5, r);
 }
 
+/* Make sure parse errors from applying a lens to a file that does not
+ * match get reported under /augeas//error
+ *
+ * Tests bug #138
+ */
+static void testParseErrorReported(CuTest *tc) {
+    augeas *aug = NULL;
+    int nmatches, r;
+
+    aug = aug_init(root, loadpath, AUG_NO_MODL_AUTOLOAD);
+    CuAssertPtrNotNull(tc, aug);
+
+    r = aug_set(aug, "/augeas/load/Bad/lens", "Yum.lns");
+    CuAssertRetSuccess(tc, r);
+
+    r = aug_set(aug, "/augeas/load/Bad/incl", "/etc/fstab");
+    CuAssertRetSuccess(tc, r);
+
+    r = aug_load(aug);
+    CuAssertRetSuccess(tc, r);
+
+    nmatches = aug_match(aug, "/augeas/files/etc/fstab/error", NULL);
+    CuAssertIntEquals(tc, 1, nmatches);
+
+    aug_close(aug);
+}
+
 int main(void) {
     char *output = NULL;
     CuSuite* suite = CuSuiteNew();
@@ -474,6 +501,7 @@ int main(void) {
     SUITE_ADD_TEST(suite, testReloadDeleted);
     SUITE_ADD_TEST(suite, testReloadDeletedMeta);
     SUITE_ADD_TEST(suite, testReloadExternalMod);
+    SUITE_ADD_TEST(suite, testParseErrorReported);
 
     abs_top_srcdir = getenv("abs_top_srcdir");
     if (abs_top_srcdir == NULL)
-- 
1.7.2.3




More information about the augeas-devel mailing list