diff options
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 110 |
1 files changed, 60 insertions, 50 deletions
diff --git a/read-cache.c b/read-cache.c index acfb028f48..cdcd11c71e 100644 --- a/read-cache.c +++ b/read-cache.c @@ -160,9 +160,9 @@ static int ce_compare_data(const struct cache_entry *ce, struct stat *st) int fd = git_open_cloexec(ce->name, O_RDONLY); if (fd >= 0) { - unsigned char sha1[20]; - if (!index_fd(sha1, fd, st, OBJ_BLOB, ce->name, 0)) - match = hashcmp(sha1, ce->oid.hash); + struct object_id oid; + if (!index_fd(&oid, fd, st, OBJ_BLOB, ce->name, 0)) + match = oidcmp(&oid, &ce->oid); /* index_fd() closed the file descriptor already */ } return match; @@ -689,7 +689,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, return 0; } if (!intent_only) { - if (index_path(ce->oid.hash, path, st, HASH_WRITE_OBJECT)) { + if (index_path(&ce->oid, path, st, HASH_WRITE_OBJECT)) { free(ce); return error("unable to index file %s", path); } @@ -1499,6 +1499,7 @@ struct ondisk_cache_entry_extended { }; /* These are only used for v3 or lower */ +#define align_padding_size(size, len) ((size + (len) + 8) & ~7) - (size + len) #define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7) #define ondisk_cache_entry_size(len) align_flex_name(ondisk_cache_entry,len) #define ondisk_cache_entry_extended_size(len) align_flex_name(ondisk_cache_entry_extended,len) @@ -1921,7 +1922,7 @@ static int ce_write_flush(git_SHA_CTX *context, int fd) unsigned int buffered = write_buffer_len; if (buffered) { git_SHA1_Update(context, write_buffer, buffered); - if (write_in_full(fd, write_buffer, buffered) != buffered) + if (write_in_full(fd, write_buffer, buffered) < 0) return -1; write_buffer_len = 0; } @@ -1970,7 +1971,7 @@ static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1) /* Flush first if not enough space for SHA1 signature */ if (left + 20 > WRITE_BUFFER_SIZE) { - if (write_in_full(fd, write_buffer, left) != left) + if (write_in_full(fd, write_buffer, left) < 0) return -1; left = 0; } @@ -1979,7 +1980,7 @@ static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1) git_SHA1_Final(write_buffer + left, context); hashcpy(sha1, write_buffer + left); left += 20; - return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0; + return (write_in_full(fd, write_buffer, left) < 0) ? -1 : 0; } static void ce_smudge_racily_clean_entry(struct cache_entry *ce) @@ -2032,7 +2033,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) } /* Copy miscellaneous fields but not the name */ -static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, +static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce) { short flags; @@ -2056,32 +2057,35 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, struct ondisk_cache_entry_extended *ondisk2; ondisk2 = (struct ondisk_cache_entry_extended *)ondisk; ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16); - return ondisk2->name; - } - else { - return ondisk->name; } } static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce, - struct strbuf *previous_name) + struct strbuf *previous_name, struct ondisk_cache_entry *ondisk) { int size; - struct ondisk_cache_entry *ondisk; int saved_namelen = saved_namelen; /* compiler workaround */ - char *name; int result; + static unsigned char padding[8] = { 0x00 }; if (ce->ce_flags & CE_STRIP_NAME) { saved_namelen = ce_namelen(ce); ce->ce_namelen = 0; } + if (ce->ce_flags & CE_EXTENDED) + size = offsetof(struct ondisk_cache_entry_extended, name); + else + size = offsetof(struct ondisk_cache_entry, name); + if (!previous_name) { - size = ondisk_ce_size(ce); - ondisk = xcalloc(1, size); - name = copy_cache_entry_to_ondisk(ondisk, ce); - memcpy(name, ce->name, ce_namelen(ce)); + int len = ce_namelen(ce); + copy_cache_entry_to_ondisk(ondisk, ce); + result = ce_write(c, fd, ondisk, size); + if (!result) + result = ce_write(c, fd, ce->name, len); + if (!result) + result = ce_write(c, fd, padding, align_padding_size(size, len)); } else { int common, to_remove, prefix_size; unsigned char to_remove_vi[16]; @@ -2094,16 +2098,14 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce, to_remove = previous_name->len - common; prefix_size = encode_varint(to_remove, to_remove_vi); - if (ce->ce_flags & CE_EXTENDED) - size = offsetof(struct ondisk_cache_entry_extended, name); - else - size = offsetof(struct ondisk_cache_entry, name); - size += prefix_size + (ce_namelen(ce) - common + 1); - - ondisk = xcalloc(1, size); - name = copy_cache_entry_to_ondisk(ondisk, ce); - memcpy(name, to_remove_vi, prefix_size); - memcpy(name + prefix_size, ce->name + common, ce_namelen(ce) - common); + copy_cache_entry_to_ondisk(ondisk, ce); + result = ce_write(c, fd, ondisk, size); + if (!result) + result = ce_write(c, fd, to_remove_vi, prefix_size); + if (!result) + result = ce_write(c, fd, ce->name + common, ce_namelen(ce) - common); + if (!result) + result = ce_write(c, fd, padding, 1); strbuf_splice(previous_name, common, to_remove, ce->name + common, ce_namelen(ce) - common); @@ -2113,8 +2115,6 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce, ce->ce_flags &= ~CE_STRIP_NAME; } - result = ce_write(c, fd, ondisk, size); - free(ondisk); return result; } @@ -2192,10 +2192,11 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, int newfd = tempfile->fd; git_SHA_CTX c; struct cache_header hdr; - int i, err, removed, extended, hdr_version; + int i, err = 0, removed, extended, hdr_version; struct cache_entry **cache = istate->cache; int entries = istate->cache_nr; struct stat st; + struct ondisk_cache_entry_extended ondisk; struct strbuf previous_name_buf = STRBUF_INIT, *previous_name; int drop_cache_tree = 0; @@ -2232,6 +2233,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, return -1; previous_name = (hdr_version == 4) ? &previous_name_buf : NULL; + for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; if (ce->ce_flags & CE_REMOVE) @@ -2247,15 +2249,21 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, if (allow) warning(msg, ce->name); else - return error(msg, ce->name); + err = error(msg, ce->name); drop_cache_tree = 1; } - if (ce_write_entry(&c, newfd, ce, previous_name) < 0) - return -1; + if (ce_write_entry(&c, newfd, ce, previous_name, (struct ondisk_cache_entry *)&ondisk) < 0) + err = -1; + + if (err) + break; } strbuf_release(&previous_name_buf); + if (err) + return err; + /* Write extension data here */ if (!strip_extensions && istate->split_index) { struct strbuf sb = STRBUF_INIT; @@ -2303,8 +2311,11 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, if (ce_flush(&c, newfd, istate->sha1)) return -1; - if (close_tempfile(tempfile)) - return error(_("could not close '%s'"), tempfile->filename.buf); + if (close_tempfile_gently(tempfile)) { + error(_("could not close '%s'"), tempfile->filename.buf); + delete_tempfile(&tempfile); + return -1; + } if (stat(tempfile->filename.buf, &st)) return -1; istate->timestamp.sec = (unsigned int)st.st_mtime; @@ -2328,7 +2339,7 @@ static int commit_locked_index(struct lock_file *lk) static int do_write_locked_index(struct index_state *istate, struct lock_file *lock, unsigned flags) { - int ret = do_write_index(istate, &lock->tempfile, 0); + int ret = do_write_index(istate, lock->tempfile, 0); if (ret) return ret; assert((flags & (COMMIT_LOCK | CLOSE_LOCK)) != @@ -2336,7 +2347,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l if (flags & COMMIT_LOCK) return commit_locked_index(lock); else if (flags & CLOSE_LOCK) - return close_lock_file(lock); + return close_lock_file_gently(lock); else return ret; } @@ -2411,34 +2422,33 @@ static int clean_shared_index_files(const char *current_hex) return 0; } -static struct tempfile temporary_sharedindex; - static int write_shared_index(struct index_state *istate, struct lock_file *lock, unsigned flags) { + struct tempfile *temp; struct split_index *si = istate->split_index; - int fd, ret; + int ret; - fd = mks_tempfile(&temporary_sharedindex, git_path("sharedindex_XXXXXX")); - if (fd < 0) { + temp = mks_tempfile(git_path("sharedindex_XXXXXX")); + if (!temp) { hashclr(si->base_sha1); return do_write_locked_index(istate, lock, flags); } move_cache_to_base_index(istate); - ret = do_write_index(si->base, &temporary_sharedindex, 1); + ret = do_write_index(si->base, temp, 1); if (ret) { - delete_tempfile(&temporary_sharedindex); + delete_tempfile(&temp); return ret; } - ret = adjust_shared_perm(get_tempfile_path(&temporary_sharedindex)); + ret = adjust_shared_perm(get_tempfile_path(temp)); if (ret) { int save_errno = errno; - error("cannot fix permission bits on %s", get_tempfile_path(&temporary_sharedindex)); - delete_tempfile(&temporary_sharedindex); + error("cannot fix permission bits on %s", get_tempfile_path(temp)); + delete_tempfile(&temp); errno = save_errno; return ret; } - ret = rename_tempfile(&temporary_sharedindex, + ret = rename_tempfile(&temp, git_path("sharedindex.%s", sha1_to_hex(si->base->sha1))); if (!ret) { hashcpy(si->base_sha1, si->base->sha1); |