diff options
Diffstat (limited to 'fs/cramfs/uncompress.c')
-rw-r--r-- | fs/cramfs/uncompress.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c new file mode 100644 index 000000000000..5034365b06a8 --- /dev/null +++ b/fs/cramfs/uncompress.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * uncompress.c | ||
3 | * | ||
4 | * (C) Copyright 1999 Linus Torvalds | ||
5 | * | ||
6 | * cramfs interfaces to the uncompression library. There's really just | ||
7 | * three entrypoints: | ||
8 | * | ||
9 | * - cramfs_uncompress_init() - called to initialize the thing. | ||
10 | * - cramfs_uncompress_exit() - tell me when you're done | ||
11 | * - cramfs_uncompress_block() - uncompress a block. | ||
12 | * | ||
13 | * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We | ||
14 | * only have one stream, and we'll initialize it only once even if it | ||
15 | * then is used by multiple filesystems. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/vmalloc.h> | ||
21 | #include <linux/zlib.h> | ||
22 | |||
23 | static z_stream stream; | ||
24 | static int initialized; | ||
25 | |||
26 | /* Returns length of decompressed data. */ | ||
27 | int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen) | ||
28 | { | ||
29 | int err; | ||
30 | |||
31 | stream.next_in = src; | ||
32 | stream.avail_in = srclen; | ||
33 | |||
34 | stream.next_out = dst; | ||
35 | stream.avail_out = dstlen; | ||
36 | |||
37 | err = zlib_inflateReset(&stream); | ||
38 | if (err != Z_OK) { | ||
39 | printk("zlib_inflateReset error %d\n", err); | ||
40 | zlib_inflateEnd(&stream); | ||
41 | zlib_inflateInit(&stream); | ||
42 | } | ||
43 | |||
44 | err = zlib_inflate(&stream, Z_FINISH); | ||
45 | if (err != Z_STREAM_END) | ||
46 | goto err; | ||
47 | return stream.total_out; | ||
48 | |||
49 | err: | ||
50 | printk("Error %d while decompressing!\n", err); | ||
51 | printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | int cramfs_uncompress_init(void) | ||
56 | { | ||
57 | if (!initialized++) { | ||
58 | stream.workspace = vmalloc(zlib_inflate_workspacesize()); | ||
59 | if ( !stream.workspace ) { | ||
60 | initialized = 0; | ||
61 | return -ENOMEM; | ||
62 | } | ||
63 | stream.next_in = NULL; | ||
64 | stream.avail_in = 0; | ||
65 | zlib_inflateInit(&stream); | ||
66 | } | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | int cramfs_uncompress_exit(void) | ||
71 | { | ||
72 | if (!--initialized) { | ||
73 | zlib_inflateEnd(&stream); | ||
74 | vfree(stream.workspace); | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||