| /* |
| * 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 |