xref: /illumos-gate/usr/src/boot/libsa/zfs/gzip.c (revision 22028508)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2015 Toomas Soome <tsoome@me.com>
14  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
15  * Use is subject to license terms.
16  */
17 
18 #include <zlib.h>
19 #include <strings.h>
20 
21 int gzip_decompress(void *, void *, size_t, size_t, int);
22 /*
23  * Uncompress the buffer 'src' into the buffer 'dst'.  The caller must store
24  * the expected decompressed data size externally so it can be passed in.
25  * The resulting decompressed size is then returned through dstlen.  This
26  * function return Z_OK on success, or another error code on failure.
27  */
28 static int
z_uncompress(void * dst,size_t * dstlen,const void * src,size_t srclen)29 z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
30 {
31 	z_stream zs;
32 	int err;
33 
34 	bzero(&zs, sizeof (zs));
35 	zs.next_in = (unsigned char *)src;
36 	zs.avail_in = srclen;
37 	zs.next_out = dst;
38 	zs.avail_out = *dstlen;
39 
40 	/*
41 	 * Call inflateInit2() specifying a window size of DEF_WBITS
42 	 * with the 6th bit set to indicate that the compression format
43 	 * type (zlib or gzip) should be automatically detected.
44 	 */
45 	if ((err = inflateInit2(&zs, 15 | 0x20)) != Z_OK)
46 		return (err);
47 
48 	if ((err = inflate(&zs, Z_FINISH)) != Z_STREAM_END) {
49 		(void) inflateEnd(&zs);
50 		return (err == Z_OK ? Z_BUF_ERROR : err);
51 	}
52 
53 	*dstlen = zs.total_out;
54 	return (inflateEnd(&zs));
55 }
56 
57 int
gzip_decompress(void * s_start,void * d_start,size_t s_len,size_t d_len,int n __unused)58 gzip_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len,
59     int n __unused)
60 {
61 	size_t dstlen = d_len;
62 
63 	if (z_uncompress(d_start, &dstlen, s_start, s_len) != Z_OK)
64 		return (-1);
65 
66 	return (0);
67 }
68