midx: use chunk-format read API
Instead of parsing the table of contents directly, use the chunk-format API methods read_table_of_contents() and pair_chunk(). In particular, we can use the return value of pair_chunk() to generate an error when a required chunk is missing. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
2692c2f6fd
commit
6ab3b8b8b8
71
midx.c
71
midx.c
@ -28,7 +28,6 @@
|
||||
#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
|
||||
#define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */
|
||||
#define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */
|
||||
#define MIDX_CHUNKLOOKUP_WIDTH (sizeof(uint32_t) + sizeof(uint64_t))
|
||||
#define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256)
|
||||
#define MIDX_CHUNK_OFFSET_WIDTH (2 * sizeof(uint32_t))
|
||||
#define MIDX_CHUNK_LARGE_OFFSET_WIDTH (sizeof(uint64_t))
|
||||
@ -53,6 +52,19 @@ static char *get_midx_filename(const char *object_dir)
|
||||
return xstrfmt("%s/pack/multi-pack-index", object_dir);
|
||||
}
|
||||
|
||||
static int midx_read_oid_fanout(const unsigned char *chunk_start,
|
||||
size_t chunk_size, void *data)
|
||||
{
|
||||
struct multi_pack_index *m = data;
|
||||
m->chunk_oid_fanout = (uint32_t *)chunk_start;
|
||||
|
||||
if (chunk_size != 4 * 256) {
|
||||
error(_("multi-pack-index OID fanout is of the wrong size"));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local)
|
||||
{
|
||||
struct multi_pack_index *m = NULL;
|
||||
@ -64,6 +76,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
|
||||
char *midx_name = get_midx_filename(object_dir);
|
||||
uint32_t i;
|
||||
const char *cur_pack_name;
|
||||
struct chunkfile *cf = NULL;
|
||||
|
||||
fd = git_open(midx_name);
|
||||
|
||||
@ -113,58 +126,23 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
|
||||
|
||||
m->num_packs = get_be32(m->data + MIDX_BYTE_NUM_PACKS);
|
||||
|
||||
for (i = 0; i < m->num_chunks; i++) {
|
||||
uint32_t chunk_id = get_be32(m->data + MIDX_HEADER_SIZE +
|
||||
MIDX_CHUNKLOOKUP_WIDTH * i);
|
||||
uint64_t chunk_offset = get_be64(m->data + MIDX_HEADER_SIZE + 4 +
|
||||
MIDX_CHUNKLOOKUP_WIDTH * i);
|
||||
cf = init_chunkfile(NULL);
|
||||
|
||||
if (chunk_offset >= m->data_len)
|
||||
die(_("invalid chunk offset (too large)"));
|
||||
if (read_table_of_contents(cf, m->data, midx_size,
|
||||
MIDX_HEADER_SIZE, m->num_chunks))
|
||||
goto cleanup_fail;
|
||||
|
||||
switch (chunk_id) {
|
||||
case MIDX_CHUNKID_PACKNAMES:
|
||||
m->chunk_pack_names = m->data + chunk_offset;
|
||||
break;
|
||||
|
||||
case MIDX_CHUNKID_OIDFANOUT:
|
||||
m->chunk_oid_fanout = (uint32_t *)(m->data + chunk_offset);
|
||||
break;
|
||||
|
||||
case MIDX_CHUNKID_OIDLOOKUP:
|
||||
m->chunk_oid_lookup = m->data + chunk_offset;
|
||||
break;
|
||||
|
||||
case MIDX_CHUNKID_OBJECTOFFSETS:
|
||||
m->chunk_object_offsets = m->data + chunk_offset;
|
||||
break;
|
||||
|
||||
case MIDX_CHUNKID_LARGEOFFSETS:
|
||||
m->chunk_large_offsets = m->data + chunk_offset;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
die(_("terminating multi-pack-index chunk id appears earlier than expected"));
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Do nothing on unrecognized chunks, allowing future
|
||||
* extensions to add optional chunks.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m->chunk_pack_names)
|
||||
if (pair_chunk(cf, MIDX_CHUNKID_PACKNAMES, &m->chunk_pack_names) == CHUNK_NOT_FOUND)
|
||||
die(_("multi-pack-index missing required pack-name chunk"));
|
||||
if (!m->chunk_oid_fanout)
|
||||
if (read_chunk(cf, MIDX_CHUNKID_OIDFANOUT, midx_read_oid_fanout, m) == CHUNK_NOT_FOUND)
|
||||
die(_("multi-pack-index missing required OID fanout chunk"));
|
||||
if (!m->chunk_oid_lookup)
|
||||
if (pair_chunk(cf, MIDX_CHUNKID_OIDLOOKUP, &m->chunk_oid_lookup) == CHUNK_NOT_FOUND)
|
||||
die(_("multi-pack-index missing required OID lookup chunk"));
|
||||
if (!m->chunk_object_offsets)
|
||||
if (pair_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS, &m->chunk_object_offsets) == CHUNK_NOT_FOUND)
|
||||
die(_("multi-pack-index missing required object offsets chunk"));
|
||||
|
||||
pair_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS, &m->chunk_large_offsets);
|
||||
|
||||
m->num_objects = ntohl(m->chunk_oid_fanout[255]);
|
||||
|
||||
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
|
||||
cleanup_fail:
|
||||
free(m);
|
||||
free(midx_name);
|
||||
free(cf);
|
||||
if (midx_map)
|
||||
munmap(midx_map, midx_size);
|
||||
if (0 <= fd)
|
||||
|
@ -314,12 +314,12 @@ test_expect_success 'verify bad OID version' '
|
||||
|
||||
test_expect_success 'verify truncated chunk count' '
|
||||
corrupt_midx_and_verify $MIDX_BYTE_CHUNK_COUNT "\01" $objdir \
|
||||
"missing required"
|
||||
"final chunk has non-zero id"
|
||||
'
|
||||
|
||||
test_expect_success 'verify extended chunk count' '
|
||||
corrupt_midx_and_verify $MIDX_BYTE_CHUNK_COUNT "\07" $objdir \
|
||||
"terminating multi-pack-index chunk id appears earlier than expected"
|
||||
"terminating chunk id appears earlier than expected"
|
||||
'
|
||||
|
||||
test_expect_success 'verify missing required chunk' '
|
||||
@ -329,7 +329,7 @@ test_expect_success 'verify missing required chunk' '
|
||||
|
||||
test_expect_success 'verify invalid chunk offset' '
|
||||
corrupt_midx_and_verify $MIDX_BYTE_CHUNK_OFFSET "\01" $objdir \
|
||||
"invalid chunk offset (too large)"
|
||||
"improper chunk offset(s)"
|
||||
'
|
||||
|
||||
test_expect_success 'verify packnames out of order' '
|
||||
|
Loading…
Reference in New Issue
Block a user