aboutsummaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2010-12-02 12:38:21 +0200
committerLasse Collin <lasse.collin@tukaani.org>2010-12-02 12:38:21 +0200
commit64a7180e84d876d44600b00e96203bf573ecc93b (patch)
tree2b02fc082e5f68668649ea3bb62b72424eb719fe /linux
parent64c515e42b2266e38a45cff12b4fe8cb0f6682af (diff)
downloadxz-embedded-64a7180e84d876d44600b00e96203bf573ecc93b.tar.gz
Fix decompress_unxz.c API.
Previously only the features that were needed by the code currently in Linux were implemented. However, <linux/decompress/generic.h> requires a few other features too, so implement them for consistency with other decompressors: - Callback-to-buffer mode - Ability to use caller-given input buffer with fill() Thanks to Phillip Lougher.
Diffstat (limited to 'linux')
-rw-r--r--linux/lib/decompress_unxz.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/linux/lib/decompress_unxz.c b/linux/lib/decompress_unxz.c
index 000332c..cecd23d 100644
--- a/linux/lib/decompress_unxz.c
+++ b/linux/lib/decompress_unxz.c
@@ -257,12 +257,16 @@ STATIC int INIT unxz(unsigned char *in, int in_size,
struct xz_buf b;
struct xz_dec *s;
enum xz_ret ret;
+ bool must_free_in = false;
#if XZ_INTERNAL_CRC32
xz_crc32_init();
#endif
- if (in != NULL && out != NULL)
+ if (in_used != NULL)
+ *in_used = 0;
+
+ if (fill == NULL && flush == NULL)
s = xz_dec_init(XZ_SINGLE, 0);
else
s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
@@ -270,32 +274,31 @@ STATIC int INIT unxz(unsigned char *in, int in_size,
if (s == NULL)
goto error_alloc_state;
- b.in = in;
- b.in_pos = 0;
- b.in_size = in_size;
- b.out_pos = 0;
-
- if (in_used != NULL)
- *in_used = 0;
-
- if (fill == NULL && flush == NULL) {
+ if (flush == NULL) {
b.out = out;
b.out_size = (size_t)-1;
- ret = xz_dec_run(s, &b);
} else {
b.out_size = XZ_IOBUF_SIZE;
b.out = malloc(XZ_IOBUF_SIZE);
if (b.out == NULL)
goto error_alloc_out;
+ }
- if (fill != NULL) {
- in = malloc(XZ_IOBUF_SIZE);
- if (in == NULL)
- goto error_alloc_in;
+ if (in == NULL) {
+ must_free_in = true;
+ in = malloc(XZ_IOBUF_SIZE);
+ if (in == NULL)
+ goto error_alloc_in;
+ }
- b.in = in;
- }
+ b.in = in;
+ b.in_pos = 0;
+ b.in_size = in_size;
+ b.out_pos = 0;
+ if (fill == NULL && flush == NULL) {
+ ret = xz_dec_run(s, &b);
+ } else {
do {
if (b.in_pos == b.in_size && fill != NULL) {
if (in_used != NULL)
@@ -319,8 +322,8 @@ STATIC int INIT unxz(unsigned char *in, int in_size,
ret = xz_dec_run(s, &b);
- if (b.out_pos == b.out_size
- || (ret != XZ_OK && b.out_pos > 0)) {
+ if (flush != NULL && (b.out_pos == b.out_size
+ || (ret != XZ_OK && b.out_pos > 0))) {
/*
* Setting ret here may hide an error
* returned by xz_dec_run(), but probably
@@ -333,10 +336,11 @@ STATIC int INIT unxz(unsigned char *in, int in_size,
}
} while (ret == XZ_OK);
- if (fill != NULL)
+ if (must_free_in)
free(in);
- free(b.out);
+ if (flush != NULL)
+ free(b.out);
}
if (in_used != NULL)
@@ -375,7 +379,8 @@ STATIC int INIT unxz(unsigned char *in, int in_size,
return -1;
error_alloc_in:
- free(b.out);
+ if (flush != NULL)
+ free(b.out);
error_alloc_out:
xz_dec_end(s);