1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2015 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "import-compress.h"
25 void import_compress_free(ImportCompress *c) {
28 if (c->type == IMPORT_COMPRESS_XZ)
30 else if (c->type == IMPORT_COMPRESS_GZIP) {
35 } else if (c->type == IMPORT_COMPRESS_BZIP2) {
37 BZ2_bzCompressEnd(&c->bzip2);
39 BZ2_bzDecompressEnd(&c->bzip2);
42 c->type = IMPORT_COMPRESS_UNKNOWN;
45 int import_uncompress_detect(ImportCompress *c, const void *data, size_t size) {
46 static const uint8_t xz_signature[] = {
47 0xfd, '7', 'z', 'X', 'Z', 0x00
49 static const uint8_t gzip_signature[] = {
52 static const uint8_t bzip2_signature[] = {
60 if (c->type != IMPORT_COMPRESS_UNKNOWN)
63 if (size < MAX3(sizeof(xz_signature),
64 sizeof(gzip_signature),
65 sizeof(bzip2_signature)))
70 if (memcmp(data, xz_signature, sizeof(xz_signature)) == 0) {
73 xzr = lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK);
77 c->type = IMPORT_COMPRESS_XZ;
79 } else if (memcmp(data, gzip_signature, sizeof(gzip_signature)) == 0) {
80 r = inflateInit2(&c->gzip, 15+16);
84 c->type = IMPORT_COMPRESS_GZIP;
86 } else if (memcmp(data, bzip2_signature, sizeof(bzip2_signature)) == 0) {
87 r = BZ2_bzDecompressInit(&c->bzip2, 0, 0);
91 c->type = IMPORT_COMPRESS_BZIP2;
93 c->type = IMPORT_COMPRESS_UNCOMPRESSED;
100 int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) {
106 r = import_uncompress_detect(c, data, size);
120 case IMPORT_COMPRESS_UNCOMPRESSED:
121 r = callback(data, size, userdata);
127 case IMPORT_COMPRESS_XZ:
128 c->xz.next_in = data;
129 c->xz.avail_in = size;
131 while (c->xz.avail_in > 0) {
132 uint8_t buffer[16 * 1024];
135 c->xz.next_out = buffer;
136 c->xz.avail_out = sizeof(buffer);
138 lzr = lzma_code(&c->xz, LZMA_RUN);
139 if (lzr != LZMA_OK && lzr != LZMA_STREAM_END)
142 r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata);
149 case IMPORT_COMPRESS_GZIP:
150 c->gzip.next_in = (void*) data;
151 c->gzip.avail_in = size;
153 while (c->gzip.avail_in > 0) {
154 uint8_t buffer[16 * 1024];
156 c->gzip.next_out = buffer;
157 c->gzip.avail_out = sizeof(buffer);
159 r = inflate(&c->gzip, Z_NO_FLUSH);
160 if (r != Z_OK && r != Z_STREAM_END)
163 r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata);
170 case IMPORT_COMPRESS_BZIP2:
171 c->bzip2.next_in = (void*) data;
172 c->bzip2.avail_in = size;
174 while (c->bzip2.avail_in > 0) {
175 uint8_t buffer[16 * 1024];
177 c->bzip2.next_out = (char*) buffer;
178 c->bzip2.avail_out = sizeof(buffer);
180 r = BZ2_bzDecompress(&c->bzip2);
181 if (r != BZ_OK && r != BZ_STREAM_END)
184 r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata);
192 assert_not_reached("Unknown compression");
198 int import_compress_init(ImportCompress *c, ImportCompressType t) {
205 case IMPORT_COMPRESS_XZ: {
208 xzr = lzma_easy_encoder(&c->xz, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64);
212 c->type = IMPORT_COMPRESS_XZ;
216 case IMPORT_COMPRESS_GZIP:
217 r = deflateInit2(&c->gzip, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
221 c->type = IMPORT_COMPRESS_GZIP;
224 case IMPORT_COMPRESS_BZIP2:
225 r = BZ2_bzCompressInit(&c->bzip2, 9, 0, 0);
229 c->type = IMPORT_COMPRESS_BZIP2;
232 case IMPORT_COMPRESS_UNCOMPRESSED:
233 c->type = IMPORT_COMPRESS_UNCOMPRESSED;
244 static int enlarge_buffer(void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
248 if (*buffer_allocated > *buffer_size)
251 l = MAX(16*1024U, (*buffer_size * 2));
252 p = realloc(*buffer, l);
257 *buffer_allocated = l;
262 int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
268 assert(buffer_allocated);
282 case IMPORT_COMPRESS_XZ:
284 c->xz.next_in = data;
285 c->xz.avail_in = size;
287 while (c->xz.avail_in > 0) {
290 r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
294 c->xz.next_out = (uint8_t*) *buffer + *buffer_size;
295 c->xz.avail_out = *buffer_allocated - *buffer_size;
297 lzr = lzma_code(&c->xz, LZMA_RUN);
301 *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out;
306 case IMPORT_COMPRESS_GZIP:
308 c->gzip.next_in = (void*) data;
309 c->gzip.avail_in = size;
311 while (c->gzip.avail_in > 0) {
312 r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
316 c->gzip.next_out = (uint8_t*) *buffer + *buffer_size;
317 c->gzip.avail_out = *buffer_allocated - *buffer_size;
319 r = deflate(&c->gzip, Z_NO_FLUSH);
323 *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out;
328 case IMPORT_COMPRESS_BZIP2:
330 c->bzip2.next_in = (void*) data;
331 c->bzip2.avail_in = size;
333 while (c->bzip2.avail_in > 0) {
334 r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
338 c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size);
339 c->bzip2.avail_out = *buffer_allocated - *buffer_size;
341 r = BZ2_bzCompress(&c->bzip2, BZ_RUN);
345 *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out;
350 case IMPORT_COMPRESS_UNCOMPRESSED:
352 if (*buffer_allocated < size) {
355 p = realloc(*buffer, size);
360 *buffer_allocated = size;
363 memcpy(*buffer, data, size);
374 int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
380 assert(buffer_allocated);
389 case IMPORT_COMPRESS_XZ: {
395 r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
399 c->xz.next_out = (uint8_t*) *buffer + *buffer_size;
400 c->xz.avail_out = *buffer_allocated - *buffer_size;
402 lzr = lzma_code(&c->xz, LZMA_FINISH);
403 if (lzr != LZMA_OK && lzr != LZMA_STREAM_END)
406 *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out;
407 } while (lzr != LZMA_STREAM_END);
412 case IMPORT_COMPRESS_GZIP:
413 c->gzip.avail_in = 0;
416 r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
420 c->gzip.next_out = (uint8_t*) *buffer + *buffer_size;
421 c->gzip.avail_out = *buffer_allocated - *buffer_size;
423 r = deflate(&c->gzip, Z_FINISH);
424 if (r != Z_OK && r != Z_STREAM_END)
427 *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out;
428 } while (r != Z_STREAM_END);
432 case IMPORT_COMPRESS_BZIP2:
433 c->bzip2.avail_in = 0;
436 r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
440 c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size);
441 c->bzip2.avail_out = *buffer_allocated - *buffer_size;
443 r = BZ2_bzCompress(&c->bzip2, BZ_FINISH);
444 if (r != BZ_FINISH_OK && r != BZ_STREAM_END)
447 *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out;
448 } while (r != BZ_STREAM_END);
452 case IMPORT_COMPRESS_UNCOMPRESSED:
462 static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = {
463 [IMPORT_COMPRESS_UNKNOWN] = "unknown",
464 [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed",
465 [IMPORT_COMPRESS_XZ] = "xz",
466 [IMPORT_COMPRESS_GZIP] = "gzip",
467 [IMPORT_COMPRESS_BZIP2] = "bzip2",
470 DEFINE_STRING_TABLE_LOOKUP(import_compress_type, ImportCompressType);