diff options
Diffstat (limited to 'libraries/xz-embedded/xzminidec.c')
-rw-r--r-- | libraries/xz-embedded/xzminidec.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/libraries/xz-embedded/xzminidec.c b/libraries/xz-embedded/xzminidec.c new file mode 100644 index 00000000..bb62c3ac --- /dev/null +++ b/libraries/xz-embedded/xzminidec.c @@ -0,0 +1,144 @@ +/* + * Simple XZ decoder command line tool + * + * Author: Lasse Collin <lasse.collin@tukaani.org> + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + */ + +/* + * This is really limited: Not all filters from .xz format are supported, + * only CRC32 is supported as the integrity check, and decoding of + * concatenated .xz streams is not supported. Thus, you may want to look + * at xzdec from XZ Utils if a few KiB bigger tool is not a problem. + */ + +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include "xz.h" + +static uint8_t in[BUFSIZ]; +static uint8_t out[BUFSIZ]; + +int main(int argc, char **argv) +{ + struct xz_buf b; + struct xz_dec *s; + enum xz_ret ret; + const char *msg; + + if (argc >= 2 && strcmp(argv[1], "--help") == 0) + { + fputs("Uncompress a .xz file from stdin to stdout.\n" + "Arguments other than `--help' are ignored.\n", + stdout); + return 0; + } + + xz_crc32_init(); +#ifdef XZ_USE_CRC64 + xz_crc64_init(); +#endif + + /* + * Support up to 64 MiB dictionary. The actually needed memory + * is allocated once the headers have been parsed. + */ + s = xz_dec_init(XZ_DYNALLOC, 1 << 26); + if (s == NULL) + { + msg = "Memory allocation failed\n"; + goto error; + } + + b.in = in; + b.in_pos = 0; + b.in_size = 0; + b.out = out; + b.out_pos = 0; + b.out_size = BUFSIZ; + + while (true) + { + if (b.in_pos == b.in_size) + { + b.in_size = fread(in, 1, sizeof(in), stdin); + b.in_pos = 0; + } + + ret = xz_dec_run(s, &b); + + if (b.out_pos == sizeof(out)) + { + if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) + { + msg = "Write error\n"; + goto error; + } + + b.out_pos = 0; + } + + if (ret == XZ_OK) + continue; + +#ifdef XZ_DEC_ANY_CHECK + if (ret == XZ_UNSUPPORTED_CHECK) + { + fputs(argv[0], stderr); + fputs(": ", stderr); + fputs("Unsupported check; not verifying " + "file integrity\n", + stderr); + continue; + } +#endif + + if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos || fclose(stdout)) + { + msg = "Write error\n"; + goto error; + } + + switch (ret) + { + case XZ_STREAM_END: + xz_dec_end(s); + return 0; + + case XZ_MEM_ERROR: + msg = "Memory allocation failed\n"; + goto error; + + case XZ_MEMLIMIT_ERROR: + msg = "Memory usage limit reached\n"; + goto error; + + case XZ_FORMAT_ERROR: + msg = "Not a .xz file\n"; + goto error; + + case XZ_OPTIONS_ERROR: + msg = "Unsupported options in the .xz headers\n"; + goto error; + + case XZ_DATA_ERROR: + case XZ_BUF_ERROR: + msg = "File is corrupt\n"; + goto error; + + default: + msg = "Bug!\n"; + goto error; + } + } + +error: + xz_dec_end(s); + fputs(argv[0], stderr); + fputs(": ", stderr); + fputs(msg, stderr); + return 1; +} |