diff --git a/cache.h b/cache.h
index 107ac61..b0eedad 100644
--- a/cache.h
+++ b/cache.h
@@ -279,6 +279,7 @@ struct index_state {
initialized : 1;
struct hashmap name_hash;
struct hashmap dir_hash;
+ unsigned char sha1[20];
};
extern struct index_state the_index;@@ -456,6 +457,8 @@ extern int daemonize(void);
} while (0)
/* Initialize and use the cache information */
+extern int verify_index_from(const struct index_state *, const char *path);
+extern int verify_index(struct index_state *);
extern int read_index(struct index_state *);
extern int read_index_preload(struct index_state *, const struct pathspec *pathspec);
extern int read_index_from(struct index_state *, const char *path);
diff --git a/read-cache.c b/read-cache.c
index ba13353..fac8655 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -14,6 +14,7 @@
#include "resolve-undo.h"
#include "strbuf.h"
#include "varint.h"
+#include "git-compat-util.h"
static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
unsigned int options);
@@ -1321,6 +1322,59 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
return 0;
}
+/* This function verifies if index_state has the correct sha1 of an index file.
+ * Don't die if we have any other failure, just return 0. */
+int verify_index_from(const struct index_state *istate, const char *path)
+{
+ int fd;
+ struct stat st;
+ struct cache_header *hdr;
+ void *mmap_addr;
+ size_t mmap_size;
+
+ if (!istate->initialized)
+ return 0;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return 0;
+
+ if (fstat(fd, &st))
+ return 0;
+
+ /* file is too big */
+ if (st.st_size > (size_t)st.st_size)
+ return 0;
+
+ mmap_size = (size_t)st.st_size;
+ if (mmap_size < sizeof(struct cache_header) + 20)
+ return 0;
+
+ mmap_addr = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ close(fd);
+ if (mmap_addr == MAP_FAILED)
+ return 0;
+
+ hdr = mmap_addr;
+ if (verify_hdr(hdr, mmap_size) < 0)
+ goto unmap;
+
+ if (hashcmp(istate->sha1, (unsigned char *)hdr + mmap_size - 20))
+ goto unmap;
+
+ munmap(mmap_addr, mmap_size);
+ return 1;
+
+unmap:
+ munmap(mmap_addr, mmap_size);
+ return 0;
+}
+
+int verify_index(struct index_state *istate)
+{
+ return verify_index_from(istate, get_index_file());
+}
+
static int read_index_extension(struct index_state *istate,
const char *ext, void *data, unsigned long sz)
{@@ -1445,7 +1499,7 @@ int read_index_from(struct index_state *istate, const char *path)
struct stat st;
unsigned long src_offset;
struct cache_header *hdr;
- void *mmap;
+ void *mmap_addr;
size_t mmap_size;
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
@@ -1468,15 +1522,16 @@ int read_index_from(struct index_state *istate, const char *path)
if (mmap_size < sizeof(struct cache_header) + 20)
die("index file smaller than expected");
- mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (mmap == MAP_FAILED)
+ mmap_addr = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (mmap_addr == MAP_FAILED)
die_errno("unable to map index file");
close(fd);
- hdr = mmap;
+ hdr = mmap_addr;
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);@@ -1494,7 +1549,7 @@ int read_index_from(struct index_state *istate, const char *path)
struct cache_entry *ce;
unsigned long consumed;
- disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
+ disk_ce = (struct ondisk_cache_entry *)((char *)mmap_addr + src_offset);
ce = create_from_disk(disk_ce, &consumed, previous_name);
set_index_entry(istate, i, ce);
@@ -1512,21 +1567,21 @@ int read_index_from(struct index_state *istate, const char *path)
* in 4-byte network byte order.
*/
uint32_t extsize;
- memcpy(&extsize, (char *)mmap + src_offset + 4, 4);
+ memcpy(&extsize, (char *)mmap_addr + src_offset + 4, 4);
extsize = ntohl(extsize);
if (read_index_extension(istate,
- (const char *) mmap + src_offset,
- (char *) mmap + src_offset + 8,
+ (const char *) mmap_addr + src_offset,
+ (char *) mmap_addr + src_offset + 8,
extsize) < 0)
goto unmap;
src_offset += 8;
src_offset += extsize;
}
- munmap(mmap, mmap_size);
+ munmap(mmap_addr, mmap_size);
return istate->cache_nr;
unmap:
- munmap(mmap, mmap_size);
+ munmap(mmap_addr, mmap_size);
die("index file corrupt");
}
@@ -1778,8 +1833,10 @@ static int has_racy_timestamp(struct index_state *istate)
*/
void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
{
+ printf("cache_changed: %d has_racy_timestamp: %d\n",
+ istate->cache_changed, has_racy_timestamp(istate));
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);--
1.9.1