Skip to content

Commit 575fa8a

Browse files
bk2204gitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3899b88 commit 575fa8a

File tree

1 file changed

+29
-45
lines changed

1 file changed

+29
-45
lines changed

read-cache.c

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,39 +1640,24 @@ struct ondisk_cache_entry {
16401640
uint32_t uid;
16411641
uint32_t gid;
16421642
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];
16661651
};
16671652

16681653
/* These are only used for v3 or lower */
16691654
#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)
16711656
#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))))
16761661

16771662
/* Allow fsck to force verification of the index checksum. */
16781663
int verify_index_checksum;
@@ -1746,6 +1731,8 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
17461731
struct cache_entry *ce;
17471732
size_t len;
17481733
const char *name;
1734+
const unsigned hashsz = the_hash_algo->rawsz;
1735+
const uint16_t *flagsp = (const uint16_t *)(ondisk->data + hashsz);
17491736
unsigned int flags;
17501737
size_t copy_len = 0;
17511738
/*
@@ -1758,22 +1745,20 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
17581745
int expand_name_field = version == 4;
17591746

17601747
/* On-disk flags are just 16 bits */
1761-
flags = get_be16(&ondisk->flags);
1748+
flags = get_be16(flagsp);
17621749
len = flags & CE_NAMEMASK;
17631750

17641751
if (flags & CE_EXTENDED) {
1765-
struct ondisk_cache_entry_extended *ondisk2;
17661752
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;
17691754
/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
17701755
if (extended_flags & ~CE_EXTENDED_FLAGS)
17711756
die(_("unknown index entry format 0x%08x"), extended_flags);
17721757
flags |= extended_flags;
1773-
name = ondisk2->name;
1758+
name = (const char *)(flagsp + 2);
17741759
}
17751760
else
1776-
name = ondisk->name;
1761+
name = (const char *)(flagsp + 1);
17771762

17781763
if (expand_name_field) {
17791764
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,
18121797
ce->ce_flags = flags & ~CE_NAMEMASK;
18131798
ce->ce_namelen = len;
18141799
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';
18161803

18171804
if (expand_name_field) {
18181805
if (copy_len)
@@ -2556,6 +2543,8 @@ static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
25562543
struct cache_entry *ce)
25572544
{
25582545
short flags;
2546+
const unsigned hashsz = the_hash_algo->rawsz;
2547+
uint16_t *flagsp = (uint16_t *)(ondisk->data + hashsz);
25592548

25602549
ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec);
25612550
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,
25672556
ondisk->uid = htonl(ce->ce_stat_data.sd_uid);
25682557
ondisk->gid = htonl(ce->ce_stat_data.sd_gid);
25692558
ondisk->size = htonl(ce->ce_stat_data.sd_size);
2570-
hashcpy(ondisk->sha1, ce->oid.hash);
2559+
hashcpy(ondisk->data, ce->oid.hash);
25712560

25722561
flags = ce->ce_flags & ~CE_NAMEMASK;
25732562
flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce));
2574-
ondisk->flags = htons(flags);
2563+
flagsp[0] = htons(flags);
25752564
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);
25792566
}
25802567
}
25812568

@@ -2594,10 +2581,7 @@ static int ce_write_entry(git_hash_ctx *c, int fd, struct cache_entry *ce,
25942581
stripped_name = 1;
25952582
}
25962583

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);
26012585

26022586
if (!previous_name) {
26032587
int len = ce_namelen(ce);
@@ -2755,7 +2739,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
27552739
struct cache_entry **cache = istate->cache;
27562740
int entries = istate->cache_nr;
27572741
struct stat st;
2758-
struct ondisk_cache_entry_extended ondisk;
2742+
struct ondisk_cache_entry ondisk;
27592743
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
27602744
int drop_cache_tree = istate->drop_cache_tree;
27612745
off_t offset;

0 commit comments

Comments
 (0)