| /* |
| * Lazy test for the case when the output size is known |
| * |
| * Author: Lasse Collin <[email protected]> |
| * |
| * 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; |
| } |