[RFC] geom_uncompress(4) changes

Luiz Otavio O Souza lists.br at gmail.com
Tue Apr 29 11:50:03 UTC 2014


Hi,

I've the attached changes to geom_uncompress(4) that modularise the
compression support.

It can now be built with support to mkuzip(8) or mkulzma(8) (or both)
independently.

It also make a lot easier to add the support to new compression
methods on geom_uncompress.

Now, building a kernel with 'options GEOM_UNCOMPRESS' (kept for
backward compatibility) adds only the support to read mkulzma images.

Building a kernel with 'options GEOM_UNCOMPRESS_UZIP' will add the
support to read mkuzip images.

The both options can be combined and they will produce a kernel which
can read both formats.

The geom_uncompress module is built with both compression methods
enabled keeping the backward compatibility.

I think we could eventually retire geom_uzip(8) as they are doing
essentially the same thing (with the same implementation and code...).
But this lets a lot of open questions regarding backward
compatibility.

Regards,
Luiz
-------------- next part --------------
Index: sys/conf/files
===================================================================
--- sys/conf/files	(revision 265013)
+++ sys/conf/files	(working copy)
@@ -2742,7 +2742,9 @@
 geom/raid3/g_raid3_ctl.c	optional geom_raid3
 geom/shsec/g_shsec.c		optional geom_shsec
 geom/stripe/g_stripe.c		optional geom_stripe
-geom/uncompress/g_uncompress.c	optional geom_uncompress
+geom/uncompress/g_uncompress.c	optional geom_uncompress | geom_uncompress_uzip
+geom/uncompress/g_uncompress_ulzma.c	optional geom_uncompress
+geom/uncompress/g_uncompress_uzip.c	optional geom_uncompress_uzip
 contrib/xz-embedded/freebsd/xz_malloc.c	\
 	optional xz_embedded | geom_uncompress \
 	compile-with "${NORMAL_C} -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
@@ -3139,7 +3141,7 @@
 net/vnet.c			optional vimage
 net/zlib.c			optional crypto | geom_uzip | ipsec | \
 					 mxge | netgraph_deflate | \
-					 ddb_ctf | gzio | geom_uncompress
+					 ddb_ctf | gzio | geom_uncompress_uzip
 net80211/ieee80211.c		optional wlan
 net80211/ieee80211_acl.c	optional wlan wlan_acl
 net80211/ieee80211_action.c	optional wlan
Index: sys/conf/options
===================================================================
--- sys/conf/options	(revision 265013)
+++ sys/conf/options	(working copy)
@@ -124,6 +124,7 @@
 GEOM_STRIPE	opt_geom.h
 GEOM_SUNLABEL	opt_geom.h
 GEOM_UNCOMPRESS	opt_geom.h
+GEOM_UNCOMPRESS_UZIP	opt_geom.h
 GEOM_UZIP	opt_geom.h
 GEOM_VIRSTOR	opt_geom.h
 GEOM_VOL	opt_geom.h
Index: sys/geom/uncompress/g_uncompress.c
===================================================================
--- sys/geom/uncompress/g_uncompress.c	(revision 265013)
+++ sys/geom/uncompress/g_uncompress.c	(working copy)
@@ -27,15 +27,19 @@
 
 /*
  * GEOM UNCOMPRESS module - simple decompression module for use with read-only
- * copressed images maked by mkuzip(8) or mkulzma(8) utilities.
+ * compressed images created by mkuzip(8) or mkulzma(8) utilities.
  *
- * To enable module in kernel config, put this line:
- * device	geom_uncompress
+ * To enable uncompress support in kernel config, add these lines (for ulzma
+ * and uzip support respectively):
+ * options	geom_uncompress
+ * options	geom_uncompress_uzip
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_geom.h"
+
 #include <sys/param.h>
 #include <sys/bio.h>
 #include <sys/endian.h>
@@ -47,10 +51,8 @@
 #include <sys/systm.h>
 
 #include <geom/geom.h>
+#include <geom/uncompress/g_uncompress.h>
 
-#include <net/zlib.h>
-#include <contrib/xz-embedded/linux/include/linux/xz.h>
-
 #ifdef GEOM_UNCOMPRESS_DEBUG
 #define	DPRINTF(a)	printf a
 extern int g_debugflags;
@@ -58,12 +60,10 @@
 #define	DPRINTF(a)
 #endif
 
-static MALLOC_DEFINE(M_GEOM_UNCOMPRESS, "geom_uncompress",
+MALLOC_DEFINE(M_GEOM_UNCOMPRESS, "geom_uncompress",
     "GEOM UNCOMPRESS data structures");
 
 #define	UNCOMPRESS_CLASS_NAME	"UNCOMPRESS"
-#define	GEOM_UZIP_MAJVER '2'
-#define	GEOM_ULZMA_MAJVER '3'
 
 /*
  * Maximum allowed valid block size (to prevent foot-shooting)
@@ -71,28 +71,17 @@
 #define	MAX_BLKSZ	(MAXPHYS)
 
 /*
- * Integer values (block size, number of blocks, offsets)
- * are stored in big-endian (network) order on disk and struct cloop_header
- * and in native order in struct g_uncompress_softc
+ * Integer values (block size, number of blocks, offsets) are stored in native
+ * order in struct g_uncompress_softc.
  */
 
-#define	CLOOP_MAGIC_LEN	128
 static char CLOOP_MAGIC_START[] = "#!/bin/sh\n";
 
-struct cloop_header {
-	char magic[CLOOP_MAGIC_LEN];	/* cloop magic */
-	uint32_t blksz;			/* block size */
-	uint32_t nblocks;		/* number of blocks */
-};
-
 struct g_uncompress_softc {
 	uint32_t blksz;			/* block size */
 	uint32_t nblocks;		/* number of blocks */
 	uint64_t *offsets;
-	enum {
-		GEOM_UZIP = 1,
-		GEOM_ULZMA
-	} type;
+	int type;
 
 	struct mtx last_mtx;
 	uint32_t last_blk;		/* last blk no */
@@ -99,11 +88,16 @@
 	char *last_buf;			/* last blk data */
 	int req_total;			/* total requests */
 	int req_cached;			/* cached requests */
+};
 
-	/* XZ decoder structs */
-	struct xz_buf *b;
-	struct xz_dec *s;
-	z_stream *zs;
+static struct g_uncompress_desc *g_uncompress[] = {
+#ifdef GEOM_UNCOMPRESS
+	&g_uncompress_ulzma,
+#endif
+#ifdef GEOM_UNCOMPRESS_UZIP
+	&g_uncompress_uzip,
+#endif
+	NULL
 };
 
 static void
@@ -119,25 +113,8 @@
 		sc->offsets = 0;
 	}
 
-	switch (sc->type) {
-	case GEOM_ULZMA:
-		if (sc->b) {
-			free(sc->b, M_GEOM_UNCOMPRESS);
-			sc->b = 0;
-		}
-		if (sc->s) {
-			xz_dec_end(sc->s);
-			sc->s = 0;
-		}
-		break;
-	case GEOM_UZIP:
-		if (sc->zs) {
-			inflateEnd(sc->zs);
-			free(sc->zs, M_GEOM_UNCOMPRESS);
-			sc->zs = 0;
-		}
-		break;
-	}
+	/* Call the free method. */
+	g_uncompress[sc->type]->d_free(g_uncompress[sc->type]);
 
 	mtx_destroy(&sc->last_mtx);
 	free(sc->last_buf, M_GEOM_UNCOMPRESS);
@@ -144,23 +121,7 @@
 	free(sc, M_GEOM_UNCOMPRESS);
 }
 
-static void *
-z_alloc(void *nil, u_int type, u_int size)
-{
-	void *ptr;
-
-	ptr = malloc(type * size, M_GEOM_UNCOMPRESS, M_NOWAIT);
-	return (ptr);
-}
-
 static void
-z_free(void *nil, void *ptr)
-{
-
-	free(ptr, M_GEOM_UNCOMPRESS);
-}
-
-static void
 g_uncompress_done(struct bio *bp)
 {
 	struct g_uncompress_softc *sc;
@@ -254,33 +215,9 @@
 			hexdump(bp->bio_data + pos, dlen, 0, 0);
 #endif
 
-		switch (sc->type) {
-		case GEOM_ULZMA:
-			sc->b->in = bp->bio_data + pos;
-			sc->b->out = sc->last_buf;
-			sc->b->in_pos = sc->b->out_pos = 0;
-			sc->b->in_size = dlen;
-			sc->b->out_size = (size_t)-1;
-
-			err = (xz_dec_run(sc->s, sc->b) != XZ_STREAM_END) ?
-			    1 : 0;
-			/* TODO decoder recovery, if needed */
-			break;
-		case GEOM_UZIP:
-			sc->zs->next_in = bp->bio_data + pos;
-			sc->zs->avail_in = dlen;
-			sc->zs->next_out = sc->last_buf;
-			sc->zs->avail_out = sc->blksz;
-
-			err = (inflate(sc->zs, Z_FINISH) != Z_STREAM_END) ?
-			    1 : 0;
-			if ((err) || (inflateReset(sc->zs) != Z_OK))
-				printf("%s: UZIP decoder reset failed\n",
-				     gp->name);
-			break;
-		}
-
-		if (err) {
+		if (g_uncompress[sc->type]->d_decom(g_uncompress[sc->type],
+		    gp->name, bp->bio_data + pos, len, sc->last_buf,
+		    sc->blksz) != 0) {
 			sc->last_blk = -1;
 			mtx_unlock(&sc->last_mtx);
 			DPRINTF(("%s: done: inflate failed, code=%d\n",
@@ -291,7 +228,7 @@
 
 #ifdef GEOM_UNCOMPRESS_DEBUG
 		if (g_debugflags & 32)
-			hexdump(sc->last_buf, sc->b->out_size, 0, 0);
+			hexdump(sc->last_buf, sc->blksz, 0, 0);
 #endif
 
 		sc->last_blk = i;
@@ -521,24 +458,16 @@
 		goto err;
 	}
 
-	switch (header->magic[0x0b]) {
-	case 'L':
-		type = GEOM_ULZMA;
-		if (header->magic[0x0c] < GEOM_ULZMA_MAJVER) {
-			DPRINTF(("%s: image version too old\n", gp->name));
+	for (i = 0; g_uncompress[i] != NULL; i++) {
+		error = g_uncompress[i]->d_taste(header, gp->name);
+		if (error == 1) {
+			/* Match. */
+			type = i;
+			break;
+		} else if (error == -1)
 			goto err;
-		}
-		printf("%s: GEOM_ULZMA image found\n", gp->name);
-		break;
-	case 'V':
-		type = GEOM_UZIP;
-		if (header->magic[0x0c] < GEOM_UZIP_MAJVER) {
-			DPRINTF(("%s: image version too old\n", gp->name));
-			goto err;
-		}
-		printf("%s: GEOM_UZIP image found\n", gp->name);
-		break;
-	default:
+	}
+	if (g_uncompress[i] == NULL) {
 		DPRINTF(("%s: unsupported image type\n", gp->name));
 		goto err;
 	}
@@ -588,23 +517,9 @@
 	sc->req_total = 0;
 	sc->req_cached = 0;
 
-	switch (sc->type) {
-	case GEOM_ULZMA:
-		xz_crc32_init();
-		sc->s = xz_dec_init(XZ_SINGLE, 0);
-		sc->b = (struct xz_buf*)malloc(sizeof(struct xz_buf),
-		    M_GEOM_UNCOMPRESS, M_WAITOK);
-		break;
-	case GEOM_UZIP:
-		sc->zs = (z_stream *)malloc(sizeof(z_stream),
-		    M_GEOM_UNCOMPRESS, M_WAITOK);
-		sc->zs->zalloc = z_alloc;
-		sc->zs->zfree = z_free;
-		if (inflateInit(sc->zs) != Z_OK) {
-			goto err;
-		}
-		break;
-	}
+	/* Initialize the compression method. */
+	if (g_uncompress[sc->type]->d_init(g_uncompress[sc->type]) != 0)
+		goto err;
 
 	g_topology_lock();
 	pp2 = g_new_providerf(gp, "%s", gp->name);
Index: sys/modules/geom/geom_uncompress/Makefile
===================================================================
--- sys/modules/geom/geom_uncompress/Makefile	(revision 265013)
+++ sys/modules/geom/geom_uncompress/Makefile	(working copy)
@@ -10,8 +10,9 @@
 CFLAGS+= -I${.CURDIR}/../../../geom/uncompress/ \
 	-I${.CURDIR}/../../../contrib/xz-embedded/freebsd \
 	-I${.CURDIR}/../../../contrib/xz-embedded/linux/lib/xz/
-SRCS=	g_uncompress.c xz_crc32.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c \
-    xz_malloc.c
+CFLAGS+=-DGEOM_UNCOMPRESS -DGEOM_UNCOMPRESS_UZIP
+SRCS=	g_uncompress.c g_uncompress_ulzma.c g_uncompress_uzip.c opt_geom.h
+SRCS+=	xz_crc32.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c xz_malloc.c
 SRCS+=	xz.h xz_config.h xz_lzma2.h xz_malloc.h xz_private.h xz_stream.h
 
 .include <bsd.kmod.mk>
--- /dev/null	2014-04-27 10:33:00.000000000 -0300
+++ sys/geom/uncompress/g_uncompress.h	2014-04-26 16:18:34.821549524 -0300
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2010-2012 Aleksandr Rybalko
+ * Copyright (c) 2004 Max Khon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _G_UNCOMPRESS_H_
+#define _G_UNCOMPRESS_H_
+
+MALLOC_DECLARE(M_GEOM_UNCOMPRESS);
+
+#define	CLOOP_MAGIC_LEN	128
+#define	CLOOP_TYPE	0x0b
+#define	CLOOP_VERSION	0x0c
+
+/*
+ * Integer values (block size, number of blocks, offsets) are stored in
+ * big-endian (network) order on disk and struct cloop_header.
+ */
+struct cloop_header {
+	char magic[CLOOP_MAGIC_LEN];	/* cloop magic */
+	uint32_t blksz;			/* block size */
+	uint32_t nblocks;		/* number of blocks */
+}; 
+
+struct g_uncompress_desc;
+
+typedef int g_uncompress_decom_t (struct g_uncompress_desc *, char *,
+	caddr_t, off_t, caddr_t, off_t);
+typedef void g_uncompress_free_t (struct g_uncompress_desc *);
+typedef int g_uncompress_init_t (struct g_uncompress_desc *);
+typedef int g_uncompress_taste_t (struct cloop_header *, char *);
+
+struct g_uncompress_desc {
+	void			*d_data;
+	g_uncompress_decom_t	*d_decom;
+	g_uncompress_free_t	*d_free;
+	g_uncompress_init_t	*d_init;
+	g_uncompress_taste_t	*d_taste;
+};
+
+/* Supported compression methods. */
+#ifdef GEOM_UNCOMPRESS
+extern struct g_uncompress_desc g_uncompress_ulzma;
+#endif
+#ifdef GEOM_UNCOMPRESS_UZIP
+extern struct g_uncompress_desc g_uncompress_uzip;
+#endif
+
+#endif /* _G_UNCOMPRESS_H_ */
--- /dev/null	2014-04-27 10:33:00.000000000 -0300
+++ sys/geom/uncompress/g_uncompress_ulzma.c	2014-04-26 16:19:04.003547710 -0300
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 2010-2012 Aleksandr Rybalko
+ * Copyright (c) 2004 Max Khon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * GEOM ULZMA module - simple decompression module for use with read-only
+ * compressed images created by mkulzma(8).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <geom/uncompress/g_uncompress.h>
+
+#include <contrib/xz-embedded/linux/include/linux/xz.h>
+
+#define	GEOM_ULZMA_MAJVER	'3'
+
+struct g_uncompress_ulzma_softc {
+	/* XZ decoder structs */
+	struct xz_buf *b;
+	struct xz_dec *s;
+};
+
+static void
+g_uncompress_ulzma_free(struct g_uncompress_desc *uncompress)
+{
+	struct g_uncompress_ulzma_softc *sc;
+                
+	sc = (struct g_uncompress_ulzma_softc *)uncompress->d_data;
+	if (sc) {
+		if (sc->b) {
+			free(sc->b, M_GEOM_UNCOMPRESS);
+			sc->b = NULL;
+		}
+		if (sc->s) {
+			xz_dec_end(sc->s);
+			sc->s = NULL;
+		}
+		free(sc, M_GEOM_UNCOMPRESS);
+		uncompress->d_data = NULL;
+	}
+}
+
+static int
+g_uncompress_ulzma_init(struct g_uncompress_desc *uncompress)
+{
+	struct g_uncompress_ulzma_softc *sc;
+
+	sc = (struct g_uncompress_ulzma_softc *)malloc(sizeof(*sc),
+	    M_GEOM_UNCOMPRESS, M_WAITOK | M_ZERO);
+	xz_crc32_init();
+	sc->s = xz_dec_init(XZ_SINGLE, 0);
+	sc->b = (struct xz_buf *)malloc(sizeof(struct xz_buf),
+	    M_GEOM_UNCOMPRESS, M_WAITOK);
+
+	uncompress->d_data = (void *)sc;
+
+	return (0);
+}
+
+static int
+g_uncompress_ulzma_decom(struct g_uncompress_desc *uncompress, char *provider,
+	caddr_t in, off_t inlen, caddr_t out, off_t outlen)
+{
+	struct g_uncompress_ulzma_softc *sc;
+
+	sc = (struct g_uncompress_ulzma_softc *)uncompress->d_data;
+	sc->b->in = in;
+	sc->b->out = out;
+	sc->b->in_pos = sc->b->out_pos = 0;
+	sc->b->in_size = inlen;
+	sc->b->out_size = (size_t)-1;
+
+	if (xz_dec_run(sc->s, sc->b) != XZ_STREAM_END)
+		return (-1);
+
+	return (0);
+}
+
+static int
+g_uncompress_ulzma_taste(struct cloop_header *header, char *provider)
+{       
+
+	if (header->magic[CLOOP_TYPE] != 'L')
+		return (0);
+	if (header->magic[CLOOP_VERSION] < GEOM_ULZMA_MAJVER) {
+		printf("%s: image version too old\n", provider);
+		return (-1);
+	}
+	printf("%s: GEOM_ULZMA image found\n", provider);
+
+	return (1);
+}
+
+struct g_uncompress_desc g_uncompress_ulzma = {
+	.d_decom = g_uncompress_ulzma_decom,
+	.d_free = g_uncompress_ulzma_free,
+	.d_init = g_uncompress_ulzma_init,
+	.d_taste = g_uncompress_ulzma_taste,
+};
--- /dev/null	2014-04-27 10:33:00.000000000 -0300
+++ sys/geom/uncompress/g_uncompress_uzip.c	2014-04-26 16:40:11.413462855 -0300
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 2010-2012 Aleksandr Rybalko
+ * Copyright (c) 2004 Max Khon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * GEOM UZIP module - simple decompression module for use with read-only
+ * compressed images created by mkuzip(8).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <geom/uncompress/g_uncompress.h>
+
+#include <net/zlib.h>
+
+#define	GEOM_UZIP_MAJVER	'2'
+
+struct g_uncompress_uzip_softc {
+	z_stream *zs;
+};
+
+static void
+g_uncompress_uzip_free(struct g_uncompress_desc *uncompress)
+{
+	struct g_uncompress_uzip_softc *sc;
+
+	sc = (struct g_uncompress_uzip_softc *)uncompress->d_data;
+	if (sc) {
+		if (sc->zs) {
+			inflateEnd(sc->zs);
+			free(sc->zs, M_GEOM_UNCOMPRESS);
+			sc->zs = NULL;
+		}
+		free(sc, M_GEOM_UNCOMPRESS);
+		uncompress->d_data = NULL;
+	}
+}
+
+static void *
+z_alloc(void *nil, u_int type, u_int size)
+{
+	void *ptr;
+
+	ptr = malloc(type * size, M_GEOM_UNCOMPRESS, M_NOWAIT);
+	return (ptr);
+}
+
+static void
+z_free(void *nil, void *ptr)
+{
+
+	free(ptr, M_GEOM_UNCOMPRESS);
+}
+
+static int
+g_uncompress_uzip_init(struct g_uncompress_desc *uncompress)
+{
+	struct g_uncompress_uzip_softc *sc;
+
+	sc = (struct g_uncompress_uzip_softc *)malloc(sizeof(*sc),
+	    M_GEOM_UNCOMPRESS, M_WAITOK | M_ZERO);
+	sc->zs = (z_stream *)malloc(sizeof(z_stream),
+	    M_GEOM_UNCOMPRESS, M_WAITOK);
+	sc->zs->zalloc = z_alloc;
+	sc->zs->zfree = z_free;
+	if (inflateInit(sc->zs) != Z_OK) {
+		free (sc->zs, M_GEOM_UNCOMPRESS);
+		free (sc, M_GEOM_UNCOMPRESS);
+		return (-1);
+	}
+
+	uncompress->d_data = (void *)sc;
+
+	return (0);
+}
+
+static int
+g_uncompress_uzip_decom(struct g_uncompress_desc *uncompress, char *provider,
+	caddr_t in, off_t inlen, caddr_t out, off_t outlen)
+{
+	int err;
+	struct g_uncompress_uzip_softc *sc;
+
+	sc = (struct g_uncompress_uzip_softc *)uncompress->d_data;
+	sc->zs->next_in = in;
+	sc->zs->avail_in = inlen;
+	sc->zs->next_out = out;
+	sc->zs->avail_out = outlen;
+
+	err = (inflate(sc->zs, Z_FINISH) != Z_STREAM_END) ?  1 : 0;
+	if (err || inflateReset(sc->zs) != Z_OK) {
+		printf("%s: UZIP decoder reset failed\n", provider);
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+g_uncompress_uzip_taste(struct cloop_header *header, char *provider)
+{
+
+	if (header->magic[CLOOP_TYPE] != 'V')
+		return (0);
+	if (header->magic[CLOOP_VERSION] < GEOM_UZIP_MAJVER) {
+		printf("%s: image version too old\n", provider);
+		return (-1);
+	}
+	printf("%s: GEOM_UZIP image found\n", provider);
+
+	return (1);
+}
+
+struct g_uncompress_desc g_uncompress_uzip = {
+	.d_decom = g_uncompress_uzip_decom,
+	.d_free = g_uncompress_uzip_free,
+	.d_init = g_uncompress_uzip_init,
+	.d_taste = g_uncompress_uzip_taste,
+};
Index: share/man/man4/geom_uncompress.4
===================================================================
--- share/man/man4/geom_uncompress.4	(revision 265013)
+++ share/man/man4/geom_uncompress.4	(working copy)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 9, 2014
+.Dd April 27, 2014
 .Dt GEOM_UNCOMPRESS 4
 .Os
 .Sh NAME
@@ -31,10 +31,11 @@
 .Nm geom_uncompress
 .Nd "GEOM based compressed disk images"
 .Sh SYNOPSIS
-To compile this driver into the kernel, place the following line in your
+To compile this driver into the kernel, place the following lines in your
 kernel configuration file:
 .Bd -ragged -offset indent
 .Cd "options GEOM_UNCOMPRESS"
+.Cd "options GEOM_UNCOMPRESS_UZIP"
 .Ed
 .Pp
 Alternatively, to load the driver as a module at boot time, place the
@@ -89,6 +90,18 @@
    Sectorsize: 512
    Mode: r1w0e0
 .Ed
+.Pp
+The compression support can be chosen in kernel configuration:
+.Bl -tag -width ".Sy options GEOM_UNCOMPRESS_UZIP"
+.It Sy options GEOM_UNCOMPRESS
+Enable the support for mkulzma(8) images.
+.It Sy options GEOM_UNCOMPRESS_UZIP
+Enable the support for mkuzip(8) images.
+.El
+.Pp
+The
+.Nm
+module is built with both compression methods enabled.
 .Sh SEE ALSO
 .Xr GEOM 4 ,
 .Xr md 4 ,


More information about the freebsd-geom mailing list