X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-unpack-objects.c;h=a6ff62fd8c66f075550e01718acf56d90b44d4bb;hb=1d431b22357389d0833830daf814ff0c4dc9189d;hp=8f8e898516e0ec73fde063ae17d26a26612c5c20;hpb=fbe3d87e5fcef2e0fff41c3b0589331c889dfb59;p=git.git diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 8f8e89851..a6ff62fd8 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -7,13 +7,15 @@ #include "commit.h" #include "tag.h" #include "tree.h" +#include "progress.h" static int dry_run, quiet, recover, has_errors; static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] < pack-file"; /* We always read in 4kB chunks. */ static unsigned char buffer[4096]; -static unsigned long offset, len, consumed_bytes; +static unsigned int offset, len; +static off_t consumed_bytes; static SHA_CTX ctx; /* @@ -32,7 +34,7 @@ static void *fill(int min) offset = 0; } do { - int ret = xread(0, buffer + len, sizeof(buffer) - len); + ssize_t ret = xread(0, buffer + len, sizeof(buffer) - len); if (ret <= 0) { if (!ret) die("early EOF"); @@ -49,6 +51,10 @@ static void use(int bytes) die("used more bytes than were available"); len -= bytes; offset += bytes; + + /* make sure off_t is sufficiently large not to wrap */ + if (consumed_bytes > consumed_bytes + bytes) + die("pack too large for current definition of off_t"); consumed_bytes += bytes; } @@ -88,17 +94,17 @@ static void *get_data(unsigned long size) struct delta_info { unsigned char base_sha1[20]; - unsigned long base_offset; + unsigned nr; + off_t base_offset; unsigned long size; void *delta; - unsigned nr; struct delta_info *next; }; static struct delta_info *delta_list; static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1, - unsigned long base_offset, + off_t base_offset, void *delta, unsigned long size) { struct delta_info *info = xmalloc(sizeof(*info)); @@ -113,24 +119,24 @@ static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1, } struct obj_info { - unsigned long offset; + off_t offset; unsigned char sha1[20]; }; static struct obj_info *obj_list; -static void added_object(unsigned nr, const char *type, void *data, - unsigned long size); +static void added_object(unsigned nr, enum object_type type, + void *data, unsigned long size); -static void write_object(unsigned nr, void *buf, unsigned long size, - const char *type) +static void write_object(unsigned nr, enum object_type type, + void *buf, unsigned long size) { - if (write_sha1_file(buf, size, type, obj_list[nr].sha1) < 0) + if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0) die("failed to write object"); added_object(nr, type, buf, size); } -static void resolve_delta(unsigned nr, const char *type, +static void resolve_delta(unsigned nr, enum object_type type, void *base, unsigned long base_size, void *delta, unsigned long delta_size) { @@ -143,12 +149,12 @@ static void resolve_delta(unsigned nr, const char *type, if (!result) die("failed to apply delta"); free(delta); - write_object(nr, result, result_size, type); + write_object(nr, type, result, result_size); free(result); } -static void added_object(unsigned nr, const char *type, void *data, - unsigned long size) +static void added_object(unsigned nr, enum object_type type, + void *data, unsigned long size) { struct delta_info **p = &delta_list; struct delta_info *info; @@ -167,33 +173,24 @@ static void added_object(unsigned nr, const char *type, void *data, } } -static void unpack_non_delta_entry(enum object_type kind, unsigned long size, +static void unpack_non_delta_entry(enum object_type type, unsigned long size, unsigned nr) { void *buf = get_data(size); - const char *type; - - switch (kind) { - case OBJ_COMMIT: type = commit_type; break; - case OBJ_TREE: type = tree_type; break; - case OBJ_BLOB: type = blob_type; break; - case OBJ_TAG: type = tag_type; break; - default: die("bad type %d", kind); - } + if (!dry_run && buf) - write_object(nr, buf, size, type); + write_object(nr, type, buf, size); free(buf); } -static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, +static void unpack_delta_entry(enum object_type type, unsigned long delta_size, unsigned nr) { void *delta_data, *base; unsigned long base_size; - char type[20]; unsigned char base_sha1[20]; - if (kind == OBJ_REF_DELTA) { + if (type == OBJ_REF_DELTA) { hashcpy(base_sha1, fill(20)); use(20); delta_data = get_data(delta_size); @@ -209,7 +206,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, } else { unsigned base_found = 0; unsigned char *pack, c; - unsigned long base_offset; + off_t base_offset; unsigned lo, mid, hi; pack = fill(1); @@ -218,7 +215,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, base_offset = c & 127; while (c & 128) { base_offset += 1; - if (!base_offset || base_offset & ~(~0UL >> 7)) + if (!base_offset || MSB(base_offset, 7)) die("offset value overflow for delta base object"); pack = fill(1); c = *pack; @@ -255,7 +252,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, } } - base = read_sha1_file(base_sha1, type, &base_size); + base = read_sha1_file(base_sha1, &type, &base_size); if (!base) { error("failed to read delta-pack base object %s", sha1_to_hex(base_sha1)); @@ -268,7 +265,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, free(base); } -static void unpack_one(unsigned nr, unsigned total) +static void unpack_one(unsigned nr) { unsigned shift; unsigned char *pack, c; @@ -290,20 +287,7 @@ static void unpack_one(unsigned nr, unsigned total) size += (c & 0x7f) << shift; shift += 7; } - if (!quiet) { - static unsigned long last_sec; - static unsigned last_percent; - struct timeval now; - unsigned percentage = ((nr+1) * 100) / total; - - gettimeofday(&now, NULL); - if (percentage != last_percent || now.tv_sec != last_sec) { - last_sec = now.tv_sec; - last_percent = percentage; - fprintf(stderr, "%4u%% (%u/%u) done\r", - percentage, (nr+1), total); - } - } + switch (type) { case OBJ_COMMIT: case OBJ_TREE: @@ -327,6 +311,7 @@ static void unpack_one(unsigned nr, unsigned total) static void unpack_all(void) { int i; + struct progress progress; struct pack_header *hdr = fill(sizeof(struct pack_header)); unsigned nr_objects = ntohl(hdr->hdr_entries); @@ -334,12 +319,19 @@ static void unpack_all(void) die("bad pack file"); if (!pack_version_ok(hdr->hdr_version)) die("unknown pack file version %d", ntohl(hdr->hdr_version)); - fprintf(stderr, "Unpacking %d objects\n", nr_objects); + use(sizeof(struct pack_header)); + if (!quiet) + start_progress(&progress, "Unpacking %u objects...", "", nr_objects); obj_list = xmalloc(nr_objects * sizeof(*obj_list)); - use(sizeof(struct pack_header)); - for (i = 0; i < nr_objects; i++) - unpack_one(i, nr_objects); + for (i = 0; i < nr_objects; i++) { + unpack_one(i); + if (!quiet) + display_progress(&progress, i + 1); + } + if (!quiet) + stop_progress(&progress); + if (delta_list) die("unresolved deltas left after unpacking"); } @@ -408,7 +400,5 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) } /* All done */ - if (!quiet) - fprintf(stderr, "\n"); return has_errors; }