sha1_file.c: learn about index version 2
[git/jrn.git] / pack-check.c
blob578f59e61e29215ba6d04fd084eac801d6523b9a
1 #include "cache.h"
2 #include "pack.h"
4 #define BATCH (1u<<20)
6 static int verify_packfile(struct packed_git *p)
8 unsigned long index_size = p->index_size;
9 const unsigned char *index_base = p->index_data;
10 SHA_CTX ctx;
11 unsigned char sha1[20];
12 struct pack_header *hdr;
13 int nr_objects, err, i;
14 unsigned char *packdata;
15 unsigned long datasize;
17 /* Header consistency check */
18 hdr = p->pack_base;
19 if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
20 return error("Packfile %s signature mismatch", p->pack_name);
21 if (!pack_version_ok(hdr->hdr_version))
22 return error("Packfile version %d unsupported",
23 ntohl(hdr->hdr_version));
24 nr_objects = ntohl(hdr->hdr_entries);
25 if (p->num_objects != nr_objects)
26 return error("Packfile claims to have %d objects, "
27 "while idx size expects %d", nr_objects,
28 p->num_objects);
30 /* Check integrity of pack data with its SHA-1 checksum */
31 SHA1_Init(&ctx);
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;
40 SHA1_Final(sha1, &ctx);
42 if (hashcmp(sha1, (unsigned char *)(p->pack_base) + p->pack_size - 20))
43 return error("Packfile %s SHA1 mismatch with itself",
44 p->pack_name);
45 if (hashcmp(sha1, index_base + index_size - 40))
46 return error("Packfile %s SHA1 mismatch with idx",
47 p->pack_name);
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.
53 for (i = err = 0; i < nr_objects; i++) {
54 const unsigned char *sha1;
55 void *data;
56 char type[20];
57 unsigned long size, offset;
59 sha1 = nth_packed_object_sha1(p, i);
60 if (!sha1)
61 die("internal error pack-check nth-packed-object");
62 offset = find_pack_entry_one(sha1, p);
63 if (!offset)
64 die("internal error pack-check find-pack-entry-one");
65 data = unpack_entry_gently(p, offset, type, &size);
66 if (!data) {
67 err = error("cannot unpack %s from %s",
68 sha1_to_hex(sha1), p->pack_name);
69 continue;
71 if (check_sha1_signature(sha1, data, size, type)) {
72 err = error("packed %s from %s is corrupt",
73 sha1_to_hex(sha1), p->pack_name);
74 free(data);
75 continue;
77 free(data);
80 return err;
84 #define MAX_CHAIN 40
86 static void show_pack_info(struct packed_git *p)
88 struct pack_header *hdr;
89 int nr_objects, i;
90 unsigned int chain_histogram[MAX_CHAIN];
92 hdr = p->pack_base;
93 nr_objects = ntohl(hdr->hdr_entries);
94 memset(chain_histogram, 0, sizeof(chain_histogram));
96 for (i = 0; i < nr_objects; i++) {
97 const unsigned char *sha1;
98 unsigned char base_sha1[20];
99 char type[20];
100 unsigned long size;
101 unsigned long store_size;
102 unsigned long offset;
103 unsigned int delta_chain_length;
105 sha1 = nth_packed_object_sha1(p, i);
106 if (!sha1)
107 die("internal error pack-check nth-packed-object");
108 offset = find_pack_entry_one(sha1, p);
109 if (!offset)
110 die("internal error pack-check find-pack-entry-one");
112 packed_object_info_detail(p, offset, type, &size, &store_size,
113 &delta_chain_length,
114 base_sha1);
115 printf("%s ", sha1_to_hex(sha1));
116 if (!delta_chain_length)
117 printf("%-6s %lu %lu\n", type, size, offset);
118 else {
119 printf("%-6s %lu %lu %u %s\n", type, size, offset,
120 delta_chain_length, sha1_to_hex(base_sha1));
121 if (delta_chain_length < MAX_CHAIN)
122 chain_histogram[delta_chain_length]++;
123 else
124 chain_histogram[0]++;
128 for (i = 0; i < MAX_CHAIN; i++) {
129 if (!chain_histogram[i])
130 continue;
131 printf("chain length %s %d: %d object%s\n",
132 i ? "=" : ">=",
133 i ? i : MAX_CHAIN,
134 chain_histogram[i],
135 1 < chain_histogram[i] ? "s" : "");
139 int verify_pack(struct packed_git *p, int verbose)
141 unsigned long index_size = p->index_size;
142 const unsigned char *index_base = p->index_data;
143 SHA_CTX ctx;
144 unsigned char sha1[20];
145 int ret;
147 ret = 0;
148 /* Verify SHA1 sum of the index file */
149 SHA1_Init(&ctx);
150 SHA1_Update(&ctx, index_base, index_size - 20);
151 SHA1_Final(sha1, &ctx);
152 if (hashcmp(sha1, index_base + index_size - 20))
153 ret = error("Packfile index for %s SHA1 mismatch",
154 p->pack_name);
156 if (!ret) {
157 /* Verify pack file */
158 use_packed_git(p);
159 ret = verify_packfile(p);
160 unuse_packed_git(p);
163 if (verbose) {
164 if (ret)
165 printf("%s: bad\n", p->pack_name);
166 else {
167 use_packed_git(p);
168 show_pack_info(p);
169 unuse_packed_git(p);
170 printf("%s: ok\n", p->pack_name);
174 return ret;