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/>.
22 #include "import-compress.h"
23 #include "string-table.h"
26 void import_compress_free(ImportCompress
*c
) {
29 if (c
->type
== IMPORT_COMPRESS_XZ
)
31 else if (c
->type
== IMPORT_COMPRESS_GZIP
) {
36 } else if (c
->type
== IMPORT_COMPRESS_BZIP2
) {
38 BZ2_bzCompressEnd(&c
->bzip2
);
40 BZ2_bzDecompressEnd(&c
->bzip2
);
43 c
->type
= IMPORT_COMPRESS_UNKNOWN
;
46 int import_uncompress_detect(ImportCompress
*c
, const void *data
, size_t size
) {
47 static const uint8_t xz_signature
[] = {
48 0xfd, '7', 'z', 'X', 'Z', 0x00
50 static const uint8_t gzip_signature
[] = {
53 static const uint8_t bzip2_signature
[] = {
61 if (c
->type
!= IMPORT_COMPRESS_UNKNOWN
)
64 if (size
< MAX3(sizeof(xz_signature
),
65 sizeof(gzip_signature
),
66 sizeof(bzip2_signature
)))
71 if (memcmp(data
, xz_signature
, sizeof(xz_signature
)) == 0) {
74 xzr
= lzma_stream_decoder(&c
->xz
, UINT64_MAX
, LZMA_TELL_UNSUPPORTED_CHECK
);
78 c
->type
= IMPORT_COMPRESS_XZ
;
80 } else if (memcmp(data
, gzip_signature
, sizeof(gzip_signature
)) == 0) {
81 r
= inflateInit2(&c
->gzip
, 15+16);
85 c
->type
= IMPORT_COMPRESS_GZIP
;
87 } else if (memcmp(data
, bzip2_signature
, sizeof(bzip2_signature
)) == 0) {
88 r
= BZ2_bzDecompressInit(&c
->bzip2
, 0, 0);
92 c
->type
= IMPORT_COMPRESS_BZIP2
;
94 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
101 int import_uncompress(ImportCompress
*c
, const void *data
, size_t size
, ImportCompressCallback callback
, void *userdata
) {
107 r
= import_uncompress_detect(c
, data
, size
);
121 case IMPORT_COMPRESS_UNCOMPRESSED
:
122 r
= callback(data
, size
, userdata
);
128 case IMPORT_COMPRESS_XZ
:
129 c
->xz
.next_in
= data
;
130 c
->xz
.avail_in
= size
;
132 while (c
->xz
.avail_in
> 0) {
133 uint8_t buffer
[16 * 1024];
136 c
->xz
.next_out
= buffer
;
137 c
->xz
.avail_out
= sizeof(buffer
);
139 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
140 if (lzr
!= LZMA_OK
&& lzr
!= LZMA_STREAM_END
)
143 r
= callback(buffer
, sizeof(buffer
) - c
->xz
.avail_out
, userdata
);
150 case IMPORT_COMPRESS_GZIP
:
151 c
->gzip
.next_in
= (void*) data
;
152 c
->gzip
.avail_in
= size
;
154 while (c
->gzip
.avail_in
> 0) {
155 uint8_t buffer
[16 * 1024];
157 c
->gzip
.next_out
= buffer
;
158 c
->gzip
.avail_out
= sizeof(buffer
);
160 r
= inflate(&c
->gzip
, Z_NO_FLUSH
);
161 if (r
!= Z_OK
&& r
!= Z_STREAM_END
)
164 r
= callback(buffer
, sizeof(buffer
) - c
->gzip
.avail_out
, userdata
);
171 case IMPORT_COMPRESS_BZIP2
:
172 c
->bzip2
.next_in
= (void*) data
;
173 c
->bzip2
.avail_in
= size
;
175 while (c
->bzip2
.avail_in
> 0) {
176 uint8_t buffer
[16 * 1024];
178 c
->bzip2
.next_out
= (char*) buffer
;
179 c
->bzip2
.avail_out
= sizeof(buffer
);
181 r
= BZ2_bzDecompress(&c
->bzip2
);
182 if (r
!= BZ_OK
&& r
!= BZ_STREAM_END
)
185 r
= callback(buffer
, sizeof(buffer
) - c
->bzip2
.avail_out
, userdata
);
193 assert_not_reached("Unknown compression");
199 int import_compress_init(ImportCompress
*c
, ImportCompressType t
) {
206 case IMPORT_COMPRESS_XZ
: {
209 xzr
= lzma_easy_encoder(&c
->xz
, LZMA_PRESET_DEFAULT
, LZMA_CHECK_CRC64
);
213 c
->type
= IMPORT_COMPRESS_XZ
;
217 case IMPORT_COMPRESS_GZIP
:
218 r
= deflateInit2(&c
->gzip
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, 15 + 16, 8, Z_DEFAULT_STRATEGY
);
222 c
->type
= IMPORT_COMPRESS_GZIP
;
225 case IMPORT_COMPRESS_BZIP2
:
226 r
= BZ2_bzCompressInit(&c
->bzip2
, 9, 0, 0);
230 c
->type
= IMPORT_COMPRESS_BZIP2
;
233 case IMPORT_COMPRESS_UNCOMPRESSED
:
234 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
245 static int enlarge_buffer(void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
249 if (*buffer_allocated
> *buffer_size
)
252 l
= MAX(16*1024U, (*buffer_size
* 2));
253 p
= realloc(*buffer
, l
);
258 *buffer_allocated
= l
;
263 int import_compress(ImportCompress
*c
, const void *data
, size_t size
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
269 assert(buffer_allocated
);
283 case IMPORT_COMPRESS_XZ
:
285 c
->xz
.next_in
= data
;
286 c
->xz
.avail_in
= size
;
288 while (c
->xz
.avail_in
> 0) {
291 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
295 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
296 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
298 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
302 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
307 case IMPORT_COMPRESS_GZIP
:
309 c
->gzip
.next_in
= (void*) data
;
310 c
->gzip
.avail_in
= size
;
312 while (c
->gzip
.avail_in
> 0) {
313 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
317 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
318 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
320 r
= deflate(&c
->gzip
, Z_NO_FLUSH
);
324 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
329 case IMPORT_COMPRESS_BZIP2
:
331 c
->bzip2
.next_in
= (void*) data
;
332 c
->bzip2
.avail_in
= size
;
334 while (c
->bzip2
.avail_in
> 0) {
335 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
339 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
340 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
342 r
= BZ2_bzCompress(&c
->bzip2
, BZ_RUN
);
346 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
351 case IMPORT_COMPRESS_UNCOMPRESSED
:
353 if (*buffer_allocated
< size
) {
356 p
= realloc(*buffer
, size
);
361 *buffer_allocated
= size
;
364 memcpy(*buffer
, data
, size
);
375 int import_compress_finish(ImportCompress
*c
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
381 assert(buffer_allocated
);
390 case IMPORT_COMPRESS_XZ
: {
396 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
400 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
401 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
403 lzr
= lzma_code(&c
->xz
, LZMA_FINISH
);
404 if (lzr
!= LZMA_OK
&& lzr
!= LZMA_STREAM_END
)
407 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
408 } while (lzr
!= LZMA_STREAM_END
);
413 case IMPORT_COMPRESS_GZIP
:
414 c
->gzip
.avail_in
= 0;
417 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
421 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
422 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
424 r
= deflate(&c
->gzip
, Z_FINISH
);
425 if (r
!= Z_OK
&& r
!= Z_STREAM_END
)
428 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
429 } while (r
!= Z_STREAM_END
);
433 case IMPORT_COMPRESS_BZIP2
:
434 c
->bzip2
.avail_in
= 0;
437 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
441 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
442 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
444 r
= BZ2_bzCompress(&c
->bzip2
, BZ_FINISH
);
445 if (r
!= BZ_FINISH_OK
&& r
!= BZ_STREAM_END
)
448 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
449 } while (r
!= BZ_STREAM_END
);
453 case IMPORT_COMPRESS_UNCOMPRESSED
:
463 static const char* const import_compress_type_table
[_IMPORT_COMPRESS_TYPE_MAX
] = {
464 [IMPORT_COMPRESS_UNKNOWN
] = "unknown",
465 [IMPORT_COMPRESS_UNCOMPRESSED
] = "uncompressed",
466 [IMPORT_COMPRESS_XZ
] = "xz",
467 [IMPORT_COMPRESS_GZIP
] = "gzip",
468 [IMPORT_COMPRESS_BZIP2
] = "bzip2",
471 DEFINE_STRING_TABLE_LOOKUP(import_compress_type
, ImportCompressType
);