1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2015 Lennart Poettering
6 #include "import-compress.h"
7 #include "string-table.h"
10 void import_compress_free(ImportCompress
*c
) {
13 if (c
->type
== IMPORT_COMPRESS_XZ
)
15 else if (c
->type
== IMPORT_COMPRESS_GZIP
) {
20 } else if (c
->type
== IMPORT_COMPRESS_BZIP2
) {
22 BZ2_bzCompressEnd(&c
->bzip2
);
24 BZ2_bzDecompressEnd(&c
->bzip2
);
27 c
->type
= IMPORT_COMPRESS_UNKNOWN
;
30 int import_uncompress_detect(ImportCompress
*c
, const void *data
, size_t size
) {
31 static const uint8_t xz_signature
[] = {
32 0xfd, '7', 'z', 'X', 'Z', 0x00
34 static const uint8_t gzip_signature
[] = {
37 static const uint8_t bzip2_signature
[] = {
45 if (c
->type
!= IMPORT_COMPRESS_UNKNOWN
)
48 if (size
< MAX3(sizeof(xz_signature
),
49 sizeof(gzip_signature
),
50 sizeof(bzip2_signature
)))
55 if (memcmp(data
, xz_signature
, sizeof(xz_signature
)) == 0) {
58 xzr
= lzma_stream_decoder(&c
->xz
, UINT64_MAX
, LZMA_TELL_UNSUPPORTED_CHECK
| LZMA_CONCATENATED
);
62 c
->type
= IMPORT_COMPRESS_XZ
;
64 } else if (memcmp(data
, gzip_signature
, sizeof(gzip_signature
)) == 0) {
65 r
= inflateInit2(&c
->gzip
, 15+16);
69 c
->type
= IMPORT_COMPRESS_GZIP
;
71 } else if (memcmp(data
, bzip2_signature
, sizeof(bzip2_signature
)) == 0) {
72 r
= BZ2_bzDecompressInit(&c
->bzip2
, 0, 0);
76 c
->type
= IMPORT_COMPRESS_BZIP2
;
78 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
85 int import_uncompress(ImportCompress
*c
, const void *data
, size_t size
, ImportCompressCallback callback
, void *userdata
) {
91 r
= import_uncompress_detect(c
, data
, size
);
105 case IMPORT_COMPRESS_UNCOMPRESSED
:
106 r
= callback(data
, size
, userdata
);
112 case IMPORT_COMPRESS_XZ
:
113 c
->xz
.next_in
= data
;
114 c
->xz
.avail_in
= size
;
116 while (c
->xz
.avail_in
> 0) {
117 uint8_t buffer
[16 * 1024];
120 c
->xz
.next_out
= buffer
;
121 c
->xz
.avail_out
= sizeof(buffer
);
123 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
124 if (!IN_SET(lzr
, LZMA_OK
, LZMA_STREAM_END
))
127 r
= callback(buffer
, sizeof(buffer
) - c
->xz
.avail_out
, userdata
);
134 case IMPORT_COMPRESS_GZIP
:
135 c
->gzip
.next_in
= (void*) data
;
136 c
->gzip
.avail_in
= size
;
138 while (c
->gzip
.avail_in
> 0) {
139 uint8_t buffer
[16 * 1024];
141 c
->gzip
.next_out
= buffer
;
142 c
->gzip
.avail_out
= sizeof(buffer
);
144 r
= inflate(&c
->gzip
, Z_NO_FLUSH
);
145 if (!IN_SET(r
, Z_OK
, Z_STREAM_END
))
148 r
= callback(buffer
, sizeof(buffer
) - c
->gzip
.avail_out
, userdata
);
155 case IMPORT_COMPRESS_BZIP2
:
156 c
->bzip2
.next_in
= (void*) data
;
157 c
->bzip2
.avail_in
= size
;
159 while (c
->bzip2
.avail_in
> 0) {
160 uint8_t buffer
[16 * 1024];
162 c
->bzip2
.next_out
= (char*) buffer
;
163 c
->bzip2
.avail_out
= sizeof(buffer
);
165 r
= BZ2_bzDecompress(&c
->bzip2
);
166 if (!IN_SET(r
, BZ_OK
, BZ_STREAM_END
))
169 r
= callback(buffer
, sizeof(buffer
) - c
->bzip2
.avail_out
, userdata
);
177 assert_not_reached("Unknown compression");
183 int import_compress_init(ImportCompress
*c
, ImportCompressType t
) {
190 case IMPORT_COMPRESS_XZ
: {
193 xzr
= lzma_easy_encoder(&c
->xz
, LZMA_PRESET_DEFAULT
, LZMA_CHECK_CRC64
);
197 c
->type
= IMPORT_COMPRESS_XZ
;
201 case IMPORT_COMPRESS_GZIP
:
202 r
= deflateInit2(&c
->gzip
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, 15 + 16, 8, Z_DEFAULT_STRATEGY
);
206 c
->type
= IMPORT_COMPRESS_GZIP
;
209 case IMPORT_COMPRESS_BZIP2
:
210 r
= BZ2_bzCompressInit(&c
->bzip2
, 9, 0, 0);
214 c
->type
= IMPORT_COMPRESS_BZIP2
;
217 case IMPORT_COMPRESS_UNCOMPRESSED
:
218 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
229 static int enlarge_buffer(void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
233 if (*buffer_allocated
> *buffer_size
)
236 l
= MAX(16*1024U, (*buffer_size
* 2));
237 p
= realloc(*buffer
, l
);
242 *buffer_allocated
= l
;
247 int import_compress(ImportCompress
*c
, const void *data
, size_t size
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
253 assert(buffer_allocated
);
267 case IMPORT_COMPRESS_XZ
:
269 c
->xz
.next_in
= data
;
270 c
->xz
.avail_in
= size
;
272 while (c
->xz
.avail_in
> 0) {
275 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
279 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
280 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
282 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
286 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
291 case IMPORT_COMPRESS_GZIP
:
293 c
->gzip
.next_in
= (void*) data
;
294 c
->gzip
.avail_in
= size
;
296 while (c
->gzip
.avail_in
> 0) {
297 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
301 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
302 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
304 r
= deflate(&c
->gzip
, Z_NO_FLUSH
);
308 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
313 case IMPORT_COMPRESS_BZIP2
:
315 c
->bzip2
.next_in
= (void*) data
;
316 c
->bzip2
.avail_in
= size
;
318 while (c
->bzip2
.avail_in
> 0) {
319 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
323 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
324 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
326 r
= BZ2_bzCompress(&c
->bzip2
, BZ_RUN
);
330 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
335 case IMPORT_COMPRESS_UNCOMPRESSED
:
337 if (*buffer_allocated
< size
) {
340 p
= realloc(*buffer
, size
);
345 *buffer_allocated
= size
;
348 memcpy(*buffer
, data
, size
);
359 int import_compress_finish(ImportCompress
*c
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
365 assert(buffer_allocated
);
374 case IMPORT_COMPRESS_XZ
: {
380 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
384 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
385 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
387 lzr
= lzma_code(&c
->xz
, LZMA_FINISH
);
388 if (!IN_SET(lzr
, LZMA_OK
, LZMA_STREAM_END
))
391 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
392 } while (lzr
!= LZMA_STREAM_END
);
397 case IMPORT_COMPRESS_GZIP
:
398 c
->gzip
.avail_in
= 0;
401 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
405 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
406 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
408 r
= deflate(&c
->gzip
, Z_FINISH
);
409 if (!IN_SET(r
, Z_OK
, Z_STREAM_END
))
412 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
413 } while (r
!= Z_STREAM_END
);
417 case IMPORT_COMPRESS_BZIP2
:
418 c
->bzip2
.avail_in
= 0;
421 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
425 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
426 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
428 r
= BZ2_bzCompress(&c
->bzip2
, BZ_FINISH
);
429 if (!IN_SET(r
, BZ_FINISH_OK
, BZ_STREAM_END
))
432 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
433 } while (r
!= BZ_STREAM_END
);
437 case IMPORT_COMPRESS_UNCOMPRESSED
:
447 static const char* const import_compress_type_table
[_IMPORT_COMPRESS_TYPE_MAX
] = {
448 [IMPORT_COMPRESS_UNKNOWN
] = "unknown",
449 [IMPORT_COMPRESS_UNCOMPRESSED
] = "uncompressed",
450 [IMPORT_COMPRESS_XZ
] = "xz",
451 [IMPORT_COMPRESS_GZIP
] = "gzip",
452 [IMPORT_COMPRESS_BZIP2
] = "bzip2",
455 DEFINE_STRING_TABLE_LOOKUP(import_compress_type
, ImportCompressType
);