diff options
Diffstat (limited to 'read-cache.c')
| -rw-r--r-- | read-cache.c | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/read-cache.c b/read-cache.c index ba13353b37..6a45966ec4 100644 --- a/read-cache.c +++ b/read-cache.c @@ -422,18 +422,26 @@ int df_name_compare(const char *name1, int len1, int mode1, return c1 - c2; } -int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2) +int name_compare(const char *name1, size_t len1, const char *name2, size_t len2) { - int len = len1 < len2 ? len1 : len2; - int cmp; - - cmp = memcmp(name1, name2, len); + size_t min_len = (len1 < len2) ? len1 : len2; + int cmp = memcmp(name1, name2, min_len); if (cmp) return cmp; if (len1 < len2) return -1; if (len1 > len2) return 1; + return 0; +} + +int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2) +{ + int cmp; + + cmp = name_compare(name1, len1, name2, len2); + if (cmp) + return cmp; if (stage1 < stage2) return -1; @@ -442,11 +450,6 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char return 0; } -int cache_name_compare(const char *name1, int len1, const char *name2, int len2) -{ - return cache_name_stage_compare(name1, len1, 0, name2, len2, 0); -} - static int index_name_stage_pos(const struct index_state *istate, const char *name, int namelen, int stage) { int first, last; @@ -1477,6 +1480,7 @@ int read_index_from(struct index_state *istate, const char *path) if (verify_hdr(hdr, mmap_size) < 0) goto unmap; + hashcpy(istate->sha1, (unsigned char *)hdr + mmap_size - 20); istate->version = ntohl(hdr->hdr_version); istate->cache_nr = ntohl(hdr->hdr_entries); istate->cache_alloc = alloc_nr(istate->cache_nr); @@ -1760,6 +1764,50 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce, return result; } +/* + * This function verifies if index_state has the correct sha1 of the + * index file. Don't die if we have any other failure, just return 0. + */ +static int verify_index_from(const struct index_state *istate, const char *path) +{ + int fd; + ssize_t n; + struct stat st; + unsigned char sha1[20]; + + if (!istate->initialized) + return 0; + + fd = open(path, O_RDONLY); + if (fd < 0) + return 0; + + if (fstat(fd, &st)) + goto out; + + if (st.st_size < sizeof(struct cache_header) + 20) + goto out; + + n = pread_in_full(fd, sha1, 20, st.st_size - 20); + if (n != 20) + goto out; + + if (hashcmp(istate->sha1, sha1)) + goto out; + + close(fd); + return 1; + +out: + close(fd); + return 0; +} + +static int verify_index(const struct index_state *istate) +{ + return verify_index_from(istate, get_index_file()); +} + static int has_racy_timestamp(struct index_state *istate) { int entries = istate->cache_nr; @@ -1779,7 +1827,7 @@ static int has_racy_timestamp(struct index_state *istate) void update_index_if_able(struct index_state *istate, struct lock_file *lockfile) { if ((istate->cache_changed || has_racy_timestamp(istate)) && - !write_index(istate, lockfile->fd)) + verify_index(istate) && !write_index(istate, lockfile->fd)) commit_locked_index(lockfile); else rollback_lock_file(lockfile); |
