X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=pack-check.c;h=0f8ad2c00f21d9a0a64b541ed95fff91650d7175;hb=3e08f5db65bcfe3ad238ee0de1cac2da84953cf3;hp=08a9fd8dc09056c1b21cb7414f2467cffcdef077;hpb=c326246accf36bc070b326773df2b9ec1c336037;p=git.git diff --git a/pack-check.c b/pack-check.c index 08a9fd8dc..0f8ad2c00 100644 --- a/pack-check.c +++ b/pack-check.c @@ -1,15 +1,35 @@ #include "cache.h" #include "pack.h" +#include "pack-revindex.h" + +struct idx_entry +{ + const unsigned char *sha1; + off_t offset; +}; + +static int compare_entries(const void *e1, const void *e2) +{ + const struct idx_entry *entry1 = e1; + const struct idx_entry *entry2 = e2; + if (entry1->offset < entry2->offset) + return -1; + if (entry1->offset > entry2->offset) + return 1; + return 0; +} static int verify_packfile(struct packed_git *p, struct pack_window **w_curs) { - unsigned long index_size = p->index_size; - void *index_base = p->index_base; + off_t index_size = p->index_size; + const unsigned char *index_base = p->index_data; SHA_CTX ctx; unsigned char sha1[20]; - unsigned long offset = 0, pack_sig = p->pack_size - 20; - int nr_objects, err, i; + off_t offset = 0, pack_sig = p->pack_size - 20; + uint32_t nr_objects, i; + int err; + struct idx_entry *entries; /* Note that the pack header checks are actually performed by * use_pack when it first opens the pack file. If anything @@ -23,14 +43,14 @@ static int verify_packfile(struct packed_git *p, unsigned char *in = use_pack(p, w_curs, offset, &remaining); offset += remaining; if (offset > pack_sig) - remaining -= offset - pack_sig; + remaining -= (unsigned int)(offset - pack_sig); SHA1_Update(&ctx, in, remaining); } SHA1_Final(sha1, &ctx); if (hashcmp(sha1, use_pack(p, w_curs, pack_sig, NULL))) return error("Packfile %s SHA1 mismatch with itself", p->pack_name); - if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40)) + if (hashcmp(sha1, index_base + index_size - 40)) return error("Packfile %s SHA1 mismatch with idx", p->pack_name); unuse_pack(w_curs); @@ -39,102 +59,118 @@ static int verify_packfile(struct packed_git *p, * have verified that nr_objects matches between idx and pack, * we do not do scan-streaming check on the pack file. */ - nr_objects = num_packed_objects(p); - for (i = err = 0; i < nr_objects; i++) { - unsigned char sha1[20]; - void *data; - char type[20]; - unsigned long size, offset; - - if (nth_packed_object_sha1(p, i, sha1)) + nr_objects = p->num_objects; + entries = xmalloc(nr_objects * sizeof(*entries)); + /* first sort entries by pack offset, since unpacking them is more efficient that way */ + for (i = 0; i < nr_objects; i++) { + entries[i].sha1 = nth_packed_object_sha1(p, i); + if (!entries[i].sha1) die("internal error pack-check nth-packed-object"); - offset = find_pack_entry_one(sha1, p); - if (!offset) + entries[i].offset = find_pack_entry_one(entries[i].sha1, p); + if (!entries[i].offset) die("internal error pack-check find-pack-entry-one"); - data = unpack_entry(p, offset, type, &size); + } + qsort(entries, nr_objects, sizeof(*entries), compare_entries); + + for (i = 0, err = 0; i < nr_objects; i++) { + void *data; + enum object_type type; + unsigned long size; + + data = unpack_entry(p, entries[i].offset, &type, &size); if (!data) { err = error("cannot unpack %s from %s", - sha1_to_hex(sha1), p->pack_name); + sha1_to_hex(entries[i].sha1), p->pack_name); continue; } - if (check_sha1_signature(sha1, data, size, type)) { + if (check_sha1_signature(entries[i].sha1, data, size, typename(type))) { err = error("packed %s from %s is corrupt", - sha1_to_hex(sha1), p->pack_name); + sha1_to_hex(entries[i].sha1), p->pack_name); free(data); continue; } free(data); } + free(entries); return err; } -#define MAX_CHAIN 40 +#define MAX_CHAIN 50 static void show_pack_info(struct packed_git *p) { - int nr_objects, i; - unsigned int chain_histogram[MAX_CHAIN]; + uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1]; - nr_objects = num_packed_objects(p); + nr_objects = p->num_objects; memset(chain_histogram, 0, sizeof(chain_histogram)); + init_pack_revindex(); for (i = 0; i < nr_objects; i++) { - unsigned char sha1[20], base_sha1[20]; - char type[20]; + const unsigned char *sha1; + unsigned char base_sha1[20]; + const char *type; unsigned long size; unsigned long store_size; - unsigned long offset; + off_t offset; unsigned int delta_chain_length; - if (nth_packed_object_sha1(p, i, sha1)) + sha1 = nth_packed_object_sha1(p, i); + if (!sha1) die("internal error pack-check nth-packed-object"); offset = find_pack_entry_one(sha1, p); if (!offset) die("internal error pack-check find-pack-entry-one"); - packed_object_info_detail(p, offset, type, &size, &store_size, - &delta_chain_length, - base_sha1); + type = packed_object_info_detail(p, offset, &size, &store_size, + &delta_chain_length, + base_sha1); printf("%s ", sha1_to_hex(sha1)); if (!delta_chain_length) - printf("%-6s %lu %lu\n", type, size, offset); + printf("%-6s %lu %lu %"PRIuMAX"\n", + type, size, store_size, (uintmax_t)offset); else { - printf("%-6s %lu %lu %u %s\n", type, size, offset, + printf("%-6s %lu %lu %"PRIuMAX" %u %s\n", + type, size, store_size, (uintmax_t)offset, delta_chain_length, sha1_to_hex(base_sha1)); - if (delta_chain_length < MAX_CHAIN) + if (delta_chain_length <= MAX_CHAIN) chain_histogram[delta_chain_length]++; else chain_histogram[0]++; } } - for (i = 0; i < MAX_CHAIN; i++) { + for (i = 0; i <= MAX_CHAIN; i++) { if (!chain_histogram[i]) continue; - printf("chain length %s %d: %d object%s\n", - i ? "=" : ">=", - i ? i : MAX_CHAIN, - chain_histogram[i], - 1 < chain_histogram[i] ? "s" : ""); + printf("chain length = %d: %d object%s\n", i, + chain_histogram[i], chain_histogram[i] > 1 ? "s" : ""); } + if (chain_histogram[0]) + printf("chain length > %d: %d object%s\n", MAX_CHAIN, + chain_histogram[0], chain_histogram[0] > 1 ? "s" : ""); } int verify_pack(struct packed_git *p, int verbose) { - unsigned long index_size = p->index_size; - void *index_base = p->index_base; + off_t index_size; + const unsigned char *index_base; SHA_CTX ctx; unsigned char sha1[20]; int ret; + if (open_pack_index(p)) + return error("packfile %s index not opened", p->pack_name); + index_size = p->index_size; + index_base = p->index_data; + ret = 0; /* Verify SHA1 sum of the index file */ SHA1_Init(&ctx); - SHA1_Update(&ctx, index_base, index_size - 20); + SHA1_Update(&ctx, index_base, (unsigned int)(index_size - 20)); SHA1_Final(sha1, &ctx); - if (hashcmp(sha1, (unsigned char *)index_base + index_size - 20)) + if (hashcmp(sha1, index_base + index_size - 20)) ret = error("Packfile index for %s SHA1 mismatch", p->pack_name);