commit 0e22967e43602d4c52a8d102e30107f8c4da765a from: Stefan Sperling date: Sun Feb 11 21:43:21 2018 UTC we must store delta's type-and-size length separately to skip it commit - a6b158cc8110b488f51e265bea16ed17a0079e0a commit + 0e22967e43602d4c52a8d102e30107f8c4da765a blob - 47d76d27b6b0d7cb999126ff93c9be462456dd24 blob + 41af9356c9c8a63448df12b4f5c977e9eb233dc5 --- lib/delta.c +++ lib/delta.c @@ -35,8 +35,8 @@ #endif struct got_delta * -got_delta_open(const char *path_packfile, int type, off_t offset, - size_t size) +got_delta_open(const char *path_packfile, off_t offset, size_t tslen, + int type, size_t size) { struct got_delta *delta; @@ -51,6 +51,7 @@ got_delta_open(const char *path_packfile, int type, of } delta->type = type; delta->offset = offset; + delta->tslen = tslen; delta->size = size; return delta; } @@ -224,11 +225,10 @@ copy_from_delta(const uint8_t **p, size_t *remain, siz } const struct got_error * -got_delta_apply(FILE *base_compressed, const uint8_t *delta_buf, +got_delta_apply(FILE *base_file, const uint8_t *delta_buf, size_t delta_len, FILE *outfile) { const struct got_error *err = NULL; - FILE *base_file = NULL; uint64_t base_size, result_size; size_t remain, outsize = 0; const uint8_t *p; @@ -259,22 +259,6 @@ got_delta_apply(FILE *base_compressed, const uint8_t * err = parse_opcode(&offset, &len, &p, &remain); if (err) break; - if (base_file == NULL) { - size_t inflated_size; - base_file = got_opentemp(); - if (base_file == NULL) { - err = got_error_from_errno(); - break; - } - err = got_inflate_to_file(&inflated_size, - base_compressed, base_file); - if (err) - break; - if (inflated_size != base_size) { - err = got_error(GOT_ERR_BAD_DELTA); - break; - } - } err = copy_from_base(base_file, offset, len, outfile); if (err == NULL) outsize += len; @@ -304,8 +288,6 @@ got_delta_apply(FILE *base_compressed, const uint8_t * if (outsize != result_size) err = got_error(GOT_ERR_BAD_DELTA); - if (base_file) - fclose(base_file); if (err == NULL) rewind(outfile); return err; blob - 84193ca76b0e39db46ace39f37ccb3854f6fed91 blob + 159057631e643f4fad94371f41acbd2023aa9529 --- lib/delta.h +++ lib/delta.h @@ -18,6 +18,7 @@ struct got_delta { SIMPLEQ_ENTRY(got_delta) entry; char *path_packfile; off_t offset; + size_t tslen; int type; size_t size; }; @@ -27,7 +28,7 @@ struct got_delta_chain { SIMPLEQ_HEAD(, got_delta) entries; }; -struct got_delta *got_delta_open(const char *, int, off_t, size_t); +struct got_delta *got_delta_open(const char *, off_t, size_t, int, size_t); void got_delta_close(struct got_delta *); const struct got_error *got_delta_chain_get_base_type(int *, struct got_delta_chain *); blob - 695e3dc57b3f6950442c696698ebf4591a41da82 blob + dd64e4ac004ebf28028927affaa8a9d342b5f944 --- lib/pack.c +++ lib/pack.c @@ -548,8 +548,9 @@ parse_offset_delta(off_t *base_offset, FILE *packfile, return NULL; } -static const struct got_error *resolve_delta_chain(struct got_delta_chain *, - struct got_repository *repo, FILE *, const char *, int, off_t, size_t); +static const struct got_error * +resolve_delta_chain(struct got_delta_chain *, struct got_repository *, + FILE *, const char *, off_t, size_t, int, size_t); static const struct got_error * resolve_offset_delta(struct got_delta_chain *deltas, @@ -576,7 +577,7 @@ resolve_offset_delta(struct got_delta_chain *deltas, return err; return resolve_delta_chain(deltas, repo, packfile, path_packfile, - base_type, base_offset + base_tslen, base_size); + base_offset, base_tslen, base_type, base_size); } static const struct got_error * @@ -625,7 +626,8 @@ resolve_ref_delta(struct got_delta_chain *deltas, stru goto done; err = resolve_delta_chain(deltas, repo, base_packfile, - path_base_packfile, base_type, base_offset + base_tslen, base_size); + path_base_packfile, base_offset, base_tslen, base_type, + base_size); done: free(path_base_packfile); if (base_packfile && fclose(base_packfile) == -1 && err == 0) @@ -635,14 +637,14 @@ done: static const struct got_error * resolve_delta_chain(struct got_delta_chain *deltas, struct got_repository *repo, - FILE *packfile, const char *path_packfile, int delta_type, - off_t delta_offset, size_t delta_size) + FILE *packfile, const char *path_packfile, off_t delta_offset, size_t tslen, + int delta_type, size_t delta_size) { const struct got_error *err = NULL; struct got_delta *delta; - delta = got_delta_open(path_packfile, delta_type, delta_offset, - delta_size); + delta = got_delta_open(path_packfile, delta_offset, tslen, + delta_type, delta_size); if (delta == NULL) return got_error(GOT_ERR_NO_MEM); deltas->nentries++; @@ -705,7 +707,7 @@ open_delta_object(struct got_object **obj, struct got_ (*obj)->flags |= GOT_OBJ_FLAG_DELTIFIED; err = resolve_delta_chain(&(*obj)->deltas, repo, packfile, - path_packfile, delta_type, offset, delta_size); + path_packfile, offset, tslen, delta_type, delta_size); if (err) goto done; @@ -830,7 +832,8 @@ dump_delta_chain(struct got_delta_chain *deltas, FILE goto done; } - if (fseeko(delta_file, delta->offset, SEEK_SET) != 0) { + if (fseeko(delta_file, delta->offset + delta->tslen, + SEEK_SET) != 0) { fclose(delta_file); err = got_error_from_errno(); goto done; @@ -856,6 +859,13 @@ dump_delta_chain(struct got_delta_chain *deltas, FILE continue; } + if (delta->type == GOT_OBJ_TYPE_REF_DELTA && + fseeko(delta_file, SHA1_DIGEST_LENGTH, SEEK_CUR) != 0) { + fclose(delta_file); + err = got_error_from_errno(); + goto done; + } + /* Delta streams should always fit in memory. */ err = got_inflate_to_mem(&delta_buf, &delta_len, delta_file); fclose(delta_file);