diff options
Diffstat (limited to 'lib/uncompress.c')
-rw-r--r-- | lib/uncompress.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/lib/uncompress.c b/lib/uncompress.c index 3e4bc5f9e5..11f55c8f9f 100644 --- a/lib/uncompress.c +++ b/lib/uncompress.c @@ -3,9 +3,6 @@ * * Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * - * See file CREDITS for list of people who contributed to this - * project. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. @@ -23,24 +20,26 @@ #include <lzo.h> #include <linux/xz.h> #include <linux/decompress/unlz4.h> +#include <linux/decompress/unzstd.h> #include <errno.h> #include <filetype.h> #include <malloc.h> #include <fs.h> +#include <libfile.h> static void *uncompress_buf; -static unsigned int uncompress_size; +static unsigned long uncompress_size; void uncompress_err_stdout(char *x) { printf("%s\n", x); } -static int (*uncompress_fill_fn)(void*, unsigned int); +static long (*uncompress_fill_fn)(void*, unsigned long); -static int uncompress_fill(void *buf, unsigned int len) +static long uncompress_fill(void *buf, unsigned long len) { - int total = 0; + long total = 0; if (uncompress_size) { int now = min(len, uncompress_size); @@ -62,19 +61,19 @@ static int uncompress_fill(void *buf, unsigned int len) return total; } -int uncompress(unsigned char *inbuf, int len, - int(*fill)(void*, unsigned int), - int(*flush)(void*, unsigned int), +int uncompress(unsigned char *inbuf, long len, + long(*fill)(void*, unsigned long), + long(*flush)(void*, unsigned long), unsigned char *output, - int *pos, + long *pos, void(*error_fn)(char *x)) { enum filetype ft; - int (*compfn)(unsigned char *inbuf, int len, - int(*fill)(void*, unsigned int), - int(*flush)(void*, unsigned int), + int (*compfn)(unsigned char *inbuf, long len, + long(*fill)(void*, unsigned long), + long(*flush)(void*, unsigned long), unsigned char *output, - int *pos, + long *pos, void(*error)(char *x)); int ret; char *err; @@ -98,6 +97,8 @@ int uncompress(unsigned char *inbuf, int len, ft = file_detect_type(uncompress_buf, 32); } + pr_debug("Filetype detected: %s\n", file_type_to_string(ft)); + switch (ft) { #ifdef CONFIG_BZLIB case filetype_bzip2: @@ -124,6 +125,11 @@ int uncompress(unsigned char *inbuf, int len, compfn = decompress_unxz; break; #endif +#ifdef CONFIG_ZSTD_DECOMPRESS + case filetype_zstd_compressed: + compfn = unzstd; + break; +#endif default: err = basprintf("cannot handle filetype %s", file_type_to_string(ft)); @@ -143,12 +149,12 @@ err: static int uncompress_infd, uncompress_outfd; -static int fill_fd(void *buf, unsigned int len) +static long fill_fd(void *buf, unsigned long len) { - return read(uncompress_infd, buf, len); + return read_full(uncompress_infd, buf, len); } -static int flush_fd(void *buf, unsigned int len) +static long flush_fd(void *buf, unsigned long len) { return write(uncompress_outfd, buf, len); } @@ -174,3 +180,39 @@ int uncompress_fd_to_buf(int infd, void *output, return uncompress(NULL, 0, fill_fd, NULL, output, NULL, error_fn); } + +int uncompress_buf_to_fd(const void *input, size_t input_len, + int outfd, void(*error_fn)(char *x)) +{ + uncompress_outfd = outfd; + + return uncompress((void *)input, input_len, NULL, flush_fd, + NULL, NULL, error_fn); +} + +ssize_t uncompress_buf_to_buf(const void *input, size_t input_len, + void **buf, void(*error_fn)(char *x)) +{ + size_t size; + int fd, ret; + void *p; + + fd = open("/tmp", O_TMPFILE | O_RDWR); + if (fd < 0) + return -ENODEV; + + ret = uncompress_buf_to_fd(input, input_len, fd, error_fn); + if (ret) + goto close_fd; + + p = read_fd(fd, &size); + if (p) + *buf = p; + else + ret = -errno; + +close_fd: + close(fd); + + return ret ?: size; +} |