if (!pack_name) {
static char tmpfile[PATH_MAX];
snprintf(tmpfile, sizeof(tmpfile),
- "%s/pack_XXXXXX", get_object_directory());
+ "%s/tmp_pack_XXXXXX", get_object_directory());
output_fd = mkstemp(tmpfile);
pack_name = xstrdup(tmpfile);
} else
{
unsigned long from = obj[0].offset + obj[0].hdr_size;
unsigned long len = obj[1].offset - from;
+ unsigned long rdy = 0;
unsigned char *src, *data;
z_stream stream;
int st;
src = xmalloc(len);
- if (pread(pack_fd, src, len, from) != len)
- die("cannot pread pack file: %s", strerror(errno));
+ data = src;
+ do {
+ ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
+ if (n <= 0)
+ die("cannot pread pack file: %s", strerror(errno));
+ rdy += n;
+ } while (rdy < len);
data = xmalloc(obj->size);
memset(&stream, 0, sizeof(stream));
stream.next_out = data;
static void sha1_object(const void *data, unsigned long size,
enum object_type type, unsigned char *sha1)
{
- SHA_CTX ctx;
- char header[50];
- int header_size;
- const char *type_str;
-
- switch (type) {
- case OBJ_COMMIT: type_str = commit_type; break;
- case OBJ_TREE: type_str = tree_type; break;
- case OBJ_BLOB: type_str = blob_type; break;
- case OBJ_TAG: type_str = tag_type; break;
- default:
- die("bad type %d", type);
+ hash_sha1_file(data, size, typename(type), sha1);
+ if (has_sha1_file(sha1)) {
+ void *has_data;
+ enum object_type has_type;
+ unsigned long has_size;
+ has_data = read_sha1_file(sha1, &has_type, &has_size);
+ if (!has_data)
+ die("cannot read existing object %s", sha1_to_hex(sha1));
+ if (size != has_size || type != has_type ||
+ memcmp(data, has_data, size) != 0)
+ die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1));
+ free(has_data);
}
-
- header_size = sprintf(header, "%s %lu", type_str, size) + 1;
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, header, header_size);
- SHA1_Update(&ctx, data, size);
- SHA1_Final(sha1, &ctx);
}
static void resolve_delta(struct object_entry *delta_obj, void *base_data,
/* If input_fd is a file, we should have reached its end now. */
if (fstat(input_fd, &st))
die("cannot fstat packfile: %s", strerror(errno));
- if (S_ISREG(st.st_mode) && st.st_size != consumed_bytes)
+ if (S_ISREG(st.st_mode) &&
+ lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
die("pack has junk at the end");
if (!nr_deltas)
return size;
}
-static void append_obj_to_pack(void *buf,
+static void append_obj_to_pack(const unsigned char *sha1, void *buf,
unsigned long size, enum object_type type)
{
struct object_entry *obj = &objects[nr_objects++];
write_or_die(output_fd, header, n);
obj[1].offset = obj[0].offset + n;
obj[1].offset += write_compressed(output_fd, buf, size);
- sha1_object(buf, size, type, obj->sha1);
+ hashcpy(obj->sha1, sha1);
}
static int delta_pos_compare(const void *_a, const void *_b)
struct delta_entry *d = sorted_by_pos[i];
void *data;
unsigned long size;
- char type[10];
- enum object_type obj_type;
+ enum object_type type;
int j, first, last;
if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
continue;
- data = read_sha1_file(d->base.sha1, type, &size);
+ data = read_sha1_file(d->base.sha1, &type, &size);
if (!data)
continue;
- if (!strcmp(type, blob_type)) obj_type = OBJ_BLOB;
- else if (!strcmp(type, tree_type)) obj_type = OBJ_TREE;
- else if (!strcmp(type, commit_type)) obj_type = OBJ_COMMIT;
- else if (!strcmp(type, tag_type)) obj_type = OBJ_TAG;
- else die("base object %s is of type '%s'",
- sha1_to_hex(d->base.sha1), type);
find_delta_children(&d->base, &first, &last);
for (j = first; j <= last; j++) {
struct object_entry *child = objects + deltas[j].obj_no;
if (child->real_type == OBJ_REF_DELTA)
- resolve_delta(child, data, size, obj_type);
+ resolve_delta(child, data, size, type);
}
- append_obj_to_pack(data, size, obj_type);
+ if (check_sha1_signature(d->base.sha1, data, size, typename(type)))
+ die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
+ append_obj_to_pack(d->base.sha1, data, size, type);
free(data);
if (verbose)
percent = display_progress(nr_resolved_deltas,
/* Rewrite pack header with updated object number */
if (lseek(output_fd, 0, SEEK_SET) != 0)
die("cannot seek back: %s", strerror(errno));
- if (xread(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
+ if (read_in_full(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
die("cannot read pack header back: %s", strerror(errno));
hdr.hdr_entries = htonl(nr_objects);
if (lseek(output_fd, 0, SEEK_SET) != 0)
if (!index_name) {
static char tmpfile[PATH_MAX];
snprintf(tmpfile, sizeof(tmpfile),
- "%s/index_XXXXXX", get_object_directory());
+ "%s/tmp_idx_XXXXXX", get_object_directory());
fd = mkstemp(tmpfile);
index_name = xstrdup(tmpfile);
} else {
const char *keep_name, const char *keep_msg,
unsigned char *sha1)
{
- char *report = "pack";
+ const char *report = "pack";
char name[PATH_MAX];
int err;
char buf[48];
int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
report, sha1_to_hex(sha1));
- xwrite(1, buf, len);
+ write_or_die(1, buf, len);
/*
* Let's just mimic git-unpack-objects here and write
fix_thin_pack = 1;
} else if (!strcmp(arg, "--keep")) {
keep_msg = "";
- } else if (!strncmp(arg, "--keep=", 7)) {
+ } else if (!prefixcmp(arg, "--keep=")) {
keep_msg = arg + 7;
- } else if (!strncmp(arg, "--pack_header=", 14)) {
+ } else if (!prefixcmp(arg, "--pack_header=")) {
struct pack_header *hdr;
char *c;