-static unsigned char* map_pack(unsigned long offset, unsigned int *left)
-{
- if (offset >= pack_size)
- die("object offset outside of pack file");
- if (!pack_base
- || offset < pack_moff
- || (offset + 20) >= (pack_moff + pack_mlen)) {
- if (pack_base)
- munmap(pack_base, pack_mlen);
- pack_moff = (offset / page_size) * page_size;
- pack_base = mmap(NULL,pack_mlen,PROT_READ,MAP_SHARED,
- pack_fd,pack_moff);
- if (pack_base == MAP_FAILED)
- die("Failed to map generated pack: %s", strerror(errno));
- remap_count++;
- }
- offset -= pack_moff;
- if (left)
- *left = pack_mlen - offset;
- return pack_base + offset;
-}
-
-static unsigned long unpack_object_header(unsigned long offset,
- enum object_type *type,
- unsigned long *sizep)
-{
- unsigned shift;
- unsigned char c;
- unsigned long size;
-
- c = *map_pack(offset++, NULL);
- *type = (c >> 4) & 7;
- size = c & 15;
- shift = 4;
- while (c & 0x80) {
- c = *map_pack(offset++, NULL);
- size += (c & 0x7f) << shift;
- shift += 7;
- }
- *sizep = size;
- return offset;
-}
-
-static void *unpack_non_delta_entry(unsigned long o, unsigned long sz)
-{
- z_stream stream;
- unsigned char *result;
-
- result = xmalloc(sz + 1);
- result[sz] = 0;
-
- memset(&stream, 0, sizeof(stream));
- stream.next_in = map_pack(o, &stream.avail_in);
- stream.next_out = result;
- stream.avail_out = sz;
-
- inflateInit(&stream);
- for (;;) {
- int st = inflate(&stream, Z_FINISH);
- if (st == Z_STREAM_END)
- break;
- if (st == Z_OK || st == Z_BUF_ERROR) {
- o = stream.next_in - pack_base + pack_moff;
- stream.next_in = map_pack(o, &stream.avail_in);
- continue;
- }
- die("Error %i from zlib during inflate.", st);
- }
- inflateEnd(&stream);
- if (stream.total_out != sz)
- die("Error after inflate: sizes mismatch");
- return result;
-}
-
-static void *gfi_unpack_entry(unsigned long offset,
- unsigned long *sizep,
- unsigned int *delta_depth);
-
-static void *unpack_delta_entry(unsigned long offset,
- unsigned long delta_size,
- unsigned long *sizep,
- unsigned int *delta_depth)
-{
- struct object_entry *base_oe;
- unsigned char *base_sha1;
- void *delta_data, *base, *result;
- unsigned long base_size, result_size;
-
- base_sha1 = map_pack(offset, NULL);
- base_oe = find_object(base_sha1);
- if (!base_oe)
- die("I'm broken; I can't find a base I know must be here.");
- base = gfi_unpack_entry(base_oe->offset, &base_size, delta_depth);
- delta_data = unpack_non_delta_entry(offset + 20, delta_size);
- result = patch_delta(base, base_size,
- delta_data, delta_size,
- &result_size);
- if (!result)
- die("failed to apply delta");
- free(delta_data);
- free(base);
- *sizep = result_size;
- (*delta_depth)++;
- return result;
-}
-
-static void *gfi_unpack_entry(unsigned long offset,
- unsigned long *sizep,
- unsigned int *delta_depth)