81 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * uncompress.c4 *5 * (C) Copyright 1999 Linus Torvalds6 *7 * cramfs interfaces to the uncompression library. There's really just8 * three entrypoints:9 *10 * - cramfs_uncompress_init() - called to initialize the thing.11 * - cramfs_uncompress_exit() - tell me when you're done12 * - cramfs_uncompress_block() - uncompress a block.13 *14 * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We15 * only have one stream, and we'll initialize it only once even if it16 * then is used by multiple filesystems.17 */18 19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt20 21#include <linux/kernel.h>22#include <linux/errno.h>23#include <linux/vmalloc.h>24#include <linux/zlib.h>25#include "internal.h"26 27static z_stream stream;28static int initialized;29 30/* Returns length of decompressed data. */31int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)32{33 int err;34 35 stream.next_in = src;36 stream.avail_in = srclen;37 38 stream.next_out = dst;39 stream.avail_out = dstlen;40 41 err = zlib_inflateReset(&stream);42 if (err != Z_OK) {43 pr_err("zlib_inflateReset error %d\n", err);44 zlib_inflateEnd(&stream);45 zlib_inflateInit(&stream);46 }47 48 err = zlib_inflate(&stream, Z_FINISH);49 if (err != Z_STREAM_END)50 goto err;51 return stream.total_out;52 53err:54 pr_err("Error %d while decompressing!\n", err);55 pr_err("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);56 return -EIO;57}58 59int cramfs_uncompress_init(void)60{61 if (!initialized++) {62 stream.workspace = vmalloc(zlib_inflate_workspacesize());63 if (!stream.workspace) {64 initialized = 0;65 return -ENOMEM;66 }67 stream.next_in = NULL;68 stream.avail_in = 0;69 zlib_inflateInit(&stream);70 }71 return 0;72}73 74void cramfs_uncompress_exit(void)75{76 if (!--initialized) {77 zlib_inflateEnd(&stream);78 vfree(stream.workspace);79 }80}81