You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
2.5 KiB
135 lines
2.5 KiB
/* |
|
* Lazy test for the case when the output size is known |
|
* |
|
* Author: Lasse Collin <lasse.collin@tukaani.org> |
|
* |
|
* This file has been put into the public domain. |
|
* You can do whatever you want with this file. |
|
*/ |
|
|
|
#include <stdbool.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <stdlib.h> |
|
#include "xz.h" |
|
|
|
static uint8_t in[1]; |
|
static uint8_t out[BUFSIZ]; |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
struct xz_buf b; |
|
struct xz_dec *s; |
|
enum xz_ret ret; |
|
const char *msg; |
|
size_t uncomp_size; |
|
|
|
if (argc != 2) { |
|
fputs("Give uncompressed size as the argument\n", stderr); |
|
return 1; |
|
} |
|
|
|
uncomp_size = atoi(argv[1]); |
|
|
|
xz_crc32_init(); |
|
|
|
/* |
|
* Support up to 64 MiB dictionary. The actually needed memory |
|
* is allocated once the headers have been parsed. |
|
*/ |
|
s = xz_dec_init(XZ_DYNALLOC, 1 << 26); |
|
if (s == NULL) { |
|
msg = "Memory allocation failed\n"; |
|
goto error; |
|
} |
|
|
|
b.in = in; |
|
b.in_pos = 0; |
|
b.in_size = 0; |
|
b.out = out; |
|
b.out_pos = 0; |
|
b.out_size = uncomp_size < BUFSIZ ? uncomp_size : BUFSIZ; |
|
|
|
while (true) { |
|
if (b.in_pos == b.in_size) { |
|
b.in_size = fread(in, 1, sizeof(in), stdin); |
|
b.in_pos = 0; |
|
} |
|
|
|
ret = xz_dec_run(s, &b); |
|
|
|
if (b.out_pos == sizeof(out)) { |
|
if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { |
|
msg = "Write error\n"; |
|
goto error; |
|
} |
|
|
|
uncomp_size -= b.out_pos; |
|
b.out_pos = 0; |
|
b.out_size = uncomp_size < BUFSIZ |
|
? uncomp_size : BUFSIZ; |
|
} |
|
|
|
if (ret == XZ_OK) |
|
continue; |
|
|
|
#ifdef XZ_DEC_ANY_CHECK |
|
if (ret == XZ_UNSUPPORTED_CHECK) { |
|
fputs(argv[0], stderr); |
|
fputs(": ", stderr); |
|
fputs("Unsupported check; not verifying " |
|
"file integrity\n", stderr); |
|
continue; |
|
} |
|
#endif |
|
|
|
if (uncomp_size != b.out_pos) { |
|
msg = "Uncompressed size doesn't match\n"; |
|
goto error; |
|
} |
|
|
|
if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos |
|
|| fclose(stdout)) { |
|
msg = "Write error\n"; |
|
goto error; |
|
} |
|
|
|
switch (ret) { |
|
case XZ_STREAM_END: |
|
xz_dec_end(s); |
|
return 0; |
|
|
|
case XZ_MEM_ERROR: |
|
msg = "Memory allocation failed\n"; |
|
goto error; |
|
|
|
case XZ_MEMLIMIT_ERROR: |
|
msg = "Memory usage limit reached\n"; |
|
goto error; |
|
|
|
case XZ_FORMAT_ERROR: |
|
msg = "Not a .xz file\n"; |
|
goto error; |
|
|
|
case XZ_OPTIONS_ERROR: |
|
msg = "Unsupported options in the .xz headers\n"; |
|
goto error; |
|
|
|
case XZ_DATA_ERROR: |
|
case XZ_BUF_ERROR: |
|
msg = "File is corrupt\n"; |
|
goto error; |
|
|
|
default: |
|
msg = "Bug!\n"; |
|
goto error; |
|
} |
|
} |
|
|
|
error: |
|
xz_dec_end(s); |
|
fputs(argv[0], stderr); |
|
fputs(": ", stderr); |
|
fputs(msg, stderr); |
|
return 1; |
|
}
|
|
|