Commit b832ecf71c8e8d6787f9252b92e97153047a3ec3

Russell Belfer 2013-06-05T09:46:51

Ensure git_futils_mkdir won't mkdir root This makes sure that git_futils_mkdir always skips over the root directory at a minimum, even on platforms where the root is not simply '/'. Also, this removes the GIT_WIN32 ifdef in favor of making EACCES as a potentially recoverable error on all platforms.

diff --git a/src/fileops.c b/src/fileops.c
index a4f56e0..8f308d2 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -277,7 +277,7 @@ int git_futils_mkdir(
 	mode_t mode,
 	uint32_t flags)
 {
-	int error = -1, tmp_errno;
+	int error = -1, tmp;
 	git_buf make_path = GIT_BUF_INIT;
 	ssize_t root = 0;
 	char lastch, *tail;
@@ -315,6 +315,11 @@ int git_futils_mkdir(
 	if (root < 0)
 		root = 0;
 
+	/* make sure mkdir root is at least after filesystem root */
+	tmp = git_path_root(make_path.ptr);
+	if (root < tmp)
+		root = tmp;
+
 	tail = & make_path.ptr[root];
 
 	while (*tail) {
@@ -345,18 +350,14 @@ int git_futils_mkdir(
 
 				already_exists = 1;
 				break;
-#ifdef GIT_WIN32
-			case EACCES:
-#endif
 			case ENOSYS:
-				/* The following errors can be generated if:
-				 * EACCES - Win32 can generate this error if you try to mkdir
-				 *          a path which is the root of a volume.
-				 * ENOSYS - Solaris can generate a ENOSYS error if you try to mkdir
-				 *          a path which is already a mount point.
-				 * In these cases, the path does already exist; but it's not implied by
-				 * the definition of the error, so let's recheck */
-				tmp_errno = errno;
+			case EACCES:
+				/* Possible recoverable errors.  These errors could occur
+				 * on some OS if we try to mkdir at a network mount point
+				 * or at the root of a volume.  If the path is a dir, just
+				 * treat as EEXIST.
+				 */
+				tmp = errno;
 
 				if (git_path_isdir(make_path.ptr)) {
 					already_exists = 1;
@@ -364,7 +365,7 @@ int git_futils_mkdir(
 				}
 
 				/* Fall through */
-				errno = tmp_errno;
+				errno = tmp;
 			default:
 				giterr_set(GITERR_OS, "Failed to make directory '%s'",
 					make_path.ptr);