/* * 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; }