Re: [PATCH v3] Demonstrate bugs when a directory is replaced with a symlink

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Wed, 29 Jul 2009, Linus Torvalds wrote:
>
> The 'merge' issue is different, though: it's not due to a blind 'lstat()', 
> but due to a blind 'unlink()' done by 'remove_path()'. I think 
> 'remove_path()' should be taught to look for symlinks, and remove just the 
> symlink - but that's a bit more work, especially since the symlink cache 
> doesn't seem to expose any way to get the "what is the first symlink path" 
> information.
> 
> Kjetil, can you look at that? 

Hmm... This looks like it should do it.

It doesn't make the test _pass_ (we don't seem to be creating a/b-2/c/d 
properly - I haven't checked why yet, but I suspect it is becasue we think 
it already exists due to the symlinked version lstat'ing fine), but it 
seems to do the right thing.

		Linus

---
 dir.c      |   20 --------------------
 symlinks.c |   26 ++++++++++++++++++++++++++
 2 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/dir.c b/dir.c
index e05b850..2204826 100644
--- a/dir.c
+++ b/dir.c
@@ -911,23 +911,3 @@ void setup_standard_excludes(struct dir_struct *dir)
 	if (excludes_file && !access(excludes_file, R_OK))
 		add_excludes_from_file(dir, excludes_file);
 }
-
-int remove_path(const char *name)
-{
-	char *slash;
-
-	if (unlink(name) && errno != ENOENT)
-		return -1;
-
-	slash = strrchr(name, '/');
-	if (slash) {
-		char *dirs = xstrdup(name);
-		slash = dirs + (slash - name);
-		do {
-			*slash = '\0';
-		} while (rmdir(dirs) && (slash = strrchr(dirs, '/')));
-		free(dirs);
-	}
-	return 0;
-}
-
diff --git a/symlinks.c b/symlinks.c
index 4bdded3..349c8d5 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -306,3 +306,29 @@ void remove_scheduled_dirs(void)
 {
 	do_remove_scheduled_dirs(0);
 }
+
+int remove_path(const char *name)
+{
+	char *slash;
+
+	/*
+	 * If we have a leading symlink, we remove
+	 * just the symlink!
+	 */
+	if (has_symlink_leading_path(name, strlen(name)))
+		name = default_cache.path;
+
+	if (unlink(name) && errno != ENOENT)
+		return -1;
+
+	slash = strrchr(name, '/');
+	if (slash) {
+		char *dirs = xstrdup(name);
+		slash = dirs + (slash - name);
+		do {
+			*slash = '\0';
+		} while (rmdir(dirs) && (slash = strrchr(dirs, '/')));
+		free(dirs);
+	}
+	return 0;
+}
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]