]>
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> | |
93e72b3c | 13 | #include <linux/bio.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, |
93e72b3c | 53 | struct bio *bio, int offset, int length, |
846b730e | 54 | struct squashfs_page_actor *output) |
e6a6d379 | 55 | { |
93e72b3c PL |
56 | struct bvec_iter_all iter_all = {}; |
57 | struct bio_vec *bvec = bvec_init_iter_all(&iter_all); | |
58 | int zlib_init = 0, error = 0; | |
9508c6b9 | 59 | z_stream *stream = strm; |
e6a6d379 | 60 | |
09cbfeaf | 61 | stream->avail_out = PAGE_SIZE; |
846b730e | 62 | stream->next_out = squashfs_first_page(output); |
f1a40359 | 63 | stream->avail_in = 0; |
e6a6d379 | 64 | |
93e72b3c PL |
65 | for (;;) { |
66 | int zlib_err; | |
67 | ||
68 | if (stream->avail_in == 0) { | |
69 | const void *data; | |
70 | int avail; | |
71 | ||
72 | if (!bio_next_segment(bio, &iter_all)) { | |
73 | /* Z_STREAM_END must be reached. */ | |
74 | error = -EIO; | |
75 | break; | |
76 | } | |
77 | ||
78 | avail = min(length, ((int)bvec->bv_len) - offset); | |
79 | data = page_address(bvec->bv_page) + bvec->bv_offset; | |
170cf021 | 80 | length -= avail; |
93e72b3c | 81 | stream->next_in = data + offset; |
f1a40359 | 82 | stream->avail_in = avail; |
e6a6d379 PL |
83 | offset = 0; |
84 | } | |
85 | ||
846b730e PL |
86 | if (stream->avail_out == 0) { |
87 | stream->next_out = squashfs_next_page(output); | |
88 | if (stream->next_out != NULL) | |
09cbfeaf | 89 | stream->avail_out = PAGE_SIZE; |
e6a6d379 PL |
90 | } |
91 | ||
92 | if (!zlib_init) { | |
f1a40359 | 93 | zlib_err = zlib_inflateInit(stream); |
846b730e | 94 | if (zlib_err != Z_OK) { |
93e72b3c PL |
95 | error = -EIO; |
96 | break; | |
846b730e | 97 | } |
e6a6d379 PL |
98 | zlib_init = 1; |
99 | } | |
100 | ||
f1a40359 | 101 | zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH); |
93e72b3c PL |
102 | if (zlib_err == Z_STREAM_END) |
103 | break; | |
104 | if (zlib_err != Z_OK) { | |
105 | error = -EIO; | |
106 | break; | |
107 | } | |
108 | } | |
e6a6d379 | 109 | |
846b730e PL |
110 | squashfs_finish_page(output); |
111 | ||
93e72b3c PL |
112 | if (!error) |
113 | if (zlib_inflateEnd(stream) != Z_OK) | |
114 | error = -EIO; | |
e6a6d379 | 115 | |
93e72b3c | 116 | return error ? error : stream->total_out; |
e6a6d379 | 117 | } |
4c0f0bb2 PL |
118 | |
119 | const struct squashfs_decompressor squashfs_zlib_comp_ops = { | |
120 | .init = zlib_init, | |
121 | .free = zlib_free, | |
122 | .decompress = zlib_uncompress, | |
123 | .id = ZLIB_COMPRESSION, | |
124 | .name = "zlib", | |
125 | .supported = 1 | |
126 | }; | |
127 |