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(); 40229159Sadrian 41229159Sadrian /* 42229159Sadrian * Support up to 64 MiB dictionary. The actually needed memory 43229159Sadrian * is allocated once the headers have been parsed. 44229159Sadrian */ 45229159Sadrian s = xz_dec_init(XZ_DYNALLOC, 1 << 26); 46229159Sadrian if (s == NULL) { 47229159Sadrian msg = "Memory allocation failed\n"; 48229159Sadrian goto error; 49229159Sadrian } 50229159Sadrian 51229159Sadrian b.in = in; 52229159Sadrian b.in_pos = 0; 53229159Sadrian b.in_size = 0; 54229159Sadrian b.out = out; 55229159Sadrian b.out_pos = 0; 56229159Sadrian b.out_size = BUFSIZ; 57229159Sadrian 58229159Sadrian while (true) { 59229159Sadrian if (b.in_pos == b.in_size) { 60229159Sadrian b.in_size = fread(in, 1, sizeof(in), stdin); 61229159Sadrian b.in_pos = 0; 62229159Sadrian } 63229159Sadrian 64229159Sadrian ret = xz_dec_run(s, &b); 65229159Sadrian 66229159Sadrian if (b.out_pos == sizeof(out)) { 67229159Sadrian if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { 68229159Sadrian msg = "Write error\n"; 69229159Sadrian goto error; 70229159Sadrian } 71229159Sadrian 72229159Sadrian b.out_pos = 0; 73229159Sadrian } 74229159Sadrian 75229159Sadrian if (ret == XZ_OK) 76229159Sadrian continue; 77229159Sadrian 78229159Sadrian#ifdef XZ_DEC_ANY_CHECK 79229159Sadrian if (ret == XZ_UNSUPPORTED_CHECK) { 80229159Sadrian fputs(argv[0], stderr); 81229159Sadrian fputs(": ", stderr); 82229159Sadrian fputs("Unsupported check; not verifying " 83229159Sadrian "file integrity\n", stderr); 84229159Sadrian continue; 85229159Sadrian } 86229159Sadrian#endif 87229159Sadrian 88229159Sadrian if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos 89229159Sadrian || fclose(stdout)) { 90229159Sadrian msg = "Write error\n"; 91229159Sadrian goto error; 92229159Sadrian } 93229159Sadrian 94229159Sadrian switch (ret) { 95229159Sadrian case XZ_STREAM_END: 96229159Sadrian xz_dec_end(s); 97229159Sadrian return 0; 98229159Sadrian 99229159Sadrian case XZ_MEM_ERROR: 100229159Sadrian msg = "Memory allocation failed\n"; 101229159Sadrian goto error; 102229159Sadrian 103229159Sadrian case XZ_MEMLIMIT_ERROR: 104229159Sadrian msg = "Memory usage limit reached\n"; 105229159Sadrian goto error; 106229159Sadrian 107229159Sadrian case XZ_FORMAT_ERROR: 108229159Sadrian msg = "Not a .xz file\n"; 109229159Sadrian goto error; 110229159Sadrian 111229159Sadrian case XZ_OPTIONS_ERROR: 112229159Sadrian msg = "Unsupported options in the .xz headers\n"; 113229159Sadrian goto error; 114229159Sadrian 115229159Sadrian case XZ_DATA_ERROR: 116229159Sadrian case XZ_BUF_ERROR: 117229159Sadrian msg = "File is corrupt\n"; 118229159Sadrian goto error; 119229159Sadrian 120229159Sadrian default: 121229159Sadrian msg = "Bug!\n"; 122229159Sadrian goto error; 123229159Sadrian } 124229159Sadrian } 125229159Sadrian 126229159Sadrianerror: 127229159Sadrian xz_dec_end(s); 128229159Sadrian fputs(argv[0], stderr); 129229159Sadrian fputs(": ", stderr); 130229159Sadrian fputs(msg, stderr); 131229159Sadrian return 1; 132229159Sadrian} 133