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