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
main(int argc,char ** argv)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