1
1
#include "cache.h"
2
2
#include "pack.h"
3
3
4
+ struct idx_entry
5
+ {
6
+ const unsigned char * sha1 ;
7
+ off_t offset ;
8
+ };
9
+
10
+ static int compare_entries (const void * e1 , const void * e2 )
11
+ {
12
+ const struct idx_entry * entry1 = e1 ;
13
+ const struct idx_entry * entry2 = e2 ;
14
+ if (entry1 -> offset < entry2 -> offset )
15
+ return -1 ;
16
+ if (entry1 -> offset > entry2 -> offset )
17
+ return 1 ;
18
+ return 0 ;
19
+ }
20
+
4
21
static int verify_packfile (struct packed_git * p ,
5
22
struct pack_window * * w_curs )
6
23
{
@@ -11,6 +28,7 @@ static int verify_packfile(struct packed_git *p,
11
28
off_t offset = 0 , pack_sig = p -> pack_size - 20 ;
12
29
uint32_t nr_objects , i ;
13
30
int err ;
31
+ struct idx_entry * entries ;
14
32
15
33
/* Note that the pack header checks are actually performed by
16
34
* use_pack when it first opens the pack file. If anything
@@ -41,33 +59,38 @@ static int verify_packfile(struct packed_git *p,
41
59
* we do not do scan-streaming check on the pack file.
42
60
*/
43
61
nr_objects = p -> num_objects ;
62
+ entries = xmalloc (nr_objects * sizeof (* entries ));
63
+ /* first sort entries by pack offset, since unpacking them is more efficient that way */
64
+ for (i = 0 ; i < nr_objects ; i ++ ) {
65
+ entries [i ].sha1 = nth_packed_object_sha1 (p , i );
66
+ if (!entries [i ].sha1 )
67
+ die ("internal error pack-check nth-packed-object" );
68
+ entries [i ].offset = find_pack_entry_one (entries [i ].sha1 , p );
69
+ if (!entries [i ].offset )
70
+ die ("internal error pack-check find-pack-entry-one" );
71
+ }
72
+ qsort (entries , nr_objects , sizeof (* entries ), compare_entries );
73
+
44
74
for (i = 0 , err = 0 ; i < nr_objects ; i ++ ) {
45
- const unsigned char * sha1 ;
46
75
void * data ;
47
76
enum object_type type ;
48
77
unsigned long size ;
49
- off_t offset ;
50
78
51
- sha1 = nth_packed_object_sha1 (p , i );
52
- if (!sha1 )
53
- die ("internal error pack-check nth-packed-object" );
54
- offset = find_pack_entry_one (sha1 , p );
55
- if (!offset )
56
- die ("internal error pack-check find-pack-entry-one" );
57
- data = unpack_entry (p , offset , & type , & size );
79
+ data = unpack_entry (p , entries [i ].offset , & type , & size );
58
80
if (!data ) {
59
81
err = error ("cannot unpack %s from %s" ,
60
- sha1_to_hex (sha1 ), p -> pack_name );
82
+ sha1_to_hex (entries [ i ]. sha1 ), p -> pack_name );
61
83
continue ;
62
84
}
63
- if (check_sha1_signature (sha1 , data , size , typename (type ))) {
85
+ if (check_sha1_signature (entries [ i ]. sha1 , data , size , typename (type ))) {
64
86
err = error ("packed %s from %s is corrupt" ,
65
- sha1_to_hex (sha1 ), p -> pack_name );
87
+ sha1_to_hex (entries [ i ]. sha1 ), p -> pack_name );
66
88
free (data );
67
89
continue ;
68
90
}
69
91
free (data );
70
92
}
93
+ free (entries );
71
94
72
95
return err ;
73
96
}
0 commit comments