3 #include "pack-revindex.h"
9 union idx_entry_object
{
10 const unsigned char *hash
;
11 struct object_id
*oid
;
16 static int compare_entries(const void *e1
, const void *e2
)
18 const struct idx_entry
*entry1
= e1
;
19 const struct idx_entry
*entry2
= e2
;
20 if (entry1
->offset
< entry2
->offset
)
22 if (entry1
->offset
> entry2
->offset
)
27 int check_pack_crc(struct packed_git
*p
, struct pack_window
**w_curs
,
28 off_t offset
, off_t len
, unsigned int nr
)
30 const uint32_t *index_crc
;
31 uint32_t data_crc
= crc32(0, NULL
, 0);
35 void *data
= use_pack(p
, w_curs
, offset
, &avail
);
38 data_crc
= crc32(data_crc
, data
, avail
);
43 index_crc
= p
->index_data
;
44 index_crc
+= 2 + 256 + p
->num_objects
* (20/4) + nr
;
46 return data_crc
!= ntohl(*index_crc
);
49 static int verify_packfile(struct packed_git
*p
,
50 struct pack_window
**w_curs
,
52 struct progress
*progress
, uint32_t base_count
)
55 off_t index_size
= p
->index_size
;
56 const unsigned char *index_base
= p
->index_data
;
58 unsigned char hash
[GIT_MAX_RAWSZ
], *pack_sig
;
59 off_t offset
= 0, pack_sig_ofs
= 0;
60 uint32_t nr_objects
, i
;
62 struct idx_entry
*entries
;
64 if (!is_pack_valid(p
))
65 return error("packfile %s cannot be accessed", p
->pack_name
);
69 unsigned long remaining
;
70 unsigned char *in
= use_pack(p
, w_curs
, offset
, &remaining
);
73 pack_sig_ofs
= p
->pack_size
- 20;
74 if (offset
> pack_sig_ofs
)
75 remaining
-= (unsigned int)(offset
- pack_sig_ofs
);
76 git_SHA1_Update(&ctx
, in
, remaining
);
77 } while (offset
< pack_sig_ofs
);
78 git_SHA1_Final(hash
, &ctx
);
79 pack_sig
= use_pack(p
, w_curs
, pack_sig_ofs
, NULL
);
80 if (hashcmp(hash
, pack_sig
))
81 err
= error("%s SHA1 checksum mismatch",
83 if (hashcmp(index_base
+ index_size
- 40, pack_sig
))
84 err
= error("%s SHA1 does not match its index",
88 /* Make sure everything reachable from idx is valid. Since we
89 * have verified that nr_objects matches between idx and pack,
90 * we do not do scan-streaming check on the pack file.
92 nr_objects
= p
->num_objects
;
93 ALLOC_ARRAY(entries
, nr_objects
+ 1);
94 entries
[nr_objects
].offset
= pack_sig_ofs
;
95 /* first sort entries by pack offset, since unpacking them is more efficient that way */
96 for (i
= 0; i
< nr_objects
; i
++) {
97 entries
[i
].oid
.hash
= nth_packed_object_sha1(p
, i
);
98 if (!entries
[i
].oid
.hash
)
99 die("internal error pack-check nth-packed-object");
100 entries
[i
].offset
= nth_packed_object_offset(p
, i
);
103 QSORT(entries
, nr_objects
, compare_entries
);
105 for (i
= 0; i
< nr_objects
; i
++) {
107 enum object_type type
;
112 if (p
->index_version
> 1) {
113 off_t offset
= entries
[i
].offset
;
114 off_t len
= entries
[i
+1].offset
- offset
;
115 unsigned int nr
= entries
[i
].nr
;
116 if (check_pack_crc(p
, w_curs
, offset
, len
, nr
))
117 err
= error("index CRC mismatch for object %s "
118 "from %s at offset %"PRIuMAX
"",
119 oid_to_hex(entries
[i
].oid
.oid
),
120 p
->pack_name
, (uintmax_t)offset
);
123 curpos
= entries
[i
].offset
;
124 type
= unpack_object_header(p
, w_curs
, &curpos
, &size
);
127 if (type
== OBJ_BLOB
&& big_file_threshold
<= size
) {
129 * Let check_sha1_signature() check it with
130 * the streaming interface; no point slurping
131 * the data in-core only to discard.
136 data
= unpack_entry(p
, entries
[i
].offset
, &type
, &size
);
140 if (data_valid
&& !data
)
141 err
= error("cannot unpack %s from %s at offset %"PRIuMAX
"",
142 oid_to_hex(entries
[i
].oid
.oid
), p
->pack_name
,
143 (uintmax_t)entries
[i
].offset
);
144 else if (check_sha1_signature(entries
[i
].oid
.hash
, data
, size
, typename(type
)))
145 err
= error("packed %s from %s is corrupt",
146 oid_to_hex(entries
[i
].oid
.oid
), p
->pack_name
);
149 err
|= fn(entries
[i
].oid
.oid
, type
, size
, data
, &eaten
);
153 if (((base_count
+ i
) & 1023) == 0)
154 display_progress(progress
, base_count
+ i
);
158 display_progress(progress
, base_count
+ i
);
164 int verify_pack_index(struct packed_git
*p
)
167 const unsigned char *index_base
;
169 unsigned char sha1
[20];
172 if (open_pack_index(p
))
173 return error("packfile %s index not opened", p
->pack_name
);
174 index_size
= p
->index_size
;
175 index_base
= p
->index_data
;
177 /* Verify SHA1 sum of the index file */
179 git_SHA1_Update(&ctx
, index_base
, (unsigned int)(index_size
- 20));
180 git_SHA1_Final(sha1
, &ctx
);
181 if (hashcmp(sha1
, index_base
+ index_size
- 20))
182 err
= error("Packfile index for %s SHA1 mismatch",
187 int verify_pack(struct packed_git
*p
, verify_fn fn
,
188 struct progress
*progress
, uint32_t base_count
)
191 struct pack_window
*w_curs
= NULL
;
193 err
|= verify_pack_index(p
);
197 err
|= verify_packfile(p
, &w_curs
, fn
, progress
, base_count
);