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 27 #include <sys/types.h> 28 #include <sys/cmn_err.h> 29 #include <sys/systm.h> 30 #include <sys/kobj.h> 31 #include <sys/zmod.h> 32 33 #include <contrib/zlib/zlib.h> 34 #include <contrib/zlib/zutil.h> 35 36 struct zchdr { 37 uint_t zch_magic; 38 uint_t zch_size; 39 }; 40 41 #define ZCH_MAGIC 0x3cc13cc1 42 43 /*ARGSUSED*/ 44 static void * 45 zfs_zcalloc(void *opaque, uint_t items, uint_t size) 46 { 47 size_t nbytes = sizeof (struct zchdr) + items * size; 48 struct zchdr *z = kobj_zalloc(nbytes, KM_NOWAIT|KM_TMP); 49 50 if (z == NULL) 51 return (NULL); 52 53 z->zch_magic = ZCH_MAGIC; 54 z->zch_size = nbytes; 55 56 return (z + 1); 57 } 58 59 /*ARGSUSED*/ 60 static void 61 zfs_zcfree(void *opaque, void *ptr) 62 { 63 struct zchdr *z = ((struct zchdr *)ptr) - 1; 64 65 if (z->zch_magic != ZCH_MAGIC) 66 panic("zcfree region corrupt: hdr=%p ptr=%p", (void *)z, ptr); 67 68 kobj_free(z, z->zch_size); 69 } 70 71 /* 72 * Uncompress the buffer 'src' into the buffer 'dst'. The caller must store 73 * the expected decompressed data size externally so it can be passed in. 74 * The resulting decompressed size is then returned through dstlen. This 75 * function return Z_OK on success, or another error code on failure. 76 */ 77 int 78 z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 79 { 80 z_stream zs; 81 int err; 82 83 bzero(&zs, sizeof (zs)); 84 zs.next_in = (uchar_t *)src; 85 zs.avail_in = srclen; 86 zs.next_out = dst; 87 zs.avail_out = *dstlen; 88 zs.zalloc = zfs_zcalloc; 89 zs.zfree = zfs_zcfree; 90 91 /* 92 * Call inflateInit2() specifying a window size of DEF_WBITS 93 * with the 6th bit set to indicate that the compression format 94 * type (zlib or gzip) should be automatically detected. 95 */ 96 if ((err = inflateInit2(&zs, DEF_WBITS | 0x20)) != Z_OK) 97 return (err); 98 99 if ((err = inflate(&zs, Z_FINISH)) != Z_STREAM_END) { 100 (void) inflateEnd(&zs); 101 return (err == Z_OK ? Z_BUF_ERROR : err); 102 } 103 104 *dstlen = zs.total_out; 105 return (inflateEnd(&zs)); 106 } 107 108 int 109 z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 110 int level) 111 { 112 113 z_stream zs; 114 int err; 115 116 bzero(&zs, sizeof (zs)); 117 zs.next_in = (uchar_t *)src; 118 zs.avail_in = srclen; 119 zs.next_out = dst; 120 zs.avail_out = *dstlen; 121 zs.zalloc = zfs_zcalloc; 122 zs.zfree = zfs_zcfree; 123 124 if ((err = deflateInit(&zs, level)) != Z_OK) 125 return (err); 126 127 if ((err = deflate(&zs, Z_FINISH)) != Z_STREAM_END) { 128 (void) deflateEnd(&zs); 129 return (err == Z_OK ? Z_BUF_ERROR : err); 130 } 131 132 *dstlen = zs.total_out; 133 return (deflateEnd(&zs)); 134 } 135 136 int 137 z_compress(void *dst, size_t *dstlen, const void *src, size_t srclen) 138 { 139 return (z_compress_level(dst, dstlen, src, srclen, 140 Z_DEFAULT_COMPRESSION)); 141 } 142 143 /* 144 * Convert a zlib error code into a string error message. 145 */ 146 const char * 147 z_strerror(int err) 148 { 149 int i = Z_NEED_DICT - err; 150 151 if (i < 0 || i > Z_NEED_DICT - Z_VERSION_ERROR) 152 return ("unknown error"); 153 154 return (zError(err)); 155 } 156