commit bdd2fbb322a3775fd72d509c35794d84cfe6c88d from: Stefan Sperling date: Sun Feb 11 23:01:26 2018 UTC read delta data from the right offset commit - 06e5fc98c0fca4d47edc5ba2d0e7e9d0addcafdd commit + bdd2fbb322a3775fd72d509c35794d84cfe6c88d blob - c7ae922fdd4a145746c22771f63ff2e6ba588bb8 blob + 0ae98da4f6d7015c65b00992f291d39125a30efd --- lib/delta.c +++ lib/delta.c @@ -36,7 +36,7 @@ struct got_delta * got_delta_open(const char *path_packfile, off_t offset, size_t tslen, - int type, size_t size) + int type, size_t size, off_t data_offset) { struct got_delta *delta; @@ -53,6 +53,7 @@ got_delta_open(const char *path_packfile, off_t offset delta->offset = offset; delta->tslen = tslen; delta->size = size; + delta->data_offset = data_offset; return delta; } blob - 159057631e643f4fad94371f41acbd2023aa9529 blob + fb5e1481403dce4d214df33cc142f465105f5dc0 --- lib/delta.h +++ lib/delta.h @@ -21,6 +21,7 @@ struct got_delta { size_t tslen; int type; size_t size; + off_t data_offset; }; struct got_delta_chain { @@ -28,7 +29,8 @@ struct got_delta_chain { SIMPLEQ_HEAD(, got_delta) entries; }; -struct got_delta *got_delta_open(const char *, off_t, size_t, int, size_t); +struct got_delta *got_delta_open(const char *, off_t, size_t, int, size_t, + off_t); void got_delta_close(struct got_delta *); const struct got_error *got_delta_chain_get_base_type(int *, struct got_delta_chain *); blob - dd64e4ac004ebf28028927affaa8a9d342b5f944 blob + 3098ee5298760506e297b4c3fcc5fa9a041e5dc2 --- lib/pack.c +++ lib/pack.c @@ -553,20 +553,48 @@ resolve_delta_chain(struct got_delta_chain *, struct g FILE *, const char *, off_t, size_t, int, size_t); static const struct got_error * +add_delta(struct got_delta_chain *deltas, const char *path_packfile, + off_t delta_offset, size_t tslen, int delta_type, size_t delta_size, + size_t delta_data_offset) +{ + struct got_delta *delta; + + delta = got_delta_open(path_packfile, delta_offset, tslen, + delta_type, delta_size, delta_data_offset); + if (delta == NULL) + return got_error(GOT_ERR_NO_MEM); + /* delta is freed in got_object_close() */ + deltas->nentries++; + SIMPLEQ_INSERT_HEAD(&deltas->entries, delta, entry); + return NULL; +} + +static const struct got_error * resolve_offset_delta(struct got_delta_chain *deltas, struct got_repository *repo, FILE *packfile, const char *path_packfile, - off_t delta_offset) + off_t delta_offset,size_t tslen, int delta_type, size_t delta_size) + { const struct got_error *err; off_t base_offset; uint8_t base_type; uint64_t base_size; size_t base_tslen; + off_t delta_data_offset; err = parse_offset_delta(&base_offset, packfile, delta_offset); if (err) return err; + delta_data_offset = ftello(packfile); + if (delta_data_offset == -1) + return got_error_from_errno(); + + err = add_delta(deltas, path_packfile, delta_offset, tslen, + delta_type, delta_size, delta_data_offset); + if (err) + return err; + /* An offset delta must be in the same packfile. */ if (fseeko(packfile, base_offset, SEEK_SET) != 0) return got_error_from_errno(); @@ -582,7 +610,8 @@ resolve_offset_delta(struct got_delta_chain *deltas, static const struct got_error * resolve_ref_delta(struct got_delta_chain *deltas, struct got_repository *repo, - FILE *packfile, const char *path_packfile, off_t delta_offset) + 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; struct got_object_id id; @@ -595,11 +624,21 @@ resolve_ref_delta(struct got_delta_chain *deltas, stru size_t n; FILE *base_packfile; char *path_base_packfile; + off_t delta_data_offset; n = fread(&id, sizeof(id), 1, packfile); if (n != 1) return got_ferror(packfile, GOT_ERR_IO); + delta_data_offset = ftello(packfile); + if (delta_data_offset == -1) + return got_error_from_errno(); + + err = add_delta(deltas, path_packfile, delta_offset, tslen, + delta_type, delta_size, delta_data_offset); + if (err) + return err; + err = search_packidx(&packidx, &idx, repo, &id); if (err) return err; @@ -641,30 +680,25 @@ resolve_delta_chain(struct got_delta_chain *deltas, st int delta_type, size_t delta_size) { const struct got_error *err = NULL; - struct got_delta *delta; - 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++; - SIMPLEQ_INSERT_HEAD(&deltas->entries, delta, entry); - /* In case of error below, delta is freed in got_object_close(). */ - switch (delta_type) { case GOT_OBJ_TYPE_COMMIT: case GOT_OBJ_TYPE_TREE: case GOT_OBJ_TYPE_BLOB: case GOT_OBJ_TYPE_TAG: /* Plain types are the final delta base. Recursion ends. */ + err = add_delta(deltas, path_packfile, delta_offset, tslen, + delta_type, delta_size, 0); break; case GOT_OBJ_TYPE_OFFSET_DELTA: err = resolve_offset_delta(deltas, repo, packfile, - path_packfile, delta_offset); + path_packfile, delta_offset, tslen, delta_type, + delta_size); break; case GOT_OBJ_TYPE_REF_DELTA: - err = resolve_ref_delta(deltas, repo, packfile, path_packfile, - delta_offset); + err = resolve_ref_delta(deltas, repo, packfile, + path_packfile, delta_offset, tslen, delta_type, + delta_size); break; default: return got_error(GOT_ERR_NOT_IMPL); @@ -832,12 +866,6 @@ dump_delta_chain(struct got_delta_chain *deltas, FILE goto done; } - if (fseeko(delta_file, delta->offset + delta->tslen, - SEEK_SET) != 0) { - fclose(delta_file); - err = got_error_from_errno(); - goto done; - } if (n == 0) { /* Plain object types are the delta base. */ @@ -849,6 +877,12 @@ dump_delta_chain(struct got_delta_chain *deltas, FILE goto done; } + if (fseeko(delta_file, delta->offset + delta->tslen, + SEEK_SET) != 0) { + fclose(delta_file); + err = got_error_from_errno(); + goto done; + } err = got_inflate_to_file(&delta_len, delta_file, base_file); fclose(delta_file); @@ -859,8 +893,7 @@ 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) { + if (fseeko(delta_file, delta->data_offset, SEEK_CUR) != 0) { fclose(delta_file); err = got_error_from_errno(); goto done;