commit 3ee5fc2109eca572a496f0da1a80fecfc8b56aea from: Stefan Sperling date: Wed Jan 17 21:25:01 2018 UTC add support for extracting non-deltified packed objects commit - 6c00b54532f90be3b76dd1aed025376a35dc35de commit + 3ee5fc2109eca572a496f0da1a80fecfc8b56aea blob - ebe18b51f48a920944e61349e59e0a689b6ef282 blob + b85bd54d8416997549d793f8e47ea9dc6dc802ed --- include/got_error.h +++ include/got_error.h @@ -34,6 +34,7 @@ #define GOT_ERR_BAD_PACKFILE 16 #define GOT_ERR_NO_OBJ 17 #define GOT_ERR_NOT_IMPL 18 +#define GOT_ERR_OBJ_NOT_PACKED 19 static const struct got_error { int code; @@ -58,6 +59,7 @@ static const struct got_error { { GOT_ERR_BAD_PACKFILE, "bad pack file" }, { GOT_ERR_NO_OBJ, "object not found" }, { GOT_ERR_NOT_IMPL, "feature not implemented" }, + { GOT_ERR_OBJ_NOT_PACKED,"object is not packed" }, }; const struct got_error * got_error(int code); blob - f3581b6726ebe6258178022ac2703b58f32165bb blob + 96d336a171264be9c2e02e38fbaa135a7859c3aa --- lib/object.c +++ lib/object.c @@ -274,9 +274,8 @@ open_object(FILE **f, struct got_object *obj, struct g const struct got_error *err = NULL; char *path; - if (obj->flags & GOT_OBJ_FLAG_PACKED) { - return got_error(GOT_ERR_NOT_IMPL); - } + if (obj->flags & GOT_OBJ_FLAG_PACKED) + return got_packfile_extract_object(f, obj, repo); err = object_path(&path, &obj->id, repo); if (err) blob - 7e7325a8f390d9822562634b04bd0eb7fc9da742 blob + 32b5af0d196466272bd3893c0d65454a8f1e4509 --- lib/pack.c +++ lib/pack.c @@ -327,7 +327,7 @@ read_packfile_hdr(FILE *f, struct got_packidx_v2_hdr * } static const struct got_error * -decode_type_and_size(uint8_t *type, uint64_t *size, FILE *packfile) +decode_type_and_size(uint8_t *type, uint64_t *size, size_t *len, FILE *packfile) { uint8_t t = 0; uint64_t s = 0; @@ -357,6 +357,7 @@ decode_type_and_size(uint8_t *type, uint64_t *size, FI *type = t; *size = s; + *len = i * sizeof(sizeN); return NULL; } @@ -374,6 +375,7 @@ open_packed_object(struct got_object **obj, struct got FILE *packfile; uint8_t type; uint64_t size; + size_t tslen; *obj = NULL; if (idx == -1) /* object not found in pack index */ @@ -407,7 +409,7 @@ open_packed_object(struct got_object **obj, struct got goto done; } - err = decode_type_and_size(&type, &size, packfile); + err = decode_type_and_size(&type, &size, &tslen, packfile); if (err) goto done; @@ -431,7 +433,7 @@ open_packed_object(struct got_object **obj, struct got (*obj)->hdrlen = 0; (*obj)->size = size; memcpy(&(*obj)->id, id, sizeof((*obj)->id)); - (*obj)->pack_offset = offset; + (*obj)->pack_offset = offset + tslen; break; case GOT_OBJ_TYPE_REF_DELTA: case GOT_OBJ_TYPE_TAG: @@ -497,6 +499,78 @@ got_packfile_open_object(struct got_object **obj, stru done: free(path_packdir); if (packdir && closedir(packdir) != 0 && err == 0) + err = got_error_from_errno(); + return err; +} + +static const struct got_error * +dump_plain_object(FILE *infile, uint8_t type, size_t size, FILE *outfile) +{ + size_t n; + + while (size > 0) { + uint8_t data[2048]; + size_t len = MIN(size, sizeof(data)); + + n = fread(data, len, 1, infile); + if (n != 1) + return got_ferror(infile, GOT_ERR_BAD_PACKIDX); + + n = fwrite(data, len, 1, outfile); + if (n != 1) + return got_ferror(outfile, GOT_ERR_BAD_PACKIDX); + + size -= len; + } + + rewind(outfile); + return NULL; +} + +const struct got_error * +got_packfile_extract_object(FILE **f, struct got_object *obj, + struct got_repository *repo) +{ + const struct got_error *err = NULL; + FILE *packfile = NULL; + + if ((obj->flags & GOT_OBJ_FLAG_PACKED) == 0) + return got_error(GOT_ERR_OBJ_NOT_PACKED); + + *f = got_opentemp(); + if (*f == NULL) { + err = got_error(GOT_ERR_FILE_OPEN); + goto done; + } + + packfile = fopen(obj->path_packfile, "rb"); + if (packfile == NULL) { err = got_error_from_errno(); + goto done; + } + + if (fseeko(packfile, obj->pack_offset, SEEK_SET) != 0) { + err = got_error_from_errno(); + goto done; + } + + switch (obj->type) { + case GOT_OBJ_TYPE_COMMIT: + case GOT_OBJ_TYPE_TREE: + case GOT_OBJ_TYPE_BLOB: + err = dump_plain_object(packfile, obj->type, obj->size, *f); + break; + case GOT_OBJ_TYPE_REF_DELTA: + case GOT_OBJ_TYPE_TAG: + case GOT_OBJ_TYPE_OFFSET_DELTA: + default: + err = got_error(GOT_ERR_NOT_IMPL); + goto done; + } +done: + if (packfile) + fclose(packfile); + if (err && *f) + fclose(*f); return err; } blob - e26be48fe9e5fa02953cf19e02932e77d46a40d5 blob + 18a6071e88706cf03a4eb280c3b30f5cd73fc425 --- lib/pack.h +++ lib/pack.h @@ -123,3 +123,5 @@ void got_packidx_close(struct got_packidx_v2_hdr *); const struct got_error *got_packfile_open_object(struct got_object **, struct got_object_id *, struct got_repository *); +const struct got_error *got_packfile_extract_object(FILE **, + struct got_object *, struct got_repository *);