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)
32 else if (c->type == IMPORT_COMPRESS_BZIP2)
33 BZ2_bzDecompressEnd(&c->bzip2);
35 c->type = IMPORT_COMPRESS_UNKNOWN;
38 int import_uncompress_detect(ImportCompress *c, const void *data, size_t size) {
39 static const uint8_t xz_signature[] = {
40 0xfd, '7', 'z', 'X', 'Z', 0x00
42 static const uint8_t gzip_signature[] = {
45 static const uint8_t bzip2_signature[] = {
53 if (c->type != IMPORT_COMPRESS_UNKNOWN)
56 if (size < MAX3(sizeof(xz_signature),
57 sizeof(gzip_signature),
58 sizeof(bzip2_signature)))
63 if (memcmp(data, xz_signature, sizeof(xz_signature)) == 0) {
66 xzr = lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK);
70 c->type = IMPORT_COMPRESS_XZ;
72 } else if (memcmp(data, gzip_signature, sizeof(gzip_signature)) == 0) {
73 r = inflateInit2(&c->gzip, 15+16);
77 c->type = IMPORT_COMPRESS_GZIP;
79 } else if (memcmp(data, bzip2_signature, sizeof(bzip2_signature)) == 0) {
80 r = BZ2_bzDecompressInit(&c->bzip2, 0, 0);
84 c->type = IMPORT_COMPRESS_BZIP2;
86 c->type = IMPORT_COMPRESS_UNCOMPRESSED;
91 int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) {
97 r = import_uncompress_detect(c, data, size);
108 case IMPORT_COMPRESS_UNCOMPRESSED:
109 r = callback(data, size, userdata);
115 case IMPORT_COMPRESS_XZ:
116 c->xz.next_in = data;
117 c->xz.avail_in = size;
119 while (c->xz.avail_in > 0) {
120 uint8_t buffer[16 * 1024];
123 c->xz.next_out = buffer;
124 c->xz.avail_out = sizeof(buffer);
126 lzr = lzma_code(&c->xz, LZMA_RUN);
127 if (lzr != LZMA_OK && lzr != LZMA_STREAM_END)
130 r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata);
137 case IMPORT_COMPRESS_GZIP:
138 c->gzip.next_in = (void*) data;
139 c->gzip.avail_in = size;
141 while (c->gzip.avail_in > 0) {
142 uint8_t buffer[16 * 1024];
144 c->gzip.next_out = buffer;
145 c->gzip.avail_out = sizeof(buffer);
147 r = inflate(&c->gzip, Z_NO_FLUSH);
148 if (r != Z_OK && r != Z_STREAM_END)
151 r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata);
158 case IMPORT_COMPRESS_BZIP2:
159 c->bzip2.next_in = (void*) data;
160 c->bzip2.avail_in = size;
162 while (c->bzip2.avail_in > 0) {
163 uint8_t buffer[16 * 1024];
165 c->bzip2.next_out = (char*) buffer;
166 c->bzip2.avail_out = sizeof(buffer);
168 r = BZ2_bzDecompress(&c->bzip2);
169 if (r != BZ_OK && r != BZ_STREAM_END)
172 r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata);
180 assert_not_reached("Unknown compression");
186 static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = {
187 [IMPORT_COMPRESS_UNKNOWN] = "unknown",
188 [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed",
189 [IMPORT_COMPRESS_XZ] = "xz",
190 [IMPORT_COMPRESS_GZIP] = "gzip",
191 [IMPORT_COMPRESS_BZIP2] = "bzip2",
194 DEFINE_STRING_TABLE_LOOKUP(import_compress_type, ImportCompressType);