1
0
Fork 0

Adding upstream version 1.12.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 22:29:09 +01:00
parent afb468092e
commit 3e2c48fe40
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
27 changed files with 612 additions and 510 deletions

View file

@ -1,7 +1,7 @@
Lunzip was written by Antonio Diaz Diaz. Lunzip was written by Antonio Diaz Diaz.
The ideas embodied in lunzip are due to (at least) the following people: The ideas embodied in lunzip are due to (at least) the following people:
Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for the
the definition of Markov chains), G.N.N. Martin (for the definition of definition of Markov chains), G.N.N. Martin (for the definition of range
range encoding), Igor Pavlov (for putting all the above together in encoding), Igor Pavlov (for putting all the above together in LZMA), and
LZMA), and Julian Seward (for bzip2's CLI). Julian Seward (for bzip2's CLI).

View file

@ -1,7 +1,19 @@
2021-01-01 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.12 released.
* main.c (main): Report an error if a file name is empty.
Make '-o' behave like '-c', but writing to file instead of stdout.
Do not open output if input is a terminal.
* Replace 'decompressed', 'compressed' with 'out', 'in' in output.
* lzip_index.c: Improve messages for corruption in last header.
* main.c: Set a valid invocation_name even if argc == 0.
* Document extraction from tar.lz in '--help' output and man page.
* testsuite: Add 9 new test files.
2019-01-01 Antonio Diaz Diaz <antonio@gnu.org> 2019-01-01 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.11 released. * Version 1.11 released.
* File_* renamed to Lzip_*. * Rename File_* to Lzip_*.
* lzip.h (Lzip_trailer): New function 'Lt_verify_consistency'. * lzip.h (Lzip_trailer): New function 'Lt_verify_consistency'.
* lzip_index.c: Detect some kinds of corrupt trailers. * lzip_index.c: Detect some kinds of corrupt trailers.
* main.c (main): Check return value of close( infd ). * main.c (main): Check return value of close( infd ).
@ -12,10 +24,10 @@
2018-02-05 Antonio Diaz Diaz <antonio@gnu.org> 2018-02-05 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.10 released. * Version 1.10 released.
* main.c: Added new option '--loose-trailing'. * main.c: New option '--loose-trailing'.
* Improved corrupt header detection to HD=3. * Improve corrupt header detection to HD=3.
* main.c: Show corrupt or truncated header in multimember file. * main.c: Show corrupt or truncated header in multimember file.
* Replaced 'bits/byte' with inverse compression ratio in output. * Replace 'bits/byte' with inverse compression ratio in output.
* Show progress of decompression at verbosity level 2 (-vv). * Show progress of decompression at verbosity level 2 (-vv).
* Show progress of decompression only if stderr is a terminal. * Show progress of decompression only if stderr is a terminal.
* main.c: Show final diagnostic when testing multiple files. * main.c: Show final diagnostic when testing multiple files.
@ -31,16 +43,16 @@
* main.c: Continue testing if any input file is a terminal. * main.c: Continue testing if any input file is a terminal.
* main.c: Show trailing data in both hexadecimal and ASCII. * main.c: Show trailing data in both hexadecimal and ASCII.
* lzip_index.c: Improve detection of bad dict and trailing data. * lzip_index.c: Improve detection of bad dict and trailing data.
* lzip.h: Unified messages for bad magic, trailing data, etc. * lzip.h: Unify messages for bad magic, trailing data, etc.
2016-05-12 Antonio Diaz Diaz <antonio@gnu.org> 2016-05-12 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.8 released. * Version 1.8 released.
* main.c: Added new option '-a, --trailing-error'. * main.c: New option '-a, --trailing-error'.
* main.c (main): With '-u', verify that output file is regular. * main.c (main): With '-u', verify that output file is regular.
* main.c (decompress): Print up to 6 bytes of trailing data * main.c (decompress): Print up to 6 bytes of trailing data
when '-vvvv' is specified. when '-vvvv' is specified.
* decoder.c (LZd_verify_trailer): Removed test of final code. * decoder.c (LZd_verify_trailer): Remove test of final code.
* main.c (main): Delete '--output' file if infd is a terminal. * main.c (main): Delete '--output' file if infd is a terminal.
* main.c (main): Don't use stdin more than once. * main.c (main): Don't use stdin more than once.
* Error messages synced with lzip-1.18. * Error messages synced with lzip-1.18.
@ -52,17 +64,17 @@
* Version 1.7 released. * Version 1.7 released.
* Minor changes. * Minor changes.
* Makefile.in: Added new targets 'install*-compress'. * Makefile.in: New targets 'install*-compress'.
2014-07-01 Antonio Diaz Diaz <antonio@gnu.org> 2014-07-01 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.6 released. * Version 1.6 released.
* License changed to GPL version 2 or later. * Change license to GPL version 2 or later.
2014-04-11 Antonio Diaz Diaz <antonio@gnu.org> 2014-04-11 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.5 released. * Version 1.5 released.
* main.c: Added new option '-u, --buffer-size' (low memory mode). * main.c: New option '-u, --buffer-size' (low memory mode).
* main.c (close_and_set_permissions): Behave like 'cp -p'. * main.c (close_and_set_permissions): Behave like 'cp -p'.
2013-09-17 Antonio Diaz Diaz <antonio@gnu.org> 2013-09-17 Antonio Diaz Diaz <antonio@gnu.org>
@ -83,8 +95,7 @@
* Version 1.2 released. * Version 1.2 released.
* Decompression time has been reduced by 12%. * Decompression time has been reduced by 12%.
* Makefile.in: Added new target 'install-as-lzip'. * Makefile.in: New targets 'install-as-lzip' and 'install-bin'.
* Makefile.in: Added new target 'install-bin'.
* main.c: Use 'setmode' instead of '_setmode' on Windows and OS/2. * main.c: Use 'setmode' instead of '_setmode' on Windows and OS/2.
2012-02-26 Antonio Diaz Diaz <ant_diaz@teleline.es> 2012-02-26 Antonio Diaz Diaz <ant_diaz@teleline.es>
@ -94,8 +105,8 @@
multi-member file when only one '-v' is specified. multi-member file when only one '-v' is specified.
* main.c (close_and_set_permissions): Inability to change output * main.c (close_and_set_permissions): Inability to change output
file attributes has been downgraded from error to warning. file attributes has been downgraded from error to warning.
* Changed quote characters in messages as advised by GNU Standards. * Change quote characters in messages as advised by GNU Standards.
* configure: 'datadir' renamed to 'datarootdir'. * configure: Rename 'datadir' to 'datarootdir'.
2011-01-17 Antonio Diaz Diaz <ant_diaz@teleline.es> 2011-01-17 Antonio Diaz Diaz <ant_diaz@teleline.es>
@ -104,8 +115,8 @@
* Created from the decompression code of clzip 1.1. * Created from the decompression code of clzip 1.1.
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This file is a collection of facts, and thus it is not copyrightable, This file is a collection of facts, and thus it is not copyrightable,
but just in case, you have unlimited permission to copy, distribute and but just in case, you have unlimited permission to copy, distribute, and
modify it. modify it.

22
INSTALL
View file

@ -1,7 +1,7 @@
Requirements Requirements
------------ ------------
You will need a C compiler. You will need a C99 compiler. (gcc 3.3.6 or newer is recommended).
I use gcc 5.3.0 and 4.1.2, but the code should compile with any standards I use gcc 6.1.0 and 4.1.2, but the code should compile with any standards
compliant compiler. compliant compiler.
Gcc is available at http://gcc.gnu.org. Gcc is available at http://gcc.gnu.org.
@ -41,11 +41,11 @@ the main archive.
documentation. documentation.
Or type 'make install-compress', which additionally compresses the Or type 'make install-compress', which additionally compresses the
man page after installation. (Installing compressed docs may become man page after installation.
the default in the future). (Installing compressed docs may become the default in the future).
You can install only the program or the man page by typing 'make You can install only the program or the man page by typing
install-bin' or 'make install-man' respectively. 'make install-bin' or 'make install-man' respectively.
Instead of 'make install', you can type 'make install-as-lzip' to Instead of 'make install', you can type 'make install-as-lzip' to
install the program and any data files and documentation, and link install the program and any data files and documentation, and link
@ -55,10 +55,10 @@ the main archive.
Another way Another way
----------- -----------
You can also compile lunzip into a separate directory. You can also compile lunzip into a separate directory.
To do this, you must use a version of 'make' that supports the 'VPATH' To do this, you must use a version of 'make' that supports the variable
variable, such as GNU 'make'. 'cd' to the directory where you want the 'VPATH', such as GNU 'make'. 'cd' to the directory where you want the
object files and executables to go and run the 'configure' script. object files and executables to go and run the 'configure' script.
'configure' automatically checks for the source code in '.', in '..' and 'configure' automatically checks for the source code in '.', in '..', and
in the directory that 'configure' is in. in the directory that 'configure' is in.
'configure' recognizes the option '--srcdir=DIR' to control where to 'configure' recognizes the option '--srcdir=DIR' to control where to
@ -69,7 +69,7 @@ After running 'configure', you can run 'make' and 'make install' as
explained above. explained above.
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute, and modify it.

View file

@ -119,7 +119,10 @@ dist : doc
$(DISTNAME)/*.c \ $(DISTNAME)/*.c \
$(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/check.sh \
$(DISTNAME)/testsuite/test.txt \ $(DISTNAME)/testsuite/test.txt \
$(DISTNAME)/testsuite/test.txt.lz $(DISTNAME)/testsuite/fox.lz \
$(DISTNAME)/testsuite/fox_*.lz \
$(DISTNAME)/testsuite/test.txt.lz \
$(DISTNAME)/testsuite/test_em.txt.lz
rm -f $(DISTNAME) rm -f $(DISTNAME)
lzip -v -9 $(DISTNAME).tar lzip -v -9 $(DISTNAME).tar

32
NEWS
View file

@ -1,14 +1,28 @@
Changes in version 1.11: Changes in version 1.12:
Detection of forbidden combinations of characters in trailing data has Lunzip now reports an error if a file name is empty (lunzip -t "").
been improved.
Errors are now also checked when closing the input file. Option '-o, --output' now behaves like '-c, --stdout', but sending the
output unconditionally to a file instead of to standard output. See the new
description of '-o' in the manual. This change is backwards compatible only
when decompressing from standard input alone. Therefore commands like:
lunzip -d -o foo - bar.lz < foo.lz
must now be split into:
lunzip -d -o foo - < foo.lz
lunzip -d bar.lz
or rewritten as:
lunzip -d - bar.lz < foo.lz > foo
Lunzip now compiles on DOS with DJGPP. (Patch from Robert Riebisch). Lunzip now does not even open the output file if the input file is a terminal.
The configure script now accepts appending options to CFLAGS using the The words 'decompressed' and 'compressed' have been replaced with the
syntax 'CFLAGS+=OPTIONS'. shorter 'out' and 'in' in the verbose output when decompressing or testing.
It has been documented in INSTALL the use of Option '--list' now reports corruption or truncation of the last header in a
CFLAGS+='-D __USE_MINGW_ANSI_STDIO' when compiling on MinGW. multimenber file specifically instead of showing the generic message "Last
member in input file is truncated or corrupt."
The commands needed to extract files from a tar.lz archive have been
documented in the output of '--help' and in the man page.
9 new test files have been added to the testsuite.

78
README
View file

@ -1,53 +1,57 @@
Description Description
Lunzip is a decompressor for the lzip format. It is written in C and its Lunzip is a decompressor for the lzip format written in C. Its small size
small size makes it well suited for embedded devices or software makes it well suited for embedded devices or software installers that need
installers that need to decompress files but don't need compression to decompress files but don't need compression capabilities. Lunzip is fully
capabilities. Lunzip is fully compatible with lzip-1.4 or newer. compatible with lzip 1.4 or newer.
The lzip file format is designed for data sharing and long-term archiving, The lzip file format is designed for data sharing and long-term archiving,
taking into account both data integrity and decoder availability: taking into account both data integrity and decoder availability:
* The lzip format provides very safe integrity checking and some data * The lzip format provides very safe integrity checking and some data
recovery means. The lziprecover program can repair bit flip errors recovery means. The program lziprecover can repair bit flip errors
(one of the most common forms of data corruption) in lzip files, (one of the most common forms of data corruption) in lzip files, and
and provides data recovery capabilities, including error-checked provides data recovery capabilities, including error-checked merging
merging of damaged copies of a file. of damaged copies of a file.
* The lzip format is as simple as possible (but not simpler). The * The lzip format is as simple as possible (but not simpler). The lzip
lzip manual provides the source code of a simple decompressor manual provides the source code of a simple decompressor along with a
along with a detailed explanation of how it works, so that with detailed explanation of how it works, so that with the only help of the
the only help of the lzip manual it would be possible for a lzip manual it would be possible for a digital archaeologist to extract
digital archaeologist to extract the data from a lzip file long the data from a lzip file long after quantum computers eventually
after quantum computers eventually render LZMA obsolete. render LZMA obsolete.
* Additionally the lzip reference implementation is copylefted, which * Additionally the lzip reference implementation is copylefted, which
guarantees that it will remain free forever. guarantees that it will remain free forever.
A nice feature of the lzip format is that a corrupt byte is easier to A nice feature of the lzip format is that a corrupt byte is easier to repair
repair the nearer it is from the beginning of the file. Therefore, with the nearer it is from the beginning of the file. Therefore, with the help of
the help of lziprecover, losing an entire archive just because of a lziprecover, losing an entire archive just because of a corrupt byte near
corrupt byte near the beginning is a thing of the past. the beginning is a thing of the past.
Lunzip uses the same well-defined exit status values used by lzip, which Lunzip uses the same well-defined exit status values used by bzip2, which
makes it safer than decompressors returning ambiguous warning values (like makes it safer than decompressors returning ambiguous warning values (like
gunzip) when it is used as a back end for other programs like tar or zutils. gunzip) when it is used as a back end for other programs like tar or zutils.
Lunzip provides a 'low memory' mode able to decompress any file using as 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 little memory as 50 kB, irrespective of the dictionary size used to
compress the file. To activate it, specify the size of the output buffer compress the file. To activate it, specify the size of the output buffer
with the '--buffer-size' option and lunzip will use the decompressed with the option '--buffer-size' and lunzip will use the decompressed
file as dictionary for distances beyond the buffer size. Of course, the file as dictionary for distances beyond the buffer size. Of course, the
smaller the buffer size used in relation to the dictionary size, the larger the difference between the buffer size and the dictionary size, the
more accesses to disk are needed and the slower the decompression is. more accesses to disk are needed and the slower the decompression is.
This 'low memory' mode only works when decompressing to a regular file This 'low memory' mode only works when decompressing to a regular file
and is intended for systems without enough memory (RAM + swap) to keep and is intended for systems without enough memory (RAM + swap) to keep
the whole dictionary at once. It has been tested on a laptop with a 486 the whole dictionary at once. It has been tested on a laptop with a 486
processor and 4 MiB of RAM. processor and 4 MiB of RAM.
The amount of memory required by lunzip to decompress a file is about The option '--buffer-size' may help to decompress a file erroneously created
46 kB larger than the dictionary size used to compress that file, unless with a dictionary size much larger than the uncompressed size. (Lzip adjusts
the '--buffer-size' option is specified. the dictionary size to the uncompressed size, but third-party tools may not).
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 Lunzip attempts to guess the name for the decompressed file from that of
the compressed file as follows: the compressed file as follows:
@ -62,12 +66,12 @@ possible, ownership of the file just as 'cp -p' does. (If the user ID or
the group ID can't be duplicated, the file permission bits S_ISUID and the group ID can't be duplicated, the file permission bits S_ISUID and
S_ISGID are cleared). S_ISGID are cleared).
Lunzip is able to read from some types of non regular files if the Lunzip is able to read from some types of non-regular files if either the
'--stdout' option is specified. option '-c' or the option '-o' is specified.
If no file names are specified, lunzip decompresses from standard input If no file names are specified, lunzip decompresses from standard input to
to standard output. In this case, lunzip will decline to read compressed standard output. In this case, lunzip will refuse to read compressed input
input from a terminal. from a terminal, as this might leave the terminal in an abnormal state.
Lunzip will correctly decompress a file which is the concatenation of two or Lunzip will correctly decompress a file which is the concatenation of two or
more compressed files. The result is the concatenation of the corresponding more compressed files. The result is the concatenation of the corresponding
@ -75,16 +79,20 @@ decompressed files. Integrity testing of concatenated compressed files is
also supported. also supported.
The ideas embodied in lunzip are due to (at least) the following people: The ideas embodied in lunzip are due to (at least) the following people:
Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for the
the definition of Markov chains), G.N.N. Martin (for the definition of definition of Markov chains), G.N.N. Martin (for the definition of range
range encoding), Igor Pavlov (for putting all the above together in encoding), Igor Pavlov (for putting all the above together in LZMA), and
LZMA), and Julian Seward (for bzip2's CLI). Julian Seward (for bzip2's CLI).
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never have
been compressed. Decompressed is used to refer to data which have undergone
the process of decompression.
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute, and modify it.
The file Makefile.in is a data file used by configure to produce the The file Makefile.in is a data file used by configure to produce the
Makefile. It has the same copyright owner and permissions that configure Makefile. It has the same copyright owner and permissions that configure

View file

@ -1,15 +1,15 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2019 Antonio Diaz Diaz. Copyright (C) 2006-2021 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
that the following conditions are met: that the following conditions are met:
1. Redistributions of source code must retain the above copyright 1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright 2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,

View file

@ -1,15 +1,15 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2019 Antonio Diaz Diaz. Copyright (C) 2006-2021 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
that the following conditions are met: that the following conditions are met:
1. Redistributions of source code must retain the above copyright 1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright 2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
@ -18,7 +18,7 @@
*/ */
/* Arg_parser reads the arguments in 'argv' and creates a number of /* Arg_parser reads the arguments in 'argv' and creates a number of
option codes, option arguments and non-option arguments. option codes, option arguments, and non-option arguments.
In case of error, 'ap_error' returns a non-null pointer to an error In case of error, 'ap_error' returns a non-null pointer to an error
message. message.
@ -79,7 +79,7 @@ void ap_free( struct Arg_parser * const ap );
const char * ap_error( const struct Arg_parser * const ap ); const char * ap_error( const struct Arg_parser * const ap );
/* The number of arguments parsed (may be different from argc) */ /* The number of arguments parsed. May be different from argc. */
int ap_arguments( const struct Arg_parser * const ap ); int ap_arguments( const struct Arg_parser * const ap );
/* If ap_code( i ) is 0, ap_argument( i ) is a non-option. /* If ap_code( i ) is 0, ap_argument( i ) is a non-option.

25
configure vendored
View file

@ -1,12 +1,12 @@
#! /bin/sh #! /bin/sh
# configure script for Lunzip - Decompressor for the lzip format # configure script for Lunzip - Decompressor for the lzip format
# Copyright (C) 2010-2019 Antonio Diaz Diaz. # Copyright (C) 2010-2021 Antonio Diaz Diaz.
# #
# This configure script is free software: you have unlimited permission # This configure script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute, and modify it.
pkgname=lunzip pkgname=lunzip
pkgversion=1.11 pkgversion=1.12
progname=lunzip progname=lunzip
srctrigger=doc/${progname}.1 srctrigger=doc/${progname}.1
@ -26,11 +26,7 @@ CFLAGS='-Wall -W -O2'
LDFLAGS= LDFLAGS=
# checking whether we are using GNU C. # checking whether we are using GNU C.
/bin/sh -c "${CC} --version" > /dev/null 2>&1 || /bin/sh -c "${CC} --version" > /dev/null 2>&1 || { CC=cc ; CFLAGS=-O2 ; }
{
CC=cc
CFLAGS=-O2
}
# Loop over all args # Loop over all args
args= args=
@ -42,11 +38,12 @@ while [ $# != 0 ] ; do
shift shift
# Add the argument quoted to args # Add the argument quoted to args
args="${args} \"${option}\"" if [ -z "${args}" ] ; then args="\"${option}\""
else args="${args} \"${option}\"" ; fi
# Split out the argument for options that take them # Split out the argument for options that take them
case ${option} in case ${option} in
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;; *=*) optarg=`echo "${option}" | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
esac esac
# Process the options # Process the options
@ -125,7 +122,7 @@ if [ -z "${srcdir}" ] ; then
if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi
if [ ! -r "${srcdir}/${srctrigger}" ] ; then if [ ! -r "${srcdir}/${srctrigger}" ] ; then
## the sed command below emulates the dirname command ## the sed command below emulates the dirname command
srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` srcdir=`echo "$0" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
fi fi
fi fi
@ -148,7 +145,7 @@ if [ -z "${no_create}" ] ; then
# Run this file to recreate the current configuration. # Run this file to recreate the current configuration.
# #
# This script is free software: you have unlimited permission # This script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute, and modify it.
exec /bin/sh $0 ${args} --no-create exec /bin/sh $0 ${args} --no-create
EOF EOF
@ -170,11 +167,11 @@ echo "LDFLAGS = ${LDFLAGS}"
rm -f Makefile rm -f Makefile
cat > Makefile << EOF cat > Makefile << EOF
# Makefile for Lunzip - Decompressor for the lzip format # Makefile for Lunzip - Decompressor for the lzip format
# Copyright (C) 2010-2019 Antonio Diaz Diaz. # Copyright (C) 2010-2021 Antonio Diaz Diaz.
# This file was generated automatically by configure. Don't edit. # This file was generated automatically by configure. Don't edit.
# #
# This Makefile is free software: you have unlimited permission # This Makefile is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute, and modify it.
pkgname = ${pkgname} pkgname = ${pkgname}
pkgversion = ${pkgversion} pkgversion = ${pkgversion}

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -104,9 +104,8 @@ void LZd_flush_data( struct LZ_decoder * const d )
writeblock( d->outfd, d->buffer + d->stream_pos, size ) != size ) writeblock( d->outfd, d->buffer + d->stream_pos, size ) != size )
{ show_error( "Write error", errno, false ); cleanup_and_fail( 1 ); } { show_error( "Write error", errno, false ); cleanup_and_fail( 1 ); }
if( d->pos >= d->buffer_size ) if( d->pos >= d->buffer_size )
{ d->partial_data_pos += d->pos; d->pos = 0; d->pos_wrapped = true; { d->partial_data_pos += d->pos; d->pos = 0;
if( d->partial_data_pos >= d->dictionary_size ) if( d->partial_data_pos >= d->dictionary_size ) d->pos_wrapped = true; }
d->pos_wrapped_dic = true; }
d->stream_pos = d->pos; d->stream_pos = d->pos;
} }
} }
@ -181,8 +180,7 @@ static bool LZd_verify_trailer( struct LZ_decoder * const d,
100.0 - ( ( 100.0 * member_size ) / data_size ) ); 100.0 - ( ( 100.0 * member_size ) / data_size ) );
if( verbosity >= 4 ) fprintf( stderr, "CRC %08X, ", td_crc ); if( verbosity >= 4 ) fprintf( stderr, "CRC %08X, ", td_crc );
if( verbosity >= 3 ) if( verbosity >= 3 )
fprintf( stderr, "decompressed %9llu, compressed %8llu. ", fprintf( stderr, "%9llu out, %8llu in. ", data_size, member_size );
data_size, member_size );
} }
return true; return true;
} }
@ -320,7 +318,7 @@ int LZd_decode_member( struct LZ_decoder * const d,
rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance; rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance;
state = St_set_match( state ); state = St_set_match( state );
if( rep0 >= d->dictionary_size || if( rep0 >= d->dictionary_size ||
( rep0 >= LZd_data_position( d ) && !d->pos_wrapped_dic ) ) ( !d->pos_wrapped && rep0 >= LZd_data_position( d ) ) )
{ LZd_flush_data( d ); return 1; } { LZd_flush_data( d ); return 1; }
} }
copy_block( d, rep0, len ); copy_block( d, rep0, len );

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -107,7 +107,7 @@ static inline unsigned Rd_decode( struct Range_decoder * const rdec,
/* symbol <<= 1; */ /* symbol <<= 1; */
/* if( rdec->code >= rdec->range ) { rdec->code -= rdec->range; symbol |= 1; } */ /* if( rdec->code >= rdec->range ) { rdec->code -= rdec->range; symbol |= 1; } */
bit = ( rdec->code >= rdec->range ); bit = ( rdec->code >= rdec->range );
symbol = ( symbol << 1 ) + bit; symbol <<= 1; symbol += bit;
rdec->code -= rdec->range & ( 0U - bit ); rdec->code -= rdec->range & ( 0U - bit );
} }
return symbol; return symbol;
@ -137,8 +137,7 @@ static inline unsigned Rd_decode_bit( struct Range_decoder * const rdec,
static inline unsigned Rd_decode_tree3( struct Range_decoder * const rdec, static inline unsigned Rd_decode_tree3( struct Range_decoder * const rdec,
Bit_model bm[] ) Bit_model bm[] )
{ {
unsigned symbol = 1; unsigned symbol = 2 | Rd_decode_bit( rdec, &bm[1] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] ); symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] ); symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
return symbol & 7; return symbol & 7;
@ -147,8 +146,7 @@ static inline unsigned Rd_decode_tree3( struct Range_decoder * const rdec,
static inline unsigned Rd_decode_tree6( struct Range_decoder * const rdec, static inline unsigned Rd_decode_tree6( struct Range_decoder * const rdec,
Bit_model bm[] ) Bit_model bm[] )
{ {
unsigned symbol = 1; unsigned symbol = 2 | Rd_decode_bit( rdec, &bm[1] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] ); symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] ); symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] ); symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
@ -177,7 +175,7 @@ Rd_decode_tree_reversed( struct Range_decoder * const rdec,
for( i = 0; i < num_bits; ++i ) for( i = 0; i < num_bits; ++i )
{ {
const unsigned bit = Rd_decode_bit( rdec, &bm[model] ); const unsigned bit = Rd_decode_bit( rdec, &bm[model] );
model = ( model << 1 ) + bit; model <<= 1; model += bit;
symbol |= ( bit << i ); symbol |= ( bit << i );
} }
return symbol; return symbol;
@ -187,12 +185,9 @@ static inline unsigned
Rd_decode_tree_reversed4( struct Range_decoder * const rdec, Bit_model bm[] ) Rd_decode_tree_reversed4( struct Range_decoder * const rdec, Bit_model bm[] )
{ {
unsigned symbol = Rd_decode_bit( rdec, &bm[1] ); unsigned symbol = Rd_decode_bit( rdec, &bm[1] );
unsigned model = 2 + symbol; symbol += Rd_decode_bit( rdec, &bm[2+symbol] ) << 1;
unsigned bit = Rd_decode_bit( rdec, &bm[model] ); symbol += Rd_decode_bit( rdec, &bm[4+symbol] ) << 2;
model = ( model << 1 ) + bit; symbol |= ( bit << 1 ); symbol += Rd_decode_bit( rdec, &bm[8+symbol] ) << 3;
bit = Rd_decode_bit( rdec, &bm[model] );
model = ( model << 1 ) + bit; symbol |= ( bit << 2 );
symbol |= ( Rd_decode_bit( rdec, &bm[model] ) << 3 );
return symbol; return symbol;
} }
@ -205,7 +200,7 @@ static inline unsigned Rd_decode_matched( struct Range_decoder * const rdec,
{ {
const unsigned match_bit = ( match_byte <<= 1 ) & mask; const unsigned match_bit = ( match_byte <<= 1 ) & mask;
const unsigned bit = Rd_decode_bit( rdec, &bm[symbol+match_bit+mask] ); const unsigned bit = Rd_decode_bit( rdec, &bm[symbol+match_bit+mask] );
symbol = ( symbol << 1 ) + bit; symbol <<= 1; symbol += bit;
if( symbol > 0xFF ) return symbol & 0xFF; if( symbol > 0xFF ) return symbol & 0xFF;
mask &= ~(match_bit ^ (bit << 8)); /* if( match_bit != bit ) mask = 0; */ mask &= ~(match_bit ^ (bit << 8)); /* if( match_bit != bit ) mask = 0; */
} }
@ -235,7 +230,6 @@ struct LZ_decoder
uint32_t crc; uint32_t crc;
int outfd; /* output file descriptor */ int outfd; /* output file descriptor */
bool pos_wrapped; bool pos_wrapped;
bool pos_wrapped_dic;
}; };
void LZd_flush_data( struct LZ_decoder * const d ); void LZd_flush_data( struct LZ_decoder * const d );
@ -333,7 +327,6 @@ static inline bool LZd_init( struct LZ_decoder * const d,
d->crc = 0xFFFFFFFFU; d->crc = 0xFFFFFFFFU;
d->outfd = ofd; d->outfd = ofd;
d->pos_wrapped = false; d->pos_wrapped = false;
d->pos_wrapped_dic = false;
/* prev_byte of first byte; also for LZd_peek( 0 ) on corrupt file */ /* prev_byte of first byte; also for LZd_peek( 0 ) on corrupt file */
d->buffer[d->buffer_size-1] = 0; d->buffer[d->buffer_size-1] = 0;
return true; return true;

View file

@ -1,22 +1,22 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
.TH LUNZIP "1" "January 2019" "lunzip 1.11" "User Commands" .TH LUNZIP "1" "January 2021" "lunzip 1.12" "User Commands"
.SH NAME .SH NAME
lunzip \- decompressor for the lzip format lunzip \- decompressor for the lzip format
.SH SYNOPSIS .SH SYNOPSIS
.B lunzip .B lunzip
[\fI\,options\/\fR] [\fI\,files\/\fR] [\fI\,options\/\fR] [\fI\,files\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Lunzip is a decompressor for the lzip format. It is written in C and its Lunzip is a decompressor for the lzip format written in C. Its small size
small size makes it well suited for embedded devices or software makes it well suited for embedded devices or software installers that need
installers that need to decompress files but don't need compression to decompress files but don't need compression capabilities. Lunzip is fully
capabilities. Lunzip is fully compatible with lzip\-1.4 or newer. compatible with lzip 1.4 or newer.
.PP .PP
Lunzip provides a 'low memory' mode able to decompress any file using as 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 little memory as 50 kB, irrespective of the dictionary size used to
compress the file. To activate it, specify the size of the output buffer compress the file. To activate it, specify the size of the output buffer
with the '\-\-buffer\-size' option and lunzip will use the decompressed with the option \fB\-\-buffer\-size\fR and lunzip will use the decompressed
file as dictionary for distances beyond the buffer size. Of course, the file as dictionary for distances beyond the buffer size. Of course, the
smaller the buffer size used in relation to the dictionary size, the larger the difference between the buffer size and the dictionary size, the
more accesses to disk are needed and the slower the decompression is. more accesses to disk are needed and the slower the decompression is.
This 'low memory' mode only works when decompressing to a regular file This 'low memory' mode only works when decompressing to a regular file
and is intended for systems without enough memory (RAM + swap) to keep and is intended for systems without enough memory (RAM + swap) to keep
@ -48,7 +48,7 @@ keep (don't delete) input files
print (un)compressed file sizes print (un)compressed file sizes
.TP .TP
\fB\-o\fR, \fB\-\-output=\fR<file> \fB\-o\fR, \fB\-\-output=\fR<file>
if reading standard input, write to <file> write to <file>, keep input files
.TP .TP
\fB\-q\fR, \fB\-\-quiet\fR \fB\-q\fR, \fB\-\-quiet\fR
suppress all messages suppress all messages
@ -72,16 +72,25 @@ Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...
Buffer sizes 12 to 29 are interpreted as powers of two, meaning 2^12 Buffer sizes 12 to 29 are interpreted as powers of two, meaning 2^12
to 2^29 bytes. to 2^29 bytes.
.PP .PP
To extract all the files from archive 'foo.tar.lz', use the commands
\&'tar \fB\-xf\fR foo.tar.lz' or 'lunzip \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'.
.PP
Exit status: 0 for a normal exit, 1 for environmental problems (file Exit status: 0 for a normal exit, 1 for environmental problems (file
not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or
invalid input file, 3 for an internal consistency error (eg, bug) which invalid input file, 3 for an internal consistency error (eg, bug) which
caused lunzip to panic. caused lunzip to panic.
.PP
The ideas embodied in lunzip are due to (at least) the following people:
Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for the
definition of Markov chains), G.N.N. Martin (for the definition of range
encoding), Igor Pavlov (for putting all the above together in LZMA), and
Julian Seward (for bzip2's CLI).
.SH "REPORTING BUGS" .SH "REPORTING BUGS"
Report bugs to lzip\-bug@nongnu.org Report bugs to lzip\-bug@nongnu.org
.br .br
Lunzip home page: http://www.nongnu.org/lzip/lunzip.html Lunzip home page: http://www.nongnu.org/lzip/lunzip.html
.SH COPYRIGHT .SH COPYRIGHT
Copyright \(co 2019 Antonio Diaz Diaz. Copyright \(co 2021 Antonio Diaz Diaz.
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
.br .br
This is free software: you are free to change and redistribute it. This is free software: you are free to change and redistribute it.

29
list.c
View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -18,9 +18,9 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -33,11 +33,11 @@ static void list_line( const unsigned long long uncomp_size,
const char * const input_filename ) const char * const input_filename )
{ {
if( uncomp_size > 0 ) if( uncomp_size > 0 )
printf( "%15llu %15llu %6.2f%% %s\n", uncomp_size, comp_size, printf( "%14llu %14llu %6.2f%% %s\n", uncomp_size, comp_size,
100.0 - ( ( 100.0 * comp_size ) / uncomp_size ), 100.0 - ( ( 100.0 * comp_size ) / uncomp_size ),
input_filename ); input_filename );
else else
printf( "%15llu %15llu -INF%% %s\n", uncomp_size, comp_size, printf( "%14llu %14llu -INF%% %s\n", uncomp_size, comp_size,
input_filename ); input_filename );
} }
@ -60,15 +60,15 @@ int list_files( const char * const filenames[], const int num_filenames,
if( from_stdin ) { if( stdin_used ) continue; else stdin_used = true; } if( from_stdin ) { if( stdin_used ) continue; else stdin_used = true; }
input_filename = from_stdin ? "(stdin)" : filenames[i]; input_filename = from_stdin ? "(stdin)" : filenames[i];
infd = from_stdin ? STDIN_FILENO : infd = from_stdin ? STDIN_FILENO :
open_instream( input_filename, &in_stats, true, true ); open_instream( input_filename, &in_stats, false, true );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
Li_init( &lzip_index, infd, ignore_trailing, loose_trailing ); Li_init( &lzip_index, infd, ignore_trailing, loose_trailing );
close( infd ); close( infd );
if( lzip_index.retval != 0 ) if( lzip_index.retval != 0 )
{ {
show_file_error( input_filename, lzip_index.error, 0 ); show_file_error( input_filename, lzip_index.error, 0 );
if( retval < lzip_index.retval ) retval = lzip_index.retval; set_retval( &retval, lzip_index.retval );
Li_free( &lzip_index ); continue; Li_free( &lzip_index ); continue;
} }
if( verbosity >= 0 ) if( verbosity >= 0 )
@ -83,17 +83,8 @@ int list_files( const char * const filenames[], const int num_filenames,
fputs( " uncompressed compressed saved name\n", stdout ); fputs( " uncompressed compressed saved name\n", stdout );
} }
if( verbosity >= 1 ) if( verbosity >= 1 )
{ printf( "%s %5ld %6lld ", format_ds( lzip_index.dictionary_size ),
long long trailing_size; lzip_index.members, Li_file_size( &lzip_index ) - cdata_size );
unsigned dictionary_size = 0;
long i;
for( i = 0; i < lzip_index.members; ++i )
dictionary_size =
max( dictionary_size, Li_dictionary_size( &lzip_index, i ) );
trailing_size = Li_file_size( &lzip_index ) - cdata_size;
printf( "%s %5ld %6lld ", format_ds( dictionary_size ),
lzip_index.members, trailing_size );
}
list_line( udata_size, cdata_size, input_filename ); list_line( udata_size, cdata_size, input_filename );
if( verbosity >= 2 && lzip_index.members > 1 ) if( verbosity >= 2 && lzip_index.members > 1 )
@ -104,7 +95,7 @@ int list_files( const char * const filenames[], const int num_filenames,
{ {
const struct Block * db = Li_dblock( &lzip_index, i ); const struct Block * db = Li_dblock( &lzip_index, i );
const struct Block * mb = Li_mblock( &lzip_index, i ); const struct Block * mb = Li_mblock( &lzip_index, i );
printf( "%5ld %15llu %15llu %15llu %15llu\n", printf( "%6ld %14llu %14llu %14llu %14llu\n",
i + 1, db->pos, db->size, mb->pos, mb->size ); i + 1, db->pos, db->size, mb->pos, mb->size );
} }
first_post = true; /* reprint heading after list of members */ first_post = true; /* reprint heading after list of members */

83
lzip.h
View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -22,8 +22,6 @@
#define min(x,y) ((x) <= (y) ? (x) : (y)) #define min(x,y) ((x) <= (y) ? (x) : (y))
#endif #endif
void * resize_buffer( void * buf, const unsigned min_size );
typedef int State; typedef int State;
enum { states = 12 }; enum { states = 12 };
@ -82,7 +80,7 @@ static inline int get_len_state( const int len )
{ return min( len - min_match_len, len_states - 1 ); } { return min( len - min_match_len, len_states - 1 ); }
static inline int get_lit_state( const uint8_t prev_byte ) static inline int get_lit_state( const uint8_t prev_byte )
{ return ( prev_byte >> ( 8 - literal_context_bits ) ); } { return prev_byte >> ( 8 - literal_context_bits ); }
enum { bit_model_move_bits = 5, enum { bit_model_move_bits = 5,
@ -116,65 +114,6 @@ static inline void Lm_init( struct Len_model * const lm )
} }
/* defined in main.c */
extern int verbosity;
struct Pretty_print /* requires global var 'int verbosity' */
{
const char * name;
char * padded_name;
const char * stdin_name;
unsigned longest_name;
bool first_post;
};
static inline void Pp_init( struct Pretty_print * const pp,
const char * const filenames[],
const int num_filenames )
{
unsigned stdin_name_len;
int i;
pp->name = 0;
pp->padded_name = 0;
pp->stdin_name = "(stdin)";
pp->longest_name = 0;
pp->first_post = false;
if( verbosity <= 0 ) return;
stdin_name_len = strlen( pp->stdin_name );
for( i = 0; i < num_filenames; ++i )
{
const char * const s = filenames[i];
const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s );
if( pp->longest_name < len ) pp->longest_name = len;
}
if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len;
}
static inline void Pp_set_name( struct Pretty_print * const pp,
const char * const filename )
{
unsigned name_len, padded_name_len, i = 0;
if( filename && filename[0] && strcmp( filename, "-" ) != 0 )
pp->name = filename;
else pp->name = pp->stdin_name;
name_len = strlen( pp->name );
padded_name_len = max( name_len, pp->longest_name ) + 4;
pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 );
while( i < 2 ) pp->padded_name[i++] = ' ';
while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; }
pp->padded_name[i++] = ':';
while( i < padded_name_len ) pp->padded_name[i++] = ' ';
pp->padded_name[i] = 0;
pp->first_post = true;
}
static inline void Pp_reset( struct 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 );
typedef uint32_t CRC32[256]; /* Table of CRCs of all 8-bit messages. */ typedef uint32_t CRC32[256]; /* Table of CRCs of all 8-bit messages. */
extern CRC32 crc32; extern CRC32 crc32;
@ -213,7 +152,7 @@ static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */
typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */ typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */
/* 4 version */ /* 4 version */
/* 5 coded_dict_size */ /* 5 coded dictionary size */
enum { Lh_size = 6 }; enum { Lh_size = 6 };
static inline bool Lh_verify_magic( const Lzip_header data ) static inline bool Lh_verify_magic( const Lzip_header data )
@ -250,6 +189,12 @@ static inline unsigned Lh_get_dictionary_size( const Lzip_header data )
return sz; return sz;
} }
static inline bool Lh_verify( const Lzip_header data )
{
return Lh_verify_magic( data ) && Lh_verify_version( data ) &&
isvalid_ds( Lh_get_dictionary_size( data ) );
}
typedef uint8_t Lzip_trailer[20]; typedef uint8_t Lzip_trailer[20];
/* 0-3 CRC32 of the uncompressed data */ /* 0-3 CRC32 of the uncompressed data */
@ -294,10 +239,14 @@ static inline bool Lt_verify_consistency( const Lzip_trailer data )
} }
static inline void set_retval( int * retval, const int new_val )
{ if( *retval < new_val ) *retval = new_val; }
static const char * const bad_magic_msg = "Bad magic number (file not in lzip format)."; static const char * const bad_magic_msg = "Bad magic number (file not in lzip format).";
static const char * const bad_dict_msg = "Invalid dictionary size in member header."; 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 corrupt_mm_msg = "Corrupt header in multimember file.";
static const char * const trailing_msg = "Trailing data not allowed."; static const char * const trailing_msg = "Trailing data not allowed.";
static const char * const mem_msg = "Not enough memory.";
/* defined in decoder.c */ /* defined in decoder.c */
int readblock( const int fd, uint8_t * const buf, const int size ); int readblock( const int fd, uint8_t * const buf, const int size );
@ -308,11 +257,15 @@ int list_files( const char * const filenames[], const int num_filenames,
/* defined in main.c */ /* defined in main.c */
struct stat; struct stat;
struct Pretty_print;
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 );
const char * bad_version( const unsigned version ); const char * bad_version( const unsigned version );
const char * format_ds( const unsigned dictionary_size ); const char * format_ds( const unsigned dictionary_size );
void show_header( const unsigned dictionary_size ); void show_header( const unsigned dictionary_size );
int open_instream( const char * const name, struct stat * const in_statsp, int open_instream( const char * const name, struct stat * const in_statsp,
const bool no_ofile, const bool reg_only ); const bool one_to_one, const bool reg_only );
void cleanup_and_fail( const int retval ); void cleanup_and_fail( const int retval );
void show_error( const char * const msg, const int errcode, const bool help ); void show_error( const char * const msg, const int errcode, const bool help );
void show_file_error( const char * const filename, const char * const msg, void show_file_error( const char * const filename, const char * const msg,

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -19,10 +19,10 @@
#include <errno.h> #include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include "lzip.h" #include "lzip.h"
@ -58,8 +58,7 @@ static bool push_back_member( struct Lzip_index * const li,
struct Member * p; struct Member * p;
void * tmp = resize_buffer( li->member_vector, void * tmp = resize_buffer( li->member_vector,
( li->members + 1 ) * sizeof li->member_vector[0] ); ( li->members + 1 ) * sizeof li->member_vector[0] );
if( !tmp ) if( !tmp ) { add_error( li, mem_msg ); li->retval = 1; return false; }
{ add_error( li, "Not enough memory." ); li->retval = 1; return false; }
li->member_vector = (struct Member *)tmp; li->member_vector = (struct Member *)tmp;
p = &(li->member_vector[li->members]); p = &(li->member_vector[li->members]);
init_member( p, dp, ds, mp, ms, dict_size ); init_member( p, dp, ds, mp, ms, dict_size );
@ -89,6 +88,19 @@ static void Li_reverse_member_vector( struct Lzip_index * const li )
} }
static bool Li_check_header_error( struct Lzip_index * const li,
const Lzip_header header )
{
if( !Lh_verify_magic( header ) )
{ add_error( li, bad_magic_msg ); li->retval = 2; return true; }
if( !Lh_verify_version( header ) )
{ add_error( li, bad_version( Lh_version( header ) ) ); li->retval = 2;
return true; }
if( !isvalid_ds( Lh_get_dictionary_size( header ) ) )
{ add_error( li, bad_dict_msg ); li->retval = 2; return true; }
return false;
}
static void Li_set_errno_error( struct Lzip_index * const li, static void Li_set_errno_error( struct Lzip_index * const li,
const char * const msg ) const char * const msg )
{ {
@ -106,9 +118,18 @@ 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 )
{
if( seek_read( fd, header, Lh_size, pos ) != Lh_size )
{ Li_set_errno_error( li, "Error reading member header: " ); return false; }
return true;
}
/* If successful, push last member and set pos to member header. */ /* If successful, push last member and set pos to member header. */
static bool Li_skip_trailing_data( struct Lzip_index * const li, static bool Li_skip_trailing_data( struct Lzip_index * const li, const int fd,
const int fd, long long * const pos, unsigned long long * const pos,
const bool ignore_trailing, const bool ignore_trailing,
const bool loose_trailing ) const bool loose_trailing )
{ {
@ -135,36 +156,40 @@ static bool Li_skip_trailing_data( struct Lzip_index * const li,
if( buffer[i-1] <= max_msb ) /* most significant byte of member_size */ if( buffer[i-1] <= max_msb ) /* most significant byte of member_size */
{ {
Lzip_header header; Lzip_header header;
const Lzip_header * header2;
const Lzip_trailer * const trailer = const Lzip_trailer * const trailer =
(const Lzip_trailer *)( buffer + i - Lt_size ); (const Lzip_trailer *)( buffer + i - Lt_size );
const unsigned long long member_size = Lt_get_member_size( *trailer ); const unsigned long long member_size = Lt_get_member_size( *trailer );
unsigned dictionary_size; unsigned dictionary_size;
bool full_h2;
if( member_size == 0 ) /* skip trailing zeros */ if( member_size == 0 ) /* skip trailing zeros */
{ while( i > Lt_size && buffer[i-9] == 0 ) --i; continue; } { while( i > Lt_size && buffer[i-9] == 0 ) --i; continue; }
if( member_size > ipos + i || !Lt_verify_consistency( *trailer ) ) if( member_size > ipos + i || !Lt_verify_consistency( *trailer ) )
continue; continue;
if( seek_read( fd, header, Lh_size, if( !Li_read_header( li, fd, header, ipos + i - member_size ) )
ipos + i - member_size ) != Lh_size ) return false;
{ Li_set_errno_error( li, "Error reading member header: " ); if( !Lh_verify( header ) ) continue;
return false; } header2 = (const Lzip_header *)( buffer + i );
dictionary_size = Lh_get_dictionary_size( header ); full_h2 = bsize - i >= Lh_size;
if( !Lh_verify_magic( header ) || !Lh_verify_version( header ) || if( Lh_verify_prefix( *header2, bsize - i ) ) /* last member */
!isvalid_ds( dictionary_size ) ) continue;
if( Lh_verify_prefix( buffer + i, bsize - i ) )
{ {
if( !full_h2 ) add_error( li, "Last member in input file is truncated." );
else if( !Li_check_header_error( li, *header2 ) )
add_error( li, "Last member in input file is truncated or corrupt." ); add_error( li, "Last member in input file is truncated or corrupt." );
li->retval = 2; return false; li->retval = 2; return false;
} }
if( !loose_trailing && bsize - i >= Lh_size && if( !loose_trailing && full_h2 && Lh_verify_corrupt( *header2 ) )
Lh_verify_corrupt( buffer + i ) )
{ add_error( li, corrupt_mm_msg ); li->retval = 2; return false; } { add_error( li, corrupt_mm_msg ); li->retval = 2; return false; }
if( !ignore_trailing ) if( !ignore_trailing )
{ add_error( li, trailing_msg ); li->retval = 2; return false; } { add_error( li, trailing_msg ); li->retval = 2; return false; }
*pos = ipos + i - member_size; *pos = ipos + i - member_size;
dictionary_size = Lh_get_dictionary_size( header );
if( li->dictionary_size < dictionary_size )
li->dictionary_size = dictionary_size;
return push_back_member( li, 0, Lt_get_data_size( *trailer ), *pos, return push_back_member( li, 0, Lt_get_data_size( *trailer ), *pos,
member_size, dictionary_size ); member_size, dictionary_size );
} }
if( ipos <= 0 ) if( ipos == 0 )
{ Li_set_num_error( li, "Bad trailer at pos ", *pos - Lt_size ); { Li_set_num_error( li, "Bad trailer at pos ", *pos - Lt_size );
return false; } return false; }
bsize = buffer_size; bsize = buffer_size;
@ -180,7 +205,7 @@ bool Li_init( struct Lzip_index * const li, const int infd,
const bool ignore_trailing, const bool loose_trailing ) const bool ignore_trailing, const bool loose_trailing )
{ {
Lzip_header header; Lzip_header header;
long long pos; unsigned long long pos;
long i; long i;
li->member_vector = 0; li->member_vector = 0;
li->error = 0; li->error = 0;
@ -188,6 +213,7 @@ bool Li_init( struct Lzip_index * const li, const int infd,
li->members = 0; li->members = 0;
li->error_size = 0; li->error_size = 0;
li->retval = 0; li->retval = 0;
li->dictionary_size = 0;
if( li->insize < 0 ) if( li->insize < 0 )
{ Li_set_errno_error( li, "Input file is not seekable: " ); return false; } { Li_set_errno_error( li, "Input file is not seekable: " ); return false; }
if( li->insize < min_member_size ) if( li->insize < min_member_size )
@ -197,15 +223,8 @@ bool Li_init( struct Lzip_index * const li, const int infd,
{ add_error( li, "Input file is too long (2^63 bytes or more)." ); { add_error( li, "Input file is too long (2^63 bytes or more)." );
li->retval = 2; return false; } li->retval = 2; return false; }
if( seek_read( infd, header, Lh_size, 0 ) != Lh_size ) if( !Li_read_header( li, infd, header, 0 ) ) return false;
{ Li_set_errno_error( li, "Error reading member header: " ); return false; } if( Li_check_header_error( li, header ) ) return false;
if( !Lh_verify_magic( header ) )
{ add_error( li, bad_magic_msg ); li->retval = 2; return false; }
if( !Lh_verify_version( header ) )
{ add_error( li, bad_version( Lh_version( header ) ) ); li->retval = 2;
return false; }
if( !isvalid_ds( Lh_get_dictionary_size( header ) ) )
{ add_error( li, bad_dict_msg ); li->retval = 2; return false; }
pos = li->insize; /* always points to a header or to EOF */ pos = li->insize; /* always points to a header or to EOF */
while( pos >= min_member_size ) while( pos >= min_member_size )
@ -216,19 +235,16 @@ bool Li_init( struct Lzip_index * const li, const int infd,
if( seek_read( infd, trailer, Lt_size, pos - Lt_size ) != Lt_size ) if( seek_read( infd, trailer, Lt_size, pos - Lt_size ) != Lt_size )
{ Li_set_errno_error( li, "Error reading member trailer: " ); break; } { Li_set_errno_error( li, "Error reading member trailer: " ); break; }
member_size = Lt_get_member_size( trailer ); member_size = Lt_get_member_size( trailer );
if( member_size > (unsigned long long)pos || !Lt_verify_consistency( trailer ) ) if( member_size > pos || !Lt_verify_consistency( trailer ) )
{ { /* bad trailer */
if( li->members <= 0 ) if( li->members <= 0 )
{ if( Li_skip_trailing_data( li, infd, &pos, ignore_trailing, { if( Li_skip_trailing_data( li, infd, &pos, ignore_trailing,
loose_trailing ) ) continue; else return false; } loose_trailing ) ) continue; else return false; }
Li_set_num_error( li, "Bad trailer at pos ", pos - Lt_size ); Li_set_num_error( li, "Bad trailer at pos ", pos - Lt_size );
break; break;
} }
if( seek_read( infd, header, Lh_size, pos - member_size ) != Lh_size ) if( !Li_read_header( li, infd, header, pos - member_size ) ) break;
{ Li_set_errno_error( li, "Error reading member header: " ); break; } if( !Lh_verify( header ) ) /* bad header */
dictionary_size = Lh_get_dictionary_size( header );
if( !Lh_verify_magic( header ) || !Lh_verify_version( header ) ||
!isvalid_ds( dictionary_size ) )
{ {
if( li->members <= 0 ) if( li->members <= 0 )
{ if( Li_skip_trailing_data( li, infd, &pos, ignore_trailing, { if( Li_skip_trailing_data( li, infd, &pos, ignore_trailing,
@ -237,6 +253,9 @@ bool Li_init( struct Lzip_index * const li, const int infd,
break; break;
} }
pos -= member_size; pos -= member_size;
dictionary_size = Lh_get_dictionary_size( header );
if( li->dictionary_size < dictionary_size )
li->dictionary_size = dictionary_size;
if( !push_back_member( li, 0, Lt_get_data_size( trailer ), pos, if( !push_back_member( li, 0, Lt_get_data_size( trailer ), pos,
member_size, dictionary_size ) ) member_size, dictionary_size ) )
return false; return false;

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -54,6 +54,7 @@ struct Lzip_index
long members; long members;
int error_size; int error_size;
int retval; int retval;
unsigned dictionary_size; /* largest dictionary size in the file */
}; };
bool Li_init( struct Lzip_index * const li, const int infd, bool Li_init( struct Lzip_index * const li, const int infd,

261
main.c
View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for the lzip format /* Lunzip - Decompressor for the lzip format
Copyright (C) 2010-2019 Antonio Diaz Diaz. Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -70,11 +70,11 @@
int verbosity = 0; int verbosity = 0;
const char * const program_name = "lunzip"; static const char * const program_name = "lunzip";
const char * const program_year = "2019"; static const char * const program_year = "2021";
const char * invocation_name = 0; static const char * invocation_name = "lunzip"; /* default value */
const struct { const char * from; const char * to; } known_extensions[] = { static const struct { const char * from; const char * to; } known_extensions[] = {
{ ".lz", "" }, { ".lz", "" },
{ ".tlz", ".tar" }, { ".tlz", ".tar" },
{ 0, 0 } }; { 0, 0 } };
@ -83,23 +83,23 @@ enum Mode { m_compress, m_decompress, m_list, m_test };
/* Variables used in signal handler context. /* Variables used in signal handler context.
They are not declared volatile because the handler never returns. */ They are not declared volatile because the handler never returns. */
char * output_filename = 0; static char * output_filename = 0;
int outfd = -1; static int outfd = -1;
bool delete_output_on_interrupt = false; static bool delete_output_on_interrupt = false;
static void show_help( void ) static void show_help( void )
{ {
printf( "Lunzip is a decompressor for the lzip format. It is written in C and its\n" printf( "Lunzip is a decompressor for the lzip format written in C. Its small size\n"
"small size makes it well suited for embedded devices or software\n" "makes it well suited for embedded devices or software installers that need\n"
"installers that need to decompress files but don't need compression\n" "to decompress files but don't need compression capabilities. Lunzip is fully\n"
"capabilities. Lunzip is fully compatible with lzip-1.4 or newer.\n" "compatible with lzip 1.4 or newer.\n"
"\nLunzip provides a 'low memory' mode able to decompress any file using as\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" "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" "compress the file. To activate it, specify the size of the output buffer\n"
"with the '--buffer-size' option and lunzip will use the decompressed\n" "with the option --buffer-size and lunzip will use the decompressed\n"
"file as dictionary for distances beyond the buffer size. Of course, the\n" "file as dictionary for distances beyond the buffer size. Of course, the\n"
"smaller the buffer size used in relation to the dictionary size, the\n" "larger the difference between the buffer size and the dictionary size, the\n"
"more accesses to disk are needed and the slower the decompression is.\n" "more accesses to disk are needed and the slower the decompression is.\n"
"This 'low memory' mode only works when decompressing to a regular file\n" "This 'low memory' mode only works when decompressing to a regular file\n"
"and is intended for systems without enough memory (RAM + swap) to keep\n" "and is intended for systems without enough memory (RAM + swap) to keep\n"
@ -114,22 +114,29 @@ static void show_help( void )
" -f, --force overwrite existing output files\n" " -f, --force overwrite existing output files\n"
" -k, --keep keep (don't delete) input files\n" " -k, --keep keep (don't delete) input files\n"
" -l, --list print (un)compressed file sizes\n" " -l, --list print (un)compressed file sizes\n"
" -o, --output=<file> if reading standard input, write to <file>\n" " -o, --output=<file> write to <file>, keep input files\n"
" -q, --quiet suppress all messages\n" " -q, --quiet suppress all messages\n"
" -t, --test test compressed file integrity\n" " -t, --test test compressed file integrity\n"
" -u, --buffer-size=<bytes> set output buffer size in bytes\n" " -u, --buffer-size=<bytes> set output buffer size in bytes\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n" " -v, --verbose be verbose (a 2nd -v gives more)\n"
" --loose-trailing allow trailing data seeming corrupt header\n" " --loose-trailing allow trailing data seeming corrupt header\n"
"If no file names are given, or if a file is '-', lunzip decompresses\n" "\nIf no file names are given, or if a file is '-', lunzip decompresses\n"
"from standard input to standard output.\n" "from standard input to standard output.\n"
"Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n"
"Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n"
"Buffer sizes 12 to 29 are interpreted as powers of two, meaning 2^12\n" "Buffer sizes 12 to 29 are interpreted as powers of two, meaning 2^12\n"
"to 2^29 bytes.\n" "to 2^29 bytes.\n"
"\nTo extract all the files from archive 'foo.tar.lz', use the commands\n"
"'tar -xf foo.tar.lz' or 'lunzip -cd foo.tar.lz | tar -xf -'.\n"
"\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n"
"not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n" "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n"
"invalid input file, 3 for an internal consistency error (eg, bug) which\n" "invalid input file, 3 for an internal consistency error (eg, bug) which\n"
"caused lunzip to panic.\n" "caused lunzip to panic.\n"
"\nThe ideas embodied in lunzip are due to (at least) the following people:\n"
"Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for the\n"
"definition of Markov chains), G.N.N. Martin (for the definition of range\n"
"encoding), Igor Pavlov (for putting all the above together in LZMA), and\n"
"Julian Seward (for bzip2's CLI).\n"
"\nReport bugs to lzip-bug@nongnu.org\n" "\nReport bugs to lzip-bug@nongnu.org\n"
"Lunzip home page: http://www.nongnu.org/lzip/lunzip.html\n" ); "Lunzip home page: http://www.nongnu.org/lzip/lunzip.html\n" );
} }
@ -150,15 +157,64 @@ void * resize_buffer( void * buf, const unsigned min_size )
{ {
if( buf ) buf = realloc( buf, min_size ); if( buf ) buf = realloc( buf, min_size );
else buf = malloc( min_size ); else buf = malloc( min_size );
if( !buf ) if( !buf ) { show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
{
show_error( "Not enough memory.", 0, false );
cleanup_and_fail( 1 );
}
return buf; return buf;
} }
struct Pretty_print
{
const char * name;
char * padded_name;
const char * stdin_name;
unsigned longest_name;
bool first_post;
};
static void Pp_init( struct Pretty_print * const pp,
const char * const filenames[], const int num_filenames )
{
unsigned stdin_name_len;
int i;
pp->name = 0;
pp->padded_name = 0;
pp->stdin_name = "(stdin)";
pp->longest_name = 0;
pp->first_post = false;
if( verbosity <= 0 ) return;
stdin_name_len = strlen( pp->stdin_name );
for( i = 0; i < num_filenames; ++i )
{
const char * const s = filenames[i];
const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s );
if( pp->longest_name < len ) pp->longest_name = len;
}
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 )
{
unsigned name_len, padded_name_len, i = 0;
if( filename && filename[0] && strcmp( filename, "-" ) != 0 )
pp->name = filename;
else pp->name = pp->stdin_name;
name_len = strlen( pp->name );
padded_name_len = max( name_len, pp->longest_name ) + 4;
pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 );
while( i < 2 ) pp->padded_name[i++] = ' ';
while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; }
pp->padded_name[i++] = ':';
while( i < padded_name_len ) pp->padded_name[i++] = ' ';
pp->padded_name[i] = 0;
pp->first_post = true;
}
static void Pp_reset( struct 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( struct Pretty_print * const pp, const char * const msg )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
@ -204,7 +260,7 @@ const char * format_ds( const unsigned dictionary_size )
void show_header( const unsigned dictionary_size ) void show_header( const unsigned dictionary_size )
{ {
fprintf( stderr, "dictionary %s, ", format_ds( dictionary_size ) ); fprintf( stderr, "dict %s, ", format_ds( dictionary_size ) );
} }
@ -271,7 +327,7 @@ static int get_dict_size( const char * const arg )
} }
void set_mode( enum Mode * const program_modep, const enum Mode new_mode ) static void set_mode( enum Mode * const program_modep, const enum Mode new_mode )
{ {
if( *program_modep != m_compress && *program_modep != new_mode ) if( *program_modep != m_compress && *program_modep != new_mode )
{ {
@ -324,7 +380,7 @@ static void set_d_outname( const char * const name, const int eindex )
int open_instream( const char * const name, struct stat * const in_statsp, int open_instream( const char * const name, struct stat * const in_statsp,
const bool no_ofile, const bool reg_only ) const bool one_to_one, const bool reg_only )
{ {
int infd = open( name, O_RDONLY | O_BINARY ); int infd = open( name, O_RDONLY | O_BINARY );
if( infd < 0 ) if( infd < 0 )
@ -336,13 +392,12 @@ int open_instream( const char * const name, struct stat * const in_statsp,
const bool can_read = ( i == 0 && !reg_only && const bool can_read = ( i == 0 && !reg_only &&
( S_ISBLK( mode ) || S_ISCHR( mode ) || ( 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 || !no_ofile ) ) ) if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
program_name, name, program_name, name, ( can_read && one_to_one ) ?
( can_read && !no_ofile ) ? ",\n and neither '-c' nor '-o' were specified" : "" );
",\n and '--stdout' was not specified" : "" );
close( infd ); close( infd );
infd = -1; infd = -1;
} }
@ -351,11 +406,11 @@ int open_instream( const char * const name, struct stat * const in_statsp,
} }
static bool open_outstream( const bool force, const bool from_stdin ) static bool open_outstream( const bool force, const bool protect )
{ {
const mode_t usr_rw = S_IRUSR | S_IWUSR; const mode_t usr_rw = S_IRUSR | S_IWUSR;
const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
const mode_t outfd_mode = from_stdin ? all_rw : usr_rw; const mode_t outfd_mode = protect ? usr_rw : all_rw;
int flags = O_APPEND | O_CREAT | O_RDWR | O_BINARY; int flags = O_APPEND | O_CREAT | O_RDWR | O_BINARY;
if( force ) flags |= O_TRUNC; else flags |= O_EXCL; if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
@ -399,7 +454,7 @@ void cleanup_and_fail( const int retval )
} }
void signal_handler( int sig ) static void signal_handler( int sig )
{ {
if( sig ) {} /* keep compiler happy */ if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false ); show_error( "Control-C or similar caught, quitting.", 0, false );
@ -407,7 +462,20 @@ void signal_handler( int sig )
} }
/* Set permissions, owner and times. */ static bool check_tty_in( const char * const input_filename, const int infd,
const enum Mode program_mode, int * const retval )
{
if( isatty( infd ) ) /* for example /dev/tty */
{ show_file_error( input_filename,
"I won't read compressed data from a terminal.", 0 );
close( infd ); set_retval( retval, 1 );
if( program_mode != m_test ) cleanup_and_fail( *retval );
return false; }
return true;
}
/* Set permissions, owner, and times. */
static void close_and_set_permissions( const struct stat * const in_statsp ) static void close_and_set_permissions( const struct stat * const in_statsp )
{ {
bool warning = false; bool warning = false;
@ -487,10 +555,7 @@ static int decompress( const unsigned long long cfile_size, const int infd,
int retval = 0; int retval = 0;
bool first_member; bool first_member;
if( !Rd_init( &rdec, infd ) ) if( !Rd_init( &rdec, infd ) )
{ { show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
show_error( "Not enough memory.", 0, false );
cleanup_and_fail( 1 );
}
for( first_member = true; ; first_member = false ) for( first_member = true; ; first_member = false )
{ {
@ -589,7 +654,7 @@ void show_file_error( const char * const filename, const char * const msg,
} }
void internal_error( const char * const msg ) static void internal_error( const char * const msg )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
@ -631,7 +696,9 @@ void show_dprogress( const unsigned long long cfile_size,
int main( const int argc, const char * const argv[] ) int main( const int argc, const char * const argv[] )
{ {
const char * default_output_filename = ""; const char * default_output_filename = "";
const char ** filenames = 0; static struct Arg_parser parser; /* static because valgrind complains */
static struct Pretty_print pp; /* and memory management in C sucks */
static const char ** filenames = 0;
int num_filenames = 0; int num_filenames = 0;
unsigned buffer_size = max_dictionary_size; unsigned buffer_size = max_dictionary_size;
enum Mode program_mode = m_compress; enum Mode program_mode = m_compress;
@ -646,7 +713,6 @@ int main( const int argc, const char * const argv[] )
bool loose_trailing = false; bool loose_trailing = false;
bool stdin_used = false; bool stdin_used = false;
bool to_stdout = false; bool to_stdout = false;
struct Pretty_print pp;
enum { opt_lt = 256 }; enum { opt_lt = 256 };
const struct ap_Option options[] = const struct ap_Option options[] =
@ -668,13 +734,11 @@ int main( const int argc, const char * const argv[] )
{ opt_lt, "loose-trailing", ap_no }, { opt_lt, "loose-trailing", ap_no },
{ 0 , 0, ap_no } }; { 0 , 0, ap_no } };
struct Arg_parser parser; if( argc > 0 ) invocation_name = argv[0];
invocation_name = argv[0];
CRC32_init(); CRC32_init();
if( !ap_init( &parser, argc, argv, options, 0 ) ) if( !ap_init( &parser, argc, argv, options, 0 ) )
{ show_error( "Not enough memory.", 0, false ); return 1; } { show_error( mem_msg, 0, false ); return 1; }
if( ap_error( &parser ) ) /* bad option */ if( ap_error( &parser ) ) /* bad option */
{ show_error( ap_error( &parser ), 0, true ); return 1; } { show_error( ap_error( &parser ), 0, true ); return 1; }
@ -693,7 +757,8 @@ int main( const int argc, const char * const argv[] )
case 'k': keep_input_files = true; break; case 'k': keep_input_files = true; break;
case 'l': set_mode( &program_mode, m_list ); break; case 'l': set_mode( &program_mode, m_list ); break;
case 'n': break; case 'n': break;
case 'o': default_output_filename = arg; break; case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true;
else { default_output_filename = arg; } break;
case 'q': verbosity = -1; break; case 'q': verbosity = -1; break;
case 't': set_mode( &program_mode, m_test ); break; case 't': set_mode( &program_mode, m_test ); break;
case 'u': buffer_size = get_dict_size( arg ); break; case 'u': buffer_size = get_dict_size( arg ); break;
@ -722,17 +787,17 @@ int main( const int argc, const char * const argv[] )
if( program_mode == m_list ) if( program_mode == m_list )
return list_files( filenames, num_filenames, ignore_trailing, loose_trailing ); return list_files( filenames, num_filenames, ignore_trailing, loose_trailing );
if( program_mode == m_test ) if( program_mode == m_compress )
outfd = -1;
else if( program_mode == m_compress )
program_mode = m_decompress; /* default mode */ program_mode = m_decompress; /* default mode */
if( program_mode == m_test ) to_stdout = false; /* apply overrides */
if( program_mode == m_test || to_stdout ) default_output_filename = "";
if( buffer_size < max_dictionary_size ) if( buffer_size < max_dictionary_size )
{ {
bool from_stdin = false; bool from_stdin = false;
if( to_stdout || program_mode == m_test ) if( to_stdout || program_mode == m_test )
{ show_error( "'--buffer-size' is incompatible with '--stdout' and '--test'.", 0, false ); { show_error( "'--buffer-size' is incompatible with '--stdout' and '--test'.",
return 1; } 0, false ); return 1; }
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 )
{ from_stdin = true; break; } { from_stdin = true; break; }
@ -741,13 +806,19 @@ int main( const int argc, const char * const argv[] )
" with a reduced buffer size.", 0, false ); return 1; } " with a reduced buffer size.", 0, false ); return 1; }
} }
if( !to_stdout && program_mode != m_test && output_filename = resize_buffer( output_filename, 1 );
( filenames_given || default_output_filename[0] ) ) output_filename[0] = 0;
if( to_stdout && program_mode != m_test ) outfd = STDOUT_FILENO;
else outfd = -1;
const bool to_file = !to_stdout && program_mode != m_test &&
default_output_filename[0];
if( !to_stdout && program_mode != m_test && ( filenames_given || to_file ) )
set_signals( signal_handler ); set_signals( signal_handler );
Pp_init( &pp, filenames, num_filenames ); Pp_init( &pp, filenames, num_filenames );
output_filename = resize_buffer( output_filename, 1 ); const bool one_to_one = !to_stdout && program_mode != m_test && !to_file;
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
{ {
unsigned long long cfile_size; unsigned long long cfile_size;
@ -756,60 +827,35 @@ int main( const int argc, const char * const argv[] )
int tmp; int tmp;
struct stat in_stats; struct stat in_stats;
const struct stat * in_statsp; const struct stat * in_statsp;
output_filename[0] = 0;
if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) Pp_set_name( &pp, filenames[i] );
if( strcmp( filenames[i], "-" ) == 0 )
{ {
if( stdin_used ) continue; else stdin_used = true; if( stdin_used ) continue; else stdin_used = true;
infd = STDIN_FILENO; infd = STDIN_FILENO;
if( program_mode != m_test ) if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue;
{ if( one_to_one ) { outfd = STDOUT_FILENO; output_filename[0] = 0; }
if( to_stdout || !default_output_filename[0] )
outfd = STDOUT_FILENO;
else
{
output_filename = resize_buffer( output_filename,
strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename );
if( !open_outstream( force, true ) )
{
if( retval < 1 ) retval = 1;
close( infd );
continue;
}
}
}
} }
else else
{ {
input_filename = filenames[i]; input_filename = filenames[i];
infd = open_instream( input_filename, &in_stats, infd = open_instream( input_filename, &in_stats, one_to_one, false );
to_stdout || program_mode == m_test, false ); if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue;
if( program_mode != m_test ) if( one_to_one ) /* open outfd after verifying infd */
{
if( to_stdout ) outfd = STDOUT_FILENO;
else
{ {
set_d_outname( input_filename, extension_index( input_filename ) ); set_d_outname( input_filename, extension_index( input_filename ) );
if( !open_outstream( force, false ) ) if( !open_outstream( force, true ) )
{ { close( infd ); set_retval( &retval, 1 ); continue; }
if( retval < 1 ) retval = 1;
close( infd );
continue;
}
}
} }
} }
Pp_set_name( &pp, input_filename ); if( to_file && outfd < 0 ) /* open outfd after verifying infd */
if( isatty( infd ) )
{ {
show_file_error( pp.name, output_filename = resize_buffer( output_filename,
"I won't read compressed data from a terminal.", 0 ); strlen( default_output_filename ) + 1 );
if( retval < 1 ) retval = 1; strcpy( output_filename, default_output_filename );
if( program_mode == m_test ) { close( infd ); continue; } if( !open_outstream( force, false ) ) return 1;
cleanup_and_fail( retval );
} }
if( delete_output_on_interrupt && buffer_size < max_dictionary_size ) if( delete_output_on_interrupt && buffer_size < max_dictionary_size )
@ -821,39 +867,34 @@ int main( const int argc, const char * const argv[] )
fprintf( stderr, "%s: Output file '%s' is not a regular file,\n" fprintf( stderr, "%s: Output file '%s' is not a regular file,\n"
" and 'low memory' mode has been requested.\n", " and 'low memory' mode has been requested.\n",
program_name, output_filename ); program_name, output_filename );
if( retval < 1 ) retval = 1; set_retval( &retval, 1 );
cleanup_and_fail( retval ); return retval; /* don't try to delete a non-regular file */
} }
} }
in_statsp = input_filename[0] ? &in_stats : 0; in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0;
cfile_size = ( in_statsp && S_ISREG( in_statsp->st_mode ) ) ? cfile_size = ( input_filename[0] && S_ISREG( in_stats.st_mode ) ) ?
( in_statsp->st_size + 99 ) / 100 : 0; ( in_stats.st_size + 99 ) / 100 : 0;
tmp = decompress( cfile_size, infd, &pp, buffer_size, ignore_trailing, tmp = decompress( cfile_size, infd, &pp, buffer_size, ignore_trailing,
loose_trailing, program_mode == m_test ); loose_trailing, program_mode == m_test );
if( close( infd ) != 0 ) if( close( infd ) != 0 )
{ { show_file_error( pp.name, "Error closing input file", errno );
show_error( input_filename[0] ? "Error closing input file" : set_retval( &tmp, 1 ); }
"Error closing stdin", errno, false ); set_retval( &retval, tmp );
if( tmp < 1 ) tmp = 1;
}
if( tmp > retval ) retval = tmp;
if( tmp ) if( tmp )
{ if( program_mode != m_test ) cleanup_and_fail( retval ); { if( program_mode != m_test ) cleanup_and_fail( retval );
else ++failed_tests; } else ++failed_tests; }
if( delete_output_on_interrupt ) if( delete_output_on_interrupt && one_to_one )
close_and_set_permissions( in_statsp ); close_and_set_permissions( in_statsp );
if( input_filename[0] ) if( input_filename[0] && !keep_input_files && one_to_one )
{
if( !keep_input_files && !to_stdout && program_mode != m_test )
remove( input_filename ); remove( input_filename );
} }
} if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); /* -o */
if( outfd >= 0 && close( outfd ) != 0 ) else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */
{ {
show_error( "Error closing stdout", errno, false ); show_error( "Error closing stdout", errno, false );
if( retval < 1 ) retval = 1; set_retval( &retval, 1 );
} }
if( failed_tests > 0 && verbosity >= 1 && num_filenames > 1 ) if( failed_tests > 0 && verbosity >= 1 && num_filenames > 1 )
fprintf( stderr, "%s: warning: %d %s failed the test.\n", fprintf( stderr, "%s: warning: %d %s failed the test.\n",

View file

@ -1,9 +1,9 @@
#! /bin/sh #! /bin/sh
# check script for Lunzip - Decompressor for the lzip format # check script for Lunzip - Decompressor for the lzip format
# Copyright (C) 2010-2019 Antonio Diaz Diaz. # Copyright (C) 2010-2021 Antonio Diaz Diaz.
# #
# This script is free software: you have unlimited permission # This script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute, and modify it.
LC_ALL=C LC_ALL=C
export LC_ALL export LC_ALL
@ -30,6 +30,8 @@ cd "${objdir}"/tmp || framework_failure
cat "${testdir}"/test.txt > in || framework_failure cat "${testdir}"/test.txt > in || framework_failure
in_lz="${testdir}"/test.txt.lz in_lz="${testdir}"/test.txt.lz
in_em="${testdir}"/test_em.txt.lz
fox_lz="${testdir}"/fox.lz
fail=0 fail=0
test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; }
@ -37,7 +39,7 @@ printf "testing lunzip-%s..." "$2"
cat "${in_lz}" > uin.lz || framework_failure cat "${in_lz}" > uin.lz || framework_failure
for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do
"${LZIP}" -dfkqu $i uin.lz "${LZIP}" -dfkq -u $i uin.lz
[ $? = 1 ] || test_failed $LINENO $i [ $? = 1 ] || test_failed $LINENO $i
[ ! -e uin ] || test_failed $LINENO $i [ ! -e uin ] || test_failed $LINENO $i
done done
@ -54,6 +56,11 @@ rm -f uin.lz || framework_failure
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
"${LZIP}" -dq -o in < "${in_lz}" "${LZIP}" -dq -o in < "${in_lz}"
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" -dq -o in "${in_lz}"
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -dq -o out nx_file.lz
[ $? = 1 ] || test_failed $LINENO
[ ! -e out ] || test_failed $LINENO
# these are for code coverage # these are for code coverage
"${LZIP}" -lt "${in_lz}" 2> /dev/null "${LZIP}" -lt "${in_lz}" 2> /dev/null
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
@ -61,7 +68,9 @@ rm -f uin.lz || framework_failure
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null "${LZIP}" -cdt "${in_lz}" > out 2> /dev/null
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" -t -- nx_file 2> /dev/null "${LZIP}" -t -- nx_file.lz 2> /dev/null
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -t "" < /dev/null 2> /dev/null
[ $? = 1 ] || test_failed $LINENO [ $? = 1 ] || test_failed $LINENO
"${LZIP}" --help > /dev/null || test_failed $LINENO "${LZIP}" --help > /dev/null || test_failed $LINENO
"${LZIP}" -n1 -V > /dev/null || test_failed $LINENO "${LZIP}" -n1 -V > /dev/null || test_failed $LINENO
@ -85,12 +94,26 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null
printf "\ntesting decompression..." printf "\ntesting decompression..."
"${LZIP}" -lq "${in_lz}" || test_failed $LINENO for i in "${in_lz}" "${in_em}" ; do
"${LZIP}" -t "${in_lz}" || test_failed $LINENO "${LZIP}" -lq "$i" || test_failed $LINENO "$i"
"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO "${LZIP}" -t "$i" || test_failed $LINENO "$i"
cmp in copy || test_failed $LINENO "${LZIP}" -d "$i" -o copy || test_failed $LINENO "$i"
cmp in copy || test_failed $LINENO "$i"
"${LZIP}" -cd "$i" > copy || test_failed $LINENO "$i"
cmp in copy || test_failed $LINENO "$i"
"${LZIP}" -d "$i" -o - > copy || test_failed $LINENO "$i"
cmp in copy || test_failed $LINENO "$i"
"${LZIP}" -d < "$i" > copy || test_failed $LINENO "$i"
cmp in copy || test_failed $LINENO "$i"
rm -f copy || framework_failure rm -f copy || framework_failure
done
lines=$("${LZIP}" -tvv "${in_em}" 2>&1 | wc -l) || test_failed $LINENO
[ "${lines}" -eq 8 ] || test_failed $LINENO "${lines}"
lines=$("${LZIP}" -lvv "${in_em}" | wc -l) || test_failed $LINENO
[ "${lines}" -eq 11 ] || test_failed $LINENO "${lines}"
cat "${in_lz}" > copy.lz || framework_failure cat "${in_lz}" > copy.lz || framework_failure
"${LZIP}" -dk copy.lz || test_failed $LINENO "${LZIP}" -dk copy.lz || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
@ -102,12 +125,20 @@ printf "to be overwritten" > copy || framework_failure
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
printf "to be overwritten" > copy || framework_failure printf "to be overwritten" > copy || framework_failure
"${LZIP}" -d -o copy < "${in_lz}" 2> /dev/null
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO "${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
rm -f out copy || framework_failure
"${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO
cmp in ./- || test_failed $LINENO
rm -f ./- || framework_failure
"${LZIP}" -d -o ./- < "${in_lz}" || test_failed $LINENO
cmp in ./- || test_failed $LINENO
rm -f ./- || framework_failure
rm -f copy || framework_failure
cat "${in_lz}" > anyothername || framework_failure cat "${in_lz}" > anyothername || framework_failure
"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null || "${LZIP}" -dv - anyothername - < "${in_lz}" > copy 2> /dev/null ||
test_failed $LINENO test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
cmp in anyothername.out || test_failed $LINENO cmp in anyothername.out || test_failed $LINENO
@ -148,16 +179,19 @@ done
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
cat in in > in2 || framework_failure cat in in > in2 || framework_failure
cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure "${LZIP}" -lq "${in_lz}" "${in_lz}" || test_failed $LINENO
"${LZIP}" -lq in2.lz || test_failed $LINENO "${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO
"${LZIP}" -t in2.lz || test_failed $LINENO "${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > copy2 || test_failed $LINENO
"${LZIP}" -cd in2.lz > copy2 || test_failed $LINENO [ ! -e out ] || test_failed $LINENO # override -o
cmp in2 copy2 || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO
rm -f copy2 || framework_failure
"${LZIP}" -d "${in_lz}" "${in_lz}" -o copy2 || test_failed $LINENO
cmp in2 copy2 || test_failed $LINENO
rm -f copy2 || framework_failure
cat in2.lz > copy2.lz || framework_failure cat "${in_lz}" "${in_lz}" > copy2.lz || framework_failure
printf "\ngarbage" >> copy2.lz || framework_failure printf "\ngarbage" >> copy2.lz || framework_failure
"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO "${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO
rm -f copy2 || framework_failure
"${LZIP}" -alq copy2.lz "${LZIP}" -alq copy2.lz
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
"${LZIP}" -atq copy2.lz "${LZIP}" -atq copy2.lz
@ -173,13 +207,20 @@ rm -f copy2 || framework_failure
printf "to be overwritten" > copy2 || framework_failure printf "to be overwritten" > copy2 || framework_failure
"${LZIP}" -df copy2.lz || test_failed $LINENO "${LZIP}" -df copy2.lz || test_failed $LINENO
cmp in2 copy2 || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO
rm -f in2 copy2 || framework_failure
for i in 12 5120 6Ki 29 512KiB ; do for i in 12 5120 6Ki 29 512KiB ; do
printf "to be overwritten" > copy || framework_failure printf "to be overwritten" > copy || framework_failure
"${LZIP}" -df -u$i -o copy < "${in_lz}" || test_failed $LINENO $i "${LZIP}" -df -u$i -o copy < "${in_lz}" || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i
rm -f copy || framework_failure
"${LZIP}" -d -u$i -o copy "${in_lz}" || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i
rm -f copy2 || framework_failure
"${LZIP}" -d -u$i -o copy2 "${in_lz}" "${in_lz}" ||
test_failed $LINENO $i
cmp in2 copy2 || test_failed $LINENO $i
done done
rm -f in2 copy copy2 || framework_failure
printf "\ntesting bad input..." printf "\ntesting bad input..."
@ -238,6 +279,21 @@ else
fi fi
rm -f int.lz || framework_failure rm -f int.lz || framework_failure
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
[ $? = 2 ] || test_failed $LINENO $i
done
"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO
for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do
"${LZIP}" -cdq "${testdir}"/$i > out
[ $? = 2 ] || test_failed $LINENO $i
cmp fox out || test_failed $LINENO $i
done
rm -f fox out || framework_failure
cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure
cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure
if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null &&
[ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then [ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then
@ -264,13 +320,21 @@ printf "g" >> ingin.lz || framework_failure
cat "${in_lz}" >> ingin.lz || framework_failure cat "${in_lz}" >> ingin.lz || framework_failure
"${LZIP}" -lq ingin.lz "${LZIP}" -lq ingin.lz
[ $? = 2 ] || test_failed $LINENO [ $? = 2 ] || test_failed $LINENO
"${LZIP}" -atq ingin.lz
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -atq < ingin.lz
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -acdq ingin.lz > out
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -adq < ingin.lz > out
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -t ingin.lz || test_failed $LINENO "${LZIP}" -t ingin.lz || test_failed $LINENO
"${LZIP}" -t < ingin.lz || test_failed $LINENO
"${LZIP}" -cd ingin.lz > copy || test_failed $LINENO "${LZIP}" -cd ingin.lz > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
"${LZIP}" -t < ingin.lz || test_failed $LINENO
"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO "${LZIP}" -d < ingin.lz > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO cmp in copy || test_failed $LINENO
rm -f copy ingin.lz || framework_failure rm -f copy ingin.lz out || framework_failure
echo echo
if [ ${fail} = 0 ] ; then if [ ${fail} = 0 ] ; then

BIN
testsuite/fox.lz Normal file

Binary file not shown.

BIN
testsuite/fox_bcrc.lz Normal file

Binary file not shown.

BIN
testsuite/fox_crc0.lz Normal file

Binary file not shown.

BIN
testsuite/fox_das46.lz Normal file

Binary file not shown.

BIN
testsuite/fox_de20.lz Normal file

Binary file not shown.

BIN
testsuite/fox_mes81.lz Normal file

Binary file not shown.

BIN
testsuite/fox_s11.lz Normal file

Binary file not shown.

BIN
testsuite/fox_v2.lz Normal file

Binary file not shown.

BIN
testsuite/test_em.txt.lz Normal file

Binary file not shown.