/* SPDX-License-Identifier: BSD-2-Clause */ /* Minimal DEFLATE decompressor for EROFS FreeBSD */ #include #include #include #include #include "internal.h" int z_erofs_load_deflate_config(struct erofs_mount *em, const void *data, size_t size) { const struct z_erofs_deflate_cfgs *deflate; if (size < sizeof(*deflate)) return (EINVAL); deflate = data; if (deflate->windowbits < 8 || deflate->windowbits > 15) return (EOPNOTSUPP); em->deflate_windowbits = deflate->windowbits; return (0); } int deflate_decompress(void *src, size_t srclen, void *dst, size_t dstlen, int n, bool partial) { z_stream strm; uInt in_before, out_before; int endret, ret; if (n < 8 || n > MAX_WBITS || srclen > (size_t)(uInt)-1 || dstlen > (size_t)(uInt)-1 || dstlen == 0) return (-1); bzero(&strm, sizeof(strm)); strm.next_in = src; strm.avail_in = srclen; strm.next_out = dst; strm.avail_out = dstlen; ret = inflateInit2(&strm, -n); if (ret != Z_OK) return (-1); ret = Z_OK; while (strm.avail_out != 0) { in_before = strm.avail_in; out_before = strm.avail_out; ret = inflate(&strm, Z_SYNC_FLUSH); if (ret == Z_STREAM_END) break; if (ret != Z_OK || (strm.avail_in == in_before && strm.avail_out == out_before)) break; } endret = inflateEnd(&strm); if (endret != Z_OK || strm.avail_out != 0) return (-1); if (partial) return (ret == Z_OK || ret == Z_STREAM_END ? 0 : -1); if (ret != Z_STREAM_END || strm.avail_in != 0) return (-1); return (0); }