1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Copyright 2026 Oxide Computer Company 27 */ 28 29 #include <sys/modctl.h> 30 #include <sys/zmod.h> 31 32 #include <zlib.h> 33 #include <zutil.h> 34 35 /* 36 * Uncompress the buffer 'src' into the buffer 'dst'. The caller must store 37 * the expected decompressed data size externally so it can be passed in. 38 * The resulting decompressed size is then returned through dstlen. This 39 * function return Z_OK on success, or another error code on failure. 40 */ 41 static int 42 z_uncompress_impl(void *dst, size_t *dstlen, const void *src, size_t srclen, 43 alloc_func zalloc) 44 { 45 z_stream zs; 46 int err; 47 48 bzero(&zs, sizeof (zs)); 49 zs.zalloc = zalloc; 50 zs.next_in = (uchar_t *)src; 51 zs.avail_in = srclen; 52 zs.next_out = dst; 53 zs.avail_out = *dstlen; 54 55 /* 56 * Call inflateInit2() specifying a window size of DEF_WBITS 57 * with the 6th bit set to indicate that the compression format 58 * type (zlib or gzip) should be automatically detected. 59 */ 60 if ((err = inflateInit2(&zs, DEF_WBITS | 0x20)) != Z_OK) 61 return (err); 62 63 if ((err = inflate(&zs, Z_FINISH)) != Z_STREAM_END) { 64 (void) inflateEnd(&zs); 65 return (err == Z_OK ? Z_BUF_ERROR : err); 66 } 67 68 *dstlen = zs.total_out; 69 return (inflateEnd(&zs)); 70 } 71 72 int 73 z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 74 { 75 return (z_uncompress_impl(dst, dstlen, src, srclen, NULL)); 76 } 77 78 /* 79 * Variant of z_uncompress which uses the KM_SLEEP allocator so callers 80 * will block waiting for memory rather than failing immediately. This is 81 * intended for callers (such as ZFS read-path) that expect to wait for 82 * memory instead of returning an error. 83 */ 84 int 85 z_uncompress_sleep(void *dst, size_t *dstlen, const void *src, size_t srclen) 86 { 87 return (z_uncompress_impl(dst, dstlen, src, srclen, zcalloc_sleep)); 88 } 89 90 int 91 z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 92 int level) 93 { 94 95 z_stream zs; 96 int err; 97 98 bzero(&zs, sizeof (zs)); 99 zs.next_in = (uchar_t *)src; 100 zs.avail_in = srclen; 101 zs.next_out = dst; 102 zs.avail_out = *dstlen; 103 104 if ((err = deflateInit(&zs, level)) != Z_OK) 105 return (err); 106 107 if ((err = deflate(&zs, Z_FINISH)) != Z_STREAM_END) { 108 (void) deflateEnd(&zs); 109 return (err == Z_OK ? Z_BUF_ERROR : err); 110 } 111 112 *dstlen = zs.total_out; 113 return (deflateEnd(&zs)); 114 } 115 116 int 117 z_compress(void *dst, size_t *dstlen, const void *src, size_t srclen) 118 { 119 return (z_compress_level(dst, dstlen, src, srclen, 120 Z_DEFAULT_COMPRESSION)); 121 } 122 123 /* 124 * Convert a zlib error code into a string error message. 125 */ 126 const char * 127 z_strerror(int err) 128 { 129 int i = Z_NEED_DICT - err; 130 131 if (i < 0 || i > Z_NEED_DICT - Z_VERSION_ERROR) 132 return ("unknown error"); 133 134 return (zError(err)); 135 } 136