2 This file is part of systemd.
4 Copyright 2015 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "import-compress.h"
21 #include "string-table.h"
24 void import_compress_free(ImportCompress
*c
) {
27 if (c
->type
== IMPORT_COMPRESS_XZ
)
29 else if (c
->type
== IMPORT_COMPRESS_GZIP
) {
34 } else if (c
->type
== IMPORT_COMPRESS_BZIP2
) {
36 BZ2_bzCompressEnd(&c
->bzip2
);
38 BZ2_bzDecompressEnd(&c
->bzip2
);
41 c
->type
= IMPORT_COMPRESS_UNKNOWN
;
44 int import_uncompress_detect(ImportCompress
*c
, const void *data
, size_t size
) {
45 static const uint8_t xz_signature
[] = {
46 0xfd, '7', 'z', 'X', 'Z', 0x00
48 static const uint8_t gzip_signature
[] = {
51 static const uint8_t bzip2_signature
[] = {
59 if (c
->type
!= IMPORT_COMPRESS_UNKNOWN
)
62 if (size
< MAX3(sizeof(xz_signature
),
63 sizeof(gzip_signature
),
64 sizeof(bzip2_signature
)))
69 if (memcmp(data
, xz_signature
, sizeof(xz_signature
)) == 0) {
72 xzr
= lzma_stream_decoder(&c
->xz
, UINT64_MAX
, LZMA_TELL_UNSUPPORTED_CHECK
);
76 c
->type
= IMPORT_COMPRESS_XZ
;
78 } else if (memcmp(data
, gzip_signature
, sizeof(gzip_signature
)) == 0) {
79 r
= inflateInit2(&c
->gzip
, 15+16);
83 c
->type
= IMPORT_COMPRESS_GZIP
;
85 } else if (memcmp(data
, bzip2_signature
, sizeof(bzip2_signature
)) == 0) {
86 r
= BZ2_bzDecompressInit(&c
->bzip2
, 0, 0);
90 c
->type
= IMPORT_COMPRESS_BZIP2
;
92 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
99 int import_uncompress(ImportCompress
*c
, const void *data
, size_t size
, ImportCompressCallback callback
, void *userdata
) {
105 r
= import_uncompress_detect(c
, data
, size
);
119 case IMPORT_COMPRESS_UNCOMPRESSED
:
120 r
= callback(data
, size
, userdata
);
126 case IMPORT_COMPRESS_XZ
:
127 c
->xz
.next_in
= data
;
128 c
->xz
.avail_in
= size
;
130 while (c
->xz
.avail_in
> 0) {
131 uint8_t buffer
[16 * 1024];
134 c
->xz
.next_out
= buffer
;
135 c
->xz
.avail_out
= sizeof(buffer
);
137 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
138 if (lzr
!= LZMA_OK
&& lzr
!= LZMA_STREAM_END
)
141 r
= callback(buffer
, sizeof(buffer
) - c
->xz
.avail_out
, userdata
);
148 case IMPORT_COMPRESS_GZIP
:
149 c
->gzip
.next_in
= (void*) data
;
150 c
->gzip
.avail_in
= size
;
152 while (c
->gzip
.avail_in
> 0) {
153 uint8_t buffer
[16 * 1024];
155 c
->gzip
.next_out
= buffer
;
156 c
->gzip
.avail_out
= sizeof(buffer
);
158 r
= inflate(&c
->gzip
, Z_NO_FLUSH
);
159 if (r
!= Z_OK
&& r
!= Z_STREAM_END
)
162 r
= callback(buffer
, sizeof(buffer
) - c
->gzip
.avail_out
, userdata
);
169 case IMPORT_COMPRESS_BZIP2
:
170 c
->bzip2
.next_in
= (void*) data
;
171 c
->bzip2
.avail_in
= size
;
173 while (c
->bzip2
.avail_in
> 0) {
174 uint8_t buffer
[16 * 1024];
176 c
->bzip2
.next_out
= (char*) buffer
;
177 c
->bzip2
.avail_out
= sizeof(buffer
);
179 r
= BZ2_bzDecompress(&c
->bzip2
);
180 if (r
!= BZ_OK
&& r
!= BZ_STREAM_END
)
183 r
= callback(buffer
, sizeof(buffer
) - c
->bzip2
.avail_out
, userdata
);
191 assert_not_reached("Unknown compression");
197 int import_compress_init(ImportCompress
*c
, ImportCompressType t
) {
204 case IMPORT_COMPRESS_XZ
: {
207 xzr
= lzma_easy_encoder(&c
->xz
, LZMA_PRESET_DEFAULT
, LZMA_CHECK_CRC64
);
211 c
->type
= IMPORT_COMPRESS_XZ
;
215 case IMPORT_COMPRESS_GZIP
:
216 r
= deflateInit2(&c
->gzip
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, 15 + 16, 8, Z_DEFAULT_STRATEGY
);
220 c
->type
= IMPORT_COMPRESS_GZIP
;
223 case IMPORT_COMPRESS_BZIP2
:
224 r
= BZ2_bzCompressInit(&c
->bzip2
, 9, 0, 0);
228 c
->type
= IMPORT_COMPRESS_BZIP2
;
231 case IMPORT_COMPRESS_UNCOMPRESSED
:
232 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
243 static int enlarge_buffer(void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
247 if (*buffer_allocated
> *buffer_size
)
250 l
= MAX(16*1024U, (*buffer_size
* 2));
251 p
= realloc(*buffer
, l
);
256 *buffer_allocated
= l
;
261 int import_compress(ImportCompress
*c
, const void *data
, size_t size
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
267 assert(buffer_allocated
);
281 case IMPORT_COMPRESS_XZ
:
283 c
->xz
.next_in
= data
;
284 c
->xz
.avail_in
= size
;
286 while (c
->xz
.avail_in
> 0) {
289 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
293 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
294 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
296 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
300 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
305 case IMPORT_COMPRESS_GZIP
:
307 c
->gzip
.next_in
= (void*) data
;
308 c
->gzip
.avail_in
= size
;
310 while (c
->gzip
.avail_in
> 0) {
311 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
315 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
316 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
318 r
= deflate(&c
->gzip
, Z_NO_FLUSH
);
322 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
327 case IMPORT_COMPRESS_BZIP2
:
329 c
->bzip2
.next_in
= (void*) data
;
330 c
->bzip2
.avail_in
= size
;
332 while (c
->bzip2
.avail_in
> 0) {
333 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
337 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
338 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
340 r
= BZ2_bzCompress(&c
->bzip2
, BZ_RUN
);
344 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
349 case IMPORT_COMPRESS_UNCOMPRESSED
:
351 if (*buffer_allocated
< size
) {
354 p
= realloc(*buffer
, size
);
359 *buffer_allocated
= size
;
362 memcpy(*buffer
, data
, size
);
373 int import_compress_finish(ImportCompress
*c
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
379 assert(buffer_allocated
);
388 case IMPORT_COMPRESS_XZ
: {
394 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
398 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
399 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
401 lzr
= lzma_code(&c
->xz
, LZMA_FINISH
);
402 if (lzr
!= LZMA_OK
&& lzr
!= LZMA_STREAM_END
)
405 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
406 } while (lzr
!= LZMA_STREAM_END
);
411 case IMPORT_COMPRESS_GZIP
:
412 c
->gzip
.avail_in
= 0;
415 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
419 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
420 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
422 r
= deflate(&c
->gzip
, Z_FINISH
);
423 if (r
!= Z_OK
&& r
!= Z_STREAM_END
)
426 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
427 } while (r
!= Z_STREAM_END
);
431 case IMPORT_COMPRESS_BZIP2
:
432 c
->bzip2
.avail_in
= 0;
435 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
439 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
440 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
442 r
= BZ2_bzCompress(&c
->bzip2
, BZ_FINISH
);
443 if (r
!= BZ_FINISH_OK
&& r
!= BZ_STREAM_END
)
446 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
447 } while (r
!= BZ_STREAM_END
);
451 case IMPORT_COMPRESS_UNCOMPRESSED
:
461 static const char* const import_compress_type_table
[_IMPORT_COMPRESS_TYPE_MAX
] = {
462 [IMPORT_COMPRESS_UNKNOWN
] = "unknown",
463 [IMPORT_COMPRESS_UNCOMPRESSED
] = "uncompressed",
464 [IMPORT_COMPRESS_XZ
] = "xz",
465 [IMPORT_COMPRESS_GZIP
] = "gzip",
466 [IMPORT_COMPRESS_BZIP2
] = "bzip2",
469 DEFINE_STRING_TABLE_LOOKUP(import_compress_type
, ImportCompressType
);