1 #include <lzma.h> 2 #include <stdio.h> 3 #include <linux/compiler.h> 4 #include "util.h" 5 #include "debug.h" 6 7 #define BUFSIZE 8192 8 9 static const char *lzma_strerror(lzma_ret ret) 10 { 11 switch ((int) ret) { 12 case LZMA_MEM_ERROR: 13 return "Memory allocation failed"; 14 case LZMA_OPTIONS_ERROR: 15 return "Unsupported decompressor flags"; 16 case LZMA_FORMAT_ERROR: 17 return "The input is not in the .xz format"; 18 case LZMA_DATA_ERROR: 19 return "Compressed file is corrupt"; 20 case LZMA_BUF_ERROR: 21 return "Compressed file is truncated or otherwise corrupt"; 22 default: 23 return "Unknown error, possibly a bug"; 24 } 25 } 26 27 int lzma_decompress_to_file(const char *input, int output_fd) 28 { 29 lzma_action action = LZMA_RUN; 30 lzma_stream strm = LZMA_STREAM_INIT; 31 lzma_ret ret; 32 33 u8 buf_in[BUFSIZE]; 34 u8 buf_out[BUFSIZE]; 35 FILE *infile; 36 37 infile = fopen(input, "rb"); 38 if (!infile) { 39 pr_err("lzma: fopen failed on %s: '%s'\n", 40 input, strerror(errno)); 41 return -1; 42 } 43 44 ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED); 45 if (ret != LZMA_OK) { 46 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n", 47 lzma_strerror(ret), ret); 48 return -1; 49 } 50 51 strm.next_in = NULL; 52 strm.avail_in = 0; 53 strm.next_out = buf_out; 54 strm.avail_out = sizeof(buf_out); 55 56 while (1) { 57 if (strm.avail_in == 0 && !feof(infile)) { 58 strm.next_in = buf_in; 59 strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile); 60 61 if (ferror(infile)) { 62 pr_err("lzma: read error: %s\n", strerror(errno)); 63 return -1; 64 } 65 66 if (feof(infile)) 67 action = LZMA_FINISH; 68 } 69 70 ret = lzma_code(&strm, action); 71 72 if (strm.avail_out == 0 || ret == LZMA_STREAM_END) { 73 ssize_t write_size = sizeof(buf_out) - strm.avail_out; 74 75 if (writen(output_fd, buf_out, write_size) != write_size) { 76 pr_err("lzma: write error: %s\n", strerror(errno)); 77 return -1; 78 } 79 80 strm.next_out = buf_out; 81 strm.avail_out = sizeof(buf_out); 82 } 83 84 if (ret != LZMA_OK) { 85 if (ret == LZMA_STREAM_END) 86 return 0; 87 88 pr_err("lzma: failed %s\n", lzma_strerror(ret)); 89 return -1; 90 } 91 } 92 93 fclose(infile); 94 return 0; 95 } 96