Home | History | Annotate | Download | only in userspace
      1 /*
      2  * Lazy test for the case when the output size is known
      3  *
      4  * Author: Lasse Collin <lasse.collin (at) 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 
     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