^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "util/compress.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) int zstd_init(struct zstd_data *data, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) size_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) data->dstream = ZSTD_createDStream();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) if (data->dstream == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) pr_err("Couldn't create decompression stream.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) ret = ZSTD_initDStream(data->dstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) if (ZSTD_isError(ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (!level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) data->cstream = ZSTD_createCStream();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (data->cstream == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) pr_err("Couldn't create compression stream.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ret = ZSTD_initCStream(data->cstream, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (ZSTD_isError(ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pr_err("Failed to initialize compression stream: %s\n", ZSTD_getErrorName(ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int zstd_fini(struct zstd_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (data->dstream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ZSTD_freeDStream(data->dstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) data->dstream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (data->cstream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ZSTD_freeCStream(data->cstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) data->cstream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) void *src, size_t src_size, size_t max_record_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) size_t process_header(void *record, size_t increment))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) size_t ret, size, compressed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ZSTD_inBuffer input = { src, src_size, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ZSTD_outBuffer output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) void *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) while (input.pos < input.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) record = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) size = process_header(record, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) compressed += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dst += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) dst_size -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) output = (ZSTD_outBuffer){ dst, (dst_size > max_record_size) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) max_record_size : dst_size, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ret = ZSTD_compressStream(data->cstream, &output, &input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ZSTD_flushStream(data->cstream, &output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ZSTD_isError(ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pr_err("failed to compress %ld bytes: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) (long)src_size, ZSTD_getErrorName(ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) memcpy(dst, src, src_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return src_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) size = output.pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) size = process_header(record, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) compressed += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) dst += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dst_size -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return compressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) void *dst, size_t dst_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) size_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ZSTD_inBuffer input = { src, src_size, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ZSTD_outBuffer output = { dst, dst_size, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) while (input.pos < input.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ret = ZSTD_decompressStream(data->dstream, &output, &input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (ZSTD_isError(ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pr_err("failed to decompress (B): %zd -> %zd, dst_size %zd : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) src_size, output.size, dst_size, ZSTD_getErrorName(ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) output.dst = dst + output.pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) output.size = dst_size - output.pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return output.pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }