^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Squashfs - a compressed read only filesystem for Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Phillip Lougher <phillip@squashfs.org.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * zlib_wrapper.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/bio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/zlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "squashfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "squashfs_fs_sb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "squashfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "decompressor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "page_actor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void *zlib_init(struct squashfs_sb_info *dummy, void *buff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (stream == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) stream->workspace = vmalloc(zlib_inflate_workspacesize());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (stream->workspace == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ERROR("Failed to allocate zlib workspace\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) kfree(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void zlib_free(void *strm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) z_stream *stream = strm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) vfree(stream->workspace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) kfree(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static int zlib_uncompress(struct squashfs_sb_info *msblk, void *strm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct bio *bio, int offset, int length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct squashfs_page_actor *output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct bvec_iter_all iter_all = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct bio_vec *bvec = bvec_init_iter_all(&iter_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int zlib_init = 0, error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) z_stream *stream = strm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) stream->avail_out = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) stream->next_out = squashfs_first_page(output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) stream->avail_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int zlib_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (stream->avail_in == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) const void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!bio_next_segment(bio, &iter_all)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Z_STREAM_END must be reached. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) avail = min(length, ((int)bvec->bv_len) - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) data = page_address(bvec->bv_page) + bvec->bv_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) length -= avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) stream->next_in = data + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) stream->avail_in = avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (stream->avail_out == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) stream->next_out = squashfs_next_page(output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (stream->next_out != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) stream->avail_out = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!zlib_init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) zlib_err = zlib_inflateInit(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (zlib_err != Z_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) zlib_init = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (zlib_err == Z_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (zlib_err != Z_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) squashfs_finish_page(output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (zlib_inflateEnd(stream) != Z_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return error ? error : stream->total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const struct squashfs_decompressor squashfs_zlib_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .init = zlib_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .free = zlib_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .decompress = zlib_uncompress,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .id = ZLIB_COMPRESSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .name = "zlib",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .supported = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)