blob: e2200146c40bbfb4a051f71bc84f1404c603a38d [file] [log] [blame]
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* For licensing information, see the file 'LICENCE' in this directory.
*
* JFFS2 wrapper to the LZMA C SDK
*
*/
//#include <stdio.h>
//#include <stdlib.h>
//#include <linux/types.h>
//#include <sys/stat.h>
//#include <fcntl.h>
#include <linux/lzma.h>
/*
1.1. Header
+------------+----+----+----+----+--+--+--+--+--+--+--+--+
| Properties | Dictionary Size | Uncompressed Size |
+------------+----+----+----+----+--+--+--+--+--+--+--+--+
1.1.1. Properties
The Properties field contains three properties. An abbreviation
is given in parentheses, followed by the value range of the
property. The field consists of
1) the number of literal context bits (lc, [0, 8]);
2) the number of literal position bits (lp, [0, 4]); and
3) the number of position bits (pb, [0, 4]).
The properties are encoded using the following formula:
Properties = (pb * 5 + lp) * 9 + lc
The following C code illustrates a straightforward way to
decode the Properties field:
uint8_t lc, lp, pb;
uint8_t prop = get_lzma_properties();
if (prop > (4 * 5 + 4) * 9 + 8)
return LZMA_PROPERTIES_ERROR;
pb = prop / (9 * 5);
prop -= pb * 9 * 5;
lp = prop / 9;
lc = prop - lp * 9;
*/
#if 0
#define ZTE_LZMA_DICT //(0x100000)
#define ZTE_LZMA_LC //3
#define ZTE_LZMA_LP //0
#define ZTE_LZMA_PB //2
#endif
static CLzmaEncHandle *p_lzma;
static Byte propsEncoded_lzma[LZMA_PROPS_SIZE];
static SizeT propsSize_lzma = sizeof(propsEncoded_lzma);
static void lzma_free_workspace(void)
{
LzmaEnc_Destroy(p_lzma, &lzma_alloc, &lzma_alloc);
}
static int INIT lzma_alloc_workspace(CLzmaEncProps * props)
{
if ((p_lzma = (CLzmaEncHandle *) LzmaEnc_Create(&lzma_alloc)) == NULL) {
PRINT_ERROR("Failed to allocate lzma deflate workspace\n");
return -ENOMEM;
}
if (LzmaEnc_SetProps(p_lzma, props) != SZ_OK) {
lzma_free_workspace();
return -1;
}
if (LzmaEnc_WriteProperties(p_lzma, propsEncoded_lzma, &propsSize_lzma) != SZ_OK) {
lzma_free_workspace();
return -1;
}
return 0;
}
static int lzma_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t * sourcelen, uint32_t * dstlen)
{
SizeT compress_size = (SizeT) (*dstlen);
int ret;
ret = LzmaEnc_MemEncode(p_lzma, cpage_out, &compress_size, data_in, *sourcelen, 0, NULL, &lzma_alloc, &lzma_alloc);
if (ret != SZ_OK)
return -1;
*dstlen = (uint32_t) compress_size;
return 0;
}
int lzma_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen)
{
int ret;
SizeT dl = (SizeT) destlen;
SizeT sl = (SizeT) srclen;
ELzmaStatus status;
ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded_lzma, propsSize_lzma, LZMA_FINISH_ANY, &status, &lzma_alloc);
if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT) destlen)
{
return -1;
}
return 0;
}
int lzma_init(UInt32 *ztelzma_dict,int *ztelzma_lc,int *ztelzma_lp,int *ztelzma_pb)
{
int ret = -1;
CLzmaEncProps props;
LzmaEncProps_Init(&props);
props.dictSize = LZMA_BEST_DICT(*ztelzma_dict);
props.level = LZMA_BEST_LEVEL;
props.lc = *ztelzma_lc; //ZTE_LZMA_LC; //LZMA_BEST_LC;
props.lp = *ztelzma_lp; //ZTE_LZMA_LP; //LZMA_BEST_LP;
props.pb = *ztelzma_pb; //ZTE_LZMA_PB; //LZMA_BEST_PB;
props.fb = LZMA_BEST_FB;
ret = lzma_alloc_workspace(&props);
return ret;
}
#if 0
int main(int argc, char *argv[])
{
int ret = -1;
struct stat stat_buf;
char *file_name = NULL;
char out_file[2048] = { 0 };
int fd1, fd2;
char *in;
uint32_t in_len;
char *out;
uint32_t out_len;
char *in2;
uint32_t in2_len;
int i, keep_flag = 0;
/*
LZMA compressed file format
---------------------------
Offset Size Description
0 1 Special LZMA properties (lc,lp, pb in encoded form)
1 4 Dictionary size (little endian)
5 8 Uncompressed size (little endian). -1 means unknown size
13 Compressed data
*/
uint8_t lzmainfo[13];
uint32_t *p_dict = (uint32_t *)(&lzmainfo[1]);
uint64_t *p_uncompress_size = (uint64_t *)(&lzmainfo[5]);
if (argc < 2) {
printf("usage:\n\t %s [-k] file\n", argv[0]);
return -1;
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-k") == 0)
keep_flag = 1;
}
file_name = argv[argc - 1];
ret = stat(file_name, &stat_buf);
if (ret < 0) {
printf("stat file %s failed\n", file_name);
return -1;
}
in_len = stat_buf.st_size;
in = malloc(in_len);
in2 = malloc(in_len);
fd1 = open(file_name, O_RDONLY, 0644);
if (fd1 < 0) {
perror("open file failed\n");
return -1;
}
ret = read(fd1, in, in_len);
if (ret < 0) {
perror("read file failed\n");
return -1;
}
close(fd1);
sprintf(out_file, "%s.lzma", file_name);
//printf("out_file is %s\n",out_file);
fd2 = open(out_file, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd2 < 0) {
perror("open out file failed\n");
return -1;
}
ret = lzma_init();
if(ret < 0) {
printf("lzma_init failed\n");
return -1;
}
out = malloc(in_len * 2);
out_len = in_len * 2;
ret = lzma_compress(in, out, &in_len, &out_len);
if (ret < 0) {
printf("lzma compress fail\n");
return -1;
}
//(pb * 5 + lp) * 9 + lc;
lzmainfo[0] = (ZTE_LZMA_PB * 5 + ZTE_LZMA_LP) * 9 + ZTE_LZMA_LC;
*p_dict = ZTE_LZMA_DICT;
*p_uncompress_size = in_len;
ret = write(fd2, lzmainfo, sizeof(lzmainfo));
if(ret < sizeof(lzmainfo)) {
printf("write failed:%d\n",ret );
return -1;
}
ret = write(fd2, out, out_len);
if(ret < out_len) {
printf("write failed:%d\n",ret );
return -1;
}
close(fd2);
ret = lzma_decompress(out, in2, out_len, in_len);
if (ret < 0) {
printf("lzma decompress fail\n");
return -1;
}
if (memcmp(in, in2, in_len) != 0) {
printf("in in2 not same\n");
return -1;
}
if (!keep_flag)
unlink(file_name);
return 0;
}
#endif