1 /* SPDX-License-Identifier: LGPL-2.1+ */
21 #include <zstd_errors.h>
24 #include "alloc-util.h"
28 #include "journal-def.h"
30 #include "sparse-endian.h"
31 #include "string-table.h"
32 #include "string-util.h"
33 #include "unaligned.h"
37 DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t
, LZ4F_freeCompressionContext
);
38 DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t
, LZ4F_freeDecompressionContext
);
42 DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_CCtx
*, ZSTD_freeCCtx
);
43 DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_DCtx
*, ZSTD_freeDCtx
);
45 static int zstd_ret_to_errno(size_t ret
) {
46 switch (ZSTD_getErrorCode(ret
)) {
47 case ZSTD_error_dstSize_tooSmall
:
49 case ZSTD_error_memory_allocation
:
57 #define ALIGN_8(l) ALIGN_TO(l, sizeof(size_t))
59 static const char* const object_compressed_table
[_OBJECT_COMPRESSED_MAX
] = {
60 [OBJECT_COMPRESSED_XZ
] = "XZ",
61 [OBJECT_COMPRESSED_LZ4
] = "LZ4",
62 [OBJECT_COMPRESSED_ZSTD
] = "ZSTD",
63 /* If we add too many more entries here, it's going to grow quite large (and be mostly sparse), since
64 * the array key is actually a bitmask, not a plain enum */
67 DEFINE_STRING_TABLE_LOOKUP(object_compressed
, int);
69 int compress_blob_xz(const void *src
, uint64_t src_size
,
70 void *dst
, size_t dst_alloc_size
, size_t *dst_size
) {
72 static const lzma_options_lzma opt
= {
73 1u << 20u, NULL
, 0, LZMA_LC_DEFAULT
, LZMA_LP_DEFAULT
,
74 LZMA_PB_DEFAULT
, LZMA_MODE_FAST
, 128, LZMA_MF_HC3
, 4
76 static const lzma_filter filters
[] = {
77 { LZMA_FILTER_LZMA2
, (lzma_options_lzma
*) &opt
},
78 { LZMA_VLI_UNKNOWN
, NULL
}
86 assert(dst_alloc_size
> 0);
89 /* Returns < 0 if we couldn't compress the data or the
90 * compressed result is longer than the original */
95 ret
= lzma_stream_buffer_encode((lzma_filter
*) filters
, LZMA_CHECK_NONE
, NULL
,
96 src
, src_size
, dst
, &out_pos
, dst_alloc_size
);
103 return -EPROTONOSUPPORT
;
107 int compress_blob_lz4(const void *src
, uint64_t src_size
,
108 void *dst
, size_t dst_alloc_size
, size_t *dst_size
) {
113 assert(src_size
> 0);
115 assert(dst_alloc_size
> 0);
118 /* Returns < 0 if we couldn't compress the data or the
119 * compressed result is longer than the original */
124 r
= LZ4_compress_default(src
, (char*)dst
+ 8, src_size
, (int) dst_alloc_size
- 8);
128 unaligned_write_le64(dst
, src_size
);
133 return -EPROTONOSUPPORT
;
137 int compress_blob_zstd(
138 const void *src
, uint64_t src_size
,
139 void *dst
, size_t dst_alloc_size
, size_t *dst_size
) {
144 assert(src_size
> 0);
146 assert(dst_alloc_size
> 0);
149 k
= ZSTD_compress(dst
, dst_alloc_size
, src
, src_size
, 0);
151 return zstd_ret_to_errno(k
);
156 return -EPROTONOSUPPORT
;
160 int decompress_blob_xz(const void *src
, uint64_t src_size
,
161 void **dst
, size_t *dst_alloc_size
, size_t* dst_size
, size_t dst_max
) {
164 _cleanup_(lzma_end
) lzma_stream s
= LZMA_STREAM_INIT
;
169 assert(src_size
> 0);
171 assert(dst_alloc_size
);
173 assert(*dst_alloc_size
== 0 || *dst
);
175 ret
= lzma_stream_decoder(&s
, UINT64_MAX
, 0);
179 space
= MIN(src_size
* 2, dst_max
?: (size_t) -1);
180 if (!greedy_realloc(dst
, dst_alloc_size
, space
, 1))
184 s
.avail_in
= src_size
;
192 ret
= lzma_code(&s
, LZMA_FINISH
);
194 if (ret
== LZMA_STREAM_END
)
196 else if (ret
!= LZMA_OK
)
199 if (dst_max
> 0 && (space
- s
.avail_out
) >= dst_max
)
201 else if (dst_max
> 0 && space
== dst_max
)
204 used
= space
- s
.avail_out
;
205 space
= MIN(2 * space
, dst_max
?: (size_t) -1);
206 if (!greedy_realloc(dst
, dst_alloc_size
, space
, 1))
209 s
.avail_out
= space
- used
;
210 s
.next_out
= *(uint8_t**)dst
+ used
;
213 *dst_size
= space
- s
.avail_out
;
216 return -EPROTONOSUPPORT
;
220 int decompress_blob_lz4(const void *src
, uint64_t src_size
,
221 void **dst
, size_t *dst_alloc_size
, size_t* dst_size
, size_t dst_max
) {
225 int r
, size
; /* LZ4 uses int for size */
228 assert(src_size
> 0);
230 assert(dst_alloc_size
);
232 assert(*dst_alloc_size
== 0 || *dst
);
237 size
= unaligned_read_le64(src
);
238 if (size
< 0 || (unsigned) size
!= unaligned_read_le64(src
))
240 if ((size_t) size
> *dst_alloc_size
) {
241 out
= realloc(*dst
, size
);
245 *dst_alloc_size
= size
;
249 r
= LZ4_decompress_safe((char*)src
+ 8, out
, src_size
- 8, size
);
250 if (r
< 0 || r
!= size
)
256 return -EPROTONOSUPPORT
;
260 int decompress_blob_zstd(
261 const void *src
, uint64_t src_size
,
262 void **dst
, size_t *dst_alloc_size
, size_t* dst_size
, size_t dst_max
) {
268 assert(src_size
> 0);
270 assert(dst_alloc_size
);
272 assert(*dst_alloc_size
== 0 || *dst
);
274 if (src_size
> SIZE_MAX
/2) /* Overflow? */
276 space
= src_size
* 2;
277 if (dst_max
> 0 && space
> dst_max
)
280 if (!greedy_realloc(dst
, dst_alloc_size
, space
, 1))
286 k
= ZSTD_decompress(*dst
, *dst_alloc_size
, src
, src_size
);
287 if (!ZSTD_isError(k
)) {
291 if (ZSTD_getErrorCode(k
) != ZSTD_error_dstSize_tooSmall
)
292 return zstd_ret_to_errno(k
);
294 if (dst_max
> 0 && space
>= dst_max
) /* Already at max? */
296 if (space
> SIZE_MAX
/ 2) /* Overflow? */
300 if (dst_max
> 0 && space
> dst_max
)
303 if (!greedy_realloc(dst
, dst_alloc_size
, space
, 1))
307 return -EPROTONOSUPPORT
;
313 const void *src
, uint64_t src_size
,
314 void **dst
, size_t *dst_alloc_size
, size_t* dst_size
, size_t dst_max
) {
316 if (compression
== OBJECT_COMPRESSED_XZ
)
317 return decompress_blob_xz(
319 dst
, dst_alloc_size
, dst_size
, dst_max
);
320 else if (compression
== OBJECT_COMPRESSED_LZ4
)
321 return decompress_blob_lz4(
323 dst
, dst_alloc_size
, dst_size
, dst_max
);
324 else if (compression
== OBJECT_COMPRESSED_ZSTD
)
325 return decompress_blob_zstd(
327 dst
, dst_alloc_size
, dst_size
, dst_max
);
332 int decompress_startswith_xz(const void *src
, uint64_t src_size
,
333 void **buffer
, size_t *buffer_size
,
334 const void *prefix
, size_t prefix_len
,
338 _cleanup_(lzma_end
) lzma_stream s
= LZMA_STREAM_INIT
;
341 /* Checks whether the decompressed blob starts with the
342 * mentioned prefix. The byte extra needs to follow the
346 assert(src_size
> 0);
350 assert(*buffer_size
== 0 || *buffer
);
352 ret
= lzma_stream_decoder(&s
, UINT64_MAX
, 0);
356 if (!(greedy_realloc(buffer
, buffer_size
, ALIGN_8(prefix_len
+ 1), 1)))
360 s
.avail_in
= src_size
;
362 s
.next_out
= *buffer
;
363 s
.avail_out
= *buffer_size
;
366 ret
= lzma_code(&s
, LZMA_FINISH
);
368 if (!IN_SET(ret
, LZMA_OK
, LZMA_STREAM_END
))
371 if (*buffer_size
- s
.avail_out
>= prefix_len
+ 1)
372 return memcmp(*buffer
, prefix
, prefix_len
) == 0 &&
373 ((const uint8_t*) *buffer
)[prefix_len
] == extra
;
375 if (ret
== LZMA_STREAM_END
)
378 s
.avail_out
+= *buffer_size
;
380 if (!(greedy_realloc(buffer
, buffer_size
, *buffer_size
* 2, 1)))
383 s
.next_out
= *(uint8_t**)buffer
+ *buffer_size
- s
.avail_out
;
387 return -EPROTONOSUPPORT
;
391 int decompress_startswith_lz4(const void *src
, uint64_t src_size
,
392 void **buffer
, size_t *buffer_size
,
393 const void *prefix
, size_t prefix_len
,
396 /* Checks whether the decompressed blob starts with the
397 * mentioned prefix. The byte extra needs to follow the
403 assert(src_size
> 0);
407 assert(*buffer_size
== 0 || *buffer
);
412 if (!(greedy_realloc(buffer
, buffer_size
, ALIGN_8(prefix_len
+ 1), 1)))
415 r
= LZ4_decompress_safe_partial((char*)src
+ 8, *buffer
, src_size
- 8,
416 prefix_len
+ 1, *buffer_size
);
417 /* One lz4 < 1.8.3, we might get "failure" (r < 0), or "success" where
418 * just a part of the buffer is decompressed. But if we get a smaller
419 * amount of bytes than requested, we don't know whether there isn't enough
420 * data to fill the requested size or whether we just got a partial answer.
422 if (r
< 0 || (size_t) r
< prefix_len
+ 1) {
425 if (LZ4_versionNumber() >= 10803)
426 /* We trust that the newer lz4 decompresses the number of bytes we
427 * requested if available in the compressed string. */
431 /* Compare what we have first, in case of mismatch we can
432 * shortcut the full comparison. */
433 if (memcmp(*buffer
, prefix
, r
) != 0)
436 /* Before version 1.8.3, lz4 always tries to decode full a "sequence",
437 * so in pathological cases might need to decompress the full field. */
438 r
= decompress_blob_lz4(src
, src_size
, buffer
, buffer_size
, &size
, 0);
442 if (size
< prefix_len
+ 1)
446 return memcmp(*buffer
, prefix
, prefix_len
) == 0 &&
447 ((const uint8_t*) *buffer
)[prefix_len
] == extra
;
449 return -EPROTONOSUPPORT
;
453 int decompress_startswith_zstd(
454 const void *src
, uint64_t src_size
,
455 void **buffer
, size_t *buffer_size
,
456 const void *prefix
, size_t prefix_len
,
459 _cleanup_(ZSTD_freeDCtxp
) ZSTD_DCtx
*dctx
= NULL
;
463 assert(src_size
> 0);
467 assert(*buffer_size
== 0 || *buffer
);
469 dctx
= ZSTD_createDCtx();
473 if (!(greedy_realloc(buffer
, buffer_size
, MAX(ZSTD_DStreamOutSize(), prefix_len
+ 1), 1)))
476 ZSTD_inBuffer input
= {
480 ZSTD_outBuffer output
= {
482 .size
= *buffer_size
,
486 k
= ZSTD_decompressStream(dctx
, &output
, &input
);
487 if (ZSTD_isError(k
)) {
488 log_debug("ZSTD decoder failed: %s", ZSTD_getErrorName(k
));
489 return zstd_ret_to_errno(k
);
492 if (output
.pos
>= prefix_len
+ 1)
493 return memcmp(*buffer
, prefix
, prefix_len
) == 0 &&
494 ((const uint8_t*) *buffer
)[prefix_len
] == extra
;
496 if (input
.pos
>= input
.size
)
499 if (*buffer_size
> SIZE_MAX
/2)
502 if (!(greedy_realloc(buffer
, buffer_size
, *buffer_size
* 2, 1)))
505 output
.dst
= *buffer
;
506 output
.size
= *buffer_size
;
509 return -EPROTONOSUPPORT
;
513 int decompress_startswith(
515 const void *src
, uint64_t src_size
,
516 void **buffer
, size_t *buffer_size
,
517 const void *prefix
, size_t prefix_len
,
520 if (compression
== OBJECT_COMPRESSED_XZ
)
521 return decompress_startswith_xz(
527 else if (compression
== OBJECT_COMPRESSED_LZ4
)
528 return decompress_startswith_lz4(
533 else if (compression
== OBJECT_COMPRESSED_ZSTD
)
534 return decompress_startswith_zstd(
543 int compress_stream_xz(int fdf
, int fdt
, uint64_t max_bytes
) {
545 _cleanup_(lzma_end
) lzma_stream s
= LZMA_STREAM_INIT
;
547 uint8_t buf
[BUFSIZ
], out
[BUFSIZ
];
548 lzma_action action
= LZMA_RUN
;
553 ret
= lzma_easy_encoder(&s
, LZMA_PRESET_DEFAULT
, LZMA_CHECK_CRC64
);
554 if (ret
!= LZMA_OK
) {
555 log_error("Failed to initialize XZ encoder: code %u", ret
);
560 if (s
.avail_in
== 0 && action
== LZMA_RUN
) {
561 size_t m
= sizeof(buf
);
564 if (max_bytes
!= (uint64_t) -1 && (uint64_t) m
> max_bytes
)
565 m
= (size_t) max_bytes
;
567 n
= read(fdf
, buf
, m
);
571 action
= LZMA_FINISH
;
576 if (max_bytes
!= (uint64_t) -1) {
577 assert(max_bytes
>= (uint64_t) n
);
583 if (s
.avail_out
== 0) {
585 s
.avail_out
= sizeof(out
);
588 ret
= lzma_code(&s
, action
);
589 if (!IN_SET(ret
, LZMA_OK
, LZMA_STREAM_END
)) {
590 log_error("Compression failed: code %u", ret
);
594 if (s
.avail_out
== 0 || ret
== LZMA_STREAM_END
) {
597 n
= sizeof(out
) - s
.avail_out
;
599 k
= loop_write(fdt
, out
, n
, false);
603 if (ret
== LZMA_STREAM_END
) {
604 log_debug("XZ compression finished (%"PRIu64
" -> %"PRIu64
" bytes, %.1f%%)",
605 s
.total_in
, s
.total_out
,
606 (double) s
.total_out
/ s
.total_in
* 100);
613 return -EPROTONOSUPPORT
;
617 #define LZ4_BUFSIZE (512*1024u)
619 int compress_stream_lz4(int fdf
, int fdt
, uint64_t max_bytes
) {
623 _cleanup_(LZ4F_freeCompressionContextp
) LZ4F_compressionContext_t ctx
= NULL
;
624 _cleanup_free_
char *buf
= NULL
;
626 size_t size
, n
, total_in
= 0, total_out
, offset
= 0, frame_size
;
629 static const LZ4F_compressOptions_t options
= {
632 static const LZ4F_preferences_t preferences
= {
633 .frameInfo
.blockSizeID
= 5,
636 c
= LZ4F_createCompressionContext(&ctx
, LZ4F_VERSION
);
640 if (fstat(fdf
, &st
) < 0)
641 return log_debug_errno(errno
, "fstat() failed: %m");
643 frame_size
= LZ4F_compressBound(LZ4_BUFSIZE
, &preferences
);
644 size
= frame_size
+ 64*1024; /* add some space for header and trailer */
649 n
= offset
= total_out
= LZ4F_compressBegin(ctx
, buf
, size
, &preferences
);
653 src
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fdf
, 0);
654 if (src
== MAP_FAILED
)
657 log_debug("Buffer size is %zu bytes, header size %zu bytes.", size
, n
);
659 while (total_in
< (size_t) st
.st_size
) {
662 k
= MIN(LZ4_BUFSIZE
, st
.st_size
- total_in
);
663 n
= LZ4F_compressUpdate(ctx
, buf
+ offset
, size
- offset
,
664 src
+ total_in
, k
, &options
);
665 if (LZ4F_isError(n
)) {
666 r
= -ENOTRECOVERABLE
;
674 if (max_bytes
!= (uint64_t) -1 && total_out
> (size_t) max_bytes
) {
675 log_debug("Compressed stream longer than %"PRIu64
" bytes", max_bytes
);
679 if (size
- offset
< frame_size
+ 4) {
680 k
= loop_write(fdt
, buf
, offset
, false);
689 n
= LZ4F_compressEnd(ctx
, buf
+ offset
, size
- offset
, &options
);
690 if (LZ4F_isError(n
)) {
691 r
= -ENOTRECOVERABLE
;
697 r
= loop_write(fdt
, buf
, offset
, false);
701 log_debug("LZ4 compression finished (%zu -> %zu bytes, %.1f%%)",
703 (double) total_out
/ total_in
* 100);
705 munmap(src
, st
.st_size
);
708 return -EPROTONOSUPPORT
;
712 int decompress_stream_xz(int fdf
, int fdt
, uint64_t max_bytes
) {
715 _cleanup_(lzma_end
) lzma_stream s
= LZMA_STREAM_INIT
;
718 uint8_t buf
[BUFSIZ
], out
[BUFSIZ
];
719 lzma_action action
= LZMA_RUN
;
724 ret
= lzma_stream_decoder(&s
, UINT64_MAX
, 0);
725 if (ret
!= LZMA_OK
) {
726 log_debug("Failed to initialize XZ decoder: code %u", ret
);
731 if (s
.avail_in
== 0 && action
== LZMA_RUN
) {
734 n
= read(fdf
, buf
, sizeof(buf
));
738 action
= LZMA_FINISH
;
745 if (s
.avail_out
== 0) {
747 s
.avail_out
= sizeof(out
);
750 ret
= lzma_code(&s
, action
);
751 if (!IN_SET(ret
, LZMA_OK
, LZMA_STREAM_END
)) {
752 log_debug("Decompression failed: code %u", ret
);
756 if (s
.avail_out
== 0 || ret
== LZMA_STREAM_END
) {
759 n
= sizeof(out
) - s
.avail_out
;
761 if (max_bytes
!= (uint64_t) -1) {
762 if (max_bytes
< (uint64_t) n
)
768 k
= loop_write(fdt
, out
, n
, false);
772 if (ret
== LZMA_STREAM_END
) {
773 log_debug("XZ decompression finished (%"PRIu64
" -> %"PRIu64
" bytes, %.1f%%)",
774 s
.total_in
, s
.total_out
,
775 (double) s
.total_out
/ s
.total_in
* 100);
782 log_debug("Cannot decompress file. Compiled without XZ support.");
783 return -EPROTONOSUPPORT
;
787 int decompress_stream_lz4(int in
, int out
, uint64_t max_bytes
) {
790 _cleanup_(LZ4F_freeDecompressionContextp
) LZ4F_decompressionContext_t ctx
= NULL
;
791 _cleanup_free_
char *buf
= NULL
;
795 size_t total_in
= 0, total_out
= 0;
797 c
= LZ4F_createDecompressionContext(&ctx
, LZ4F_VERSION
);
801 if (fstat(in
, &st
) < 0)
802 return log_debug_errno(errno
, "fstat() failed: %m");
804 buf
= malloc(LZ4_BUFSIZE
);
808 src
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, in
, 0);
809 if (src
== MAP_FAILED
)
812 while (total_in
< (size_t) st
.st_size
) {
813 size_t produced
= LZ4_BUFSIZE
;
814 size_t used
= st
.st_size
- total_in
;
816 c
= LZ4F_decompress(ctx
, buf
, &produced
, src
+ total_in
, &used
, NULL
);
817 if (LZ4F_isError(c
)) {
823 total_out
+= produced
;
825 if (max_bytes
!= (uint64_t) -1 && total_out
> (size_t) max_bytes
) {
826 log_debug("Decompressed stream longer than %"PRIu64
" bytes", max_bytes
);
831 r
= loop_write(out
, buf
, produced
, false);
836 log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)",
838 total_in
> 0 ? (double) total_out
/ total_in
* 100 : 0.0);
840 munmap(src
, st
.st_size
);
843 log_debug("Cannot decompress file. Compiled without LZ4 support.");
844 return -EPROTONOSUPPORT
;
848 int compress_stream_zstd(int fdf
, int fdt
, uint64_t max_bytes
) {
850 _cleanup_(ZSTD_freeCCtxp
) ZSTD_CCtx
*cctx
= NULL
;
851 _cleanup_free_
void *in_buff
= NULL
, *out_buff
= NULL
;
852 size_t in_allocsize
, out_allocsize
;
854 uint64_t left
= max_bytes
, in_bytes
= 0;
859 /* Create the context and buffers */
860 in_allocsize
= ZSTD_CStreamInSize();
861 out_allocsize
= ZSTD_CStreamOutSize();
862 in_buff
= malloc(in_allocsize
);
863 out_buff
= malloc(out_allocsize
);
864 cctx
= ZSTD_createCCtx();
865 if (!cctx
|| !out_buff
|| !in_buff
)
868 z
= ZSTD_CCtx_setParameter(cctx
, ZSTD_c_checksumFlag
, 1);
870 log_debug("Failed to enable ZSTD checksum, ignoring: %s", ZSTD_getErrorName(z
));
872 /* This loop read from the input file, compresses that entire chunk,
873 * and writes all output produced to the output file.
877 ZSTD_inBuffer input
= {
884 red
= loop_read(fdf
, in_buff
, in_allocsize
, true);
887 is_last_chunk
= red
== 0;
889 in_bytes
+= (size_t) red
;
890 input
.size
= (size_t) red
;
892 for (bool finished
= false; !finished
;) {
893 ZSTD_outBuffer output
= {
895 .size
= out_allocsize
,
901 /* Compress into the output buffer and write all of the
902 * output to the file so we can reuse the buffer next
905 remaining
= ZSTD_compressStream2(
906 cctx
, &output
, &input
,
907 is_last_chunk
? ZSTD_e_end
: ZSTD_e_continue
);
909 if (ZSTD_isError(remaining
)) {
910 log_debug("ZSTD encoder failed: %s", ZSTD_getErrorName(remaining
));
911 return zstd_ret_to_errno(remaining
);
914 if (left
< output
.pos
)
917 wrote
= loop_write(fdt
, output
.dst
, output
.pos
, 1);
923 /* If we're on the last chunk we're finished when zstd
924 * returns 0, which means its consumed all the input AND
925 * finished the frame. Otherwise, we're finished when
926 * we've consumed all the input.
928 finished
= is_last_chunk
? (remaining
== 0) : (input
.pos
== input
.size
);
931 /* zstd only returns 0 when the input is completely consumed */
932 assert(input
.pos
== input
.size
);
938 "ZSTD compression finished (%" PRIu64
" -> %" PRIu64
" bytes, %.1f%%)",
941 (double) (max_bytes
- left
) / in_bytes
* 100);
945 return -EPROTONOSUPPORT
;
949 int decompress_stream_zstd(int fdf
, int fdt
, uint64_t max_bytes
) {
951 _cleanup_(ZSTD_freeDCtxp
) ZSTD_DCtx
*dctx
= NULL
;
952 _cleanup_free_
void *in_buff
= NULL
, *out_buff
= NULL
;
953 size_t in_allocsize
, out_allocsize
;
954 size_t last_result
= 0;
955 uint64_t left
= max_bytes
, in_bytes
= 0;
960 /* Create the context and buffers */
961 in_allocsize
= ZSTD_DStreamInSize();
962 out_allocsize
= ZSTD_DStreamOutSize();
963 in_buff
= malloc(in_allocsize
);
964 out_buff
= malloc(out_allocsize
);
965 dctx
= ZSTD_createDCtx();
966 if (!dctx
|| !out_buff
|| !in_buff
)
969 /* This loop assumes that the input file is one or more concatenated
970 * zstd streams. This example won't work if there is trailing non-zstd
971 * data at the end, but streaming decompression in general handles this
972 * case. ZSTD_decompressStream() returns 0 exactly when the frame is
973 * completed, and doesn't consume input after the frame.
976 bool has_error
= false;
977 ZSTD_inBuffer input
= {
984 red
= loop_read(fdf
, in_buff
, in_allocsize
, true);
990 in_bytes
+= (size_t) red
;
991 input
.size
= (size_t) red
;
994 /* Given a valid frame, zstd won't consume the last byte of the
995 * frame until it has flushed all of the decompressed data of
996 * the frame. So input.pos < input.size means frame is not done
997 * or there is still output available.
999 while (input
.pos
< input
.size
) {
1000 ZSTD_outBuffer output
= {
1002 .size
= out_allocsize
,
1006 /* The return code is zero if the frame is complete, but
1007 * there may be multiple frames concatenated together.
1008 * Zstd will automatically reset the context when a
1009 * frame is complete. Still, calling ZSTD_DCtx_reset()
1010 * can be useful to reset the context to a clean state,
1011 * for instance if the last decompression call returned
1014 last_result
= ZSTD_decompressStream(dctx
, &output
, &input
);
1015 if (ZSTD_isError(last_result
)) {
1020 if (left
< output
.pos
)
1023 wrote
= loop_write(fdt
, output
.dst
, output
.pos
, 1);
1034 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
), "ZSTD decoder failed: no data read");
1036 if (last_result
!= 0) {
1037 /* The last return value from ZSTD_decompressStream did not end
1038 * on a frame, but we reached the end of the file! We assume
1039 * this is an error, and the input was truncated.
1041 log_debug("ZSTD decoder failed: %s", ZSTD_getErrorName(last_result
));
1042 return zstd_ret_to_errno(last_result
);
1046 "ZSTD decompression finished (%" PRIu64
" -> %" PRIu64
" bytes, %.1f%%)",
1049 (double) (max_bytes
- left
) / in_bytes
* 100);
1052 log_debug("Cannot decompress file. Compiled without ZSTD support.");
1053 return -EPROTONOSUPPORT
;
1057 int decompress_stream(const char *filename
, int fdf
, int fdt
, uint64_t max_bytes
) {
1059 if (endswith(filename
, ".lz4"))
1060 return decompress_stream_lz4(fdf
, fdt
, max_bytes
);
1061 else if (endswith(filename
, ".xz"))
1062 return decompress_stream_xz(fdf
, fdt
, max_bytes
);
1063 else if (endswith(filename
, ".zst"))
1064 return decompress_stream_zstd(fdf
, fdt
, max_bytes
);
1066 return -EPROTONOSUPPORT
;