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>

brian m. carlson committed Feb 19, 2019 at 00:05 UTC 575fa8a3ed5828f01a934fc3337f05a43ccf7679
1 file changed +29 -45
read-cache.c
+29 -45
@@ -1640,39 +1640,24 @@ struct ondisk_cache_entry {
1640 uint32_t uid;
1641 uint32_t gid;
1642 uint32_t size;
1643 - unsigned char sha1[20];
1644 - uint16_t flags;
1645 - char name[FLEX_ARRAY]; /* more */
1646 -};
1647 -
1648 -/*
1649 - * This struct is used when CE_EXTENDED bit is 1
1650 - * The struct must match ondisk_cache_entry exactly from
1651 - * ctime till flags
1652 - */
1653 -struct ondisk_cache_entry_extended {
1654 - struct cache_time ctime;
1655 - struct cache_time mtime;
1656 - uint32_t dev;
1657 - uint32_t ino;
1658 - uint32_t mode;
1659 - uint32_t uid;
1660 - uint32_t gid;
1661 - uint32_t size;
1662 - unsigned char sha1[20];
1663 - uint16_t flags;
1664 - uint16_t flags2;
1665 - char name[FLEX_ARRAY]; /* more */
1643 + /*
1644 + * unsigned char hash[hashsz];
1645 + * uint16_t flags;
1646 + * if (flags & CE_EXTENDED)
1647 + * uint16_t flags2;
1648 + */
1649 + unsigned char data[GIT_MAX_RAWSZ + 2 * sizeof(uint16_t)];
1650 + char name[FLEX_ARRAY];
1651 };
1652
1653 /* These are only used for v3 or lower */
1654 #define align_padding_size(size, len) ((size + (len) + 8) & ~7) - (size + len)
1670 -#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
1655 +#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,data) + (len) + 8) & ~7)
1656 #define ondisk_cache_entry_size(len) align_flex_name(ondisk_cache_entry,len)
1672 -#define ondisk_cache_entry_extended_size(len) align_flex_name(ondisk_cache_entry_extended,len)
1673 -#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
1674 - ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
1675 - ondisk_cache_entry_size(ce_namelen(ce)))
1657 +#define ondisk_data_size(flags, len) (the_hash_algo->rawsz + \
1658 + ((flags & CE_EXTENDED) ? 2 : 1) * sizeof(uint16_t) + len)
1659 +#define ondisk_data_size_max(len) (ondisk_data_size(CE_EXTENDED, len))
1660 +#define ondisk_ce_size(ce) (ondisk_cache_entry_size(ondisk_data_size((ce)->ce_flags, ce_namelen(ce))))
1661
1662 /* Allow fsck to force verification of the index checksum. */
1663 int verify_index_checksum;
@@ -1746,6 +1731,8 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
1731 struct cache_entry *ce;
1732 size_t len;
1733 const char *name;
1734 + const unsigned hashsz = the_hash_algo->rawsz;
1735 + const uint16_t *flagsp = (const uint16_t *)(ondisk->data + hashsz);
1736 unsigned int flags;
1737 size_t copy_len = 0;
1738 /*
@@ -1758,22 +1745,20 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
1745 int expand_name_field = version == 4;
1746
1747 /* On-disk flags are just 16 bits */
1761 - flags = get_be16(&ondisk->flags);
1748 + flags = get_be16(flagsp);
1749 len = flags & CE_NAMEMASK;
1750
1751 if (flags & CE_EXTENDED) {
1765 - struct ondisk_cache_entry_extended *ondisk2;
1752 int extended_flags;
1767 - ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
1768 - extended_flags = get_be16(&ondisk2->flags2) << 16;
1753 + extended_flags = get_be16(flagsp + 1) << 16;
1754 /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
1755 if (extended_flags & ~CE_EXTENDED_FLAGS)
1756 die(_("unknown index entry format 0x%08x"), extended_flags);
1757 flags |= extended_flags;
1773 - name = ondisk2->name;
1758 + name = (const char *)(flagsp + 2);
1759 }
1760 else
1776 - name = ondisk->name;
1761 + name = (const char *)(flagsp + 1);
1762
1763 if (expand_name_field) {
1764 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,
1797 ce->ce_flags = flags & ~CE_NAMEMASK;
1798 ce->ce_namelen = len;
1799 ce->index = 0;
1815 - hashcpy(ce->oid.hash, ondisk->sha1);
1800 + hashcpy(ce->oid.hash, ondisk->data);
1801 + memcpy(ce->name, name, len);
1802 + ce->name[len] = '\0';
1803
1804 if (expand_name_field) {
1805 if (copy_len)
@@ -2556,6 +2543,8 @@ static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
2543 struct cache_entry *ce)
2544 {
2545 short flags;
2546 + const unsigned hashsz = the_hash_algo->rawsz;
2547 + uint16_t *flagsp = (uint16_t *)(ondisk->data + hashsz);
2548
2549 ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec);
2550 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,
2556 ondisk->uid = htonl(ce->ce_stat_data.sd_uid);
2557 ondisk->gid = htonl(ce->ce_stat_data.sd_gid);
2558 ondisk->size = htonl(ce->ce_stat_data.sd_size);
2570 - hashcpy(ondisk->sha1, ce->oid.hash);
2559 + hashcpy(ondisk->data, ce->oid.hash);
2560
2561 flags = ce->ce_flags & ~CE_NAMEMASK;
2562 flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce));
2574 - ondisk->flags = htons(flags);
2563 + flagsp[0] = htons(flags);
2564 if (ce->ce_flags & CE_EXTENDED) {
2576 - struct ondisk_cache_entry_extended *ondisk2;
2577 - ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
2578 - ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
2565 + flagsp[1] = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
2566 }
2567 }
2568
@@ -2594,10 +2581,7 @@ static int ce_write_entry(git_hash_ctx *c, int fd, struct cache_entry *ce,
2581 stripped_name = 1;
2582 }
2583
2597 - if (ce->ce_flags & CE_EXTENDED)
2598 - size = offsetof(struct ondisk_cache_entry_extended, name);
2599 - else
2600 - size = offsetof(struct ondisk_cache_entry, name);
2584 + size = offsetof(struct ondisk_cache_entry,data) + ondisk_data_size(ce->ce_flags, 0);
2585
2586 if (!previous_name) {
2587 int len = ce_namelen(ce);
@@ -2755,7 +2739,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2739 struct cache_entry **cache = istate->cache;
2740 int entries = istate->cache_nr;
2741 struct stat st;
2758 - struct ondisk_cache_entry_extended ondisk;
2742 + struct ondisk_cache_entry ondisk;
2743 struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
2744 int drop_cache_tree = istate->drop_cache_tree;
2745 off_t offset;