28
28
#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
29
29
#define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */
30
30
#define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */
31
- #define MIDX_CHUNKLOOKUP_WIDTH (sizeof(uint32_t) + sizeof(uint64_t))
32
31
#define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256)
33
32
#define MIDX_CHUNK_OFFSET_WIDTH (2 * sizeof(uint32_t))
34
33
#define MIDX_CHUNK_LARGE_OFFSET_WIDTH (sizeof(uint64_t))
@@ -53,6 +52,19 @@ static char *get_midx_filename(const char *object_dir)
53
52
return xstrfmt ("%s/pack/multi-pack-index" , object_dir );
54
53
}
55
54
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
+
56
68
struct multi_pack_index * load_multi_pack_index (const char * object_dir , int local )
57
69
{
58
70
struct multi_pack_index * m = NULL ;
@@ -64,6 +76,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
64
76
char * midx_name = get_midx_filename (object_dir );
65
77
uint32_t i ;
66
78
const char * cur_pack_name ;
79
+ struct chunkfile * cf = NULL ;
67
80
68
81
fd = git_open (midx_name );
69
82
@@ -113,58 +126,23 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
113
126
114
127
m -> num_packs = get_be32 (m -> data + MIDX_BYTE_NUM_PACKS );
115
128
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 );
158
130
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 )
160
136
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 )
162
138
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 )
164
140
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 )
166
142
die (_ ("multi-pack-index missing required object offsets chunk" ));
167
143
144
+ pair_chunk (cf , MIDX_CHUNKID_LARGEOFFSETS , & m -> chunk_large_offsets );
145
+
168
146
m -> num_objects = ntohl (m -> chunk_oid_fanout [255 ]);
169
147
170
148
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
190
168
cleanup_fail :
191
169
free (m );
192
170
free (midx_name );
171
+ free (cf );
193
172
if (midx_map )
194
173
munmap (midx_map , midx_size );
195
174
if (0 <= fd )
0 commit comments