1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "import-compress.h"
4 #include "string-table.h"
7 void import_compress_free(ImportCompress
*c
) {
10 if (c
->type
== IMPORT_COMPRESS_XZ
)
12 else if (c
->type
== IMPORT_COMPRESS_GZIP
) {
18 } else if (c
->type
== IMPORT_COMPRESS_BZIP2
) {
20 BZ2_bzCompressEnd(&c
->bzip2
);
22 BZ2_bzDecompressEnd(&c
->bzip2
);
26 c
->type
= IMPORT_COMPRESS_UNKNOWN
;
29 int import_uncompress_detect(ImportCompress
*c
, const void *data
, size_t size
) {
30 static const uint8_t xz_signature
[] = {
31 0xfd, '7', 'z', 'X', 'Z', 0x00
33 static const uint8_t gzip_signature
[] = {
36 static const uint8_t bzip2_signature
[] = {
44 if (c
->type
!= IMPORT_COMPRESS_UNKNOWN
)
47 if (size
< MAX3(sizeof(xz_signature
),
48 sizeof(gzip_signature
),
49 sizeof(bzip2_signature
)))
54 if (memcmp(data
, xz_signature
, sizeof(xz_signature
)) == 0) {
57 xzr
= lzma_stream_decoder(&c
->xz
, UINT64_MAX
, LZMA_TELL_UNSUPPORTED_CHECK
| LZMA_CONCATENATED
);
61 c
->type
= IMPORT_COMPRESS_XZ
;
63 } else if (memcmp(data
, gzip_signature
, sizeof(gzip_signature
)) == 0) {
64 r
= inflateInit2(&c
->gzip
, 15+16);
68 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
;
79 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
86 int import_uncompress(ImportCompress
*c
, const void *data
, size_t size
, ImportCompressCallback callback
, void *userdata
) {
92 r
= import_uncompress_detect(c
, data
, size
);
106 case IMPORT_COMPRESS_UNCOMPRESSED
:
107 r
= callback(data
, size
, userdata
);
113 case IMPORT_COMPRESS_XZ
:
114 c
->xz
.next_in
= data
;
115 c
->xz
.avail_in
= size
;
117 while (c
->xz
.avail_in
> 0) {
118 uint8_t buffer
[16 * 1024];
121 c
->xz
.next_out
= buffer
;
122 c
->xz
.avail_out
= sizeof(buffer
);
124 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
125 if (!IN_SET(lzr
, LZMA_OK
, LZMA_STREAM_END
))
128 if (c
->xz
.avail_out
< sizeof(buffer
)) {
129 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 (!IN_SET(r
, Z_OK
, Z_STREAM_END
))
151 if (c
->gzip
.avail_out
< sizeof(buffer
)) {
152 r
= callback(buffer
, sizeof(buffer
) - c
->gzip
.avail_out
, userdata
);
161 case IMPORT_COMPRESS_BZIP2
:
162 c
->bzip2
.next_in
= (void*) data
;
163 c
->bzip2
.avail_in
= size
;
165 while (c
->bzip2
.avail_in
> 0) {
166 uint8_t buffer
[16 * 1024];
168 c
->bzip2
.next_out
= (char*) buffer
;
169 c
->bzip2
.avail_out
= sizeof(buffer
);
171 r
= BZ2_bzDecompress(&c
->bzip2
);
172 if (!IN_SET(r
, BZ_OK
, BZ_STREAM_END
))
175 if (c
->bzip2
.avail_out
< sizeof(buffer
)) {
176 r
= callback(buffer
, sizeof(buffer
) - c
->bzip2
.avail_out
, userdata
);
186 assert_not_reached("Unknown compression");
192 int import_compress_init(ImportCompress
*c
, ImportCompressType t
) {
199 case IMPORT_COMPRESS_XZ
: {
202 xzr
= lzma_easy_encoder(&c
->xz
, LZMA_PRESET_DEFAULT
, LZMA_CHECK_CRC64
);
206 c
->type
= IMPORT_COMPRESS_XZ
;
210 case IMPORT_COMPRESS_GZIP
:
211 r
= deflateInit2(&c
->gzip
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, 15 + 16, 8, Z_DEFAULT_STRATEGY
);
215 c
->type
= IMPORT_COMPRESS_GZIP
;
219 case IMPORT_COMPRESS_BZIP2
:
220 r
= BZ2_bzCompressInit(&c
->bzip2
, 9, 0, 0);
224 c
->type
= IMPORT_COMPRESS_BZIP2
;
228 case IMPORT_COMPRESS_UNCOMPRESSED
:
229 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
240 static int enlarge_buffer(void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
244 if (*buffer_allocated
> *buffer_size
)
247 l
= MAX(16*1024U, (*buffer_size
* 2));
248 p
= realloc(*buffer
, l
);
253 *buffer_allocated
= l
;
258 int import_compress(ImportCompress
*c
, const void *data
, size_t size
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
264 assert(buffer_allocated
);
278 case IMPORT_COMPRESS_XZ
:
280 c
->xz
.next_in
= data
;
281 c
->xz
.avail_in
= size
;
283 while (c
->xz
.avail_in
> 0) {
286 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
290 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
291 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
293 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
297 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
302 case IMPORT_COMPRESS_GZIP
:
304 c
->gzip
.next_in
= (void*) data
;
305 c
->gzip
.avail_in
= size
;
307 while (c
->gzip
.avail_in
> 0) {
308 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
312 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
313 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
315 r
= deflate(&c
->gzip
, Z_NO_FLUSH
);
319 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
325 case IMPORT_COMPRESS_BZIP2
:
327 c
->bzip2
.next_in
= (void*) data
;
328 c
->bzip2
.avail_in
= size
;
330 while (c
->bzip2
.avail_in
> 0) {
331 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
335 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
336 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
338 r
= BZ2_bzCompress(&c
->bzip2
, BZ_RUN
);
342 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
348 case IMPORT_COMPRESS_UNCOMPRESSED
:
350 if (*buffer_allocated
< size
) {
353 p
= realloc(*buffer
, size
);
358 *buffer_allocated
= size
;
361 memcpy(*buffer
, data
, size
);
372 int import_compress_finish(ImportCompress
*c
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
378 assert(buffer_allocated
);
387 case IMPORT_COMPRESS_XZ
: {
393 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
397 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
398 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
400 lzr
= lzma_code(&c
->xz
, LZMA_FINISH
);
401 if (!IN_SET(lzr
, LZMA_OK
, LZMA_STREAM_END
))
404 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
405 } while (lzr
!= LZMA_STREAM_END
);
410 case IMPORT_COMPRESS_GZIP
:
411 c
->gzip
.avail_in
= 0;
414 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
418 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
419 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
421 r
= deflate(&c
->gzip
, Z_FINISH
);
422 if (!IN_SET(r
, Z_OK
, Z_STREAM_END
))
425 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
426 } 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 (!IN_SET(r
, BZ_FINISH_OK
, BZ_STREAM_END
))
446 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
447 } 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",
468 [IMPORT_COMPRESS_BZIP2
] = "bzip2",
472 DEFINE_STRING_TABLE_LOOKUP(import_compress_type
, ImportCompressType
);