1
0
Fork 0

Adding upstream version 1.11.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-23 19:26:07 +01:00
parent 187580aeb9
commit 90a9130b80
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
23 changed files with 560 additions and 480 deletions

View file

@ -1,4 +1,4 @@
Pdlzip was written by Antonio Diaz Diaz.
Pdlzip includes public domain (de)compression code from the LZMA SDK
(Software Development Kit) written by Igor Pavlov.
Pdlzip includes public domain compression/decompression code from the LZMA
SDK (Software Development Kit) written by Igor Pavlov.

View file

@ -8,10 +8,10 @@
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.
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
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This program is distributed in the hope that it will be useful,

View file

@ -1,7 +1,20 @@
2021-01-01 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.11 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.
* Don't allow mixing different operations (-d and -t).
* Replace 'decompressed', 'compressed' with 'out', 'in' in output.
* Document extraction from tar.lz in '--help' output and man page.
* main.c: Set a valid invocation_name even if argc == 0.
* testsuite: Add 9 new test files.
2019-01-01 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.10 released.
* File_* renamed to Lzip_*.
* Rename File_* to Lzip_*.
* main.c: Document option -0 and make it use a 64 KiB dict size.
* main.c (main): Check return value of close( infd ).
* main.c: Compile on DOS with DJGPP.
@ -11,9 +24,9 @@
2018-02-04 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.9 released.
* main.c: Added new option '--loose-trailing'.
* main.c (decompress): Improved corrupt header detection to HD=3.
* Replaced 'bits/byte' with inverse compression ratio in output.
* main.c: New option '--loose-trailing'.
* main.c (decompress): Improve corrupt header detection to HD=3.
* Replace 'bits/byte' with inverse compression ratio in output.
* main.c: Show final diagnostic when testing multiple files.
* main.c: Do not add a second .lz extension to the arg of -o.
* main.c (lzip_decode): Show stored sizes also in hex.
@ -23,12 +36,12 @@
* Version 1.8 released.
* main.c: Continue testing if any input file is a terminal.
* main.c (decompress): Improved detection of trailing data.
* main.c (decompress): Improve detection of trailing data.
2016-05-16 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.7 released.
* main.c: Added new option '-a, --trailing-error'.
* main.c: New option '-a, --trailing-error'.
* main.c (main): Delete '--output' file if infd is a terminal.
* main.c (main): Don't use stdin more than once.
* configure: Avoid warning on some shells when testing for gcc.
@ -39,7 +52,7 @@
* Version 1.6 released.
* main.c (close_and_set_permissions): Behave like 'cp -p'.
* Makefile.in: Added new targets 'install*-compress'.
* Makefile.in: New targets 'install*-compress'.
2013-09-14 Antonio Diaz Diaz <antonio@gnu.org>
@ -50,26 +63,23 @@
2013-05-27 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.4 released.
* main.c: Added new option '-f, --force'.
* main.c: Added new option '-F, --recompress'.
* main.c: Added new option '-k, --keep'.
* main.c: Added new option '-o, --output'.
* main.c: New options '-f, --force', '-F, --recompress',
'-k, --keep', and '-o, --output'.
* main.c: Accept more than one file in command line.
* Decompression time has been reduced by 5%.
* main.c: '--test' no longer needs '/dev/null'.
* Fixed return value of '-d' and '-t' in case of data error.
* main.c: Changed info shown at verbosity levels 2 and 3.
* Fix return value of '-d' and '-t' in case of data error.
* main.c: Change info shown at verbosity levels 2 and 3.
* Ignore option '-n, --threads' for compatibility with plzip.
* configure: Options now accept a separate argument.
* configure: 'datadir' renamed to 'datarootdir'.
* Makefile.in: Added new target 'install-as-lzip'.
* Makefile.in: Added new target 'install-bin'.
* configure: Rename 'datadir' to 'datarootdir'.
* Makefile.in: New targets 'install-as-lzip' and 'install-bin'.
2012-01-03 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.3 released.
* Small change in '--help' output and man page.
* Changed quote characters in messages as advised by GNU Standards.
* Change quote characters in messages as advised by GNU Standards.
* main.c: Set stdin/stdout in binary mode on OS2.
2011-01-05 Antonio Diaz Diaz <ant_diaz@teleline.es>
@ -80,7 +90,7 @@
2010-08-19 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.1 released.
* main.c: Added support for decompression of lzma-alone files.
* main.c: Add support for decompression of lzma-alone files.
* 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
@ -94,8 +104,8 @@
* Using LZMA SDK 9.10 (public domain) from Igor Pavlov.
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
man page after installation. (Installing compressed docs may become
the default in the future).
man page after installation.
(Installing compressed docs may become the default in the future).
You can install only the program or the man page by typing 'make
install-bin' or 'make install-man' respectively.
You can install only the program or the man page by typing
'make install-bin' or 'make install-man' respectively.
Instead of 'make install', you can type 'make install-as-lzip' to
install the program and any data files and documentation, and link
@ -55,10 +55,10 @@ the main archive.
Another way
-----------
You can also compile pdlzip 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
@ -69,7 +69,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

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

34
NEWS
View file

@ -1,14 +1,30 @@
Changes in version 1.10:
Changes in version 1.11:
Compression level '-0' now uses a dictionary size of 64 KiB instead of
1 MiB.
Pdlzip now reports an error if a file name is empty (pdlzip -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:
pdlzip -o foo.lz - bar < foo
must now be split into:
pdlzip -o foo.lz - < foo
pdlzip bar
or rewritten as:
pdlzip - bar < foo > foo.lz
Pdlzip now compiles on DOS with DJGPP. (Patch from Robert Riebisch).
When using '-c' or '-o', pdlzip now checks whether the output is a terminal
only once.
The configure script now accepts appending options to CFLAGS using the
syntax 'CFLAGS+=OPTIONS'.
Pdlzip now does not even open the output file if the input file is a terminal.
It has been documented in INSTALL the use of
CFLAGS+='-D __USE_MINGW_ANSI_STDIO' when compiling on MinGW.
It is now an error to specify two different operations in the command line
(--decompress and --test).
The words 'decompressed' and 'compressed' have been replaced with the
shorter 'out' and 'in' in the verbose output when decompressing or testing.
The commands needed to extract files from a tar.lz archive have been
documented in the output of '--help' and in the man page.
9 new test files have been added to the testsuite.

52
README
View file

@ -6,37 +6,39 @@ licensed Free Software. (The name of pdlzip comes from 'public domain
lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4
or newer.
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.
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.
Pdlzip is also able to decompress legacy lzma-alone (.lzma) files.
Lzma-alone is a very bad format; it is essentially a raw LZMA stream.
@ -44,8 +46,8 @@ If you keep any lzma-alone files, it is advisable to recompress them to
lzip format. Lziprecover can convert some lzma-alone files to lzip format
without recompressing.
Pdlzip includes public domain (de)compression code from the LZMA SDK
(Software Development Kit) written by Igor Pavlov.
Pdlzip includes public domain compression/decompression code from the LZMA
SDK (Software Development Kit) written by Igor Pavlov.
I would not write non-copylefted software unless it is too simple to be
worth copylefting it, but one of the uses of the lzip format is the
@ -54,10 +56,10 @@ users of the most non-free platforms can share lzip files with everybody
else.
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,15 +1,15 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2019 Antonio Diaz Diaz.
Copyright (C) 2006-2021 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
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.
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
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,

View file

@ -1,15 +1,15 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2019 Antonio Diaz Diaz.
Copyright (C) 2006-2021 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
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.
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
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,
@ -18,7 +18,7 @@
*/
/* Arg_parser reads the arguments in 'argv' and creates a number of
option codes, option arguments and non-option arguments.
option codes, option arguments, and non-option arguments.
In case of error, 'ap_error' returns a non-null pointer to an error
message.
@ -79,10 +79,10 @@ 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.
/* 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 );

25
configure vendored
View file

@ -1,12 +1,12 @@
#! /bin/sh
# configure script for Pdlzip - 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=pdlzip
pkgversion=1.10
pkgversion=1.11
progname=pdlzip
srctrigger=doc/${progname}.1
@ -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 Pdlzip - 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,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
.TH PDLZIP "1" "January 2019" "pdlzip 1.10" "User Commands"
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
.TH PDLZIP "1" "January 2021" "pdlzip 1.11" "User Commands"
.SH NAME
pdlzip \- reduces the size of files
.SH SYNOPSIS
@ -12,13 +12,15 @@ licensed Free Software. (The name of pdlzip comes from 'public domain
lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4
or newer.
.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.
.PP
Pdlzip is also able to decompress legacy lzma\-alone (.lzma) files.
Lzma\-alone is a very bad format; it is essentially a raw LZMA stream.
@ -55,7 +57,7 @@ keep (don't delete) input files
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
@ -90,20 +92,26 @@ to 2^27 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. For example, \fB\-9m64\fR
usually compresses executables more (and faster) than \fB\-9\fR.
etc, you may need to use the options \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR
directly to achieve optimal performance. For example, \fB\-9m64\fR usually
compresses executables more (and faster) than \fB\-9\fR.
.PP
To extract all the files from archive 'foo.tar.lz', use the commands
\&'tar \fB\-xf\fR foo.tar.lz' or 'pdlzip \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 pdlzip to panic.
.PP
Pdlzip includes public domain compression/decompression code from the LZMA
SDK (Software Development Kit) written by Igor Pavlov.
.SH "REPORTING BUGS"
Report bugs to lzip\-bug@nongnu.org
.br
Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html
.SH COPYRIGHT
Copyright \(co 2019 Antonio Diaz Diaz.
Copyright \(co 2021 Antonio Diaz Diaz.
Public Domain 2009 Igor Pavlov.
License 2\-clause BSD.
.br

86
lzip.h
View file

@ -1,15 +1,15 @@
/* Pdlzip - LZMA lossless data compressor
Copyright (C) 2010-2019 Antonio Diaz Diaz.
Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program 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.
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
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This program is distributed in the hope that it will be useful,
@ -20,17 +20,12 @@
#ifndef max
#define max(x,y) ((x) >= (y) ? (x) : (y))
#endif
#ifndef min
#define min(x,y) ((x) <= (y) ? (x) : (y))
#endif
void * resize_buffer( void * buf, const unsigned min_size );
typedef int State;
enum {
min_dictionary_bits = 12,
min_dictionary_size = 1 << min_dictionary_bits,
min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */
max_dictionary_bits = 29,
max_dictionary_size = 1 << max_dictionary_bits,
max_dictionary_bits_c = 27, /* kDicLogSizeMaxCompress */
@ -52,65 +47,6 @@ enum {
min_match_len_limit = 5 };
/* 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;
@ -157,7 +93,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 )
@ -251,19 +187,17 @@ static inline void Lt_set_member_size( Lzip_trailer data, unsigned long long sz
{ int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } }
static inline void set_retval( int * retval, const int new_val )
{ if( *retval < new_val ) *retval = new_val; }
static const char * const trailing_msg = "Trailing data not allowed.";
static const char * const mem_msg = "Not enough memory.";
/* defined in main.c */
extern int verbosity;
int readblock( const int fd, uint8_t * const buf, const int size );
int writeblock( const int fd, const uint8_t * const buf, const int size );
/* defined in main.c */
void cleanup_and_fail( const int retval );
void show_error( const char * const msg, const int errcode, const bool help );
void show_file_error( const char * const filename, const char * const msg,
const int errcode );
void internal_error( const char * const msg );
#define SZ_OK 0
#define SZ_ERROR_READ 8

396
main.c
View file

@ -1,16 +1,16 @@
/* Pdlzip - LZMA lossless data compressor
2009-08-14 : Igor Pavlov : Public domain
Copyright (C) 2010-2019 Antonio Diaz Diaz.
Copyright (C) 2010-2021 Antonio Diaz Diaz.
This program 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.
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
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This program is distributed in the hope that it will be useful,
@ -72,12 +72,18 @@
#endif
int verbosity = 0;
static void cleanup_and_fail( const int retval );
static void show_error( const char * const msg, const int errcode,
const bool help );
static void show_file_error( const char * const filename,
const char * const msg, const int errcode );
static void internal_error( const char * const msg );
const char * const program_name = "pdlzip";
const char * const program_year = "2019";
const char * invocation_name = 0;
static const char * const program_name = "pdlzip";
static const char * const program_year = "2021";
static const char * invocation_name = "pdlzip"; /* 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" },
{ ".lzma", "" },
@ -93,9 +99,9 @@ enum Mode { m_compress, m_decompress, m_test };
/* Variables used in signal handler context.
They are not declared volatile because the handler never returns. */
char * output_filename = 0;
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 )
@ -105,13 +111,15 @@ static void show_help( void )
"licensed Free Software. (The name of pdlzip comes from 'public domain\n"
"lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4\n"
"or newer.\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"
"\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"
"\nPdlzip is also able to decompress legacy lzma-alone (.lzma) files.\n"
"Lzma-alone is a very bad format; it is essentially a raw LZMA stream.\n"
"If you keep any lzma-alone files, it is advisable to recompress them to\n"
@ -128,7 +136,7 @@ static void show_help( void )
" -F, --recompress force re-compression of compressed files\n"
" -k, --keep keep (don't delete) input files\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"
" -t, --test test compressed file integrity\n"
@ -137,7 +145,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 '-', pdlzip compresses or\n"
"\nIf no file names are given, or if a file is '-', pdlzip 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"
@ -145,13 +153,17 @@ static void show_help( void )
"to 2^27 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. For example, -9m64\n"
"usually compresses executables more (and faster) than -9.\n"
"etc, you may need to use the options --dictionary-size and --match-length\n"
"directly to achieve optimal performance. For example, -9m64 usually\n"
"compresses executables more (and faster) than -9.\n"
"\nTo extract all the files from archive 'foo.tar.lz', use the commands\n"
"'tar -xf foo.tar.lz' or 'pdlzip -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 pdlzip to panic.\n"
"\nPdlzip includes public domain compression/decompression code from the LZMA\n"
"SDK (Software Development Kit) written by Igor Pavlov.\n"
"\nReport bugs to lzip-bug@nongnu.org\n"
"Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" );
}
@ -169,20 +181,69 @@ static void show_version( void )
/* assure at least a minimum size for buffer 'buf' */
void * resize_buffer( void * buf, const unsigned min_size )
static 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;
}
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
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; }
static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
{
if( verbosity >= 0 )
{
@ -210,7 +271,7 @@ static void show_header( const unsigned dictionary_size )
int i; for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false;
p = prefix[i]; np = ""; }
fprintf( stderr, "dictionary %s%4u %sB, ", np, num, p );
fprintf( stderr, "dict %s%4u %sB, ", np, num, p );
}
@ -277,6 +338,17 @@ static int get_dict_size( const char * const arg )
}
static void set_mode( enum Mode * const program_modep, const enum Mode new_mode )
{
if( *program_modep != m_compress && *program_modep != new_mode )
{
show_error( "Only one operation can be specified.", 0, true );
exit( 1 );
}
*program_modep = new_mode;
}
static int extension_index( const char * const name )
{
int eindex;
@ -293,12 +365,16 @@ static int extension_index( const char * const name )
}
static void set_c_outname( const char * const name, const bool force_ext )
static void set_c_outname( const char * const name, const bool filenames_given,
const bool force_ext )
{
/* 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 ) +
strlen( known_extensions[0].from ) + 1 );
strcpy( output_filename, name );
if( force_ext || extension_index( output_filename ) < 0 )
if( force_ext ||
( !filenames_given && extension_index( output_filename ) < 0 ) )
strcat( output_filename, known_extensions[0].from );
}
@ -330,7 +406,7 @@ static void set_d_outname( const char * const name, const int eindex )
static int open_instream( 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 )
{
int infd = -1;
if( program_mode == m_compress && !recompress && eindex >= 0 )
@ -351,14 +427,12 @@ static int open_instream( const char * const name, struct stat * const in_statsp
const bool can_read = ( i == 0 &&
( S_ISBLK( mode ) || S_ISCHR( mode ) ||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
const bool no_ofile = ( to_stdout || program_mode == m_test );
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;
}
@ -368,11 +442,11 @@ static int open_instream( const char * const name, struct stat * const in_statsp
}
static bool open_outstream( const bool force, const bool from_stdin )
static bool open_outstream( const bool force, const bool protect )
{
const mode_t usr_rw = S_IRUSR | S_IWUSR;
const mode_t 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;
@ -391,25 +465,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 );
@ -418,7 +473,7 @@ static void set_signals( void (*action)(int) )
}
void cleanup_and_fail( const int retval )
static void cleanup_and_fail( const int retval )
{
set_signals( SIG_IGN ); /* ignore signals */
if( delete_output_on_interrupt )
@ -435,7 +490,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 );
@ -443,7 +498,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;
@ -509,6 +588,28 @@ static int compress( const struct Lzma_options * const encoder_options,
}
static void show_results( const long long data_size,
const long long member_size, const unsigned crc,
const unsigned dictionary_size, const bool lzip_mode )
{
if( verbosity >= 2 )
{
if( verbosity >= 4 ) show_header( dictionary_size );
if( data_size == 0 || member_size == 0 )
fputs( "no data compressed. ", stderr );
else
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 && lzip_mode ) fprintf( stderr, "CRC %08X, ", crc );
if( verbosity >= 3 )
fprintf( stderr, "%9llu out, %8llu in. ", data_size, member_size );
if( !lzip_mode ) fputs( "lzma-alone, ", stderr );
}
}
#define IN_BUF_SIZE (1 << 16)
#define OUT_BUF_SIZE (1 << 16)
@ -584,21 +685,7 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd,
if( ( thereIsSize && unpackSize != 0 ) ||
( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) )
{ show_error( "Data error.", 0, false ); return 2; }
if( verbosity >= 2 )
{
if( verbosity >= 4 ) show_header( dictionary_size );
if( data_size == 0 || member_size == 0 )
fputs( "no data compressed. ", stderr );
else
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 >= 3 )
fprintf( stderr, "decompressed %9llu, compressed %8llu. ",
data_size, member_size );
fputs( "lzma-alone, ", stderr );
}
show_results( data_size, member_size, 0, dictionary_size, false );
if( verbosity >= 1 )
fputs( testing ? "(apparently) ok\n" : "(apparently) done\n", stderr );
return 0;
@ -705,21 +792,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
}
}
if( error ) return 2;
if( verbosity >= 2 )
{
if( verbosity >= 4 ) show_header( dictionary_size );
if( data_size == 0 || member_size == 0 )
fputs( "no data compressed. ", stderr );
else
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 );
}
show_results( data_size, member_size, td_crc, dictionary_size, true );
return 0;
}
}
@ -742,7 +815,7 @@ static int decompress( const int infd, struct Pretty_print * const pp,
for( first_member = true; ; first_member = false )
{
int i, size;
unsigned dictionary_size;
unsigned dictionary_size = 0; /* keep gcc 3.3.6 happy */
Lzip_header header;
if( inSize - inPos < lzma_header_size &&
!read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1;
@ -819,7 +892,7 @@ static int decompress( const int infd, struct Pretty_print * const pp,
Pp_show_msg( pp, 0 );
if( !LzmaDec_Init( &decoder, raw_props ) )
{ Pp_show_msg( pp, "Not enough memory." ); return 1; }
{ Pp_show_msg( pp, mem_msg ); return 1; }
if( lzip_mode )
retval = lzip_decode( &decoder, infd, pp, inBuf, &inPos, &inSize,
dictionary_size );
@ -877,7 +950,8 @@ int writeblock( const int fd, const uint8_t * const buf, const int size )
}
void show_error( const char * const msg, const int errcode, const bool help )
static void show_error( const char * const msg, const int errcode,
const bool help )
{
if( verbosity < 0 ) return;
if( msg && msg[0] )
@ -890,8 +964,8 @@ void show_error( const char * const msg, const int errcode, const bool help )
}
void show_file_error( const char * const filename, const char * const msg,
const int errcode )
static void show_file_error( const char * const filename,
const char * const msg, const int errcode )
{
if( verbosity >= 0 )
fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg,
@ -900,7 +974,7 @@ void show_file_error( const char * const filename, const char * const msg,
}
void internal_error( const char * const msg )
static void internal_error( const char * const msg )
{
if( verbosity >= 0 )
fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
@ -926,7 +1000,9 @@ int main( const int argc, const char * const argv[] )
{ 1 << 25, 273 } }; /* -9 */
struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */
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;
@ -941,7 +1017,6 @@ int main( const int argc, const char * const argv[] )
bool recompress = false;
bool stdin_used = false;
bool to_stdout = false;
struct Pretty_print pp;
enum { opt_lt = 256 };
const struct ap_Option options[] =
@ -974,15 +1049,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; }
@ -999,7 +1072,7 @@ int main( const int argc, const char * const argv[] )
case 'a': ignore_trailing = false; break;
case 'b': break;
case 'c': to_stdout = true; break;
case 'd': program_mode = m_decompress; break;
case 'd': set_mode( &program_mode, m_decompress ); break;
case 'f': force = true; break;
case 'F': recompress = true; break;
case 'h': show_help(); return 0;
@ -1007,12 +1080,13 @@ int main( const int argc, const char * const argv[] )
case 'm': encoder_options.match_len_limit =
getnum( arg, min_match_len_limit, max_match_len ); 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 );
break;
case 'S': break;
case 't': program_mode = m_test; break;
case 't': set_mode( &program_mode, m_test ); break;
case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0;
case opt_lt: loose_trailing = true; break;
@ -1035,16 +1109,23 @@ int main( const int argc, const char * const argv[] )
if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true;
}
if( program_mode == m_test )
outfd = -1;
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 )
{
const char * input_filename = "";
@ -1052,96 +1133,71 @@ 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 );
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_instream( input_filename, &in_stats, program_mode,
eindex, recompress, to_stdout );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
if( program_mode != m_test )
{
if( to_stdout ) outfd = STDOUT_FILENO;
else
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( program_mode == m_compress )
set_c_outname( input_filename, true );
set_c_outname( input_filename, true, true );
else set_d_outname( input_filename, eindex );
if( !open_outstream( force, false ) )
{
if( retval < 1 ) retval = 1;
close( infd );
continue;
}
}
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 );
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;
in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0;
if( program_mode == m_compress )
tmp = compress( &encoder_options, &pp, infd );
else
tmp = decompress( 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 )
if( input_filename[0] && !keep_input_files && one_to_one )
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 Pdlzip - 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)" ; }
@ -56,8 +58,20 @@ 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
# these are for code coverage
"${LZIP}" -t -- nx_file 2> /dev/null
"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null
[ $? = 1 ] || test_failed $LINENO
"${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
@ -81,15 +95,22 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null
printf "\ntesting decompression..."
"${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}" "${testdir}"/test.txt.lzma ; do
"${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
"${LZIP}" -t "${testdir}"/test.txt.lzma || test_failed $LINENO
"${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || test_failed $LINENO
cmp in copy || test_failed $LINENO
lines=$("${LZIP}" -tvv "${in_em}" 2>&1 | wc -l) || test_failed $LINENO
[ "${lines}" -eq 8 ] || 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
@ -100,19 +121,21 @@ printf "to be overwritten" > copy || framework_failure
[ ! -e copy.lz ] || test_failed $LINENO
cmp in copy || test_failed $LINENO
rm -f copy || framework_failure
cat "${in_lz}" > copy.lz || framework_failure
"${LZIP}" -d -S100k copy.lz || test_failed $LINENO # ignore -S
[ ! -e copy.lz ] || test_failed $LINENO
cmp in copy || test_failed $LINENO
printf "to be overwritten" > copy || framework_failure
"${LZIP}" -d -o copy < "${in_lz}" 2> /dev/null
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO
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}" -s16 < 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
@ -147,19 +170,18 @@ done
cmp in copy || test_failed $LINENO
cat in in > in2 || framework_failure
cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure
"${LZIP}" -t in2.lz || test_failed $LINENO
"${LZIP}" -cd in2.lz > copy2 || 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}" -s16 --output=copy2.lz < in2 || 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}" -atq copy2.lz
[ $? = 2 ] || test_failed $LINENO
"${LZIP}" -atq < copy2.lz
@ -179,37 +201,46 @@ printf "\ntesting compression..."
"${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2
[ $? = 1 ] || test_failed $LINENO
"${LZIP}" -cFvvm36 -s16 "${in_lz}" > out 2> /dev/null || test_failed $LINENO
"${LZIP}" -Fvvm36 -o - -s16 "${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 -s16 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 -s16 in > out || test_failed $LINENO $i
"${LZIP}" -$i -s16 in -c > out || test_failed $LINENO $i
"${LZIP}" -$i -s16 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 -s16 < 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 -s16 -o out < in || test_failed $LINENO $i
rm -f out || framework_failure
printf "to be overwritten" > out.lz || framework_failure
"${LZIP}" -f -$i -s16 -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
printf "\ntesting bad input..."
@ -258,6 +289,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
@ -280,13 +326,21 @@ rm -f in2.lz in3.lz trunc.lz out || framework_failure
cat "${in_lz}" > ingin.lz || framework_failure
printf "g" >> ingin.lz || framework_failure
cat "${in_lz}" >> ingin.lz || framework_failure
"${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.