From 8c502bdb549cddf3d42d56731467c45cc2b8e503 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 28 Apr 2014 00:38:11 -0500 Subject: [PATCH] Check for rename loops --- src/update_image.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/update_image.c b/src/update_image.c index 70038d42..3e7613fc 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -949,6 +949,19 @@ free_dentry_full_path(struct wim_dentry *dentry, void *_ignore) return 0; } +/* Is @d1 a (possibly nonproper) ancestor of @d2? */ +static bool +is_ancestor(struct wim_dentry *d1, struct wim_dentry *d2) +{ + for (;;) { + if (d2 == d1) + return true; + if (dentry_is_root(d2)) + return false; + d2 = d2->parent; + } +} + /* Rename a file or directory in the WIM. * * This returns a -errno value. @@ -1003,6 +1016,11 @@ rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to, return -ENOTDIR; } + /* @src can't be an ancestor of @dst. Otherwise we're unlinking @src + * from the tree and creating a loop... */ + if (is_ancestor(src, parent_of_dst)) + return -EBUSY; + if (j) { if (journaled_change_name(j, src, path_basename(to))) return -ENOMEM; @@ -1059,6 +1077,9 @@ execute_rename_command(struct update_command_journal *j, ret = WIMLIB_ERR_NOTDIR; break; case ENOTEMPTY: + case EBUSY: + /* XXX: EBUSY is returned when the rename would create a + * loop. It maybe should have its own error code. */ ret = WIMLIB_ERR_NOTEMPTY; break; case EISDIR: -- 2.43.0