From a2750dee0e4c374ae51f83eead7eb7df3c018d95 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 4 May 2019 23:20:28 +0200 Subject: rdsquashfs: malloc extraction buffers ahead of time Instead of malloc/freeing the buffers for every file, allocate them once, ahead of time. Signed-off-by: David Oberhollenzer --- unpack/extract_file.c | 43 +++++++++++++++++-------------------------- unpack/rdsquashfs.c | 25 +++++++++++++++++++++++++ unpack/rdsquashfs.h | 3 +++ 3 files changed, 45 insertions(+), 26 deletions(-) (limited to 'unpack') diff --git a/unpack/extract_file.c b/unpack/extract_file.c index 4d5997a..62d1086 100644 --- a/unpack/extract_file.c +++ b/unpack/extract_file.c @@ -3,19 +3,12 @@ int extract_file(file_info_t *fi, unsqfs_info_t *info, int outfd) { - void *buffer, *scratch, *ptr; size_t i, count, fragsz; bool compressed; uint32_t bs; ssize_t ret; + void *ptr; - buffer = malloc(info->block_size * 2); - if (buffer == NULL) { - perror("allocating scratch buffer"); - return -1; - } - - scratch = (char *)buffer + info->block_size; count = fi->size / info->block_size; if (count > 0) { @@ -31,7 +24,7 @@ int extract_file(file_info_t *fi, unsqfs_info_t *info, int outfd) if (bs > info->block_size) goto fail_bs; - ret = read_retry(info->sqfsfd, buffer, bs); + ret = read_retry(info->sqfsfd, info->buffer, bs); if (ret < 0) goto fail_rd; @@ -39,16 +32,17 @@ int extract_file(file_info_t *fi, unsqfs_info_t *info, int outfd) goto fail_trunc; if (compressed) { - ret = info->cmp->do_block(info->cmp, buffer, bs, - scratch, + ret = info->cmp->do_block(info->cmp, + info->buffer, bs, + info->scratch, info->block_size); if (ret <= 0) - goto fail; + return -1; bs = ret; - ptr = scratch; + ptr = info->scratch; } else { - ptr = buffer; + ptr = info->buffer; } ret = write_retry(outfd, ptr, bs); @@ -64,11 +58,12 @@ int extract_file(file_info_t *fi, unsqfs_info_t *info, int outfd) if (fragsz > 0) { if (frag_reader_read(info->frag, fi->fragment, - fi->fragment_offset, buffer, fragsz)) { - goto fail; + fi->fragment_offset, info->buffer, + fragsz)) { + return -1; } - ret = write_retry(outfd, buffer, fragsz); + ret = write_retry(outfd, info->buffer, fragsz); if (ret < 0) goto fail_wr; @@ -76,27 +71,23 @@ int extract_file(file_info_t *fi, unsqfs_info_t *info, int outfd) goto fail_wr_trunc; } - free(buffer); return 0; fail_seek: perror("seek on squashfs"); - goto fail; + return -1; fail_wr: perror("writing uncompressed block"); - goto fail; + return -1; fail_wr_trunc: fputs("writing uncompressed block: truncated write\n", stderr); - goto fail; + return -1; fail_rd: perror("reading from squashfs"); - goto fail; + return -1; fail_trunc: fputs("reading from squashfs: unexpected end of file\n", stderr); - goto fail; + return -1; fail_bs: fputs("found compressed block larger than block size\n", stderr); - goto fail; -fail: - free(buffer); return -1; } diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index 3c80853..c286a78 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -110,6 +110,23 @@ static char *get_path(char *old, const char *arg) return path; } +static int alloc_buffers(unsqfs_info_t *info, sqfs_super_t *super) +{ + info->buffer = malloc(super->block_size); + if (info->buffer == NULL) { + perror("allocating block buffer"); + return -1; + } + + info->scratch = malloc(super->block_size); + if (info->scratch == NULL) { + perror("allocating scrtach buffer for extracting blocks"); + return -1; + } + + return 0; +} + static int load_fragment_table(unsqfs_info_t *info, sqfs_super_t *super) { if (super->fragment_entry_count == 0) @@ -274,6 +291,9 @@ int main(int argc, char **argv) if (load_fragment_table(&info, &super)) goto out_fs; + if (alloc_buffers(&info, &super)) + goto out_fs; + if (extract_file(n->data.file, &info, STDOUT_FILENO)) goto out_fs; break; @@ -291,6 +311,9 @@ int main(int argc, char **argv) if (load_fragment_table(&info, &super)) goto out_fs; + if (alloc_buffers(&info, &super)) + goto out_fs; + if (restore_fstree(unpack_root, n, &info)) goto out_fs; break; @@ -307,6 +330,8 @@ out_fd: close(info.sqfsfd); out_cmd: free(cmdpath); + free(info.buffer); + free(info.scratch); return status; fail_arg: fprintf(stderr, "Try `%s --help' for more information.\n", __progname); diff --git a/unpack/rdsquashfs.h b/unpack/rdsquashfs.h index 0961591..c06afb2 100644 --- a/unpack/rdsquashfs.h +++ b/unpack/rdsquashfs.h @@ -35,6 +35,9 @@ typedef struct { frag_reader_t *frag; int sqfsfd; int flags; + + void *buffer; + void *scratch; } unsqfs_info_t; tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, -- cgit v1.2.3