| 50 | } |
| 51 | |
| 52 | static int verify_packfile(struct repository *r, |
| 53 | struct packed_git *p, |
| 54 | struct pack_window **w_curs, |
| 55 | verify_fn fn, |
| 56 | void *fn_data, |
| 57 | struct progress *progress, uint32_t base_count) |
| 58 | |
| 59 | { |
| 60 | off_t index_size = p->index_size; |
| 61 | const unsigned char *index_base = p->index_data; |
| 62 | struct git_hash_ctx ctx; |
| 63 | unsigned char hash[GIT_MAX_RAWSZ], *pack_sig; |
| 64 | off_t offset = 0, pack_sig_ofs = 0; |
| 65 | uint32_t nr_objects, i; |
| 66 | int err = 0; |
| 67 | struct idx_entry *entries; |
| 68 | |
| 69 | if (!is_pack_valid(p)) |
| 70 | return error("packfile %s cannot be accessed", p->pack_name); |
| 71 | |
| 72 | r->hash_algo->init_fn(&ctx); |
| 73 | do { |
| 74 | unsigned long remaining; |
| 75 | unsigned char *in = use_pack(p, w_curs, offset, &remaining); |
| 76 | offset += remaining; |
| 77 | if (!pack_sig_ofs) |
| 78 | pack_sig_ofs = p->pack_size - r->hash_algo->rawsz; |
| 79 | if (offset > pack_sig_ofs) |
| 80 | remaining -= (unsigned int)(offset - pack_sig_ofs); |
| 81 | git_hash_update(&ctx, in, remaining); |
| 82 | } while (offset < pack_sig_ofs); |
| 83 | git_hash_final(hash, &ctx); |
| 84 | pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL); |
| 85 | if (!hasheq(hash, pack_sig, r->hash_algo)) |
| 86 | err = error("%s pack checksum mismatch", |
| 87 | p->pack_name); |
| 88 | if (!hasheq(index_base + index_size - r->hash_algo->hexsz, pack_sig, |
| 89 | r->hash_algo)) |
| 90 | err = error("%s pack checksum does not match its index", |
| 91 | p->pack_name); |
| 92 | unuse_pack(w_curs); |
| 93 | |
| 94 | /* Make sure everything reachable from idx is valid. Since we |
| 95 | * have verified that nr_objects matches between idx and pack, |
| 96 | * we do not do scan-streaming check on the pack file. |
| 97 | */ |
| 98 | nr_objects = p->num_objects; |
| 99 | ALLOC_ARRAY(entries, nr_objects + 1); |
| 100 | entries[nr_objects].offset = pack_sig_ofs; |
| 101 | /* first sort entries by pack offset, since unpacking them is more efficient that way */ |
| 102 | for (i = 0; i < nr_objects; i++) { |
| 103 | entries[i].offset = nth_packed_object_offset(p, i); |
| 104 | entries[i].nr = i; |
| 105 | } |
| 106 | QSORT(entries, nr_objects, compare_entries); |
| 107 | |
| 108 | for (i = 0; i < nr_objects; i++) { |
| 109 | struct odb_read_stream *stream = NULL; |
no test coverage detected