git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Jul 29, 2009, 23:58 UTC
Message-ID
<alpine.LFD.2.01.0907291656420.3161@localhost.localdomain>
In-Reply-To
<alpine.LFD.2.01.0907291440480.3161@localhost.localdomain>
On Wed, 29 Jul 2009, Linus Torvalds wrote:
Show 9 quoted lines
>
> 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;
+}
Previous: Kjetil BarvikNext: Linus Torvalds
Message 15 of 18 in “More symlink/directory troubles”
  1. James PickensJul 28, 2009
  2. 1/2 Demonstrate bugs when a directory is replaced with a symlink.James Pickens, Jul 28, 2009
  3. 2/2 Demonstrate merge failure when a directory is replaced with a symlink.James Pickens, Jul 28, 2009
  4. Michael J GruberJul 29, 2009
  5. Pickens, James EJul 29, 2009
  6. Michael J GruberJul 29, 2009
  7. Junio C HamanoJul 29, 2009
  8. Pickens, James EJul 29, 2009
  9. Demonstrate bugs when a directory is replaced with a symlinkPickens, James E, Jul 29, 2009
  10. Junio C HamanoJul 29, 2009
  11. Demonstrate bugs when a directory is replaced with a symlinkPickens, James E, Jul 29, 2009
  12. Linus TorvaldsJul 29, 2009
  13. Junio C HamanoJul 29, 2009
  14. Kjetil BarvikJul 29, 2009
  15. Linus TorvaldsJul 29, 2009
  16. Linus TorvaldsJul 30, 2009
  17. Junio C HamanoJul 30, 2009
  18. Junio C HamanoJul 30, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.