1 /*-
2  * Copyright (c) 2009-2011 Sean Purcell
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "archive_platform.h"
27 
28 #ifdef HAVE_ERRNO_H
29 #include <errno.h>
30 #endif
31 
32 #ifdef HAVE_ERRNO_H
33 #include <errno.h>
34 #endif
35 #include <stdio.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 #ifdef HAVE_STRING_H
40 #include <string.h>
41 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #if HAVE_ZSTD_H
46 #include <zstd.h>
47 #endif
48 
49 #include "archive.h"
50 #include "archive_endian.h"
51 #include "archive_private.h"
52 #include "archive_read_private.h"
53 
54 #if HAVE_ZSTD_H && HAVE_LIBZSTD
55 
56 struct private_data {
57 	ZSTD_DStream	*dstream;
58 	unsigned char	*out_block;
59 	size_t		 out_block_size;
60 	int64_t		 total_out;
61 	char		 in_frame; /* True = in the middle of a zstd frame. */
62 	char		 eof; /* True = found end of compressed data. */
63 };
64 
65 /* Zstd Filter. */
66 static ssize_t	zstd_filter_read(struct archive_read_filter *, const void**);
67 static int	zstd_filter_close(struct archive_read_filter *);
68 #endif
69 
70 /*
71  * Note that we can detect zstd compressed files even if we can't decompress
72  * them.  (In fact, we like detecting them because we can give better error
73  * messages.)  So the bid framework here gets compiled even if no zstd library
74  * is available.
75  */
76 static int	zstd_bidder_bid(struct archive_read_filter_bidder *,
77 		    struct archive_read_filter *);
78 static int	zstd_bidder_init(struct archive_read_filter *);
79 
80 static const struct archive_read_filter_bidder_vtable
81 zstd_bidder_vtable = {
82 	.bid = zstd_bidder_bid,
83 	.init = zstd_bidder_init,
84 };
85 
86 int
87 archive_read_support_filter_zstd(struct archive *_a)
88 {
89 	struct archive_read *a = (struct archive_read *)_a;
90 
91 	if (__archive_read_register_bidder(a, NULL, "zstd",
92 				&zstd_bidder_vtable) != ARCHIVE_OK)
93 		return (ARCHIVE_FATAL);
94 
95 #if HAVE_ZSTD_H && HAVE_LIBZSTD
96 	return (ARCHIVE_OK);
97 #else
98 	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
99 	    "Using external zstd program for zstd decompression");
100 	return (ARCHIVE_WARN);
101 #endif
102 }
103 
104 /*
105  * Test whether we can handle this data.
106  */
107 static int
108 zstd_bidder_bid(struct archive_read_filter_bidder *self,
109     struct archive_read_filter *filter)
110 {
111 	const unsigned char *buffer;
112 	ssize_t avail;
113 	unsigned prefix;
114 
115 	/* Zstd frame magic values */
116 	unsigned zstd_magic = 0xFD2FB528U;
117 	unsigned zstd_magic_skippable_start = 0x184D2A50U;
118 	unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
119 
120 	(void) self; /* UNUSED */
121 
122 	buffer = __archive_read_filter_ahead(filter, 4, &avail);
123 	if (buffer == NULL)
124 		return (0);
125 
126 	prefix = archive_le32dec(buffer);
127 	if (prefix == zstd_magic)
128 		return (32);
129 	if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start)
130 		return (32);
131 
132 	return (0);
133 }
134 
135 #if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
136 
137 /*
138  * If we don't have the library on this system, we can't do the
139  * decompression directly.  We can, however, try to run "zstd -d"
140  * in case that's available.
141  */
142 static int
143 zstd_bidder_init(struct archive_read_filter *self)
144 {
145 	int r;
146 
147 	r = __archive_read_program(self, "zstd -d -qq");
148 	/* Note: We set the format here even if __archive_read_program()
149 	 * above fails.  We do, after all, know what the format is
150 	 * even if we weren't able to read it. */
151 	self->code = ARCHIVE_FILTER_ZSTD;
152 	self->name = "zstd";
153 	return (r);
154 }
155 
156 #else
157 
158 static const struct archive_read_filter_vtable
159 zstd_reader_vtable = {
160 	.read = zstd_filter_read,
161 	.close = zstd_filter_close,
162 };
163 
164 /*
165  * Initialize the filter object
166  */
167 static int
168 zstd_bidder_init(struct archive_read_filter *self)
169 {
170 	struct private_data *state;
171 	size_t out_block_size = ZSTD_DStreamOutSize();
172 	void *out_block;
173 	ZSTD_DStream *dstream;
174 
175 	self->code = ARCHIVE_FILTER_ZSTD;
176 	self->name = "zstd";
177 
178 	state = (struct private_data *)calloc(1, sizeof(*state));
179 	out_block = (unsigned char *)malloc(out_block_size);
180 	dstream = ZSTD_createDStream();
181 
182 	if (state == NULL || out_block == NULL || dstream == NULL) {
183 		free(out_block);
184 		free(state);
185 		ZSTD_freeDStream(dstream); /* supports free on NULL */
186 		archive_set_error(&self->archive->archive, ENOMEM,
187 		    "Can't allocate data for zstd decompression");
188 		return (ARCHIVE_FATAL);
189 	}
190 
191 	self->data = state;
192 
193 	state->out_block_size = out_block_size;
194 	state->out_block = out_block;
195 	state->dstream = dstream;
196 	self->vtable = &zstd_reader_vtable;
197 
198 	state->eof = 0;
199 	state->in_frame = 0;
200 
201 	return (ARCHIVE_OK);
202 }
203 
204 static ssize_t
205 zstd_filter_read(struct archive_read_filter *self, const void **p)
206 {
207 	struct private_data *state;
208 	size_t decompressed;
209 	ssize_t avail_in;
210 	ZSTD_outBuffer out;
211 	ZSTD_inBuffer in;
212 	size_t ret;
213 
214 	state = (struct private_data *)self->data;
215 
216 	out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
217 
218 	/* Try to fill the output buffer. */
219 	while (out.pos < out.size && !state->eof) {
220 		if (!state->in_frame) {
221 			ret = ZSTD_initDStream(state->dstream);
222 			if (ZSTD_isError(ret)) {
223 				archive_set_error(&self->archive->archive,
224 				    ARCHIVE_ERRNO_MISC,
225 				    "Error initializing zstd decompressor: %s",
226 				    ZSTD_getErrorName(ret));
227 				return (ARCHIVE_FATAL);
228 			}
229 		}
230 		in.src = __archive_read_filter_ahead(self->upstream, 1,
231 		    &avail_in);
232 		if (avail_in < 0) {
233 			return avail_in;
234 		}
235 		if (in.src == NULL && avail_in == 0) {
236 			if (!state->in_frame) {
237 				/* end of stream */
238 				state->eof = 1;
239 				break;
240 			} else {
241 				archive_set_error(&self->archive->archive,
242 				    ARCHIVE_ERRNO_MISC,
243 				    "Truncated zstd input");
244 				return (ARCHIVE_FATAL);
245 			}
246 		}
247 		in.size = avail_in;
248 		in.pos = 0;
249 
250 		{
251 			ret = ZSTD_decompressStream(state->dstream, &out, &in);
252 
253 			if (ZSTD_isError(ret)) {
254 				archive_set_error(&self->archive->archive,
255 				    ARCHIVE_ERRNO_MISC,
256 				    "Zstd decompression failed: %s",
257 				    ZSTD_getErrorName(ret));
258 				return (ARCHIVE_FATAL);
259 			}
260 
261 			/* Decompressor made some progress */
262 			__archive_read_filter_consume(self->upstream, in.pos);
263 
264 			/* ret guaranteed to be > 0 if frame isn't done yet */
265 			state->in_frame = (ret != 0);
266 		}
267 	}
268 
269 	decompressed = out.pos;
270 	state->total_out += decompressed;
271 	if (decompressed == 0)
272 		*p = NULL;
273 	else
274 		*p = state->out_block;
275 	return (decompressed);
276 }
277 
278 /*
279  * Clean up the decompressor.
280  */
281 static int
282 zstd_filter_close(struct archive_read_filter *self)
283 {
284 	struct private_data *state;
285 
286 	state = (struct private_data *)self->data;
287 
288 	ZSTD_freeDStream(state->dstream);
289 	free(state->out_block);
290 	free(state);
291 
292 	return (ARCHIVE_OK);
293 }
294 
295 #endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */
296