]> git.ipfire.org Git - thirdparty/git.git/blame - pack-check.c
rerere: Fix removal of already resolved path.
[thirdparty/git.git] / pack-check.c
CommitLineData
f9253394
JH
1#include "cache.h"
2#include "pack.h"
3
8977c110
JH
4#define BATCH (1u<<20)
5
f9253394
JH
6static int verify_packfile(struct packed_git *p)
7{
8 unsigned long index_size = p->index_size;
9 void *index_base = p->index_base;
10 SHA_CTX ctx;
11 unsigned char sha1[20];
f9253394 12 struct pack_header *hdr;
f3bf9224 13 int nr_objects, err, i;
8977c110
JH
14 unsigned char *packdata;
15 unsigned long datasize;
f9253394 16
f3bf9224 17 /* Header consistency check */
f9253394
JH
18 hdr = p->pack_base;
19 if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
4ec99bf0 20 return error("Packfile %s signature mismatch", p->pack_name);
d60fc1c8
NP
21 if (!pack_version_ok(hdr->hdr_version))
22 return error("Packfile version %d unsupported",
23 ntohl(hdr->hdr_version));
f9253394
JH
24 nr_objects = ntohl(hdr->hdr_entries);
25 if (num_packed_objects(p) != nr_objects)
26 return error("Packfile claims to have %d objects, "
27 "while idx size expects %d", nr_objects,
28 num_packed_objects(p));
29
8977c110 30 /* Check integrity of pack data with its SHA-1 checksum */
f9253394 31 SHA1_Init(&ctx);
8977c110
JH
32 packdata = p->pack_base;
33 datasize = p->pack_size - 20;
34 while (datasize) {
35 unsigned long batch = (datasize < BATCH) ? datasize : BATCH;
36 SHA1_Update(&ctx, packdata, batch);
37 datasize -= batch;
38 packdata += batch;
39 }
f9253394 40 SHA1_Final(sha1, &ctx);
8977c110
JH
41
42 if (hashcmp(sha1, (unsigned char *)(p->pack_base) + p->pack_size - 20))
f9253394
JH
43 return error("Packfile %s SHA1 mismatch with itself",
44 p->pack_name);
a89fccd2 45 if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40))
55e1805d
JH
46 return error("Packfile %s SHA1 mismatch with idx",
47 p->pack_name);
f3bf9224
JH
48
49 /* Make sure everything reachable from idx is valid. Since we
50 * have verified that nr_objects matches between idx and pack,
51 * we do not do scan-streaming check on the pack file.
52 */
53 for (i = err = 0; i < nr_objects; i++) {
54 unsigned char sha1[20];
f3bf9224
JH
55 void *data;
56 char type[20];
43057304 57 unsigned long size, offset;
f3bf9224
JH
58
59 if (nth_packed_object_sha1(p, i, sha1))
60 die("internal error pack-check nth-packed-object");
43057304
NP
61 offset = find_pack_entry_one(sha1, p);
62 if (!offset)
f3bf9224 63 die("internal error pack-check find-pack-entry-one");
43057304 64 data = unpack_entry_gently(p, offset, type, &size);
f3bf9224
JH
65 if (!data) {
66 err = error("cannot unpack %s from %s",
67 sha1_to_hex(sha1), p->pack_name);
68 continue;
69 }
70 if (check_sha1_signature(sha1, data, size, type)) {
1038f0c0 71 err = error("packed %s from %s is corrupt",
f3bf9224
JH
72 sha1_to_hex(sha1), p->pack_name);
73 free(data);
74 continue;
75 }
76 free(data);
77 }
78
79 return err;
f9253394
JH
80}
81
82
473ab165
JH
83#define MAX_CHAIN 40
84
f3bf9224
JH
85static void show_pack_info(struct packed_git *p)
86{
ad8c80a5
JH
87 struct pack_header *hdr;
88 int nr_objects, i;
473ab165 89 unsigned int chain_histogram[MAX_CHAIN];
ad8c80a5
JH
90
91 hdr = p->pack_base;
92 nr_objects = ntohl(hdr->hdr_entries);
473ab165 93 memset(chain_histogram, 0, sizeof(chain_histogram));
ad8c80a5
JH
94
95 for (i = 0; i < nr_objects; i++) {
96 unsigned char sha1[20], base_sha1[20];
ad8c80a5
JH
97 char type[20];
98 unsigned long size;
99 unsigned long store_size;
43057304 100 unsigned long offset;
f8f135c9 101 unsigned int delta_chain_length;
ad8c80a5
JH
102
103 if (nth_packed_object_sha1(p, i, sha1))
104 die("internal error pack-check nth-packed-object");
43057304
NP
105 offset = find_pack_entry_one(sha1, p);
106 if (!offset)
ad8c80a5
JH
107 die("internal error pack-check find-pack-entry-one");
108
43057304 109 packed_object_info_detail(p, offset, type, &size, &store_size,
ad8c80a5
JH
110 &delta_chain_length,
111 base_sha1);
112 printf("%s ", sha1_to_hex(sha1));
113 if (!delta_chain_length)
43057304 114 printf("%-6s %lu %lu\n", type, size, offset);
473ab165 115 else {
43057304 116 printf("%-6s %lu %lu %u %s\n", type, size, offset,
ad8c80a5 117 delta_chain_length, sha1_to_hex(base_sha1));
473ab165
JH
118 if (delta_chain_length < MAX_CHAIN)
119 chain_histogram[delta_chain_length]++;
120 else
121 chain_histogram[0]++;
122 }
ad8c80a5
JH
123 }
124
473ab165
JH
125 for (i = 0; i < MAX_CHAIN; i++) {
126 if (!chain_histogram[i])
127 continue;
128 printf("chain length %s %d: %d object%s\n",
129 i ? "=" : ">=",
130 i ? i : MAX_CHAIN,
131 chain_histogram[i],
132 1 < chain_histogram[i] ? "s" : "");
133 }
f3bf9224
JH
134}
135
136int verify_pack(struct packed_git *p, int verbose)
f9253394
JH
137{
138 unsigned long index_size = p->index_size;
139 void *index_base = p->index_base;
140 SHA_CTX ctx;
141 unsigned char sha1[20];
142 int ret;
143
f3bf9224 144 ret = 0;
f9253394
JH
145 /* Verify SHA1 sum of the index file */
146 SHA1_Init(&ctx);
147 SHA1_Update(&ctx, index_base, index_size - 20);
148 SHA1_Final(sha1, &ctx);
a89fccd2 149 if (hashcmp(sha1, (unsigned char *)index_base + index_size - 20))
f3bf9224
JH
150 ret = error("Packfile index for %s SHA1 mismatch",
151 p->pack_name);
152
153 if (!ret) {
154 /* Verify pack file */
155 use_packed_git(p);
156 ret = verify_packfile(p);
157 unuse_packed_git(p);
158 }
159
160 if (verbose) {
161 if (ret)
162 printf("%s: bad\n", p->pack_name);
163 else {
ad8c80a5 164 use_packed_git(p);
f3bf9224 165 show_pack_info(p);
ad8c80a5 166 unuse_packed_git(p);
f3bf9224
JH
167 printf("%s: ok\n", p->pack_name);
168 }
169 }
f9253394 170
f9253394
JH
171 return ret;
172}