1303167Ssobomax/*-
2303167Ssobomax * Copyright (c) 2004 Max Khon
3303167Ssobomax * Copyright (c) 2014 Juniper Networks, Inc.
4303167Ssobomax * Copyright (c) 2006-2016 Maxim Sobolev <sobomax@FreeBSD.org>
5303167Ssobomax * All rights reserved.
6303167Ssobomax *
7303167Ssobomax * Redistribution and use in source and binary forms, with or without
8303167Ssobomax * modification, are permitted provided that the following conditions
9303167Ssobomax * are met:
10303167Ssobomax * 1. Redistributions of source code must retain the above copyright
11303167Ssobomax *    notice, this list of conditions and the following disclaimer.
12303167Ssobomax * 2. Redistributions in binary form must reproduce the above copyright
13303167Ssobomax *    notice, this list of conditions and the following disclaimer in the
14303167Ssobomax *    documentation and/or other materials provided with the distribution.
15303167Ssobomax *
16303167Ssobomax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17303167Ssobomax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18303167Ssobomax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19303167Ssobomax * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20303167Ssobomax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21303167Ssobomax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22303167Ssobomax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23303167Ssobomax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24303167Ssobomax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25303167Ssobomax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26303167Ssobomax * SUCH DAMAGE.
27303167Ssobomax */
28303167Ssobomax
29303167Ssobomax#include <sys/cdefs.h>
30303167Ssobomax__FBSDID("$FreeBSD$");
31303167Ssobomax
32303167Ssobomax#include <sys/types.h>
33303167Ssobomax#include <sys/systm.h>
34303167Ssobomax#include <sys/malloc.h>
35303167Ssobomax
36303167Ssobomax#include <net/zlib.h>
37303167Ssobomax
38303167Ssobomax#include <geom/uzip/g_uzip.h>
39303167Ssobomax#include <geom/uzip/g_uzip_dapi.h>
40303167Ssobomax#include <geom/uzip/g_uzip_zlib.h>
41303167Ssobomax
42303167Ssobomaxstruct g_uzip_zlib {
43303167Ssobomax	uint32_t blksz;
44303167Ssobomax	struct g_uzip_dapi pub;
45303167Ssobomax	/* Zlib decoder structs */
46303167Ssobomax	z_stream zs;
47303167Ssobomax};
48303167Ssobomax
49303167Ssobomaxstatic void *z_alloc(void *, u_int, u_int);
50303167Ssobomaxstatic void z_free(void *, void *);
51303167Ssobomaxstatic int g_uzip_zlib_rewind(struct g_uzip_dapi *, const char *);
52303167Ssobomax
53303167Ssobomaxstatic void
54303167Ssobomaxg_uzip_zlib_free(struct g_uzip_dapi *zpp)
55303167Ssobomax{
56303167Ssobomax	struct g_uzip_zlib *zp;
57303167Ssobomax
58303167Ssobomax	zp = (struct g_uzip_zlib *)zpp->pvt;
59303167Ssobomax	inflateEnd(&zp->zs);
60303167Ssobomax	free(zp, M_GEOM_UZIP);
61303167Ssobomax}
62303167Ssobomax
63303167Ssobomaxstatic int
64303167Ssobomaxg_uzip_zlib_decompress(struct g_uzip_dapi *zpp, const char *gp_name, void *ibp,
65303167Ssobomax    size_t ilen, void *obp)
66303167Ssobomax{
67303167Ssobomax	int err;
68303167Ssobomax	struct g_uzip_zlib *zp;
69303167Ssobomax
70303167Ssobomax	zp = (struct g_uzip_zlib *)zpp->pvt;
71303167Ssobomax
72303167Ssobomax	zp->zs.next_in = ibp;
73303167Ssobomax	zp->zs.avail_in = ilen;
74303167Ssobomax	zp->zs.next_out = obp;
75303167Ssobomax	zp->zs.avail_out = zp->blksz;
76303167Ssobomax
77303167Ssobomax	err = (inflate(&zp->zs, Z_FINISH) != Z_STREAM_END) ? 1 : 0;
78303167Ssobomax	if (err != 0) {
79303167Ssobomax		printf("%s: UZIP(zlib) inflate() failed\n", gp_name);
80303167Ssobomax	}
81303167Ssobomax	return (err);
82303167Ssobomax}
83303167Ssobomax
84303167Ssobomaxstatic int
85303167Ssobomaxg_uzip_zlib_rewind(struct g_uzip_dapi *zpp, const char *gp_name)
86303167Ssobomax{
87303167Ssobomax	int err;
88303167Ssobomax	struct g_uzip_zlib *zp;
89303167Ssobomax
90303167Ssobomax	zp = (struct g_uzip_zlib *)zpp->pvt;
91303167Ssobomax
92303167Ssobomax	err = 0;
93303167Ssobomax	if (inflateReset(&zp->zs) != Z_OK) {
94303167Ssobomax		printf("%s: UZIP(zlib) decoder reset failed\n", gp_name);
95303167Ssobomax		err = 1;
96303167Ssobomax	}
97303167Ssobomax	return (err);
98303167Ssobomax}
99303167Ssobomax
100303167Ssobomaxstatic int
101303167Ssobomaxz_compressBound(int len)
102303167Ssobomax{
103303167Ssobomax
104303167Ssobomax	return (len + (len >> 12) + (len >> 14) + 11);
105303167Ssobomax}
106303167Ssobomax
107303167Ssobomaxstruct g_uzip_dapi *
108303167Ssobomaxg_uzip_zlib_ctor(uint32_t blksz)
109303167Ssobomax{
110303167Ssobomax	struct g_uzip_zlib *zp;
111303167Ssobomax
112303167Ssobomax	zp = malloc(sizeof(struct g_uzip_zlib), M_GEOM_UZIP, M_WAITOK);
113303167Ssobomax	zp->zs.zalloc = z_alloc;
114303167Ssobomax	zp->zs.zfree = z_free;
115303167Ssobomax	if (inflateInit(&zp->zs) != Z_OK) {
116303167Ssobomax		goto e1;
117303167Ssobomax	}
118303167Ssobomax	zp->blksz = blksz;
119303167Ssobomax	zp->pub.max_blen = z_compressBound(blksz);
120303167Ssobomax	zp->pub.decompress = &g_uzip_zlib_decompress;
121303167Ssobomax	zp->pub.free = &g_uzip_zlib_free;
122303167Ssobomax	zp->pub.rewind = &g_uzip_zlib_rewind;
123303167Ssobomax	zp->pub.pvt = (void *)zp;
124303167Ssobomax	return (&zp->pub);
125303167Ssobomaxe1:
126303167Ssobomax	free(zp, M_GEOM_UZIP);
127303167Ssobomax	return (NULL);
128303167Ssobomax}
129303167Ssobomax
130303167Ssobomaxstatic void *
131303167Ssobomaxz_alloc(void *nil, u_int type, u_int size)
132303167Ssobomax{
133303167Ssobomax        void *ptr;
134303167Ssobomax
135303167Ssobomax        ptr = malloc(type * size, M_GEOM_UZIP, M_NOWAIT);
136303167Ssobomax
137303167Ssobomax        return (ptr);
138303167Ssobomax}
139303167Ssobomax
140303167Ssobomaxstatic void
141303167Ssobomaxz_free(void *nil, void *ptr)
142303167Ssobomax{
143303167Ssobomax
144303167Ssobomax        free(ptr, M_GEOM_UZIP);
145303167Ssobomax}
146