2010-08-05 05:29:59 +04:00
/*
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright ( c ) 2010 LG Electronics
* Chan Jeong < chan . jeong @ lge . com >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2 ,
* or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
* lzo_wrapper . c
*/
# include <linux/mutex.h>
# include <linux/buffer_head.h>
# include <linux/slab.h>
# include <linux/vmalloc.h>
# include <linux/lzo.h>
# include "squashfs_fs.h"
# include "squashfs_fs_sb.h"
# include "squashfs.h"
# include "decompressor.h"
2013-11-18 06:59:12 +04:00
# include "page_actor.h"
2010-08-05 05:29:59 +04:00
struct squashfs_lzo {
void * input ;
void * output ;
} ;
2013-11-13 06:56:26 +04:00
static void * lzo_init ( struct squashfs_sb_info * msblk , void * buff )
2010-08-05 05:29:59 +04:00
{
2010-08-05 07:51:50 +04:00
int block_size = max_t ( int , msblk - > block_size , SQUASHFS_METADATA_SIZE ) ;
2010-08-05 05:29:59 +04:00
struct squashfs_lzo * stream = kzalloc ( sizeof ( * stream ) , GFP_KERNEL ) ;
if ( stream = = NULL )
goto failed ;
2010-08-05 07:51:50 +04:00
stream - > input = vmalloc ( block_size ) ;
2010-08-05 05:29:59 +04:00
if ( stream - > input = = NULL )
goto failed ;
2010-08-05 07:51:50 +04:00
stream - > output = vmalloc ( block_size ) ;
2010-08-05 05:29:59 +04:00
if ( stream - > output = = NULL )
goto failed2 ;
return stream ;
failed2 :
vfree ( stream - > input ) ;
failed :
ERROR ( " Failed to allocate lzo workspace \n " ) ;
kfree ( stream ) ;
2011-02-28 04:45:42 +03:00
return ERR_PTR ( - ENOMEM ) ;
2010-08-05 05:29:59 +04:00
}
static void lzo_free ( void * strm )
{
struct squashfs_lzo * stream = strm ;
if ( stream ) {
vfree ( stream - > input ) ;
vfree ( stream - > output ) ;
}
kfree ( stream ) ;
}
2013-11-13 06:56:26 +04:00
static int lzo_uncompress ( struct squashfs_sb_info * msblk , void * strm ,
2013-11-18 06:59:12 +04:00
struct buffer_head * * bh , int b , int offset , int length ,
struct squashfs_page_actor * output )
2010-08-05 05:29:59 +04:00
{
2013-11-13 06:56:26 +04:00
struct squashfs_lzo * stream = strm ;
2013-11-18 06:59:12 +04:00
void * buff = stream - > input , * data ;
2010-08-05 05:29:59 +04:00
int avail , i , bytes = length , res ;
2013-11-18 06:59:12 +04:00
size_t out_len = output - > length ;
2010-08-05 05:29:59 +04:00
for ( i = 0 ; i < b ; i + + ) {
avail = min ( bytes , msblk - > devblksize - offset ) ;
memcpy ( buff , bh [ i ] - > b_data + offset , avail ) ;
buff + = avail ;
bytes - = avail ;
offset = 0 ;
put_bh ( bh [ i ] ) ;
}
res = lzo1x_decompress_safe ( stream - > input , ( size_t ) length ,
stream - > output , & out_len ) ;
if ( res ! = LZO_E_OK )
goto failed ;
res = bytes = ( int ) out_len ;
2013-11-18 06:59:12 +04:00
data = squashfs_first_page ( output ) ;
buff = stream - > output ;
while ( data ) {
if ( bytes < = PAGE_CACHE_SIZE ) {
memcpy ( data , buff , bytes ) ;
break ;
} else {
memcpy ( data , buff , PAGE_CACHE_SIZE ) ;
buff + = PAGE_CACHE_SIZE ;
bytes - = PAGE_CACHE_SIZE ;
data = squashfs_next_page ( output ) ;
}
2010-08-05 05:29:59 +04:00
}
2013-11-18 06:59:12 +04:00
squashfs_finish_page ( output ) ;
2010-08-05 05:29:59 +04:00
return res ;
failed :
return - EIO ;
}
const struct squashfs_decompressor squashfs_lzo_comp_ops = {
. init = lzo_init ,
. free = lzo_free ,
. decompress = lzo_uncompress ,
. id = LZO_COMPRESSION ,
. name = " lzo " ,
. supported = 1
} ;