2 * Copyright (c) 2009-2011 Sean Purcell
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 #include "archive_platform.h"
28 __FBSDID("$FreeBSD$");
52 #include "archive_endian.h"
53 #include "archive_private.h"
54 #include "archive_read_private.h"
56 #if HAVE_ZSTD_H && HAVE_LIBZSTD
59 ZSTD_DStream *dstream;
60 unsigned char *out_block;
61 size_t out_block_size;
63 char in_frame; /* True = in the middle of a zstd frame. */
64 char eof; /* True = found end of compressed data. */
68 static ssize_t zstd_filter_read(struct archive_read_filter *, const void**);
69 static int zstd_filter_close(struct archive_read_filter *);
73 * Note that we can detect zstd compressed files even if we can't decompress
74 * them. (In fact, we like detecting them because we can give better error
75 * messages.) So the bid framework here gets compiled even if no zstd library
78 static int zstd_bidder_bid(struct archive_read_filter_bidder *,
79 struct archive_read_filter *);
80 static int zstd_bidder_init(struct archive_read_filter *);
82 static const struct archive_read_filter_bidder_vtable
83 zstd_bidder_vtable = {
84 .bid = zstd_bidder_bid,
85 .init = zstd_bidder_init,
89 archive_read_support_filter_zstd(struct archive *_a)
91 struct archive_read *a = (struct archive_read *)_a;
93 if (__archive_read_register_bidder(a, NULL, "zstd",
94 &zstd_bidder_vtable) != ARCHIVE_OK)
95 return (ARCHIVE_FATAL);
97 #if HAVE_ZSTD_H && HAVE_LIBZSTD
100 archive_set_error(_a, ARCHIVE_ERRNO_MISC,
101 "Using external zstd program for zstd decompression");
102 return (ARCHIVE_WARN);
107 * Test whether we can handle this data.
110 zstd_bidder_bid(struct archive_read_filter_bidder *self,
111 struct archive_read_filter *filter)
113 const unsigned char *buffer;
117 /* Zstd frame magic values */
118 const unsigned zstd_magic = 0xFD2FB528U;
119 const unsigned zstd_magic_skippable_start = 0x184D2A50U;
120 const unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
122 (void) self; /* UNUSED */
124 buffer = __archive_read_filter_ahead(filter, 4, &avail);
128 prefix = archive_le32dec(buffer);
129 if (prefix == zstd_magic)
131 if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start)
137 #if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
140 * If we don't have the library on this system, we can't do the
141 * decompression directly. We can, however, try to run "zstd -d"
142 * in case that's available.
145 zstd_bidder_init(struct archive_read_filter *self)
149 r = __archive_read_program(self, "zstd -d -qq");
150 /* Note: We set the format here even if __archive_read_program()
151 * above fails. We do, after all, know what the format is
152 * even if we weren't able to read it. */
153 self->code = ARCHIVE_FILTER_ZSTD;
160 static const struct archive_read_filter_vtable
161 zstd_reader_vtable = {
162 .read = zstd_filter_read,
163 .close = zstd_filter_close,
167 * Initialize the filter object
170 zstd_bidder_init(struct archive_read_filter *self)
172 struct private_data *state;
173 const size_t out_block_size = ZSTD_DStreamOutSize();
175 ZSTD_DStream *dstream;
177 self->code = ARCHIVE_FILTER_ZSTD;
180 state = (struct private_data *)calloc(sizeof(*state), 1);
181 out_block = (unsigned char *)malloc(out_block_size);
182 dstream = ZSTD_createDStream();
184 if (state == NULL || out_block == NULL || dstream == NULL) {
187 ZSTD_freeDStream(dstream); /* supports free on NULL */
188 archive_set_error(&self->archive->archive, ENOMEM,
189 "Can't allocate data for zstd decompression");
190 return (ARCHIVE_FATAL);
195 state->out_block_size = out_block_size;
196 state->out_block = out_block;
197 state->dstream = dstream;
198 self->vtable = &zstd_reader_vtable;
207 zstd_filter_read(struct archive_read_filter *self, const void **p)
209 struct private_data *state;
215 state = (struct private_data *)self->data;
217 out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
219 /* Try to fill the output buffer. */
220 while (out.pos < out.size && !state->eof) {
221 if (!state->in_frame) {
222 const size_t ret = ZSTD_initDStream(state->dstream);
223 if (ZSTD_isError(ret)) {
224 archive_set_error(&self->archive->archive,
226 "Error initializing zstd decompressor: %s",
227 ZSTD_getErrorName(ret));
228 return (ARCHIVE_FATAL);
231 in.src = __archive_read_filter_ahead(self->upstream, 1,
236 if (in.src == NULL && avail_in == 0) {
237 if (!state->in_frame) {
242 archive_set_error(&self->archive->archive,
244 "Truncated zstd input");
245 return (ARCHIVE_FATAL);
253 ZSTD_decompressStream(state->dstream, &out, &in);
255 if (ZSTD_isError(ret)) {
256 archive_set_error(&self->archive->archive,
258 "Zstd decompression failed: %s",
259 ZSTD_getErrorName(ret));
260 return (ARCHIVE_FATAL);
263 /* Decompressor made some progress */
264 __archive_read_filter_consume(self->upstream, in.pos);
266 /* ret guaranteed to be > 0 if frame isn't done yet */
267 state->in_frame = (ret != 0);
271 decompressed = out.pos;
272 state->total_out += decompressed;
273 if (decompressed == 0)
276 *p = state->out_block;
277 return (decompressed);
281 * Clean up the decompressor.
284 zstd_filter_close(struct archive_read_filter *self)
286 struct private_data *state;
288 state = (struct private_data *)self->data;
290 ZSTD_freeDStream(state->dstream);
291 free(state->out_block);
297 #endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */