]>
Commit | Line | Data |
---|---|---|
f9253394 JH |
1 | #include "cache.h" |
2 | #include "pack.h" | |
3 | ||
03e79c88 SP |
4 | static int verify_packfile(struct packed_git *p, |
5 | struct pack_window **w_curs) | |
f9253394 JH |
6 | { |
7 | unsigned long index_size = p->index_size; | |
8 | void *index_base = p->index_base; | |
9 | SHA_CTX ctx; | |
10 | unsigned char sha1[20]; | |
079afb18 | 11 | unsigned long offset = 0, pack_sig = p->pack_size - 20; |
f3bf9224 | 12 | int nr_objects, err, i; |
f9253394 | 13 | |
079afb18 SP |
14 | /* Note that the pack header checks are actually performed by |
15 | * use_pack when it first opens the pack file. If anything | |
16 | * goes wrong during those checks then the call will die out | |
17 | * immediately. | |
18 | */ | |
f9253394 JH |
19 | |
20 | SHA1_Init(&ctx); | |
079afb18 SP |
21 | while (offset < pack_sig) { |
22 | unsigned int remaining; | |
23 | unsigned char *in = use_pack(p, w_curs, offset, &remaining); | |
24 | offset += remaining; | |
25 | if (offset > pack_sig) | |
26 | remaining -= offset - pack_sig; | |
27 | SHA1_Update(&ctx, in, remaining); | |
28 | } | |
f9253394 | 29 | SHA1_Final(sha1, &ctx); |
079afb18 | 30 | if (hashcmp(sha1, use_pack(p, w_curs, pack_sig, NULL))) |
f9253394 JH |
31 | return error("Packfile %s SHA1 mismatch with itself", |
32 | p->pack_name); | |
a89fccd2 | 33 | if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40)) |
55e1805d JH |
34 | return error("Packfile %s SHA1 mismatch with idx", |
35 | p->pack_name); | |
079afb18 | 36 | unuse_pack(w_curs); |
f3bf9224 JH |
37 | |
38 | /* Make sure everything reachable from idx is valid. Since we | |
39 | * have verified that nr_objects matches between idx and pack, | |
40 | * we do not do scan-streaming check on the pack file. | |
41 | */ | |
079afb18 | 42 | nr_objects = num_packed_objects(p); |
f3bf9224 JH |
43 | for (i = err = 0; i < nr_objects; i++) { |
44 | unsigned char sha1[20]; | |
f3bf9224 JH |
45 | void *data; |
46 | char type[20]; | |
43057304 | 47 | unsigned long size, offset; |
f3bf9224 JH |
48 | |
49 | if (nth_packed_object_sha1(p, i, sha1)) | |
50 | die("internal error pack-check nth-packed-object"); | |
43057304 NP |
51 | offset = find_pack_entry_one(sha1, p); |
52 | if (!offset) | |
f3bf9224 | 53 | die("internal error pack-check find-pack-entry-one"); |
4d703a1a | 54 | data = unpack_entry(p, offset, type, &size); |
f3bf9224 JH |
55 | if (!data) { |
56 | err = error("cannot unpack %s from %s", | |
57 | sha1_to_hex(sha1), p->pack_name); | |
58 | continue; | |
59 | } | |
60 | if (check_sha1_signature(sha1, data, size, type)) { | |
1038f0c0 | 61 | err = error("packed %s from %s is corrupt", |
f3bf9224 JH |
62 | sha1_to_hex(sha1), p->pack_name); |
63 | free(data); | |
64 | continue; | |
65 | } | |
66 | free(data); | |
67 | } | |
68 | ||
69 | return err; | |
f9253394 JH |
70 | } |
71 | ||
72 | ||
473ab165 JH |
73 | #define MAX_CHAIN 40 |
74 | ||
079afb18 | 75 | static void show_pack_info(struct packed_git *p) |
f3bf9224 | 76 | { |
ad8c80a5 | 77 | int nr_objects, i; |
473ab165 | 78 | unsigned int chain_histogram[MAX_CHAIN]; |
ad8c80a5 | 79 | |
079afb18 | 80 | nr_objects = num_packed_objects(p); |
473ab165 | 81 | memset(chain_histogram, 0, sizeof(chain_histogram)); |
ad8c80a5 JH |
82 | |
83 | for (i = 0; i < nr_objects; i++) { | |
84 | unsigned char sha1[20], base_sha1[20]; | |
ad8c80a5 JH |
85 | char type[20]; |
86 | unsigned long size; | |
87 | unsigned long store_size; | |
43057304 | 88 | unsigned long offset; |
f8f135c9 | 89 | unsigned int delta_chain_length; |
ad8c80a5 JH |
90 | |
91 | if (nth_packed_object_sha1(p, i, sha1)) | |
92 | die("internal error pack-check nth-packed-object"); | |
43057304 NP |
93 | offset = find_pack_entry_one(sha1, p); |
94 | if (!offset) | |
ad8c80a5 JH |
95 | die("internal error pack-check find-pack-entry-one"); |
96 | ||
43057304 | 97 | packed_object_info_detail(p, offset, type, &size, &store_size, |
ad8c80a5 JH |
98 | &delta_chain_length, |
99 | base_sha1); | |
100 | printf("%s ", sha1_to_hex(sha1)); | |
101 | if (!delta_chain_length) | |
43057304 | 102 | printf("%-6s %lu %lu\n", type, size, offset); |
473ab165 | 103 | else { |
43057304 | 104 | printf("%-6s %lu %lu %u %s\n", type, size, offset, |
ad8c80a5 | 105 | delta_chain_length, sha1_to_hex(base_sha1)); |
473ab165 JH |
106 | if (delta_chain_length < MAX_CHAIN) |
107 | chain_histogram[delta_chain_length]++; | |
108 | else | |
109 | chain_histogram[0]++; | |
110 | } | |
ad8c80a5 JH |
111 | } |
112 | ||
473ab165 JH |
113 | for (i = 0; i < MAX_CHAIN; i++) { |
114 | if (!chain_histogram[i]) | |
115 | continue; | |
116 | printf("chain length %s %d: %d object%s\n", | |
117 | i ? "=" : ">=", | |
118 | i ? i : MAX_CHAIN, | |
119 | chain_histogram[i], | |
120 | 1 < chain_histogram[i] ? "s" : ""); | |
121 | } | |
f3bf9224 JH |
122 | } |
123 | ||
124 | int verify_pack(struct packed_git *p, int verbose) | |
f9253394 JH |
125 | { |
126 | unsigned long index_size = p->index_size; | |
127 | void *index_base = p->index_base; | |
128 | SHA_CTX ctx; | |
129 | unsigned char sha1[20]; | |
130 | int ret; | |
131 | ||
f3bf9224 | 132 | ret = 0; |
f9253394 JH |
133 | /* Verify SHA1 sum of the index file */ |
134 | SHA1_Init(&ctx); | |
135 | SHA1_Update(&ctx, index_base, index_size - 20); | |
136 | SHA1_Final(sha1, &ctx); | |
a89fccd2 | 137 | if (hashcmp(sha1, (unsigned char *)index_base + index_size - 20)) |
f3bf9224 JH |
138 | ret = error("Packfile index for %s SHA1 mismatch", |
139 | p->pack_name); | |
140 | ||
141 | if (!ret) { | |
142 | /* Verify pack file */ | |
03e79c88 SP |
143 | struct pack_window *w_curs = NULL; |
144 | ret = verify_packfile(p, &w_curs); | |
145 | unuse_pack(&w_curs); | |
f3bf9224 JH |
146 | } |
147 | ||
148 | if (verbose) { | |
149 | if (ret) | |
150 | printf("%s: bad\n", p->pack_name); | |
151 | else { | |
079afb18 | 152 | show_pack_info(p); |
f3bf9224 JH |
153 | printf("%s: ok\n", p->pack_name); |
154 | } | |
155 | } | |
f9253394 | 156 | |
f9253394 JH |
157 | return ret; |
158 | } |