Re: [PATCH 7/7] t0000: verify that real_path() removes extra slashes

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

 



On Wed, Sep 05, 2012 at 08:23:58PM -0700, Junio C Hamano wrote:
> Nguyen Thai Ngoc Duy <pclouds@xxxxxxxxx> writes:
> 
> > diff --git a/path.c b/path.c
> > index 66acd24..ad2881c 100644
> > --- a/path.c
> > +++ b/path.c
> > @@ -503,6 +503,10 @@ int normalize_path_copy(char *dst, const char *src)
> >                 *dst++ = *src++;
> >                 *dst++ = *src++;
> >         }
> > +#ifdef WIN32
> > +       else if (src[0] == '/' && src[1] == '/')
> > +               *dst++ = *src++;
> > +#endif
> 
> The two-byte copy we see above the context is conditional on a nice
> abstraction "has_dos_drive_prefix()" so that we do not have to
> suffer from these ugly ifdefs.  Could we do something similar?

Just an idea. We could unify "[a-z]:" and "//host" into "dos root"
concept. That would teach other code paths about UNC paths too.

Replace has_dos_drive_prefix() with has_dos_root_prefix(). Because the
root component's length is not fixed, offset_1st_component() should be
used instead of hard coding "2".

Something like this. Totally untested.

-- 8< --
diff --git a/cache.h b/cache.h
index 67f28b4..7946489 100644
--- a/cache.h
+++ b/cache.h
@@ -711,7 +711,7 @@ extern char *expand_user_path(const char *path);
 const char *enter_repo(const char *path, int strict);
 static inline int is_absolute_path(const char *path)
 {
-	return is_dir_sep(path[0]) || has_dos_drive_prefix(path);
+	return is_dir_sep(path[0]) || has_dos_root_prefix(path);
 }
 int is_directory(const char *);
 const char *real_path(const char *path);
@@ -721,7 +721,7 @@ int normalize_path_copy(char *dst, const char *src);
 int longest_ancestor_length(const char *path, const char *prefix_list);
 char *strip_path_suffix(const char *path, const char *suffix);
 int daemon_avoid_alias(const char *path);
-int offset_1st_component(const char *path);
+int offset_1st_component(const char *path, int keep_root);
 
 /* object replacement */
 #define READ_SHA1_FILE_REPLACE 1
diff --git a/compat/basename.c b/compat/basename.c
index d8f8a3c..178b60d 100644
--- a/compat/basename.c
+++ b/compat/basename.c
@@ -5,8 +5,7 @@ char *gitbasename (char *path)
 {
 	const char *base;
 	/* Skip over the disk name in MSDOS pathnames. */
-	if (has_dos_drive_prefix(path))
-		path += 2;
+	path += offset_1st_component(path, 0);
 	for (base = path; *path; path++) {
 		if (is_dir_sep(*path))
 			base = path + 1;
diff --git a/compat/mingw.h b/compat/mingw.h
index 61a6521..1ca3e19 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -302,7 +302,9 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
  * git specific compatibility
  */
 
-#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
+#define has_dos_root_prefix(path) \
+	((is_dir_sep[(path)[0]] && is_dir_sep[(path)[1]]) \
+	 || (isalpha(*(path)) && (path)[1] == ':'))
 #define is_dir_sep(c) ((c) == '/' || (c) == '\\')
 static inline char *mingw_find_last_dir_sep(const char *path)
 {
diff --git a/connect.c b/connect.c
index 55a85ad..3d9f7fe 100644
--- a/connect.c
+++ b/connect.c
@@ -521,7 +521,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
 		end = host;
 
 	path = strchr(end, c);
-	if (path && !has_dos_drive_prefix(end)) {
+	if (path && (!isalpha(*end) || end[1] != ':')) {
 		if (c == ':') {
 			protocol = PROTO_SSH;
 			*path++ = '\0';
diff --git a/git-compat-util.h b/git-compat-util.h
index 35b095e..c6656e2 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -216,8 +216,8 @@ extern char *gitbasename(char *);
 #define STRIP_EXTENSION ""
 #endif
 
-#ifndef has_dos_drive_prefix
-#define has_dos_drive_prefix(path) 0
+#ifndef has_dos_root_prefix
+#define has_dos_root_prefix(path) 0
 #endif
 
 #ifndef is_dir_sep
diff --git a/path.c b/path.c
index 66acd24..0e4e2d7 100644
--- a/path.c
+++ b/path.c
@@ -498,11 +498,12 @@ const char *relative_path(const char *abs, const char *base)
 int normalize_path_copy(char *dst, const char *src)
 {
 	char *dst0;
+	int i, len;
 
-	if (has_dos_drive_prefix(src)) {
+	len = offset_1st_component(src, 1);
+	for (i = 0; i < len; i++)
 		*dst++ = *src++;
-		*dst++ = *src++;
-	}
+
 	dst0 = dst;
 
 	if (is_dir_sep(*src)) {
@@ -702,9 +703,18 @@ int daemon_avoid_alias(const char *p)
 	}
 }
 
-int offset_1st_component(const char *path)
+int offset_1st_component(const char *path, int keep_root)
 {
-	if (has_dos_drive_prefix(path))
-		return 2 + is_dir_sep(path[2]);
-	return is_dir_sep(path[0]);
+	if (has_dos_root_prefix(path)) {
+		if (path[1] == ':')
+			return 2 + (keep_root ? 0 : is_dir_sep(path[2]));
+		else {
+			const char *s = strchr(path + 2, '/');
+			/* //host is considered a "drive" */
+			if (s)
+				return s - path + (keep_root ? 0 : 1);
+		}
+	}
+
+	return keep_root ? 0 : is_dir_sep(path[0]);
 }
diff --git a/read-cache.c b/read-cache.c
index 2f8159f..d4d339a 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -755,7 +755,7 @@ int verify_path(const char *path)
 {
 	char c;
 
-	if (has_dos_drive_prefix(path))
+	if (has_dos_root_prefix(path))
 		return 0;
 
 	goto inside;
diff --git a/setup.c b/setup.c
index 9139bee..e010cf8 100644
--- a/setup.c
+++ b/setup.c
@@ -26,7 +26,7 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path)
 		if (!work_tree)
 			goto error_out;
 		len = strlen(work_tree);
-		root_len = offset_1st_component(work_tree);
+		root_len = offset_1st_component(work_tree, 0);
 		total = strlen(sanitized) + 1;
 		if (strncmp(sanitized, work_tree, len) ||
 		    (len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
@@ -587,7 +587,7 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
 	if (offset != len) {
 		if (chdir(cwd))
 			die_errno("Cannot come back to cwd");
-		root_len = offset_1st_component(cwd);
+		root_len = offset_1st_component(cwd, 0);
 		cwd[offset > root_len ? offset : root_len] = '\0';
 		set_git_dir(cwd);
 	}
@@ -654,7 +654,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
 		return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
 
 	ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
-	if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
+	if (ceil_offset < 0 && has_dos_root_prefix(cwd))
 		ceil_offset = 1;
 
 	/*
diff --git a/sha1_file.c b/sha1_file.c
index af5cfbd..21ce020 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -102,7 +102,7 @@ int mkdir_in_gitdir(const char *path)
 
 int safe_create_leading_directories(char *path)
 {
-	char *pos = path + offset_1st_component(path);
+	char *pos = path + offset_1st_component(path, 0);
 	struct stat st;
 
 	while (pos) {
diff --git a/transport.c b/transport.c
index 1811b50..5141e8f 100644
--- a/transport.c
+++ b/transport.c
@@ -869,7 +869,7 @@ static int is_local(const char *url)
 	const char *colon = strchr(url, ':');
 	const char *slash = strchr(url, '/');
 	return !colon || (slash && slash < colon) ||
-		has_dos_drive_prefix(url);
+		has_dos_root_prefix(url);
 }
 
 static int is_file(const char *url)
-- 8< --
--
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]