Merging upstream version 1.15~rc1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
03e700319c
commit
dc06553bd5
24 changed files with 472 additions and 466 deletions
3
COPYING
3
COPYING
|
@ -1,8 +1,7 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
|
30
ChangeLog
30
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2024-11-17 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.15-rc1 released.
|
||||
* Remove options '--empty-error' and '--marking-error'.
|
||||
* main.c (Pp_free): New function.
|
||||
* decoder.c (LZd_decode_member): Remove support for Sync Flush marker.
|
||||
* check.sh: Use 'cp' instead of 'cat'.
|
||||
* testsuite: Add em.lz, fox_nz.lz.
|
||||
Remove fox6.lz, fox6_mark.lz, test_em.txt.lz.
|
||||
|
||||
2024-01-21 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.14 released.
|
||||
|
@ -43,13 +53,13 @@
|
|||
2018-02-05 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.10 released.
|
||||
* main.c: New option '--loose-trailing'.
|
||||
* New option '--loose-trailing'.
|
||||
* Improve corrupt header detection to HD=3.
|
||||
* main.c: Show corrupt or truncated header in multimember file.
|
||||
(main): Show final diagnostic when testing multiple files.
|
||||
* Replace 'bits/byte' with inverse compression ratio in output.
|
||||
* Show progress of decompression at verbosity level 2 (-vv).
|
||||
* Show progress of decompression only if stderr is a terminal.
|
||||
* main.c: Show final diagnostic when testing multiple files.
|
||||
* decoder.c (LZd_verify_trailer): Show stored sizes also in hex.
|
||||
Show dictionary size at verbosity level 4 (-vvvv).
|
||||
|
||||
|
@ -67,17 +77,15 @@
|
|||
2016-05-12 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.8 released.
|
||||
* main.c: New option '-a, --trailing-error'.
|
||||
* New option '-a, --trailing-error'.
|
||||
* main.c (main): With '-u', check that output file is regular.
|
||||
* main.c (decompress): Print up to 6 bytes of trailing data
|
||||
when '-vvvv' is specified.
|
||||
(main): Delete '--output' file if infd is a terminal.
|
||||
(main): Don't use stdin more than once.
|
||||
(decompress): Print 6 bytes of trailing data at verbosity level 4.
|
||||
* decoder.c (LZd_verify_trailer): Remove test of final code.
|
||||
* main.c (main): Delete '--output' file if infd is a terminal.
|
||||
* main.c (main): Don't use stdin more than once.
|
||||
* Error messages synced with lzip-1.18.
|
||||
* configure: Avoid warning on some shells when testing for gcc.
|
||||
* check.sh: A POSIX shell is required to run the tests.
|
||||
* check.sh: Don't check error messages.
|
||||
* check.sh: Require a POSIX shell. Don't check error messages.
|
||||
|
||||
2015-05-27 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
|
@ -93,7 +101,7 @@
|
|||
2014-04-11 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.5 released.
|
||||
* main.c: New option '-u, --buffer-size' (low memory mode).
|
||||
* New option '-u, --buffer-size' (low memory mode).
|
||||
* main.c (close_and_set_permissions): Behave like 'cp -p'.
|
||||
|
||||
2013-09-17 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
@ -115,7 +123,7 @@
|
|||
* Version 1.2 released.
|
||||
* Decompression time has been reduced by 12%.
|
||||
* Makefile.in: New targets 'install-as-lzip' and 'install-bin'.
|
||||
* main.c: Use 'setmode' instead of '_setmode' on Windows and OS/2.
|
||||
* (main): Use 'setmode' instead of '_setmode' on Windows and OS/2.
|
||||
|
||||
2012-02-26 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||
|
||||
|
|
11
Makefile.in
11
Makefile.in
|
@ -2,8 +2,8 @@
|
|||
DISTNAME = $(pkgname)-$(pkgversion)
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL) -m 755
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
INSTALL_DIR = $(INSTALL) -d -m 755
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
SHELL = /bin/sh
|
||||
CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1
|
||||
|
||||
|
@ -30,7 +30,8 @@ main.o : main.c
|
|||
|
||||
# prevent 'make' from trying to remake source files
|
||||
$(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ;
|
||||
%.h %.c : ;
|
||||
MAKEFLAGS += -r
|
||||
.SUFFIXES :
|
||||
|
||||
$(objs) : Makefile
|
||||
carg_parser.o : carg_parser.h
|
||||
|
@ -122,12 +123,10 @@ dist : doc
|
|||
$(DISTNAME)/*.c \
|
||||
$(DISTNAME)/testsuite/check.sh \
|
||||
$(DISTNAME)/testsuite/test.txt \
|
||||
$(DISTNAME)/testsuite/em.lz \
|
||||
$(DISTNAME)/testsuite/fox.lz \
|
||||
$(DISTNAME)/testsuite/fox_*.lz \
|
||||
$(DISTNAME)/testsuite/fox6.lz \
|
||||
$(DISTNAME)/testsuite/fox6_mark.lz \
|
||||
$(DISTNAME)/testsuite/test.txt.lz \
|
||||
$(DISTNAME)/testsuite/test_em.txt.lz
|
||||
$(DISTNAME)/testsuite/test.txt.lz
|
||||
rm -f $(DISTNAME)
|
||||
lzip -v -9 $(DISTNAME).tar
|
||||
|
||||
|
|
27
NEWS
27
NEWS
|
@ -1,24 +1,9 @@
|
|||
Changes in version 1.14:
|
||||
Changes in version 1.15:
|
||||
|
||||
The option '--empty-error', which forces exit status 2 if any empty member
|
||||
is found, has been added.
|
||||
lunzip now exits with error status 2 if any empty member is found in a
|
||||
multimember file.
|
||||
|
||||
The option '--marking-error', which forces exit status 2 if the first LZMA
|
||||
byte is non-zero in any member, has been added.
|
||||
lunzip now exits with error status 2 if the first byte of the LZMA stream is
|
||||
not 0.
|
||||
|
||||
File diagnostics have been reformatted as 'PROGRAM: FILE: MESSAGE'.
|
||||
|
||||
Diagnostics caused by invalid arguments to command-line options now show the
|
||||
argument and the name of the option.
|
||||
|
||||
The option '-o, --output' now preserves dates, permissions, and ownership of
|
||||
the file when decompressing exactly one file.
|
||||
|
||||
The option '-o, --output' now creates missing intermediate directories when
|
||||
writing to a file.
|
||||
|
||||
The variable MAKEINFO has been added to configure and Makefile.in.
|
||||
|
||||
It has been documented in INSTALL that when choosing a C standard, the POSIX
|
||||
features need to be enabled explicitly:
|
||||
./configure CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500'
|
||||
Options '--empty-error' and '--marking-error' have been removed.
|
||||
|
|
27
README
27
README
|
@ -2,20 +2,19 @@ Description
|
|||
|
||||
Lunzip is a decompressor for the lzip format written in C. Its small size
|
||||
makes it well suited for embedded devices or software installers that need
|
||||
to decompress files but don't need compression capabilities. Lunzip is
|
||||
compatible with lzip 1.4 or newer.
|
||||
to decompress files but don't need compression capabilities.
|
||||
|
||||
Lzip is a lossless data compressor with a user interface similar to the one
|
||||
of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov
|
||||
chain-Algorithm' (LZMA) stream format to maximize interoperability. The
|
||||
maximum dictionary size is 512 MiB so that any lzip file can be decompressed
|
||||
on 32-bit machines. Lzip provides accurate and robust 3-factor integrity
|
||||
checking. Lzip can compress about as fast as gzip (lzip -0) or compress most
|
||||
files more than bzip2 (lzip -9). Decompression speed is intermediate between
|
||||
gzip and bzip2. Lzip is better than gzip and bzip2 from a data recovery
|
||||
perspective. Lzip has been designed, written, and tested with great care to
|
||||
replace gzip and bzip2 as the standard general-purpose compressed format for
|
||||
Unix-like systems.
|
||||
of gzip or bzip2. Lzip uses a simplified form of LZMA (Lempel-Ziv-Markov
|
||||
chain-Algorithm) designed to achieve complete interoperability between
|
||||
implementations. The maximum dictionary size is 512 MiB so that any lzip
|
||||
file can be decompressed on 32-bit machines. Lzip provides accurate and
|
||||
robust 3-factor integrity checking. 'lzip -0' compresses about as fast as
|
||||
gzip, while 'lzip -9' compresses most files more than bzip2. Decompression
|
||||
speed is intermediate between gzip and bzip2. Lzip provides better data
|
||||
recovery capabilities than gzip and bzip2. Lzip has been designed, written,
|
||||
and tested with great care to replace gzip and bzip2 as general-purpose
|
||||
compressed format for Unix-like systems.
|
||||
|
||||
The lzip file format is designed for data sharing and long-term archiving,
|
||||
taking into account both data integrity and decoder availability:
|
||||
|
@ -65,8 +64,8 @@ The amount of memory required by lunzip to decompress a file is about 46 kB
|
|||
larger than the dictionary size used to compress that file, unless
|
||||
'--buffer-size' is specified.
|
||||
|
||||
Lunzip attempts to guess the name for the decompressed file from that of
|
||||
the compressed file as follows:
|
||||
When decompressing, lunzip attempts to guess the name for the decompressed
|
||||
file from that of the compressed file as follows:
|
||||
|
||||
filename.lz becomes filename
|
||||
filename.tlz becomes filename.tar
|
||||
|
|
|
@ -32,15 +32,15 @@ static void * ap_resize_buffer( void * buf, const int min_size )
|
|||
}
|
||||
|
||||
|
||||
static char push_back_record( struct Arg_parser * const ap, const int code,
|
||||
static char push_back_record( Arg_parser * const ap, const int code,
|
||||
const char * const long_name,
|
||||
const char * const argument )
|
||||
{
|
||||
struct ap_Record * p;
|
||||
ap_Record * p;
|
||||
void * tmp = ap_resize_buffer( ap->data,
|
||||
( ap->data_size + 1 ) * sizeof (struct ap_Record) );
|
||||
( ap->data_size + 1 ) * sizeof (ap_Record) );
|
||||
if( !tmp ) return 0;
|
||||
ap->data = (struct ap_Record *)tmp;
|
||||
ap->data = (ap_Record *)tmp;
|
||||
p = &(ap->data[ap->data_size]);
|
||||
p->code = code;
|
||||
if( long_name )
|
||||
|
@ -71,7 +71,7 @@ static char push_back_record( struct Arg_parser * const ap, const int code,
|
|||
}
|
||||
|
||||
|
||||
static char add_error( struct Arg_parser * const ap, const char * const msg )
|
||||
static char add_error( Arg_parser * const ap, const char * const msg )
|
||||
{
|
||||
const int len = strlen( msg );
|
||||
void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 );
|
||||
|
@ -83,7 +83,7 @@ static char add_error( struct Arg_parser * const ap, const char * const msg )
|
|||
}
|
||||
|
||||
|
||||
static void free_data( struct Arg_parser * const ap )
|
||||
static void free_data( Arg_parser * const ap )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < ap->data_size; ++i )
|
||||
|
@ -94,10 +94,9 @@ static void free_data( struct Arg_parser * const ap )
|
|||
|
||||
|
||||
/* Return 0 only if out of memory. */
|
||||
static char parse_long_option( struct Arg_parser * const ap,
|
||||
static char parse_long_option( Arg_parser * const ap,
|
||||
const char * const opt, const char * const arg,
|
||||
const struct ap_Option options[],
|
||||
int * const argindp )
|
||||
const ap_Option options[], int * const argindp )
|
||||
{
|
||||
unsigned len;
|
||||
int index = -1, i;
|
||||
|
@ -148,21 +147,21 @@ static char parse_long_option( struct Arg_parser * const ap,
|
|||
add_error( ap, "' requires an argument" );
|
||||
return 1;
|
||||
}
|
||||
return push_back_record( ap, options[index].code,
|
||||
options[index].long_name, &opt[len+3] );
|
||||
return push_back_record( ap, options[index].code, options[index].long_name,
|
||||
&opt[len+3] ); /* argument may be empty */
|
||||
}
|
||||
|
||||
if( options[index].has_arg == ap_yes )
|
||||
if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme )
|
||||
{
|
||||
if( !arg || !arg[0] )
|
||||
if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) )
|
||||
{
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].long_name );
|
||||
add_error( ap, "' requires an argument" );
|
||||
return 1;
|
||||
}
|
||||
++*argindp;
|
||||
return push_back_record( ap, options[index].code,
|
||||
options[index].long_name, arg );
|
||||
return push_back_record( ap, options[index].code, options[index].long_name,
|
||||
arg ); /* argument may be empty */
|
||||
}
|
||||
|
||||
return push_back_record( ap, options[index].code,
|
||||
|
@ -171,10 +170,9 @@ static char parse_long_option( struct Arg_parser * const ap,
|
|||
|
||||
|
||||
/* Return 0 only if out of memory. */
|
||||
static char parse_short_option( struct Arg_parser * const ap,
|
||||
static char parse_short_option( Arg_parser * const ap,
|
||||
const char * const opt, const char * const arg,
|
||||
const struct ap_Option options[],
|
||||
int * const argindp )
|
||||
const ap_Option options[], int * const argindp )
|
||||
{
|
||||
int cind = 1; /* character index in opt */
|
||||
|
||||
|
@ -204,15 +202,15 @@ static char parse_short_option( struct Arg_parser * const ap,
|
|||
if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0;
|
||||
++*argindp; cind = 0;
|
||||
}
|
||||
else if( options[index].has_arg == ap_yes )
|
||||
else if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme )
|
||||
{
|
||||
if( !arg || !arg[0] )
|
||||
if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) )
|
||||
{
|
||||
add_error( ap, "option requires an argument -- '" );
|
||||
add_error( ap, code_str ); add_error( ap, "'" );
|
||||
return 1;
|
||||
}
|
||||
++*argindp; cind = 0;
|
||||
++*argindp; cind = 0; /* argument may be empty */
|
||||
if( !push_back_record( ap, c, 0, arg ) ) return 0;
|
||||
}
|
||||
else if( !push_back_record( ap, c, 0, 0 ) ) return 0;
|
||||
|
@ -221,9 +219,9 @@ static char parse_short_option( struct Arg_parser * const ap,
|
|||
}
|
||||
|
||||
|
||||
char ap_init( struct Arg_parser * const ap,
|
||||
char ap_init( Arg_parser * const ap,
|
||||
const int argc, const char * const argv[],
|
||||
const struct ap_Option options[], const char in_order )
|
||||
const ap_Option options[], const char in_order )
|
||||
{
|
||||
const char ** non_options = 0; /* skipped non-options */
|
||||
int non_options_size = 0; /* number of skipped non-options */
|
||||
|
@ -282,7 +280,7 @@ out: if( non_options ) free( non_options );
|
|||
}
|
||||
|
||||
|
||||
void ap_free( struct Arg_parser * const ap )
|
||||
void ap_free( Arg_parser * const ap )
|
||||
{
|
||||
free_data( ap );
|
||||
if( ap->error ) { free( ap->error ); ap->error = 0; }
|
||||
|
@ -290,29 +288,25 @@ void ap_free( struct Arg_parser * const ap )
|
|||
}
|
||||
|
||||
|
||||
const char * ap_error( const struct Arg_parser * const ap )
|
||||
{ return ap->error; }
|
||||
const char * ap_error( const Arg_parser * const ap ) { return ap->error; }
|
||||
|
||||
int ap_arguments( const Arg_parser * const ap ) { return ap->data_size; }
|
||||
|
||||
int ap_arguments( const struct Arg_parser * const ap )
|
||||
{ return ap->data_size; }
|
||||
|
||||
|
||||
int ap_code( const struct Arg_parser * const ap, const int i )
|
||||
int ap_code( const Arg_parser * const ap, const int i )
|
||||
{
|
||||
if( i < 0 || i >= ap_arguments( ap ) ) return 0;
|
||||
return ap->data[i].code;
|
||||
}
|
||||
|
||||
|
||||
const char * ap_parsed_name( const struct Arg_parser * const ap, const int i )
|
||||
const char * ap_parsed_name( const Arg_parser * const ap, const int i )
|
||||
{
|
||||
if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].parsed_name ) return "";
|
||||
return ap->data[i].parsed_name;
|
||||
}
|
||||
|
||||
|
||||
const char * ap_argument( const struct Arg_parser * const ap, const int i )
|
||||
const char * ap_argument( const Arg_parser * const ap, const int i )
|
||||
{
|
||||
if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].argument ) return "";
|
||||
return ap->data[i].argument;
|
||||
|
|
|
@ -37,60 +37,65 @@
|
|||
The argument '--' terminates all options; any following arguments are
|
||||
treated as non-option arguments, even if they begin with a hyphen.
|
||||
|
||||
The syntax for optional option arguments is '-<short_option><argument>'
|
||||
(without whitespace), or '--<long_option>=<argument>'.
|
||||
The syntax of options with an optional argument is
|
||||
'-<short_option><argument>' (without whitespace), or
|
||||
'--<long_option>=<argument>'.
|
||||
|
||||
The syntax of options with an empty argument is '-<short_option> ""',
|
||||
'--<long_option> ""', or '--<long_option>=""'.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ap_Has_arg { ap_no, ap_yes, ap_maybe };
|
||||
/* ap_yme = yes but maybe empty */
|
||||
typedef enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme } ap_Has_arg;
|
||||
|
||||
struct ap_Option
|
||||
typedef struct ap_Option
|
||||
{
|
||||
int code; /* Short option letter or code ( code != 0 ) */
|
||||
const char * long_name; /* Long option name (maybe null) */
|
||||
enum ap_Has_arg has_arg;
|
||||
};
|
||||
ap_Has_arg has_arg;
|
||||
} ap_Option;
|
||||
|
||||
|
||||
struct ap_Record
|
||||
typedef struct ap_Record
|
||||
{
|
||||
int code;
|
||||
char * parsed_name;
|
||||
char * argument;
|
||||
};
|
||||
} ap_Record;
|
||||
|
||||
|
||||
struct Arg_parser
|
||||
typedef struct Arg_parser
|
||||
{
|
||||
struct ap_Record * data;
|
||||
ap_Record * data;
|
||||
char * error;
|
||||
int data_size;
|
||||
int error_size;
|
||||
};
|
||||
} Arg_parser;
|
||||
|
||||
|
||||
char ap_init( struct Arg_parser * const ap,
|
||||
char ap_init( Arg_parser * const ap,
|
||||
const int argc, const char * const argv[],
|
||||
const struct ap_Option options[], const char in_order );
|
||||
const ap_Option options[], const char in_order );
|
||||
|
||||
void ap_free( struct Arg_parser * const ap );
|
||||
void ap_free( Arg_parser * const ap );
|
||||
|
||||
const char * ap_error( const struct Arg_parser * const ap );
|
||||
const char * ap_error( const Arg_parser * const ap );
|
||||
|
||||
/* The number of arguments parsed. May be different from argc. */
|
||||
int ap_arguments( const struct Arg_parser * const ap );
|
||||
int ap_arguments( const Arg_parser * const ap );
|
||||
|
||||
/* If ap_code( i ) is 0, ap_argument( i ) is a non-option.
|
||||
Else ap_argument( i ) is the option's argument (or empty). */
|
||||
int ap_code( const struct Arg_parser * const ap, const int i );
|
||||
int ap_code( const Arg_parser * const ap, const int i );
|
||||
|
||||
/* Full name of the option parsed (short or long). */
|
||||
const char * ap_parsed_name( const struct Arg_parser * const ap, const int i );
|
||||
const char * ap_parsed_name( const Arg_parser * const ap, const int i );
|
||||
|
||||
const char * ap_argument( const struct Arg_parser * const ap, const int i );
|
||||
const char * ap_argument( const Arg_parser * const ap, const int i );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -6,7 +6,7 @@
|
|||
# to copy, distribute, and modify it.
|
||||
|
||||
pkgname=lunzip
|
||||
pkgversion=1.14
|
||||
pkgversion=1.15-rc1
|
||||
progname=lunzip
|
||||
srctrigger=doc/${progname}.1
|
||||
|
||||
|
@ -109,7 +109,7 @@ while [ $# != 0 ] ; do
|
|||
exit 1 ;;
|
||||
esac
|
||||
|
||||
# Check if the option took a separate argument
|
||||
# Check whether the option took a separate argument
|
||||
if [ "${arg2}" = yes ] ; then
|
||||
if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift
|
||||
else echo "configure: Missing argument to '${option}'" 1>&2
|
||||
|
|
63
decoder.c
63
decoder.c
|
@ -78,14 +78,14 @@ unsigned seek_read_back( const int fd, uint8_t * const buf, const int size,
|
|||
}
|
||||
|
||||
|
||||
bool Rd_read_block( struct Range_decoder * const rdec )
|
||||
bool Rd_read_block( Range_decoder * const rdec )
|
||||
{
|
||||
if( !rdec->at_stream_end )
|
||||
{
|
||||
rdec->stream_pos = readblock( rdec->infd, rdec->buffer, rd_buffer_size );
|
||||
if( rdec->stream_pos != rd_buffer_size && errno )
|
||||
{ show_error( "Read error", errno, false ); cleanup_and_fail( 1 ); }
|
||||
rdec->at_stream_end = ( rdec->stream_pos < rd_buffer_size );
|
||||
rdec->at_stream_end = rdec->stream_pos < rd_buffer_size;
|
||||
rdec->partial_member_pos += rdec->pos;
|
||||
rdec->pos = 0;
|
||||
show_dprogress( 0, 0, 0, 0 );
|
||||
|
@ -94,7 +94,7 @@ bool Rd_read_block( struct Range_decoder * const rdec )
|
|||
}
|
||||
|
||||
|
||||
void LZd_flush_data( struct LZ_decoder * const d )
|
||||
void LZd_flush_data( LZ_decoder * const d )
|
||||
{
|
||||
if( d->pos > d->stream_pos )
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ void LZd_flush_data( struct LZ_decoder * const d )
|
|||
CRC32_update_buf( &d->crc, d->buffer + d->stream_pos, size );
|
||||
if( d->outfd >= 0 &&
|
||||
writeblock( d->outfd, d->buffer + d->stream_pos, size ) != size )
|
||||
{ show_error( "Write error", errno, false ); cleanup_and_fail( 1 ); }
|
||||
{ show_error( write_error_msg, errno, false ); cleanup_and_fail( 1 ); }
|
||||
if( d->pos >= d->buffer_size )
|
||||
{ d->partial_data_pos += d->pos; d->pos = 0;
|
||||
if( d->partial_data_pos >= d->dictionary_size ) d->pos_wrapped = true; }
|
||||
|
@ -111,9 +111,7 @@ void LZd_flush_data( struct LZ_decoder * const d )
|
|||
}
|
||||
|
||||
|
||||
static int LZd_check_trailer( struct LZ_decoder * const d,
|
||||
struct Pretty_print * const pp,
|
||||
const bool ignore_empty )
|
||||
static bool LZd_check_trailer( LZ_decoder * const d, Pretty_print * const pp )
|
||||
{
|
||||
Lzip_trailer trailer;
|
||||
int size = Rd_read_data( d->rdec, trailer, Lt_size );
|
||||
|
@ -158,8 +156,7 @@ static int LZd_check_trailer( struct LZ_decoder * const d,
|
|||
fprintf( stderr, "Member size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
||||
tm_size, tm_size, member_size, member_size ); }
|
||||
}
|
||||
if( error ) return 3;
|
||||
if( !ignore_empty && data_size == 0 ) return 5;
|
||||
if( error ) return false;
|
||||
if( verbosity >= 2 )
|
||||
{
|
||||
if( verbosity >= 4 ) show_header( d->dictionary_size );
|
||||
|
@ -174,18 +171,16 @@ static int LZd_check_trailer( struct LZ_decoder * const d,
|
|||
if( verbosity >= 3 )
|
||||
fprintf( stderr, "%9llu out, %8llu in. ", data_size, member_size );
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Return value: 0 = OK, 1 = decoder error, 2 = unexpected EOF,
|
||||
3 = trailer error, 4 = unknown marker found,
|
||||
5 = empty member found, 6 = marked member found. */
|
||||
int LZd_decode_member( struct LZ_decoder * const d,
|
||||
const struct Cl_options * const cl_opts,
|
||||
struct Pretty_print * const pp )
|
||||
5 = nonzero first LZMA byte found. */
|
||||
int LZd_decode_member( LZ_decoder * const d, Pretty_print * const pp )
|
||||
{
|
||||
struct Range_decoder * const rdec = d->rdec;
|
||||
Range_decoder * const rdec = d->rdec;
|
||||
Bit_model bm_literal[1<<literal_context_bits][0x300];
|
||||
Bit_model bm_match[states][pos_states];
|
||||
Bit_model bm_rep[states];
|
||||
|
@ -196,8 +191,8 @@ int LZd_decode_member( struct LZ_decoder * const d,
|
|||
Bit_model bm_dis_slot[len_states][1<<dis_slot_bits];
|
||||
Bit_model bm_dis[modeled_distances-end_dis_model+1];
|
||||
Bit_model bm_align[dis_align_size];
|
||||
struct Len_model match_len_model;
|
||||
struct Len_model rep_len_model;
|
||||
Len_model match_len_model;
|
||||
Len_model rep_len_model;
|
||||
unsigned rep0 = 0; /* rep[0-3] latest four distances */
|
||||
unsigned rep1 = 0; /* used for efficient coding of */
|
||||
unsigned rep2 = 0; /* repeated distances */
|
||||
|
@ -218,7 +213,7 @@ int LZd_decode_member( struct LZ_decoder * const d,
|
|||
Lm_init( &match_len_model );
|
||||
Lm_init( &rep_len_model );
|
||||
|
||||
if( !Rd_load( rdec, cl_opts->ignore_marking ) ) return 6;
|
||||
if( !Rd_load( rdec ) ) return 5;
|
||||
while( !Rd_finished( rdec ) )
|
||||
{
|
||||
const int pos_state = LZd_data_position( d ) & pos_state_mask;
|
||||
|
@ -263,39 +258,33 @@ int LZd_decode_member( struct LZ_decoder * const d,
|
|||
}
|
||||
else /* match */
|
||||
{
|
||||
rep3 = rep2; rep2 = rep1; rep1 = rep0;
|
||||
len = Rd_decode_len( rdec, &match_len_model, pos_state );
|
||||
unsigned distance = Rd_decode_tree6( rdec, bm_dis_slot[get_len_state(len)] );
|
||||
if( distance >= start_dis_model )
|
||||
rep0 = Rd_decode_tree6( rdec, bm_dis_slot[get_len_state(len)] );
|
||||
if( rep0 >= start_dis_model )
|
||||
{
|
||||
const unsigned dis_slot = distance;
|
||||
const unsigned dis_slot = rep0;
|
||||
const int direct_bits = ( dis_slot >> 1 ) - 1;
|
||||
distance = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
|
||||
rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
|
||||
if( dis_slot < end_dis_model )
|
||||
distance += Rd_decode_tree_reversed( rdec,
|
||||
bm_dis + ( distance - dis_slot ), direct_bits );
|
||||
rep0 += Rd_decode_tree_reversed( rdec, bm_dis + ( rep0 - dis_slot ),
|
||||
direct_bits );
|
||||
else
|
||||
{
|
||||
distance +=
|
||||
Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;
|
||||
distance += Rd_decode_tree_reversed4( rdec, bm_align );
|
||||
if( distance == 0xFFFFFFFFU ) /* marker found */
|
||||
rep0 += Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;
|
||||
rep0 += Rd_decode_tree_reversed4( rdec, bm_align );
|
||||
if( rep0 == 0xFFFFFFFFU ) /* marker found */
|
||||
{
|
||||
Rd_normalize( rdec );
|
||||
LZd_flush_data( d );
|
||||
if( len == min_match_len ) /* End Of Stream marker */
|
||||
return LZd_check_trailer( d, pp, cl_opts->ignore_empty );
|
||||
if( len == min_match_len + 1 ) /* Sync Flush marker */
|
||||
{ Rd_load( rdec, true ); continue; }
|
||||
if( verbosity >= 0 )
|
||||
{
|
||||
Pp_show_msg( pp, 0 );
|
||||
fprintf( stderr, "Unsupported marker code '%d'\n", len );
|
||||
}
|
||||
{ if( LZd_check_trailer( d, pp ) ) return 0; else return 3; }
|
||||
if( verbosity >= 0 ) { Pp_show_msg( pp, 0 );
|
||||
fprintf( stderr, "Unsupported marker code '%d'\n", len ); }
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance;
|
||||
state = St_set_match( state );
|
||||
if( rep0 >= d->dictionary_size ||
|
||||
( !d->pos_wrapped && rep0 >= LZd_data_position( d ) ) )
|
||||
|
|
94
decoder.h
94
decoder.h
|
@ -29,9 +29,9 @@ struct Range_decoder
|
|||
bool at_stream_end;
|
||||
};
|
||||
|
||||
bool Rd_read_block( struct Range_decoder * const rdec );
|
||||
bool Rd_read_block( Range_decoder * const rdec );
|
||||
|
||||
static inline bool Rd_init( struct Range_decoder * const rdec, const int ifd )
|
||||
static inline bool Rd_init( Range_decoder * const rdec, const int ifd )
|
||||
{
|
||||
rdec->partial_member_pos = 0;
|
||||
rdec->buffer = (uint8_t *)malloc( rd_buffer_size );
|
||||
|
@ -45,27 +45,27 @@ static inline bool Rd_init( struct Range_decoder * const rdec, const int ifd )
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void Rd_free( struct Range_decoder * const rdec )
|
||||
static inline void Rd_free( Range_decoder * const rdec )
|
||||
{ free( rdec->buffer ); }
|
||||
|
||||
static inline bool Rd_finished( struct Range_decoder * const rdec )
|
||||
static inline bool Rd_finished( Range_decoder * const rdec )
|
||||
{ return rdec->pos >= rdec->stream_pos && !Rd_read_block( rdec ); }
|
||||
|
||||
static inline unsigned long long
|
||||
Rd_member_position( const struct Range_decoder * const rdec )
|
||||
Rd_member_position( const Range_decoder * const rdec )
|
||||
{ return rdec->partial_member_pos + rdec->pos; }
|
||||
|
||||
static inline void Rd_reset_member_position( struct Range_decoder * const rdec )
|
||||
static inline void Rd_reset_member_position( Range_decoder * const rdec )
|
||||
{ rdec->partial_member_pos = 0; rdec->partial_member_pos -= rdec->pos; }
|
||||
|
||||
static inline uint8_t Rd_get_byte( struct Range_decoder * const rdec )
|
||||
static inline uint8_t Rd_get_byte( Range_decoder * const rdec )
|
||||
{
|
||||
/* 0xFF avoids decoder error if member is truncated at EOS marker */
|
||||
if( Rd_finished( rdec ) ) return 0xFF;
|
||||
return rdec->buffer[rdec->pos++];
|
||||
}
|
||||
|
||||
static inline int Rd_read_data( struct Range_decoder * const rdec,
|
||||
static inline int Rd_read_data( Range_decoder * const rdec,
|
||||
uint8_t * const outbuf, const int size )
|
||||
{
|
||||
int sz = 0;
|
||||
|
@ -79,25 +79,24 @@ static inline int Rd_read_data( struct Range_decoder * const rdec,
|
|||
return sz;
|
||||
}
|
||||
|
||||
static inline bool Rd_load( struct Range_decoder * const rdec,
|
||||
const bool ignore_marking )
|
||||
static inline bool Rd_load( Range_decoder * const rdec )
|
||||
{
|
||||
int i;
|
||||
rdec->code = 0;
|
||||
rdec->range = 0xFFFFFFFFU;
|
||||
/* check and discard first byte of the LZMA stream */
|
||||
if( Rd_get_byte( rdec ) != 0 && !ignore_marking ) return false;
|
||||
for( i = 0; i < 4; ++i ) rdec->code = (rdec->code << 8) | Rd_get_byte( rdec );
|
||||
/* check first byte of the LZMA stream */
|
||||
if( Rd_get_byte( rdec ) != 0 ) return false;
|
||||
int i; for( i = 0; i < 4; ++i )
|
||||
rdec->code = (rdec->code << 8) | Rd_get_byte( rdec );
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void Rd_normalize( struct Range_decoder * const rdec )
|
||||
static inline void Rd_normalize( Range_decoder * const rdec )
|
||||
{
|
||||
if( rdec->range <= 0x00FFFFFFU )
|
||||
{ rdec->range <<= 8; rdec->code = (rdec->code << 8) | Rd_get_byte( rdec ); }
|
||||
}
|
||||
|
||||
static inline unsigned Rd_decode( struct Range_decoder * const rdec,
|
||||
static inline unsigned Rd_decode( Range_decoder * const rdec,
|
||||
const int num_bits )
|
||||
{
|
||||
unsigned symbol = 0;
|
||||
|
@ -108,14 +107,14 @@ static inline unsigned Rd_decode( struct Range_decoder * const rdec,
|
|||
rdec->range >>= 1;
|
||||
/* symbol <<= 1; */
|
||||
/* if( rdec->code >= rdec->range ) { rdec->code -= rdec->range; symbol |= 1; } */
|
||||
const bool bit = ( rdec->code >= rdec->range );
|
||||
const bool bit = rdec->code >= rdec->range;
|
||||
symbol <<= 1; symbol += bit;
|
||||
rdec->code -= rdec->range & ( 0U - bit );
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static inline unsigned Rd_decode_bit( struct Range_decoder * const rdec,
|
||||
static inline unsigned Rd_decode_bit( Range_decoder * const rdec,
|
||||
Bit_model * const probability )
|
||||
{
|
||||
Rd_normalize( rdec );
|
||||
|
@ -135,7 +134,7 @@ static inline unsigned Rd_decode_bit( struct Range_decoder * const rdec,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void Rd_decode_symbol_bit( struct Range_decoder * const rdec,
|
||||
static inline void Rd_decode_symbol_bit( Range_decoder * const rdec,
|
||||
Bit_model * const probability, unsigned * symbol )
|
||||
{
|
||||
Rd_normalize( rdec );
|
||||
|
@ -155,7 +154,7 @@ static inline void Rd_decode_symbol_bit( struct Range_decoder * const rdec,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void Rd_decode_symbol_bit_reversed( struct Range_decoder * const rdec,
|
||||
static inline void Rd_decode_symbol_bit_reversed( Range_decoder * const rdec,
|
||||
Bit_model * const probability, unsigned * model,
|
||||
unsigned * symbol, const int i )
|
||||
{
|
||||
|
@ -177,7 +176,7 @@ static inline void Rd_decode_symbol_bit_reversed( struct Range_decoder * const r
|
|||
}
|
||||
}
|
||||
|
||||
static inline unsigned Rd_decode_tree6( struct Range_decoder * const rdec,
|
||||
static inline unsigned Rd_decode_tree6( Range_decoder * const rdec,
|
||||
Bit_model bm[] )
|
||||
{
|
||||
unsigned symbol = 1;
|
||||
|
@ -190,7 +189,7 @@ static inline unsigned Rd_decode_tree6( struct Range_decoder * const rdec,
|
|||
return symbol & 0x3F;
|
||||
}
|
||||
|
||||
static inline unsigned Rd_decode_tree8( struct Range_decoder * const rdec,
|
||||
static inline unsigned Rd_decode_tree8( Range_decoder * const rdec,
|
||||
Bit_model bm[] )
|
||||
{
|
||||
unsigned symbol = 1;
|
||||
|
@ -206,7 +205,7 @@ static inline unsigned Rd_decode_tree8( struct Range_decoder * const rdec,
|
|||
}
|
||||
|
||||
static inline unsigned
|
||||
Rd_decode_tree_reversed( struct Range_decoder * const rdec,
|
||||
Rd_decode_tree_reversed( Range_decoder * const rdec,
|
||||
Bit_model bm[], const int num_bits )
|
||||
{
|
||||
unsigned model = 1;
|
||||
|
@ -218,7 +217,7 @@ Rd_decode_tree_reversed( struct Range_decoder * const rdec,
|
|||
}
|
||||
|
||||
static inline unsigned
|
||||
Rd_decode_tree_reversed4( struct Range_decoder * const rdec, Bit_model bm[] )
|
||||
Rd_decode_tree_reversed4( Range_decoder * const rdec, Bit_model bm[] )
|
||||
{
|
||||
unsigned model = 1;
|
||||
unsigned symbol = 0;
|
||||
|
@ -229,7 +228,7 @@ Rd_decode_tree_reversed4( struct Range_decoder * const rdec, Bit_model bm[] )
|
|||
return symbol;
|
||||
}
|
||||
|
||||
static inline unsigned Rd_decode_matched( struct Range_decoder * const rdec,
|
||||
static inline unsigned Rd_decode_matched( Range_decoder * const rdec,
|
||||
Bit_model bm[], unsigned match_byte )
|
||||
{
|
||||
unsigned symbol = 1;
|
||||
|
@ -244,8 +243,8 @@ static inline unsigned Rd_decode_matched( struct Range_decoder * const rdec,
|
|||
}
|
||||
}
|
||||
|
||||
static inline unsigned Rd_decode_len( struct Range_decoder * const rdec,
|
||||
struct Len_model * const lm,
|
||||
static inline unsigned Rd_decode_len( Range_decoder * const rdec,
|
||||
Len_model * const lm,
|
||||
const int pos_state )
|
||||
{
|
||||
Bit_model * bm;
|
||||
|
@ -269,10 +268,10 @@ len3:
|
|||
}
|
||||
|
||||
|
||||
struct LZ_decoder
|
||||
typedef struct LZ_decoder
|
||||
{
|
||||
unsigned long long partial_data_pos;
|
||||
struct Range_decoder * rdec;
|
||||
Range_decoder * rdec;
|
||||
unsigned dictionary_size;
|
||||
unsigned buffer_size;
|
||||
uint8_t * buffer; /* output buffer */
|
||||
|
@ -281,17 +280,17 @@ struct LZ_decoder
|
|||
uint32_t crc;
|
||||
int outfd; /* output file descriptor */
|
||||
bool pos_wrapped;
|
||||
};
|
||||
} LZ_decoder;
|
||||
|
||||
void LZd_flush_data( struct LZ_decoder * const d );
|
||||
void LZd_flush_data( LZ_decoder * const d );
|
||||
|
||||
unsigned seek_read_back( const int fd, uint8_t * const buf, const int size,
|
||||
const int offset );
|
||||
|
||||
static inline uint8_t LZd_peek_prev( const struct LZ_decoder * const d )
|
||||
static inline uint8_t LZd_peek_prev( const LZ_decoder * const d )
|
||||
{ return d->buffer[((d->pos > 0) ? d->pos : d->buffer_size)-1]; }
|
||||
|
||||
static inline uint8_t LZd_peek( const struct LZ_decoder * const d,
|
||||
static inline uint8_t LZd_peek( const LZ_decoder * const d,
|
||||
const unsigned distance )
|
||||
{
|
||||
uint8_t b;
|
||||
|
@ -304,27 +303,27 @@ static inline uint8_t LZd_peek( const struct LZ_decoder * const d,
|
|||
return b;
|
||||
}
|
||||
|
||||
static inline void LZd_put_byte( struct LZ_decoder * const d, const uint8_t b )
|
||||
static inline void LZd_put_byte( LZ_decoder * const d, const uint8_t b )
|
||||
{
|
||||
d->buffer[d->pos] = b;
|
||||
if( ++d->pos >= d->buffer_size ) LZd_flush_data( d );
|
||||
}
|
||||
|
||||
static inline void LZd_copy_block( struct LZ_decoder * const d,
|
||||
static inline void LZd_copy_block( LZ_decoder * const d,
|
||||
const unsigned distance, unsigned len )
|
||||
{
|
||||
unsigned lpos = d->pos, i = lpos - distance - 1;
|
||||
bool fast, fast2;
|
||||
if( lpos > distance )
|
||||
{
|
||||
fast = ( len < d->buffer_size - lpos );
|
||||
fast2 = ( fast && len <= lpos - i );
|
||||
fast = len < d->buffer_size - lpos;
|
||||
fast2 = fast && len <= lpos - i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i += d->buffer_size;
|
||||
fast = ( len < d->buffer_size - i ); /* (i == pos) may happen */
|
||||
fast2 = ( fast && len <= i - lpos );
|
||||
fast = len < d->buffer_size - i; /* (i == pos) may happen */
|
||||
fast2 = fast && len <= i - lpos;
|
||||
}
|
||||
if( fast ) /* no wrap */
|
||||
{
|
||||
|
@ -342,8 +341,8 @@ static inline void LZd_copy_block( struct LZ_decoder * const d,
|
|||
}
|
||||
}
|
||||
|
||||
/* block is (at least partially) outside of the buffer */
|
||||
static inline void LZd_copy_block2( struct LZ_decoder * const d,
|
||||
/* block is (at least partially) outside the buffer */
|
||||
static inline void LZd_copy_block2( LZ_decoder * const d,
|
||||
const unsigned distance, unsigned len )
|
||||
{
|
||||
if( len < d->buffer_size - d->pos ) /* no wrap */
|
||||
|
@ -361,8 +360,7 @@ static inline void LZd_copy_block2( struct LZ_decoder * const d,
|
|||
LZd_put_byte( d, LZd_peek( d, distance ) );
|
||||
}
|
||||
|
||||
static inline bool LZd_init( struct LZ_decoder * const d,
|
||||
struct Range_decoder * const rde,
|
||||
static inline bool LZd_init( LZ_decoder * const d, Range_decoder * const rde,
|
||||
const unsigned buffer_size,
|
||||
const unsigned dict_size, const int ofd )
|
||||
{
|
||||
|
@ -382,16 +380,14 @@ static inline bool LZd_init( struct LZ_decoder * const d,
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void LZd_free( struct LZ_decoder * const d )
|
||||
static inline void LZd_free( LZ_decoder * const d )
|
||||
{ free( d->buffer ); }
|
||||
|
||||
static inline unsigned LZd_crc( const struct LZ_decoder * const d )
|
||||
static inline unsigned LZd_crc( const LZ_decoder * const d )
|
||||
{ return d->crc ^ 0xFFFFFFFFU; }
|
||||
|
||||
static inline unsigned long long
|
||||
LZd_data_position( const struct LZ_decoder * const d )
|
||||
LZd_data_position( const LZ_decoder * const d )
|
||||
{ return d->partial_data_pos + d->pos; }
|
||||
|
||||
int LZd_decode_member( struct LZ_decoder * const d,
|
||||
const struct Cl_options * const cl_opts,
|
||||
struct Pretty_print * const pp );
|
||||
int LZd_decode_member( LZ_decoder * const d, Pretty_print * const pp );
|
||||
|
|
31
doc/lunzip.1
31
doc/lunzip.1
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
|
||||
.TH LUNZIP "1" "January 2024" "lunzip 1.14" "User Commands"
|
||||
.TH LUNZIP "1" "November 2024" "lunzip 1.15-rc1" "User Commands"
|
||||
.SH NAME
|
||||
lunzip \- decompressor for the lzip format
|
||||
.SH SYNOPSIS
|
||||
|
@ -8,20 +8,19 @@ lunzip \- decompressor for the lzip format
|
|||
.SH DESCRIPTION
|
||||
Lunzip is a decompressor for the lzip format written in C. Its small size
|
||||
makes it well suited for embedded devices or software installers that need
|
||||
to decompress files but don't need compression capabilities. Lunzip is
|
||||
compatible with lzip 1.4 or newer.
|
||||
to decompress files but don't need compression capabilities.
|
||||
.PP
|
||||
Lzip is a lossless data compressor with a user interface similar to the one
|
||||
of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov
|
||||
chain\-Algorithm' (LZMA) stream format to maximize interoperability. The
|
||||
maximum dictionary size is 512 MiB so that any lzip file can be decompressed
|
||||
on 32\-bit machines. Lzip provides accurate and robust 3\-factor integrity
|
||||
checking. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) or compress most
|
||||
files more than bzip2 (lzip \fB\-9\fR). Decompression speed is intermediate between
|
||||
gzip and bzip2. Lzip is better than gzip and bzip2 from a data recovery
|
||||
perspective. Lzip has been designed, written, and tested with great care to
|
||||
replace gzip and bzip2 as the standard general\-purpose compressed format for
|
||||
Unix\-like systems.
|
||||
of gzip or bzip2. Lzip uses a simplified form of LZMA (Lempel\-Ziv\-Markov
|
||||
chain\-Algorithm) designed to achieve complete interoperability between
|
||||
implementations. The maximum dictionary size is 512 MiB so that any lzip
|
||||
file can be decompressed on 32\-bit machines. Lzip provides accurate and
|
||||
robust 3\-factor integrity checking. 'lzip \fB\-0\fR' compresses about as fast as
|
||||
gzip, while 'lzip \fB\-9\fR' compresses most files more than bzip2. Decompression
|
||||
speed is intermediate between gzip and bzip2. Lzip provides better data
|
||||
recovery capabilities than gzip and bzip2. Lzip has been designed, written,
|
||||
and tested with great care to replace gzip and bzip2 as general\-purpose
|
||||
compressed format for Unix\-like systems.
|
||||
.PP
|
||||
Lunzip provides a 'low memory' mode able to decompress any file using as
|
||||
little memory as 50 kB, irrespective of the dictionary size used to
|
||||
|
@ -74,12 +73,6 @@ set output buffer size in bytes
|
|||
\fB\-v\fR, \fB\-\-verbose\fR
|
||||
be verbose (a 2nd \fB\-v\fR gives more)
|
||||
.TP
|
||||
\fB\-\-empty\-error\fR
|
||||
exit with error status if empty member in file
|
||||
.TP
|
||||
\fB\-\-marking\-error\fR
|
||||
exit with error status if 1st LZMA byte not 0
|
||||
.TP
|
||||
\fB\-\-loose\-trailing\fR
|
||||
allow trailing data seeming corrupt header
|
||||
.PP
|
||||
|
|
21
list.c
21
list.c
|
@ -17,6 +17,7 @@
|
|||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
@ -43,7 +44,7 @@ static void list_line( const unsigned long long uncomp_size,
|
|||
|
||||
|
||||
int list_files( const char * const filenames[], const int num_filenames,
|
||||
const struct Cl_options * const cl_opts )
|
||||
const Cl_options * const cl_opts )
|
||||
{
|
||||
unsigned long long total_comp = 0, total_uncomp = 0;
|
||||
int files = 0, retval = 0;
|
||||
|
@ -53,7 +54,7 @@ int list_files( const char * const filenames[], const int num_filenames,
|
|||
|
||||
for( i = 0; i < num_filenames; ++i )
|
||||
{
|
||||
const bool from_stdin = ( strcmp( filenames[i], "-" ) == 0 );
|
||||
const bool from_stdin = strcmp( filenames[i], "-" ) == 0;
|
||||
if( from_stdin ) { if( stdin_used ) continue; else stdin_used = true; }
|
||||
const char * const input_filename = from_stdin ? "(stdin)" : filenames[i];
|
||||
struct stat in_stats; /* not used */
|
||||
|
@ -61,7 +62,7 @@ int list_files( const char * const filenames[], const int num_filenames,
|
|||
open_instream( input_filename, &in_stats, false, true );
|
||||
if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
|
||||
|
||||
struct Lzip_index lzip_index;
|
||||
Lzip_index lzip_index;
|
||||
Li_init( &lzip_index, infd, cl_opts );
|
||||
close( infd );
|
||||
if( lzip_index.retval != 0 )
|
||||
|
@ -70,6 +71,8 @@ int list_files( const char * const filenames[], const int num_filenames,
|
|||
set_retval( &retval, lzip_index.retval );
|
||||
Li_free( &lzip_index ); continue;
|
||||
}
|
||||
const bool multi_empty = !from_stdin && Li_multi_empty( &lzip_index );
|
||||
if( multi_empty ) set_retval( &retval, 2 );
|
||||
if( verbosity < 0 ) { Li_free( &lzip_index ); continue; }
|
||||
const unsigned long long udata_size = Li_udata_size( &lzip_index );
|
||||
const unsigned long long cdata_size = Li_cdata_size( &lzip_index );
|
||||
|
@ -81,6 +84,8 @@ int list_files( const char * const filenames[], const int num_filenames,
|
|||
if( verbosity >= 1 ) fputs( " dict memb trail ", stdout );
|
||||
fputs( " uncompressed compressed saved name\n", stdout );
|
||||
}
|
||||
if( multi_empty )
|
||||
{ fflush( stdout ); show_file_error( input_filename, empty_msg, 0 ); }
|
||||
if( verbosity >= 1 )
|
||||
printf( "%s %5ld %6lld ", format_ds( lzip_index.dictionary_size ),
|
||||
members, Li_file_size( &lzip_index ) - cdata_size );
|
||||
|
@ -92,8 +97,8 @@ int list_files( const char * const filenames[], const int num_filenames,
|
|||
fputs( " member data_pos data_size member_pos member_size\n", stdout );
|
||||
for( i = 0; i < members; ++i )
|
||||
{
|
||||
const struct Block * db = Li_dblock( &lzip_index, i );
|
||||
const struct Block * mb = Li_mblock( &lzip_index, i );
|
||||
const Block * db = Li_dblock( &lzip_index, i );
|
||||
const Block * mb = Li_mblock( &lzip_index, i );
|
||||
printf( "%6ld %14llu %14llu %14llu %14llu\n",
|
||||
i + 1, db->pos, db->size, mb->pos, mb->size );
|
||||
}
|
||||
|
@ -101,12 +106,16 @@ int list_files( const char * const filenames[], const int num_filenames,
|
|||
}
|
||||
fflush( stdout );
|
||||
Li_free( &lzip_index );
|
||||
if( ferror( stdout ) ) break;
|
||||
}
|
||||
if( verbosity >= 0 && files > 1 )
|
||||
if( verbosity >= 0 && files > 1 && !ferror( stdout ) )
|
||||
{
|
||||
if( verbosity >= 1 ) fputs( " ", stdout );
|
||||
list_line( total_uncomp, total_comp, "(totals)" );
|
||||
fflush( stdout );
|
||||
}
|
||||
if( verbosity >= 0 && ( ferror( stdout ) || fclose( stdout ) != 0 ) )
|
||||
{ show_file_error( "(stdout)", write_error_msg, errno );
|
||||
set_retval( &retval, 1 ); }
|
||||
return retval;
|
||||
}
|
||||
|
|
34
lzip.h
34
lzip.h
|
@ -91,16 +91,16 @@ static inline void Bm_init( Bit_model * const probability )
|
|||
static inline void Bm_array_init( Bit_model bm[], const int size )
|
||||
{ int i; for( i = 0; i < size; ++i ) Bm_init( &bm[i] ); }
|
||||
|
||||
struct Len_model
|
||||
typedef struct Len_model
|
||||
{
|
||||
Bit_model choice1;
|
||||
Bit_model choice2;
|
||||
Bit_model bm_low[pos_states][len_low_symbols];
|
||||
Bit_model bm_mid[pos_states][len_mid_symbols];
|
||||
Bit_model bm_high[len_high_symbols];
|
||||
};
|
||||
} Len_model;
|
||||
|
||||
static inline void Lm_init( struct Len_model * const lm )
|
||||
static inline void Lm_init( Len_model * const lm )
|
||||
{
|
||||
Bm_init( &lm->choice1 );
|
||||
Bm_init( &lm->choice2 );
|
||||
|
@ -236,17 +236,14 @@ static inline bool Lt_check_consistency( const Lzip_trailer data )
|
|||
}
|
||||
|
||||
|
||||
struct Cl_options /* command-line options */
|
||||
typedef struct Cl_options /* command-line options */
|
||||
{
|
||||
bool ignore_empty;
|
||||
bool ignore_marking;
|
||||
bool ignore_trailing;
|
||||
bool loose_trailing;
|
||||
};
|
||||
} Cl_options;
|
||||
|
||||
static inline void Cl_options_init( struct Cl_options * cl_opts )
|
||||
{ cl_opts->ignore_empty = true; cl_opts->ignore_marking = true;
|
||||
cl_opts->ignore_trailing = true; cl_opts->loose_trailing = false; }
|
||||
static inline void Cl_options_init( Cl_options * cl_opts )
|
||||
{ cl_opts->ignore_trailing = true; cl_opts->loose_trailing = false; }
|
||||
|
||||
|
||||
static inline void set_retval( int * retval, const int new_val )
|
||||
|
@ -256,23 +253,25 @@ static const char * const bad_magic_msg = "Bad magic number (file not in lzip fo
|
|||
static const char * const bad_dict_msg = "Invalid dictionary size in member header.";
|
||||
static const char * const corrupt_mm_msg = "Corrupt header in multimember file.";
|
||||
static const char * const empty_msg = "Empty member not allowed.";
|
||||
static const char * const marking_msg = "Marking data not allowed.";
|
||||
static const char * const trailing_msg = "Trailing data not allowed.";
|
||||
static const char * const mem_msg = "Not enough memory.";
|
||||
static const char * const nonzero_msg = "Nonzero first LZMA byte.";
|
||||
static const char * const trailing_msg = "Trailing data not allowed.";
|
||||
static const char * const write_error_msg = "Write error";
|
||||
|
||||
/* defined in decoder.c */
|
||||
int readblock( const int fd, uint8_t * const buf, const int size );
|
||||
|
||||
/* defined in list.c */
|
||||
int list_files( const char * const filenames[], const int num_filenames,
|
||||
const struct Cl_options * const cl_opts );
|
||||
const Cl_options * const cl_opts );
|
||||
|
||||
/* defined in main.c */
|
||||
struct stat;
|
||||
struct Pretty_print;
|
||||
typedef struct Pretty_print Pretty_print;
|
||||
typedef struct Range_decoder Range_decoder;
|
||||
extern int verbosity;
|
||||
void * resize_buffer( void * buf, const unsigned min_size );
|
||||
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg );
|
||||
void Pp_show_msg( Pretty_print * const pp, const char * const msg );
|
||||
const char * bad_version( const unsigned version );
|
||||
const char * format_ds( const unsigned dictionary_size );
|
||||
void show_header( const unsigned dictionary_size );
|
||||
|
@ -282,8 +281,7 @@ void cleanup_and_fail( const int retval );
|
|||
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,
|
||||
const int errcode );
|
||||
struct Range_decoder;
|
||||
void show_dprogress( const unsigned long long cfile_size,
|
||||
const unsigned long long partial_size,
|
||||
const struct Range_decoder * const d,
|
||||
struct Pretty_print * const p );
|
||||
const Range_decoder * const d,
|
||||
Pretty_print * const p );
|
||||
|
|
78
lzip_index.c
78
lzip_index.c
|
@ -38,7 +38,7 @@ static int seek_read( const int fd, uint8_t * const buf, const int size,
|
|||
}
|
||||
|
||||
|
||||
static bool add_error( struct Lzip_index * const li, const char * const msg )
|
||||
static bool add_error( Lzip_index * const li, const char * const msg )
|
||||
{
|
||||
const int len = strlen( msg );
|
||||
void * tmp = resize_buffer( li->error, li->error_size + len + 1 );
|
||||
|
@ -50,16 +50,15 @@ static bool add_error( struct Lzip_index * const li, const char * const msg )
|
|||
}
|
||||
|
||||
|
||||
static bool push_back_member( struct Lzip_index * const li,
|
||||
const long long dp, const long long ds,
|
||||
const long long mp, const long long ms,
|
||||
const unsigned dict_size )
|
||||
static bool push_back_member( Lzip_index * const li, const long long dp,
|
||||
const long long ds, const long long mp,
|
||||
const long long ms, const unsigned dict_size )
|
||||
{
|
||||
struct Member * p;
|
||||
Member * p;
|
||||
void * tmp = resize_buffer( li->member_vector,
|
||||
( li->members + 1 ) * sizeof li->member_vector[0] );
|
||||
if( !tmp ) { add_error( li, mem_msg ); li->retval = 1; return false; }
|
||||
li->member_vector = (struct Member *)tmp;
|
||||
li->member_vector = (Member *)tmp;
|
||||
p = &(li->member_vector[li->members]);
|
||||
init_member( p, dp, ds, mp, ms, dict_size );
|
||||
++li->members;
|
||||
|
@ -67,7 +66,7 @@ static bool push_back_member( struct Lzip_index * const li,
|
|||
}
|
||||
|
||||
|
||||
static void Li_free_member_vector( struct Lzip_index * const li )
|
||||
static void Li_free_member_vector( Lzip_index * const li )
|
||||
{
|
||||
if( li->member_vector )
|
||||
{ free( li->member_vector ); li->member_vector = 0; }
|
||||
|
@ -75,9 +74,9 @@ static void Li_free_member_vector( struct Lzip_index * const li )
|
|||
}
|
||||
|
||||
|
||||
static void Li_reverse_member_vector( struct Lzip_index * const li )
|
||||
static void Li_reverse_member_vector( Lzip_index * const li )
|
||||
{
|
||||
struct Member tmp;
|
||||
Member tmp;
|
||||
long i;
|
||||
for( i = 0; i < li->members / 2; ++i )
|
||||
{
|
||||
|
@ -88,8 +87,7 @@ static void Li_reverse_member_vector( struct Lzip_index * const li )
|
|||
}
|
||||
|
||||
|
||||
static bool Li_check_header( struct Lzip_index * const li,
|
||||
const Lzip_header header )
|
||||
static bool Li_check_header( Lzip_index * const li, const Lzip_header header )
|
||||
{
|
||||
if( !Lh_check_magic( header ) )
|
||||
{ add_error( li, bad_magic_msg ); li->retval = 2; return false; }
|
||||
|
@ -101,15 +99,14 @@ static bool Li_check_header( struct Lzip_index * const li,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void Li_set_errno_error( struct Lzip_index * const li,
|
||||
const char * const msg )
|
||||
static void Li_set_errno_error( Lzip_index * const li, const char * const msg )
|
||||
{
|
||||
add_error( li, msg ); add_error( li, strerror( errno ) );
|
||||
li->retval = 1;
|
||||
}
|
||||
|
||||
static void Li_set_num_error( struct Lzip_index * const li,
|
||||
const char * const msg, unsigned long long num )
|
||||
static void Li_set_num_error( Lzip_index * const li, const char * const msg,
|
||||
unsigned long long num )
|
||||
{
|
||||
char buf[80];
|
||||
snprintf( buf, sizeof buf, "%s%llu", msg, num );
|
||||
|
@ -118,22 +115,19 @@ static void Li_set_num_error( struct Lzip_index * const li,
|
|||
}
|
||||
|
||||
|
||||
static bool Li_read_header( struct Lzip_index * const li, const int fd,
|
||||
Lzip_header header, const long long pos, const bool ignore_marking )
|
||||
static bool Li_read_header( Lzip_index * const li, const int fd,
|
||||
Lzip_header header, const long long pos )
|
||||
{
|
||||
if( seek_read( fd, header, Lh_size, pos ) != Lh_size )
|
||||
{ Li_set_errno_error( li, "Error reading member header: " ); return false; }
|
||||
uint8_t byte;
|
||||
if( !ignore_marking && readblock( fd, &byte, 1 ) == 1 && byte != 0 )
|
||||
{ add_error( li, marking_msg ); li->retval = 2; return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* If successful, push last member and set pos to member header. */
|
||||
static bool Li_skip_trailing_data( struct Lzip_index * const li, const int fd,
|
||||
static bool Li_skip_trailing_data( Lzip_index * const li, const int fd,
|
||||
unsigned long long * const pos,
|
||||
const struct Cl_options * const cl_opts )
|
||||
const Cl_options * const cl_opts )
|
||||
{
|
||||
if( *pos < min_member_size ) return false;
|
||||
enum { block_size = 16384,
|
||||
|
@ -162,8 +156,8 @@ static bool Li_skip_trailing_data( struct Lzip_index * const li, const int fd,
|
|||
if( member_size > ipos + i || !Lt_check_consistency( *trailer ) )
|
||||
continue;
|
||||
Lzip_header header;
|
||||
if( !Li_read_header( li, fd, header, ipos + i - member_size,
|
||||
cl_opts->ignore_marking ) ) return false;
|
||||
if( !Li_read_header( li, fd, header, ipos + i - member_size ) )
|
||||
return false;
|
||||
if( !Lh_check( header ) ) continue;
|
||||
const Lzip_header * header2 = (const Lzip_header *)( buffer + i );
|
||||
const bool full_h2 = bsize - i >= Lh_size;
|
||||
|
@ -178,15 +172,12 @@ static bool Li_skip_trailing_data( struct Lzip_index * const li, const int fd,
|
|||
{ add_error( li, corrupt_mm_msg ); li->retval = 2; return false; }
|
||||
if( !cl_opts->ignore_trailing )
|
||||
{ add_error( li, trailing_msg ); li->retval = 2; return false; }
|
||||
const unsigned long long data_size = Lt_get_data_size( *trailer );
|
||||
if( !cl_opts->ignore_empty && data_size == 0 )
|
||||
{ add_error( li, empty_msg ); li->retval = 2; return false; }
|
||||
*pos = ipos + i - member_size; /* good member */
|
||||
const unsigned dictionary_size = Lh_get_dictionary_size( header );
|
||||
if( li->dictionary_size < dictionary_size )
|
||||
li->dictionary_size = dictionary_size;
|
||||
return push_back_member( li, 0, data_size, *pos, member_size,
|
||||
dictionary_size );
|
||||
return push_back_member( li, 0, Lt_get_data_size( *trailer ), *pos,
|
||||
member_size, dictionary_size );
|
||||
}
|
||||
if( ipos == 0 )
|
||||
{ Li_set_num_error( li, "Bad trailer at pos ", *pos - Lt_size );
|
||||
|
@ -200,8 +191,8 @@ static bool Li_skip_trailing_data( struct Lzip_index * const li, const int fd,
|
|||
}
|
||||
|
||||
|
||||
bool Li_init( struct Lzip_index * const li, const int infd,
|
||||
const struct Cl_options * const cl_opts )
|
||||
bool Li_init( Lzip_index * const li, const int infd,
|
||||
const Cl_options * const cl_opts )
|
||||
{
|
||||
li->member_vector = 0;
|
||||
li->error = 0;
|
||||
|
@ -212,6 +203,10 @@ bool Li_init( struct Lzip_index * const li, const int infd,
|
|||
li->dictionary_size = 0;
|
||||
if( li->insize < 0 )
|
||||
{ Li_set_errno_error( li, "Input file is not seekable: " ); return false; }
|
||||
Lzip_header header;
|
||||
if( li->insize >= Lh_size &&
|
||||
( !Li_read_header( li, infd, header, 0 ) ||
|
||||
!Li_check_header( li, header ) ) ) return false;
|
||||
if( li->insize < min_member_size )
|
||||
{ add_error( li, "Input file is too short." ); li->retval = 2;
|
||||
return false; }
|
||||
|
@ -219,10 +214,6 @@ bool Li_init( struct Lzip_index * const li, const int infd,
|
|||
{ add_error( li, "Input file is too long (2^63 bytes or more)." );
|
||||
li->retval = 2; return false; }
|
||||
|
||||
Lzip_header header;
|
||||
if( !Li_read_header( li, infd, header, 0, cl_opts->ignore_marking ) ||
|
||||
!Li_check_header( li, header ) ) return false;
|
||||
|
||||
unsigned long long pos = li->insize; /* always points to a header or to EOF */
|
||||
while( pos >= min_member_size )
|
||||
{
|
||||
|
@ -237,8 +228,7 @@ bool Li_init( struct Lzip_index * const li, const int infd,
|
|||
return false; }
|
||||
Li_set_num_error( li, "Bad trailer at pos ", pos - Lt_size ); break;
|
||||
}
|
||||
if( !Li_read_header( li, infd, header, pos - member_size,
|
||||
cl_opts->ignore_marking ) ) break;
|
||||
if( !Li_read_header( li, infd, header, pos - member_size ) ) break;
|
||||
if( !Lh_check( header ) ) /* bad header */
|
||||
{
|
||||
if( li->members <= 0 )
|
||||
|
@ -246,15 +236,12 @@ bool Li_init( struct Lzip_index * const li, const int infd,
|
|||
return false; }
|
||||
Li_set_num_error( li, "Bad header at pos ", pos - member_size ); break;
|
||||
}
|
||||
const unsigned long long data_size = Lt_get_data_size( trailer );
|
||||
if( !cl_opts->ignore_empty && data_size == 0 )
|
||||
{ add_error( li, empty_msg ); li->retval = 2; break; }
|
||||
pos -= member_size; /* good member */
|
||||
const unsigned dictionary_size = Lh_get_dictionary_size( header );
|
||||
if( li->dictionary_size < dictionary_size )
|
||||
li->dictionary_size = dictionary_size;
|
||||
if( !push_back_member( li, 0, data_size, pos, member_size,
|
||||
dictionary_size ) ) return false;
|
||||
if( !push_back_member( li, 0, Lt_get_data_size( trailer ), pos,
|
||||
member_size, dictionary_size ) ) return false;
|
||||
}
|
||||
if( pos != 0 || li->members <= 0 || li->retval != 0 )
|
||||
{
|
||||
|
@ -264,8 +251,7 @@ bool Li_init( struct Lzip_index * const li, const int infd,
|
|||
return false;
|
||||
}
|
||||
Li_reverse_member_vector( li );
|
||||
long i;
|
||||
for( i = 0; ; ++i )
|
||||
long i; for( i = 0; ; ++i )
|
||||
{
|
||||
const long long end = block_end( li->member_vector[i].dblock );
|
||||
if( end < 0 || end > INT64_MAX )
|
||||
|
@ -281,7 +267,7 @@ bool Li_init( struct Lzip_index * const li, const int infd,
|
|||
}
|
||||
|
||||
|
||||
void Li_free( struct Lzip_index * const li )
|
||||
void Li_free( Lzip_index * const li )
|
||||
{
|
||||
Li_free_member_vector( li );
|
||||
if( li->error ) { free( li->error ); li->error = 0; }
|
||||
|
|
60
lzip_index.h
60
lzip_index.h
|
@ -20,72 +20,80 @@
|
|||
#endif
|
||||
|
||||
|
||||
struct Block
|
||||
typedef struct Block
|
||||
{
|
||||
long long pos, size; /* pos >= 0, size >= 0, pos + size <= INT64_MAX */
|
||||
};
|
||||
} Block;
|
||||
|
||||
static inline void init_block( struct Block * const b,
|
||||
static inline void init_block( Block * const b,
|
||||
const long long p, const long long s )
|
||||
{ b->pos = p; b->size = s; }
|
||||
|
||||
static inline long long block_end( const struct Block b )
|
||||
{ return b.pos + b.size; }
|
||||
static inline long long block_end( const Block b ) { return b.pos + b.size; }
|
||||
|
||||
|
||||
struct Member
|
||||
typedef struct Member
|
||||
{
|
||||
struct Block dblock, mblock; /* data block, member block */
|
||||
Block dblock, mblock; /* data block, member block */
|
||||
unsigned dictionary_size;
|
||||
};
|
||||
} Member;
|
||||
|
||||
static inline void init_member( struct Member * const m,
|
||||
const long long dpos, const long long dsize,
|
||||
const long long mpos, const long long msize,
|
||||
const unsigned dict_size )
|
||||
{ init_block( &m->dblock, dpos, dsize ); init_block( &m->mblock, mpos, msize );
|
||||
m->dictionary_size = dict_size; }
|
||||
static inline void init_member( Member * const m, const long long dpos,
|
||||
const long long dsize, const long long mpos,
|
||||
const long long msize, const unsigned dict_size )
|
||||
{ init_block( &m->dblock, dpos, dsize );
|
||||
init_block( &m->mblock, mpos, msize ); m->dictionary_size = dict_size; }
|
||||
|
||||
struct Lzip_index
|
||||
typedef struct Lzip_index
|
||||
{
|
||||
struct Member * member_vector;
|
||||
Member * member_vector;
|
||||
char * error;
|
||||
long long insize;
|
||||
long members;
|
||||
int error_size;
|
||||
int retval;
|
||||
unsigned dictionary_size; /* largest dictionary size in the file */
|
||||
};
|
||||
} Lzip_index;
|
||||
|
||||
bool Li_init( struct Lzip_index * const li, const int infd,
|
||||
const struct Cl_options * const cl_opts );
|
||||
bool Li_init( Lzip_index * const li, const int infd,
|
||||
const Cl_options * const cl_opts );
|
||||
|
||||
void Li_free( struct Lzip_index * const li );
|
||||
void Li_free( Lzip_index * const li );
|
||||
|
||||
static inline long long Li_udata_size( const struct Lzip_index * const li )
|
||||
/* multimember file with empty member(s) */
|
||||
static inline bool Li_multi_empty( Lzip_index * const li )
|
||||
{
|
||||
long i;
|
||||
if( li->members > 1 )
|
||||
for( i = 0; i < li->members; ++i )
|
||||
if( li->member_vector[i].dblock.size == 0 ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline long long Li_udata_size( const Lzip_index * const li )
|
||||
{
|
||||
if( li->members <= 0 ) return 0;
|
||||
return block_end( li->member_vector[li->members-1].dblock );
|
||||
}
|
||||
|
||||
static inline long long Li_cdata_size( const struct Lzip_index * const li )
|
||||
static inline long long Li_cdata_size( const Lzip_index * const li )
|
||||
{
|
||||
if( li->members <= 0 ) return 0;
|
||||
return block_end( li->member_vector[li->members-1].mblock );
|
||||
}
|
||||
|
||||
/* total size including trailing data (if any) */
|
||||
static inline long long Li_file_size( const struct Lzip_index * const li )
|
||||
static inline long long Li_file_size( const Lzip_index * const li )
|
||||
{ if( li->insize >= 0 ) return li->insize; else return 0; }
|
||||
|
||||
static inline const struct Block * Li_dblock( const struct Lzip_index * const li,
|
||||
static inline const Block * Li_dblock( const Lzip_index * const li,
|
||||
const long i )
|
||||
{ return &li->member_vector[i].dblock; }
|
||||
|
||||
static inline const struct Block * Li_mblock( const struct Lzip_index * const li,
|
||||
static inline const Block * Li_mblock( const Lzip_index * const li,
|
||||
const long i )
|
||||
{ return &li->member_vector[i].mblock; }
|
||||
|
||||
static inline unsigned Li_dictionary_size( const struct Lzip_index * const li,
|
||||
static inline unsigned Li_dictionary_size( const Lzip_index * const li,
|
||||
const long i )
|
||||
{ return li->member_vector[i].dictionary_size; }
|
||||
|
|
119
main.c
119
main.c
|
@ -26,7 +26,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h> /* SSIZE_MAX */
|
||||
#include <limits.h> /* CHAR_BIT, SSIZE_MAX */
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h> /* SIZE_MAX */
|
||||
|
@ -39,8 +39,10 @@
|
|||
#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__
|
||||
#include <io.h>
|
||||
#if defined __MSVCRT__
|
||||
#include <direct.h>
|
||||
#define fchmod(x,y) 0
|
||||
#define fchown(x,y,z) 0
|
||||
#define mkdir(name,mode) _mkdir(name)
|
||||
#define SIGHUP SIGTERM
|
||||
#define S_ISSOCK(x) 0
|
||||
#ifndef S_IRGRP
|
||||
|
@ -84,7 +86,7 @@ static const struct { const char * from; const char * to; } known_extensions[] =
|
|||
{ ".tlz", ".tar" },
|
||||
{ 0, 0 } };
|
||||
|
||||
enum Mode { m_compress, m_decompress, m_list, m_test };
|
||||
typedef enum Mode { m_compress, m_decompress, m_list, m_test } Mode;
|
||||
|
||||
/* Variables used in signal handler context.
|
||||
They are not declared volatile because the handler never returns. */
|
||||
|
@ -97,19 +99,18 @@ static void show_help( void )
|
|||
{
|
||||
printf( "Lunzip is a decompressor for the lzip format written in C. Its small size\n"
|
||||
"makes it well suited for embedded devices or software installers that need\n"
|
||||
"to decompress files but don't need compression capabilities. Lunzip is\n"
|
||||
"compatible with lzip 1.4 or newer.\n"
|
||||
"to decompress files but don't need compression capabilities.\n"
|
||||
"\nLzip is a lossless data compressor with a user interface similar to the one\n"
|
||||
"of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov\n"
|
||||
"chain-Algorithm' (LZMA) stream format to maximize interoperability. The\n"
|
||||
"maximum dictionary size is 512 MiB so that any lzip file can be decompressed\n"
|
||||
"on 32-bit machines. Lzip provides accurate and robust 3-factor integrity\n"
|
||||
"checking. Lzip can compress about as fast as gzip (lzip -0) or compress most\n"
|
||||
"files more than bzip2 (lzip -9). Decompression speed is intermediate between\n"
|
||||
"gzip and bzip2. Lzip is better than gzip and bzip2 from a data recovery\n"
|
||||
"perspective. Lzip has been designed, written, and tested with great care to\n"
|
||||
"replace gzip and bzip2 as the standard general-purpose compressed format for\n"
|
||||
"Unix-like systems.\n"
|
||||
"of gzip or bzip2. Lzip uses a simplified form of LZMA (Lempel-Ziv-Markov\n"
|
||||
"chain-Algorithm) designed to achieve complete interoperability between\n"
|
||||
"implementations. The maximum dictionary size is 512 MiB so that any lzip\n"
|
||||
"file can be decompressed on 32-bit machines. Lzip provides accurate and\n"
|
||||
"robust 3-factor integrity checking. 'lzip -0' compresses about as fast as\n"
|
||||
"gzip, while 'lzip -9' compresses most files more than bzip2. Decompression\n"
|
||||
"speed is intermediate between gzip and bzip2. Lzip provides better data\n"
|
||||
"recovery capabilities than gzip and bzip2. Lzip has been designed, written,\n"
|
||||
"and tested with great care to replace gzip and bzip2 as general-purpose\n"
|
||||
"compressed format for Unix-like systems.\n"
|
||||
"\nLunzip provides a 'low memory' mode able to decompress any file using as\n"
|
||||
"little memory as 50 kB, irrespective of the dictionary size used to\n"
|
||||
"compress the file. To activate it, specify the size of the output buffer\n"
|
||||
|
@ -135,8 +136,6 @@ static void show_help( void )
|
|||
" -t, --test test compressed file integrity\n"
|
||||
" -u, --buffer-size=<bytes> set output buffer size in bytes\n"
|
||||
" -v, --verbose be verbose (a 2nd -v gives more)\n"
|
||||
" --empty-error exit with error status if empty member in file\n"
|
||||
" --marking-error exit with error status if 1st LZMA byte not 0\n"
|
||||
" --loose-trailing allow trailing data seeming corrupt header\n"
|
||||
"\nIf no file names are given, or if a file is '-', lunzip decompresses\n"
|
||||
"from standard input to standard output.\n"
|
||||
|
@ -189,7 +188,7 @@ struct Pretty_print
|
|||
bool first_post;
|
||||
};
|
||||
|
||||
static void Pp_init( struct Pretty_print * const pp,
|
||||
static void Pp_init( Pretty_print * const pp,
|
||||
const char * const filenames[], const int num_filenames )
|
||||
{
|
||||
pp->name = 0;
|
||||
|
@ -210,8 +209,10 @@ static void Pp_init( struct Pretty_print * const pp,
|
|||
if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len;
|
||||
}
|
||||
|
||||
static void Pp_set_name( struct Pretty_print * const pp,
|
||||
const char * const filename )
|
||||
void Pp_free( Pretty_print * const pp )
|
||||
{ if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } }
|
||||
|
||||
static void Pp_set_name( Pretty_print * const pp, const char * const filename )
|
||||
{
|
||||
unsigned name_len, padded_name_len, i = 0;
|
||||
|
||||
|
@ -229,10 +230,10 @@ static void Pp_set_name( struct Pretty_print * const pp,
|
|||
pp->first_post = true;
|
||||
}
|
||||
|
||||
static void Pp_reset( struct Pretty_print * const pp )
|
||||
static void Pp_reset( Pretty_print * const pp )
|
||||
{ if( pp->name && pp->name[0] ) pp->first_post = true; }
|
||||
|
||||
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
|
||||
void Pp_show_msg( Pretty_print * const pp, const char * const msg )
|
||||
{
|
||||
if( verbosity < 0 ) return;
|
||||
if( pp->first_post )
|
||||
|
@ -262,7 +263,7 @@ const char * format_ds( const unsigned dictionary_size )
|
|||
const char * p = "";
|
||||
const char * np = " ";
|
||||
unsigned num = dictionary_size;
|
||||
bool exact = ( num % factor == 0 );
|
||||
bool exact = num % factor == 0;
|
||||
|
||||
int i; for( i = 0; i < n && ( num > 9999 || ( exact && num >= factor ) ); ++i )
|
||||
{ num /= factor; if( num % factor != 0 ) exact = false;
|
||||
|
@ -278,7 +279,7 @@ void show_header( const unsigned dictionary_size )
|
|||
}
|
||||
|
||||
|
||||
/* separate numbers of 5 or more digits in groups of 3 digits using '_' */
|
||||
/* separate numbers of 6 or more digits in groups of 3 digits using '_' */
|
||||
static const char * format_num3( unsigned long long num )
|
||||
{
|
||||
enum { buffers = 8, bufsize = 4 * sizeof num, n = 10 };
|
||||
|
@ -290,7 +291,7 @@ static const char * format_num3( unsigned long long num )
|
|||
char * const buf = buffer[current++]; current %= buffers;
|
||||
char * p = buf + bufsize - 1; /* fill the buffer backwards */
|
||||
*p = 0; /* terminator */
|
||||
if( num > 1024 )
|
||||
if( num > 9999 )
|
||||
{
|
||||
char prefix = 0; /* try binary first, then si */
|
||||
for( i = 0; i < n && num != 0 && num % 1024 == 0; ++i )
|
||||
|
@ -301,7 +302,7 @@ static const char * format_num3( unsigned long long num )
|
|||
{ num /= 1000; prefix = si_prefix[i]; }
|
||||
if( prefix ) *(--p) = prefix;
|
||||
}
|
||||
const bool split = num >= 10000;
|
||||
const bool split = num >= 100000;
|
||||
|
||||
for( i = 0; ; )
|
||||
{
|
||||
|
@ -336,7 +337,7 @@ static unsigned long getnum( const char * const arg,
|
|||
|
||||
if( !errno && tail[0] )
|
||||
{
|
||||
const unsigned factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
||||
const unsigned factor = (tail[1] == 'i') ? 1024 : 1000;
|
||||
int exponent = 0; /* 0 = bad multiplier */
|
||||
int i;
|
||||
switch( tail[0] )
|
||||
|
@ -386,7 +387,7 @@ static int get_dict_size( const char * const arg, const char * const option_name
|
|||
}
|
||||
|
||||
|
||||
static void set_mode( enum Mode * const program_modep, const enum Mode new_mode )
|
||||
static void set_mode( Mode * const program_modep, const Mode new_mode )
|
||||
{
|
||||
if( *program_modep != m_compress && *program_modep != new_mode )
|
||||
{
|
||||
|
@ -448,9 +449,9 @@ int open_instream( const char * const name, struct stat * const in_statsp,
|
|||
{
|
||||
const int i = fstat( infd, in_statsp );
|
||||
const mode_t mode = in_statsp->st_mode;
|
||||
const bool can_read = ( i == 0 && !reg_only &&
|
||||
const bool can_read = i == 0 && !reg_only &&
|
||||
( S_ISBLK( mode ) || S_ISCHR( mode ) ||
|
||||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
|
||||
S_ISFIFO( mode ) || S_ISSOCK( mode ) );
|
||||
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
|
@ -479,7 +480,7 @@ static bool make_dirs( const char * const name )
|
|||
while( i < dirsize && name[i] != '/' ) ++i;
|
||||
if( first < i )
|
||||
{
|
||||
char partial[i+1]; memcpy( partial, name, i ); partial[i] = 0;
|
||||
char partial[i+1]; memcpy( partial, name, i ); partial[i] = 0; /* vla */
|
||||
const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
||||
struct stat st;
|
||||
if( stat( partial, &st ) == 0 )
|
||||
|
@ -550,7 +551,7 @@ static void signal_handler( int sig )
|
|||
|
||||
|
||||
static bool check_tty_in( const char * const input_filename, const int infd,
|
||||
const enum Mode program_mode, int * const retval )
|
||||
const Mode program_mode, int * const retval )
|
||||
{
|
||||
if( isatty( infd ) ) /* for example /dev/tty */
|
||||
{ show_file_error( input_filename,
|
||||
|
@ -604,7 +605,7 @@ static unsigned char xdigit( const unsigned value ) /* hex digit for 'value' */
|
|||
|
||||
|
||||
static bool show_trailing_data( const uint8_t * const data, const int size,
|
||||
struct Pretty_print * const pp, const bool all,
|
||||
Pretty_print * const pp, const bool all,
|
||||
const int ignore_trailing ) /* -1 = show */
|
||||
{
|
||||
if( verbosity >= 4 || ignore_trailing <= 0 )
|
||||
|
@ -632,16 +633,17 @@ static bool show_trailing_data( const uint8_t * const data, const int size,
|
|||
|
||||
|
||||
static int decompress( const unsigned long long cfile_size, const int infd,
|
||||
const struct Cl_options * const cl_opts,
|
||||
struct Pretty_print * const pp,
|
||||
const unsigned buffer_size, const bool testing )
|
||||
const Cl_options * const cl_opts, Pretty_print * const pp,
|
||||
const unsigned buffer_size,
|
||||
const bool from_stdin, const bool testing )
|
||||
{
|
||||
unsigned long long partial_file_pos = 0;
|
||||
struct Range_decoder rdec;
|
||||
Range_decoder rdec;
|
||||
int retval = 0;
|
||||
bool first_member;
|
||||
if( !Rd_init( &rdec, infd ) )
|
||||
{ show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
|
||||
bool empty = false, multi = false;
|
||||
|
||||
for( first_member = true; ; first_member = false )
|
||||
{
|
||||
|
@ -681,14 +683,14 @@ static int decompress( const unsigned long long cfile_size, const int infd,
|
|||
if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
|
||||
Pp_show_msg( pp, 0 );
|
||||
|
||||
struct LZ_decoder decoder;
|
||||
LZ_decoder decoder;
|
||||
if( !LZd_init( &decoder, &rdec, buffer_size, dictionary_size, outfd ) )
|
||||
{
|
||||
Pp_show_msg( pp, "Not enough memory. Try a smaller output buffer size." );
|
||||
retval = 1; break;
|
||||
}
|
||||
show_dprogress( cfile_size, partial_file_pos, &rdec, pp ); /* init */
|
||||
const int result = LZd_decode_member( &decoder, cl_opts, pp );
|
||||
const int result = LZd_decode_member( &decoder, pp );
|
||||
partial_file_pos += Rd_member_position( &rdec );
|
||||
LZd_free( &decoder );
|
||||
if( result != 0 )
|
||||
|
@ -700,16 +702,19 @@ static int decompress( const unsigned long long cfile_size, const int infd,
|
|||
"File ends unexpectedly" : "Decoder error",
|
||||
partial_file_pos );
|
||||
}
|
||||
else if( result == 5 ) Pp_show_msg( pp, empty_msg );
|
||||
else if( result == 6 ) Pp_show_msg( pp, marking_msg );
|
||||
else if( result == 5 ) Pp_show_msg( pp, nonzero_msg );
|
||||
retval = 2; break;
|
||||
}
|
||||
if( !from_stdin ) { multi = !first_member;
|
||||
if( LZd_data_position( &decoder ) == 0 ) empty = true; }
|
||||
if( verbosity >= 2 )
|
||||
{ fputs( testing ? "ok\n" : "done\n", stderr ); Pp_reset( pp ); }
|
||||
}
|
||||
Rd_free( &rdec );
|
||||
if( verbosity == 1 && retval == 0 )
|
||||
fputs( testing ? "ok\n" : "done\n", stderr );
|
||||
if( empty && multi && retval == 0 )
|
||||
{ show_file_error( pp->name, empty_msg, 0 ); retval = 2; }
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -747,13 +752,13 @@ static void internal_error( const char * const msg )
|
|||
|
||||
void show_dprogress( const unsigned long long cfile_size,
|
||||
const unsigned long long partial_size,
|
||||
const struct Range_decoder * const d,
|
||||
struct Pretty_print * const p )
|
||||
const Range_decoder * const d,
|
||||
Pretty_print * const p )
|
||||
{
|
||||
static unsigned long long csize = 0; /* file_size / 100 */
|
||||
static unsigned long long psize = 0;
|
||||
static const struct Range_decoder * rdec = 0;
|
||||
static struct Pretty_print * pp = 0;
|
||||
static const Range_decoder * rdec = 0;
|
||||
static Pretty_print * pp = 0;
|
||||
static int counter = 0;
|
||||
static bool enabled = true;
|
||||
|
||||
|
@ -780,17 +785,16 @@ int main( const int argc, const char * const argv[] )
|
|||
{
|
||||
const char * default_output_filename = "";
|
||||
unsigned buffer_size = max_dictionary_size;
|
||||
enum Mode program_mode = m_compress;
|
||||
int i;
|
||||
struct Cl_options cl_opts; /* command-line options */
|
||||
Mode program_mode = m_compress;
|
||||
Cl_options cl_opts; /* command-line options */
|
||||
Cl_options_init( &cl_opts );
|
||||
bool force = false;
|
||||
bool keep_input_files = false;
|
||||
bool to_stdout = false;
|
||||
if( argc > 0 ) invocation_name = argv[0];
|
||||
|
||||
enum { opt_eer = 256, opt_lt, opt_mer };
|
||||
const struct ap_Option options[] =
|
||||
enum { opt_lt = 256 };
|
||||
const ap_Option options[] =
|
||||
{
|
||||
{ 'a', "trailing-error", ap_no },
|
||||
{ 'c', "stdout", ap_no },
|
||||
|
@ -806,15 +810,13 @@ int main( const int argc, const char * const argv[] )
|
|||
{ 'u', "buffer-size", ap_yes },
|
||||
{ 'v', "verbose", ap_no },
|
||||
{ 'V', "version", ap_no },
|
||||
{ opt_eer, "empty-error", ap_no },
|
||||
{ opt_lt, "loose-trailing", ap_no },
|
||||
{ opt_mer, "marking-error", ap_no },
|
||||
{ 0, 0, ap_no } };
|
||||
|
||||
CRC32_init();
|
||||
|
||||
/* static because valgrind complains and memory management in C sucks */
|
||||
static struct Arg_parser parser;
|
||||
static Arg_parser parser;
|
||||
if( !ap_init( &parser, argc, argv, options, 0 ) )
|
||||
{ show_error( mem_msg, 0, false ); return 1; }
|
||||
if( ap_error( &parser ) ) /* bad option */
|
||||
|
@ -836,7 +838,7 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'h': show_help(); return 0;
|
||||
case 'k': keep_input_files = true; break;
|
||||
case 'l': set_mode( &program_mode, m_list ); break;
|
||||
case 'n': break;
|
||||
case 'n': break; /* ignored */
|
||||
case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true;
|
||||
else { default_output_filename = arg; } break;
|
||||
case 'q': verbosity = -1; break;
|
||||
|
@ -844,9 +846,7 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'u': buffer_size = get_dict_size( arg, pn ); break;
|
||||
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
||||
case 'V': show_version(); return 0;
|
||||
case opt_eer: cl_opts.ignore_empty = false; break;
|
||||
case opt_lt: cl_opts.loose_trailing = true; break;
|
||||
case opt_mer: cl_opts.ignore_marking = false; break;
|
||||
default: internal_error( "uncaught option." );
|
||||
}
|
||||
} /* end process options */
|
||||
|
@ -861,6 +861,7 @@ int main( const int argc, const char * const argv[] )
|
|||
filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] );
|
||||
filenames[0] = "-";
|
||||
|
||||
int i;
|
||||
bool filenames_given = false;
|
||||
for( i = 0; argind + i < ap_arguments( &parser ); ++i )
|
||||
{
|
||||
|
@ -900,7 +901,7 @@ int main( const int argc, const char * const argv[] )
|
|||
if( !to_stdout && program_mode != m_test && ( filenames_given || to_file ) )
|
||||
set_signals( signal_handler );
|
||||
|
||||
static struct Pretty_print pp;
|
||||
static Pretty_print pp;
|
||||
Pp_init( &pp, filenames, num_filenames );
|
||||
|
||||
int failed_tests = 0;
|
||||
|
@ -912,9 +913,10 @@ int main( const int argc, const char * const argv[] )
|
|||
{
|
||||
const char * input_filename = "";
|
||||
int infd;
|
||||
const bool from_stdin = strcmp( filenames[i], "-" ) == 0;
|
||||
|
||||
Pp_set_name( &pp, filenames[i] );
|
||||
if( strcmp( filenames[i], "-" ) == 0 )
|
||||
if( from_stdin )
|
||||
{
|
||||
if( stdin_used ) continue; else stdin_used = true;
|
||||
infd = STDIN_FILENO;
|
||||
|
@ -963,7 +965,7 @@ int main( const int argc, const char * const argv[] )
|
|||
( input_filename[0] && S_ISREG( in_stats.st_mode ) ) ?
|
||||
( in_stats.st_size + 99 ) / 100 : 0;
|
||||
int tmp = decompress( cfile_size, infd, &cl_opts, &pp, buffer_size,
|
||||
program_mode == m_test );
|
||||
from_stdin, program_mode == m_test );
|
||||
if( close( infd ) != 0 )
|
||||
{ show_file_error( pp.name, "Error closing input file", errno );
|
||||
set_retval( &tmp, 1 ); }
|
||||
|
@ -990,6 +992,7 @@ int main( const int argc, const char * const argv[] )
|
|||
program_name, failed_tests,
|
||||
( failed_tests == 1 ) ? "file" : "files" );
|
||||
free( output_filename );
|
||||
Pp_free( &pp );
|
||||
free( filenames );
|
||||
ap_free( &parser );
|
||||
return retval;
|
||||
|
|
|
@ -28,18 +28,17 @@ if [ -d tmp ] ; then rm -rf tmp ; fi
|
|||
mkdir tmp
|
||||
cd "${objdir}"/tmp || framework_failure
|
||||
|
||||
cat "${testdir}"/test.txt > in || framework_failure
|
||||
cp "${testdir}"/test.txt in || framework_failure
|
||||
in_lz="${testdir}"/test.txt.lz
|
||||
in_em="${testdir}"/test_em.txt.lz
|
||||
em_lz="${testdir}"/em.lz
|
||||
fox_lz="${testdir}"/fox.lz
|
||||
fox6_lz="${testdir}"/fox6.lz
|
||||
f6mk_lz="${testdir}"/fox6_mark.lz
|
||||
fnz_lz="${testdir}"/fox_nz.lz
|
||||
fail=0
|
||||
test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; }
|
||||
|
||||
printf "testing lunzip-%s..." "$2"
|
||||
|
||||
cat "${in_lz}" > uin.lz || framework_failure
|
||||
cp "${in_lz}" uin.lz || framework_failure
|
||||
for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do
|
||||
"${LZIP}" -dfkq -u $i uin.lz
|
||||
[ $? = 1 ] || test_failed $LINENO $i
|
||||
|
@ -96,37 +95,25 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null
|
|||
|
||||
printf "\ntesting decompression..."
|
||||
|
||||
for i in "${in_lz}" "${in_em}" ; do
|
||||
"${LZIP}" -lq "$i" || test_failed $LINENO "$i"
|
||||
"${LZIP}" -t "$i" || test_failed $LINENO "$i"
|
||||
"${LZIP}" -d "$i" -o out || test_failed $LINENO "$i"
|
||||
cmp in out || test_failed $LINENO "$i"
|
||||
"${LZIP}" -cd "$i" > out || test_failed $LINENO "$i"
|
||||
cmp in out || test_failed $LINENO "$i"
|
||||
"${LZIP}" -d "$i" -o - > out || test_failed $LINENO "$i"
|
||||
cmp in out || test_failed $LINENO "$i"
|
||||
"${LZIP}" -d < "$i" > out || test_failed $LINENO "$i"
|
||||
cmp in out || test_failed $LINENO "$i"
|
||||
rm -f out || framework_failure
|
||||
done
|
||||
"${LZIP}" -l "${in_lz}" > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -t "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -d "${in_lz}" -o out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -cd "${in_lz}" > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d "${in_lz}" -o - > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d < "${in_lz}" > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
|
||||
lines=`"${LZIP}" -tvv "${in_em}" 2>&1 | wc -l` || test_failed $LINENO
|
||||
[ "${lines}" -eq 8 ] || test_failed $LINENO "${lines}"
|
||||
"${LZIP}" -tq "${in_em}" --empty-error
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
||||
lines=`"${LZIP}" -lvv "${in_em}" | wc -l` || test_failed $LINENO
|
||||
[ "${lines}" -eq 11 ] || test_failed $LINENO "${lines}"
|
||||
"${LZIP}" -lq "${in_em}" --empty-error
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
||||
cat "${in_lz}" > out.lz || framework_failure
|
||||
cp "${in_lz}" out.lz || framework_failure
|
||||
"${LZIP}" -dk out.lz || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO
|
||||
cat fox > copy || framework_failure
|
||||
cat "${in_lz}" > copy.lz || framework_failure
|
||||
cp fox copy || framework_failure
|
||||
cp "${in_lz}" copy.lz || framework_failure
|
||||
"${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ ! -e out.lz ] || test_failed $LINENO
|
||||
|
@ -140,7 +127,6 @@ rm -f copy out || framework_failure
|
|||
printf "to be overwritten" > out || framework_failure
|
||||
"${LZIP}" -df -o out < "${in_lz}" || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO
|
||||
cmp in ./- || test_failed $LINENO
|
||||
rm -f ./- || framework_failure
|
||||
|
@ -148,12 +134,12 @@ rm -f ./- || framework_failure
|
|||
cmp in ./- || test_failed $LINENO
|
||||
rm -f ./- || framework_failure
|
||||
|
||||
cat "${in_lz}" > anyothername || framework_failure
|
||||
cp "${in_lz}" anyothername || framework_failure
|
||||
"${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null ||
|
||||
test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
cmp in anyothername.out || test_failed $LINENO
|
||||
rm -f out anyothername.out || framework_failure
|
||||
rm -f anyothername.out || framework_failure
|
||||
|
||||
"${LZIP}" -lq in "${in_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
@ -170,7 +156,7 @@ cat out in | cmp in - || test_failed $LINENO # out must be empty
|
|||
[ $? = 1 ] || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
cat "${in_lz}" > out.lz || framework_failure
|
||||
cp "${in_lz}" out.lz || framework_failure
|
||||
for i in 1 2 3 4 5 6 7 ; do
|
||||
printf "g" >> out.lz || framework_failure
|
||||
"${LZIP}" -alvv out.lz "${in_lz}" > /dev/null 2>&1
|
||||
|
@ -191,7 +177,7 @@ cmp in out || test_failed $LINENO
|
|||
rm -f out || framework_failure
|
||||
|
||||
cat in in > in2 || framework_failure
|
||||
"${LZIP}" -lq "${in_lz}" "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -l "${in_lz}" "${in_lz}" > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > out2 || test_failed $LINENO
|
||||
[ ! -e out ] || test_failed $LINENO # override -o
|
||||
|
@ -202,6 +188,11 @@ cmp in2 out2 || test_failed $LINENO
|
|||
rm -f out2 || framework_failure
|
||||
|
||||
cat "${in_lz}" "${in_lz}" > out2.lz || framework_failure
|
||||
lines=`"${LZIP}" -tvv out2.lz 2>&1 | wc -l` || test_failed $LINENO
|
||||
[ "${lines}" -eq 2 ] || test_failed $LINENO "${lines}"
|
||||
lines=`"${LZIP}" -lvv out2.lz | wc -l` || test_failed $LINENO
|
||||
[ "${lines}" -eq 5 ] || test_failed $LINENO "${lines}"
|
||||
|
||||
printf "\ngarbage" >> out2.lz || framework_failure
|
||||
"${LZIP}" -tvvvv out2.lz 2> /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -alq out2.lz
|
||||
|
@ -233,16 +224,6 @@ for i in 12 5120 6Ki 29 512KiB ; do
|
|||
cmp in2 out2 || test_failed $LINENO $i
|
||||
rm -f out2 || framework_failure
|
||||
done
|
||||
rm -f in2 out || framework_failure
|
||||
|
||||
"${LZIP}" -cd "${fox6_lz}" > out || test_failed $LINENO
|
||||
"${LZIP}" -cd "${f6mk_lz}" > copy || test_failed $LINENO
|
||||
cmp copy out || test_failed $LINENO
|
||||
rm -f copy out || framework_failure
|
||||
"${LZIP}" -lq "${f6mk_lz}" --marking-error
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq "${f6mk_lz}" --marking-error
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
||||
"${LZIP}" -d "${fox_lz}" -o a/b/c/fox || test_failed $LINENO
|
||||
cmp fox a/b/c/fox || test_failed $LINENO
|
||||
|
@ -254,13 +235,61 @@ rm -rf a || framework_failure
|
|||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ ! -e a ] || test_failed $LINENO
|
||||
|
||||
touch empty || framework_failure
|
||||
cp "${em_lz}" em.lz || framework_failure
|
||||
"${LZIP}" -l em.lz > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -dk em.lz || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
cat em.lz em.lz | "${LZIP}" -t || test_failed $LINENO
|
||||
cat em.lz em.lz | "${LZIP}" -d > em || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
cat em.lz "${in_lz}" | "${LZIP}" -t || test_failed $LINENO
|
||||
cat em.lz "${in_lz}" | "${LZIP}" -d > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
cat "${in_lz}" em.lz | "${LZIP}" -t || test_failed $LINENO
|
||||
cat "${in_lz}" em.lz | "${LZIP}" -d > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
|
||||
printf "\ntesting bad input..."
|
||||
|
||||
cat em.lz em.lz > ee.lz || framework_failure
|
||||
"${LZIP}" -l < ee.lz > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -t < ee.lz || test_failed $LINENO
|
||||
"${LZIP}" -d < ee.lz > em || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
"${LZIP}" -lq ee.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq ee.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -dq ee.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
[ ! -e ee ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq ee.lz > em
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
rm -f empty em || framework_failure
|
||||
cat "${in_lz}" em.lz "${in_lz}" > inein.lz || framework_failure
|
||||
"${LZIP}" -l < inein.lz > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -t < inein.lz || test_failed $LINENO
|
||||
"${LZIP}" -d < inein.lz > out2 || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
"${LZIP}" -lq inein.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq inein.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -dq inein.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
[ ! -e inein ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq inein.lz > out2
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
rm -f in2 out2 inein.lz em.lz || framework_failure
|
||||
|
||||
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'
|
||||
cat "${in_lz}" > int.lz || framework_failure
|
||||
body='\001\014\000\000\101\376\367\377\377\340\000\200\000\215\357\002\322\001\000\000\000\000\000\000\000\045\000\000\000\000\000\000\000'
|
||||
cp "${in_lz}" int.lz || framework_failure
|
||||
printf "LZIP${body}" >> int.lz || framework_failure
|
||||
if "${LZIP}" -tq int.lz ; then
|
||||
if "${LZIP}" -t int.lz ; then
|
||||
for header in ${headers} ; do
|
||||
printf "${header}${body}" > int.lz || framework_failure
|
||||
"${LZIP}" -lq int.lz # first member
|
||||
|
@ -279,7 +308,7 @@ if "${LZIP}" -tq int.lz ; then
|
|||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -cdq --loose-trailing int.lz > /dev/null
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
cat "${in_lz}" > int.lz || framework_failure
|
||||
cp "${in_lz}" int.lz || framework_failure
|
||||
printf "${header}${body}" >> int.lz || framework_failure
|
||||
"${LZIP}" -lq int.lz # trailing data
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
|
@ -289,7 +318,7 @@ if "${LZIP}" -tq int.lz ; then
|
|||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -cdq int.lz > /dev/null
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -lq --loose-trailing int.lz ||
|
||||
"${LZIP}" -l --loose-trailing int.lz > /dev/null ||
|
||||
test_failed $LINENO ${header}
|
||||
"${LZIP}" -t --loose-trailing int.lz ||
|
||||
test_failed $LINENO ${header}
|
||||
|
@ -307,10 +336,14 @@ if "${LZIP}" -tq int.lz ; then
|
|||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
done
|
||||
else
|
||||
printf "\nwarning: skipping header test: 'printf' does not work on your system."
|
||||
printf "warning: skipping header test: 'printf' does not work on your system."
|
||||
fi
|
||||
rm -f int.lz || framework_failure
|
||||
|
||||
"${LZIP}" -l "${fnz_lz}" > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -tq "${fnz_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
||||
for i in fox_v2.lz fox_s11.lz fox_de20.lz \
|
||||
fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do
|
||||
"${LZIP}" -tq "${testdir}"/$i
|
||||
|
@ -322,13 +355,13 @@ for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do
|
|||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
cmp fox out || test_failed $LINENO $i
|
||||
done
|
||||
rm -f fox out || framework_failure
|
||||
rm -f fox || framework_failure
|
||||
|
||||
cat "${in_lz}" "${in_lz}" > in2.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 &&
|
||||
[ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then
|
||||
for i in 6 20 14734 14753 14754 14755 14756 14757 14758 ; do
|
||||
if dd if=in3.lz of=trunc.lz bs=14682 count=1 2> /dev/null &&
|
||||
[ -e trunc.lz ] && cmp in2.lz trunc.lz ; then
|
||||
for i in 6 20 14664 14683 14684 14685 14686 14687 14688 ; do
|
||||
dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null
|
||||
"${LZIP}" -lq trunc.lz
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
|
@ -342,11 +375,11 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null &&
|
|||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
done
|
||||
else
|
||||
printf "\nwarning: skipping truncation test: 'dd' does not work on your system."
|
||||
printf "warning: skipping truncation test: 'dd' does not work on your system."
|
||||
fi
|
||||
rm -f in2.lz in3.lz trunc.lz || framework_failure
|
||||
|
||||
cat "${in_lz}" > ingin.lz || framework_failure
|
||||
cp "${in_lz}" ingin.lz || framework_failure
|
||||
printf "g" >> ingin.lz || framework_failure
|
||||
cat "${in_lz}" >> ingin.lz || framework_failure
|
||||
"${LZIP}" -lq ingin.lz
|
||||
|
@ -355,17 +388,21 @@ cat "${in_lz}" >> ingin.lz || framework_failure
|
|||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -atq < ingin.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -acdq ingin.lz > /dev/null
|
||||
"${LZIP}" -acdq ingin.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -adq < ingin.lz > /dev/null
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -adq < ingin.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -t ingin.lz || test_failed $LINENO
|
||||
"${LZIP}" -t < ingin.lz || test_failed $LINENO
|
||||
"${LZIP}" -dk ingin.lz || test_failed $LINENO
|
||||
cmp in ingin || test_failed $LINENO
|
||||
"${LZIP}" -cd ingin.lz > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d < ingin.lz > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out ingin.lz || framework_failure
|
||||
rm -f out ingin ingin.lz || framework_failure
|
||||
|
||||
echo
|
||||
if [ ${fail} = 0 ] ; then
|
||||
|
|
BIN
testsuite/em.lz
Normal file
BIN
testsuite/em.lz
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
testsuite/fox_nz.lz
Normal file
BIN
testsuite/fox_nz.lz
Normal file
Binary file not shown.
|
@ -1,8 +1,7 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
@ -339,8 +338,7 @@ Public License instead of this License.
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue