diff options
author | brian m. carlson <sandals@crustytoothpaste.net> | 2019-02-19 00:05:24 +0000 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2019-04-01 11:57:39 +0900 |
commit | 575fa8a3ed5828f01a934fc3337f05a43ccf7679 (patch) | |
tree | 446cbb171d4c30338b57d7f746b76cb868fb1efa | |
parent | dir: make untracked cache extension hash size independent (diff) | |
download | tgif-575fa8a3ed5828f01a934fc3337f05a43ccf7679.tar.xz |
read-cache: read data in a hash-independent way
Index entries are structured with a variety of fields up front, followed
by a hash and one or two flags fields. Because the hash field is stored
in the middle of the structure, it's difficult to use one fixed-size
structure that easily allows access to the hash and flags fields.
Adjust the structure to hold the maximum amount of data that may be
needed using a member called "data" and read and write this field
independently in the various places that need to read and write the
structure.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | read-cache.c | 74 |
1 files changed, 29 insertions, 45 deletions
diff --git a/read-cache.c b/read-cache.c index 4dc6de1b55..da0e411c55 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1640,39 +1640,24 @@ struct ondisk_cache_entry { uint32_t uid; uint32_t gid; uint32_t size; - unsigned char sha1[20]; - uint16_t flags; - char name[FLEX_ARRAY]; /* more */ -}; - -/* - * This struct is used when CE_EXTENDED bit is 1 - * The struct must match ondisk_cache_entry exactly from - * ctime till flags - */ -struct ondisk_cache_entry_extended { - struct cache_time ctime; - struct cache_time mtime; - uint32_t dev; - uint32_t ino; - uint32_t mode; - uint32_t uid; - uint32_t gid; - uint32_t size; - unsigned char sha1[20]; - uint16_t flags; - uint16_t flags2; - char name[FLEX_ARRAY]; /* more */ + /* + * unsigned char hash[hashsz]; + * uint16_t flags; + * if (flags & CE_EXTENDED) + * uint16_t flags2; + */ + unsigned char data[GIT_MAX_RAWSZ + 2 * sizeof(uint16_t)]; + char name[FLEX_ARRAY]; }; /* 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 align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,data) + (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) -#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \ - ondisk_cache_entry_extended_size(ce_namelen(ce)) : \ - ondisk_cache_entry_size(ce_namelen(ce))) +#define ondisk_data_size(flags, len) (the_hash_algo->rawsz + \ + ((flags & CE_EXTENDED) ? 2 : 1) * sizeof(uint16_t) + len) +#define ondisk_data_size_max(len) (ondisk_data_size(CE_EXTENDED, len)) +#define ondisk_ce_size(ce) (ondisk_cache_entry_size(ondisk_data_size((ce)->ce_flags, ce_namelen(ce)))) /* Allow fsck to force verification of the index checksum. */ int verify_index_checksum; @@ -1746,6 +1731,8 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool, struct cache_entry *ce; size_t len; const char *name; + const unsigned hashsz = the_hash_algo->rawsz; + const uint16_t *flagsp = (const uint16_t *)(ondisk->data + hashsz); unsigned int flags; size_t copy_len = 0; /* @@ -1758,22 +1745,20 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool, int expand_name_field = version == 4; /* On-disk flags are just 16 bits */ - flags = get_be16(&ondisk->flags); + flags = get_be16(flagsp); len = flags & CE_NAMEMASK; if (flags & CE_EXTENDED) { - struct ondisk_cache_entry_extended *ondisk2; int extended_flags; - ondisk2 = (struct ondisk_cache_entry_extended *)ondisk; - extended_flags = get_be16(&ondisk2->flags2) << 16; + extended_flags = get_be16(flagsp + 1) << 16; /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */ if (extended_flags & ~CE_EXTENDED_FLAGS) die(_("unknown index entry format 0x%08x"), extended_flags); flags |= extended_flags; - name = ondisk2->name; + name = (const char *)(flagsp + 2); } else - name = ondisk->name; + name = (const char *)(flagsp + 1); if (expand_name_field) { const unsigned char *cp = (const unsigned char *)name; @@ -1812,7 +1797,9 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool, ce->ce_flags = flags & ~CE_NAMEMASK; ce->ce_namelen = len; ce->index = 0; - hashcpy(ce->oid.hash, ondisk->sha1); + hashcpy(ce->oid.hash, ondisk->data); + memcpy(ce->name, name, len); + ce->name[len] = '\0'; if (expand_name_field) { if (copy_len) @@ -2556,6 +2543,8 @@ static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce) { short flags; + const unsigned hashsz = the_hash_algo->rawsz; + uint16_t *flagsp = (uint16_t *)(ondisk->data + hashsz); ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec); ondisk->mtime.sec = htonl(ce->ce_stat_data.sd_mtime.sec); @@ -2567,15 +2556,13 @@ static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, ondisk->uid = htonl(ce->ce_stat_data.sd_uid); ondisk->gid = htonl(ce->ce_stat_data.sd_gid); ondisk->size = htonl(ce->ce_stat_data.sd_size); - hashcpy(ondisk->sha1, ce->oid.hash); + hashcpy(ondisk->data, ce->oid.hash); flags = ce->ce_flags & ~CE_NAMEMASK; flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce)); - ondisk->flags = htons(flags); + flagsp[0] = htons(flags); if (ce->ce_flags & CE_EXTENDED) { - struct ondisk_cache_entry_extended *ondisk2; - ondisk2 = (struct ondisk_cache_entry_extended *)ondisk; - ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16); + flagsp[1] = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16); } } @@ -2594,10 +2581,7 @@ static int ce_write_entry(git_hash_ctx *c, int fd, struct cache_entry *ce, stripped_name = 1; } - if (ce->ce_flags & CE_EXTENDED) - size = offsetof(struct ondisk_cache_entry_extended, name); - else - size = offsetof(struct ondisk_cache_entry, name); + size = offsetof(struct ondisk_cache_entry,data) + ondisk_data_size(ce->ce_flags, 0); if (!previous_name) { int len = ce_namelen(ce); @@ -2755,7 +2739,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, struct cache_entry **cache = istate->cache; int entries = istate->cache_nr; struct stat st; - struct ondisk_cache_entry_extended ondisk; + struct ondisk_cache_entry ondisk; struct strbuf previous_name_buf = STRBUF_INIT, *previous_name; int drop_cache_tree = istate->drop_cache_tree; off_t offset; |