1
0
Fork 0

Merging upstream version 1.12.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 20:49:14 +01:00
parent 819b7ffe8f
commit 93292ac251
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
35 changed files with 1973 additions and 1678 deletions

View file

@ -1,7 +1,7 @@
Clzip was written by Antonio Diaz Diaz.
The ideas embodied in clzip 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).
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).

View file

@ -1,31 +1,46 @@
2021-01-04 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.
Make '-c' and '-o' check whether the output is a terminal only once.
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 manual, '--help', and man page.
* clzip.texi (Introduction): Mention plzip and tarlz as alternatives.
* clzip.texi: Several fixes and improvements.
* testsuite: Add 9 new test files.
2019-01-03 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.11 released.
* File_* renamed to Lzip_*.
* Rename File_* to Lzip_*.
* lzip.h (Lzip_trailer): New function 'Lt_verify_consistency'.
* lzip_index.c: Detect some kinds of corrupt trailers.
* main.c (main): Check return value of close( infd ).
* main.c: Compile on DOS with DJGPP.
* clzip.texi: Improved descriptions of '-0..-9', '-m' and '-s'.
* clzip.texi: Improve descriptions of '-0..-9', '-m', and '-s'.
* configure: Accept appending to CFLAGS, 'CFLAGS+=OPTIONS'.
* INSTALL: Document use of CFLAGS+='-D __USE_MINGW_ANSI_STDIO'.
2018-02-06 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.10 released.
* Added new option '--loose-trailing'.
* Improved corrupt header detection to HD=3.
* New option '--loose-trailing'.
* Improve corrupt header detection to HD=3.
* main.c: Show corrupt or truncated header in multimember file.
* main.c (main): Option '-S, --volume-size' now keeps input files.
* encoder_base.*: Adjust dictionary size for each member.
* 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 (de)compression only if stderr is a terminal.
* main.c: Show final diagnostic when testing multiple files.
* main.c: Do not add a second .lz extension to the arg of -o.
* decoder.c (LZd_verify_trailer): Show stored sizes also in hex.
Show dictionary size at verbosity level 4 (-vvvv).
* lzip.texi: Added chapter 'Output'.
* clzip.texi: New chapter 'Meaning of clzip's output'.
2017-04-13 Antonio Diaz Diaz <antonio@gnu.org>
@ -38,19 +53,19 @@
* main.c: Continue testing if any input file is a terminal.
* main.c: Show trailing data in both hexadecimal and ASCII.
* lzip_index.c: Improve detection of bad dict and trailing data.
* lzip.h: Unified messages for bad magic, trailing data, etc.
* clzip.texi: Added missing chapters from lzip.texi.
* lzip.h: Unify messages for bad magic, trailing data, etc.
* clzip.texi: Add missing chapters from lzip.texi.
2016-05-13 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.8 released.
* Added new option '-a, --trailing-error'.
* New option '-a, --trailing-error'.
* main.c (decompress): Print up to 6 bytes of trailing data
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): Don't use stdin more than once.
* clzip.texi: Added chapter 'Trailing data'.
* clzip.texi: New chapter 'Trailing data'.
* configure: Avoid warning on some shells when testing for gcc.
* Makefile.in: Detect the existence of install-info.
* check.sh: A POSIX shell is required to run the tests.
@ -59,16 +74,16 @@
2015-07-07 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.7 released.
* Ported fast encoder and option '-0' from lzip.
* Makefile.in: Added new targets 'install*-compress'.
* Port fast encoder and option '-0' from lzip.
* Makefile.in: New targets 'install*-compress'.
2014-08-28 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.6 released.
* Compression ratio of option '-9' has been slightly increased.
* main.c (close_and_set_permissions): Behave like 'cp -p'.
* clzip.texinfo: Renamed to clzip.texi.
* License changed to GPL version 2 or later.
* clzip.texinfo: Rename to clzip.texi.
* Change license to GPL version 2 or later.
2013-09-17 Antonio Diaz Diaz <antonio@gnu.org>
@ -85,8 +100,7 @@
* Compression ratio has been slightly increased.
* Compression time has been reduced by 10%.
* Decompression time has been reduced by 8%.
* Makefile.in: Added new target 'install-as-lzip'.
* Makefile.in: Added new target 'install-bin'.
* Makefile.in: New targets 'install-as-lzip' and 'install-bin'.
* main.c: Use 'setmode' instead of '_setmode' on Windows and OS/2.
* main.c: Define 'strtoull' to 'strtoul' on Windows.
@ -98,33 +112,33 @@
* encoder.c (Mf_init): Return false if out of memory instead of
calling cleanup_and_fail.
* Small change in '--help' output and man page.
* Changed quote characters in messages as advised by GNU Standards.
* configure: 'datadir' renamed to 'datarootdir'.
* Change quote characters in messages as advised by GNU Standards.
* configure: Rename 'datadir' to 'datarootdir'.
2011-05-18 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.2 released.
* Added new option '-F, --recompress'.
* New option '-F, --recompress'.
* main.c (decompress): Print only one status line for each
multimember file when only one '-v' is specified.
* encoder.h (Lee_update_prices): Update high length symbol prices
independently of the value of 'pos_state'. This gives better
compression for large values of '--match-length' without being
slower.
* encoder.h encoder.c: Optimize pair price calculations. This
reduces compression time for large values of '--match-length'
by up to 6%.
* encoder.h, encoder.c: Optimize pair price calculations, reducing
compression time for large values of '--match-length' by up to 6%.
2011-01-11 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.1 released.
* Code has been converted to 'C89 + long long' from C99.
* main.c: Fixed warning about fchown return value being ignored.
* main.c: Fix warning about fchown return value being ignored.
* decoder.c: '-tvvvv' now shows compression ratio.
* main.c: Match length limit set by options -1 to -8 has been
reduced to extend range of use towards gzip. Lower numbers now
compress less but faster. (-1 now takes 43% less time for only
20% larger compressed size).
compress less but faster. (-1 now takes 43% less time for only 20%
larger compressed size).
Exit with status 1 if any output file exists and is skipped.
* Compression ratio of option '-9' has been slightly increased.
* main.c (open_instream): Don't show the message
" and '--stdout' was not specified" for directories, etc.
@ -137,8 +151,8 @@
* Translated to C from the C++ source of lzip 1.10.
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,
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.

22
INSTALL
View file

@ -1,7 +1,7 @@
Requirements
------------
You will need a C compiler.
I use gcc 5.3.0 and 4.1.2, but the code should compile with any standards
You will need a C99 compiler. (gcc 3.3.6 or newer is recommended).
I use gcc 6.1.0 and 4.1.2, but the code should compile with any standards
compliant compiler.
Gcc is available at http://gcc.gnu.org.
@ -41,11 +41,11 @@ the main archive.
documentation.
Or type 'make install-compress', which additionally compresses the
info manual and the man page after installation. (Installing
compressed docs may become the default in the future).
info manual and the man page after installation.
(Installing compressed docs may become the default in the future).
You can install only the program, the info manual or the man page by
typing 'make install-bin', 'make install-info' or 'make install-man'
You can install only the program, the info manual, or the man page by
typing 'make install-bin', 'make install-info', or 'make install-man'
respectively.
Instead of 'make install', you can type 'make install-as-lzip' to
@ -56,10 +56,10 @@ the main archive.
Another way
-----------
You can also compile clzip into a separate directory.
To do this, you must use a version of 'make' that supports the 'VPATH'
variable, such as GNU 'make'. 'cd' to the directory where you want the
To do this, you must use a version of 'make' that supports the variable
'VPATH', such as GNU 'make'. 'cd' to the directory where you want the
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.
'configure' recognizes the option '--srcdir=DIR' to control where to
@ -70,7 +70,7 @@ After running 'configure', you can run 'make' and 'make install' as
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,
distribute and modify it.
distribute, and modify it.

View file

@ -75,7 +75,7 @@ install-info :
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"*
$(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info"
-if $(CAN_RUN_INSTALLINFO) ; then \
install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \
install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \
fi
install-info-compress : install-info
@ -100,7 +100,7 @@ uninstall-bin :
uninstall-info :
-if $(CAN_RUN_INSTALLINFO) ; then \
install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \
install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \
fi
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"*
@ -125,7 +125,10 @@ dist : doc
$(DISTNAME)/*.c \
$(DISTNAME)/testsuite/check.sh \
$(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)
lzip -v -9 $(DISTNAME).tar

41
NEWS
View file

@ -1,17 +1,36 @@
Changes in version 1.11:
Changes in version 1.12:
Detection of forbidden combinations of characters in trailing data has been
improved.
Clzip now reports an error if a file name is empty (clzip -t "").
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 (de)compressing from standard input alone. Therefore commands like:
clzip -o foo.lz - bar < foo
must now be split into:
clzip -o foo.lz - < foo
clzip bar
or rewritten as:
clzip - bar < foo > foo.lz
Clzip now compiles on DOS with DJGPP. (Patch from Robert Riebisch).
When using '-c' or '-o', clzip now checks whether the output is a terminal
only once.
The descriptions of '-0..-9', '-m' and '-s' in the manual have been
improved.
Clzip 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
syntax 'CFLAGS+=OPTIONS'.
The words 'decompressed' and 'compressed' have been replaced with the
shorter 'out' and 'in' in the verbose output when decompressing or testing.
It has been documented in INSTALL the use of
CFLAGS+='-D __USE_MINGW_ANSI_STDIO' when compiling on MinGW.
Option '--list' now reports corruption or truncation of the last header in a
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 manual, in the output of '--help', and in the man page.
Plzip and tarlz are mentioned in the manual as alternatives for
multiprocessors.
Several fixes and improvements have been made to the manual.
9 new test files have been added to the testsuite.

127
README
View file

@ -2,56 +2,66 @@ Description
Clzip is a C language version of lzip, fully compatible with lzip 1.4 or
newer. As clzip is written in C, it may be easier to integrate in
applications like package managers, embedded devices, or systems lacking
a C++ compiler.
applications like package managers, embedded devices, or systems lacking a
C++ compiler.
Lzip is a lossless data compressor with a user interface similar to the
one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0)
or compress most files more than bzip2 (lzip -9). Decompression speed is
intermediate between gzip and bzip2. Lzip is better than gzip and bzip2
from a data recovery perspective. Lzip has been designed, written and
tested with great care to replace gzip and bzip2 as the standard
general-purpose compressed format for unix-like systems.
Lzip is a lossless data compressor with a user interface similar to the one
of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov
chain-Algorithm' (LZMA) stream format, chosen to maximize safety and
interoperability. Lzip can compress about as fast as gzip (lzip -0) or
compress most files more than bzip2 (lzip -9). Decompression speed is
intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from
a data recovery perspective. Lzip has been designed, written, and tested
with great care to replace gzip and bzip2 as the standard general-purpose
compressed format for unix-like systems.
For compressing/decompressing large files on multiprocessor machines plzip
can be much faster than lzip at the cost of a slightly reduced compression
ratio.
For creation and manipulation of compressed tar archives tarlz can be more
efficient than using tar and plzip because tarlz is able to keep the
alignment between tar members and lzip members.
The lzip file format is designed for data sharing and long-term archiving,
taking into account both data integrity and decoder availability:
* The lzip format provides very safe integrity checking and some data
recovery means. The lziprecover program can repair bit flip errors
(one of the most common forms of data corruption) in lzip files,
and provides data recovery capabilities, including error-checked
merging of damaged copies of a file.
recovery means. The program lziprecover can repair bit flip errors
(one of the most common forms of data corruption) in lzip files, and
provides data recovery capabilities, including error-checked merging
of damaged copies of a file.
* The lzip format is as simple as possible (but not simpler). The
lzip manual provides the source code of a simple decompressor
along with a detailed explanation of how it works, so that with
the only help of the lzip manual it would be possible for a
digital archaeologist to extract the data from a lzip file long
after quantum computers eventually render LZMA obsolete.
* The lzip format is as simple as possible (but not simpler). The lzip
manual provides the source code of a simple decompressor along with a
detailed explanation of how it works, so that with the only help of the
lzip manual it would be possible for a digital archaeologist to extract
the data from a lzip file long after quantum computers eventually
render LZMA obsolete.
* Additionally the lzip reference implementation is copylefted, which
guarantees that it will remain free forever.
A nice feature of the lzip format is that a corrupt byte is easier to
repair the nearer it is from the beginning of the file. Therefore, with
the help of lziprecover, losing an entire archive just because of a
corrupt byte near the beginning is a thing of the past.
A nice feature of the lzip format is that a corrupt byte is easier to repair
the nearer it is from the beginning of the file. Therefore, with the help of
lziprecover, losing an entire archive just because of a corrupt byte near
the beginning is a thing of the past.
Clzip uses the same well-defined exit status values used by lzip, which
Clzip uses the same well-defined exit status values used by bzip2, which
makes it safer than compressors returning ambiguous warning values (like
gzip) when it is used as a back end for other programs like tar or zutils.
Clzip will automatically use for each file the largest dictionary size
that does not exceed neither the file size nor the limit given. Keep in
mind that the decompression memory requirement is affected at
compression time by the choice of dictionary size limit.
Clzip will automatically use for each file the largest dictionary size that
does not exceed neither the file size nor the limit given. Keep in mind that
the decompression memory requirement is affected at compression time by the
choice of dictionary size limit.
The amount of memory required for compression is about 1 or 2 times the
dictionary size limit (1 if input file size is less than dictionary size
limit, else 2) plus 9 times the dictionary size really used. The option
'-0' is special and only requires about 1.5 MiB at most. The amount of
memory required for decompression is about 46 kB larger than the
dictionary size really used.
limit, else 2) plus 9 times the dictionary size really used. The option '-0'
is special and only requires about 1.5 MiB at most. The amount of memory
required for decompression is about 46 kB larger than the dictionary size
really used.
When compressing, clzip replaces every file given in the command line
with a compressed version of itself, with the name "original_name.lz".
@ -68,37 +78,36 @@ 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
S_ISGID are cleared).
Clzip is able to read from some types of non regular files if the
'--stdout' option is specified.
Clzip is able to read from some types of non-regular files if either the
option '-c' or the option '-o' is specified.
If no file names are specified, clzip compresses (or decompresses) from
standard input to standard output. In this case, clzip will decline to
write compressed output to a terminal, as this would be entirely
incomprehensible and therefore pointless.
standard input to standard output. Clzip will refuse to read compressed data
from a terminal or write compressed data to a terminal, as this would be
entirely incomprehensible and might leave the terminal in an abnormal state.
Clzip will correctly decompress a file which is the concatenation of two or
more compressed files. The result is the concatenation of the corresponding
decompressed files. Integrity testing of concatenated compressed files is
also supported.
Clzip can produce multimember files, and lziprecover can safely recover
the undamaged members in case of file damage. Clzip can also split the
compressed output in volumes of a given size, even when reading from
standard input. This allows the direct creation of multivolume
compressed tar archives.
Clzip can produce multimember files, and lziprecover can safely recover the
undamaged members in case of file damage. Clzip can also split the compressed
output in volumes of a given size, even when reading from standard input.
This allows the direct creation of multivolume compressed tar archives.
Clzip is able to compress and decompress streams of unlimited size by
automatically creating multimember output. The members so created are
large, about 2 PiB each.
automatically creating multimember output. The members so created are large,
about 2 PiB each.
In spite of its name (Lempel-Ziv-Markov chain-Algorithm), LZMA is not a
concrete algorithm; it is more like "any algorithm using the LZMA coding
scheme". For example, the option '-0' of lzip uses the scheme in almost
the simplest way possible; issuing the longest match it can find, or a
literal byte if it can't find a match. Inversely, a much more elaborated
way of finding coding sequences of minimum size than the one currently
used by lzip could be developed, and the resulting sequence could also
be coded using the LZMA coding scheme.
scheme". For example, the option '-0' of lzip uses the scheme in almost the
simplest way possible; issuing the longest match it can find, or a literal
byte if it can't find a match. Inversely, a much more elaborated way of
finding coding sequences of minimum size than the one currently used by lzip
could be developed, and the resulting sequence could also be coded using the
LZMA coding scheme.
Clzip currently implements two variants of the LZMA algorithm; fast
(used by option '-0') and normal (used by all other compression levels).
@ -110,20 +119,20 @@ similar order-0 entropy coder as its last stage) with segregation of
contexts according to what the bits are used for.
The ideas embodied in clzip 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).
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).
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.
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,
distribute and modify it.
distribute, and modify it.
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

View file

@ -1,20 +1,20 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2019 Antonio Diaz Diaz.
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2021 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
that the following conditions are met:
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdlib.h>

View file

@ -1,44 +1,44 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2019 Antonio Diaz Diaz.
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2021 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
that the following conditions are met:
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Arg_parser reads the arguments in 'argv' and creates a number of
option codes, option arguments and non-option arguments.
/* Arg_parser reads the arguments in 'argv' and creates a number of
option codes, option arguments, and non-option arguments.
In case of error, 'ap_error' returns a non-null pointer to an error
message.
In case of error, 'ap_error' returns a non-null pointer to an error
message.
'options' is an array of 'struct ap_Option' terminated by an element
containing a code which is zero. A null name means a short-only
option. A code value outside the unsigned char range means a
long-only option.
'options' is an array of 'struct ap_Option' terminated by an element
containing a code which is zero. A null name means a short-only
option. A code value outside the unsigned char range means a
long-only option.
Arg_parser normally makes it appear as if all the option arguments
were specified before all the non-option arguments for the purposes
of parsing, even if the user of your program intermixed option and
non-option arguments. If you want the arguments in the exact order
the user typed them, call 'ap_init' with 'in_order' = true.
Arg_parser normally makes it appear as if all the option arguments
were specified before all the non-option arguments for the purposes
of parsing, even if the user of your program intermixed option and
non-option arguments. If you want the arguments in the exact order
the user typed them, call 'ap_init' with 'in_order' = true.
The argument '--' terminates all options; any following arguments are
treated as non-option arguments, even if they begin with a hyphen.
The argument '--' terminates all options; any following arguments are
treated as non-option arguments, even if they begin with a hyphen.
The syntax for optional option arguments is '-<short_option><argument>'
(without whitespace), or '--<long_option>=<argument>'.
The syntax for optional option arguments is '-<short_option><argument>'
(without whitespace), or '--<long_option>=<argument>'.
*/
#ifdef __cplusplus
@ -79,11 +79,11 @@ void ap_free( 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 );
/* If ap_code( i ) is 0, ap_argument( i ) is a non-option.
Else ap_argument( i ) is the option's argument (or empty). */
/* If ap_code( i ) is 0, ap_argument( i ) is a non-option.
Else ap_argument( i ) is the option's argument (or empty). */
int ap_code( const struct Arg_parser * const ap, const int i );
const char * ap_argument( const struct Arg_parser * const ap, const int i );

25
configure vendored
View file

@ -1,12 +1,12 @@
#! /bin/sh
# configure script for Clzip - LZMA lossless data compressor
# Copyright (C) 2010-2019 Antonio Diaz Diaz.
# Copyright (C) 2010-2021 Antonio Diaz Diaz.
#
# This configure script is free software: you have unlimited permission
# to copy, distribute and modify it.
# to copy, distribute, and modify it.
pkgname=clzip
pkgversion=1.11
pkgversion=1.12
progname=clzip
srctrigger=doc/${pkgname}.texi
@ -26,11 +26,7 @@ CFLAGS='-Wall -W -O2'
LDFLAGS=
# checking whether we are using GNU C.
/bin/sh -c "${CC} --version" > /dev/null 2>&1 ||
{
CC=cc
CFLAGS=-O2
}
/bin/sh -c "${CC} --version" > /dev/null 2>&1 || { CC=cc ; CFLAGS=-O2 ; }
# Loop over all args
args=
@ -42,11 +38,12 @@ while [ $# != 0 ] ; do
shift
# 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
case ${option} in
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
*=*) optarg=`echo "${option}" | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
esac
# Process the options
@ -125,7 +122,7 @@ if [ -z "${srcdir}" ] ; then
if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
## 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
@ -148,7 +145,7 @@ if [ -z "${no_create}" ] ; then
# Run this file to recreate the current configuration.
#
# 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
EOF
@ -170,11 +167,11 @@ echo "LDFLAGS = ${LDFLAGS}"
rm -f Makefile
cat > Makefile << EOF
# Makefile for Clzip - LZMA lossless data compressor
# 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 Makefile is free software: you have unlimited permission
# to copy, distribute and modify it.
# to copy, distribute, and modify it.
pkgname = ${pkgname}
pkgversion = ${pkgversion}

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
@ -159,16 +159,15 @@ static bool LZd_verify_trailer( struct LZ_decoder * const d,
{
if( verbosity >= 4 ) show_header( d->dictionary_size );
if( data_size == 0 || member_size == 0 )
fputs( "no data compressed. ", stderr );
fputs( "no data compressed. ", stderr );
else
fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ",
fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ",
(double)data_size / member_size,
( 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 >= 3 )
fprintf( stderr, "decompressed %9llu, compressed %8llu. ",
data_size, member_size );
fprintf( stderr, "%9llu out, %8llu in. ", data_size, member_size );
}
return true;
}

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
enum { rd_buffer_size = 16384 };
@ -107,7 +107,7 @@ static inline unsigned Rd_decode( struct Range_decoder * const rdec,
/* symbol <<= 1; */
/* if( rdec->code >= rdec->range ) { rdec->code -= rdec->range; symbol |= 1; } */
bit = ( rdec->code >= rdec->range );
symbol = ( symbol << 1 ) + bit;
symbol <<= 1; symbol += bit;
rdec->code -= rdec->range & ( 0U - bit );
}
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,
Bit_model bm[] )
{
unsigned symbol = 1;
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
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] );
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,
Bit_model bm[] )
{
unsigned symbol = 1;
symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] );
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] );
@ -177,7 +175,7 @@ Rd_decode_tree_reversed( struct Range_decoder * const rdec,
for( i = 0; i < num_bits; ++i )
{
const unsigned bit = Rd_decode_bit( rdec, &bm[model] );
model = ( model << 1 ) + bit;
model <<= 1; model += bit;
symbol |= ( bit << i );
}
return symbol;
@ -187,12 +185,9 @@ static inline unsigned
Rd_decode_tree_reversed4( struct Range_decoder * const rdec, Bit_model bm[] )
{
unsigned symbol = Rd_decode_bit( rdec, &bm[1] );
unsigned model = 2 + symbol;
unsigned bit = Rd_decode_bit( rdec, &bm[model] );
model = ( model << 1 ) + bit; symbol |= ( bit << 1 );
bit = Rd_decode_bit( rdec, &bm[model] );
model = ( model << 1 ) + bit; symbol |= ( bit << 2 );
symbol |= ( Rd_decode_bit( rdec, &bm[model] ) << 3 );
symbol += Rd_decode_bit( rdec, &bm[2+symbol] ) << 1;
symbol += Rd_decode_bit( rdec, &bm[4+symbol] ) << 2;
symbol += Rd_decode_bit( rdec, &bm[8+symbol] ) << 3;
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 bit = Rd_decode_bit( rdec, &bm[symbol+match_bit+mask] );
symbol = ( symbol << 1 ) + bit;
symbol <<= 1; symbol += bit;
if( symbol > 0xFF ) return symbol & 0xFF;
mask &= ~(match_bit ^ (bit << 8)); /* if( match_bit != bit ) mask = 0; */
}

View file

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
.TH CLZIP "1" "January 2019" "clzip 1.11" "User Commands"
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
.TH CLZIP "1" "January 2021" "clzip 1.12" "User Commands"
.SH NAME
clzip \- reduces the size of files
.SH SYNOPSIS
@ -8,16 +8,18 @@ clzip \- reduces the size of files
.SH DESCRIPTION
Clzip is a C language version of lzip, fully compatible with lzip 1.4 or
newer. As clzip is written in C, it may be easier to integrate in
applications like package managers, embedded devices, or systems lacking
a C++ compiler.
applications like package managers, embedded devices, or systems lacking a
C++ compiler.
.PP
Lzip is a lossless data compressor with a user interface similar to the
one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip \fB\-0\fR)
or compress most files more than bzip2 (lzip \fB\-9\fR). Decompression speed is
intermediate between gzip and bzip2. Lzip is better than gzip and bzip2
from a data recovery perspective. Lzip has been designed, written and
tested with great care to replace gzip and bzip2 as the standard
general\-purpose compressed format for unix\-like systems.
Lzip is a lossless data compressor with a user interface similar to the one
of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov
chain\-Algorithm' (LZMA) stream format, chosen to maximize safety and
interoperability. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) or
compress most files more than bzip2 (lzip \fB\-9\fR). Decompression speed is
intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from
a data recovery perspective. Lzip has been designed, written, and tested
with great care to replace gzip and bzip2 as the standard general\-purpose
compressed format for unix\-like systems.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
@ -54,7 +56,7 @@ print (un)compressed file sizes
set match length limit in bytes [36]
.TP
\fB\-o\fR, \fB\-\-output=\fR<file>
if reading standard input, write to <file>
write to <file>, keep input files
.TP
\fB\-q\fR, \fB\-\-quiet\fR
suppress all messages
@ -92,19 +94,28 @@ to 2^29 bytes.
.PP
The bidimensional parameter space of LZMA can't be mapped to a linear
scale optimal for all files. If your files are large, very repetitive,
etc, you may need to use the \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR
options directly to achieve optimal performance.
etc, you may need to use the options \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR
directly to achieve optimal performance.
.PP
To extract all the files from archive 'foo.tar.lz', use the commands
\&'tar \fB\-xf\fR foo.tar.lz' or 'clzip \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'.
.PP
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
invalid input file, 3 for an internal consistency error (eg, bug) which
caused clzip to panic.
.PP
The ideas embodied in clzip 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"
Report bugs to lzip\-bug@nongnu.org
.br
Clzip home page: http://www.nongnu.org/lzip/clzip.html
.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>
.br
This is free software: you are free to change and redistribute it.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
@ -37,7 +37,7 @@ int LZe_get_match_pairs( struct LZ_encoder * const e, struct Pair * pairs )
int32_t * ptr1 = ptr0 + 1;
int32_t * newptr;
int len = 0, len0 = 0, len1 = 0;
int maxlen = 0;
int maxlen = 3; /* only used if pairs != 0 */
int num_pairs = 0;
const int pos1 = e->eb.mb.pos + 1;
const int min_pos = ( e->eb.mb.pos > e->eb.mb.dictionary_size ) ?
@ -62,8 +62,8 @@ int LZe_get_match_pairs( struct LZ_encoder * const e, struct Pair * pairs )
if( pairs )
{
int np2 = e->eb.mb.prev_positions[key2];
int np3 = e->eb.mb.prev_positions[key3];
const int np2 = e->eb.mb.prev_positions[key2];
const int np3 = e->eb.mb.prev_positions[key3];
if( np2 > min_pos && e->eb.mb.buffer[np2-1] == data[0] )
{
pairs[0].dis = e->eb.mb.pos - np2;
@ -73,19 +73,17 @@ int LZe_get_match_pairs( struct LZ_encoder * const e, struct Pair * pairs )
if( np2 != np3 && np3 > min_pos && e->eb.mb.buffer[np3-1] == data[0] )
{
maxlen = 3;
np2 = np3;
pairs[num_pairs].dis = e->eb.mb.pos - np2;
++num_pairs;
pairs[num_pairs++].dis = e->eb.mb.pos - np3;
}
if( num_pairs > 0 )
{
const int delta = pos1 - np2;
const int delta = pairs[num_pairs-1].dis + 1;
while( maxlen < len_limit && data[maxlen-delta] == data[maxlen] )
++maxlen;
pairs[num_pairs-1].len = maxlen;
if( maxlen < 3 ) maxlen = 3;
if( maxlen >= len_limit ) pairs = 0; /* done. now just skip */
}
if( maxlen < 3 ) maxlen = 3;
}
e->eb.mb.prev_positions[key2] = pos1;

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
struct Len_prices

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
@ -95,11 +95,10 @@ bool Mb_init( struct Matchfinder_base * const mb, const int before_size,
if( Mb_read_block( mb ) && !mb->at_stream_end &&
mb->buffer_size < buffer_size_limit )
{
uint8_t * tmp;
mb->buffer_size = buffer_size_limit;
tmp = (uint8_t *)realloc( mb->buffer, mb->buffer_size );
uint8_t * const tmp = (uint8_t *)realloc( mb->buffer, buffer_size_limit );
if( !tmp ) { free( mb->buffer ); return false; }
mb->buffer = tmp;
mb->buffer_size = buffer_size_limit;
Mb_read_block( mb );
}
if( mb->at_stream_end && mb->stream_pos < dict_size )
@ -167,7 +166,7 @@ void Re_flush_data( struct Range_encoder * const renc )
}
/* End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) */
/* End Of Stream marker => (dis == 0xFFFFFFFFU, len == min_match_len) */
void LZeb_full_flush( struct LZ_encoder_base * const eb, const State state )
{
int i;

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
enum { price_shift_bits = 6,
@ -133,7 +133,7 @@ static inline int price_symbol_reversed( const Bit_model bm[], int symbol,
const bool bit = symbol & 1;
symbol >>= 1;
price += price_bit( bm[model], bit );
model = ( model << 1 ) | bit;
model <<= 1; model |= bit;
}
return price;
}
@ -333,28 +333,30 @@ static inline void Re_encode_bit( struct Range_encoder * const renc,
static inline void Re_encode_tree3( struct Range_encoder * const renc,
Bit_model bm[], const int symbol )
{
int model = 1;
int model;
bool bit = ( symbol >> 2 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[1], bit );
model = 2 | bit;
bit = ( symbol >> 1 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[model], bit ); model <<= 1; model |= bit;
Re_encode_bit( renc, &bm[model], symbol & 1 );
}
static inline void Re_encode_tree6( struct Range_encoder * const renc,
Bit_model bm[], const unsigned symbol )
{
int model = 1;
int model;
bool bit = ( symbol >> 5 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[1], bit );
model = 2 | bit;
bit = ( symbol >> 4 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[model], bit ); model <<= 1; model |= bit;
bit = ( symbol >> 3 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[model], bit ); model <<= 1; model |= bit;
bit = ( symbol >> 2 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[model], bit ); model <<= 1; model |= bit;
bit = ( symbol >> 1 ) & 1;
Re_encode_bit( renc, &bm[model], bit ); model = ( model << 1 ) | bit;
Re_encode_bit( renc, &bm[model], bit ); model <<= 1; model |= bit;
Re_encode_bit( renc, &bm[model], symbol & 1 );
}
@ -367,7 +369,7 @@ static inline void Re_encode_tree8( struct Range_encoder * const renc,
{
const bool bit = ( symbol >> i ) & 1;
Re_encode_bit( renc, &bm[model], bit );
model = ( model << 1 ) | bit;
model <<= 1; model |= bit;
}
}
@ -381,7 +383,7 @@ static inline void Re_encode_tree_reversed( struct Range_encoder * const renc,
const bool bit = symbol & 1;
symbol >>= 1;
Re_encode_bit( renc, &bm[model], bit );
model = ( model << 1 ) | bit;
model <<= 1; model |= bit;
}
}

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
struct FLZ_encoder

55
list.c
View file

@ -1,26 +1,26 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
@ -33,11 +33,11 @@ static void list_line( const unsigned long long uncomp_size,
const char * const input_filename )
{
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 ),
input_filename );
else
printf( "%15llu %15llu -INF%% %s\n", uncomp_size, comp_size,
printf( "%14llu %14llu -INF%% %s\n", uncomp_size, comp_size,
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; }
input_filename = from_stdin ? "(stdin)" : filenames[i];
infd = from_stdin ? STDIN_FILENO :
open_instream( input_filename, &in_stats, true, true );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
open_instream( input_filename, &in_stats, false, true );
if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
Li_init( &lzip_index, infd, ignore_trailing, loose_trailing );
close( infd );
if( lzip_index.retval != 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;
}
if( verbosity >= 0 )
@ -80,31 +80,22 @@ int list_files( const char * const filenames[], const int num_filenames,
{
first_post = false;
if( verbosity >= 1 ) fputs( " dict memb trail ", stdout );
fputs( " uncompressed compressed saved name\n", stdout );
fputs( " uncompressed compressed saved name\n", stdout );
}
if( verbosity >= 1 )
{
long long trailing_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 );
}
printf( "%s %5ld %6lld ", format_ds( lzip_index.dictionary_size ),
lzip_index.members, Li_file_size( &lzip_index ) - cdata_size );
list_line( udata_size, cdata_size, input_filename );
if( verbosity >= 2 && lzip_index.members > 1 )
{
long i;
fputs( " member data_pos data_size member_pos member_size\n", stdout );
fputs( " member data_pos data_size member_pos member_size\n", stdout );
for( i = 0; i < lzip_index.members; ++i )
{
const struct Block * db = Li_dblock( &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 );
}
first_post = true; /* reprint heading after list of members */

105
lzip.h
View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef max
@ -22,8 +22,6 @@
#define min(x,y) ((x) <= (y) ? (x) : (y))
#endif
void * resize_buffer( void * buf, const unsigned min_size );
typedef int State;
enum { states = 12 };
@ -84,7 +82,7 @@ static inline int get_len_state( const int len )
{ return min( len - min_match_len, len_states - 1 ); }
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,
@ -118,65 +116,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. */
extern CRC32 crc32;
@ -226,7 +165,7 @@ static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */
typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */
/* 4 version */
/* 5 coded_dict_size */
/* 5 coded dictionary size */
enum { Lh_size = 6 };
static inline void Lh_set_magic( Lzip_header data )
@ -282,6 +221,12 @@ static inline bool Lh_set_dictionary_size( Lzip_header data, const unsigned sz )
return true;
}
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];
/* 0-3 CRC32 of the uncompressed data */
@ -335,10 +280,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_dict_msg = "Invalid dictionary size in member header.";
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 mem_msg = "Not enough memory.";
/* defined in decoder.c */
int readblock( const int fd, uint8_t * const buf, const int size );
@ -350,11 +299,15 @@ int list_files( const char * const filenames[], const int num_filenames,
/* defined in main.c */
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 * format_ds( const unsigned dictionary_size );
void show_header( const unsigned dictionary_size );
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 show_error( const char * const msg, const int errcode, const bool help );
void show_file_error( const char * const filename, const char * const msg,

View file

@ -1,28 +1,28 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "lzip.h"
@ -58,8 +58,7 @@ static bool push_back_member( struct Lzip_index * const li,
struct Member * p;
void * tmp = resize_buffer( li->member_vector,
( li->members + 1 ) * sizeof li->member_vector[0] );
if( !tmp )
{ add_error( li, "Not enough memory." ); li->retval = 1; return false; }
if( !tmp ) { add_error( li, mem_msg ); li->retval = 1; return false; }
li->member_vector = (struct Member *)tmp;
p = &(li->member_vector[li->members]);
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,
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. */
static bool Li_skip_trailing_data( struct Lzip_index * const li,
const int fd, long long * const pos,
static bool Li_skip_trailing_data( struct Lzip_index * const li, const int fd,
unsigned long long * const pos,
const bool ignore_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 */
{
Lzip_header header;
const Lzip_header * header2;
const Lzip_trailer * const trailer =
(const Lzip_trailer *)( buffer + i - Lt_size );
const unsigned long long member_size = Lt_get_member_size( *trailer );
unsigned dictionary_size;
bool full_h2;
if( member_size == 0 ) /* skip trailing zeros */
{ while( i > Lt_size && buffer[i-9] == 0 ) --i; continue; }
if( member_size > ipos + i || !Lt_verify_consistency( *trailer ) )
continue;
if( seek_read( fd, header, Lh_size,
ipos + i - member_size ) != Lh_size )
{ Li_set_errno_error( li, "Error reading member header: " );
return false; }
dictionary_size = Lh_get_dictionary_size( header );
if( !Lh_verify_magic( header ) || !Lh_verify_version( header ) ||
!isvalid_ds( dictionary_size ) ) continue;
if( Lh_verify_prefix( buffer + i, bsize - i ) )
if( !Li_read_header( li, fd, header, ipos + i - member_size ) )
return false;
if( !Lh_verify( header ) ) continue;
header2 = (const Lzip_header *)( buffer + i );
full_h2 = bsize - i >= Lh_size;
if( Lh_verify_prefix( *header2, bsize - i ) ) /* last member */
{
add_error( li, "Last member in input file is truncated or corrupt." );
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." );
li->retval = 2; return false;
}
if( !loose_trailing && bsize - i >= Lh_size &&
Lh_verify_corrupt( buffer + i ) )
if( !loose_trailing && full_h2 && Lh_verify_corrupt( *header2 ) )
{ add_error( li, corrupt_mm_msg ); li->retval = 2; return false; }
if( !ignore_trailing )
{ add_error( li, trailing_msg ); li->retval = 2; return false; }
*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,
member_size, dictionary_size );
}
if( ipos <= 0 )
if( ipos == 0 )
{ Li_set_num_error( li, "Bad trailer at pos ", *pos - Lt_size );
return false; }
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 )
{
Lzip_header header;
long long pos;
unsigned long long pos;
long i;
li->member_vector = 0;
li->error = 0;
@ -188,6 +213,7 @@ bool Li_init( struct Lzip_index * const li, const int infd,
li->members = 0;
li->error_size = 0;
li->retval = 0;
li->dictionary_size = 0;
if( li->insize < 0 )
{ Li_set_errno_error( li, "Input file is not seekable: " ); return false; }
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)." );
li->retval = 2; return false; }
if( seek_read( infd, header, Lh_size, 0 ) != Lh_size )
{ Li_set_errno_error( li, "Error reading member 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; }
if( !Li_read_header( li, infd, header, 0 ) ) return false;
if( Li_check_header_error( li, header ) ) return false;
pos = li->insize; /* always points to a header or to EOF */
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 )
{ Li_set_errno_error( li, "Error reading member trailer: " ); break; }
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_skip_trailing_data( li, infd, &pos, ignore_trailing,
loose_trailing ) ) continue; else return false; }
Li_set_num_error( li, "Bad trailer at pos ", pos - Lt_size );
break;
}
if( seek_read( infd, header, Lh_size, pos - member_size ) != Lh_size )
{ Li_set_errno_error( li, "Error reading member header: " ); break; }
dictionary_size = Lh_get_dictionary_size( header );
if( !Lh_verify_magic( header ) || !Lh_verify_version( header ) ||
!isvalid_ds( dictionary_size ) )
if( !Li_read_header( li, infd, header, pos - member_size ) ) break;
if( !Lh_verify( header ) ) /* bad header */
{
if( li->members <= 0 )
{ 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;
}
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,
member_size, dictionary_size ) )
return false;

View file

@ -1,18 +1,18 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INT64_MAX
@ -54,6 +54,7 @@ struct Lzip_index
long members;
int error_size;
int retval;
unsigned dictionary_size; /* largest dictionary size in the file */
};
bool Li_init( struct Lzip_index * const li, const int infd,

388
main.c
View file

@ -1,24 +1,24 @@
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
/* Clzip - LZMA lossless data compressor
Copyright (C) 2010-2021 Antonio Diaz Diaz.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
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 invalid input file, 3 for an internal consistency error
(eg, bug) which caused clzip to panic.
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 invalid input file, 3 for an internal consistency error
(eg, bug) which caused clzip to panic.
*/
#define _FILE_OFFSET_BITS 64
@ -74,11 +74,11 @@
int verbosity = 0;
const char * const program_name = "clzip";
const char * const program_year = "2019";
const char * invocation_name = 0;
static const char * const program_name = "clzip";
static const char * const program_year = "2021";
static const char * invocation_name = "clzip"; /* default value */
const struct { const char * from; const char * to; } known_extensions[] = {
static const struct { const char * from; const char * to; } known_extensions[] = {
{ ".lz", "" },
{ ".tlz", ".tar" },
{ 0, 0 } };
@ -93,24 +93,26 @@ enum Mode { m_compress, m_decompress, m_list, m_test };
/* Variables used in signal handler context.
They are not declared volatile because the handler never returns. */
char * output_filename = 0;
int outfd = -1;
bool delete_output_on_interrupt = false;
static char * output_filename = 0;
static int outfd = -1;
static bool delete_output_on_interrupt = false;
static void show_help( void )
{
printf( "Clzip is a C language version of lzip, fully compatible with lzip 1.4 or\n"
"newer. As clzip is written in C, it may be easier to integrate in\n"
"applications like package managers, embedded devices, or systems lacking\n"
"a C++ compiler.\n"
"\nLzip is a lossless data compressor with a user interface similar to the\n"
"one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0)\n"
"or compress most files more than bzip2 (lzip -9). Decompression speed is\n"
"intermediate between gzip and bzip2. Lzip is better than gzip and bzip2\n"
"from a data recovery perspective. Lzip has been designed, written and\n"
"tested with great care to replace gzip and bzip2 as the standard\n"
"general-purpose compressed format for unix-like systems.\n"
"applications like package managers, embedded devices, or systems lacking a\n"
"C++ compiler.\n"
"\nLzip is a lossless data compressor with a user interface similar to the one\n"
"of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov\n"
"chain-Algorithm' (LZMA) stream format, chosen to maximize safety and\n"
"interoperability. Lzip can compress about as fast as gzip (lzip -0) or\n"
"compress most files more than bzip2 (lzip -9). Decompression speed is\n"
"intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from\n"
"a data recovery perspective. Lzip has been designed, written, and tested\n"
"with great care to replace gzip and bzip2 as the standard general-purpose\n"
"compressed format for unix-like systems.\n"
"\nUsage: %s [options] [files]\n", invocation_name );
printf( "\nOptions:\n"
" -h, --help display this help and exit\n"
@ -124,7 +126,7 @@ static void show_help( void )
" -k, --keep keep (don't delete) input files\n"
" -l, --list print (un)compressed file sizes\n"
" -m, --match-length=<bytes> set match length limit in bytes [36]\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"
" -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8 MiB]\n"
" -S, --volume-size=<bytes> set volume size limit in bytes\n"
@ -134,7 +136,7 @@ static void show_help( void )
" --fast alias for -0\n"
" --best alias for -9\n"
" --loose-trailing allow trailing data seeming corrupt header\n"
"If no file names are given, or if a file is '-', clzip compresses or\n"
"\nIf no file names are given, or if a file is '-', clzip compresses or\n"
"decompresses from standard input to standard output.\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"
@ -142,12 +144,19 @@ static void show_help( void )
"to 2^29 bytes.\n"
"\nThe bidimensional parameter space of LZMA can't be mapped to a linear\n"
"scale optimal for all files. If your files are large, very repetitive,\n"
"etc, you may need to use the --dictionary-size and --match-length\n"
"options directly to achieve optimal performance.\n"
"etc, you may need to use the options --dictionary-size and --match-length\n"
"directly to achieve optimal performance.\n"
"\nTo extract all the files from archive 'foo.tar.lz', use the commands\n"
"'tar -xf foo.tar.lz' or 'clzip -cd foo.tar.lz | tar -xf -'.\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"
"invalid input file, 3 for an internal consistency error (eg, bug) which\n"
"caused clzip to panic.\n"
"\nThe ideas embodied in clzip 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"
"Clzip home page: http://www.nongnu.org/lzip/clzip.html\n" );
}
@ -168,15 +177,64 @@ void * resize_buffer( void * buf, const unsigned min_size )
{
if( buf ) buf = realloc( buf, min_size );
else buf = malloc( min_size );
if( !buf )
{
show_error( "Not enough memory.", 0, false );
cleanup_and_fail( 1 );
}
if( !buf ) { show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
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 )
{
if( verbosity >= 0 )
@ -222,7 +280,7 @@ const char * format_ds( 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 ) );
}
@ -289,7 +347,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 )
{
@ -316,14 +374,17 @@ static int extension_index( const char * const name )
}
static void set_c_outname( const char * const name, const bool force_ext,
const bool multifile )
static void set_c_outname( const char * const name, const bool filenames_given,
const bool force_ext, const bool multifile )
{
/* zupdate < 1.9 depends on lzip adding the extension '.lz' to name when
reading from standard input. */
output_filename = resize_buffer( output_filename, strlen( name ) + 5 +
strlen( known_extensions[0].from ) + 1 );
strcpy( output_filename, name );
if( multifile ) strcat( output_filename, "00001" );
if( force_ext || multifile || extension_index( output_filename ) < 0 )
if( force_ext || multifile ||
( !filenames_given && extension_index( output_filename ) < 0 ) )
strcat( output_filename, known_extensions[0].from );
}
@ -354,7 +415,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,
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 );
if( infd < 0 )
@ -366,13 +427,12 @@ int open_instream( const char * const name, struct stat * const in_statsp,
const bool can_read = ( i == 0 && !reg_only &&
( S_ISBLK( mode ) || S_ISCHR( 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 )
fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
program_name, name,
( can_read && !no_ofile ) ?
",\n and '--stdout' was not specified" : "" );
program_name, name, ( can_read && one_to_one ) ?
",\n and neither '-c' nor '-o' were specified" : "" );
close( infd );
infd = -1;
}
@ -383,9 +443,8 @@ int open_instream( const char * const name, struct stat * const in_statsp,
static int open_instream2( const char * const name, struct stat * const in_statsp,
const enum Mode program_mode, const int eindex,
const bool recompress, const bool to_stdout )
const bool one_to_one, const bool recompress )
{
const bool no_ofile = ( to_stdout || program_mode == m_test );
if( program_mode == m_compress && !recompress && eindex >= 0 )
{
if( verbosity >= 0 )
@ -393,15 +452,15 @@ static int open_instream2( const char * const name, struct stat * const in_stats
program_name, name, known_extensions[eindex].from );
return -1;
}
return open_instream( name, in_statsp, no_ofile, false );
return open_instream( name, in_statsp, one_to_one, false );
}
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 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_CREAT | O_WRONLY | O_BINARY;
if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
@ -420,25 +479,6 @@ static bool open_outstream( const bool force, const bool from_stdin )
}
static bool check_tty( const char * const input_filename, const int infd,
const enum Mode program_mode )
{
if( program_mode == m_compress && isatty( outfd ) )
{
show_error( "I won't write compressed data to a terminal.", 0, true );
return false;
}
if( ( program_mode == m_decompress || program_mode == m_test ) &&
isatty( infd ) )
{
show_file_error( input_filename,
"I won't read compressed data from a terminal.", 0 );
return false;
}
return true;
}
static void set_signals( void (*action)(int) )
{
signal( SIGHUP, action );
@ -464,7 +504,7 @@ void cleanup_and_fail( const int retval )
}
void signal_handler( int sig )
static void signal_handler( int sig )
{
if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false );
@ -472,7 +512,31 @@ 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( ( program_mode == m_decompress || program_mode == m_test ) &&
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;
}
static bool check_tty_out( const enum Mode program_mode )
{
if( program_mode == m_compress && isatty( outfd ) )
{ show_file_error( output_filename[0] ?
output_filename : "(stdout)",
"I won't write compressed data to a terminal.", 0 );
return false; }
return true;
}
/* Set permissions, owner, and times. */
static void close_and_set_permissions( const struct stat * const in_statsp )
{
bool warning = false;
@ -591,7 +655,7 @@ static int compress( const unsigned long long cfile_size,
close_and_set_permissions( in_statsp );
if( !next_filename() )
{ Pp_show_msg( pp, "Too many volume files." ); retval = 1; break; }
if( !open_outstream( true, !in_statsp ) ) { retval = 1; break; }
if( !open_outstream( true, in_statsp ) ) { retval = 1; break; }
}
}
}
@ -661,10 +725,7 @@ static int decompress( const unsigned long long cfile_size, const int infd,
int retval = 0;
bool first_member;
if( !Rd_init( &rdec, infd ) )
{
show_error( "Not enough memory.", 0, false );
cleanup_and_fail( 1 );
}
{ show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
for( first_member = true; ; first_member = false )
{
@ -711,7 +772,7 @@ static int decompress( const unsigned long long cfile_size, const int infd,
Pp_show_msg( pp, 0 );
if( !LZd_init( &decoder, &rdec, dictionary_size, outfd ) )
{ Pp_show_msg( pp, "Not enough memory." ); retval = 1; break; }
{ Pp_show_msg( pp, mem_msg ); retval = 1; break; }
show_dprogress( cfile_size, partial_file_pos, &rdec, pp ); /* init */
result = LZd_decode_member( &decoder, pp );
partial_file_pos += Rd_member_position( &rdec );
@ -845,12 +906,14 @@ int main( const int argc, const char * const argv[] )
{ 3 << 23, 132 }, /* -8 */
{ 1 << 25, 273 } }; /* -9 */
struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */
const unsigned long long max_member_size = 0x0008000000000000ULL;
const unsigned long long max_volume_size = 0x4000000000000000ULL;
const unsigned long long max_member_size = 0x0008000000000000ULL; /* 2 PiB */
const unsigned long long max_volume_size = 0x4000000000000000ULL; /* 4 EiB */
unsigned long long member_size = max_member_size;
unsigned long long volume_size = 0;
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;
enum Mode program_mode = m_compress;
int argind = 0;
@ -866,20 +929,19 @@ int main( const int argc, const char * const argv[] )
bool stdin_used = false;
bool to_stdout = false;
bool zero = false;
struct Pretty_print pp;
enum { opt_lt = 256 };
const struct ap_Option options[] =
{
{ '0', "fast", ap_no },
{ '1', 0, ap_no },
{ '2', 0, ap_no },
{ '3', 0, ap_no },
{ '4', 0, ap_no },
{ '5', 0, ap_no },
{ '6', 0, ap_no },
{ '7', 0, ap_no },
{ '8', 0, ap_no },
{ '1', 0, ap_no },
{ '2', 0, ap_no },
{ '3', 0, ap_no },
{ '4', 0, ap_no },
{ '5', 0, ap_no },
{ '6', 0, ap_no },
{ '7', 0, ap_no },
{ '8', 0, ap_no },
{ '9', "best", ap_no },
{ 'a', "trailing-error", ap_no },
{ 'b', "member-size", ap_yes },
@ -900,15 +962,13 @@ int main( const int argc, const char * const argv[] )
{ 'v', "verbose", ap_no },
{ 'V', "version", ap_no },
{ opt_lt, "loose-trailing", ap_no },
{ 0 , 0, ap_no } };
{ 0, 0, ap_no } };
struct Arg_parser parser;
invocation_name = argv[0];
if( argc > 0 ) invocation_name = argv[0];
CRC32_init();
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 */
{ show_error( ap_error( &parser ), 0, true ); return 1; }
@ -936,7 +996,8 @@ int main( const int argc, const char * const argv[] )
getnum( arg, min_match_len_limit, max_match_len );
zero = false; 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 's': encoder_options.dictionary_size = get_dict_size( arg );
zero = false; break;
@ -967,21 +1028,33 @@ int main( const int argc, const char * const argv[] )
if( program_mode == m_list )
return list_files( filenames, num_filenames, ignore_trailing, loose_trailing );
if( program_mode == m_test )
outfd = -1;
else if( program_mode == m_compress )
if( program_mode == m_compress )
{
if( volume_size > 0 && !to_stdout && default_output_filename[0] &&
num_filenames > 1 )
{ show_error( "Only can compress one file when using '-o' and '-S'.",
0, true ); return 1; }
Dis_slots_init();
Prob_prices_init();
}
else volume_size = 0;
if( program_mode == m_test ) to_stdout = false; /* apply overrides */
if( program_mode == m_test || to_stdout ) default_output_filename = "";
if( !to_stdout && program_mode != m_test &&
( filenames_given || default_output_filename[0] ) )
output_filename = resize_buffer( output_filename, 1 );
output_filename[0] = 0;
if( to_stdout && program_mode != m_test ) /* check tty only once */
{ outfd = STDOUT_FILENO; if( !check_tty_out( program_mode ) ) return 1; }
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 );
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 )
{
unsigned long long cfile_size;
@ -990,70 +1063,50 @@ int main( const int argc, const char * const argv[] )
int tmp;
struct stat in_stats;
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;
infd = STDIN_FILENO;
if( program_mode != m_test )
{
if( to_stdout || !default_output_filename[0] )
outfd = STDOUT_FILENO;
else
{
if( program_mode == m_compress )
set_c_outname( default_output_filename, false, volume_size > 0 );
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;
}
}
}
if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue;
if( one_to_one ) { outfd = STDOUT_FILENO; output_filename[0] = 0; }
}
else
{
const int eindex = extension_index( input_filename = filenames[i] );
infd = open_instream2( input_filename, &in_stats, program_mode,
eindex, recompress, to_stdout );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
if( program_mode != m_test )
eindex, one_to_one, recompress );
if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue;
if( one_to_one ) /* open outfd after verifying infd */
{
if( to_stdout ) outfd = STDOUT_FILENO;
else
{
if( program_mode == m_compress )
set_c_outname( input_filename, true, volume_size > 0 );
else set_d_outname( input_filename, eindex );
if( !open_outstream( force, false ) )
{
if( retval < 1 ) retval = 1;
close( infd );
continue;
}
}
if( program_mode == m_compress )
set_c_outname( input_filename, true, true, volume_size > 0 );
else set_d_outname( input_filename, eindex );
if( !open_outstream( force, true ) )
{ close( infd ); set_retval( &retval, 1 ); continue; }
}
}
Pp_set_name( &pp, input_filename );
if( !check_tty( pp.name, infd, program_mode ) )
if( one_to_one && !check_tty_out( program_mode ) )
{ set_retval( &retval, 1 ); return retval; } /* don't delete a tty */
if( to_file && outfd < 0 ) /* open outfd after verifying infd */
{
if( retval < 1 ) retval = 1;
if( program_mode == m_test ) { close( infd ); continue; }
cleanup_and_fail( retval );
if( program_mode == m_compress ) set_c_outname( default_output_filename,
filenames_given, false, volume_size > 0 );
else
{ output_filename = resize_buffer( output_filename,
strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename ); }
if( !open_outstream( force, false ) || !check_tty_out( program_mode ) )
return 1; /* check tty only once and don't try to delete a tty */
}
in_statsp = input_filename[0] ? &in_stats : 0;
cfile_size = ( in_statsp && S_ISREG( in_statsp->st_mode ) ) ?
( in_statsp->st_size + 99 ) / 100 : 0;
in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0;
cfile_size = ( input_filename[0] && S_ISREG( in_stats.st_mode ) ) ?
( in_stats.st_size + 99 ) / 100 : 0;
if( program_mode == m_compress )
tmp = compress( cfile_size, member_size, volume_size, infd,
&encoder_options, &pp, in_statsp, zero );
@ -1061,29 +1114,24 @@ int main( const int argc, const char * const argv[] )
tmp = decompress( cfile_size, infd, &pp, ignore_trailing,
loose_trailing, program_mode == m_test );
if( close( infd ) != 0 )
{
show_error( input_filename[0] ? "Error closing input file" :
"Error closing stdin", errno, false );
if( tmp < 1 ) tmp = 1;
}
if( tmp > retval ) retval = tmp;
{ show_file_error( pp.name, "Error closing input file", errno );
set_retval( &tmp, 1 ); }
set_retval( &retval, tmp );
if( tmp )
{ if( program_mode != m_test ) cleanup_and_fail( retval );
else ++failed_tests; }
if( delete_output_on_interrupt )
if( delete_output_on_interrupt && one_to_one )
close_and_set_permissions( in_statsp );
if( input_filename[0] )
{
if( !keep_input_files && !to_stdout && program_mode != m_test &&
( program_mode != m_compress || volume_size == 0 ) )
remove( input_filename );
}
if( input_filename[0] && !keep_input_files && one_to_one &&
( program_mode != m_compress || volume_size == 0 ) )
remove( input_filename );
}
if( outfd >= 0 && close( outfd ) != 0 )
if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); /* -o */
else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */
{
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 )
fprintf( stderr, "%s: warning: %d %s failed the test.\n",

View file

@ -1,9 +1,9 @@
#! /bin/sh
# check script for Clzip - LZMA lossless data compressor
# Copyright (C) 2010-2019 Antonio Diaz Diaz.
# Copyright (C) 2010-2021 Antonio Diaz Diaz.
#
# This script is free software: you have unlimited permission
# to copy, distribute and modify it.
# to copy, distribute, and modify it.
LC_ALL=C
export LC_ALL
@ -30,6 +30,8 @@ cd "${objdir}"/tmp || framework_failure
cat "${testdir}"/test.txt > in || framework_failure
in_lz="${testdir}"/test.txt.lz
in_em="${testdir}"/test_em.txt.lz
fox_lz="${testdir}"/fox.lz
fail=0
test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; }
@ -58,6 +60,16 @@ done
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -dq -o in < "${in_lz}"
[ $? = 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
"${LZIP}" -q -o out.lz nx_file
[ $? = 1 ] || test_failed $LINENO
[ ! -e out.lz ] || test_failed $LINENO
"${LZIP}" -qf -S100k -o out in in
[ $? = 1 ] || test_failed $LINENO
# these are for code coverage
"${LZIP}" -lt "${in_lz}" 2> /dev/null
[ $? = 1 ] || test_failed $LINENO
@ -65,7 +77,9 @@ done
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null
[ $? = 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
"${LZIP}" --help > /dev/null || test_failed $LINENO
"${LZIP}" -n1 -V > /dev/null || test_failed $LINENO
@ -89,12 +103,26 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null
printf "\ntesting decompression..."
"${LZIP}" -lq "${in_lz}" || test_failed $LINENO
"${LZIP}" -t "${in_lz}" || test_failed $LINENO
"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO
for i in "${in_lz}" "${in_em}" ; do
"${LZIP}" -lq "$i" || test_failed $LINENO "$i"
"${LZIP}" -t "$i" || test_failed $LINENO "$i"
"${LZIP}" -d "$i" -o 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
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}"
rm -f copy || framework_failure
cat "${in_lz}" > copy.lz || framework_failure
"${LZIP}" -dk copy.lz || test_failed $LINENO
cmp in copy || test_failed $LINENO
@ -114,10 +142,16 @@ cmp in copy || test_failed $LINENO
printf "to be overwritten" > copy || framework_failure
"${LZIP}" -df -o copy < "${in_lz}" || 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
"${LZIP}" < in > anyothername || test_failed $LINENO
"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null ||
cat "${in_lz}" > anyothername || framework_failure
"${LZIP}" -dv - anyothername - < "${in_lz}" > copy 2> /dev/null ||
test_failed $LINENO
cmp in copy || test_failed $LINENO
cmp in anyothername.out || test_failed $LINENO
@ -158,21 +192,19 @@ done
cmp in copy || test_failed $LINENO
cat in in > in2 || framework_failure
cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure
"${LZIP}" -lq in2.lz || test_failed $LINENO
"${LZIP}" -t in2.lz || test_failed $LINENO
"${LZIP}" -cd in2.lz > copy2 || test_failed $LINENO
"${LZIP}" -lq "${in_lz}" "${in_lz}" || test_failed $LINENO
"${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO
"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > copy2 || test_failed $LINENO
[ ! -e out ] || test_failed $LINENO # override -o
cmp in2 copy2 || test_failed $LINENO
"${LZIP}" --output=copy2.lz < in2 || test_failed $LINENO
"${LZIP}" -lq copy2.lz || test_failed $LINENO
"${LZIP}" -t copy2.lz || test_failed $LINENO
"${LZIP}" -cd copy2.lz > 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 "${in_lz}" "${in_lz}" > copy2.lz || framework_failure
printf "\ngarbage" >> copy2.lz || framework_failure
"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO
rm -f copy2 || framework_failure
"${LZIP}" -alq copy2.lz
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -atq copy2.lz
@ -188,68 +220,92 @@ rm -f copy2 || framework_failure
printf "to be overwritten" > copy2 || framework_failure
"${LZIP}" -df copy2.lz || test_failed $LINENO
cmp in2 copy2 || test_failed $LINENO
rm -f in2 copy2 || framework_failure
rm -f copy2 || framework_failure
printf "\ntesting compression..."
"${LZIP}" -c -0 in in in -S100k -o out3.lz > copy2.lz || test_failed $LINENO
[ ! -e out3.lz ] || test_failed $LINENO # override -o and -S
"${LZIP}" -0f in in --output=copy2.lz || test_failed $LINENO
"${LZIP}" -d copy2.lz -o out2 || test_failed $LINENO
cmp in2 out2 || test_failed $LINENO
rm -f in2 out2 copy2.lz || framework_failure
"${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -cFvvm36 "${in_lz}" > out 2> /dev/null || test_failed $LINENO
"${LZIP}" -Fvvm36 -o - "${in_lz}" > out 2> /dev/null || test_failed $LINENO
"${LZIP}" -cd out | "${LZIP}" -d > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO
"${LZIP}" -0 -o ./- in || test_failed $LINENO
"${LZIP}" -cd ./- | cmp in - || test_failed $LINENO
rm -f ./- || framework_failure
"${LZIP}" -0 -o ./- < in || test_failed $LINENO # add .lz
[ ! -e ./- ] || test_failed $LINENO
"${LZIP}" -cd -- -.lz | cmp in - || test_failed $LINENO
rm -f ./-.lz || framework_failure
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
"${LZIP}" -k -$i in || test_failed $LINENO $i
mv -f in.lz copy.lz || test_failed $LINENO $i
printf "garbage" >> copy.lz || framework_failure
"${LZIP}" -df copy.lz || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i
done
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
"${LZIP}" -c -$i in > out || test_failed $LINENO $i
"${LZIP}" -$i in -c > out || test_failed $LINENO $i
"${LZIP}" -$i in -o o_out || test_failed $LINENO $i # don't add .lz
[ ! -e o_out.lz ] || test_failed $LINENO
cmp out o_out || test_failed $LINENO $i
rm -f o_out || framework_failure
printf "g" >> out || framework_failure
"${LZIP}" -cd out > copy || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i
done
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
"${LZIP}" -$i < in > out || test_failed $LINENO $i
"${LZIP}" -d < out > copy || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i
done
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
"${LZIP}" -f -$i -o out < in || test_failed $LINENO $i
rm -f out || framework_failure
printf "to be overwritten" > out.lz || framework_failure
"${LZIP}" -f -$i -o out < in || test_failed $LINENO $i # add .lz
[ ! -e out ] || test_failed $LINENO
"${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i
cmp in copy || test_failed $LINENO $i
done
rm -f out.lz || framework_failure
rm -f out out.lz || framework_failure
cat in in in in in in in in > in8 || framework_failure
"${LZIP}" -1s12 -S100k in8 || test_failed $LINENO
"${LZIP}" -t in800001.lz in800002.lz || test_failed $LINENO
"${LZIP}" -cd in800001.lz in800002.lz | cmp in8 - || test_failed $LINENO
[ ! -e in800003.lz ] || test_failed $LINENO
rm -f in800001.lz in800002.lz || framework_failure
"${LZIP}" -1s12 -S100k -o out.lz < in8 || test_failed $LINENO
"${LZIP}" -1s12 -S100k -o out.lz in8 || test_failed $LINENO
# ignore -S
"${LZIP}" -d out.lz00001.lz out.lz00002.lz -S100k -o out || test_failed $LINENO
cmp in8 out || test_failed $LINENO
"${LZIP}" -t out.lz00001.lz out.lz00002.lz || test_failed $LINENO
"${LZIP}" -cd out.lz00001.lz out.lz00002.lz | cmp in8 - || test_failed $LINENO
rm -f out.lz00001.lz out.lz00002.lz || framework_failure
[ ! -e out.lz00003.lz ] || test_failed $LINENO
rm -f out out.lz00001.lz out.lz00002.lz || framework_failure
"${LZIP}" -1ks4Ki -b100000 in8 || test_failed $LINENO
"${LZIP}" -t in8.lz || test_failed $LINENO
"${LZIP}" -cd in8.lz | cmp in8 - || test_failed $LINENO
"${LZIP}" -cd in8.lz -o out | cmp in8 - || test_failed $LINENO # override -o
[ ! -e out ] || test_failed $LINENO
rm -f in8 || framework_failure
"${LZIP}" -0 -S100k -o out < in8.lz || test_failed $LINENO
"${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO
"${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO
[ ! -e out00003.lz ] || test_failed $LINENO
rm -f out00001.lz || framework_failure
"${LZIP}" -1 -S100k -o out < in8.lz || test_failed $LINENO
"${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO
"${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO
[ ! -e out00003.lz ] || test_failed $LINENO
rm -f out00001.lz out00002.lz || framework_failure
"${LZIP}" -0 -F -S100k in8.lz || test_failed $LINENO
"${LZIP}" -t in8.lz00001.lz in8.lz00002.lz || test_failed $LINENO
"${LZIP}" -cd in8.lz00001.lz in8.lz00002.lz | cmp in8.lz - || test_failed $LINENO
[ ! -e in8.lz00003.lz ] || test_failed $LINENO
rm -f in8.lz00001.lz in8.lz00002.lz || framework_failure
"${LZIP}" -0kF -b100k in8.lz || test_failed $LINENO
"${LZIP}" -t in8.lz.lz || test_failed $LINENO
@ -313,6 +369,21 @@ else
fi
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
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
@ -339,13 +410,21 @@ printf "g" >> ingin.lz || framework_failure
cat "${in_lz}" >> ingin.lz || framework_failure
"${LZIP}" -lq ingin.lz
[ $? = 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}" -cd ingin.lz > 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
cmp in copy || test_failed $LINENO
rm -f copy ingin.lz || framework_failure
rm -f copy ingin.lz out || framework_failure
echo
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.