]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * uncompress.c | |
4 | * | |
5 | * (C) Copyright 1999 Linus Torvalds | |
6 | * | |
7 | * cramfs interfaces to the uncompression library. There's really just | |
8 | * three entrypoints: | |
9 | * | |
10 | * - cramfs_uncompress_init() - called to initialize the thing. | |
11 | * - cramfs_uncompress_exit() - tell me when you're done | |
12 | * - cramfs_uncompress_block() - uncompress a block. | |
13 | * | |
14 | * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We | |
15 | * only have one stream, and we'll initialize it only once even if it | |
16 | * then is used by multiple filesystems. | |
17 | */ | |
18 | ||
4f21e1ea FF |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | ||
1da177e4 LT |
21 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | |
23 | #include <linux/vmalloc.h> | |
24 | #include <linux/zlib.h> | |
f7f4f4dd | 25 | #include "internal.h" |
1da177e4 LT |
26 | |
27 | static z_stream stream; | |
28 | static int initialized; | |
29 | ||
30 | /* Returns length of decompressed data. */ | |
31 | int 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) { | |
f175ff81 | 43 | pr_err("zlib_inflateReset error %d\n", err); |
1da177e4 LT |
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 | ||
53 | err: | |
f175ff81 FF |
54 | pr_err("Error %d while decompressing!\n", err); |
55 | pr_err("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); | |
98310e58 | 56 | return -EIO; |
1da177e4 LT |
57 | } |
58 | ||
59 | int cramfs_uncompress_init(void) | |
60 | { | |
61 | if (!initialized++) { | |
62 | stream.workspace = vmalloc(zlib_inflate_workspacesize()); | |
31d92e55 | 63 | if (!stream.workspace) { |
1da177e4 LT |
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 | ||
368bdb3d | 74 | void cramfs_uncompress_exit(void) |
1da177e4 LT |
75 | { |
76 | if (!--initialized) { | |
77 | zlib_inflateEnd(&stream); | |
78 | vfree(stream.workspace); | |
79 | } | |
1da177e4 | 80 | } |