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

Re: [PATCH] Do _not_ call unlink on a directory

From
TGThomas Glanzmann <thomas@glanzmann.de>
Date
Jul 17, 2007, 10:15 UTC
Message-ID
<20070717101527.GB7774@cip.informatik.uni-erlangen.de>
In-Reply-To
<7vtzs3a0xg.fsf@assigned-by-dhcp.cox.net>
Hello Junio,
> This is wrong.  If the filesystem has a symlink and we would want a
> directory there, we should unlink().  So at least the stat there needs
> to be lstat().
I see.
> I wonder if anybody involved in the discussion has actually
> tested this patch (or the other one, that has the same problem)?
I tested it. But I did not test it with symlinks.
> Does the following replacement work for you?  It adds far more lines
> than your version, but they are mostly comments to make it clear why
> we do things this way.
Yes, it does. Excuse the delay but my build machine is not the fastest.
	(faui04a) [/var/tmp] git clone ~/work/repositories/public/easix.git test-10
	Initialized empty Git repository in /var/tmp/test-10/.git/
	remote: Generating pack...
	remote: Done counting 317 objects.
	remote: Deltifying 317 objects...
	remote: te: % (317/317) done: ) done
	Indexing 317 objects...
	remote: Total 317 (delta 182), reused 278 (delta 157)
	100% (317/317) done
	Resolving 182 deltas...
	100% (182/182) done
	(faui04a) [/var/tmp] cd test-10
	./test-10
	(faui04a) [/var/tmp/test-10] git status
	# On branch master
	nothing to commit (working directory clean)

I rebased your patch on top of current HEAD (as I can access it on git.kernel.org) and removed trailing whitspace from one line (git-apply complained)

	Thomas
>From 3b60b807007507ce5e1f8490f1469dac5bb95917 Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
Date: Tue, 17 Jul 2007 11:31:07 +0200
Subject: [PATCH] Do _not_ call unlink on a directory
Calling unlink on a directory on a Solaris UFS filesystem as root makes it
inconsistent. Thanks to Junio for the not so obvious fix.
---
 entry.c |   37 ++++++++++++++++++++++++++++++-------
 1 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/entry.c b/entry.c
index c540ae1..0625112 100644
--- a/entry.c
+++ b/entry.c
@@ -8,17 +8,40 @@ static void create_directories(const char *path, const struct checkout *state)
 	const char *slash = path;
 
 	while ((slash = strchr(slash+1, '/')) != NULL) {
+		struct stat st;
+		int stat_status;
+
 		len = slash - path;
 		memcpy(buf, path, len);
 		buf[len] = 0;
+
+		if (len <= state->base_dir_len)
+			/*
+			 * checkout-index --prefix=<dir>; <dir> is
+			 * allowed to be a symlink to an existing
+			 * directory.
+			 */
+			stat_status = stat(buf, &st);
+		else
+			/*
+			 * if there currently is a symlink, we would
+			 * want to replace it with a real directory.
+			 */
+			stat_status = lstat(buf, &st);
+
+		if (!stat_status && S_ISDIR(st.st_mode))
+			continue; /* ok, it is already a directory. */
+
+		/*
+		 * We know stat_status == 0 means something exists
+		 * there and this mkdir would fail, but that is an
+		 * error codepath; we do not care, as we unlink and
+		 * mkdir again in such a case.
+		 */
 		if (mkdir(buf, 0777)) {
-			if (errno == EEXIST) {
-				struct stat st;
-				if (len > state->base_dir_len && state->force && !unlink(buf) && !mkdir(buf, 0777))
-					continue;
-				if (!stat(buf, &st) && S_ISDIR(st.st_mode))
-					continue; /* ok */
-			}
+			if (errno == EEXIST && state->force &&
+			    !unlink(buf) && !mkdir(buf, 0777))
+				continue;
 			die("cannot create directory at %s", buf);
 		}
 	}
-- 
1.5.2.1
Previous: Junio C HamanoNext: Junio C Hamano
Message 25 of 30 in “Do _not_ call unlink on a directory”
  1. Do _not_ call unlink on a directoryThomas Glanzmann, Jul 16, 2007
  2. Matthieu MoyJul 16, 2007
  3. Scott LambJul 16, 2007
  4. Thomas GlanzmannJul 16, 2007
  5. Thomas GlanzmannJul 16, 2007
  6. Linus TorvaldsJul 16, 2007
  7. Thomas GlanzmannJul 16, 2007
  8. Linus TorvaldsJul 16, 2007
  9. Thomas GlanzmannJul 16, 2007
  10. Scott LambJul 16, 2007
  11. Linus TorvaldsJul 16, 2007
  12. Scott LambJul 16, 2007
  13. Linus TorvaldsJul 16, 2007
  14. Linus TorvaldsJul 16, 2007
  15. Do _not_ call unlink on a directoryThomas Glanzmann, Jul 16, 2007
  16. Jan-Benedict GlawJul 16, 2007
  17. Brian DowningJul 16, 2007
  18. Thomas GlanzmannJul 16, 2007
  19. Linus TorvaldsJul 16, 2007
  20. Brian DowningJul 16, 2007
  21. Linus TorvaldsJul 16, 2007
  22. David KastrupJul 17, 2007
  23. Junio C HamanoJul 17, 2007
  24. Junio C HamanoJul 17, 2007
  25. Thomas GlanzmannJul 17, 2007
  26. Junio C HamanoJul 17, 2007
  27. Thomas GlanzmannJul 17, 2007
  28. Johannes SixtJul 18, 2007
  29. Thomas GlanzmannJul 18, 2007
  30. Linus TorvaldsJul 17, 2007

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.