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;