[PATCH v2 3/5] sha1_file: improve directories comparison method

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

 



From: Hui Wang <Hui.Wang@xxxxxxxxxxxxx>

In the past, to check if two directory paths are same, we use memcmp()
to directly compare their path strings, this method can't get an
accurate result if paths include ".." or "." or redundant slash, e.g.
current dir is /, "/a/b/c", "/a/b//c/d/e/../.." and "./a/b/f/../c"
should be the same dir, but current method will identify they are
different.

Now add a global function is_same_directory() to replace the old
memcmp() method, this function will change two input paths to real
path first, then normalized them and compare them.

Signed-off-by: Hui Wang <Hui.Wang@xxxxxxxxxxxxx>
---
 abspath.c   |   26 ++++++++++++++++++++++++++
 cache.h     |    1 +
 sha1_file.c |    4 ++--
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/abspath.c b/abspath.c
index 3005aed..7717f06 100644
--- a/abspath.c
+++ b/abspath.c
@@ -138,3 +138,29 @@ const char *absolute_path(const char *path)
 	}
 	return buf;
 }
+
+/* Compare two directories, if they are the same dir, return 1, otherwise
+ * return 0.
+ *
+ * The input path can be relative or absolute one, before the comparison, they
+ * will be changed to real path first, then be normalized to remove .. and
+ * redundant slash, in the end, we will compare two real and normalized paths.
+ */
+int is_same_directory(const char *dir1, const char *dir2)
+{
+	const char *real_path1, *real_path2;
+	char norm_path1[PATH_MAX], norm_path2[PATH_MAX];
+
+	real_path1 = real_path(dir1);
+	if (normalize_path_copy(norm_path1, real_path1))
+		return 0;
+
+	real_path2 = real_path(dir2);
+	if (normalize_path_copy(norm_path2, real_path2))
+		return 0;
+
+	if (strlen(norm_path1) != strlen(norm_path2))
+		return 0;
+
+	return !memcmp(norm_path1, norm_path2, strlen(norm_path1));
+}
diff --git a/cache.h b/cache.h
index e11cf6a..70056b5 100644
--- a/cache.h
+++ b/cache.h
@@ -758,6 +758,7 @@ 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 is_same_directory(const char *dir1, const char *dir2);
 
 /* object replacement */
 #define READ_SHA1_FILE_REPLACE 1
diff --git a/sha1_file.c b/sha1_file.c
index 5940d84..18f7fb3 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -286,12 +286,12 @@ static int link_alt_odb_entry(const char * entry, int len, const char * relative
 	 * thing twice, or object directory itself.
 	 */
 	for (alt = alt_odb_list; alt; alt = alt->next) {
-		if (!memcmp(ent->base, alt->base, pfxlen)) {
+		if (is_same_directory(ent->base, alt->base)) {
 			free(ent);
 			return -1;
 		}
 	}
-	if (!memcmp(ent->base, objdir, pfxlen)) {
+	if (is_same_directory(ent->base, objdir)) {
 		free(ent);
 		return -1;
 	}
-- 
1.6.3.1

--
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]