commit 740bba1c3179a597c83f7dd3a23bffb50a494bdf from: Stefan Sperling date: Fri Jun 18 14:07:35 2021 UTC allow the delta base file to lose its header between deltify_init and deltify This simplifies pack file creation. A delta base could be read from a loose object, a packfile, or it might be available in a temporary file. All these cases can now be handled the same way. We may need to open, close, and re-open a given delta base multiple times while packing. commit - 7550e799ee994b0b74689a6895f84d8aaec86f49 commit + 740bba1c3179a597c83f7dd3a23bffb50a494bdf blob - bbacc26192e00fbffaf5fe865009ca9857b1da8c blob + b743863af583889f11b7117b9af6b067cbd196c7 --- lib/deltify.c +++ lib/deltify.c @@ -96,7 +96,8 @@ hashblk(const unsigned char *p, off_t n) } static const struct got_error * -addblk(struct got_delta_table *dt, FILE *f, off_t len, off_t offset, uint64_t h) +addblk(struct got_delta_table *dt, FILE *f, off_t file_offset0, off_t len, + off_t offset, uint64_t h) { const struct got_error *err = NULL; int i; @@ -116,7 +117,7 @@ addblk(struct got_delta_table *dt, FILE *f, off_t len, */ if (len == dt->blocks[i].len && h == dt->blocks[i].hash) { if (r == 0) { - if (fseeko(f, offset, SEEK_SET) == -1) + if (fseeko(f, file_offset0 + offset, SEEK_SET) == -1) return got_error_from_errno("fseeko"); r = fread(buf, 1, len, f); if (r != len) { @@ -125,7 +126,8 @@ addblk(struct got_delta_table *dt, FILE *f, off_t len, return got_ferror(f, GOT_ERR_IO); } } - if (fseeko(f, dt->blocks[i].offset, SEEK_SET) == -1) + if (fseeko(f, file_offset0 + dt->blocks[i].offset, + SEEK_SET) == -1) return got_error_from_errno("fseeko"); if (fread(buf2, 1, len, f) != len) return got_ferror(f, GOT_ERR_IO); @@ -160,8 +162,8 @@ addblk(struct got_delta_table *dt, FILE *f, off_t len, for (i = 0; i < old_size; i++) { if (db[i].len == 0) continue; - err = addblk(dt, f, db[i].len, db[i].offset, - db[i].hash); + err = addblk(dt, f, file_offset0, db[i].len, + db[i].offset, db[i].hash); if (err) break; } @@ -173,7 +175,7 @@ addblk(struct got_delta_table *dt, FILE *f, off_t len, static const struct got_error * lookupblk(struct got_delta_block **block, struct got_delta_table *dt, - unsigned char *p, off_t len, FILE *basefile) + unsigned char *p, off_t len, FILE *basefile, off_t basefile_offset0) { int i; uint64_t h; @@ -188,7 +190,8 @@ lookupblk(struct got_delta_block **block, struct got_d if (dt->blocks[i].hash != h || dt->blocks[i].len != len) continue; - if (fseeko(basefile, dt->blocks[i].offset, SEEK_SET) == -1) + if (fseeko(basefile, basefile_offset0 + dt->blocks[i].offset, + SEEK_SET) == -1) return got_error_from_errno("fseeko"); r = fread(buf, 1, len, basefile); if (r != len) @@ -239,6 +242,7 @@ got_deltify_init(struct got_delta_table **dt, FILE *f, { const struct got_error *err = NULL; uint64_t h; + const off_t offset0 = fileoffset; *dt = calloc(1, sizeof(**dt)); if (*dt == NULL) @@ -264,7 +268,8 @@ got_deltify_init(struct got_delta_table **dt, FILE *f, if (blocklen == 0) break; h = hashblk(buf, blocklen); - err = addblk(*dt, f, blocklen, fileoffset, h); + err = addblk(*dt, f, offset0, blocklen, + fileoffset - offset0, h); if (err) goto done; fileoffset += blocklen; @@ -310,14 +315,14 @@ emitdelta(struct got_delta_instruction **deltas, int * } static const struct got_error * -stretchblk(FILE *basefile, struct got_delta_block *block, FILE *f, - off_t filesize, off_t *blocklen) +stretchblk(FILE *basefile, off_t base_offset0, struct got_delta_block *block, + FILE *f, off_t filesize, off_t *blocklen) { uint8_t basebuf[GOT_DELTIFY_MAXCHUNK], buf[GOT_DELTIFY_MAXCHUNK]; size_t base_r, r, i; int buf_equal = 1; - if (fseeko(basefile, block->offset, SEEK_SET) == -1) + if (fseeko(basefile, base_offset0 + block->offset, SEEK_SET) == -1) return got_error_from_errno("fseeko"); while (buf_equal && *blocklen < (1 << 24) - 1) { @@ -374,7 +379,8 @@ got_deltify(struct got_delta_instruction **deltas, int break; if (blocklen == 0) break; - err = lookupblk(&block, dt, buf, blocklen, basefile); + err = lookupblk(&block, dt, buf, blocklen, basefile, + basefile_offset0); if (err) break; if (block != NULL) { @@ -383,8 +389,8 @@ got_deltify(struct got_delta_instruction **deltas, int * Attempt to stretch the block as far as possible and * generate a copy instruction. */ - err = stretchblk(basefile, block, f, filesize, - &blocklen); + err = stretchblk(basefile, basefile_offset0, block, + f, filesize, &blocklen); if (err) break; err = emitdelta(deltas, ndeltas, 1, block->offset, blocklen);