2828#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
2929#define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */
3030#define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */
31- #define MIDX_CHUNKLOOKUP_WIDTH (sizeof(uint32_t) + sizeof(uint64_t))
3231#define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256)
3332#define MIDX_CHUNK_OFFSET_WIDTH (2 * sizeof(uint32_t))
3433#define MIDX_CHUNK_LARGE_OFFSET_WIDTH (sizeof(uint64_t))
@@ -53,6 +52,19 @@ static char *get_midx_filename(const char *object_dir)
5352 return xstrfmt ("%s/pack/multi-pack-index" , object_dir );
5453}
5554
55+ static int midx_read_oid_fanout (const unsigned char * chunk_start ,
56+ size_t chunk_size , void * data )
57+ {
58+ struct multi_pack_index * m = data ;
59+ m -> chunk_oid_fanout = (uint32_t * )chunk_start ;
60+
61+ if (chunk_size != 4 * 256 ) {
62+ error (_ ("multi-pack-index OID fanout is of the wrong size" ));
63+ return 1 ;
64+ }
65+ return 0 ;
66+ }
67+
5668struct multi_pack_index * load_multi_pack_index (const char * object_dir , int local )
5769{
5870 struct multi_pack_index * m = NULL ;
@@ -64,6 +76,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
6476 char * midx_name = get_midx_filename (object_dir );
6577 uint32_t i ;
6678 const char * cur_pack_name ;
79+ struct chunkfile * cf = NULL ;
6780
6881 fd = git_open (midx_name );
6982
@@ -113,58 +126,23 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
113126
114127 m -> num_packs = get_be32 (m -> data + MIDX_BYTE_NUM_PACKS );
115128
116- for (i = 0 ; i < m -> num_chunks ; i ++ ) {
117- uint32_t chunk_id = get_be32 (m -> data + MIDX_HEADER_SIZE +
118- MIDX_CHUNKLOOKUP_WIDTH * i );
119- uint64_t chunk_offset = get_be64 (m -> data + MIDX_HEADER_SIZE + 4 +
120- MIDX_CHUNKLOOKUP_WIDTH * i );
121-
122- if (chunk_offset >= m -> data_len )
123- die (_ ("invalid chunk offset (too large)" ));
124-
125- switch (chunk_id ) {
126- case MIDX_CHUNKID_PACKNAMES :
127- m -> chunk_pack_names = m -> data + chunk_offset ;
128- break ;
129-
130- case MIDX_CHUNKID_OIDFANOUT :
131- m -> chunk_oid_fanout = (uint32_t * )(m -> data + chunk_offset );
132- break ;
133-
134- case MIDX_CHUNKID_OIDLOOKUP :
135- m -> chunk_oid_lookup = m -> data + chunk_offset ;
136- break ;
137-
138- case MIDX_CHUNKID_OBJECTOFFSETS :
139- m -> chunk_object_offsets = m -> data + chunk_offset ;
140- break ;
141-
142- case MIDX_CHUNKID_LARGEOFFSETS :
143- m -> chunk_large_offsets = m -> data + chunk_offset ;
144- break ;
145-
146- case 0 :
147- die (_ ("terminating multi-pack-index chunk id appears earlier than expected" ));
148- break ;
149-
150- default :
151- /*
152- * Do nothing on unrecognized chunks, allowing future
153- * extensions to add optional chunks.
154- */
155- break ;
156- }
157- }
129+ cf = init_chunkfile (NULL );
158130
159- if (!m -> chunk_pack_names )
131+ if (read_table_of_contents (cf , m -> data , midx_size ,
132+ MIDX_HEADER_SIZE , m -> num_chunks ))
133+ goto cleanup_fail ;
134+
135+ if (pair_chunk (cf , MIDX_CHUNKID_PACKNAMES , & m -> chunk_pack_names ) == CHUNK_NOT_FOUND )
160136 die (_ ("multi-pack-index missing required pack-name chunk" ));
161- if (! m -> chunk_oid_fanout )
137+ if (read_chunk ( cf , MIDX_CHUNKID_OIDFANOUT , midx_read_oid_fanout , m ) == CHUNK_NOT_FOUND )
162138 die (_ ("multi-pack-index missing required OID fanout chunk" ));
163- if (! m -> chunk_oid_lookup )
139+ if (pair_chunk ( cf , MIDX_CHUNKID_OIDLOOKUP , & m -> chunk_oid_lookup ) == CHUNK_NOT_FOUND )
164140 die (_ ("multi-pack-index missing required OID lookup chunk" ));
165- if (! m -> chunk_object_offsets )
141+ if (pair_chunk ( cf , MIDX_CHUNKID_OBJECTOFFSETS , & m -> chunk_object_offsets ) == CHUNK_NOT_FOUND )
166142 die (_ ("multi-pack-index missing required object offsets chunk" ));
167143
144+ pair_chunk (cf , MIDX_CHUNKID_LARGEOFFSETS , & m -> chunk_large_offsets );
145+
168146 m -> num_objects = ntohl (m -> chunk_oid_fanout [255 ]);
169147
170148 m -> pack_names = xcalloc (m -> num_packs , sizeof (* m -> pack_names ));
@@ -190,6 +168,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
190168cleanup_fail :
191169 free (m );
192170 free (midx_name );
171+ free (cf );
193172 if (midx_map )
194173 munmap (midx_map , midx_size );
195174 if (0 <= fd )
0 commit comments