summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2014-06-30 13:04:03 -0400
committerJunio C Hamano <gitster@pobox.com>2014-06-30 13:43:32 -0700
commit47bf4b0fc52f3ad5823185a85f5f82325787c84b (patch)
tree0a8a268a2db24b7bf1013b8e53e5f9a6a875e56b
parentd6cd00c76866a6412e0c13da91a022acdd187a47 (diff)
downloadgit-jk/strip-suffix.tar.gz
prepare_packed_git_one: refactor duplicate-pack checkjk/strip-suffix
When we are reloading the list of packs, we check whether a particular pack has been loaded. This is slightly tricky, because we load packs based on the presence of their ".idx" files, but record the name of the matching ".pack" file. Therefore we want to compare their bases. The existing code stripped off ".idx" from a file we found, then compared that whole base length to strings containing the ".pack" version. This meant we could end up comparing bytes past what the ".pack" string contained, if the ".idx" file name was much longer. In practice, it worked OK because memcmp would end up seeing a difference in the two strings and would return early before hitting the full length. However, memcmp may sometimes read extra bytes past a difference (e.g., because it is comparing 64-bit words), or is even free to compare in reverse order. Furthermore, our memcmp made no guarantees that we matched the whole pack name, up to ".pack". So "foo.idx" would match "foo-bar.pack", which is wrong (but does not typically happen, because our pack names have a fixed size). We can fix both issues, avoid magic numbers, and document that we expect to compare against a string with ".pack" by using strip_suffix. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--sha1_file.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 93b794f58e..129a4c52df 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1197,6 +1197,7 @@ static void prepare_packed_git_one(char *objdir, int local)
dirnamelen = path.len;
while ((de = readdir(dir)) != NULL) {
struct packed_git *p;
+ size_t base_len;
if (is_dot_or_dotdot(de->d_name))
continue;
@@ -1204,10 +1205,14 @@ static void prepare_packed_git_one(char *objdir, int local)
strbuf_setlen(&path, dirnamelen);
strbuf_addstr(&path, de->d_name);
- if (ends_with(de->d_name, ".idx")) {
+ base_len = path.len;
+ if (strip_suffix_mem(path.buf, &base_len, ".idx")) {
/* Don't reopen a pack we already have. */
for (p = packed_git; p; p = p->next) {
- if (!memcmp(path.buf, p->pack_name, path.len - 4))
+ size_t len;
+ if (strip_suffix(p->pack_name, ".pack", &len) &&
+ len == base_len &&
+ !memcmp(p->pack_name, path.buf, len))
break;
}
if (p == NULL &&