Commit | Line | Data |
---|---|---|
68252eb5 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
e6a6d379 PL |
2 | /* |
3 | * Squashfs - a compressed read only filesystem for Linux | |
4 | * | |
5 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 | |
d7f2ff67 | 6 | * Phillip Lougher <phillip@squashfs.org.uk> |
e6a6d379 | 7 | * |
e6a6d379 PL |
8 | * zlib_wrapper.c |
9 | */ | |
10 | ||
11 | ||
12 | #include <linux/mutex.h> | |
13 | #include <linux/buffer_head.h> | |
5a0e3ad6 | 14 | #include <linux/slab.h> |
e6a6d379 | 15 | #include <linux/zlib.h> |
117a91e0 | 16 | #include <linux/vmalloc.h> |
e6a6d379 PL |
17 | |
18 | #include "squashfs_fs.h" | |
19 | #include "squashfs_fs_sb.h" | |
e6a6d379 | 20 | #include "squashfs.h" |
4c0f0bb2 | 21 | #include "decompressor.h" |
846b730e | 22 | #include "page_actor.h" |
e6a6d379 | 23 | |
9508c6b9 | 24 | static void *zlib_init(struct squashfs_sb_info *dummy, void *buff) |
f1a40359 PL |
25 | { |
26 | z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); | |
27 | if (stream == NULL) | |
28 | goto failed; | |
117a91e0 | 29 | stream->workspace = vmalloc(zlib_inflate_workspacesize()); |
f1a40359 PL |
30 | if (stream->workspace == NULL) |
31 | goto failed; | |
32 | ||
33 | return stream; | |
34 | ||
35 | failed: | |
36 | ERROR("Failed to allocate zlib workspace\n"); | |
37 | kfree(stream); | |
b7fc0ff0 | 38 | return ERR_PTR(-ENOMEM); |
f1a40359 PL |
39 | } |
40 | ||
41 | ||
4c0f0bb2 | 42 | static void zlib_free(void *strm) |
f1a40359 PL |
43 | { |
44 | z_stream *stream = strm; | |
45 | ||
46 | if (stream) | |
117a91e0 | 47 | vfree(stream->workspace); |
f1a40359 PL |
48 | kfree(stream); |
49 | } | |
50 | ||
51 | ||
9508c6b9 | 52 | static int zlib_uncompress(struct squashfs_sb_info *msblk, void *strm, |
846b730e PL |
53 | struct buffer_head **bh, int b, int offset, int length, |
54 | struct squashfs_page_actor *output) | |
e6a6d379 | 55 | { |
846b730e | 56 | int zlib_err, zlib_init = 0, k = 0; |
9508c6b9 | 57 | z_stream *stream = strm; |
e6a6d379 | 58 | |
09cbfeaf | 59 | stream->avail_out = PAGE_SIZE; |
846b730e | 60 | stream->next_out = squashfs_first_page(output); |
f1a40359 | 61 | stream->avail_in = 0; |
e6a6d379 | 62 | |
e6a6d379 | 63 | do { |
f1a40359 | 64 | if (stream->avail_in == 0 && k < b) { |
170cf021 PL |
65 | int avail = min(length, msblk->devblksize - offset); |
66 | length -= avail; | |
f1a40359 PL |
67 | stream->next_in = bh[k]->b_data + offset; |
68 | stream->avail_in = avail; | |
e6a6d379 PL |
69 | offset = 0; |
70 | } | |
71 | ||
846b730e PL |
72 | if (stream->avail_out == 0) { |
73 | stream->next_out = squashfs_next_page(output); | |
74 | if (stream->next_out != NULL) | |
09cbfeaf | 75 | stream->avail_out = PAGE_SIZE; |
e6a6d379 PL |
76 | } |
77 | ||
78 | if (!zlib_init) { | |
f1a40359 | 79 | zlib_err = zlib_inflateInit(stream); |
846b730e PL |
80 | if (zlib_err != Z_OK) { |
81 | squashfs_finish_page(output); | |
9508c6b9 | 82 | goto out; |
846b730e | 83 | } |
e6a6d379 PL |
84 | zlib_init = 1; |
85 | } | |
86 | ||
f1a40359 | 87 | zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH); |
e6a6d379 | 88 | |
f1a40359 | 89 | if (stream->avail_in == 0 && k < b) |
e6a6d379 PL |
90 | put_bh(bh[k++]); |
91 | } while (zlib_err == Z_OK); | |
92 | ||
846b730e PL |
93 | squashfs_finish_page(output); |
94 | ||
9508c6b9 PL |
95 | if (zlib_err != Z_STREAM_END) |
96 | goto out; | |
e6a6d379 | 97 | |
f1a40359 | 98 | zlib_err = zlib_inflateEnd(stream); |
9508c6b9 PL |
99 | if (zlib_err != Z_OK) |
100 | goto out; | |
e7ee11f0 | 101 | |
9508c6b9 PL |
102 | if (k < b) |
103 | goto out; | |
e6a6d379 | 104 | |
9508c6b9 | 105 | return stream->total_out; |
e6a6d379 | 106 | |
9508c6b9 | 107 | out: |
e6a6d379 PL |
108 | for (; k < b; k++) |
109 | put_bh(bh[k]); | |
110 | ||
111 | return -EIO; | |
112 | } | |
4c0f0bb2 PL |
113 | |
114 | const struct squashfs_decompressor squashfs_zlib_comp_ops = { | |
115 | .init = zlib_init, | |
116 | .free = zlib_free, | |
117 | .decompress = zlib_uncompress, | |
118 | .id = ZLIB_COMPRESSION, | |
119 | .name = "zlib", | |
120 | .supported = 1 | |
121 | }; | |
122 |