diff --git a/common.c b/common.c index e9af5ec..90431dd 100644 --- a/common.c +++ b/common.c @@ -62,6 +62,14 @@ void *decode_block_start(off_t block_seek) { return bw; } +bool is_multi_header(const char *name) { + size_t i = strlen(name); + while (i != 0 && name[i - 1] != '/') + --i; + + return strncmp(name + i, "._", 2) == 0; +} + #pragma mark INDEX diff --git a/pixz.h b/pixz.h index f3d3bac..6467ce4 100644 --- a/pixz.h +++ b/pixz.h @@ -53,6 +53,7 @@ extern file_index_t *gFileIndex, *gLastFile; // As discovered from footer extern lzma_check gCheck; +bool is_multi_header(const char *name); void decode_index(void); lzma_vli find_file_index(void **bdatap); diff --git a/pread.c b/pread.c index 8fe92f1..b7a6932 100644 --- a/pread.c +++ b/pread.c @@ -8,7 +8,6 @@ /* TODO * - Don't read index unless necessary? * - Check sizes of files vs index - * - Allow copyfile multi-headers */ #define DEBUG 0 @@ -122,8 +121,10 @@ int main(int argc, char **argv) { fprintf(stderr, "%s\n", archive_error_string(ar)); die("Error reading archive entry"); } - const char *path = archive_entry_pathname(entry); + if (is_multi_header(path)) + continue; + size_t size = archive_entry_size(entry); if (!w) die("File %s missing in index", path); @@ -136,6 +137,7 @@ int main(int argc, char **argv) { } if (w && w->name) die("File %s missing in archive", w->name); + tar_read(NULL, NULL, NULL); // write whatever's left } else { pipeline_item_t *pi; while ((pi = pipeline_merged())) { @@ -373,6 +375,7 @@ static ssize_t tar_read(struct archive *ar, void *ref, const void **bufp) { if (gArItem) { io_block_t *ib = (io_block_t*)(gArItem->data); fwrite(ib->output + gArLastOffset, gArLastSize, 1, gOutFile); + gArLastSize = 0; } // Write the first wanted file @@ -383,13 +386,14 @@ static ssize_t tar_read(struct archive *ar, void *ref, const void **bufp) { size_t size; io_block_t *ib = (io_block_t*)(gArItem->data); if (gWantedFiles) { + debug("tar want: %s", gArWanted->name); off = gArWanted->start - ib->uoffset; size = gArWanted->size; if (off < 0) { size += off; off = 0; } - if (off + size > ib->outsize) { + if (off + size >= ib->outsize) { size = ib->outsize - off; gArNextItem = true; // force the end of this block } else { @@ -399,9 +403,11 @@ static ssize_t tar_read(struct archive *ar, void *ref, const void **bufp) { off = 0; size = ib->outsize; } + debug("tar off = %zu, size = %zu", off, size); gArLastOffset = off; gArLastSize = size; - *bufp = ib->output + off; + if (bufp) + *bufp = ib->output + off; return size; } diff --git a/write.c b/write.c index a5b17ad..7409f2d 100644 --- a/write.c +++ b/write.c @@ -52,7 +52,6 @@ static void encode_thread(size_t thnum); static void *block_create(); static void block_free(void *data); -static bool is_multi_header(const char *name); static void add_file(off_t offset, const char *name); static archive_read_callback tar_read; @@ -240,14 +239,6 @@ static int tar_ok(struct archive *ar, void *ref) { return ARCHIVE_OK; } -static bool is_multi_header(const char *name) { - size_t i = strlen(name); - while (i != 0 && name[i - 1] != '/') - --i; - - return strncmp(name + i, "._", 2) == 0; -} - static void add_file(off_t offset, const char *name) { if (name && is_multi_header(name)) { if (!gMultiHeader)