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