diff options
-rw-r--r-- | lib/sqfs/data_reader.c | 132 |
1 files changed, 67 insertions, 65 deletions
diff --git a/lib/sqfs/data_reader.c b/lib/sqfs/data_reader.c index e03a436..196da32 100644 --- a/lib/sqfs/data_reader.c +++ b/lib/sqfs/data_reader.c @@ -61,86 +61,94 @@ void data_reader_destroy(data_reader_t *data) free(data); } -int data_reader_dump_file(data_reader_t *data, file_info_t *fi, int outfd, - bool allow_sparse) +static int dump_blocks(data_reader_t *data, file_info_t *fi, int outfd, + bool allow_sparse, size_t count) { - size_t i, count, fragsz, unpackedsz; - off_t sqfs_location; + off_t sqfs_location = fi->startblock; + size_t i, unpackedsz; uint64_t filesz = 0; bool compressed; uint32_t bs; ssize_t ret; void *ptr; - count = fi->size / data->block_size; - fragsz = fi->size % data->block_size; + for (i = 0; i < count; ++i) { + bs = fi->blocksizes[i]; - if (fragsz != 0 && (fi->fragment == 0xFFFFFFFF || - fi->fragment_offset == 0xFFFFFFFF)) { - fragsz = 0; - ++count; - } + compressed = (bs & (1 << 24)) == 0; + bs &= (1 << 24) - 1; - if (count > 0) { - sqfs_location = fi->startblock; + if (bs > data->block_size) + goto fail_bs; - for (i = 0; i < count; ++i) { - bs = fi->blocksizes[i]; + if ((fi->size - filesz) < (uint64_t)data->block_size) { + unpackedsz = fi->size - filesz; + } else { + unpackedsz = data->block_size; + } - compressed = (bs & (1 << 24)) == 0; - bs &= (1 << 24) - 1; + filesz += unpackedsz; - if (bs > data->block_size) - goto fail_bs; + if (bs == 0 && allow_sparse) { + if (ftruncate(outfd, filesz)) + goto fail_sparse; + if (lseek(outfd, 0, SEEK_END) == (off_t)-1) + goto fail_sparse; + continue; + } - if ((fi->size - filesz) < (uint64_t)data->block_size) { - unpackedsz = fi->size - filesz; - } else { - unpackedsz = data->block_size; + if (bs == 0) { + memset(data->buffer, 0, unpackedsz); + compressed = false; + } else { + if (read_data_at("reading data block", sqfs_location, + data->sqfsfd, data->buffer, bs)) { + return -1; } + sqfs_location += bs; + } - filesz += unpackedsz; + if (compressed) { + ret = data->cmp->do_block(data->cmp, data->buffer, bs, + data->scratch, + data->block_size); + if (ret <= 0) + return -1; - if (bs == 0 && allow_sparse) { - if (ftruncate(outfd, filesz)) - goto fail_sparse; - if (lseek(outfd, 0, SEEK_END) == (off_t)-1) - goto fail_sparse; - continue; - } + ptr = data->scratch; + } else { + ptr = data->buffer; + } - if (bs == 0) { - memset(data->buffer, 0, unpackedsz); - compressed = false; - } else { - if (read_data_at("reading data block", - sqfs_location, data->sqfsfd, - data->buffer, bs)) { - return -1; - } - sqfs_location += bs; - } + if (write_data("writing uncompressed block", + outfd, ptr, unpackedsz)) { + return -1; + } + } + return 0; +fail_sparse: + perror("creating sparse output file"); + return -1; +fail_bs: + fputs("found compressed block larger than block size\n", stderr); + return -1; +} - if (compressed) { - ret = data->cmp->do_block(data->cmp, - data->buffer, bs, - data->scratch, - data->block_size); - if (ret <= 0) - return -1; - - ptr = data->scratch; - } else { - ptr = data->buffer; - } +int data_reader_dump_file(data_reader_t *data, file_info_t *fi, int outfd, + bool allow_sparse) +{ + size_t fragsz = fi->size % data->block_size; + size_t count = fi->size / data->block_size; - if (write_data("writing uncompressed block", - outfd, ptr, unpackedsz)) { - return -1; - } - } + if (fragsz != 0 && (fi->fragment == 0xFFFFFFFF || + fi->fragment_offset == 0xFFFFFFFF)) { + fragsz = 0; + ++count; } + if (dump_blocks(data, fi, outfd, allow_sparse, count)) + return -1; + if (fragsz > 0) { if (data->frag == NULL) goto fail_frag; @@ -158,12 +166,6 @@ int data_reader_dump_file(data_reader_t *data, file_info_t *fi, int outfd, } return 0; -fail_sparse: - perror("creating sparse output file"); - return -1; -fail_bs: - fputs("found compressed block larger than block size\n", stderr); - return -1; fail_frag: fputs("file not a multiple of block size but no fragments available\n", stderr); |