1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
/*
* Copyright (C) 2021 Gao Xiang <xiang@kernel.org>
*/
#include <stdlib.h>
#include "config.h"
#ifdef HAVE_LIBLZMA
#include <lzma.h>
#include "erofs/config.h"
#include "erofs/print.h"
#include "erofs/internal.h"
#include "compressor.h"
struct erofs_liblzma_context {
lzma_options_lzma opt;
lzma_stream strm;
};
static int erofs_liblzma_compress_destsize(const struct erofs_compress *c,
const void *src, unsigned int *srcsize,
void *dst, unsigned int dstsize)
{
struct erofs_liblzma_context *ctx = c->private_data;
lzma_stream *strm = &ctx->strm;
lzma_ret ret = lzma_microlzma_encoder(strm, &ctx->opt);
if (ret != LZMA_OK)
return -EFAULT;
strm->next_in = src;
strm->avail_in = *srcsize;
strm->next_out = dst;
strm->avail_out = dstsize;
ret = lzma_code(strm, LZMA_FINISH);
if (ret != LZMA_STREAM_END)
return -EBADMSG;
*srcsize = strm->total_in;
return strm->total_out;
}
static int erofs_compressor_liblzma_exit(struct erofs_compress *c)
{
struct erofs_liblzma_context *ctx = c->private_data;
if (!ctx)
return -EINVAL;
lzma_end(&ctx->strm);
free(ctx);
return 0;
}
static int erofs_compressor_liblzma_setlevel(struct erofs_compress *c,
int compression_level)
{
struct erofs_liblzma_context *ctx = c->private_data;
if (compression_level < 0)
compression_level = LZMA_PRESET_DEFAULT;
if (lzma_lzma_preset(&ctx->opt, compression_level))
return -EINVAL;
/* XXX: temporary hack */
if (cfg.c_dict_size) {
if (cfg.c_dict_size > Z_EROFS_LZMA_MAX_DICT_SIZE) {
erofs_err("dict size %u is too large", cfg.c_dict_size);
return -EINVAL;
}
ctx->opt.dict_size = cfg.c_dict_size;
} else {
if (ctx->opt.dict_size > Z_EROFS_LZMA_MAX_DICT_SIZE)
ctx->opt.dict_size = Z_EROFS_LZMA_MAX_DICT_SIZE;
cfg.c_dict_size = ctx->opt.dict_size;
}
c->compression_level = compression_level;
return 0;
}
static int erofs_compressor_liblzma_init(struct erofs_compress *c)
{
struct erofs_liblzma_context *ctx;
c->alg = &erofs_compressor_lzma;
ctx = malloc(sizeof(*ctx));
if (!ctx)
return -ENOMEM;
ctx->strm = (lzma_stream)LZMA_STREAM_INIT;
c->private_data = ctx;
erofs_warn("EXPERIMENTAL MicroLZMA feature in use. Use at your own risk!");
erofs_warn("Note that it may take more time since the compressor is still single-threaded for now.");
return 0;
}
const struct erofs_compressor erofs_compressor_lzma = {
.name = "lzma",
.default_level = LZMA_PRESET_DEFAULT,
.best_level = LZMA_PRESET_EXTREME,
.init = erofs_compressor_liblzma_init,
.exit = erofs_compressor_liblzma_exit,
.setlevel = erofs_compressor_liblzma_setlevel,
.compress_destsize = erofs_liblzma_compress_destsize,
};
#endif
|