[augeas-devel] augeas: master - Remove files whose tree under /files was deleted

David Lutterkort lutter at fedoraproject.org
Thu Feb 26 23:43:38 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=48348fdf53cba8b01e6a0f65507b75e65d1fb597
Commit:        48348fdf53cba8b01e6a0f65507b75e65d1fb597
Parent:        a3f081e44128940353083db3ce3138dba0ca3033
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Wed Feb 25 12:28:41 2009 -0800
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Feb 25 13:43:47 2009 -0800

Remove files whose tree under /files was deleted

When doing rm /files/etc/hosts, we now delete the file /etc/hosts
on save
---
 src/augeas.c               |   49 +++++++++++++++++++++++++
 src/transform.c            |   87 +++++++++++++++++++++++++++++++++++++++++++-
 src/transform.h            |    7 ++++
 tests/rec-hosts-rm.rb      |   19 ----------
 tests/test-events-saved.sh |    8 ++++-
 5 files changed, 148 insertions(+), 22 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index af2117b..2ba574c 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -618,6 +618,47 @@ static struct tree *tree_find(struct tree *origin, const char *path) {
     return result;
 }
 
+static struct tree *tree_child(struct tree *tree, const char *label) {
+    list_for_each(child, tree->children) {
+        if (streqv(label, child->label))
+            return child;
+    }
+    return NULL;
+}
+
+static int unlink_removed_files(struct augeas *aug,
+                                struct tree *files, struct tree *meta) {
+    int result = 0;
+
+    if (! files->dirty)
+        return 0;
+
+    for (struct tree *tm = meta->children; tm != NULL;) {
+        struct tree *tf = tree_child(files, tm->label);
+        struct tree *next = tm->next;
+        if (tf == NULL) {
+            /* Unlink all files in tm */
+            struct pathx *px = NULL;
+            if (pathx_parse(tm, "descendant-or-self::*[path]", &px)
+                != PATHX_NOERROR) {
+                result = -1;
+                continue;
+            }
+            for (struct tree *t = pathx_first(px);
+                 t != NULL;
+                 t = pathx_next(px)) {
+                remove_file(aug, t);
+            }
+            free_pathx(px);
+        } else if (tf->dirty && ! tree_child(tm, "path")) {
+            if (unlink_removed_files(aug, tf, tm) < 0)
+                result = -1;
+        }
+        tm = next;
+    }
+    return result;
+}
+
 int aug_save(struct augeas *aug) {
     int ret = 0;
     struct tree *files;
@@ -639,6 +680,14 @@ int aug_save(struct augeas *aug) {
             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)
+                ret = -1;
+        }
     }
     if (!(aug->flags & AUG_SAVE_NOOP)) {
         tree_clean(aug->origin->children);
diff --git a/src/transform.c b/src/transform.c
index bc91668..991f654 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -189,7 +189,10 @@ void free_transform(struct transform *xform) {
 
 static char *err_path(const char *filename) {
     char *result = NULL;
-    pathjoin(&result, 3, AUGEAS_META_FILES, filename, err_node);
+    if (filename == NULL)
+        pathjoin(&result, 2, AUGEAS_META_FILES, err_node);
+    else
+        pathjoin(&result, 3, AUGEAS_META_FILES, filename, err_node);
     return result;
 }
 
@@ -624,7 +627,6 @@ int transform_save(struct augeas *aug, struct transform *xform,
 
     if (tree != NULL)
         lns_put(fp, xform->lens, tree->children, text, &err);
-    // FIXME: Delete file if tree == NULL
 
     if (ferror (fp) || fclose(fp) != 0)
         goto done;
@@ -707,6 +709,87 @@ int transform_save(struct augeas *aug, struct transform *xform,
     return result;
 }
 
+int remove_file(struct augeas *aug, struct tree *tree) {
+    char *path = NULL;
+    const char *filename = NULL;
+    const char *err_status = NULL;
+    char *dyn_err_status = NULL;
+    char *augsave = NULL, *augorig = NULL, *augorig_canon = NULL;
+    int r;
+
+    path = path_of_tree(tree);
+    if (path == NULL) {
+        err_status = "path_of_tree";
+        goto error;
+    }
+    filename = path + strlen(AUGEAS_META_FILES);
+
+    if ((augorig = strappend(aug->root, filename + 1)) == NULL) {
+        err_status = "root_file";
+        goto error;
+    }
+
+    augorig_canon = canonicalize_file_name(augorig);
+    if (augorig_canon == NULL) {
+        if (errno == ENOENT) {
+            goto done;
+        } else {
+            err_status = "canon_augorig";
+            goto error;
+        }
+    }
+
+    r = file_saved_event(aug, path + strlen(AUGEAS_META_TREE));
+    if (r < 0) {
+        err_status = "saved_event";
+        goto error;
+    }
+
+    if (aug->flags & AUG_SAVE_NOOP)
+        goto done;
+
+    if (aug->flags & AUG_SAVE_BACKUP) {
+        /* Move file to one with extension .augsave */
+        r = asprintf(&augsave, "%s" EXT_AUGSAVE, augorig_canon);
+        if (r == -1) {
+            augsave = NULL;
+                goto error;
+        }
+
+        r = clone_file(augorig_canon, augsave, &err_status, 1);
+        if (r != 0) {
+            dyn_err_status = strappend(err_status, "_augsave");
+            goto error;
+        }
+    } else {
+        /* Unlink file */
+        r = unlink(augorig_canon);
+        if (r < 0) {
+            err_status = "unlink_orig";
+            goto error;
+        }
+    }
+    tree_unlink(tree);
+ done:
+    free(path);
+    free(augorig);
+    free(augorig_canon);
+    free(augsave);
+    return 0;
+ error:
+    {
+        const char *emsg =
+            dyn_err_status == NULL ? err_status : dyn_err_status;
+        store_error(aug, filename, path, emsg, errno, NULL);
+    }
+    free(path);
+    free(augorig);
+    free(augorig_canon);
+    free(augsave);
+    free(dyn_err_status);
+    return -1;
+}
+
 /*
  * Local variables:
  *  indent-tabs-mode: nil
diff --git a/src/transform.h b/src/transform.h
index 9eff28b..cc3396d 100644
--- a/src/transform.h
+++ b/src/transform.h
@@ -66,6 +66,13 @@ int transform_applies(struct transform *transform, const char *path);
 int transform_save(struct augeas *aug, struct transform *transform,
                    const char *path, struct tree *tree);
 
+/* Remove the file for TREE, either by moving it to a .augsave file or by
+ * unlinking it, depending on aug->flags. TREE must be the node underneath
+ * /augeas/files corresponding to the file to be removed.
+ *
+ * Return 0 on success, -1 on failure
+ */
+int remove_file(struct augeas *aug, struct tree *tree);
 #endif
 
 
diff --git a/tests/rec-hosts-rm.rb b/tests/rec-hosts-rm.rb
deleted file mode 100644
index 6b05bcf..0000000
--- a/tests/rec-hosts-rm.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# This will leave /etc/hosts completely empty
-skip=true
-commands="
-rm /files/etc/hosts
-save
-"
-
-diff["/etc/hosts"] = <<TXT
---- /etc/hosts
-+++ /etc/hosts.augnew
-@@ -1,6 +0,0 @@
--# Do not remove the following line, or various programs
--# that require network functionality will fail.
--127.0.0.1\tlocalhost.localdomain\tlocalhost galia.watzmann.net galia
--#172.31.122.254   granny.watzmann.net granny puppet
--#172.31.122.1     galia.watzmann.net galia
--172.31.122.14   orange.watzmann.net orange
-TXT
-
diff --git a/tests/test-events-saved.sh b/tests/test-events-saved.sh
index b8c5cc6..54760de 100755
--- a/tests/test-events-saved.sh
+++ b/tests/test-events-saved.sh
@@ -9,7 +9,7 @@ augtool --nostdinc -r $root -I $abs_top_srcdir/lenses <<EOF
 set /files/etc/hosts/1/ipaddr 127.0.1.1
 set /files/etc/grub.conf/default 3
 set /files/etc/inittab/1/action fake
-set /files/etc/puppet/puppet.conf/main/ssldir /dev/null
+rm /files/etc/puppet/puppet.conf
 set /files/etc/yum.repos.d/fedora.repo/fedora/enabled 0
 save
 match /augeas/events/saved
@@ -25,6 +25,12 @@ cp -pr $abs_top_srcdir/tests/root/* $root
 saved=$(run_augtool | grep ^/augeas/events/saved | cut -d ' ' -f 3 | sort | tr '\n' ' ')
 exp="/files/etc/grub.conf /files/etc/hosts /files/etc/inittab /files/etc/puppet/puppet.conf /files/etc/yum.repos.d/fedora.repo "
 
+if [ -f "$root/etc/puppet/puppet.conf" ]
+then
+  echo "File /etc/puppet/puppet.conf should have been deleted"
+  exit 1
+fi
+
 if [ "$saved" != "$exp" ]
 then
     echo "Unexpected entries in /augeas/events/saved:"




More information about the augeas-devel mailing list