Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /* streams working on a lzma/xz-compressed disk file */
14 :
15 : #include "monetdb_config.h"
16 : #include "stream.h"
17 : #include "stream_internal.h"
18 : #include "pump.h"
19 :
20 :
21 : #ifdef HAVE_LIBLZMA
22 :
23 : struct inner_state {
24 : lzma_stream strm;
25 : uint8_t buf[64*1024];
26 : lzma_ret error_code;
27 : };
28 :
29 : static pump_buffer
30 2690 : xz_get_src_win(inner_state_t *xz)
31 : {
32 2690 : return (pump_buffer) {
33 2690 : .start = (char*) xz->strm.next_in,
34 2690 : .count = xz->strm.avail_in,
35 : };
36 : }
37 :
38 : static void
39 726 : xz_set_src_win(inner_state_t *xz, pump_buffer buf)
40 : {
41 726 : xz->strm.next_in = (const uint8_t*)buf.start;
42 726 : xz->strm.avail_in = buf.count;
43 726 : }
44 :
45 : static pump_buffer
46 1460 : xz_get_dst_win(inner_state_t *xz)
47 : {
48 1460 : return (pump_buffer) {
49 1460 : .start = (char*) xz->strm.next_out,
50 1460 : .count = xz->strm.avail_out,
51 : };
52 : }
53 :
54 : static void
55 214 : xz_set_dst_win(inner_state_t *xz, pump_buffer buf)
56 : {
57 214 : xz->strm.next_out = (uint8_t*)buf.start;
58 214 : xz->strm.avail_out = buf.count;
59 214 : }
60 :
61 : static pump_buffer
62 728 : xz_get_buffer(inner_state_t *xz)
63 : {
64 728 : return (pump_buffer) {
65 728 : .start = (char*)xz->buf,
66 : .count = sizeof(xz->buf),
67 : };
68 : }
69 :
70 : static pump_result
71 728 : xz_work(inner_state_t *xz, pump_action action)
72 : {
73 728 : lzma_action a;
74 728 : switch (action) {
75 : case PUMP_NO_FLUSH:
76 : a = LZMA_RUN;
77 : break;
78 : case PUMP_FLUSH_DATA:
79 : a = LZMA_SYNC_FLUSH;
80 : break;
81 : case PUMP_FLUSH_ALL:
82 : a = LZMA_FULL_FLUSH;
83 : break;
84 : case PUMP_FINISH:
85 : a = LZMA_FINISH;
86 : break;
87 : default:
88 0 : assert(0 /* unknown action */);
89 : return PUMP_ERROR;
90 : }
91 :
92 728 : lzma_ret ret = lzma_code(&xz->strm, a);
93 728 : xz->error_code = ret;
94 :
95 728 : switch (ret) {
96 : case LZMA_OK:
97 : return PUMP_OK;
98 211 : case LZMA_STREAM_END:
99 211 : return PUMP_END;
100 0 : default:
101 0 : return PUMP_ERROR;
102 : }
103 : }
104 :
105 : static void
106 2 : xz_finalizer(inner_state_t *xz)
107 : {
108 2 : lzma_end(&xz->strm);
109 2 : free(xz);
110 2 : }
111 :
112 : static const char *
113 0 : xz_get_error(inner_state_t *xz)
114 : {
115 0 : static const char *msgs[] = {
116 : "LZMA_OK",
117 : "LZMA_STREAM_END",
118 : "LZMA_NO_CHECK",
119 : "LZMA_UNSUPPORTED_CHECK",
120 : "LZMA_GET_CHECK",
121 : "LZMA_MEM_ERROR",
122 : "LZMA_MEMLIMIT_ERROR",
123 : "LZMA_FORMAT_ERROR",
124 : "LZMA_OPTIONS_ERROR",
125 : "LZMA_DATA_ERROR",
126 : "LZMA_BUF_ERROR",
127 : "LZMA_PROG_ERROR"
128 : };
129 :
130 0 : if (xz->error_code <= LZMA_PROG_ERROR)
131 0 : return msgs[xz->error_code];
132 : else
133 : return "unknown LZMA error code";
134 : }
135 :
136 :
137 :
138 :
139 : stream *
140 2 : xz_stream(stream *inner, int preset)
141 : {
142 2 : inner_state_t *xz = calloc(1, sizeof(inner_state_t));
143 2 : pump_state *state = calloc(1, sizeof(pump_state));
144 2 : if (xz == NULL || state == NULL) {
145 0 : free(xz);
146 0 : free(state);
147 0 : mnstr_set_open_error(inner->name, errno, "couldn't initialize xz stream");
148 0 : return NULL;
149 : }
150 :
151 2 : state->inner_state = xz;
152 2 : state->get_src_win = xz_get_src_win;
153 2 : state->set_src_win = xz_set_src_win;
154 2 : state->get_dst_win = xz_get_dst_win;
155 2 : state->set_dst_win = xz_set_dst_win;
156 2 : state->get_buffer = xz_get_buffer;
157 2 : state->worker = xz_work;
158 2 : state->finalizer = xz_finalizer;
159 2 : state->get_error = xz_get_error;
160 :
161 2 : lzma_ret ret;
162 2 : if (inner->readonly) {
163 1 : ret = lzma_stream_decoder(&xz->strm, UINT64_MAX, LZMA_CONCATENATED);
164 : } else {
165 1 : ret = lzma_easy_encoder(&xz->strm, preset, LZMA_CHECK_CRC64);
166 : }
167 :
168 2 : stream *s;
169 :
170 2 : if (ret != LZMA_OK || (s = pump_stream(inner, state)) == NULL) {
171 0 : lzma_end(&xz->strm);
172 0 : free(xz);
173 0 : free(state);
174 0 : return NULL;
175 : }
176 :
177 : return s;
178 : }
179 :
180 : static stream *
181 0 : open_xzstream(const char *restrict filename, const char *restrict flags)
182 : {
183 0 : stream *inner;
184 0 : int preset = 0;
185 :
186 0 : inner = open_stream(filename, flags);
187 0 : if (inner == NULL)
188 : return NULL;
189 :
190 0 : return xz_stream(inner, preset);
191 : }
192 :
193 : stream *
194 0 : open_xzrstream(const char *filename)
195 : {
196 0 : stream *s = open_xzstream(filename, "rb");
197 0 : if (s == NULL)
198 : return NULL;
199 :
200 0 : assert(s->readonly == true);
201 0 : assert(s->binary == true);
202 : return s;
203 : }
204 :
205 : stream *
206 0 : open_xzwstream(const char *restrict filename, const char *restrict mode)
207 : {
208 0 : stream *s = open_xzstream(filename, mode);
209 0 : if (s == NULL)
210 : return NULL;
211 :
212 0 : assert(s->readonly == false);
213 0 : assert(s->binary == true);
214 : return s;
215 : }
216 :
217 : stream *
218 0 : open_xzrastream(const char *filename)
219 : {
220 0 : stream *s = open_xzstream(filename, "r");
221 0 : s = create_text_stream(s);
222 0 : if (s == NULL)
223 : return NULL;
224 :
225 0 : assert(s->readonly == true);
226 0 : assert(s->binary == false);
227 : return s;
228 : }
229 :
230 : stream *
231 0 : open_xzwastream(const char *restrict filename, const char *restrict mode)
232 : {
233 0 : stream *s = open_xzstream(filename, mode);
234 0 : s = create_text_stream(s);
235 0 : if (s == NULL)
236 : return NULL;
237 0 : assert(s->readonly == false);
238 0 : assert(s->binary == false);
239 : return s;
240 : }
241 : #else
242 :
243 : stream *
244 : xz_stream(stream *inner, int preset)
245 : {
246 : (void) inner;
247 : (void) preset;
248 : mnstr_set_open_error(inner->name, 0, "XZ/LZMA support has been left out of this MonetDB");
249 : return NULL;
250 : }
251 : stream *
252 : open_xzrstream(const char *filename)
253 : {
254 : mnstr_set_open_error(filename, 0, "XZ/LZMA support has been left out of this MonetDB");
255 : return NULL;
256 : }
257 :
258 : stream *
259 : open_xzwstream(const char *restrict filename, const char *restrict mode)
260 : {
261 : (void) mode;
262 : mnstr_set_open_error(filename, 0, "XZ/LZMA support has been left out of this MonetDB");
263 : return NULL;
264 : }
265 :
266 : stream *
267 : open_xzrastream(const char *filename)
268 : {
269 : mnstr_set_open_error(filename, 0, "XZ/LZMA support has been left out of this MonetDB");
270 : return NULL;
271 : }
272 :
273 : stream *
274 : open_xzwastream(const char *restrict filename, const char *restrict mode)
275 : {
276 : (void) mode;
277 : mnstr_set_open_error(filename, 0, "XZ/LZMA support has been left out of this MonetDB");
278 : return NULL;
279 : }
280 :
281 : #endif
|