1 /* 2 * Lazy test for the case when the output size is known 3 * 4 * Author: Lasse Collin <lasse.collin@tukaani.org> 5 * 6 * This file has been put into the public domain. 7 * You can do whatever you want with this file. 8 */ 9 10 #include <stdbool.h> 11 #include <stdio.h> 12 #include <string.h> 13 #include <stdlib.h> 14 #include "xz.h" 15 16 static uint8_t in[1]; 17 static uint8_t out[BUFSIZ]; 18 19 int main(int argc, char **argv) 20 { 21 struct xz_buf b; 22 struct xz_dec *s; 23 enum xz_ret ret; 24 const char *msg; 25 size_t uncomp_size; 26 27 if (argc != 2) { 28 fputs("Give uncompressed size as the argument\n", stderr); 29 return 1; 30 } 31 32 uncomp_size = atoi(argv[1]); 33 34 xz_crc32_init(); 35 36 /* 37 * Support up to 64 MiB dictionary. The actually needed memory 38 * is allocated once the headers have been parsed. 39 */ 40 s = xz_dec_init(XZ_DYNALLOC, 1 << 26); 41 if (s == NULL) { 42 msg = "Memory allocation failed\n"; 43 goto error; 44 } 45 46 b.in = in; 47 b.in_pos = 0; 48 b.in_size = 0; 49 b.out = out; 50 b.out_pos = 0; 51 b.out_size = uncomp_size < BUFSIZ ? uncomp_size : BUFSIZ; 52 53 while (true) { 54 if (b.in_pos == b.in_size) { 55 b.in_size = fread(in, 1, sizeof(in), stdin); 56 b.in_pos = 0; 57 } 58 59 ret = xz_dec_run(s, &b); 60 61 if (b.out_pos == sizeof(out)) { 62 if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { 63 msg = "Write error\n"; 64 goto error; 65 } 66 67 uncomp_size -= b.out_pos; 68 b.out_pos = 0; 69 b.out_size = uncomp_size < BUFSIZ 70 ? uncomp_size : BUFSIZ; 71 } 72 73 if (ret == XZ_OK) 74 continue; 75 76 #ifdef XZ_DEC_ANY_CHECK 77 if (ret == XZ_UNSUPPORTED_CHECK) { 78 fputs(argv[0], stderr); 79 fputs(": ", stderr); 80 fputs("Unsupported check; not verifying " 81 "file integrity\n", stderr); 82 continue; 83 } 84 #endif 85 86 if (uncomp_size != b.out_pos) { 87 msg = "Uncompressed size doesn't match\n"; 88 goto error; 89 } 90 91 if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos 92 || fclose(stdout)) { 93 msg = "Write error\n"; 94 goto error; 95 } 96 97 switch (ret) { 98 case XZ_STREAM_END: 99 xz_dec_end(s); 100 return 0; 101 102 case XZ_MEM_ERROR: 103 msg = "Memory allocation failed\n"; 104 goto error; 105 106 case XZ_MEMLIMIT_ERROR: 107 msg = "Memory usage limit reached\n"; 108 goto error; 109 110 case XZ_FORMAT_ERROR: 111 msg = "Not a .xz file\n"; 112 goto error; 113 114 case XZ_OPTIONS_ERROR: 115 msg = "Unsupported options in the .xz headers\n"; 116 goto error; 117 118 case XZ_DATA_ERROR: 119 case XZ_BUF_ERROR: 120 msg = "File is corrupt\n"; 121 goto error; 122 123 default: 124 msg = "Bug!\n"; 125 goto error; 126 } 127 } 128 129 error: 130 xz_dec_end(s); 131 fputs(argv[0], stderr); 132 fputs(": ", stderr); 133 fputs(msg, stderr); 134 return 1; 135 } 136