[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