]> pd.if.org Git - zpackage/blob - lib/uncompress.c
add error checking
[zpackage] / lib / uncompress.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <errno.h>
7
8 #include <sys/mman.h>
9
10 #include <sqlite3.h>
11
12 #include "sha256.h"
13
14 #include "lzma.h"
15
16 void uncompresslzma(void *buf, size_t bufsize, FILE *out) {
17         lzma_stream s = LZMA_STREAM_INIT;
18         lzma_stream *strm;
19         
20         uint8_t outbuf[BUFSIZ];
21
22         int ret;
23
24         strm = &s;
25
26         ret = lzma_stream_decoder(strm, UINT64_MAX, 0);
27         /* The only reasonable error here is LZMA_MEM_ERROR. */
28         if (ret != LZMA_OK) {
29                 fprintf(stderr, "%s", ret == LZMA_MEM_ERROR ? strerror(ENOMEM)
30                                 : "Internal error (bug)");
31                 exit(EXIT_FAILURE);
32         }
33
34         strm->avail_in = bufsize;
35         strm->next_in = buf;
36         strm->avail_out = BUFSIZ;
37         strm->next_out = outbuf;
38
39         lzma_action action = LZMA_RUN;
40
41         while (1) {
42                 ret = lzma_code(strm, action);
43
44                 // Write and check write error before checking decoder error.
45                 // This way as much data as possible gets written to output
46                 // even if decoder detected an error.
47                 if (strm->avail_out == 0 || ret != LZMA_OK) {
48                         const size_t write_size = BUFSIZ - strm->avail_out;
49
50                         if (fwrite(outbuf, 1, write_size, out) != write_size) {
51                                 // Wouldn't be a surprise if writing to stderr
52                                 // would fail too but at least try to show an
53                                 // error message.
54                                 fprintf(stderr, "Cannot write to output file stream: "
55                                                 "%s", strerror(errno));
56                                 exit(EXIT_FAILURE);
57                         }
58
59                         strm->next_out = outbuf;
60                         strm->avail_out = BUFSIZ;
61                 }
62
63                 if (ret != LZMA_OK) {
64                         if (ret == LZMA_STREAM_END) {
65                                 // lzma_stream_decoder() already guarantees
66                                 // that there's no trailing garbage.
67                                 assert(strm->avail_in == 0);
68                                 //assert(action == LZMA_FINISH);
69                                 return;
70                         }
71
72                         const char *msg;
73                         switch (ret) {
74                                 case LZMA_MEM_ERROR:
75                                         msg = strerror(ENOMEM);
76                                         break;
77
78                                 case LZMA_FORMAT_ERROR:
79                                         msg = "File format not recognized";
80                                         break;
81
82                                 case LZMA_OPTIONS_ERROR:
83                                         // FIXME: Better message?
84                                         msg = "Unsupported compression options";
85                                         break;
86
87                                 case LZMA_DATA_ERROR:
88                                         msg = "File is corrupt";
89                                         break;
90
91                                 case LZMA_BUF_ERROR:
92                                         msg = "Unexpected end of input";
93                                         break;
94
95                                 default:
96                                         msg = "Internal error (bug)";
97                                         break;
98                         }
99
100                         fprintf(stderr, "xz: %s\n", msg);
101                         exit(EXIT_FAILURE);
102                 }
103         }
104 }