1
0
Fork 0

Adding upstream version 1.11.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-20 21:27:58 +01:00
parent 1b337df7d0
commit 34f7af7bd1
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
27 changed files with 614 additions and 442 deletions

View file

@ -1,3 +1,19 @@
2019-01-02 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.11 released.
* File_* renamed to Lzip_*.
* LZ_decompress_read: Don't return error until all data is read.
* decoder.c (LZd_decode_member): Decode truncated data until EOF.
* main.c: Don't allow mixing different operations (-d and -t).
* main.c: Check return value of close( infd ).
* main.c: Compile on DOS with DJGPP.
* lzlib.texi: Improved descriptions of '-0..-9', '-m' and '-s'.
Document that 'LZ_(de)compress_finish' can be called repeatedly.
* configure: Accept appending to CFLAGS, 'CFLAGS+=OPTIONS'.
* Makefile.in: Targets 'install-bin*' renamed to 'install-lib*'.
* Makefile.in: Targets 'install-bin*' now install minilzip.
* INSTALL: Document use of CFLAGS+='-D __USE_MINGW_ANSI_STDIO'.
2018-02-07 Antonio Diaz Diaz <antonio@gnu.org> 2018-02-07 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.10 released. * Version 1.10 released.
@ -188,7 +204,7 @@
* Version 0.1 released. * Version 0.1 released.
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This file is a collection of facts, and thus it is not copyrightable, This file is a collection of facts, and thus it is not copyrightable,
but just in case, you have unlimited permission to copy, distribute and but just in case, you have unlimited permission to copy, distribute and

22
INSTALL
View file

@ -1,10 +1,14 @@
Requirements Requirements
------------ ------------
You will need a C compiler. You will need a C compiler.
I use gcc 5.3.0 and 4.1.2, but the code should compile with any I use gcc 5.3.0 and 4.1.2, but the code should compile with any standards
standards compliant compiler. compliant compiler.
Gcc is available at http://gcc.gnu.org. Gcc is available at http://gcc.gnu.org.
The operating system must allow signal handlers read access to objects with
static storage duration so that the cleanup handler for Control-C can delete
the partial output file.
Procedure Procedure
--------- ---------
@ -23,6 +27,10 @@ the main archive.
cd lzlib[version] cd lzlib[version]
./configure ./configure
If you are compiling on MinGW, use:
./configure CFLAGS+='-D __USE_MINGW_ANSI_STDIO'
3. Run make. 3. Run make.
make make
@ -37,11 +45,13 @@ the main archive.
become the default in the future). become the default in the future).
You can install only the library, the info manual or the man page by You can install only the library, the info manual or the man page by
typing 'make install-bin', 'make install-info' or 'make install-man' typing 'make install-lib', 'make install-info' or 'make install-man'
respectively. respectively.
Instead of 'make install', you can type 'make install-as-lzip' to 'make install-bin' installs the minilzip program and its man page.
install the library and any data files and documentation, and link 'install-bin' installs a shared minilzip if the shared library has
been configured. Else it installs a static minilzip.
'make install-as-lzip' runs 'make install-bin' and then links
minilzip to the name 'lzip'. minilzip to the name 'lzip'.
@ -62,7 +72,7 @@ After running 'configure', you can run 'make' and 'make install' as
explained above. explained above.
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute and modify it.

View file

@ -15,7 +15,7 @@ objs = carg_parser.o main.o
.PHONY : all install install-bin install-info install-man \ .PHONY : all install install-bin install-info install-man \
install-strip install-compress install-strip-compress \ install-strip install-compress install-strip-compress \
install-bin-strip install-info-compress install-man-compress \ install-bin-strip install-info-compress install-man-compress \
install-as-lzip \ install-lib install-lib-strip uninstall-lib install-as-lzip \
uninstall uninstall-bin uninstall-info uninstall-man \ uninstall uninstall-bin uninstall-info uninstall-man \
doc info man check dist clean distclean doc info man check dist clean distclean
@ -78,12 +78,19 @@ Makefile : $(VPATH)/configure $(VPATH)/Makefile.in
check : $(progname) bbexample lzcheck check : $(progname) bbexample lzcheck
@$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion) @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion)
install : install-bin install-info install : install-lib install-info
install-strip : install-bin-strip install-info install-strip : install-lib-strip install-info
install-compress : install-bin install-info-compress install-compress : install-lib install-info-compress
install-strip-compress : install-bin-strip install-info-compress install-strip-compress : install-lib-strip install-info-compress
install-bin : all install-bin : all install-man
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
$(INSTALL_PROGRAM) ./$(progname_lzip) "$(DESTDIR)$(bindir)/$(progname)"
install-bin-strip : all
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install-bin
install-lib : all
if [ ! -d "$(DESTDIR)$(includedir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(includedir)" ; fi if [ ! -d "$(DESTDIR)$(includedir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(includedir)" ; fi
if [ ! -d "$(DESTDIR)$(libdir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(libdir)" ; fi if [ ! -d "$(DESTDIR)$(libdir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(libdir)" ; fi
$(INSTALL_DATA) $(VPATH)/$(libname)lib.h "$(DESTDIR)$(includedir)/$(libname)lib.h" $(INSTALL_DATA) $(VPATH)/$(libname)lib.h "$(DESTDIR)$(includedir)/$(libname)lib.h"
@ -104,8 +111,8 @@ install-bin : all
[ -x "$(LDCONFIG)" ] ; then "$(LDCONFIG)" -n "$(DESTDIR)$(libdir)" || true ; fi ; \ [ -x "$(LDCONFIG)" ] ; then "$(LDCONFIG)" -n "$(DESTDIR)$(libdir)" || true ; fi ; \
fi fi
install-bin-strip : all install-lib-strip : all
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install-bin $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install-lib
install-info : install-info :
if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi
@ -126,16 +133,16 @@ install-man :
install-man-compress : install-man install-man-compress : install-man
lzip -v -9 "$(DESTDIR)$(mandir)/man1/$(progname).1" lzip -v -9 "$(DESTDIR)$(mandir)/man1/$(progname).1"
install-as-lzip : install install-man install-as-lzip : install-bin
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
$(INSTALL_PROGRAM) ./$(progname_lzip) "$(DESTDIR)$(bindir)/$(progname)"
-rm -f "$(DESTDIR)$(bindir)/lzip" -rm -f "$(DESTDIR)$(bindir)/lzip"
cd "$(DESTDIR)$(bindir)" && ln -s $(progname) lzip cd "$(DESTDIR)$(bindir)" && ln -s $(progname) lzip
uninstall : uninstall-man uninstall-info uninstall-bin uninstall : uninstall-info uninstall-lib
uninstall-bin : uninstall-bin : uninstall-man
-rm -f "$(DESTDIR)$(bindir)/$(progname)" -rm -f "$(DESTDIR)$(bindir)/$(progname)"
uninstall-lib :
-rm -f "$(DESTDIR)$(includedir)/$(libname)lib.h" -rm -f "$(DESTDIR)$(includedir)/$(libname)lib.h"
-rm -f "$(DESTDIR)$(libdir)/lib$(libname).a" -rm -f "$(DESTDIR)$(libdir)/lib$(libname).a"
-rm -f "$(DESTDIR)$(libdir)/lib$(libname).so" -rm -f "$(DESTDIR)$(libdir)/lib$(libname).so"
@ -171,8 +178,8 @@ dist : doc
$(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/check.sh \
$(DISTNAME)/testsuite/test.txt \ $(DISTNAME)/testsuite/test.txt \
$(DISTNAME)/testsuite/test2.txt \ $(DISTNAME)/testsuite/test2.txt \
$(DISTNAME)/testsuite/test.txt.lz \ $(DISTNAME)/testsuite/test_sync.lz \
$(DISTNAME)/testsuite/test_sync.lz $(DISTNAME)/testsuite/test.txt.lz
rm -f $(DISTNAME) rm -f $(DISTNAME)
lzip -v -9 $(DISTNAME).tar lzip -v -9 $(DISTNAME).tar

44
NEWS
View file

@ -1,32 +1,30 @@
Changes in version 1.10: Changes in version 1.11:
The function 'LZ_compress_finish' now adjusts the dictionary size for In case of decompression error caused by corrupt or truncated data,
each member. LZ_decompress_read now does not signal the error immediately to the
application, but waits until all decoded bytes have been read. This
allows tools like tarlz to recover as much data as possible from damaged
members.
The option '--loose-trailing', has been added to minilzip. It is now an error to specify two different operations to minilzip in
the command line (--decompress and --test).
The test used by lzlib to discriminate trailing data from a corrupt Minilzip now also checks for errors when closing the input file.
header in multimember or concatenated files has been improved to a
Hamming distance (HD) of 3, and the 3 bit flips must happen in different
magic bytes for the test to fail. As a consequence, lzlib now returns a
data error when some kinds of files are appended to a lzip file as
trailing data.
The '--loose-trailing' option of minilzip can be used to ignore such
trailing data when decompressing.
Lziprecover can be used to remove conflicting trailing data from a file.
Option '-S, --volume-size' of minilzip now keeps input files unchanged. Minilzip now compiles on DOS with DJGPP. (Patch from Robert Riebisch).
The 'bits/byte' ratio has been replaced with the inverse compression The descriptions of '-0..-9', '-m' and '-s' in the manual have been
ratio in the output of minilzip. improved.
minilzip now shows a final diagnostic at verbosity level 1 (-v) or It has been documented that it is safe to call 'LZ_(de)compress_finish'
higher if any file fails the test when testing multiple files. as many times as needed. Examples in the manual have been simplified.
minilzip no longer adds a second '.lz' extension to the argument of '-o' The configure script now accepts appending options to CFLAGS using the
if it already ends in '.lz' or '.tlz'. syntax 'CFLAGS+=OPTIONS'.
minilzip now shows the dictionary size at verbosity level 4 (-vvvv) when Makefile targets 'install-bin*' have been renamed to 'install-lib*'. New
decompressing or testing. 'install-bin*' targets have been created that install a shared minilzip,
or a static minilzip if the shared library has not been configured.
The new chapter 'Invoking minilzip' has been added to the manual. It has been documented in INSTALL the use of
CFLAGS+='-D __USE_MINGW_ANSI_STDIO' when compiling on MinGW.

30
README
View file

@ -5,22 +5,21 @@ and decompression functions, including integrity checking of the
decompressed data. The compressed data format used by the library is the decompressed data. The compressed data format used by the library is the
lzip format. Lzlib is written in C. lzip format. Lzlib is written in C.
The lzip file format is designed for data sharing and long-term The lzip file format is designed for data sharing and long-term archiving,
archiving, taking into account both data integrity and decoder taking into account both data integrity and decoder availability:
availability:
* The lzip format provides very safe integrity checking and some data * The lzip format provides very safe integrity checking and some data
recovery means. The lziprecover program can repair bit-flip errors recovery means. The lziprecover program can repair bit flip errors
(one of the most common forms of data corruption) in lzip files, (one of the most common forms of data corruption) in lzip files,
and provides data recovery capabilities, including error-checked and provides data recovery capabilities, including error-checked
merging of damaged copies of a file. merging of damaged copies of a file.
* The lzip format is as simple as possible (but not simpler). The * The lzip format is as simple as possible (but not simpler). The
lzip manual provides the source code of a simple decompressor along lzip manual provides the source code of a simple decompressor
with a detailed explanation of how it works, so that with the only along with a detailed explanation of how it works, so that with
help of the lzip manual it would be possible for a digital the only help of the lzip manual it would be possible for a
archaeologist to extract the data from a lzip file long after digital archaeologist to extract the data from a lzip file long
quantum computers eventually render LZMA obsolete. after quantum computers eventually render LZMA obsolete.
* Additionally the lzip reference implementation is copylefted, which * Additionally the lzip reference implementation is copylefted, which
guarantees that it will remain free forever. guarantees that it will remain free forever.
@ -48,7 +47,8 @@ size equal to 0.
If all the data to be compressed are written in advance, lzlib will If all the data to be compressed are written in advance, lzlib will
automatically adjust the header of the compressed data to use the automatically adjust the header of the compressed data to use the
smallest possible dictionary size. This feature reduces the amount of largest dictionary size that does not exceed neither the data size nor
the limit given to LZ_compress_open. This feature reduces the amount of
memory needed for decompression and allows minilzip to produce identical memory needed for decompression and allows minilzip to produce identical
compressed output as lzip. compressed output as lzip.
@ -57,6 +57,10 @@ of two or more compressed data streams. The result is the concatenation
of the corresponding decompressed data streams. Integrity testing of of the corresponding decompressed data streams. Integrity testing of
concatenated compressed data streams is also supported. concatenated compressed data streams is also supported.
Lzlib is able to compress and decompress streams of unlimited size by
automatically creating multimember output. The members so created are
large, about 2 PiB each.
All the library functions are thread safe. The library does not install All the library functions are thread safe. The library does not install
any signal handler. The decoder checks the consistency of the compressed any signal handler. The decoder checks the consistency of the compressed
data, so the library should never crash even in case of corrupted input. data, so the library should never crash even in case of corrupted input.
@ -86,8 +90,12 @@ the definition of Markov chains), G.N.N. Martin (for the definition of
range encoding), Igor Pavlov (for putting all the above together in range encoding), Igor Pavlov (for putting all the above together in
LZMA), and Julian Seward (for bzip2's CLI). LZMA), and Julian Seward (for bzip2's CLI).
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
have been compressed. Decompressed is used to refer to data which have
undergone the process of decompression.
Copyright (C) 2009-2018 Antonio Diaz Diaz.
Copyright (C) 2009-2019 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute and modify it.

View file

@ -1,5 +1,5 @@
/* Buffer to buffer example - Test program for the lzlib library /* Buffer to buffer example - Test program for the lzlib library
Copyright (C) 2010-2018 Antonio Diaz Diaz. Copyright (C) 2010-2019 Antonio Diaz Diaz.
This program is free software: you have unlimited permission This program is free software: you have unlimited permission
to copy, distribute and modify it. to copy, distribute and modify it.
@ -26,10 +26,10 @@
/* Returns the address of a malloc'd buffer containing the file data and /* Returns the address of a malloc'd buffer containing the file data and
its size in '*size'. the file size in '*file_sizep'.
In case of error, returns 0 and does not modify '*size'. In case of error, returns 0 and does not modify '*file_sizep'.
*/ */
uint8_t * read_file( const char * const name, long * const size ) uint8_t * read_file( const char * const name, long * const file_sizep )
{ {
long buffer_size = 1 << 20, file_size; long buffer_size = 1 << 20, file_size;
uint8_t * buffer, * tmp; uint8_t * buffer, * tmp;
@ -67,7 +67,7 @@ uint8_t * read_file( const char * const name, long * const size )
free( buffer ); return 0; free( buffer ); return 0;
} }
fclose( f ); fclose( f );
*size = file_size; *file_sizep = file_size;
return buffer; return buffer;
} }

View file

@ -1,5 +1,5 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2018 Antonio Diaz Diaz. Copyright (C) 2006-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided

View file

@ -1,5 +1,5 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2018 Antonio Diaz Diaz. Copyright (C) 2006-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -25,9 +25,6 @@ struct Circular_buffer
unsigned put; unsigned put;
}; };
static inline void Cb_reset( struct Circular_buffer * const cb )
{ cb->get = 0; cb->put = 0; }
static inline bool Cb_init( struct Circular_buffer * const cb, static inline bool Cb_init( struct Circular_buffer * const cb,
const unsigned buf_size ) const unsigned buf_size )
{ {
@ -42,6 +39,12 @@ static inline bool Cb_init( struct Circular_buffer * const cb,
static inline void Cb_free( struct Circular_buffer * const cb ) static inline void Cb_free( struct Circular_buffer * const cb )
{ free( cb->buffer ); cb->buffer = 0; } { free( cb->buffer ); cb->buffer = 0; }
static inline void Cb_reset( struct Circular_buffer * const cb )
{ cb->get = 0; cb->put = 0; }
static inline unsigned Cb_empty( const struct Circular_buffer * const cb )
{ return cb->get == cb->put; }
static inline unsigned Cb_used_bytes( const struct Circular_buffer * const cb ) static inline unsigned Cb_used_bytes( const struct Circular_buffer * const cb )
{ return ( (cb->get <= cb->put) ? 0 : cb->buffer_size ) + cb->put - cb->get; } { return ( (cb->get <= cb->put) ? 0 : cb->buffer_size ) + cb->put - cb->get; }
@ -74,7 +77,8 @@ static bool Cb_unread_data( struct Circular_buffer * const cb,
/* Copies up to 'out_size' bytes to 'out_buffer' and updates 'get'. /* Copies up to 'out_size' bytes to 'out_buffer' and updates 'get'.
Returns the number of bytes copied. If 'out_buffer' is null, the bytes are discarded.
Returns the number of bytes copied or discarded.
*/ */
static unsigned Cb_read_data( struct Circular_buffer * const cb, static unsigned Cb_read_data( struct Circular_buffer * const cb,
uint8_t * const out_buffer, uint8_t * const out_buffer,
@ -87,7 +91,7 @@ static unsigned Cb_read_data( struct Circular_buffer * const cb,
size = min( cb->buffer_size - cb->get, out_size ); size = min( cb->buffer_size - cb->get, out_size );
if( size > 0 ) if( size > 0 )
{ {
memcpy( out_buffer, cb->buffer + cb->get, size ); if( out_buffer ) memcpy( out_buffer, cb->buffer + cb->get, size );
cb->get += size; cb->get += size;
if( cb->get >= cb->buffer_size ) cb->get = 0; if( cb->get >= cb->buffer_size ) cb->get = 0;
} }
@ -97,7 +101,7 @@ static unsigned Cb_read_data( struct Circular_buffer * const cb,
const unsigned size2 = min( cb->put - cb->get, out_size - size ); const unsigned size2 = min( cb->put - cb->get, out_size - size );
if( size2 > 0 ) if( size2 > 0 )
{ {
memcpy( out_buffer + size, cb->buffer + cb->get, size2 ); if( out_buffer ) memcpy( out_buffer + size, cb->buffer + cb->get, size2 );
cb->get += size2; cb->get += size2;
size += size2; size += size2;
} }

20
configure vendored
View file

@ -1,12 +1,12 @@
#! /bin/sh #! /bin/sh
# configure script for Lzlib - Compression library for the lzip format # configure script for Lzlib - Compression library for the lzip format
# Copyright (C) 2009-2018 Antonio Diaz Diaz. # Copyright (C) 2009-2019 Antonio Diaz Diaz.
# #
# This configure script is free software: you have unlimited permission # This configure script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute and modify it.
pkgname=lzlib pkgname=lzlib
pkgversion=1.10 pkgversion=1.11
soversion=1 soversion=1
progname=minilzip progname=minilzip
progname_static=${progname} progname_static=${progname}
@ -84,6 +84,7 @@ while [ $# != 0 ] ; do
echo " CC=COMPILER C compiler to use [${CC}]" echo " CC=COMPILER C compiler to use [${CC}]"
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]" echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]" echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]"
echo " CFLAGS+=OPTIONS append options to the current value of CFLAGS"
echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]" echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]"
echo echo
exit 0 ;; exit 0 ;;
@ -114,13 +115,16 @@ while [ $# != 0 ] ; do
progname_static= progname_static=
progname_shared=${progname}_shared progname_shared=${progname}_shared
progname_lzip=${progname}_shared ;; progname_lzip=${progname}_shared ;;
--enable-shared) progname_shared=${progname}_shared ;; --enable-shared)
progname_shared=${progname}_shared
progname_lzip=${progname}_shared ;;
--disable-ldconfig) disable_ldconfig=yes ;; --disable-ldconfig) disable_ldconfig=yes ;;
CC=*) CC=${optarg} ;; CC=*) CC=${optarg} ;;
CPPFLAGS=*) CPPFLAGS=${optarg} ;; CPPFLAGS=*) CPPFLAGS=${optarg} ;;
CFLAGS=*) CFLAGS=${optarg} ;; CFLAGS=*) CFLAGS=${optarg} ;;
LDFLAGS=*) LDFLAGS=${optarg} ;; CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;;
LDFLAGS=*) LDFLAGS=${optarg} ;;
--*) --*)
echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;; echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;;
@ -194,7 +198,7 @@ echo "LDFLAGS = ${LDFLAGS}"
rm -f Makefile rm -f Makefile
cat > Makefile << EOF cat > Makefile << EOF
# Makefile for Lzlib - Compression library for the lzip format # Makefile for Lzlib - Compression library for the lzip format
# Copyright (C) 2009-2018 Antonio Diaz Diaz. # Copyright (C) 2009-2019 Antonio Diaz Diaz.
# This file was generated automatically by configure. Don't edit. # This file was generated automatically by configure. Don't edit.
# #
# This Makefile is free software: you have unlimited permission # This Makefile is free software: you have unlimited permission

137
decoder.c
View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -19,16 +19,16 @@
static int LZd_try_verify_trailer( struct LZ_decoder * const d ) static int LZd_try_verify_trailer( struct LZ_decoder * const d )
{ {
File_trailer trailer; Lzip_trailer trailer;
if( Rd_available_bytes( d->rdec ) < Ft_size && !d->rdec->at_stream_end ) if( Rd_available_bytes( d->rdec ) < Lt_size && !d->rdec->at_stream_end )
return 0; return 0;
d->verify_trailer_pending = false; d->verify_trailer_pending = false;
d->member_finished = true; d->member_finished = true;
if( Rd_read_data( d->rdec, trailer, Ft_size ) == Ft_size && if( Rd_read_data( d->rdec, trailer, Lt_size ) == Lt_size &&
Ft_get_data_crc( trailer ) == LZd_crc( d ) && Lt_get_data_crc( trailer ) == LZd_crc( d ) &&
Ft_get_data_size( trailer ) == LZd_data_position( d ) && Lt_get_data_size( trailer ) == LZd_data_position( d ) &&
Ft_get_member_size( trailer ) == d->rdec->member_position ) return 0; Lt_get_member_size( trailer ) == d->rdec->member_position ) return 0;
return 3; return 3;
} }
@ -49,15 +49,18 @@ static int LZd_decode_member( struct LZ_decoder * const d )
while( !Rd_finished( rdec ) ) while( !Rd_finished( rdec ) )
{ {
int len;
const int pos_state = LZd_data_position( d ) & pos_state_mask; const int pos_state = LZd_data_position( d ) & pos_state_mask;
/* const unsigned mpos = d->rdec->member_position; /* const unsigned mpos = d->rdec->member_position;
if( mpos - old_mpos > rd_min_available_bytes ) return 5; if( mpos - old_mpos > rd_min_available_bytes ) return 5;
old_mpos = mpos; */ old_mpos = mpos; */
if( !Rd_enough_available_bytes( rdec ) ) /* check unexpected eof */ if( !Rd_enough_available_bytes( rdec ) ) /* check unexpected EOF */
{ if( !rdec->at_stream_end ) return 0; else break; } { if( !rdec->at_stream_end ) return 0;
if( Cb_empty( &rdec->cb ) ) break; } /* decode until EOF */
if( !LZd_enough_free_bytes( d ) ) return 0; if( !LZd_enough_free_bytes( d ) ) return 0;
if( Rd_decode_bit( rdec, &d->bm_match[*state][pos_state] ) == 0 ) /* 1st bit */ if( Rd_decode_bit( rdec, &d->bm_match[*state][pos_state] ) == 0 ) /* 1st bit */
{ {
/* literal byte */
Bit_model * const bm = d->bm_literal[get_lit_state(LZd_peek_prev( d ))]; Bit_model * const bm = d->bm_literal[get_lit_state(LZd_peek_prev( d ))];
if( St_is_char( *state ) ) if( St_is_char( *state ) )
{ {
@ -69,79 +72,77 @@ static int LZd_decode_member( struct LZ_decoder * const d )
*state -= ( *state < 10 ) ? 3 : 6; *state -= ( *state < 10 ) ? 3 : 6;
LZd_put_byte( d, Rd_decode_matched( rdec, bm, LZd_peek( d, d->rep0 ) ) ); LZd_put_byte( d, Rd_decode_matched( rdec, bm, LZd_peek( d, d->rep0 ) ) );
} }
continue;
} }
else /* match or repeated match */ /* match or repeated match */
if( Rd_decode_bit( rdec, &d->bm_rep[*state] ) != 0 ) /* 2nd bit */
{ {
int len; if( Rd_decode_bit( rdec, &d->bm_rep0[*state] ) == 0 ) /* 3rd bit */
if( Rd_decode_bit( rdec, &d->bm_rep[*state] ) != 0 ) /* 2nd bit */
{ {
if( Rd_decode_bit( rdec, &d->bm_rep0[*state] ) == 0 ) /* 3rd bit */ if( Rd_decode_bit( rdec, &d->bm_len[*state][pos_state] ) == 0 ) /* 4th bit */
{ { *state = St_set_short_rep( *state );
if( Rd_decode_bit( rdec, &d->bm_len[*state][pos_state] ) == 0 ) /* 4th bit */ LZd_put_byte( d, LZd_peek( d, d->rep0 ) ); continue; }
{ *state = St_set_short_rep( *state );
LZd_put_byte( d, LZd_peek( d, d->rep0 ) ); continue; }
}
else
{
unsigned distance;
if( Rd_decode_bit( rdec, &d->bm_rep1[*state] ) == 0 ) /* 4th bit */
distance = d->rep1;
else
{
if( Rd_decode_bit( rdec, &d->bm_rep2[*state] ) == 0 ) /* 5th bit */
distance = d->rep2;
else
{ distance = d->rep3; d->rep3 = d->rep2; }
d->rep2 = d->rep1;
}
d->rep1 = d->rep0;
d->rep0 = distance;
}
*state = St_set_rep( *state );
len = min_match_len + Rd_decode_len( rdec, &d->rep_len_model, pos_state );
} }
else /* match */ else
{ {
unsigned distance; unsigned distance;
len = min_match_len + Rd_decode_len( rdec, &d->match_len_model, pos_state ); if( Rd_decode_bit( rdec, &d->bm_rep1[*state] ) == 0 ) /* 4th bit */
distance = Rd_decode_tree6( rdec, d->bm_dis_slot[get_len_state(len)] ); distance = d->rep1;
if( distance >= start_dis_model ) else
{ {
const unsigned dis_slot = distance; if( Rd_decode_bit( rdec, &d->bm_rep2[*state] ) == 0 ) /* 5th bit */
const int direct_bits = ( dis_slot >> 1 ) - 1; distance = d->rep2;
distance = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
if( dis_slot < end_dis_model )
distance += Rd_decode_tree_reversed( rdec,
d->bm_dis + ( distance - dis_slot ), direct_bits );
else else
{ distance = d->rep3; d->rep3 = d->rep2; }
d->rep2 = d->rep1;
}
d->rep1 = d->rep0;
d->rep0 = distance;
}
*state = St_set_rep( *state );
len = min_match_len + Rd_decode_len( rdec, &d->rep_len_model, pos_state );
}
else /* match */
{
unsigned distance;
len = min_match_len + Rd_decode_len( rdec, &d->match_len_model, pos_state );
distance = Rd_decode_tree6( rdec, d->bm_dis_slot[get_len_state(len)] );
if( distance >= start_dis_model )
{
const unsigned dis_slot = distance;
const int direct_bits = ( dis_slot >> 1 ) - 1;
distance = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
if( dis_slot < end_dis_model )
distance += Rd_decode_tree_reversed( rdec,
d->bm_dis + ( distance - dis_slot ), direct_bits );
else
{
distance +=
Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;
distance += Rd_decode_tree_reversed4( rdec, d->bm_align );
if( distance == 0xFFFFFFFFU ) /* marker found */
{ {
distance += Rd_normalize( rdec );
Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits; if( len == min_match_len ) /* End Of Stream marker */
distance += Rd_decode_tree_reversed4( rdec, d->bm_align );
if( distance == 0xFFFFFFFFU ) /* marker found */
{ {
Rd_normalize( rdec ); d->verify_trailer_pending = true;
if( len == min_match_len ) /* End Of Stream marker */ return LZd_try_verify_trailer( d );
{
d->verify_trailer_pending = true;
return LZd_try_verify_trailer( d );
}
if( len == min_match_len + 1 ) /* Sync Flush marker */
{
if( Rd_try_reload( rdec, true ) ) { /*old_mpos += 5;*/ continue; }
else { if( !rdec->at_stream_end ) return 0; else break; }
}
return 4;
} }
if( len == min_match_len + 1 ) /* Sync Flush marker */
{
if( Rd_try_reload( rdec, true ) ) { /*old_mpos += 5;*/ continue; }
else { if( !rdec->at_stream_end ) return 0; else break; }
}
return 4;
} }
} }
d->rep3 = d->rep2; d->rep2 = d->rep1; d->rep1 = d->rep0; d->rep0 = distance;
*state = St_set_match( *state );
if( d->rep0 >= d->dictionary_size ||
( d->rep0 >= d->cb.put && !d->pos_wrapped ) ) return 1;
} }
LZd_copy_block( d, d->rep0, len ); d->rep3 = d->rep2; d->rep2 = d->rep1; d->rep1 = d->rep0; d->rep0 = distance;
*state = St_set_match( *state );
if( d->rep0 >= d->dictionary_size ||
( d->rep0 >= d->cb.put && !d->pos_wrapped ) ) return 1;
} }
LZd_copy_block( d, d->rep0, len );
} }
return 2; return 2;
} }

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -44,7 +44,7 @@ static inline void Rd_free( struct Range_decoder * const rdec )
{ Cb_free( &rdec->cb ); } { Cb_free( &rdec->cb ); }
static inline bool Rd_finished( const struct Range_decoder * const rdec ) static inline bool Rd_finished( const struct Range_decoder * const rdec )
{ return rdec->at_stream_end && !Cb_used_bytes( &rdec->cb ); } { return rdec->at_stream_end && Cb_empty( &rdec->cb ); }
static inline void Rd_finish( struct Range_decoder * const rdec ) static inline void Rd_finish( struct Range_decoder * const rdec )
{ rdec->at_stream_end = true; } { rdec->at_stream_end = true; }
@ -56,7 +56,7 @@ static inline unsigned Rd_available_bytes( const struct Range_decoder * const rd
{ return Cb_used_bytes( &rdec->cb ); } { return Cb_used_bytes( &rdec->cb ); }
static inline unsigned Rd_free_bytes( const struct Range_decoder * const rdec ) static inline unsigned Rd_free_bytes( const struct Range_decoder * const rdec )
{ if( rdec->at_stream_end ) return 0; return Cb_free_bytes( &rdec->cb ); } { return rdec->at_stream_end ? 0 : Cb_free_bytes( &rdec->cb ); }
static inline unsigned long long Rd_purge( struct Range_decoder * const rdec ) static inline unsigned long long Rd_purge( struct Range_decoder * const rdec )
{ {
@ -81,18 +81,18 @@ static bool Rd_find_header( struct Range_decoder * const rdec,
*skippedp = 0; *skippedp = 0;
while( rdec->cb.get != rdec->cb.put ) while( rdec->cb.get != rdec->cb.put )
{ {
if( rdec->cb.buffer[rdec->cb.get] == magic_string[0] ) if( rdec->cb.buffer[rdec->cb.get] == lzip_magic[0] )
{ {
unsigned get = rdec->cb.get; unsigned get = rdec->cb.get;
int i; int i;
File_header header; Lzip_header header;
for( i = 0; i < Fh_size; ++i ) for( i = 0; i < Lh_size; ++i )
{ {
if( get == rdec->cb.put ) return false; /* not enough data */ if( get == rdec->cb.put ) return false; /* not enough data */
header[i] = rdec->cb.buffer[get]; header[i] = rdec->cb.buffer[get];
if( ++get >= rdec->cb.buffer_size ) get = 0; if( ++get >= rdec->cb.buffer_size ) get = 0;
} }
if( Fh_verify( header ) ) return true; if( Lh_verify( header ) ) return true;
} }
if( ++rdec->cb.get >= rdec->cb.buffer_size ) rdec->cb.get = 0; if( ++rdec->cb.get >= rdec->cb.buffer_size ) rdec->cb.get = 0;
++*skippedp; ++*skippedp;
@ -110,6 +110,8 @@ static inline int Rd_write_data( struct Range_decoder * const rdec,
static inline uint8_t Rd_get_byte( struct Range_decoder * const rdec ) static inline uint8_t Rd_get_byte( struct Range_decoder * const rdec )
{ {
/* 0xFF avoids decoder error if member is truncated at EOS marker */
if( Rd_finished( rdec ) ) return 0xFF;
++rdec->member_position; ++rdec->member_position;
return Cb_get_byte( &rdec->cb ); return Cb_get_byte( &rdec->cb );
} }
@ -410,7 +412,7 @@ static inline void LZd_free( struct LZ_decoder * const d )
{ Cb_free( &d->cb ); } { Cb_free( &d->cb ); }
static inline bool LZd_member_finished( const struct LZ_decoder * const d ) static inline bool LZd_member_finished( const struct LZ_decoder * const d )
{ return ( d->member_finished && !Cb_used_bytes( &d->cb ) ); } { return ( d->member_finished && Cb_empty( &d->cb ) ); }
static inline unsigned LZd_crc( const struct LZ_decoder * const d ) static inline unsigned LZd_crc( const struct LZ_decoder * const d )
{ return d->crc ^ 0xFFFFFFFFU; } { return d->crc ^ 0xFFFFFFFFU; }

View file

@ -11,7 +11,7 @@ File: lzlib.info, Node: Top, Next: Introduction, Up: (dir)
Lzlib Manual Lzlib Manual
************ ************
This manual is for Lzlib (version 1.10, 7 February 2018). This manual is for Lzlib (version 1.11, 2 January 2019).
* Menu: * Menu:
@ -30,7 +30,7 @@ This manual is for Lzlib (version 1.10, 7 February 2018).
* Concept index:: Index of concepts * Concept index:: Index of concepts
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This manual is free documentation: you have unlimited permission to This manual is free documentation: you have unlimited permission to
copy, distribute and modify it. copy, distribute and modify it.
@ -41,10 +41,10 @@ File: lzlib.info, Node: Introduction, Next: Library version, Prev: Top, Up:
1 Introduction 1 Introduction
************** **************
Lzlib is a data compression library providing in-memory LZMA compression Lzlib is a data compression library providing in-memory LZMA
and decompression functions, including integrity checking of the compression and decompression functions, including integrity checking
decompressed data. The compressed data format used by the library is the of the decompressed data. The compressed data format used by the
lzip format. Lzlib is written in C. library is the lzip format. Lzlib is written in C.
The lzip file format is designed for data sharing and long-term The lzip file format is designed for data sharing and long-term
archiving, taking into account both data integrity and decoder archiving, taking into account both data integrity and decoder
@ -90,15 +90,20 @@ with a SIZE equal to 0.
If all the data to be compressed are written in advance, lzlib will If all the data to be compressed are written in advance, lzlib will
automatically adjust the header of the compressed data to use the automatically adjust the header of the compressed data to use the
smallest possible dictionary size. This feature reduces the amount of largest dictionary size that does not exceed neither the data size nor
memory needed for decompression and allows minilzip to produce identical the limit given to 'LZ_compress_open'. This feature reduces the amount
compressed output as lzip. of memory needed for decompression and allows minilzip to produce
identical compressed output as lzip.
Lzlib will correctly decompress a data stream which is the Lzlib will correctly decompress a data stream which is the
concatenation of two or more compressed data streams. The result is the concatenation of two or more compressed data streams. The result is the
concatenation of the corresponding decompressed data streams. Integrity concatenation of the corresponding decompressed data streams. Integrity
testing of concatenated compressed data streams is also supported. testing of concatenated compressed data streams is also supported.
Lzlib is able to compress and decompress streams of unlimited size by
automatically creating multimember output. The members so created are
large, about 2 PiB each.
All the library functions are thread safe. The library does not All the library functions are thread safe. The library does not
install any signal handler. The decoder checks the consistency of the install any signal handler. The decoder checks the consistency of the
compressed data, so the library should never crash even in case of compressed data, so the library should never crash even in case of
@ -253,11 +258,13 @@ calling 'LZ_compress_errno' before using it.
output as 'lzip -0'. (The dictionary size used will be rounded output as 'lzip -0'. (The dictionary size used will be rounded
upwards to 64 KiB). upwards to 64 KiB).
MEMBER_SIZE sets the member size limit in bytes. Minimum member MEMBER_SIZE sets the member size limit in bytes. Valid values
size limit is 100 kB. Small member size may degrade compression range from 100 kB to 2 PiB. Small member size may degrade
ratio, so use it only when needed. To produce a single-member data compression ratio, so use it only when needed. To produce a
stream, give MEMBER_SIZE a value larger than the amount of data to single-member data stream, give MEMBER_SIZE a value larger than
be produced, for example INT64_MAX. the amount of data to be produced. Values larger than 2 PiB will be
reduced to 2 PiB to prevent the uncompressed size of the member
from overflowing.
-- Function: int LZ_compress_close ( struct LZ_Encoder * const ENCODER -- Function: int LZ_compress_close ( struct LZ_Encoder * const ENCODER
) )
@ -270,6 +277,7 @@ calling 'LZ_compress_errno' before using it.
ENCODER ) ENCODER )
Use this function to tell 'lzlib' that all the data for this member Use this function to tell 'lzlib' that all the data for this member
have already been written (with the 'LZ_compress_write' function). have already been written (with the 'LZ_compress_write' function).
It is safe to call 'LZ_compress_finish' as many times as needed.
After all the produced compressed data have been read with After all the produced compressed data have been read with
'LZ_compress_read' and 'LZ_compress_member_finished' returns 1, a 'LZ_compress_read' and 'LZ_compress_member_finished' returns 1, a
new member can be started with 'LZ_compress_restart_member'. new member can be started with 'LZ_compress_restart_member'.
@ -322,7 +330,7 @@ calling 'LZ_compress_errno' before using it.
-- Function: enum LZ_Errno LZ_compress_errno ( struct LZ_Encoder * -- Function: enum LZ_Errno LZ_compress_errno ( struct LZ_Encoder *
const ENCODER ) const ENCODER )
Returns the current error code for ENCODER (*note Error codes::). Returns the current error code for ENCODER. *Note Error codes::.
-- Function: int LZ_compress_finished ( struct LZ_Encoder * const -- Function: int LZ_compress_finished ( struct LZ_Encoder * const
ENCODER ) ENCODER )
@ -388,7 +396,8 @@ verified by calling 'LZ_decompress_errno' before using it.
DECODER ) DECODER )
Use this function to tell 'lzlib' that all the data for this stream Use this function to tell 'lzlib' that all the data for this stream
have already been written (with the 'LZ_decompress_write' have already been written (with the 'LZ_decompress_write'
function). function). It is safe to call 'LZ_decompress_finish' as many
times as needed.
-- Function: int LZ_decompress_reset ( struct LZ_Decoder * const -- Function: int LZ_decompress_reset ( struct LZ_Decoder * const
DECODER ) DECODER )
@ -420,6 +429,12 @@ verified by calling 'LZ_decompress_errno' before using it.
'LZ_decompress_write' function. Note that reading less than SIZE 'LZ_decompress_write' function. Note that reading less than SIZE
bytes is not an error. bytes is not an error.
In case of decompression error caused by corrupt or truncated data,
'LZ_decompress_read' does not signal the error immediately to the
application, but waits until all decoded bytes have been read. This
allows tools like tarlz to recover as much data as possible from
each damaged member. *Note tarlz manual: (tarlz)Top.
-- Function: int LZ_decompress_write ( struct LZ_Decoder * const -- Function: int LZ_decompress_write ( struct LZ_Decoder * const
DECODER, uint8_t * const BUFFER, const int SIZE ) DECODER, uint8_t * const BUFFER, const int SIZE )
The 'LZ_decompress_write' function writes up to SIZE bytes from The 'LZ_decompress_write' function writes up to SIZE bytes from
@ -440,7 +455,7 @@ verified by calling 'LZ_decompress_errno' before using it.
-- Function: enum LZ_Errno LZ_decompress_errno ( struct LZ_Decoder * -- Function: enum LZ_Errno LZ_decompress_errno ( struct LZ_Decoder *
const DECODER ) const DECODER )
Returns the current error code for DECODER (*note Error codes::). Returns the current error code for DECODER. *Note Error codes::.
-- Function: int LZ_decompress_finished ( struct LZ_Decoder * const -- Function: int LZ_decompress_finished ( struct LZ_Decoder * const
DECODER ) DECODER )
@ -543,8 +558,8 @@ whether a call failed. If the call failed, then you can examine
file. file.
-- Constant: enum LZ_Errno LZ_library_error -- Constant: enum LZ_Errno LZ_library_error
A bug was detected in the library. Please, report it (*note A bug was detected in the library. Please, report it. *Note
Problems::). Problems::.
 
File: lzlib.info, Node: Error messages, Next: Invoking minilzip, Prev: Error codes, Up: Top File: lzlib.info, Node: Error messages, Next: Invoking minilzip, Prev: Error codes, Up: Top
@ -568,6 +583,9 @@ File: lzlib.info, Node: Invoking minilzip, Next: Data format, Prev: Error mes
9 Invoking minilzip 9 Invoking minilzip
******************* *******************
Minilzip is a test program for the lzlib compression library, fully
compatible with lzip 1.4 or newer.
The format for running minilzip is: The format for running minilzip is:
minilzip [OPTIONS] [FILES] minilzip [OPTIONS] [FILES]
@ -585,7 +603,7 @@ command line.
'-V' '-V'
'--version' '--version'
Print the version number of minilzip on the standard output and Print the version number of minilzip on the standard output and
exit. exit. This version number should be included in all bug reports.
'-a' '-a'
'--trailing-error' '--trailing-error'
@ -654,12 +672,14 @@ command line.
'-s BYTES' '-s BYTES'
'--dictionary-size=BYTES' '--dictionary-size=BYTES'
When compressing, set the dictionary size limit in bytes. Minilzip When compressing, set the dictionary size limit in bytes. Minilzip
will use the smallest possible dictionary size for each file will use for each file the largest dictionary size that does not
without exceeding this limit. Valid values range from 4 KiB to exceed neither the file size nor this limit. Valid values range
512 MiB. Values 12 to 29 are interpreted as powers of two, meaning from 4 KiB to 512 MiB. Values 12 to 29 are interpreted as powers
2^12 to 2^29 bytes. Note that dictionary sizes are quantized. If of two, meaning 2^12 to 2^29 bytes. Dictionary sizes are quantized
the specified size does not match one of the valid sizes, it will so that they can be coded in just one byte (*note
be rounded upwards by adding up to (BYTES / 8) to it. coded-dict-size::). If the specified size does not match one of
the valid sizes, it will be rounded upwards by adding up to
(BYTES / 8) to it.
For maximum compression you should use a dictionary size limit as For maximum compression you should use a dictionary size limit as
large as possible, but keep in mind that the decompression memory large as possible, but keep in mind that the decompression memory
@ -695,27 +715,32 @@ command line.
size, and trailer contents (CRC, data size, member size). size, and trailer contents (CRC, data size, member size).
'-0 .. -9' '-0 .. -9'
Set the compression parameters (dictionary size and match length Compression level. Set the compression parameters (dictionary size
limit) as shown in the table below. The default compression level and match length limit) as shown in the table below. The default
is '-6'. Note that '-9' can be much slower than '-0'. These compression level is '-6', equivalent to '-s8MiB -m36'. Note that
options have no effect when decompressing or testing. '-9' can be much slower than '-0'. These options have no effect
when decompressing or testing.
The bidimensional parameter space of LZMA can't be mapped to a The bidimensional parameter space of LZMA can't be mapped to a
linear scale optimal for all files. If your files are large, very linear scale optimal for all files. If your files are large, very
repetitive, etc, you may need to use the '--dictionary-size' and repetitive, etc, you may need to use the '--dictionary-size' and
'--match-length' options directly to achieve optimal performance. '--match-length' options directly to achieve optimal performance.
Level Dictionary size Match length limit If several compression levels or '-s' or '-m' options are given,
-0 64 KiB 16 bytes the last setting is used. For example '-9 -s64MiB' is equivalent
-1 1 MiB 5 bytes to '-s64MiB -m273'
-2 1.5 MiB 6 bytes
-3 2 MiB 8 bytes Level Dictionary size (-s) Match length limit (-m)
-4 3 MiB 12 bytes -0 64 KiB 16 bytes
-5 4 MiB 20 bytes -1 1 MiB 5 bytes
-6 8 MiB 36 bytes -2 1.5 MiB 6 bytes
-7 16 MiB 68 bytes -3 2 MiB 8 bytes
-8 24 MiB 132 bytes -4 3 MiB 12 bytes
-9 32 MiB 273 bytes -5 4 MiB 20 bytes
-6 8 MiB 36 bytes
-7 16 MiB 68 bytes
-8 24 MiB 132 bytes
-9 32 MiB 273 bytes
'--fast' '--fast'
'--best' '--best'
@ -795,11 +820,11 @@ stream, with no additional information before, between, or after them.
'DS (coded dictionary size, 1 byte)' 'DS (coded dictionary size, 1 byte)'
The dictionary size is calculated by taking a power of 2 (the base The dictionary size is calculated by taking a power of 2 (the base
size) and substracting from it a fraction between 0/16 and 7/16 of size) and subtracting from it a fraction between 0/16 and 7/16 of
the base size. the base size.
Bits 4-0 contain the base 2 logarithm of the base size (12 to 29). Bits 4-0 contain the base 2 logarithm of the base size (12 to 29).
Bits 7-5 contain the numerator of the fraction (0 to 7) to Bits 7-5 contain the numerator of the fraction (0 to 7) to subtract
substract from the base size to obtain the dictionary size. from the base size to obtain the dictionary size.
Example: 0xD3 = 2^19 - 6 * 2^15 = 512 KiB - 6 * 32 KiB = 320 KiB Example: 0xD3 = 2^19 - 6 * 2^15 = 512 KiB - 6 * 32 KiB = 320 KiB
Valid values for dictionary size range from 4 KiB to 512 MiB. Valid values for dictionary size range from 4 KiB to 512 MiB.
@ -845,12 +870,10 @@ Example 1: Normal compression (MEMBER_SIZE > total output).
1) LZ_compress_open 1) LZ_compress_open
2) LZ_compress_write 2) LZ_compress_write
3) LZ_compress_read 3) if no more data to write, call LZ_compress_finish
4) go back to step 2 until all input data have been written 4) LZ_compress_read
5) LZ_compress_finish 5) go back to step 2 until LZ_compress_finished returns 1
6) LZ_compress_read 6) LZ_compress_close
7) go back to step 6 until LZ_compress_finished returns 1
8) LZ_compress_close
Example 2: Normal compression using LZ_compress_write_size. Example 2: Normal compression using LZ_compress_write_size.
@ -868,12 +891,10 @@ Example 3: Decompression.
1) LZ_decompress_open 1) LZ_decompress_open
2) LZ_decompress_write 2) LZ_decompress_write
3) LZ_decompress_read 3) if no more data to write, call LZ_decompress_finish
4) go back to step 2 until all input data have been written 4) LZ_decompress_read
5) LZ_decompress_finish 5) go back to step 2 until LZ_decompress_finished returns 1
6) LZ_decompress_read 6) LZ_decompress_close
7) go back to step 6 until LZ_decompress_finished returns 1
8) LZ_decompress_close
Example 4: Decompression using LZ_decompress_write_size. Example 4: Decompression using LZ_decompress_write_size.
@ -988,20 +1009,21 @@ Concept index
 
Tag Table: Tag Table:
Node: Top220 Node: Top220
Node: Introduction1342 Node: Introduction1341
Node: Library version6154 Node: Library version6397
Node: Buffering6799 Node: Buffering7042
Node: Parameter limits8024 Node: Parameter limits8267
Node: Compression functions8983 Node: Compression functions9226
Node: Decompression functions15592 Node: Decompression functions16010
Node: Error codes21762 Node: Error codes22599
Node: Error messages24064 Node: Error messages24900
Node: Invoking minilzip24649 Node: Invoking minilzip25485
Ref: --trailing-error25243 Ref: --trailing-error26243
Node: Data format31883 Node: Data format33248
Node: Examples34454 Ref: coded-dict-size34557
Node: Problems38570 Node: Examples35817
Node: Concept index39142 Node: Problems39813
Node: Concept index40385
 
End Tag Table End Tag Table

View file

@ -6,8 +6,8 @@
@finalout @finalout
@c %**end of header @c %**end of header
@set UPDATED 7 February 2018 @set UPDATED 2 January 2019
@set VERSION 1.10 @set VERSION 1.11
@dircategory Data Compression @dircategory Data Compression
@direntry @direntry
@ -51,7 +51,7 @@ This manual is for Lzlib (version @value{VERSION}, @value{UPDATED}).
@end menu @end menu
@sp 1 @sp 1
Copyright @copyright{} 2009-2018 Antonio Diaz Diaz. Copyright @copyright{} 2009-2019 Antonio Diaz Diaz.
This manual is free documentation: you have unlimited permission This manual is free documentation: you have unlimited permission
to copy, distribute and modify it. to copy, distribute and modify it.
@ -61,14 +61,13 @@ to copy, distribute and modify it.
@chapter Introduction @chapter Introduction
@cindex introduction @cindex introduction
Lzlib is a data compression library providing in-memory LZMA compression @uref{http://www.nongnu.org/lzip/lzlib.html,,Lzlib} is a data compression
and decompression functions, including integrity checking of the library providing in-memory LZMA compression and decompression functions,
decompressed data. The compressed data format used by the library is the including integrity checking of the decompressed data. The compressed data
lzip format. Lzlib is written in C. format used by the library is the lzip format. Lzlib is written in C.
The lzip file format is designed for data sharing and long-term The lzip file format is designed for data sharing and long-term archiving,
archiving, taking into account both data integrity and decoder taking into account both data integrity and decoder availability:
availability:
@itemize @bullet @itemize @bullet
@item @item
@ -118,15 +117,20 @@ data to be compressed in advance, just call the read function with a
If all the data to be compressed are written in advance, lzlib will If all the data to be compressed are written in advance, lzlib will
automatically adjust the header of the compressed data to use the automatically adjust the header of the compressed data to use the
smallest possible dictionary size. This feature reduces the amount of largest dictionary size that does not exceed neither the data size nor
memory needed for decompression and allows minilzip to produce identical the limit given to @samp{LZ_compress_open}. This feature reduces the
compressed output as lzip. amount of memory needed for decompression and allows minilzip to produce
identical compressed output as lzip.
Lzlib will correctly decompress a data stream which is the concatenation Lzlib will correctly decompress a data stream which is the concatenation
of two or more compressed data streams. The result is the concatenation of two or more compressed data streams. The result is the concatenation
of the corresponding decompressed data streams. Integrity testing of of the corresponding decompressed data streams. Integrity testing of
concatenated compressed data streams is also supported. concatenated compressed data streams is also supported.
Lzlib is able to compress and decompress streams of unlimited size by
automatically creating multimember output. The members so created are
large, about @w{2 PiB} each.
All the library functions are thread safe. The library does not install All the library functions are thread safe. The library does not install
any signal handler. The decoder checks the consistency of the compressed any signal handler. The decoder checks the consistency of the compressed
data, so the library should never crash even in case of corrupted input. data, so the library should never crash even in case of corrupted input.
@ -286,11 +290,13 @@ fast variant of LZMA is chosen, which produces identical compressed
output as @code{lzip -0}. (The dictionary size used will be rounded output as @code{lzip -0}. (The dictionary size used will be rounded
upwards to @w{64 KiB}). upwards to @w{64 KiB}).
@var{member_size} sets the member size limit in bytes. Minimum member @var{member_size} sets the member size limit in bytes. Valid values
size limit is @w{100 kB}. Small member size may degrade compression range from @w{100 kB} to @w{2 PiB}. Small member size may degrade
ratio, so use it only when needed. To produce a single-member data compression ratio, so use it only when needed. To produce a
stream, give @var{member_size} a value larger than the amount of data to single-member data stream, give @var{member_size} a value larger than
be produced, for example INT64_MAX. the amount of data to be produced. Values larger than @w{2 PiB} will be
reduced to @w{2 PiB} to prevent the uncompressed size of the member from
overflowing.
@end deftypefun @end deftypefun
@ -305,6 +311,7 @@ longer be used as an argument to any LZ_compress function.
@deftypefun int LZ_compress_finish ( struct LZ_Encoder * const @var{encoder} ) @deftypefun int LZ_compress_finish ( struct LZ_Encoder * const @var{encoder} )
Use this function to tell @samp{lzlib} that all the data for this member Use this function to tell @samp{lzlib} that all the data for this member
have already been written (with the @samp{LZ_compress_write} function). have already been written (with the @samp{LZ_compress_write} function).
It is safe to call @samp{LZ_compress_finish} as many times as needed.
After all the produced compressed data have been read with After all the produced compressed data have been read with
@samp{LZ_compress_read} and @samp{LZ_compress_member_finished} returns @samp{LZ_compress_read} and @samp{LZ_compress_member_finished} returns
1, a new member can be started with @samp{LZ_compress_restart_member}. 1, a new member can be started with @samp{LZ_compress_restart_member}.
@ -364,7 +371,7 @@ accept a @var{size} up to the returned number of bytes.
@deftypefun {enum LZ_Errno} LZ_compress_errno ( struct LZ_Encoder * const @var{encoder} ) @deftypefun {enum LZ_Errno} LZ_compress_errno ( struct LZ_Encoder * const @var{encoder} )
Returns the current error code for @var{encoder} (@pxref{Error codes}). Returns the current error code for @var{encoder}. @xref{Error codes}.
@end deftypefun @end deftypefun
@ -440,6 +447,7 @@ longer be used as an argument to any LZ_decompress function.
@deftypefun int LZ_decompress_finish ( struct LZ_Decoder * const @var{decoder} ) @deftypefun int LZ_decompress_finish ( struct LZ_Decoder * const @var{decoder} )
Use this function to tell @samp{lzlib} that all the data for this stream Use this function to tell @samp{lzlib} that all the data for this stream
have already been written (with the @samp{LZ_decompress_write} function). have already been written (with the @samp{LZ_decompress_write} function).
It is safe to call @samp{LZ_decompress_finish} as many times as needed.
@end deftypefun @end deftypefun
@ -474,6 +482,16 @@ less than @var{size}; for example, if there aren't that many bytes left
in the stream or if more bytes have to be yet written with the in the stream or if more bytes have to be yet written with the
@samp{LZ_decompress_write} function. Note that reading less than @samp{LZ_decompress_write} function. Note that reading less than
@var{size} bytes is not an error. @var{size} bytes is not an error.
In case of decompression error caused by corrupt or truncated data,
@samp{LZ_decompress_read} does not signal the error immediately to the
application, but waits until all decoded bytes have been read. This
allows tools like
@uref{http://www.nongnu.org/lzip/manual/tarlz_manual.html,,tarlz} to
recover as much data as possible from each damaged member.
@ifnothtml
@xref{Top,tarlz manual,,tarlz}.
@end ifnothtml
@end deftypefun @end deftypefun
@ -498,7 +516,7 @@ will accept a @var{size} up to the returned number of bytes.
@deftypefun {enum LZ_Errno} LZ_decompress_errno ( struct LZ_Decoder * const @var{decoder} ) @deftypefun {enum LZ_Errno} LZ_decompress_errno ( struct LZ_Decoder * const @var{decoder} )
Returns the current error code for @var{decoder} (@pxref{Error codes}). Returns the current error code for @var{decoder}. @xref{Error codes}.
@end deftypefun @end deftypefun
@ -616,7 +634,7 @@ used to remove conflicting trailing data from a file.
@end deftypevr @end deftypevr
@deftypevr Constant {enum LZ_Errno} LZ_library_error @deftypevr Constant {enum LZ_Errno} LZ_library_error
A bug was detected in the library. Please, report it (@pxref{Problems}). A bug was detected in the library. Please, report it. @xref{Problems}.
@end deftypevr @end deftypevr
@ -640,6 +658,10 @@ The value of @var{lz_errno} normally comes from a call to
@cindex invoking @cindex invoking
@cindex options @cindex options
Minilzip is a test program for the lzlib compression library, fully
compatible with lzip 1.4 or newer.
@noindent
The format for running minilzip is: The format for running minilzip is:
@example @example
@ -661,6 +683,7 @@ Print an informative help message describing the options and exit.
@item -V @item -V
@itemx --version @itemx --version
Print the version number of minilzip on the standard output and exit. Print the version number of minilzip on the standard output and exit.
This version number should be included in all bug reports.
@anchor{--trailing-error} @anchor{--trailing-error}
@item -a @item -a
@ -728,12 +751,13 @@ Quiet operation. Suppress all messages.
@item -s @var{bytes} @item -s @var{bytes}
@itemx --dictionary-size=@var{bytes} @itemx --dictionary-size=@var{bytes}
When compressing, set the dictionary size limit in bytes. Minilzip will use When compressing, set the dictionary size limit in bytes. Minilzip will use
the smallest possible dictionary size for each file without exceeding for each file the largest dictionary size that does not exceed neither
this limit. Valid values range from @w{4 KiB} to @w{512 MiB}. Values 12 the file size nor this limit. Valid values range from @w{4 KiB} to
to 29 are interpreted as powers of two, meaning 2^12 to 2^29 bytes. Note @w{512 MiB}. Values 12 to 29 are interpreted as powers of two, meaning
that dictionary sizes are quantized. If the specified size does not 2^12 to 2^29 bytes. Dictionary sizes are quantized so that they can be
match one of the valid sizes, it will be rounded upwards by adding up to coded in just one byte (@pxref{coded-dict-size}). If the specified size
@w{(@var{bytes} / 8)} to it. does not match one of the valid sizes, it will be rounded upwards by
adding up to @w{(@var{bytes} / 8)} to it.
For maximum compression you should use a dictionary size limit as large For maximum compression you should use a dictionary size limit as large
as possible, but keep in mind that the decompression memory requirement as possible, but keep in mind that the decompression memory requirement
@ -768,18 +792,23 @@ verbosity level, showing status, compression ratio, dictionary size,
and trailer contents (CRC, data size, member size). and trailer contents (CRC, data size, member size).
@item -0 .. -9 @item -0 .. -9
Set the compression parameters (dictionary size and match length limit) Compression level. Set the compression parameters (dictionary size and
as shown in the table below. The default compression level is @samp{-6}. match length limit) as shown in the table below. The default compression
Note that @samp{-9} can be much slower than @samp{-0}. These options level is @samp{-6}, equivalent to @w{@samp{-s8MiB -m36}}. Note that
have no effect when decompressing or testing. @samp{-9} can be much slower than @samp{-0}. These options have no
effect when decompressing or testing.
The bidimensional parameter space of LZMA can't be mapped to a linear The bidimensional parameter space of LZMA can't be mapped to a linear
scale optimal for all files. If your files are large, very repetitive, scale optimal for all files. If your files are large, very repetitive,
etc, you may need to use the @samp{--dictionary-size} and etc, you may need to use the @samp{--dictionary-size} and
@samp{--match-length} options directly to achieve optimal performance. @samp{--match-length} options directly to achieve optimal performance.
@multitable {Level} {Dictionary size} {Match length limit} If several compression levels or @samp{-s} or @samp{-m} options are
@item Level @tab Dictionary size @tab Match length limit given, the last setting is used. For example @w{@samp{-9 -s64MiB}} is
equivalent to @w{@samp{-s64MiB -m273}}
@multitable {Level} {Dictionary size (-s)} {Match length limit (-m)}
@item Level @tab Dictionary size (-s) @tab Match length limit (-m)
@item -0 @tab 64 KiB @tab 16 bytes @item -0 @tab 64 KiB @tab 16 bytes
@item -1 @tab 1 MiB @tab 5 bytes @item -1 @tab 1 MiB @tab 5 bytes
@item -2 @tab 1.5 MiB @tab 6 bytes @item -2 @tab 1.5 MiB @tab 6 bytes
@ -875,12 +904,13 @@ A four byte string, identifying the lzip format, with the value "LZIP"
@item VN (version number, 1 byte) @item VN (version number, 1 byte)
Just in case something needs to be modified in the future. 1 for now. Just in case something needs to be modified in the future. 1 for now.
@anchor{coded-dict-size}
@item DS (coded dictionary size, 1 byte) @item DS (coded dictionary size, 1 byte)
The dictionary size is calculated by taking a power of 2 (the base size) The dictionary size is calculated by taking a power of 2 (the base size)
and substracting from it a fraction between 0/16 and 7/16 of the base and subtracting from it a fraction between 0/16 and 7/16 of the base
size.@* size.@*
Bits 4-0 contain the base 2 logarithm of the base size (12 to 29).@* Bits 4-0 contain the base 2 logarithm of the base size (12 to 29).@*
Bits 7-5 contain the numerator of the fraction (0 to 7) to substract Bits 7-5 contain the numerator of the fraction (0 to 7) to subtract
from the base size to obtain the dictionary size.@* from the base size to obtain the dictionary size.@*
Example: 0xD3 = 2^19 - 6 * 2^15 = 512 KiB - 6 * 32 KiB = 320 KiB@* Example: 0xD3 = 2^19 - 6 * 2^15 = 512 KiB - 6 * 32 KiB = 320 KiB@*
Valid values for dictionary size range from 4 KiB to 512 MiB. Valid values for dictionary size range from 4 KiB to 512 MiB.
@ -934,12 +964,10 @@ Example 1: Normal compression (@var{member_size} > total output).
@example @example
1) LZ_compress_open 1) LZ_compress_open
2) LZ_compress_write 2) LZ_compress_write
3) LZ_compress_read 3) if no more data to write, call LZ_compress_finish
4) go back to step 2 until all input data have been written 4) LZ_compress_read
5) LZ_compress_finish 5) go back to step 2 until LZ_compress_finished returns 1
6) LZ_compress_read 6) LZ_compress_close
7) go back to step 6 until LZ_compress_finished returns 1
8) LZ_compress_close
@end example @end example
@sp 1 @sp 1
@ -963,12 +991,10 @@ Example 3: Decompression.
@example @example
1) LZ_decompress_open 1) LZ_decompress_open
2) LZ_decompress_write 2) LZ_decompress_write
3) LZ_decompress_read 3) if no more data to write, call LZ_decompress_finish
4) go back to step 2 until all input data have been written 4) LZ_decompress_read
5) LZ_decompress_finish 5) go back to step 2 until LZ_decompress_finished returns 1
6) LZ_decompress_read 6) LZ_decompress_close
7) go back to step 6 until LZ_decompress_finished returns 1
8) LZ_decompress_close
@end example @end example
@sp 1 @sp 1

View file

@ -1,12 +1,13 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
.TH MINILZIP "1" "February 2018" "minilzip 1.10" "User Commands" .TH MINILZIP "1" "January 2019" "minilzip 1.11" "User Commands"
.SH NAME .SH NAME
minilzip \- reduces the size of files minilzip \- reduces the size of files
.SH SYNOPSIS .SH SYNOPSIS
.B minilzip .B minilzip
[\fI\,options\/\fR] [\fI\,files\/\fR] [\fI\,options\/\fR] [\fI\,files\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Minilzip \- Test program for the lzlib library. Minilzip is a test program for the lzlib compression library, fully
compatible with lzip 1.4 or newer.
.SH OPTIONS .SH OPTIONS
.TP .TP
\fB\-h\fR, \fB\-\-help\fR \fB\-h\fR, \fB\-\-help\fR
@ -49,7 +50,7 @@ suppress all messages
set dictionary size limit in bytes [8 MiB] set dictionary size limit in bytes [8 MiB]
.TP .TP
\fB\-S\fR, \fB\-\-volume\-size=\fR<bytes> \fB\-S\fR, \fB\-\-volume\-size=\fR<bytes>
set volume size limit in bytes, implies \fB\-k\fR set volume size limit in bytes
.TP .TP
\fB\-t\fR, \fB\-\-test\fR \fB\-t\fR, \fB\-\-test\fR
test compressed file integrity test compressed file integrity
@ -90,8 +91,8 @@ Report bugs to lzip\-bug@nongnu.org
.br .br
Lzlib home page: http://www.nongnu.org/lzip/lzlib.html Lzlib home page: http://www.nongnu.org/lzip/lzlib.html
.SH COPYRIGHT .SH COPYRIGHT
Copyright \(co 2018 Antonio Diaz Diaz. Copyright \(co 2019 Antonio Diaz Diaz.
Using lzlib 1.10 Using lzlib 1.11
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
.br .br
This is free software: you are free to change and redistribute it. This is free software: you are free to change and redistribute it.

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -313,7 +313,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
--prev_index; --prev_index;
else /* prev_index2 >= 0 */ else /* prev_index2 >= 0 */
prev_index = prev_index2; prev_index = prev_index2;
cur_state = 8; /* St_set_char_rep(); */ cur_state = St_set_char_rep();
} }
cur_trial->state = cur_state; cur_trial->state = cur_state;
for( i = 0; i < num_rep_distances; ++i ) for( i = 0; i < num_rep_distances; ++i )

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -24,7 +24,8 @@ static bool Mb_normalize_pos( struct Matchfinder_base * const mb )
if( !mb->at_stream_end ) if( !mb->at_stream_end )
{ {
int i; int i;
const int offset = mb->pos - mb->before_size - mb->dictionary_size; /* offset is int32_t for the min below */
const int32_t offset = mb->pos - mb->before_size - mb->dictionary_size;
const int size = mb->stream_pos - offset; const int size = mb->stream_pos - offset;
memmove( mb->buffer, mb->buffer + offset, size ); memmove( mb->buffer, mb->buffer + offset, size );
mb->partial_data_pos += offset; mb->partial_data_pos += offset;
@ -131,19 +132,19 @@ static void LZeb_try_full_flush( struct LZ_encoder_base * const eb )
int i; int i;
const int pos_state = Mb_data_position( &eb->mb ) & pos_state_mask; const int pos_state = Mb_data_position( &eb->mb ) & pos_state_mask;
const State state = eb->state; const State state = eb->state;
File_trailer trailer; Lzip_trailer trailer;
if( eb->member_finished || if( eb->member_finished ||
Cb_free_bytes( &eb->renc.cb ) < max_marker_size + eb->renc.ff_count + Ft_size ) Cb_free_bytes( &eb->renc.cb ) < max_marker_size + eb->renc.ff_count + Lt_size )
return; return;
eb->member_finished = true; eb->member_finished = true;
Re_encode_bit( &eb->renc, &eb->bm_match[state][pos_state], 1 ); Re_encode_bit( &eb->renc, &eb->bm_match[state][pos_state], 1 );
Re_encode_bit( &eb->renc, &eb->bm_rep[state], 0 ); Re_encode_bit( &eb->renc, &eb->bm_rep[state], 0 );
LZeb_encode_pair( eb, 0xFFFFFFFFU, min_match_len, pos_state ); LZeb_encode_pair( eb, 0xFFFFFFFFU, min_match_len, pos_state );
Re_flush( &eb->renc ); Re_flush( &eb->renc );
Ft_set_data_crc( trailer, LZeb_crc( eb ) ); Lt_set_data_crc( trailer, LZeb_crc( eb ) );
Ft_set_data_size( trailer, Mb_data_position( &eb->mb ) ); Lt_set_data_size( trailer, Mb_data_position( &eb->mb ) );
Ft_set_member_size( trailer, Re_member_position( &eb->renc ) + Ft_size ); Lt_set_member_size( trailer, Re_member_position( &eb->renc ) + Lt_size );
for( i = 0; i < Ft_size; ++i ) for( i = 0; i < Lt_size; ++i )
Cb_put_byte( &eb->renc.cb, trailer[i] ); Cb_put_byte( &eb->renc.cb, trailer[i] );
} }
@ -173,7 +174,8 @@ static void LZeb_reset( struct LZ_encoder_base * const eb,
{ {
int i; int i;
Mb_reset( &eb->mb ); Mb_reset( &eb->mb );
eb->member_size_limit = member_size - Ft_size - max_marker_size; eb->member_size_limit =
min( member_size, 0x0008000000000000ULL ) - Lt_size - max_marker_size;
eb->crc = 0xFFFFFFFFU; eb->crc = 0xFFFFFFFFU;
Bm_array_init( eb->bm_literal[0], (1 << literal_context_bits) * 0x300 ); Bm_array_init( eb->bm_literal[0], (1 << literal_context_bits) * 0x300 );
Bm_array_init( eb->bm_match[0], states * pos_states ); Bm_array_init( eb->bm_match[0], states * pos_states );

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -322,7 +322,7 @@ struct Range_encoder
uint32_t range; uint32_t range;
unsigned ff_count; unsigned ff_count;
uint8_t cache; uint8_t cache;
File_header header; Lzip_header header;
}; };
static inline void Re_shift_low( struct Range_encoder * const renc ) static inline void Re_shift_low( struct Range_encoder * const renc )
@ -349,8 +349,8 @@ static inline void Re_reset( struct Range_encoder * const renc,
renc->range = 0xFFFFFFFFU; renc->range = 0xFFFFFFFFU;
renc->ff_count = 0; renc->ff_count = 0;
renc->cache = 0; renc->cache = 0;
Fh_set_dictionary_size( renc->header, dictionary_size ); Lh_set_dictionary_size( renc->header, dictionary_size );
for( i = 0; i < Fh_size; ++i ) for( i = 0; i < Lh_size; ++i )
Cb_put_byte( &renc->cb, renc->header[i] ); Cb_put_byte( &renc->cb, renc->header[i] );
} }
@ -360,7 +360,7 @@ static inline bool Re_init( struct Range_encoder * const renc,
{ {
if( !Cb_init( &renc->cb, 65536 + min_free_bytes ) ) return false; if( !Cb_init( &renc->cb, 65536 + min_free_bytes ) ) return false;
renc->min_free_bytes = min_free_bytes; renc->min_free_bytes = min_free_bytes;
Fh_set_magic( renc->header ); Lh_set_magic( renc->header );
Re_reset( renc, dictionary_size ); Re_reset( renc, dictionary_size );
return true; return true;
} }

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -58,9 +58,9 @@ static inline bool FLZe_init( struct FLZ_encoder * const fe,
/* bytes to keep in buffer after pos */ /* bytes to keep in buffer after pos */
after_size = max_match_len, after_size = max_match_len,
dict_factor = 16, dict_factor = 16,
min_free_bytes = max_marker_size,
num_prev_positions23 = 0, num_prev_positions23 = 0,
pos_array_factor = 1, pos_array_factor = 1 };
min_free_bytes = max_marker_size };
return LZeb_init( &fe->eb, before_size, dict_size, after_size, dict_factor, return LZeb_init( &fe->eb, before_size, dict_size, after_size, dict_factor,
num_prev_positions23, pos_array_factor, min_free_bytes, num_prev_positions23, pos_array_factor, min_free_bytes,

View file

@ -1,5 +1,5 @@
/* Lzcheck - Test program for the lzlib library /* Lzcheck - Test program for the lzlib library
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This program is free software: you have unlimited permission This program is free software: you have unlimited permission
to copy, distribute and modify it. to copy, distribute and modify it.
@ -119,9 +119,11 @@ int lzcheck( FILE * const file, const int dictionary_size )
{ {
rewind( file ); rewind( file );
if( LZ_compress_finish( encoder ) < 0 || if( LZ_compress_finish( encoder ) < 0 ||
LZ_compress_finish( encoder ) < 0 ||
LZ_decompress_write( decoder, mid_buffer, LZ_decompress_write( decoder, mid_buffer,
LZ_compress_read( encoder, mid_buffer, buffer_size ) ) < 0 || LZ_compress_read( encoder, mid_buffer, buffer_size ) ) < 0 ||
LZ_decompress_read( decoder, out_buffer, buffer_size ) != 0 || LZ_decompress_read( decoder, out_buffer, buffer_size ) != 0 ||
LZ_compress_finish( encoder ) < 0 ||
LZ_compress_restart_member( encoder, member_size ) < 0 ) LZ_compress_restart_member( encoder, member_size ) < 0 )
{ {
fprintf( stderr, "lzcheck: Can't finish member: %s\n", fprintf( stderr, "lzcheck: Can't finish member: %s\n",

57
lzip.h
View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -36,6 +36,8 @@ static inline State St_set_char( const State st )
return next[st]; return next[st];
} }
static inline State St_set_char_rep() { return 8; }
static inline State St_set_match( const State st ) static inline State St_set_match( const State st )
{ return ( ( st < 7 ) ? 7 : 10 ); } { return ( ( st < 7 ) ? 7 : 10 ); }
@ -191,43 +193,43 @@ static inline int real_bits( unsigned value )
} }
static const uint8_t magic_string[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */
typedef uint8_t File_header[6]; /* 0-3 magic bytes */ typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */
/* 4 version */ /* 4 version */
/* 5 coded_dict_size */ /* 5 coded_dict_size */
enum { Fh_size = 6 }; enum { Lh_size = 6 };
static inline void Fh_set_magic( File_header data ) static inline void Lh_set_magic( Lzip_header data )
{ memcpy( data, magic_string, 4 ); data[4] = 1; } { memcpy( data, lzip_magic, 4 ); data[4] = 1; }
static inline bool Fh_verify_magic( const File_header data ) static inline bool Lh_verify_magic( const Lzip_header data )
{ return ( memcmp( data, magic_string, 4 ) == 0 ); } { return ( memcmp( data, lzip_magic, 4 ) == 0 ); }
/* detect (truncated) header */ /* detect (truncated) header */
static inline bool Fh_verify_prefix( const File_header data, const int sz ) static inline bool Lh_verify_prefix( const Lzip_header data, const int sz )
{ {
int i; for( i = 0; i < sz && i < 4; ++i ) int i; for( i = 0; i < sz && i < 4; ++i )
if( data[i] != magic_string[i] ) return false; if( data[i] != lzip_magic[i] ) return false;
return ( sz > 0 ); return ( sz > 0 );
} }
/* detect corrupt header */ /* detect corrupt header */
static inline bool Fh_verify_corrupt( const File_header data ) static inline bool Lh_verify_corrupt( const Lzip_header data )
{ {
int matches = 0; int matches = 0;
int i; for( i = 0; i < 4; ++i ) int i; for( i = 0; i < 4; ++i )
if( data[i] == magic_string[i] ) ++matches; if( data[i] == lzip_magic[i] ) ++matches;
return ( matches > 1 && matches < 4 ); return ( matches > 1 && matches < 4 );
} }
static inline uint8_t Fh_version( const File_header data ) static inline uint8_t Lh_version( const Lzip_header data )
{ return data[4]; } { return data[4]; }
static inline bool Fh_verify_version( const File_header data ) static inline bool Lh_verify_version( const Lzip_header data )
{ return ( data[4] == 1 ); } { return ( data[4] == 1 ); }
static inline unsigned Fh_get_dictionary_size( const File_header data ) static inline unsigned Lh_get_dictionary_size( const Lzip_header data )
{ {
unsigned sz = ( 1 << ( data[5] & 0x1F ) ); unsigned sz = ( 1 << ( data[5] & 0x1F ) );
if( sz > min_dictionary_size ) if( sz > min_dictionary_size )
@ -235,7 +237,7 @@ static inline unsigned Fh_get_dictionary_size( const File_header data )
return sz; return sz;
} }
static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) static inline bool Lh_set_dictionary_size( Lzip_header data, const unsigned sz )
{ {
if( !isvalid_ds( sz ) ) return false; if( !isvalid_ds( sz ) ) return false;
data[5] = real_bits( sz - 1 ); data[5] = real_bits( sz - 1 );
@ -251,47 +253,46 @@ static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz )
return true; return true;
} }
static inline bool Fh_verify( const File_header data ) static inline bool Lh_verify( const Lzip_header data )
{ {
if( Fh_verify_magic( data ) && Fh_verify_version( data ) ) if( Lh_verify_magic( data ) && Lh_verify_version( data ) )
return isvalid_ds( Fh_get_dictionary_size( data ) ); return isvalid_ds( Lh_get_dictionary_size( data ) );
return false; return false;
} }
typedef uint8_t File_trailer[20]; typedef uint8_t Lzip_trailer[20];
/* 0-3 CRC32 of the uncompressed data */ /* 0-3 CRC32 of the uncompressed data */
/* 4-11 size of the uncompressed data */ /* 4-11 size of the uncompressed data */
/* 12-19 member size including header and trailer */ /* 12-19 member size including header and trailer */
enum { Lt_size = 20 };
enum { Ft_size = 20 }; static inline unsigned Lt_get_data_crc( const Lzip_trailer data )
static inline unsigned Ft_get_data_crc( const File_trailer data )
{ {
unsigned tmp = 0; unsigned tmp = 0;
int i; for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; } int i; for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; }
return tmp; return tmp;
} }
static inline void Ft_set_data_crc( File_trailer data, unsigned crc ) static inline void Lt_set_data_crc( Lzip_trailer data, unsigned crc )
{ int i; for( i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } { int i; for( i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } }
static inline unsigned long long Ft_get_data_size( const File_trailer data ) static inline unsigned long long Lt_get_data_size( const Lzip_trailer data )
{ {
unsigned long long tmp = 0; unsigned long long tmp = 0;
int i; for( i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; } int i; for( i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; }
return tmp; return tmp;
} }
static inline void Ft_set_data_size( File_trailer data, unsigned long long sz ) static inline void Lt_set_data_size( Lzip_trailer data, unsigned long long sz )
{ int i; for( i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } { int i; for( i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } }
static inline unsigned long long Ft_get_member_size( const File_trailer data ) static inline unsigned long long Lt_get_member_size( const Lzip_trailer data )
{ {
unsigned long long tmp = 0; unsigned long long tmp = 0;
int i; for( i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; } int i; for( i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; }
return tmp; return tmp;
} }
static inline void Ft_set_member_size( File_trailer data, unsigned long long sz ) static inline void Lt_set_member_size( Lzip_trailer data, unsigned long long sz )
{ int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } { int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } }

58
lzlib.c
View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -65,7 +65,7 @@ struct LZ_Decoder
struct Range_decoder * rdec; struct Range_decoder * rdec;
struct LZ_decoder * lz_decoder; struct LZ_decoder * lz_decoder;
enum LZ_Errno lz_errno; enum LZ_Errno lz_errno;
File_header member_header; /* header of current member */ Lzip_header member_header; /* header of current member */
bool fatal; bool fatal;
bool first_header; /* true until first header is read */ bool first_header; /* true until first header is read */
bool seeking; bool seeking;
@ -79,7 +79,7 @@ static void LZ_Decoder_init( struct LZ_Decoder * const d )
d->rdec = 0; d->rdec = 0;
d->lz_decoder = 0; d->lz_decoder = 0;
d->lz_errno = LZ_ok; d->lz_errno = LZ_ok;
for( i = 0; i < Fh_size; ++i ) d->member_header[i] = 0; for( i = 0; i < Lh_size; ++i ) d->member_header[i] = 0;
d->fatal = false; d->fatal = false;
d->first_header = true; d->first_header = true;
d->seeking = false; d->seeking = false;
@ -119,7 +119,7 @@ const char * LZ_strerror( const enum LZ_Errno lz_errno )
case LZ_mem_error : return "Not enough memory"; case LZ_mem_error : return "Not enough memory";
case LZ_sequence_error: return "Sequence error"; case LZ_sequence_error: return "Sequence error";
case LZ_header_error : return "Header error"; case LZ_header_error : return "Header error";
case LZ_unexpected_eof: return "Unexpected eof"; case LZ_unexpected_eof: return "Unexpected EOF";
case LZ_data_error : return "Data error"; case LZ_data_error : return "Data error";
case LZ_library_error : return "Library error"; case LZ_library_error : return "Library error";
} }
@ -141,12 +141,12 @@ struct LZ_Encoder * LZ_compress_open( const int dictionary_size,
const int match_len_limit, const int match_len_limit,
const unsigned long long member_size ) const unsigned long long member_size )
{ {
File_header header; Lzip_header header;
struct LZ_Encoder * const e = struct LZ_Encoder * const e =
(struct LZ_Encoder *)malloc( sizeof (struct LZ_Encoder) ); (struct LZ_Encoder *)malloc( sizeof (struct LZ_Encoder) );
if( !e ) return 0; if( !e ) return 0;
LZ_Encoder_init( e ); LZ_Encoder_init( e );
if( !Fh_set_dictionary_size( header, dictionary_size ) || if( !Lh_set_dictionary_size( header, dictionary_size ) ||
match_len_limit < min_match_len_limit || match_len_limit < min_match_len_limit ||
match_len_limit > max_match_len || match_len_limit > max_match_len ||
member_size < min_dictionary_size ) member_size < min_dictionary_size )
@ -163,7 +163,7 @@ struct LZ_Encoder * LZ_compress_open( const int dictionary_size,
else else
{ {
e->lz_encoder = (struct LZ_encoder *)malloc( sizeof (struct LZ_encoder) ); e->lz_encoder = (struct LZ_encoder *)malloc( sizeof (struct LZ_encoder) );
if( e->lz_encoder && LZe_init( e->lz_encoder, Fh_get_dictionary_size( header ), if( e->lz_encoder && LZe_init( e->lz_encoder, Lh_get_dictionary_size( header ),
match_len_limit, member_size ) ) match_len_limit, member_size ) )
{ e->lz_encoder_base = &e->lz_encoder->eb; return e; } { e->lz_encoder_base = &e->lz_encoder->eb; return e; }
free( e->lz_encoder ); e->lz_encoder = 0; free( e->lz_encoder ); e->lz_encoder = 0;
@ -193,10 +193,10 @@ int LZ_compress_finish( struct LZ_Encoder * const e )
/* if (open --> write --> finish) use same dictionary size as lzip. */ /* if (open --> write --> finish) use same dictionary size as lzip. */
/* this does not save any memory. */ /* this does not save any memory. */
if( Mb_data_position( &e->lz_encoder_base->mb ) == 0 && if( Mb_data_position( &e->lz_encoder_base->mb ) == 0 &&
Re_member_position( &e->lz_encoder_base->renc ) == Fh_size ) Re_member_position( &e->lz_encoder_base->renc ) == Lh_size )
{ {
Mb_adjust_dictionary_size( &e->lz_encoder_base->mb ); Mb_adjust_dictionary_size( &e->lz_encoder_base->mb );
Fh_set_dictionary_size( e->lz_encoder_base->renc.header, Lh_set_dictionary_size( e->lz_encoder_base->renc.header,
e->lz_encoder_base->mb.dictionary_size ); e->lz_encoder_base->mb.dictionary_size );
e->lz_encoder_base->renc.cb.buffer[5] = e->lz_encoder_base->renc.header[5]; e->lz_encoder_base->renc.cb.buffer[5] = e->lz_encoder_base->renc.header[5];
} }
@ -400,7 +400,10 @@ int LZ_decompress_read( struct LZ_Decoder * const d,
uint8_t * const buffer, const int size ) uint8_t * const buffer, const int size )
{ {
int result; int result;
if( !verify_decoder( d ) || d->fatal ) return -1; if( !verify_decoder( d ) ) return -1;
if( d->fatal ) /* don't return error until pending bytes are read */
{ if( d->lz_decoder && !Cb_empty( &d->lz_decoder->cb ) ) goto get_data;
return -1; }
if( d->seeking || size < 0 ) return 0; if( d->seeking || size < 0 ) return 0;
if( d->lz_decoder && LZd_member_finished( d->lz_decoder ) ) if( d->lz_decoder && LZd_member_finished( d->lz_decoder ) )
@ -413,26 +416,26 @@ int LZ_decompress_read( struct LZ_Decoder * const d,
int rd; int rd;
d->partial_in_size += d->rdec->member_position; d->partial_in_size += d->rdec->member_position;
d->rdec->member_position = 0; d->rdec->member_position = 0;
if( Rd_available_bytes( d->rdec ) < Fh_size + 5 && if( Rd_available_bytes( d->rdec ) < Lh_size + 5 &&
!d->rdec->at_stream_end ) return 0; !d->rdec->at_stream_end ) return 0;
if( Rd_finished( d->rdec ) && !d->first_header ) return 0; if( Rd_finished( d->rdec ) && !d->first_header ) return 0;
rd = Rd_read_data( d->rdec, d->member_header, Fh_size ); rd = Rd_read_data( d->rdec, d->member_header, Lh_size );
if( Rd_finished( d->rdec ) ) /* End Of File */ if( rd < Lh_size || Rd_finished( d->rdec ) ) /* End Of File */
{ {
if( rd <= 0 || Fh_verify_prefix( d->member_header, rd ) ) if( rd <= 0 || Lh_verify_prefix( d->member_header, rd ) )
d->lz_errno = LZ_unexpected_eof; d->lz_errno = LZ_unexpected_eof;
else else
d->lz_errno = LZ_header_error; d->lz_errno = LZ_header_error;
d->fatal = true; d->fatal = true;
return -1; return -1;
} }
if( !Fh_verify_magic( d->member_header ) ) if( !Lh_verify_magic( d->member_header ) )
{ {
/* unreading the header prevents sync_to_member from skipping a member /* unreading the header prevents sync_to_member from skipping a member
if leading garbage is shorter than a full header; "lgLZIP\x01\x0C" */ if leading garbage is shorter than a full header; "lgLZIP\x01\x0C" */
if( Rd_unread_data( d->rdec, rd ) ) if( Rd_unread_data( d->rdec, rd ) )
{ {
if( d->first_header || !Fh_verify_corrupt( d->member_header ) ) if( d->first_header || !Lh_verify_corrupt( d->member_header ) )
d->lz_errno = LZ_header_error; d->lz_errno = LZ_header_error;
else else
d->lz_errno = LZ_data_error; /* corrupt header */ d->lz_errno = LZ_data_error; /* corrupt header */
@ -442,10 +445,12 @@ int LZ_decompress_read( struct LZ_Decoder * const d,
d->fatal = true; d->fatal = true;
return -1; return -1;
} }
if( !Fh_verify_version( d->member_header ) || if( !Lh_verify_version( d->member_header ) ||
!isvalid_ds( Fh_get_dictionary_size( d->member_header ) ) ) !isvalid_ds( Lh_get_dictionary_size( d->member_header ) ) )
{ {
if( Rd_unread_data( d->rdec, 1 + !Fh_verify_version( d->member_header ) ) ) /* Skip a possible "LZIP" leading garbage; "LZIPLZIP\x01\x0C".
Leave member_pos pointing to the first error. */
if( Rd_unread_data( d->rdec, 1 + !Lh_verify_version( d->member_header ) ) )
d->lz_errno = LZ_data_error; /* bad version or bad dict size */ d->lz_errno = LZ_data_error; /* bad version or bad dict size */
else else
d->lz_errno = LZ_library_error; d->lz_errno = LZ_library_error;
@ -464,7 +469,7 @@ int LZ_decompress_read( struct LZ_Decoder * const d,
} }
d->lz_decoder = (struct LZ_decoder *)malloc( sizeof (struct LZ_decoder) ); d->lz_decoder = (struct LZ_decoder *)malloc( sizeof (struct LZ_decoder) );
if( !d->lz_decoder || !LZd_init( d->lz_decoder, d->rdec, if( !d->lz_decoder || !LZd_init( d->lz_decoder, d->rdec,
Fh_get_dictionary_size( d->member_header ) ) ) Lh_get_dictionary_size( d->member_header ) ) )
{ /* not enough free memory */ { /* not enough free memory */
if( d->lz_decoder ) if( d->lz_decoder )
{ LZd_free( d->lz_decoder ); free( d->lz_decoder ); d->lz_decoder = 0; } { LZd_free( d->lz_decoder ); free( d->lz_decoder ); d->lz_decoder = 0; }
@ -477,15 +482,16 @@ int LZ_decompress_read( struct LZ_Decoder * const d,
result = LZd_decode_member( d->lz_decoder ); result = LZd_decode_member( d->lz_decoder );
if( result != 0 ) if( result != 0 )
{ {
if( result == 2 ) /* set position at EOF */ if( result == 2 ) /* set input position at EOF */
{ d->rdec->member_position += Cb_used_bytes( &d->rdec->cb ); { d->rdec->member_position += Cb_used_bytes( &d->rdec->cb );
Cb_reset( &d->rdec->cb ); Cb_reset( &d->rdec->cb );
d->lz_errno = LZ_unexpected_eof; } d->lz_errno = LZ_unexpected_eof; }
else if( result == 5 ) d->lz_errno = LZ_library_error; else if( result == 5 ) d->lz_errno = LZ_library_error;
else d->lz_errno = LZ_data_error; else d->lz_errno = LZ_data_error;
d->fatal = true; d->fatal = true;
return -1; if( Cb_empty( &d->lz_decoder->cb ) ) return -1;
} }
get_data:
return Cb_read_data( &d->lz_decoder->cb, buffer, size ); return Cb_read_data( &d->lz_decoder->cb, buffer, size );
} }
@ -529,7 +535,7 @@ enum LZ_Errno LZ_decompress_errno( struct LZ_Decoder * const d )
int LZ_decompress_finished( struct LZ_Decoder * const d ) int LZ_decompress_finished( struct LZ_Decoder * const d )
{ {
if( !verify_decoder( d ) ) return -1; if( !verify_decoder( d ) || d->fatal ) return -1;
return ( Rd_finished( d->rdec ) && return ( Rd_finished( d->rdec ) &&
( !d->lz_decoder || LZd_member_finished( d->lz_decoder ) ) ); ( !d->lz_decoder || LZd_member_finished( d->lz_decoder ) ) );
} }
@ -537,7 +543,7 @@ int LZ_decompress_finished( struct LZ_Decoder * const d )
int LZ_decompress_member_finished( struct LZ_Decoder * const d ) int LZ_decompress_member_finished( struct LZ_Decoder * const d )
{ {
if( !verify_decoder( d ) ) return -1; if( !verify_decoder( d ) || d->fatal ) return -1;
return ( d->lz_decoder && LZd_member_finished( d->lz_decoder ) ); return ( d->lz_decoder && LZd_member_finished( d->lz_decoder ) );
} }
@ -545,14 +551,14 @@ int LZ_decompress_member_finished( struct LZ_Decoder * const d )
int LZ_decompress_member_version( struct LZ_Decoder * const d ) int LZ_decompress_member_version( struct LZ_Decoder * const d )
{ {
if( !verify_decoder( d ) ) return -1; if( !verify_decoder( d ) ) return -1;
return Fh_version( d->member_header ); return Lh_version( d->member_header );
} }
int LZ_decompress_dictionary_size( struct LZ_Decoder * const d ) int LZ_decompress_dictionary_size( struct LZ_Decoder * const d )
{ {
if( !verify_decoder( d ) ) return -1; if( !verify_decoder( d ) ) return -1;
return Fh_get_dictionary_size( d->member_header ); return Lh_get_dictionary_size( d->member_header );
} }

View file

@ -1,5 +1,5 @@
/* Lzlib - Compression library for the lzip format /* Lzlib - Compression library for the lzip format
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -23,7 +23,7 @@ extern "C" {
#define LZ_API_VERSION 1 #define LZ_API_VERSION 1
static const char * const LZ_version_string = "1.10"; static const char * const LZ_version_string = "1.11";
enum LZ_Errno { LZ_ok = 0, LZ_bad_argument, LZ_mem_error, enum LZ_Errno { LZ_ok = 0, LZ_bad_argument, LZ_mem_error,
LZ_sequence_error, LZ_header_error, LZ_unexpected_eof, LZ_sequence_error, LZ_header_error, LZ_unexpected_eof,

108
main.c
View file

@ -1,5 +1,5 @@
/* Minilzip - Test program for the lzlib library /* Minilzip - Test program for the lzlib library
Copyright (C) 2009-2018 Antonio Diaz Diaz. Copyright (C) 2009-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -35,20 +35,25 @@
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#include <sys/stat.h> #include <sys/stat.h>
#if defined(__MSVCRT__) #if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__)
#include <io.h> #include <io.h>
#if defined(__MSVCRT__)
#define fchmod(x,y) 0 #define fchmod(x,y) 0
#define fchown(x,y,z) 0 #define fchown(x,y,z) 0
#define strtoull strtoul #define strtoull strtoul
#define SIGHUP SIGTERM #define SIGHUP SIGTERM
#define S_ISSOCK(x) 0 #define S_ISSOCK(x) 0
#ifndef S_IRGRP
#define S_IRGRP 0 #define S_IRGRP 0
#define S_IWGRP 0 #define S_IWGRP 0
#define S_IROTH 0 #define S_IROTH 0
#define S_IWOTH 0 #define S_IWOTH 0
#endif #endif
#if defined(__OS2__) #endif
#include <io.h> #if defined(__DJGPP__)
#define S_ISSOCK(x) 0
#define S_ISVTX 0
#endif
#endif #endif
#include "carg_parser.h" #include "carg_parser.h"
@ -77,9 +82,8 @@ void internal_error( const char * const msg );
int verbosity = 0; int verbosity = 0;
const char * const Program_name = "Minilzip";
const char * const program_name = "minilzip"; const char * const program_name = "minilzip";
const char * const program_year = "2018"; const char * const program_year = "2019";
const char * invocation_name = 0; const char * invocation_name = 0;
const struct { const char * from; const char * to; } known_extensions[] = { const struct { const char * from; const char * to; } known_extensions[] = {
@ -95,6 +99,8 @@ struct Lzma_options
enum Mode { m_compress, m_decompress, m_test }; enum Mode { m_compress, m_decompress, m_test };
/* Variables used in signal handler context.
They are not declared volatile because the handler never returns. */
char * output_filename = 0; char * output_filename = 0;
int outfd = -1; int outfd = -1;
bool delete_output_on_interrupt = false; bool delete_output_on_interrupt = false;
@ -102,8 +108,9 @@ bool delete_output_on_interrupt = false;
static void show_help( void ) static void show_help( void )
{ {
printf( "%s - Test program for the lzlib library.\n", Program_name ); printf( "Minilzip is a test program for the lzlib compression library, fully\n"
printf( "\nUsage: %s [options] [files]\n", invocation_name ); "compatible with lzip 1.4 or newer.\n"
"\nUsage: %s [options] [files]\n", invocation_name );
printf( "\nOptions:\n" printf( "\nOptions:\n"
" -h, --help display this help and exit\n" " -h, --help display this help and exit\n"
" -V, --version output version information and exit\n" " -V, --version output version information and exit\n"
@ -118,7 +125,7 @@ static void show_help( void )
" -o, --output=<file> if reading standard input, write to <file>\n" " -o, --output=<file> if reading standard input, write to <file>\n"
" -q, --quiet suppress all messages\n" " -q, --quiet suppress all messages\n"
" -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8 MiB]\n" " -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8 MiB]\n"
" -S, --volume-size=<bytes> set volume size limit in bytes, implies -k\n" " -S, --volume-size=<bytes> set volume size limit in bytes\n"
" -t, --test test compressed file integrity\n" " -t, --test test compressed file integrity\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n" " -v, --verbose be verbose (a 2nd -v gives more)\n"
" -0 .. -9 set compression level [default 6]\n" " -0 .. -9 set compression level [default 6]\n"
@ -196,7 +203,7 @@ static void Pp_init( struct Pretty_print * const pp,
{ {
const char * const s = filenames[i]; const char * const s = filenames[i];
const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s );
if( len > pp->longest_name ) pp->longest_name = len; if( pp->longest_name < len ) pp->longest_name = len;
} }
if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len;
} }
@ -322,6 +329,17 @@ static int get_dict_size( const char * const arg )
} }
void set_mode( enum Mode * const program_modep, const enum Mode new_mode )
{
if( *program_modep != m_compress && *program_modep != new_mode )
{
show_error( "Only one operation can be specified.", 0, true );
exit( 1 );
}
*program_modep = new_mode;
}
static int extension_index( const char * const name ) static int extension_index( const char * const name )
{ {
int eindex; int eindex;
@ -457,8 +475,17 @@ static bool check_tty( const char * const input_filename, const int infd,
} }
static void set_signals( void (*action)(int) )
{
signal( SIGHUP, action );
signal( SIGINT, action );
signal( SIGTERM, action );
}
void cleanup_and_fail( const int retval ) void cleanup_and_fail( const int retval )
{ {
set_signals( SIG_IGN ); /* ignore signals */
if( delete_output_on_interrupt ) if( delete_output_on_interrupt )
{ {
delete_output_on_interrupt = false; delete_output_on_interrupt = false;
@ -473,6 +500,14 @@ void cleanup_and_fail( const int retval )
} }
void signal_handler( int sig )
{
if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false );
cleanup_and_fail( 1 );
}
/* Set permissions, owner and times. */ /* Set permissions, owner and times. */
static void close_and_set_permissions( const struct stat * const in_statsp ) static void close_and_set_permissions( const struct stat * const in_statsp )
{ {
@ -696,7 +731,8 @@ static int do_decompress( struct LZ_Decoder * const decoder, const int infd,
for( first_member = true; ; ) for( first_member = true; ; )
{ {
const int max_in_size = min( LZ_decompress_write_size( decoder ), buffer_size ); const int max_in_size =
min( LZ_decompress_write_size( decoder ), buffer_size );
int in_size = 0, out_size = 0; int in_size = 0, out_size = 0;
if( max_in_size > 0 ) if( max_in_size > 0 )
{ {
@ -712,7 +748,8 @@ static int do_decompress( struct LZ_Decoder * const decoder, const int infd,
} }
while( true ) while( true )
{ {
const int rd = LZ_decompress_read( decoder, buffer, buffer_size ); const int rd =
LZ_decompress_read( decoder, (outfd >= 0) ? buffer : 0, buffer_size );
if( rd > 0 ) if( rd > 0 )
{ {
out_size += rd; out_size += rd;
@ -839,31 +876,13 @@ static int decompress( const int infd, struct Pretty_print * const pp,
} }
void signal_handler( int sig )
{
if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false );
cleanup_and_fail( 1 );
}
static void set_signals( void )
{
signal( SIGHUP, signal_handler );
signal( SIGINT, signal_handler );
signal( SIGTERM, signal_handler );
}
void show_error( const char * const msg, const int errcode, const bool help ) void show_error( const char * const msg, const int errcode, const bool help )
{ {
if( verbosity < 0 ) return; if( verbosity < 0 ) return;
if( msg && msg[0] ) if( msg && msg[0] )
{ fprintf( stderr, "%s: %s%s%s\n", program_name, msg,
fprintf( stderr, "%s: %s", program_name, msg ); ( errcode > 0 ) ? ": " : "",
if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); ( errcode > 0 ) ? strerror( errcode ) : "" );
fputc( '\n', stderr );
}
if( help ) if( help )
fprintf( stderr, "Try '%s --help' for more information.\n", fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name ); invocation_name );
@ -873,10 +892,10 @@ void show_error( const char * const msg, const int errcode, const bool help )
void show_file_error( const char * const filename, const char * const msg, void show_file_error( const char * const filename, const char * const msg,
const int errcode ) const int errcode )
{ {
if( verbosity < 0 ) return; if( verbosity >= 0 )
fprintf( stderr, "%s: %s: %s", program_name, filename, msg ); fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg,
if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); ( errcode > 0 ) ? ": " : "",
fputc( '\n', stderr ); ( errcode > 0 ) ? strerror( errcode ) : "" );
} }
@ -987,7 +1006,7 @@ int main( const int argc, const char * const argv[] )
case 'a': ignore_trailing = false; break; case 'a': ignore_trailing = false; break;
case 'b': member_size = getnum( arg, 100000, max_member_size ); break; case 'b': member_size = getnum( arg, 100000, max_member_size ); break;
case 'c': to_stdout = true; break; case 'c': to_stdout = true; break;
case 'd': program_mode = m_decompress; break; case 'd': set_mode( &program_mode, m_decompress ); break;
case 'f': force = true; break; case 'f': force = true; break;
case 'F': recompress = true; break; case 'F': recompress = true; break;
case 'h': show_help(); return 0; case 'h': show_help(); return 0;
@ -1001,7 +1020,7 @@ int main( const int argc, const char * const argv[] )
case 's': encoder_options.dictionary_size = get_dict_size( arg ); case 's': encoder_options.dictionary_size = get_dict_size( arg );
break; break;
case 'S': volume_size = getnum( arg, 100000, max_volume_size ); break; case 'S': volume_size = getnum( arg, 100000, max_volume_size ); break;
case 't': program_mode = m_test; break; case 't': set_mode( &program_mode, m_test ); break;
case 'v': if( verbosity < 4 ) ++verbosity; break; case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0; case 'V': show_version(); return 0;
case opt_lt: loose_trailing = true; break; case opt_lt: loose_trailing = true; break;
@ -1009,7 +1028,7 @@ int main( const int argc, const char * const argv[] )
} }
} /* end process options */ } /* end process options */
#if defined(__MSVCRT__) || defined(__OS2__) #if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__)
setmode( STDIN_FILENO, O_BINARY ); setmode( STDIN_FILENO, O_BINARY );
setmode( STDOUT_FILENO, O_BINARY ); setmode( STDOUT_FILENO, O_BINARY );
#endif #endif
@ -1029,7 +1048,7 @@ int main( const int argc, const char * const argv[] )
if( !to_stdout && program_mode != m_test && if( !to_stdout && program_mode != m_test &&
( filenames_given || default_output_filename[0] ) ) ( filenames_given || default_output_filename[0] ) )
set_signals(); set_signals( signal_handler );
Pp_init( &pp, filenames, num_filenames ); Pp_init( &pp, filenames, num_filenames );
@ -1109,6 +1128,12 @@ int main( const int argc, const char * const argv[] )
else else
tmp = decompress( infd, &pp, ignore_trailing, tmp = decompress( infd, &pp, ignore_trailing,
loose_trailing, program_mode == m_test ); loose_trailing, program_mode == m_test );
if( close( infd ) != 0 )
{
show_error( input_filename[0] ? "Error closing input file" :
"Error closing stdin", errno, false );
if( tmp < 1 ) tmp = 1;
}
if( tmp > retval ) retval = tmp; if( tmp > retval ) retval = tmp;
if( tmp ) if( tmp )
{ if( program_mode != m_test ) cleanup_and_fail( retval ); { if( program_mode != m_test ) cleanup_and_fail( retval );
@ -1118,7 +1143,6 @@ int main( const int argc, const char * const argv[] )
close_and_set_permissions( in_statsp ); close_and_set_permissions( in_statsp );
if( input_filename[0] ) if( input_filename[0] )
{ {
close( infd );
if( !keep_input_files && !to_stdout && program_mode != m_test && if( !keep_input_files && !to_stdout && program_mode != m_test &&
( program_mode != m_compress || volume_size == 0 ) ) ( program_mode != m_compress || volume_size == 0 ) )
remove( input_filename ); remove( input_filename );

View file

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# check script for Lzlib - Compression library for the lzip format # check script for Lzlib - Compression library for the lzip format
# Copyright (C) 2009-2018 Antonio Diaz Diaz. # Copyright (C) 2009-2019 Antonio Diaz Diaz.
# #
# This script is free software: you have unlimited permission # This script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute and modify it.
@ -39,12 +39,15 @@ test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; }
printf "testing lzlib-%s..." "$2" printf "testing lzlib-%s..." "$2"
"${LZIP}" -fkqm4 in "${LZIP}" -fkqm4 in
{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
[ ! -e in.lz ] || test_failed $LINENO
"${LZIP}" -fkqm274 in "${LZIP}" -fkqm274 in
{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
[ ! -e in.lz ] || test_failed $LINENO
for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do
"${LZIP}" -fkqs $i in "${LZIP}" -fkqs $i in
{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO $i [ $? = 1 ] || test_failed $LINENO $i
[ ! -e in.lz ] || test_failed $LINENO $i
done done
"${LZIP}" -tq in "${LZIP}" -tq in
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
@ -57,6 +60,8 @@ done
"${LZIP}" -dq -o in < "${in_lz}" "${LZIP}" -dq -o in < "${in_lz}"
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
# these are for code coverage # these are for code coverage
"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -t -- nx_file 2> /dev/null "${LZIP}" -t -- nx_file 2> /dev/null
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" --help > /dev/null || test_failed $LINENO "${LZIP}" --help > /dev/null || test_failed $LINENO
@ -89,41 +94,46 @@ cmp in copy || test_failed $LINENO
"${LZIP}" -cd "${testdir}"/test_sync.lz > copy || test_failed $LINENO "${LZIP}" -cd "${testdir}"/test_sync.lz > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
rm -f copy rm -f copy || framework_failure
cat "${in_lz}" > copy.lz || framework_failure cat "${in_lz}" > copy.lz || framework_failure
"${LZIP}" -dk copy.lz || test_failed $LINENO "${LZIP}" -dk copy.lz || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
printf "to be overwritten" > copy || framework_failure printf "to be overwritten" > copy || framework_failure
"${LZIP}" -d copy.lz 2> /dev/null "${LZIP}" -d copy.lz 2> /dev/null
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" -df copy.lz "${LZIP}" -df copy.lz || test_failed $LINENO
{ [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; } || test_failed $LINENO [ ! -e copy.lz ] || test_failed $LINENO
cmp in copy || test_failed $LINENO
rm -f copy rm -f copy || framework_failure
cat "${in_lz}" > copy.lz || framework_failure cat "${in_lz}" > copy.lz || framework_failure
"${LZIP}" -d -S100k copy.lz "${LZIP}" -d -S100k copy.lz || test_failed $LINENO # ignore -S
{ [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; } || test_failed $LINENO [ ! -e copy.lz ] || test_failed $LINENO
cmp in copy || test_failed $LINENO
printf "to be overwritten" > copy || framework_failure printf "to be overwritten" > copy || framework_failure
"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO "${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
rm -f copy rm -f copy || framework_failure
"${LZIP}" -s16 < in > anyothername || test_failed $LINENO "${LZIP}" -s16 < in > anyothername || test_failed $LINENO
"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null "${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null ||
{ [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; } ||
test_failed $LINENO test_failed $LINENO
rm -f copy anyothername.out cmp in copy || test_failed $LINENO
cmp in anyothername.out || test_failed $LINENO
rm -f copy anyothername.out || framework_failure
"${LZIP}" -tq in "${in_lz}" "${LZIP}" -tq in "${in_lz}"
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
"${LZIP}" -tq nx_file.lz "${in_lz}" "${LZIP}" -tq nx_file.lz "${in_lz}"
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" -cdq in "${in_lz}" > copy "${LZIP}" -cdq in "${in_lz}" > copy
{ [ $? = 2 ] && cat copy in | cmp in - ; } || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
cat copy in | cmp in - || test_failed $LINENO
"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy "${LZIP}" -cdq nx_file.lz "${in_lz}" > copy
{ [ $? = 1 ] && cmp in copy ; } || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
rm -f copy cmp in copy || test_failed $LINENO
rm -f copy || framework_failure
cat "${in_lz}" > copy.lz || framework_failure cat "${in_lz}" > copy.lz || framework_failure
for i in 1 2 3 4 5 6 7 ; do for i in 1 2 3 4 5 6 7 ; do
printf "g" >> copy.lz || framework_failure printf "g" >> copy.lz || framework_failure
@ -131,11 +141,15 @@ for i in 1 2 3 4 5 6 7 ; do
[ $? = 2 ] || test_failed $LINENO $i [ $? = 2 ] || test_failed $LINENO $i
done done
"${LZIP}" -dq in copy.lz "${LZIP}" -dq in copy.lz
{ [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; } || [ $? = 2 ] || test_failed $LINENO
test_failed $LINENO [ -e copy.lz ] || test_failed $LINENO
[ ! -e copy ] || test_failed $LINENO
[ ! -e in.out ] || test_failed $LINENO
"${LZIP}" -dq nx_file.lz copy.lz "${LZIP}" -dq nx_file.lz copy.lz
{ [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e nx_file ] && cmp in copy ; } || [ $? = 1 ] || test_failed $LINENO
test_failed $LINENO [ ! -e copy.lz ] || test_failed $LINENO
[ ! -e nx_file ] || test_failed $LINENO
cmp in copy || test_failed $LINENO
cat in in > in2 || framework_failure cat in in > in2 || framework_failure
cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure
@ -150,18 +164,21 @@ cmp in2 copy2 || test_failed $LINENO
printf "\ngarbage" >> copy2.lz || framework_failure printf "\ngarbage" >> copy2.lz || framework_failure
"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO "${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO
rm -f copy2 rm -f copy2 || framework_failure
"${LZIP}" -atq copy2.lz "${LZIP}" -atq copy2.lz
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
"${LZIP}" -atq < copy2.lz "${LZIP}" -atq < copy2.lz
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
"${LZIP}" -adkq copy2.lz "${LZIP}" -adkq copy2.lz
{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
[ ! -e copy2 ] || test_failed $LINENO
"${LZIP}" -adkq -o copy2 < copy2.lz "${LZIP}" -adkq -o copy2 < copy2.lz
{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
[ ! -e copy2 ] || test_failed $LINENO
printf "to be overwritten" > copy2 || framework_failure printf "to be overwritten" > copy2 || framework_failure
"${LZIP}" -df copy2.lz || test_failed $LINENO "${LZIP}" -df copy2.lz || test_failed $LINENO
cmp in2 copy2 || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO
rm -f in2 copy2 || framework_failure
printf "\ntesting compression..." printf "\ntesting compression..."
@ -197,36 +214,37 @@ for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
"${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i "${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i
done done
rm -f out.lz || framework_failure
cat in in in in in in in in > in8 || framework_failure cat in in in in in in in in > in8 || framework_failure
"${LZIP}" -1s12 -S100k in8 || test_failed $LINENO "${LZIP}" -1s12 -S100k in8 || test_failed $LINENO
"${LZIP}" -t in800001.lz in800002.lz || test_failed $LINENO "${LZIP}" -t in800001.lz in800002.lz || test_failed $LINENO
"${LZIP}" -cd in800001.lz in800002.lz | cmp in8 - || test_failed $LINENO "${LZIP}" -cd in800001.lz in800002.lz | cmp in8 - || test_failed $LINENO
rm -f in800001.lz in800002.lz rm -f in800001.lz in800002.lz || framework_failure
"${LZIP}" -1s12 -S100k -o out.lz < in8 || test_failed $LINENO "${LZIP}" -1s12 -S100k -o out.lz < in8 || test_failed $LINENO
"${LZIP}" -t out.lz00001.lz out.lz00002.lz || test_failed $LINENO "${LZIP}" -t out.lz00001.lz out.lz00002.lz || test_failed $LINENO
"${LZIP}" -cd out.lz00001.lz out.lz00002.lz | cmp in8 - || test_failed $LINENO "${LZIP}" -cd out.lz00001.lz out.lz00002.lz | cmp in8 - || test_failed $LINENO
rm -f out.lz00001.lz out.lz00002.lz rm -f out.lz00001.lz out.lz00002.lz || framework_failure
"${LZIP}" -1ks4Ki -b100000 in8 || test_failed $LINENO "${LZIP}" -1ks4Ki -b100000 in8 || test_failed $LINENO
"${LZIP}" -t in8.lz || test_failed $LINENO "${LZIP}" -t in8.lz || test_failed $LINENO
"${LZIP}" -cd in8.lz | cmp in8 - || test_failed $LINENO "${LZIP}" -cd in8.lz | cmp in8 - || test_failed $LINENO
rm -f in8 rm -f in8 || framework_failure
"${LZIP}" -0 -S100k -o out < in8.lz || test_failed $LINENO "${LZIP}" -0 -S100k -o out < in8.lz || test_failed $LINENO
"${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO "${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO
"${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO "${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO
rm -f out00001.lz rm -f out00001.lz || framework_failure
"${LZIP}" -1 -S100k -o out < in8.lz || test_failed $LINENO "${LZIP}" -1 -S100k -o out < in8.lz || test_failed $LINENO
"${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO "${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO
"${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO "${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO
rm -f out00001.lz out00002.lz rm -f out00001.lz out00002.lz || framework_failure
"${LZIP}" -0 -F -S100k in8.lz || test_failed $LINENO "${LZIP}" -0 -F -S100k in8.lz || test_failed $LINENO
"${LZIP}" -t in8.lz00001.lz in8.lz00002.lz || test_failed $LINENO "${LZIP}" -t in8.lz00001.lz in8.lz00002.lz || test_failed $LINENO
"${LZIP}" -cd in8.lz00001.lz in8.lz00002.lz | cmp in8.lz - || test_failed $LINENO "${LZIP}" -cd in8.lz00001.lz in8.lz00002.lz | cmp in8.lz - || test_failed $LINENO
rm -f in8.lz00001.lz in8.lz00002.lz rm -f in8.lz00001.lz in8.lz00002.lz || framework_failure
"${LZIP}" -0kF -b100k in8.lz || test_failed $LINENO "${LZIP}" -0kF -b100k in8.lz || test_failed $LINENO
"${LZIP}" -t in8.lz.lz || test_failed $LINENO "${LZIP}" -t in8.lz.lz || test_failed $LINENO
"${LZIP}" -cd in8.lz.lz | cmp in8.lz - || test_failed $LINENO "${LZIP}" -cd in8.lz.lz | cmp in8.lz - || test_failed $LINENO
rm -f in8.lz in8.lz.lz rm -f in8.lz in8.lz.lz || framework_failure
"${BBEXAMPLE}" in || test_failed $LINENO "${BBEXAMPLE}" in || test_failed $LINENO
"${BBEXAMPLE}" out || test_failed $LINENO "${BBEXAMPLE}" out || test_failed $LINENO
@ -240,28 +258,48 @@ printf "\ntesting bad input..."
headers='LZIp LZiP LZip LzIP LzIp LziP lZIP lZIp lZiP lzIP' headers='LZIp LZiP LZip LzIP LzIp LziP lZIP lZIp lZiP lzIP'
body='\001\014\000\203\377\373\377\377\300\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000' body='\001\014\000\203\377\373\377\377\300\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000'
cat "${in_lz}" > in0.lz cat "${in_lz}" > int.lz
printf "LZIP${body}" >> in0.lz printf "LZIP${body}" >> int.lz
if "${LZIP}" -tq in0.lz ; then if "${LZIP}" -tq int.lz ; then
for header in ${headers} ; do for header in ${headers} ; do
printf "${header}${body}" > in0.lz # first member printf "${header}${body}" > int.lz # first member
"${LZIP}" -tq in0.lz "${LZIP}" -tq int.lz
[ $? = 2 ] || test_failed $LINENO ${header} [ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -tq --loose-trailing in0.lz "${LZIP}" -tq < int.lz
[ $? = 2 ] || test_failed $LINENO ${header} [ $? = 2 ] || test_failed $LINENO ${header}
cat "${in_lz}" > in0.lz "${LZIP}" -cdq int.lz > /dev/null
printf "${header}${body}" >> in0.lz # trailing data
"${LZIP}" -tq in0.lz
[ $? = 2 ] || test_failed $LINENO ${header} [ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -t --loose-trailing in0.lz "${LZIP}" -tq --loose-trailing int.lz
[ $? = 0 ] || test_failed $LINENO ${header} [ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -tq --loose-trailing --trailing-error in0.lz "${LZIP}" -tq --loose-trailing < int.lz
[ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -cdq --loose-trailing int.lz > /dev/null
[ $? = 2 ] || test_failed $LINENO ${header}
cat "${in_lz}" > int.lz
printf "${header}${body}" >> int.lz # trailing data
"${LZIP}" -tq int.lz
[ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -tq < int.lz
[ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -cdq int.lz > /dev/null
[ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -t --loose-trailing int.lz ||
test_failed $LINENO ${header}
"${LZIP}" -t --loose-trailing < int.lz ||
test_failed $LINENO ${header}
"${LZIP}" -cd --loose-trailing int.lz > /dev/null ||
test_failed $LINENO ${header}
"${LZIP}" -tq --loose-trailing --trailing-error int.lz
[ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -tq --loose-trailing --trailing-error < int.lz
[ $? = 2 ] || test_failed $LINENO ${header}
"${LZIP}" -cdq --loose-trailing --trailing-error int.lz > /dev/null
[ $? = 2 ] || test_failed $LINENO ${header} [ $? = 2 ] || test_failed $LINENO ${header}
done done
else else
printf "\nwarning: skipping header test: 'printf' does not work on your system." printf "\nwarning: skipping header test: 'printf' does not work on your system."
fi fi
rm -f in0.lz rm -f int.lz || framework_failure
cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure
if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null &&
@ -280,7 +318,7 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null &&
else else
printf "\nwarning: skipping truncation test: 'dd' does not work on your system." printf "\nwarning: skipping truncation test: 'dd' does not work on your system."
fi fi
rm -f in3.lz trunc.lz rm -f in2.lz in3.lz trunc.lz out || framework_failure
cat "${in_lz}" > ingin.lz || framework_failure cat "${in_lz}" > ingin.lz || framework_failure
printf "g" >> ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure
@ -291,7 +329,7 @@ cmp in copy || test_failed $LINENO
"${LZIP}" -t < ingin.lz || test_failed $LINENO "${LZIP}" -t < ingin.lz || test_failed $LINENO
"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO "${LZIP}" -d < ingin.lz > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
rm -f ingin.lz rm -f copy ingin.lz || framework_failure
echo echo
if [ ${fail} = 0 ] ; then if [ ${fail} = 0 ] ; then