diff options
| -rw-r--r-- | bin/sqfs2tar/Makemodule.am | 3 | ||||
| -rw-r--r-- | bin/tar2sqfs/Makemodule.am | 2 | ||||
| -rw-r--r-- | configure.ac | 14 | ||||
| -rw-r--r-- | include/fstream.h | 4 | ||||
| -rw-r--r-- | lib/fstream/Makemodule.am | 6 | ||||
| -rw-r--r-- | lib/fstream/compress/bzip2.c | 87 | ||||
| -rw-r--r-- | lib/fstream/compress/ostream_compressor.c | 5 | ||||
| -rw-r--r-- | lib/fstream/compressor.c | 10 | ||||
| -rw-r--r-- | lib/fstream/internal.h | 4 | ||||
| -rw-r--r-- | lib/fstream/uncompress/autodetect.c | 1 | ||||
| -rw-r--r-- | lib/fstream/uncompress/bzip2.c | 87 | ||||
| -rw-r--r-- | lib/fstream/uncompress/istream_compressor.c | 5 | 
12 files changed, 225 insertions, 3 deletions
diff --git a/bin/sqfs2tar/Makemodule.am b/bin/sqfs2tar/Makemodule.am index 9dbfbbb..a28c3b8 100644 --- a/bin/sqfs2tar/Makemodule.am +++ b/bin/sqfs2tar/Makemodule.am @@ -4,7 +4,8 @@ sqfs2tar_SOURCES += bin/sqfs2tar/xattr.c  sqfs2tar_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)  sqfs2tar_LDADD = libcommon.a libutil.a libsquashfs.la libtar.a  sqfs2tar_LDADD += libfstream.a libcompat.a libfstree.a -sqfs2tar_LDADD += $(ZLIB_LIBS) $(XZ_LIBS) $(LZO_LIBS) $(PTHREAD_LIBS) +sqfs2tar_LDADD += $(ZLIB_LIBS) $(XZ_LIBS) $(LZO_LIBS) $(BZIP2_LIBS) +sqfs2tar_LDADD += $(PTHREAD_LIBS)  if WITH_OWN_ZLIB  sqfs2tar_LDADD += libz.la diff --git a/bin/tar2sqfs/Makemodule.am b/bin/tar2sqfs/Makemodule.am index 58d1ef9..ce66e5c 100644 --- a/bin/tar2sqfs/Makemodule.am +++ b/bin/tar2sqfs/Makemodule.am @@ -3,7 +3,7 @@ tar2sqfs_SOURCES += bin/tar2sqfs/options.c bin/tar2sqfs/process_tarball.c  tar2sqfs_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)  tar2sqfs_LDADD = libcommon.a libsquashfs.la libtar.a libfstream.a  tar2sqfs_LDADD += libfstree.a libcompat.a libfstree.a $(LZO_LIBS) -tar2sqfs_LDADD += $(ZLIB_LIBS) $(XZ_LIBS) $(PTHREAD_LIBS) +tar2sqfs_LDADD += $(ZLIB_LIBS) $(XZ_LIBS) $(BZIP2_LIBS) $(PTHREAD_LIBS)  if WITH_OWN_ZLIB  tar2sqfs_LDADD += libz.la diff --git a/configure.ac b/configure.ac index b3bb300..3de1109 100644 --- a/configure.ac +++ b/configure.ac @@ -59,6 +59,11 @@ AM_CONDITIONAL([WINDOWS], [test "x$build_windows" = "xyes"])  ##### config options ##### +AC_ARG_WITH([bzip2], +	[AS_HELP_STRING([--with-bzip2], +			[Build with bzip2 compression support])], +	[], [with_bzip2="check"]) +  AC_ARG_WITH([xz],  	[AS_HELP_STRING([--with-xz], [Build with xz compression support])],  	[], [with_xz="check"]) @@ -138,6 +143,13 @@ fi  ##### search for dependencies ##### +AS_IF([test "x$with_bzip2" != "xno"], [ +	PKG_CHECK_MODULES(BZIP2, [bzip2], [with_bzip2="yes"], +			      [AS_IF([test "x$with_bzip2" != "xcheck"], +				     [AC_MSG_ERROR([cannot Bzip2 libs])], +				     [with_bzip2="no"])]) +], []) +  AS_IF([test "x$with_gzip" != "xno" -a "x$with_builtin_zlib" != "xyes"], [  	PKG_CHECK_MODULES(ZLIB, [zlib], [with_gzip="yes"],  				[AS_IF([test "x$with_gzip" != "xcheck"], @@ -206,6 +218,7 @@ AS_IF([test "x$with_pthread" != "xno"], [  			  [with_pthread="no"])])  ], []) +AM_CONDITIONAL([WITH_BZIP2], [test "x$with_bzip2" = "xyes"])  AM_CONDITIONAL([WITH_GZIP], [test "x$with_gzip" = "xyes"])  AM_CONDITIONAL([WITH_XZ], [test "x$with_xz" = "xyes"])  AM_CONDITIONAL([WITH_LZ4], [test "x$with_lz4" = "xyes"]) @@ -276,6 +289,7 @@ AC_MSG_RESULT([  	LZO support:       ${with_lzo}  	LZ4 support:       ${with_lz4}  	ZSTD support:      ${with_zstd} +	BZIP2 support:     ${with_bzip2}  	SELinux support:   ${with_selinux}  	Using pthreads:    ${with_pthread} diff --git a/include/fstream.h b/include/fstream.h index a934c95..8693fff 100644 --- a/include/fstream.h +++ b/include/fstream.h @@ -68,8 +68,10 @@ enum {  	FSTREAM_COMPRESSOR_ZSTD = 3, +	FSTREAM_COMPRESSOR_BZIP2 = 4, +  	FSTREAM_COMPRESSOR_MIN = 1, -	FSTREAM_COMPRESSOR_MAX = 3, +	FSTREAM_COMPRESSOR_MAX = 4,  };  #ifdef __cplusplus diff --git a/lib/fstream/Makemodule.am b/lib/fstream/Makemodule.am index 8a1254c..1834cb8 100644 --- a/lib/fstream/Makemodule.am +++ b/lib/fstream/Makemodule.am @@ -35,4 +35,10 @@ libfstream_a_SOURCES += lib/fstream/uncompress/zstd.c  libfstream_a_CPPFLAGS += -DWITH_ZSTD  endif +if WITH_BZIP2 +libfstream_a_SOURCES += lib/fstream/compress/bzip2.c +libfstream_a_SOURCES += lib/fstream/uncompress/bzip2.c +libfstream_a_CPPFLAGS += -DWITH_BZIP2 +endif +  noinst_LIBRARIES += libfstream.a diff --git a/lib/fstream/compress/bzip2.c b/lib/fstream/compress/bzip2.c new file mode 100644 index 0000000..3ca425a --- /dev/null +++ b/lib/fstream/compress/bzip2.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * bzip2.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "../internal.h" + +#include <bzlib.h> + +typedef struct { +	ostream_comp_t base; + +	bz_stream strm; +} ostream_bzip2_t; + +static int flush_inbuf(ostream_comp_t *base, bool finish) +{ +	ostream_bzip2_t *bzip2 = (ostream_bzip2_t *)base; +	size_t have; +	int ret; + +	bzip2->strm.next_in = (char *)base->inbuf; +	bzip2->strm.avail_in = base->inbuf_used; + +	for (;;) { +		bzip2->strm.next_out = (char *)base->outbuf; +		bzip2->strm.avail_out = sizeof(base->outbuf); + +		ret = BZ2_bzCompress(&bzip2->strm, finish ? BZ_FINISH : BZ_RUN); + +		if (ret < 0 && ret != BZ_OUTBUFF_FULL) { +			fprintf(stderr, "%s: internal error in bzip2 " +				"compressor.\n", +				base->wrapped->get_filename(base->wrapped)); +			return -1; +		} + +		have = sizeof(base->outbuf) - bzip2->strm.avail_out; + +		if (base->wrapped->append(base->wrapped, base->outbuf, have)) +			return -1; + +		if (ret == BZ_STREAM_END || ret == BZ_OUTBUFF_FULL || +		    bzip2->strm.avail_in == 0) { +			break; +		} +	} + +	if (bzip2->strm.avail_in > 0) { +		memmove(base->inbuf, bzip2->strm.next_in, +			bzip2->strm.avail_in); +	} + +	base->inbuf_used = bzip2->strm.avail_in; +	return 0; +} + +static void cleanup(ostream_comp_t *base) +{ +	ostream_bzip2_t *bzip2 = (ostream_bzip2_t *)base; + +	BZ2_bzCompressEnd(&bzip2->strm); +} + +ostream_comp_t *ostream_bzip2_create(const char *filename) +{ +	ostream_bzip2_t *bzip2 = calloc(1, sizeof(*bzip2)); +	ostream_comp_t *base = (ostream_comp_t *)bzip2; + +	if (bzip2 == NULL) { +		fprintf(stderr, "%s: creating bzip2 compressor: %s.\n", +			filename, strerror(errno)); +		return NULL; +	} + +	if (BZ2_bzCompressInit(&bzip2->strm, 9, 0, 30) != BZ_OK) { +		fprintf(stderr, "%s: error initializing bzip2 compressor.\n", +			filename); +		free(bzip2); +		return NULL; +	} + +	base->flush_inbuf = flush_inbuf; +	base->cleanup = cleanup; +	return base; +} diff --git a/lib/fstream/compress/ostream_compressor.c b/lib/fstream/compress/ostream_compressor.c index d1d55e1..7ea7919 100644 --- a/lib/fstream/compress/ostream_compressor.c +++ b/lib/fstream/compress/ostream_compressor.c @@ -82,6 +82,11 @@ ostream_t *ostream_compressor_create(ostream_t *strm, int comp_id)  		comp = ostream_zstd_create(strm->get_filename(strm));  #endif  		break; +	case FSTREAM_COMPRESSOR_BZIP2: +#ifdef WITH_BZIP2 +		comp = ostream_bzip2_create(strm->get_filename(strm)); +#endif +		break;  	default:  		break;  	} diff --git a/lib/fstream/compressor.c b/lib/fstream/compressor.c index 84a859c..903a5f7 100644 --- a/lib/fstream/compressor.c +++ b/lib/fstream/compressor.c @@ -17,6 +17,9 @@ int fstream_compressor_id_from_name(const char *name)  	if (strcmp(name, "zstd") == 0)  		return FSTREAM_COMPRESSOR_ZSTD; +	if (strcmp(name, "bzip2") == 0) +		return FSTREAM_COMPRESSOR_BZIP2; +  	return -1;  } @@ -31,6 +34,9 @@ const char *fstream_compressor_name_from_id(int id)  	if (id == FSTREAM_COMPRESSOR_ZSTD)  		return "zstd"; +	if (id == FSTREAM_COMPRESSOR_BZIP2) +		return "bzip2"; +  	return NULL;  } @@ -49,6 +55,10 @@ bool fstream_compressor_exists(int id)  	case FSTREAM_COMPRESSOR_ZSTD:  		return true;  #endif +#ifdef WITH_BZIP2 +	case FSTREAM_COMPRESSOR_BZIP2: +		return true; +#endif  	default:  		break;  	} diff --git a/lib/fstream/internal.h b/lib/fstream/internal.h index 83ecc64..2dc81e4 100644 --- a/lib/fstream/internal.h +++ b/lib/fstream/internal.h @@ -59,12 +59,16 @@ SQFS_INTERNAL ostream_comp_t *ostream_xz_create(const char *filename);  SQFS_INTERNAL ostream_comp_t *ostream_zstd_create(const char *filename); +SQFS_INTERNAL ostream_comp_t *ostream_bzip2_create(const char *filename); +  SQFS_INTERNAL istream_comp_t *istream_gzip_create(const char *filename);  SQFS_INTERNAL istream_comp_t *istream_xz_create(const char *filename);  SQFS_INTERNAL istream_comp_t *istream_zstd_create(const char *filename); +SQFS_INTERNAL istream_comp_t *istream_bzip2_create(const char *filename); +  #ifdef __cplusplus  }  #endif diff --git a/lib/fstream/uncompress/autodetect.c b/lib/fstream/uncompress/autodetect.c index b788518..61628f8 100644 --- a/lib/fstream/uncompress/autodetect.c +++ b/lib/fstream/uncompress/autodetect.c @@ -14,6 +14,7 @@ static const struct {  	{ FSTREAM_COMPRESSOR_GZIP, (const sqfs_u8 *)"\x1F\x8B\x08", 3 },  	{ FSTREAM_COMPRESSOR_XZ, (const sqfs_u8 *)("\xFD" "7zXZ"), 6 },  	{ FSTREAM_COMPRESSOR_ZSTD, (const sqfs_u8 *)"\x28\xB5\x2F\xFD", 4 }, +	{ FSTREAM_COMPRESSOR_BZIP2, (const sqfs_u8 *)"BZh", 3 },  };  int istream_detect_compressor(istream_t *strm, diff --git a/lib/fstream/uncompress/bzip2.c b/lib/fstream/uncompress/bzip2.c new file mode 100644 index 0000000..b5fae5c --- /dev/null +++ b/lib/fstream/uncompress/bzip2.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * bzip2.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "../internal.h" + +#include <bzlib.h> + +typedef struct { +	istream_comp_t base; + +	bz_stream strm; +} istream_bzip2_t; + +static int precache(istream_t *base) +{ +	istream_bzip2_t *bzip2 = (istream_bzip2_t *)base; +	istream_t *wrapped = ((istream_comp_t *)base)->wrapped; +	int ret; + +	for (;;) { +		ret = istream_precache(wrapped); +		if (ret != 0) +			return ret; + +		bzip2->strm.next_in = (char *)wrapped->buffer; +		bzip2->strm.avail_in = wrapped->buffer_used; + +		bzip2->strm.next_out = (char *)base->buffer + base->buffer_used; +		bzip2->strm.avail_out = BUFSZ - base->buffer_used; + +		if (bzip2->strm.avail_out < 1) +			break; + +		ret = BZ2_bzDecompress(&bzip2->strm); + +		if (ret < 0) { +			fprintf(stderr, "%s: internal error in bzip2 " +				"decompressor.\n", +				wrapped->get_filename(wrapped)); +			return -1; +		} + +		base->buffer_used = BUFSZ - bzip2->strm.avail_out; +		wrapped->buffer_offset = wrapped->buffer_used - +					 bzip2->strm.avail_in; + +		if (ret == BZ_STREAM_END) { +			base->eof = true; +			break; +		} +	} + +	return 0; +} + +static void cleanup(istream_comp_t *base) +{ +	istream_bzip2_t *bzip2 = (istream_bzip2_t *)base; + +	BZ2_bzDecompressEnd(&bzip2->strm); +} + +istream_comp_t *istream_bzip2_create(const char *filename) +{ +	istream_bzip2_t *bzip2 = calloc(1, sizeof(*bzip2)); +	istream_comp_t *base = (istream_comp_t *)bzip2; + +	if (bzip2 == NULL) { +		fprintf(stderr, "%s: creating bzip2 compressor: %s.\n", +			filename, strerror(errno)); +		return NULL; +	} + +	if (BZ2_bzDecompressInit(&bzip2->strm, 0, 0) != BZ_OK) { +		fprintf(stderr, "%s: error initializing bzip2 decompressor.\n", +			filename); +		free(bzip2); +		return NULL; +	} + +	((istream_t *)base)->precache = precache; +	base->cleanup = cleanup; +	return base; +} diff --git a/lib/fstream/uncompress/istream_compressor.c b/lib/fstream/uncompress/istream_compressor.c index 2262c9b..bc8ef39 100644 --- a/lib/fstream/uncompress/istream_compressor.c +++ b/lib/fstream/uncompress/istream_compressor.c @@ -44,6 +44,11 @@ istream_t *istream_compressor_create(istream_t *strm, int comp_id)  		comp = istream_zstd_create(strm->get_filename(strm));  #endif  		break; +	case FSTREAM_COMPRESSOR_BZIP2: +#ifdef WITH_BZIP2 +		comp = istream_bzip2_create(strm->get_filename(strm)); +#endif +		break;  	default:  		break;  	}  | 
