2
0
mirror of https://github.com/vasi/pixz synced 2024-11-03 09:40:24 +00:00
pixz/read.c
2010-10-10 23:48:34 -04:00

106 lines
2.9 KiB
C

#include "pixz.h"
#pragma mark FUNCTION DECLARATIONS
static void extract_file(const char *target);
static void extract_block(off_t block_seek, off_t skip, off_t size);
#pragma mark FUNCTION DEFINITIONS
int main(int argc, char **argv) {
if (argc != 3)
die("Need two arguments");
if (!(gInFile = fopen(argv[1], "r")))
die("Can't open input file");
char *target = argv[2];
decode_index();
if (!read_file_index())
die("File has no index");
extract_file(target);
free_file_index();
lzma_index_end(gIndex, NULL);
return 0;
}
static void extract_file(const char *target) {
// find it in the index
file_index_t *f;
for (f = gFileIndex; f != NULL; f = f->next) {
if (f->name && strcmp(f->name, target) == 0)
break;
}
if (!f)
die("Can't find target file");
off_t fstart = f->offset, fsize = f->next->offset - fstart;
// extract the data
lzma_index_iter iter;
lzma_index_iter_init(&iter, gIndex);
if (lzma_index_iter_locate(&iter, fstart))
die("Block with file contents can't be found");
do {
off_t bstart = iter.block.uncompressed_file_offset,
bsize = iter.block.uncompressed_size;
off_t dstart = fstart > bstart ? fstart - bstart : 0;
bsize -= dstart;
off_t dsize = fsize > bsize ? bsize : fsize;
fsize -= dsize;
extract_block(iter.block.compressed_file_offset, dstart, dsize);
} while (fsize && !lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
if (fsize)
die("Block with file contents missing");
}
static void extract_block(off_t block_seek, off_t skip, off_t size) {
void *bdata = decode_block_start(block_seek);
uint8_t ibuf[CHUNKSIZE], obuf[CHUNKSIZE];
gStream.avail_in = 0;
lzma_ret err = LZMA_OK;
while (size && err != LZMA_STREAM_END) {
gStream.next_out = obuf;
gStream.avail_out = CHUNKSIZE;
if (gStream.avail_in == 0) {
gStream.avail_in = fread(ibuf, 1, CHUNKSIZE, gInFile);
if (ferror(gInFile))
die("Error reading block data");
gStream.next_in = ibuf;
}
err = lzma_code(&gStream, LZMA_RUN);
if (err != LZMA_OK && err != LZMA_STREAM_END)
die("Error decoding block");
// do we want to write?
uint8_t *start = obuf;
size_t out = gStream.next_out - obuf;
if (out <= skip) {
skip -= out;
continue;
}
// what do we want to write?
start += skip;
out -= skip;
skip = 0;
if (out > size)
out = size;
if (fwrite(start, out, 1, stdout) != 1)
die("Error writing output");
size -= out;
}
if (size)
die("Block data missing");
lzma_end(&gStream);
free(bdata);
}