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