X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=read-cache.c;h=f67aceb6b12f6d9cadf6a80bb1d33cf1bcd7f619;hb=c5b423860d4a0f2c1144c578207f327e0985bba7;hp=bfa2de767a9be1dfb4c53ebc21784741c1f49b77;hpb=0fcfd160b0495c0881e142c546c4418b8cea7e93;p=git.git diff --git a/read-cache.c b/read-cache.c index bfa2de76..f67aceb6 100644 --- a/read-cache.c +++ b/read-cache.c @@ -24,9 +24,9 @@ int cache_match_stat(struct cache_entry *ce, struct stat *st) * as long as it is in the inode cache you get right nsec * but after it gets flushed, you get zero nsec. */ - if (ce->ce_mtime.nsec != htonl(st->st_mtim.tv_nsec) + if (ce->ce_mtime.nsec != htonl(st->st_mtim.tv_nsec)) changed |= MTIME_CHANGED; - if (ce->ce_ctime.nsec != htonl(st->st_ctim.tv_nsec) + if (ce->ce_ctime.nsec != htonl(st->st_ctim.tv_nsec)) changed |= CTIME_CHANGED; #endif @@ -87,7 +87,7 @@ int cache_name_pos(const char *name, int namelen) } /* Remove entry, return true if there are more entries to go.. */ -static int remove_entry_at(int pos) +int remove_entry_at(int pos) { active_nr--; if (pos >= active_nr) @@ -106,7 +106,7 @@ int remove_file_from_cache(char *path) return 0; } -static int same_name(struct cache_entry *a, struct cache_entry *b) +int same_name(struct cache_entry *a, struct cache_entry *b) { int len = ce_namelen(a); return ce_namelen(b) == len && !memcmp(a->name, b->name, len); @@ -161,14 +161,13 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size) if (hdr->hdr_signature != htonl(CACHE_SIGNATURE)) return error("bad signature"); - if (hdr->hdr_version != htonl(1)) - return error("bad version"); + if (hdr->hdr_version != htonl(2)) + return error("bad index version"); SHA1_Init(&c); - SHA1_Update(&c, hdr, offsetof(struct cache_header, sha1)); - SHA1_Update(&c, hdr+1, size - sizeof(*hdr)); + SHA1_Update(&c, hdr, size - 20); SHA1_Final(sha1, &c); - if (memcmp(sha1, hdr->sha1, 20)) - return error("bad header sha1"); + if (memcmp(sha1, (void *)hdr + size - 20, 20)) + return error("bad index file sha1 signature"); return 0; } @@ -189,7 +188,7 @@ int read_cache(void) sha1_file_directory = DEFAULT_DB_ENVIRONMENT; if (access(sha1_file_directory, X_OK) < 0) return error("no access to SHA1 file directory"); - fd = open(".git/index", O_RDONLY); + fd = open(get_index_file(), O_RDONLY); if (fd < 0) return (errno == ENOENT) ? 0 : error("open failed"); @@ -198,7 +197,7 @@ int read_cache(void) if (!fstat(fd, &st)) { size = st.st_size; errno = EINVAL; - if (size >= sizeof(struct cache_header)) + if (size >= sizeof(struct cache_header) + 20) map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); } close(fd); @@ -227,6 +226,49 @@ unmap: return error("verify header failed"); } +#define WRITE_BUFFER_SIZE 8192 +static char write_buffer[WRITE_BUFFER_SIZE]; +static unsigned long write_buffer_len; + +static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len) +{ + while (len) { + unsigned int buffered = write_buffer_len; + unsigned int partial = WRITE_BUFFER_SIZE - buffered; + if (partial > len) + partial = len; + memcpy(write_buffer + buffered, data, partial); + buffered += partial; + if (buffered == WRITE_BUFFER_SIZE) { + SHA1_Update(context, write_buffer, WRITE_BUFFER_SIZE); + if (write(fd, write_buffer, WRITE_BUFFER_SIZE) != WRITE_BUFFER_SIZE) + return -1; + buffered = 0; + } + write_buffer_len = buffered; + len -= partial; + data += partial; + } + return 0; +} + +static int ce_flush(SHA_CTX *context, int fd) +{ + unsigned int left = write_buffer_len; + + if (left) { + write_buffer_len = 0; + SHA1_Update(context, write_buffer, left); + } + + /* Append the SHA1 signature at the end */ + SHA1_Final(write_buffer + left, context); + left += 20; + if (write(fd, write_buffer, left) != left) + return -1; + return 0; +} + int write_cache(int newfd, struct cache_entry **cache, int entries) { SHA_CTX c; @@ -234,26 +276,17 @@ int write_cache(int newfd, struct cache_entry **cache, int entries) int i; hdr.hdr_signature = htonl(CACHE_SIGNATURE); - hdr.hdr_version = htonl(1); + hdr.hdr_version = htonl(2); hdr.hdr_entries = htonl(entries); SHA1_Init(&c); - SHA1_Update(&c, &hdr, offsetof(struct cache_header, sha1)); - for (i = 0; i < entries; i++) { - struct cache_entry *ce = cache[i]; - int size = ce_size(ce); - SHA1_Update(&c, ce, size); - } - SHA1_Final(hdr.sha1, &c); - - if (write(newfd, &hdr, sizeof(hdr)) != sizeof(hdr)) + if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0) return -1; for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; - int size = ce_size(ce); - if (write(newfd, ce, size) != size) + if (ce_write(&c, newfd, ce, ce_size(ce)) < 0) return -1; } - return 0; + return ce_flush(&c, newfd); }