1229159Sadrian/* 2229159Sadrian * Simple XZ decoder command line tool 3229159Sadrian * 4229159Sadrian * Author: Lasse Collin <lasse.collin@tukaani.org> 5229159Sadrian * 6229159Sadrian * This file has been put into the public domain. 7229159Sadrian * You can do whatever you want with this file. 8229159Sadrian */ 9229159Sadrian 10229159Sadrian/* 11229159Sadrian * This is really limited: Not all filters from .xz format are supported, 12229159Sadrian * only CRC32 is supported as the integrity check, and decoding of 13229159Sadrian * concatenated .xz streams is not supported. Thus, you may want to look 14229159Sadrian * at xzdec from XZ Utils if a few KiB bigger tool is not a problem. 15229159Sadrian */ 16229159Sadrian 17229159Sadrian#include <stdbool.h> 18229159Sadrian#include <stdio.h> 19229159Sadrian#include <string.h> 20229159Sadrian#include "xz.h" 21229159Sadrian 22229159Sadrianstatic uint8_t in[BUFSIZ]; 23229159Sadrianstatic uint8_t out[BUFSIZ]; 24229159Sadrian 25229159Sadrianint main(int argc, char **argv) 26229159Sadrian{ 27229159Sadrian struct xz_buf b; 28229159Sadrian struct xz_dec *s; 29229159Sadrian enum xz_ret ret; 30229159Sadrian const char *msg; 31229159Sadrian 32229159Sadrian if (argc >= 2 && strcmp(argv[1], "--help") == 0) { 33229159Sadrian fputs("Uncompress a .xz file from stdin to stdout.\n" 34229159Sadrian "Arguments other than `--help' are ignored.\n", 35229159Sadrian stdout); 36229159Sadrian return 0; 37229159Sadrian } 38229159Sadrian 39229159Sadrian xz_crc32_init(); 40262764Sdelphij#ifdef XZ_USE_CRC64 41262764Sdelphij xz_crc64_init(); 42262764Sdelphij#endif 43229159Sadrian 44229159Sadrian /* 45229159Sadrian * Support up to 64 MiB dictionary. The actually needed memory 46229159Sadrian * is allocated once the headers have been parsed. 47229159Sadrian */ 48229159Sadrian s = xz_dec_init(XZ_DYNALLOC, 1 << 26); 49229159Sadrian if (s == NULL) { 50229159Sadrian msg = "Memory allocation failed\n"; 51229159Sadrian goto error; 52229159Sadrian } 53229159Sadrian 54229159Sadrian b.in = in; 55229159Sadrian b.in_pos = 0; 56229159Sadrian b.in_size = 0; 57229159Sadrian b.out = out; 58229159Sadrian b.out_pos = 0; 59229159Sadrian b.out_size = BUFSIZ; 60229159Sadrian 61229159Sadrian while (true) { 62229159Sadrian if (b.in_pos == b.in_size) { 63229159Sadrian b.in_size = fread(in, 1, sizeof(in), stdin); 64229159Sadrian b.in_pos = 0; 65229159Sadrian } 66229159Sadrian 67229159Sadrian ret = xz_dec_run(s, &b); 68229159Sadrian 69229159Sadrian if (b.out_pos == sizeof(out)) { 70229159Sadrian if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { 71229159Sadrian msg = "Write error\n"; 72229159Sadrian goto error; 73229159Sadrian } 74229159Sadrian 75229159Sadrian b.out_pos = 0; 76229159Sadrian } 77229159Sadrian 78229159Sadrian if (ret == XZ_OK) 79229159Sadrian continue; 80229159Sadrian 81229159Sadrian#ifdef XZ_DEC_ANY_CHECK 82229159Sadrian if (ret == XZ_UNSUPPORTED_CHECK) { 83229159Sadrian fputs(argv[0], stderr); 84229159Sadrian fputs(": ", stderr); 85229159Sadrian fputs("Unsupported check; not verifying " 86229159Sadrian "file integrity\n", stderr); 87229159Sadrian continue; 88229159Sadrian } 89229159Sadrian#endif 90229159Sadrian 91229159Sadrian if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos 92229159Sadrian || fclose(stdout)) { 93229159Sadrian msg = "Write error\n"; 94229159Sadrian goto error; 95229159Sadrian } 96229159Sadrian 97229159Sadrian switch (ret) { 98229159Sadrian case XZ_STREAM_END: 99229159Sadrian xz_dec_end(s); 100229159Sadrian return 0; 101229159Sadrian 102229159Sadrian case XZ_MEM_ERROR: 103229159Sadrian msg = "Memory allocation failed\n"; 104229159Sadrian goto error; 105229159Sadrian 106229159Sadrian case XZ_MEMLIMIT_ERROR: 107229159Sadrian msg = "Memory usage limit reached\n"; 108229159Sadrian goto error; 109229159Sadrian 110229159Sadrian case XZ_FORMAT_ERROR: 111229159Sadrian msg = "Not a .xz file\n"; 112229159Sadrian goto error; 113229159Sadrian 114229159Sadrian case XZ_OPTIONS_ERROR: 115229159Sadrian msg = "Unsupported options in the .xz headers\n"; 116229159Sadrian goto error; 117229159Sadrian 118229159Sadrian case XZ_DATA_ERROR: 119229159Sadrian case XZ_BUF_ERROR: 120229159Sadrian msg = "File is corrupt\n"; 121229159Sadrian goto error; 122229159Sadrian 123229159Sadrian default: 124229159Sadrian msg = "Bug!\n"; 125229159Sadrian goto error; 126229159Sadrian } 127229159Sadrian } 128229159Sadrian 129229159Sadrianerror: 130229159Sadrian xz_dec_end(s); 131229159Sadrian fputs(argv[0], stderr); 132229159Sadrian fputs(": ", stderr); 133229159Sadrian fputs(msg, stderr); 134229159Sadrian return 1; 135229159Sadrian} 136