1 /* SPDX-License-Identifier: LGPL-2.1+ */
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
) {
17 } else if (c
->type
== IMPORT_COMPRESS_BZIP2
) {
19 BZ2_bzCompressEnd(&c
->bzip2
);
21 BZ2_bzDecompressEnd(&c
->bzip2
);
24 c
->type
= IMPORT_COMPRESS_UNKNOWN
;
27 int import_uncompress_detect(ImportCompress
*c
, const void *data
, size_t size
) {
28 static const uint8_t xz_signature
[] = {
29 0xfd, '7', 'z', 'X', 'Z', 0x00
31 static const uint8_t gzip_signature
[] = {
34 static const uint8_t bzip2_signature
[] = {
42 if (c
->type
!= IMPORT_COMPRESS_UNKNOWN
)
45 if (size
< MAX3(sizeof(xz_signature
),
46 sizeof(gzip_signature
),
47 sizeof(bzip2_signature
)))
52 if (memcmp(data
, xz_signature
, sizeof(xz_signature
)) == 0) {
55 xzr
= lzma_stream_decoder(&c
->xz
, UINT64_MAX
, LZMA_TELL_UNSUPPORTED_CHECK
| LZMA_CONCATENATED
);
59 c
->type
= IMPORT_COMPRESS_XZ
;
61 } else if (memcmp(data
, gzip_signature
, sizeof(gzip_signature
)) == 0) {
62 r
= inflateInit2(&c
->gzip
, 15+16);
66 c
->type
= IMPORT_COMPRESS_GZIP
;
68 } else if (memcmp(data
, bzip2_signature
, sizeof(bzip2_signature
)) == 0) {
69 r
= BZ2_bzDecompressInit(&c
->bzip2
, 0, 0);
73 c
->type
= IMPORT_COMPRESS_BZIP2
;
75 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
82 int import_uncompress(ImportCompress
*c
, const void *data
, size_t size
, ImportCompressCallback callback
, void *userdata
) {
88 r
= import_uncompress_detect(c
, data
, size
);
102 case IMPORT_COMPRESS_UNCOMPRESSED
:
103 r
= callback(data
, size
, userdata
);
109 case IMPORT_COMPRESS_XZ
:
110 c
->xz
.next_in
= data
;
111 c
->xz
.avail_in
= size
;
113 while (c
->xz
.avail_in
> 0) {
114 uint8_t buffer
[16 * 1024];
117 c
->xz
.next_out
= buffer
;
118 c
->xz
.avail_out
= sizeof(buffer
);
120 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
121 if (!IN_SET(lzr
, LZMA_OK
, LZMA_STREAM_END
))
124 r
= callback(buffer
, sizeof(buffer
) - c
->xz
.avail_out
, userdata
);
131 case IMPORT_COMPRESS_GZIP
:
132 c
->gzip
.next_in
= (void*) data
;
133 c
->gzip
.avail_in
= size
;
135 while (c
->gzip
.avail_in
> 0) {
136 uint8_t buffer
[16 * 1024];
138 c
->gzip
.next_out
= buffer
;
139 c
->gzip
.avail_out
= sizeof(buffer
);
141 r
= inflate(&c
->gzip
, Z_NO_FLUSH
);
142 if (!IN_SET(r
, Z_OK
, Z_STREAM_END
))
145 r
= callback(buffer
, sizeof(buffer
) - c
->gzip
.avail_out
, userdata
);
152 case IMPORT_COMPRESS_BZIP2
:
153 c
->bzip2
.next_in
= (void*) data
;
154 c
->bzip2
.avail_in
= size
;
156 while (c
->bzip2
.avail_in
> 0) {
157 uint8_t buffer
[16 * 1024];
159 c
->bzip2
.next_out
= (char*) buffer
;
160 c
->bzip2
.avail_out
= sizeof(buffer
);
162 r
= BZ2_bzDecompress(&c
->bzip2
);
163 if (!IN_SET(r
, BZ_OK
, BZ_STREAM_END
))
166 r
= callback(buffer
, sizeof(buffer
) - c
->bzip2
.avail_out
, userdata
);
174 assert_not_reached("Unknown compression");
180 int import_compress_init(ImportCompress
*c
, ImportCompressType t
) {
187 case IMPORT_COMPRESS_XZ
: {
190 xzr
= lzma_easy_encoder(&c
->xz
, LZMA_PRESET_DEFAULT
, LZMA_CHECK_CRC64
);
194 c
->type
= IMPORT_COMPRESS_XZ
;
198 case IMPORT_COMPRESS_GZIP
:
199 r
= deflateInit2(&c
->gzip
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, 15 + 16, 8, Z_DEFAULT_STRATEGY
);
203 c
->type
= IMPORT_COMPRESS_GZIP
;
206 case IMPORT_COMPRESS_BZIP2
:
207 r
= BZ2_bzCompressInit(&c
->bzip2
, 9, 0, 0);
211 c
->type
= IMPORT_COMPRESS_BZIP2
;
214 case IMPORT_COMPRESS_UNCOMPRESSED
:
215 c
->type
= IMPORT_COMPRESS_UNCOMPRESSED
;
226 static int enlarge_buffer(void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
230 if (*buffer_allocated
> *buffer_size
)
233 l
= MAX(16*1024U, (*buffer_size
* 2));
234 p
= realloc(*buffer
, l
);
239 *buffer_allocated
= l
;
244 int import_compress(ImportCompress
*c
, const void *data
, size_t size
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
250 assert(buffer_allocated
);
264 case IMPORT_COMPRESS_XZ
:
266 c
->xz
.next_in
= data
;
267 c
->xz
.avail_in
= size
;
269 while (c
->xz
.avail_in
> 0) {
272 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
276 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
277 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
279 lzr
= lzma_code(&c
->xz
, LZMA_RUN
);
283 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
288 case IMPORT_COMPRESS_GZIP
:
290 c
->gzip
.next_in
= (void*) data
;
291 c
->gzip
.avail_in
= size
;
293 while (c
->gzip
.avail_in
> 0) {
294 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
298 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
299 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
301 r
= deflate(&c
->gzip
, Z_NO_FLUSH
);
305 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
310 case IMPORT_COMPRESS_BZIP2
:
312 c
->bzip2
.next_in
= (void*) data
;
313 c
->bzip2
.avail_in
= size
;
315 while (c
->bzip2
.avail_in
> 0) {
316 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
320 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
321 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
323 r
= BZ2_bzCompress(&c
->bzip2
, BZ_RUN
);
327 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
332 case IMPORT_COMPRESS_UNCOMPRESSED
:
334 if (*buffer_allocated
< size
) {
337 p
= realloc(*buffer
, size
);
342 *buffer_allocated
= size
;
345 memcpy(*buffer
, data
, size
);
356 int import_compress_finish(ImportCompress
*c
, void **buffer
, size_t *buffer_size
, size_t *buffer_allocated
) {
362 assert(buffer_allocated
);
371 case IMPORT_COMPRESS_XZ
: {
377 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
381 c
->xz
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
382 c
->xz
.avail_out
= *buffer_allocated
- *buffer_size
;
384 lzr
= lzma_code(&c
->xz
, LZMA_FINISH
);
385 if (!IN_SET(lzr
, LZMA_OK
, LZMA_STREAM_END
))
388 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->xz
.avail_out
;
389 } while (lzr
!= LZMA_STREAM_END
);
394 case IMPORT_COMPRESS_GZIP
:
395 c
->gzip
.avail_in
= 0;
398 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
402 c
->gzip
.next_out
= (uint8_t*) *buffer
+ *buffer_size
;
403 c
->gzip
.avail_out
= *buffer_allocated
- *buffer_size
;
405 r
= deflate(&c
->gzip
, Z_FINISH
);
406 if (!IN_SET(r
, Z_OK
, Z_STREAM_END
))
409 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->gzip
.avail_out
;
410 } while (r
!= Z_STREAM_END
);
414 case IMPORT_COMPRESS_BZIP2
:
415 c
->bzip2
.avail_in
= 0;
418 r
= enlarge_buffer(buffer
, buffer_size
, buffer_allocated
);
422 c
->bzip2
.next_out
= (void*) ((uint8_t*) *buffer
+ *buffer_size
);
423 c
->bzip2
.avail_out
= *buffer_allocated
- *buffer_size
;
425 r
= BZ2_bzCompress(&c
->bzip2
, BZ_FINISH
);
426 if (!IN_SET(r
, BZ_FINISH_OK
, BZ_STREAM_END
))
429 *buffer_size
+= (*buffer_allocated
- *buffer_size
) - c
->bzip2
.avail_out
;
430 } while (r
!= BZ_STREAM_END
);
434 case IMPORT_COMPRESS_UNCOMPRESSED
:
444 static const char* const import_compress_type_table
[_IMPORT_COMPRESS_TYPE_MAX
] = {
445 [IMPORT_COMPRESS_UNKNOWN
] = "unknown",
446 [IMPORT_COMPRESS_UNCOMPRESSED
] = "uncompressed",
447 [IMPORT_COMPRESS_XZ
] = "xz",
448 [IMPORT_COMPRESS_GZIP
] = "gzip",
449 [IMPORT_COMPRESS_BZIP2
] = "bzip2",
452 DEFINE_STRING_TABLE_LOOKUP(import_compress_type
, ImportCompressType
);