diff options
| author | Nicolas Pitre <nico@cam.org> | 2008-08-29 16:08:01 -0400 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2008-08-29 21:51:28 -0700 | 
| commit | 8522148f79c29ef8f63688e7186e458a22333224 (patch) | |
| tree | 6b60d62750d4eb7a573a1744b5999cd31420a645 /index-pack.c | |
| parent | ac0463ed44e859c84e354cd0ae47d9b5b124e112 (diff) | |
| download | git-8522148f79c29ef8f63688e7186e458a22333224.tar.gz | |
index-pack: use fixup_pack_header_footer()'s validation mode
When completing a thin pack, a new header has to be written to
the pack and a new SHA1 computed.  Make sure that the SHA1 of what
is being read back matches the SHA1 of what was written for both:
the original pack and the appended objects.
To do so, a couple write_or_die() calls were converted to sha1write()
which has the advantage of doing some buffering as well as handling
SHA1 and CRC32 checksum already.
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'index-pack.c')
| -rw-r--r-- | index-pack.c | 43 | 
1 files changed, 25 insertions, 18 deletions
| diff --git a/index-pack.c b/index-pack.c index 411b80d815..a6e91fe3ba 100644 --- a/index-pack.c +++ b/index-pack.c @@ -654,7 +654,7 @@ static void parse_pack_objects(unsigned char *sha1)  	}  } -static int write_compressed(int fd, void *in, unsigned int size, uint32_t *obj_crc) +static int write_compressed(struct sha1file *f, void *in, unsigned int size)  {  	z_stream stream;  	unsigned long maxsize; @@ -674,13 +674,12 @@ static int write_compressed(int fd, void *in, unsigned int size, uint32_t *obj_c  	deflateEnd(&stream);  	size = stream.total_out; -	write_or_die(fd, out, size); -	*obj_crc = crc32(*obj_crc, out, size); +	sha1write(f, out, size);  	free(out);  	return size;  } -static struct object_entry *append_obj_to_pack( +static struct object_entry *append_obj_to_pack(struct sha1file *f,  			       const unsigned char *sha1, void *buf,  			       unsigned long size, enum object_type type)  { @@ -696,15 +695,15 @@ static struct object_entry *append_obj_to_pack(  		s >>= 7;  	}  	header[n++] = c; -	write_or_die(output_fd, header, n); -	obj[0].idx.crc32 = crc32(0, Z_NULL, 0); -	obj[0].idx.crc32 = crc32(obj[0].idx.crc32, header, n); +	crc32_begin(f); +	sha1write(f, header, n);  	obj[0].size = size;  	obj[0].hdr_size = n;  	obj[0].type = type;  	obj[0].real_type = type;  	obj[1].idx.offset = obj[0].idx.offset + n; -	obj[1].idx.offset += write_compressed(output_fd, buf, size, &obj[0].idx.crc32); +	obj[1].idx.offset += write_compressed(f, buf, size); +	obj[0].idx.crc32 = crc32_end(f);  	hashcpy(obj->idx.sha1, sha1);  	return obj;  } @@ -716,7 +715,7 @@ static int delta_pos_compare(const void *_a, const void *_b)  	return a->obj_no - b->obj_no;  } -static void fix_unresolved_deltas(int nr_unresolved) +static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved)  {  	struct delta_entry **sorted_by_pos;  	int i, n = 0; @@ -754,8 +753,8 @@ static void fix_unresolved_deltas(int nr_unresolved)  		if (check_sha1_signature(d->base.sha1, base_obj.data,  				base_obj.size, typename(type)))  			die("local object %s is corrupt", sha1_to_hex(d->base.sha1)); -		base_obj.obj = append_obj_to_pack(d->base.sha1, base_obj.data, -			base_obj.size, type); +		base_obj.obj = append_obj_to_pack(f, d->base.sha1, +					base_obj.data, base_obj.size, type);  		link_base_data(NULL, &base_obj);  		find_delta_children(&d->base, &first, &last); @@ -875,7 +874,7 @@ int main(int argc, char **argv)  	const char *keep_name = NULL, *keep_msg = NULL;  	char *index_name_buf = NULL, *keep_name_buf = NULL;  	struct pack_idx_entry **idx_objects; -	unsigned char sha1[20]; +	unsigned char pack_sha1[20];  	int nongit = 0;  	setup_git_directory_gently(&nongit); @@ -962,13 +961,15 @@ int main(int argc, char **argv)  	parse_pack_header();  	objects = xmalloc((nr_objects + 1) * sizeof(struct object_entry));  	deltas = xmalloc(nr_objects * sizeof(struct delta_entry)); -	parse_pack_objects(sha1); +	parse_pack_objects(pack_sha1);  	if (nr_deltas == nr_resolved_deltas) {  		stop_progress(&progress);  		/* Flush remaining pack final 20-byte SHA1. */  		flush();  	} else {  		if (fix_thin_pack) { +			struct sha1file *f; +			unsigned char read_sha1[20], tail_sha1[20];  			char msg[48];  			int nr_unresolved = nr_deltas - nr_resolved_deltas;  			int nr_objects_initial = nr_objects; @@ -977,13 +978,19 @@ int main(int argc, char **argv)  			objects = xrealloc(objects,  					   (nr_objects + nr_unresolved + 1)  					   * sizeof(*objects)); -			fix_unresolved_deltas(nr_unresolved); +			f = sha1fd(output_fd, curr_pack); +			fix_unresolved_deltas(f, nr_unresolved);  			sprintf(msg, "completed with %d local objects",  				nr_objects - nr_objects_initial);  			stop_progress_msg(&progress, msg); -			fixup_pack_header_footer(output_fd, sha1, +			sha1close(f, tail_sha1, 0); +			hashcpy(read_sha1, pack_sha1); +			fixup_pack_header_footer(output_fd, pack_sha1,  						 curr_pack, nr_objects, -						 NULL, 0); +						 read_sha1, consumed_bytes-20); +			if (hashcmp(read_sha1, tail_sha1) != 0) +				die("Unexpected tail checksum for %s " +				    "(disk corruption?)", curr_pack);  		}  		if (nr_deltas != nr_resolved_deltas)  			die("pack has %d unresolved deltas", @@ -996,13 +1003,13 @@ int main(int argc, char **argv)  	idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *));  	for (i = 0; i < nr_objects; i++)  		idx_objects[i] = &objects[i].idx; -	curr_index = write_idx_file(index_name, idx_objects, nr_objects, sha1); +	curr_index = write_idx_file(index_name, idx_objects, nr_objects, pack_sha1);  	free(idx_objects);  	final(pack_name, curr_pack,  		index_name, curr_index,  		keep_name, keep_msg, -		sha1); +		pack_sha1);  	free(objects);  	free(index_name_buf);  	free(keep_name_buf); | 
