Home | History | Annotate | Download | only in squashfs-tools
      1 /*
      2  * Copyright (c) 2009, 2010, 2013
      3  * Phillip Lougher <phillip (at) squashfs.org.uk>
      4  *
      5  * This program is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU General Public License
      7  * as published by the Free Software Foundation; either version 2,
      8  * or (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     18  *
     19  * lzma_wrapper.c
     20  *
     21  * Support for LZMA1 compression using LZMA SDK (4.65 used in
     22  * development, other versions may work) http://www.7-zip.org/sdk.html
     23  */
     24 
     25 #include <LzmaLib.h>
     26 
     27 #include "squashfs_fs.h"
     28 #include "compressor.h"
     29 
     30 #define LZMA_HEADER_SIZE	(LZMA_PROPS_SIZE + 8)
     31 
     32 static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size,
     33 		int *error)
     34 {
     35 	unsigned char *d = dest;
     36 	size_t props_size = LZMA_PROPS_SIZE,
     37 		outlen = block_size - LZMA_HEADER_SIZE;
     38 	int res;
     39 
     40 	res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest,
     41 		&props_size, 5, block_size, 3, 0, 2, 32, 1);
     42 
     43 	if(res == SZ_ERROR_OUTPUT_EOF) {
     44 		/*
     45 		 * Output buffer overflow.  Return out of buffer space error
     46 		 */
     47 		return 0;
     48 	}
     49 
     50 	if(res != SZ_OK) {
     51 		/*
     52 		 * All other errors return failure, with the compressor
     53 		 * specific error code in *error
     54 		 */
     55 		*error = res;
     56 		return -1;
     57 	}
     58 
     59 	/*
     60 	 * Fill in the 8 byte little endian uncompressed size field in the
     61 	 * LZMA header.  8 bytes is excessively large for squashfs but
     62 	 * this is the standard LZMA header and which is expected by the kernel
     63 	 * code
     64 	 */
     65 	d[LZMA_PROPS_SIZE] = size & 255;
     66 	d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
     67 	d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
     68 	d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
     69 	d[LZMA_PROPS_SIZE + 4] = 0;
     70 	d[LZMA_PROPS_SIZE + 5] = 0;
     71 	d[LZMA_PROPS_SIZE + 6] = 0;
     72 	d[LZMA_PROPS_SIZE + 7] = 0;
     73 
     74 	/*
     75 	 * Success, return the compressed size.  Outlen returned by the LZMA
     76 	 * compressor does not include the LZMA header space
     77 	 */
     78 	return outlen + LZMA_HEADER_SIZE;
     79 }
     80 
     81 
     82 static int lzma_uncompress(void *dest, void *src, int size, int outsize,
     83 	int *error)
     84 {
     85 	unsigned char *s = src;
     86 	size_t outlen, inlen = size - LZMA_HEADER_SIZE;
     87 	int res;
     88 
     89 	outlen = s[LZMA_PROPS_SIZE] |
     90 		(s[LZMA_PROPS_SIZE + 1] << 8) |
     91 		(s[LZMA_PROPS_SIZE + 2] << 16) |
     92 		(s[LZMA_PROPS_SIZE + 3] << 24);
     93 
     94 	if(outlen > outsize) {
     95 		*error = 0;
     96 		return -1;
     97 	}
     98 
     99 	res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src,
    100 		LZMA_PROPS_SIZE);
    101 
    102 	if(res == SZ_OK)
    103 		return outlen;
    104 	else {
    105 		*error = res;
    106 		return -1;
    107 	}
    108 }
    109 
    110 
    111 struct compressor lzma_comp_ops = {
    112 	.init = NULL,
    113 	.compress = lzma_compress,
    114 	.uncompress = lzma_uncompress,
    115 	.options = NULL,
    116 	.usage = NULL,
    117 	.id = LZMA_COMPRESSION,
    118 	.name = "lzma",
    119 	.supported = 1
    120 };
    121 
    122