Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * uncompress.c
0004  *
0005  * (C) Copyright 1999 Linus Torvalds
0006  *
0007  * cramfs interfaces to the uncompression library. There's really just
0008  * three entrypoints:
0009  *
0010  *  - cramfs_uncompress_init() - called to initialize the thing.
0011  *  - cramfs_uncompress_exit() - tell me when you're done
0012  *  - cramfs_uncompress_block() - uncompress a block.
0013  *
0014  * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
0015  * only have one stream, and we'll initialize it only once even if it
0016  * then is used by multiple filesystems.
0017  */
0018 
0019 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0020 
0021 #include <linux/kernel.h>
0022 #include <linux/errno.h>
0023 #include <linux/vmalloc.h>
0024 #include <linux/zlib.h>
0025 #include "internal.h"
0026 
0027 static z_stream stream;
0028 static int initialized;
0029 
0030 /* Returns length of decompressed data. */
0031 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
0032 {
0033     int err;
0034 
0035     stream.next_in = src;
0036     stream.avail_in = srclen;
0037 
0038     stream.next_out = dst;
0039     stream.avail_out = dstlen;
0040 
0041     err = zlib_inflateReset(&stream);
0042     if (err != Z_OK) {
0043         pr_err("zlib_inflateReset error %d\n", err);
0044         zlib_inflateEnd(&stream);
0045         zlib_inflateInit(&stream);
0046     }
0047 
0048     err = zlib_inflate(&stream, Z_FINISH);
0049     if (err != Z_STREAM_END)
0050         goto err;
0051     return stream.total_out;
0052 
0053 err:
0054     pr_err("Error %d while decompressing!\n", err);
0055     pr_err("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
0056     return -EIO;
0057 }
0058 
0059 int cramfs_uncompress_init(void)
0060 {
0061     if (!initialized++) {
0062         stream.workspace = vmalloc(zlib_inflate_workspacesize());
0063         if (!stream.workspace) {
0064             initialized = 0;
0065             return -ENOMEM;
0066         }
0067         stream.next_in = NULL;
0068         stream.avail_in = 0;
0069         zlib_inflateInit(&stream);
0070     }
0071     return 0;
0072 }
0073 
0074 void cramfs_uncompress_exit(void)
0075 {
0076     if (!--initialized) {
0077         zlib_inflateEnd(&stream);
0078         vfree(stream.workspace);
0079     }
0080 }