Compare commits
No commits in common. "4a3010ccc62d0f08b826abe36a5c2411d03581f2" and "08fc35fa3451d074a42c5fc3065ff0469f0c3a8b" have entirely different histories.
4a3010ccc6
...
08fc35fa34
31 changed files with 885 additions and 1237 deletions
3
COPYING
3
COPYING
|
@ -1,7 +1,8 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
|
66
ChangeLog
66
ChangeLog
|
@ -1,70 +1,13 @@
|
|||
2025-01-06 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.9 released.
|
||||
* main.c (decompress): Return 2 if empty member in multimember file.
|
||||
(Pp_free): New function.
|
||||
* lzip_decompress.c (Rd_load): Check first byte of the LZMA stream.
|
||||
* check.sh: Use 'cp' instead of 'cat'.
|
||||
|
||||
2024-01-18 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.8 released.
|
||||
* main.c: Reformat file diagnostics as 'PROGRAM: FILE: MESSAGE'.
|
||||
(getnum): Show option name and valid range if error.
|
||||
(show_option_error): New function showing argument and option name.
|
||||
(main): Make -o preserve date/mode/owner if 1 input file.
|
||||
* lzip.h: Rename verify_* to check_*.
|
||||
* configure, Makefile.in: New variable 'MAKEINFO'.
|
||||
* INSTALL: Document use of CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500'.
|
||||
|
||||
2021-01-01 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.7 released.
|
||||
* main.c (main): Do not open output if input is a terminal.
|
||||
|
||||
2020-06-24 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.6 released.
|
||||
* Make '-o' behave like '-c', but writing to file instead of stdout.
|
||||
* in_place.c: Multimember decompression should now work for any file
|
||||
that fits in memory and is smaller than (LONG_MAX - extra_bytes).
|
||||
* README: Add an analysis of the in-place decompression.
|
||||
|
||||
2020-04-27 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.5 released.
|
||||
* lzip_decompress module updated to version 5.4.18.
|
||||
* main.c (main): Report an error if a file name is empty.
|
||||
* Replace 'decompressed', 'compressed' with 'out', 'in' in output.
|
||||
* Decompression speed has been slightly increased.
|
||||
* Fix a compilation error with GCC 10. (Reported by Daniel Baumann).
|
||||
* main.c: Set a valid invocation_name even if argc == 0.
|
||||
* Document extraction from tar.lz in '--help' output and man page.
|
||||
* main.c: Compile on DOS with DJGPP.
|
||||
* configure: Accept appending to CFLAGS; 'CFLAGS+=OPTIONS'.
|
||||
* testsuite: Add 9 new test files.
|
||||
|
||||
2018-09-18 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.4 released.
|
||||
* lzip_decompress module updated to version 4.18.1-2.
|
||||
* lzip.c: Rename to lzip_decompress.c.
|
||||
* lzip_decompress.c (LZd_init): Fix a warning on 32 bit systems.
|
||||
* in_place.c (set_file_sizes): Skip trailing zeros efficiently.
|
||||
* main.c (main): Check return value of close( infd ).
|
||||
* INSTALL: Document use of '-D __USE_MINGW_ANSI_STDIO'.
|
||||
|
||||
2018-07-10 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.3 released.
|
||||
* lzip_decompress module updated to version 4.14.40-3.
|
||||
* lzip.c: Use a precalculated CRC table as lzlib does.
|
||||
|
||||
2018-07-09 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 0.2 released.
|
||||
* lzip_decompress module updated to version 4.14.40-2.
|
||||
* Improve corrupt header detection to HD=3.
|
||||
* Improved corrupt header detection to HD=3.
|
||||
* --in-place now works with both --decompress and --test.
|
||||
* main.c: Show final diagnostic when testing multiple files.
|
||||
|
||||
|
@ -75,7 +18,8 @@
|
|||
* Tests the code shipped in linux patches before june 2018.
|
||||
|
||||
|
||||
Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
Copyright (C) 2016-2018 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 modify it.
|
||||
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
|
||||
modify it.
|
||||
|
|
50
INSTALL
50
INSTALL
|
@ -1,14 +1,9 @@
|
|||
Requirements
|
||||
------------
|
||||
You will need a C99 compiler. (gcc 3.3.6 or newer is recommended).
|
||||
I use gcc 6.1.0 and 3.3.6, but the code should compile with any standards
|
||||
compliant compiler.
|
||||
Gcc is available at http://gcc.gnu.org
|
||||
Lzip is available at http://www.nongnu.org/lzip/lzip.html
|
||||
|
||||
The operating system must allow signal handlers read access to objects with
|
||||
static storage duration so that the cleanup handler for Control-C can delete
|
||||
the partial output file.
|
||||
You will need a C compiler.
|
||||
I use gcc 5.3.0 and 4.1.2, but the code should compile with any
|
||||
standards compliant compiler.
|
||||
Gcc is available at http://gcc.gnu.org.
|
||||
|
||||
|
||||
Procedure
|
||||
|
@ -19,8 +14,8 @@ Procedure
|
|||
or
|
||||
lzip -cd xlunzip[version].tar.lz | tar -xf -
|
||||
|
||||
This creates the directory ./xlunzip[version] containing the source code
|
||||
extracted from the archive.
|
||||
This creates the directory ./xlunzip[version] containing the source from
|
||||
the main archive.
|
||||
|
||||
2. Change to xlunzip directory and run configure.
|
||||
(Try 'configure --help' for usage instructions).
|
||||
|
@ -28,14 +23,6 @@ extracted from the archive.
|
|||
cd xlunzip[version]
|
||||
./configure
|
||||
|
||||
If you choose a C standard, enable the POSIX features explicitly:
|
||||
|
||||
./configure CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500'
|
||||
|
||||
If you are compiling on MinGW, use:
|
||||
|
||||
./configure CFLAGS+='-D __USE_MINGW_ANSI_STDIO'
|
||||
|
||||
3. Run make.
|
||||
|
||||
make
|
||||
|
@ -43,15 +30,14 @@ extracted from the archive.
|
|||
4. Optionally, type 'make check' to run the tests that come with xlunzip.
|
||||
|
||||
5. Type 'make install' to install the program and any data files and
|
||||
documentation. You need root privileges to install into a prefix owned
|
||||
by root.
|
||||
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
|
||||
|
@ -61,21 +47,21 @@ extracted from the archive.
|
|||
Another way
|
||||
-----------
|
||||
You can also compile xlunzip into a separate directory.
|
||||
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
|
||||
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
|
||||
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 look
|
||||
for the source code. Usually 'configure' can determine that directory
|
||||
'configure' recognizes the option '--srcdir=DIR' to control where to
|
||||
look for the sources. Usually 'configure' can determine that directory
|
||||
automatically.
|
||||
|
||||
After running 'configure', you can run 'make' and 'make install' as
|
||||
explained above.
|
||||
|
||||
|
||||
Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
Copyright (C) 2016-2018 Antonio Diaz Diaz.
|
||||
|
||||
This file is free documentation: you have unlimited permission to copy,
|
||||
distribute, and modify it.
|
||||
distribute and modify it.
|
||||
|
|
26
Makefile.in
26
Makefile.in
|
@ -2,12 +2,12 @@
|
|||
DISTNAME = $(pkgname)-$(pkgversion)
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL) -m 755
|
||||
INSTALL_DIR = $(INSTALL) -d -m 755
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
INSTALL_DIR = $(INSTALL) -d -m 755
|
||||
SHELL = /bin/sh
|
||||
CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1
|
||||
|
||||
objs = carg_parser.o decompress_lunzip.o in_place.o lzip_decompress.o main.o
|
||||
objs = carg_parser.o decompress_lunzip.o in_place.o lzip.o main.o
|
||||
|
||||
|
||||
.PHONY : all install install-bin install-info install-man \
|
||||
|
@ -20,7 +20,7 @@ objs = carg_parser.o decompress_lunzip.o in_place.o lzip_decompress.o main.o
|
|||
all : $(progname)
|
||||
|
||||
$(progname) : $(objs)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(objs)
|
||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(objs)
|
||||
|
||||
main.o : main.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $<
|
||||
|
@ -28,29 +28,25 @@ main.o : main.c
|
|||
%.o : %.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
# prevent 'make' from trying to remake source files
|
||||
$(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ;
|
||||
MAKEFLAGS += -r
|
||||
.SUFFIXES :
|
||||
|
||||
$(objs) : Makefile
|
||||
carg_parser.o : carg_parser.h
|
||||
decompress_lunzip.o : linux_lzip.h linux_lunzip.h linux_mm.h lzip_decompress.c
|
||||
decompress_lunzip.o : linux_lzip.h linux_lunzip.h linux_mm.h lzip.c
|
||||
in_place.o : linux_lunzip.h lzip.h
|
||||
lzip_decompress.o : linux_module.h linux_lzip.h linux_mm.h
|
||||
lzip.o : linux_lzip.h linux_mm.h
|
||||
main.o : carg_parser.h linux_lzip.h linux_lunzip.h lzip.h
|
||||
|
||||
|
||||
doc : man
|
||||
|
||||
info : $(VPATH)/doc/$(pkgname).info
|
||||
|
||||
$(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texi
|
||||
cd $(VPATH)/doc && $(MAKEINFO) $(pkgname).texi
|
||||
cd $(VPATH)/doc && makeinfo $(pkgname).texi
|
||||
|
||||
man : $(VPATH)/doc/$(progname).1
|
||||
|
||||
$(VPATH)/doc/$(progname).1 : $(progname)
|
||||
help2man -n 'test tool for the lzip_decompress linux module' -o $@ --no-info ./$(progname)
|
||||
help2man -n 'test tool for the lunzip linux module' -o $@ --no-info ./$(progname)
|
||||
|
||||
Makefile : $(VPATH)/configure $(VPATH)/Makefile.in
|
||||
./config.status
|
||||
|
@ -123,10 +119,8 @@ dist : doc
|
|||
$(DISTNAME)/*.c \
|
||||
$(DISTNAME)/testsuite/check.sh \
|
||||
$(DISTNAME)/testsuite/test.txt \
|
||||
$(DISTNAME)/testsuite/em.lz \
|
||||
$(DISTNAME)/testsuite/fox.lz \
|
||||
$(DISTNAME)/testsuite/fox_*.lz \
|
||||
$(DISTNAME)/testsuite/test.txt.lz
|
||||
$(DISTNAME)/testsuite/test.txt.lz \
|
||||
$(DISTNAME)/testsuite/zero.lz
|
||||
rm -f $(DISTNAME)
|
||||
lzip -v -9 $(DISTNAME).tar
|
||||
|
||||
|
|
14
NEWS
14
NEWS
|
@ -1,7 +1,11 @@
|
|||
Changes in version 0.9:
|
||||
Changes in version 0.3:
|
||||
|
||||
xlunzip now exits with error status 2 if any empty member is found in a
|
||||
multimember file.
|
||||
lzip_decompress module updated to version 4.14.40-3.
|
||||
|
||||
xlunzip now exits with error status 2 if the first byte of the LZMA stream
|
||||
is not 0.
|
||||
Use a precalculated CRC table as lzlib does.
|
||||
|
||||
Improved corrupt header detection to HD=3.
|
||||
|
||||
'--in-place' now works with both '--decompress' and '--test'.
|
||||
|
||||
Show final diagnostic when testing multiple files.
|
||||
|
|
118
README
118
README
|
@ -1,25 +1,24 @@
|
|||
See the file INSTALL for compilation and installation instructions.
|
||||
|
||||
Description
|
||||
|
||||
Xlunzip is a test tool for the lzip decompression code of my lzip patch for
|
||||
linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress linux
|
||||
module as a backend. Xlunzip tests the module for stream, buffer-to-buffer,
|
||||
and mixed decompression modes, including in-place decompression (using the
|
||||
same buffer for input and output). You can use xlunzip to check that the
|
||||
module produces correct results when decompressing single member files,
|
||||
multimember files, or the concatenation of two or more compressed files.
|
||||
Xlunzip can be used with unzcrash to test the robustness of the module to
|
||||
the decompression of corrupted data.
|
||||
Xlunzip is a test tool for the lzip decompression code of my lzip patch
|
||||
for linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress
|
||||
linux module as a backend. Xlunzip tests the module for stream,
|
||||
buffer-to-buffer and mixed decompression modes, including in-place
|
||||
decompression (using the same buffer for input and output). You can use
|
||||
xlunzip to verify that the module produces correct results when
|
||||
decompressing single member files, multimember files, or the
|
||||
concatenation of two or more compressed files. Xlunzip can be used with
|
||||
unzcrash to test the robustness of the module to the decompression of
|
||||
corrupted data.
|
||||
|
||||
The distributed index feature of the lzip format allows xlunzip to
|
||||
decompress concatenated files in place. This can't be guaranteed to work
|
||||
with formats like gzip or bzip2 because they can't detect whether a high
|
||||
compression ratio in the first members of the multimember data is being
|
||||
masked by a low compression ratio in the last members.
|
||||
Note that the in-place decompression of concatenated files can't be
|
||||
guaranteed to work because an arbitrarily low compression ratio of the
|
||||
last part of the data can be achieved by appending enough empty
|
||||
compressed members to a file.
|
||||
|
||||
The xlunzip tarball contains a copy of the lzip_decompress module and can be
|
||||
compiled and tested without downloading or applying the patch to the kernel.
|
||||
The xlunzip tarball contains a copy of the lzip_decompress module and
|
||||
can be compiled and tested without downloading or applying the patch to
|
||||
the kernel.
|
||||
|
||||
My lzip patch for linux can be found at
|
||||
http://download.savannah.gnu.org/releases/lzip/kernel/
|
||||
|
@ -27,87 +26,22 @@ http://download.savannah.gnu.org/releases/lzip/kernel/
|
|||
Lzip related components in the kernel
|
||||
=====================================
|
||||
|
||||
The lzip_decompress module in lib/lzip_decompress.c provides a versatile
|
||||
lzip decompression function able to do buffer-to-buffer decompression or
|
||||
stream decompression with fill and flush callback functions. The usage of
|
||||
the function is documented in include/linux/lzip.h.
|
||||
The lzip_decompress module in lib/lzip.c provides a versatile lzip
|
||||
decompression function able to do buffer to buffer decompression or
|
||||
stream decompression with fill and flush callback functions. The usage
|
||||
of the function is documented in include/linux/lzip.h.
|
||||
|
||||
For decompressing the kernel image, initramfs, and initrd, there is a
|
||||
wrapper function in lib/decompress_lunzip.c providing the same common
|
||||
interface as the other decompress_*.c files, which is defined in
|
||||
include/linux/decompress/generic.h.
|
||||
|
||||
Analysis of the in-place decompression
|
||||
======================================
|
||||
|
||||
In order to decompress the kernel in place (using the same buffer for input
|
||||
and output), the compressed data is placed at the end of the buffer used to
|
||||
hold the decompressed data. The buffer must be large enough to contain after
|
||||
the decompressed data extra space for a marker, a trailer, the maximum
|
||||
possible data expansion, and (if the compressed data consists of more than
|
||||
one member) N-1 empty members.
|
||||
|
||||
|------ compressed data ------|
|
||||
V V
|
||||
|----------------|-------------------|---------|
|
||||
^ ^ extra
|
||||
|-------- decompressed data ---------|
|
||||
|
||||
The input pointer initially points to the beginning of the compressed data
|
||||
and the output pointer initially points to the beginning of the buffer.
|
||||
Decompressing compressible data reduces the distance between the pointers,
|
||||
while decompressing uncompressible data increases the distance. The extra
|
||||
space must be large enough that the output pointer does not overrun the
|
||||
input pointer even if all the overlap between compressed and decompressed
|
||||
data is uncompressible. The worst case is very compressible data followed by
|
||||
uncompressible data because in this case the output pointer increases faster
|
||||
when the input pointer is smaller.
|
||||
|
||||
| * <-- input pointer (*)
|
||||
| * , <-- output pointer (,)
|
||||
| * , '
|
||||
| x ' <-- overrun (x)
|
||||
memory | * ,'
|
||||
address | * ,'
|
||||
|* ,'
|
||||
| ,'
|
||||
| ,'
|
||||
|,'
|
||||
'--------------------------
|
||||
time
|
||||
|
||||
All we need to know to calculate the minimum required extra space is:
|
||||
The maximum expansion ratio.
|
||||
The size of the last part of a member required to check integrity.
|
||||
For multimember data, the overhead per member. (36 bytes for lzip).
|
||||
|
||||
The maximum expansion ratio of LZMA data is of about 1.4%. Rounding this up
|
||||
to 1/64 (1.5625%) and adding 36 bytes per input member, the extra space
|
||||
required to decompress lzip data in place is:
|
||||
|
||||
extra_bytes = ( compressed_size >> 6 ) + members * 36
|
||||
|
||||
Using the compressed size to calculate the extra_bytes (as in the formula
|
||||
above) may slightly overestimate the amount of space required in the worst
|
||||
case (maximum expansion). But calculating the extra_bytes from the
|
||||
uncompressed size (as does linux currently) is wrong (and inefficient for
|
||||
high compression ratios). The formula used in arch/x86/boot/header.S:
|
||||
|
||||
extra_bytes = ( uncompressed_size >> 8 ) + 131072
|
||||
|
||||
fails to decompress 1 MB of zeros followed by 8 MB of random data, wastes
|
||||
memory for compression ratios larger than 4:1, and does not even consider
|
||||
multimember data.
|
||||
|
||||
|
||||
Xlunzip uses Arg_parser for command-line argument parsing:
|
||||
http://www.nongnu.org/arg-parser/arg_parser.html
|
||||
|
||||
|
||||
Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
Copyright (C) 2016-2018 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 itself.
|
||||
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
|
||||
itself.
|
||||
|
|
168
carg_parser.c
168
carg_parser.c
|
@ -1,15 +1,15 @@
|
|||
/* Arg_parser - POSIX/GNU command-line argument parser. (C version)
|
||||
Copyright (C) 2006-2025 Antonio Diaz Diaz.
|
||||
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||
Copyright (C) 2006-2018 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,
|
||||
|
@ -32,46 +32,28 @@ static void * ap_resize_buffer( void * buf, const int min_size )
|
|||
}
|
||||
|
||||
|
||||
static char push_back_record( Arg_parser * const ap, const int code,
|
||||
const char * const long_name,
|
||||
const char * const argument )
|
||||
{
|
||||
ap_Record * p;
|
||||
void * tmp = ap_resize_buffer( ap->data,
|
||||
( ap->data_size + 1 ) * sizeof (ap_Record) );
|
||||
if( !tmp ) return 0;
|
||||
ap->data = (ap_Record *)tmp;
|
||||
p = &(ap->data[ap->data_size]);
|
||||
p->code = code;
|
||||
if( long_name )
|
||||
{
|
||||
const int len = strlen( long_name );
|
||||
p->parsed_name = (char *)malloc( len + 2 + 1 );
|
||||
if( !p->parsed_name ) return 0;
|
||||
p->parsed_name[0] = p->parsed_name[1] = '-';
|
||||
strncpy( p->parsed_name + 2, long_name, len + 1 );
|
||||
}
|
||||
else if( code > 0 && code < 256 )
|
||||
{
|
||||
p->parsed_name = (char *)malloc( 2 + 1 );
|
||||
if( !p->parsed_name ) return 0;
|
||||
p->parsed_name[0] = '-'; p->parsed_name[1] = code; p->parsed_name[2] = 0;
|
||||
}
|
||||
else p->parsed_name = 0;
|
||||
if( argument )
|
||||
static char push_back_record( struct Arg_parser * const ap,
|
||||
const int code, const char * const argument )
|
||||
{
|
||||
const int len = strlen( argument );
|
||||
p->argument = (char *)malloc( len + 1 );
|
||||
if( !p->argument ) { free( p->parsed_name ); return 0; }
|
||||
struct ap_Record * p;
|
||||
void * tmp = ap_resize_buffer( ap->data,
|
||||
( ap->data_size + 1 ) * sizeof (struct ap_Record) );
|
||||
if( !tmp ) return 0;
|
||||
ap->data = (struct ap_Record *)tmp;
|
||||
p = &(ap->data[ap->data_size]);
|
||||
p->code = code;
|
||||
p->argument = 0;
|
||||
tmp = ap_resize_buffer( p->argument, len + 1 );
|
||||
if( !tmp ) return 0;
|
||||
p->argument = (char *)tmp;
|
||||
strncpy( p->argument, argument, len + 1 );
|
||||
}
|
||||
else p->argument = 0;
|
||||
++ap->data_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static char add_error( Arg_parser * const ap, const char * const msg )
|
||||
static char add_error( struct Arg_parser * const ap, const char * const msg )
|
||||
{
|
||||
const int len = strlen( msg );
|
||||
void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 );
|
||||
|
@ -83,20 +65,19 @@ static char add_error( Arg_parser * const ap, const char * const msg )
|
|||
}
|
||||
|
||||
|
||||
static void free_data( Arg_parser * const ap )
|
||||
static void free_data( struct Arg_parser * const ap )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < ap->data_size; ++i )
|
||||
{ free( ap->data[i].argument ); free( ap->data[i].parsed_name ); }
|
||||
for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument );
|
||||
if( ap->data ) { free( ap->data ); ap->data = 0; }
|
||||
ap->data_size = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return 0 only if out of memory. */
|
||||
static char parse_long_option( Arg_parser * const ap,
|
||||
static char parse_long_option( struct Arg_parser * const ap,
|
||||
const char * const opt, const char * const arg,
|
||||
const ap_Option options[], int * const argindp )
|
||||
const struct ap_Option options[],
|
||||
int * const argindp )
|
||||
{
|
||||
unsigned len;
|
||||
int index = -1, i;
|
||||
|
@ -106,10 +87,9 @@ static char parse_long_option( Arg_parser * const ap,
|
|||
|
||||
/* Test all long options for either exact match or abbreviated matches. */
|
||||
for( i = 0; options[i].code != 0; ++i )
|
||||
if( options[i].long_name &&
|
||||
strncmp( options[i].long_name, &opt[2], len ) == 0 )
|
||||
if( options[i].name && strncmp( options[i].name, &opt[2], len ) == 0 )
|
||||
{
|
||||
if( strlen( options[i].long_name ) == len ) /* Exact match found */
|
||||
if( strlen( options[i].name ) == len ) /* Exact match found */
|
||||
{ index = i; exact = 1; break; }
|
||||
else if( index < 0 ) index = i; /* First nonexact match found */
|
||||
else if( options[index].code != options[i].code ||
|
||||
|
@ -137,55 +117,52 @@ static char parse_long_option( Arg_parser * const ap,
|
|||
{
|
||||
if( options[index].has_arg == ap_no )
|
||||
{
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].long_name );
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].name );
|
||||
add_error( ap, "' doesn't allow an argument" );
|
||||
return 1;
|
||||
}
|
||||
if( options[index].has_arg == ap_yes && !opt[len+3] )
|
||||
{
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].long_name );
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].name );
|
||||
add_error( ap, "' requires an argument" );
|
||||
return 1;
|
||||
}
|
||||
return push_back_record( ap, options[index].code, options[index].long_name,
|
||||
&opt[len+3] ); /* argument may be empty */
|
||||
return push_back_record( ap, options[index].code, &opt[len+3] );
|
||||
}
|
||||
|
||||
if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme )
|
||||
if( options[index].has_arg == ap_yes )
|
||||
{
|
||||
if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) )
|
||||
if( !arg || !arg[0] )
|
||||
{
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].long_name );
|
||||
add_error( ap, "option '--" ); add_error( ap, options[index].name );
|
||||
add_error( ap, "' requires an argument" );
|
||||
return 1;
|
||||
}
|
||||
++*argindp;
|
||||
return push_back_record( ap, options[index].code, options[index].long_name,
|
||||
arg ); /* argument may be empty */
|
||||
return push_back_record( ap, options[index].code, arg );
|
||||
}
|
||||
|
||||
return push_back_record( ap, options[index].code,
|
||||
options[index].long_name, 0 );
|
||||
return push_back_record( ap, options[index].code, "" );
|
||||
}
|
||||
|
||||
|
||||
/* Return 0 only if out of memory. */
|
||||
static char parse_short_option( Arg_parser * const ap,
|
||||
static char parse_short_option( struct Arg_parser * const ap,
|
||||
const char * const opt, const char * const arg,
|
||||
const ap_Option options[], int * const argindp )
|
||||
const struct ap_Option options[],
|
||||
int * const argindp )
|
||||
{
|
||||
int cind = 1; /* character index in opt */
|
||||
|
||||
while( cind > 0 )
|
||||
{
|
||||
int index = -1, i;
|
||||
const unsigned char c = opt[cind];
|
||||
const unsigned char code = opt[cind];
|
||||
char code_str[2];
|
||||
code_str[0] = c; code_str[1] = 0;
|
||||
code_str[0] = code; code_str[1] = 0;
|
||||
|
||||
if( c != 0 )
|
||||
if( code != 0 )
|
||||
for( i = 0; options[i].code; ++i )
|
||||
if( c == options[i].code )
|
||||
if( code == options[i].code )
|
||||
{ index = i; break; }
|
||||
|
||||
if( index < 0 )
|
||||
|
@ -199,34 +176,34 @@ static char parse_short_option( Arg_parser * const ap,
|
|||
|
||||
if( options[index].has_arg != ap_no && cind > 0 && opt[cind] )
|
||||
{
|
||||
if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0;
|
||||
if( !push_back_record( ap, code, &opt[cind] ) ) return 0;
|
||||
++*argindp; cind = 0;
|
||||
}
|
||||
else if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme )
|
||||
else if( options[index].has_arg == ap_yes )
|
||||
{
|
||||
if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) )
|
||||
if( !arg || !arg[0] )
|
||||
{
|
||||
add_error( ap, "option requires an argument -- '" );
|
||||
add_error( ap, code_str ); add_error( ap, "'" );
|
||||
return 1;
|
||||
}
|
||||
++*argindp; cind = 0; /* argument may be empty */
|
||||
if( !push_back_record( ap, c, 0, arg ) ) return 0;
|
||||
++*argindp; cind = 0;
|
||||
if( !push_back_record( ap, code, arg ) ) return 0;
|
||||
}
|
||||
else if( !push_back_record( ap, c, 0, 0 ) ) return 0;
|
||||
else if( !push_back_record( ap, code, "" ) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char ap_init( Arg_parser * const ap,
|
||||
char ap_init( struct Arg_parser * const ap,
|
||||
const int argc, const char * const argv[],
|
||||
const ap_Option options[], const char in_order )
|
||||
const struct ap_Option options[], const char in_order )
|
||||
{
|
||||
const char ** non_options = 0; /* skipped non-options */
|
||||
int non_options_size = 0; /* number of skipped non-options */
|
||||
int argind = 1; /* index in argv */
|
||||
char done = 0; /* false until success */
|
||||
int i;
|
||||
|
||||
ap->data = 0;
|
||||
ap->error = 0;
|
||||
|
@ -246,20 +223,20 @@ char ap_init( Arg_parser * const ap,
|
|||
if( ch2 == '-' )
|
||||
{
|
||||
if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */
|
||||
else if( !parse_long_option( ap, opt, arg, options, &argind ) ) goto out;
|
||||
else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0;
|
||||
}
|
||||
else if( !parse_short_option( ap, opt, arg, options, &argind ) ) goto out;
|
||||
else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0;
|
||||
if( ap->error ) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( in_order )
|
||||
{ if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; }
|
||||
{ if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; }
|
||||
else
|
||||
{
|
||||
void * tmp = ap_resize_buffer( non_options,
|
||||
( non_options_size + 1 ) * sizeof *non_options );
|
||||
if( !tmp ) goto out;
|
||||
if( !tmp ) return 0;
|
||||
non_options = (const char **)tmp;
|
||||
non_options[non_options_size++] = argv[argind++];
|
||||
}
|
||||
|
@ -268,19 +245,17 @@ char ap_init( Arg_parser * const ap,
|
|||
if( ap->error ) free_data( ap );
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < non_options_size; ++i )
|
||||
if( !push_back_record( ap, 0, 0, non_options[i] ) ) goto out;
|
||||
if( !push_back_record( ap, 0, non_options[i] ) ) return 0;
|
||||
while( argind < argc )
|
||||
if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out;
|
||||
if( !push_back_record( ap, 0, argv[argind++] ) ) return 0;
|
||||
}
|
||||
done = 1;
|
||||
out: if( non_options ) free( non_options );
|
||||
return done;
|
||||
if( non_options ) free( non_options );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void ap_free( Arg_parser * const ap )
|
||||
void ap_free( struct Arg_parser * const ap )
|
||||
{
|
||||
free_data( ap );
|
||||
if( ap->error ) { free( ap->error ); ap->error = 0; }
|
||||
|
@ -288,26 +263,23 @@ void ap_free( Arg_parser * const ap )
|
|||
}
|
||||
|
||||
|
||||
const char * ap_error( const Arg_parser * const ap ) { return ap->error; }
|
||||
const char * ap_error( const struct Arg_parser * const ap )
|
||||
{ return ap->error; }
|
||||
|
||||
int ap_arguments( const Arg_parser * const ap ) { return ap->data_size; }
|
||||
|
||||
int ap_code( const Arg_parser * const ap, const int i )
|
||||
int ap_arguments( const struct Arg_parser * const ap )
|
||||
{ return ap->data_size; }
|
||||
|
||||
|
||||
int ap_code( const struct Arg_parser * const ap, const int i )
|
||||
{
|
||||
if( i < 0 || i >= ap_arguments( ap ) ) return 0;
|
||||
return ap->data[i].code;
|
||||
if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
const char * ap_parsed_name( const Arg_parser * const ap, const int i )
|
||||
const char * ap_argument( const struct Arg_parser * const ap, const int i )
|
||||
{
|
||||
if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].parsed_name ) return "";
|
||||
return ap->data[i].parsed_name;
|
||||
}
|
||||
|
||||
|
||||
const char * ap_argument( const Arg_parser * const ap, const int i )
|
||||
{
|
||||
if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].argument ) return "";
|
||||
return ap->data[i].argument;
|
||||
if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument;
|
||||
else return "";
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/* Arg_parser - POSIX/GNU command-line argument parser. (C version)
|
||||
Copyright (C) 2006-2025 Antonio Diaz Diaz.
|
||||
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||
Copyright (C) 2006-2018 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,15 +18,15 @@
|
|||
*/
|
||||
|
||||
/* 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.
|
||||
|
||||
'options' is an array of 'struct ap_Option' terminated by an element
|
||||
containing a code which is zero. A null long_name means a short-only
|
||||
option. A code value outside the unsigned char range means a long-only
|
||||
option.
|
||||
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
|
||||
|
@ -37,65 +37,56 @@
|
|||
The argument '--' terminates all options; any following arguments are
|
||||
treated as non-option arguments, even if they begin with a hyphen.
|
||||
|
||||
The syntax of options with an optional argument is
|
||||
'-<short_option><argument>' (without whitespace), or
|
||||
'--<long_option>=<argument>'.
|
||||
|
||||
The syntax of options with an empty argument is '-<short_option> ""',
|
||||
'--<long_option> ""', or '--<long_option>=""'.
|
||||
The syntax for optional option arguments is '-<short_option><argument>'
|
||||
(without whitespace), or '--<long_option>=<argument>'.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ap_yme = yes but maybe empty */
|
||||
typedef enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme } ap_Has_arg;
|
||||
enum ap_Has_arg { ap_no, ap_yes, ap_maybe };
|
||||
|
||||
typedef struct ap_Option
|
||||
struct ap_Option
|
||||
{
|
||||
int code; /* Short option letter or code ( code != 0 ) */
|
||||
const char * long_name; /* Long option name (maybe null) */
|
||||
ap_Has_arg has_arg;
|
||||
} ap_Option;
|
||||
const char * name; /* Long option name (maybe null) */
|
||||
enum ap_Has_arg has_arg;
|
||||
};
|
||||
|
||||
|
||||
typedef struct ap_Record
|
||||
struct ap_Record
|
||||
{
|
||||
int code;
|
||||
char * parsed_name;
|
||||
char * argument;
|
||||
} ap_Record;
|
||||
};
|
||||
|
||||
|
||||
typedef struct Arg_parser
|
||||
struct Arg_parser
|
||||
{
|
||||
ap_Record * data;
|
||||
struct ap_Record * data;
|
||||
char * error;
|
||||
int data_size;
|
||||
int error_size;
|
||||
} Arg_parser;
|
||||
};
|
||||
|
||||
|
||||
char ap_init( Arg_parser * const ap,
|
||||
char ap_init( struct Arg_parser * const ap,
|
||||
const int argc, const char * const argv[],
|
||||
const ap_Option options[], const char in_order );
|
||||
const struct ap_Option options[], const char in_order );
|
||||
|
||||
void ap_free( Arg_parser * const ap );
|
||||
void ap_free( struct Arg_parser * const ap );
|
||||
|
||||
const char * ap_error( const Arg_parser * const ap );
|
||||
const char * ap_error( const struct Arg_parser * const ap );
|
||||
|
||||
/* The number of arguments parsed. May be different from argc. */
|
||||
int ap_arguments( const Arg_parser * const ap );
|
||||
/* 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). */
|
||||
int ap_code( const Arg_parser * const ap, const int i );
|
||||
int ap_code( const struct Arg_parser * const ap, const int i );
|
||||
|
||||
/* Full name of the option parsed (short or long). */
|
||||
const char * ap_parsed_name( const Arg_parser * const ap, const int i );
|
||||
|
||||
const char * ap_argument( const Arg_parser * const ap, const int i );
|
||||
const char * ap_argument( const struct Arg_parser * const ap, const int i );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
52
configure
vendored
52
configure
vendored
|
@ -1,12 +1,12 @@
|
|||
#! /bin/sh
|
||||
# configure script for Xlunzip - Test tool for the lzip_decompress linux module
|
||||
# Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
# configure script for Xlunzip - Test tool for the lunzip linux module
|
||||
# Copyright (C) 2016-2018 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=xlunzip
|
||||
pkgversion=0.9
|
||||
pkgversion=0.3
|
||||
progname=xlunzip
|
||||
srctrigger=doc/${progname}.1
|
||||
|
||||
|
@ -24,10 +24,13 @@ CC=gcc
|
|||
CPPFLAGS=
|
||||
CFLAGS='-Wall -W -O2'
|
||||
LDFLAGS=
|
||||
MAKEINFO=makeinfo
|
||||
|
||||
# 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=
|
||||
|
@ -39,12 +42,11 @@ while [ $# != 0 ] ; do
|
|||
shift
|
||||
|
||||
# Add the argument quoted to args
|
||||
if [ -z "${args}" ] ; then args="\"${option}\""
|
||||
else args="${args} \"${option}\"" ; fi
|
||||
args="${args} \"${option}\""
|
||||
|
||||
# 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
|
||||
|
@ -58,7 +60,7 @@ while [ $# != 0 ] ; do
|
|||
echo "Options and variables: [defaults in brackets]"
|
||||
echo " -h, --help display this help and exit"
|
||||
echo " -V, --version output version information and exit"
|
||||
echo " --srcdir=DIR find the source code in DIR [. or ..]"
|
||||
echo " --srcdir=DIR find the sources in DIR [. or ..]"
|
||||
echo " --prefix=DIR install into DIR [${prefix}]"
|
||||
echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]"
|
||||
echo " --bindir=DIR user executables directory [${bindir}]"
|
||||
|
@ -66,11 +68,9 @@ while [ $# != 0 ] ; do
|
|||
echo " --infodir=DIR info files directory [${infodir}]"
|
||||
echo " --mandir=DIR man pages directory [${mandir}]"
|
||||
echo " CC=COMPILER C compiler to use [${CC}]"
|
||||
echo " CPPFLAGS=OPTIONS command-line options for the preprocessor [${CPPFLAGS}]"
|
||||
echo " CFLAGS=OPTIONS command-line options for the C compiler [${CFLAGS}]"
|
||||
echo " CFLAGS+=OPTIONS append options to the current value of CFLAGS"
|
||||
echo " LDFLAGS=OPTIONS command-line options for the linker [${LDFLAGS}]"
|
||||
echo " MAKEINFO=NAME makeinfo program to use [${MAKEINFO}]"
|
||||
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
|
||||
echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]"
|
||||
echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]"
|
||||
echo
|
||||
exit 0 ;;
|
||||
--version | -V)
|
||||
|
@ -96,9 +96,7 @@ while [ $# != 0 ] ; do
|
|||
CC=*) CC=${optarg} ;;
|
||||
CPPFLAGS=*) CPPFLAGS=${optarg} ;;
|
||||
CFLAGS=*) CFLAGS=${optarg} ;;
|
||||
CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;;
|
||||
LDFLAGS=*) LDFLAGS=${optarg} ;;
|
||||
MAKEINFO=*) MAKEINFO=${optarg} ;;
|
||||
|
||||
--*)
|
||||
echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;;
|
||||
|
@ -109,7 +107,7 @@ while [ $# != 0 ] ; do
|
|||
exit 1 ;;
|
||||
esac
|
||||
|
||||
# Check whether the option took a separate argument
|
||||
# Check if the option took a separate argument
|
||||
if [ "${arg2}" = yes ] ; then
|
||||
if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift
|
||||
else echo "configure: Missing argument to '${option}'" 1>&2
|
||||
|
@ -118,19 +116,19 @@ while [ $# != 0 ] ; do
|
|||
fi
|
||||
done
|
||||
|
||||
# Find the source code, if location was not specified.
|
||||
# Find the source files, if location was not specified.
|
||||
srcdirtext=
|
||||
if [ -z "${srcdir}" ] ; then
|
||||
srcdirtext="or . or .." ; srcdir=.
|
||||
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
|
||||
|
||||
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||
echo "configure: Can't find source code in ${srcdir} ${srcdirtext}" 1>&2
|
||||
echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" 1>&2
|
||||
echo "configure: (At least ${srctrigger} is missing)." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
@ -148,9 +146,9 @@ 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
|
||||
exec /bin/sh $0 ${args} --no-create
|
||||
EOF
|
||||
chmod +x config.status
|
||||
fi
|
||||
|
@ -167,15 +165,14 @@ echo "CC = ${CC}"
|
|||
echo "CPPFLAGS = ${CPPFLAGS}"
|
||||
echo "CFLAGS = ${CFLAGS}"
|
||||
echo "LDFLAGS = ${LDFLAGS}"
|
||||
echo "MAKEINFO = ${MAKEINFO}"
|
||||
rm -f Makefile
|
||||
cat > Makefile << EOF
|
||||
# Makefile for Xlunzip - Test tool for the lzip_decompress linux module
|
||||
# Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
# Makefile for Xlunzip - Test tool for the lunzip linux module
|
||||
# Copyright (C) 2016-2018 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}
|
||||
|
@ -191,7 +188,6 @@ CC = ${CC}
|
|||
CPPFLAGS = ${CPPFLAGS}
|
||||
CFLAGS = ${CFLAGS}
|
||||
LDFLAGS = ${LDFLAGS}
|
||||
MAKEINFO = ${MAKEINFO}
|
||||
EOF
|
||||
cat "${srcdir}/Makefile.in" >> Makefile
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/*
|
||||
* Wrapper for decompressing LZIP-compressed kernel, initramfs, and initrd
|
||||
*
|
||||
* Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
* Copyright (C) 2016-2018 Antonio Diaz Diaz.
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
*/
|
||||
|
||||
#ifdef STATIC
|
||||
#define PREBOOT
|
||||
#include "lzip_decompress.c"
|
||||
#include "lzip.c"
|
||||
#else
|
||||
#include "linux_lzip.h"
|
||||
#include "linux_lunzip.h"
|
||||
|
@ -62,18 +62,16 @@ STATIC int INIT __lunzip(unsigned char *inbuf, long in_len,
|
|||
case LZIP_BAD_CRC:
|
||||
error("CRC mismatch in LZIP-compressed data.");
|
||||
break;
|
||||
case LZIP_EMPTY_MEMBER:
|
||||
error("Empty member in LZIP multimember data.");
|
||||
break;
|
||||
default: error("Bug in the LZIP decompressor.");
|
||||
default:
|
||||
error("Bug in the LZIP decompressor.");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifndef PREBOOT
|
||||
/* decompress_fn (see include/linux/decompress/generic.h) should have an
|
||||
* out_size argument to prevent overflowing outbuf in case of corruption
|
||||
* of the compressed data.
|
||||
/* decompress_fn (see linux/decompress/generic.h) should have an out_size
|
||||
* argument to prevent overrunning outbuf in case of corruption of the
|
||||
* compressed data.
|
||||
*/
|
||||
STATIC int INIT lunzip(unsigned char *inbuf, long in_len,
|
||||
long (*fill)(void*, unsigned long),
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
|
||||
.TH XLUNZIP "1" "January 2025" "xlunzip 0.9" "User Commands"
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
|
||||
.TH XLUNZIP "1" "July 2018" "xlunzip 0.3" "User Commands"
|
||||
.SH NAME
|
||||
xlunzip \- test tool for the lzip_decompress linux module
|
||||
xlunzip \- test tool for the lunzip linux module
|
||||
.SH SYNOPSIS
|
||||
.B xlunzip
|
||||
[\fI\,options\/\fR] [\fI\,files\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Xlunzip is a test tool for the lzip decompression code of my lzip patch for
|
||||
linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress linux
|
||||
module as a backend. Xlunzip tests the module for stream, buffer\-to\-buffer,
|
||||
and mixed decompression modes, including in\-place decompression (using the
|
||||
same buffer for input and output). You can use xlunzip to check that the
|
||||
module produces correct results when decompressing single member files,
|
||||
multimember files, or the concatenation of two or more compressed files.
|
||||
Xlunzip can be used with unzcrash to test the robustness of the module to
|
||||
the decompression of corrupted data.
|
||||
Xlunzip is a test tool for the lzip decompression code of my lzip patch
|
||||
for linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress
|
||||
linux module as a backend. Xlunzip tests the module for stream,
|
||||
buffer\-to\-buffer and mixed decompression modes, including in\-place
|
||||
decompression (using the same buffer for input and output). You can use
|
||||
xlunzip to verify that the module produces correct results when
|
||||
decompressing single member files, multimember files, or the
|
||||
concatenation of two or more compressed files. Xlunzip can be used with
|
||||
unzcrash to test the robustness of the module to the decompression of
|
||||
corrupted data.
|
||||
.PP
|
||||
The distributed index feature of the lzip format allows xlunzip to
|
||||
decompress concatenated files in place. This can't be guaranteed to work
|
||||
with formats like gzip or bzip2 because they can't detect whether a high
|
||||
compression ratio in the first members of the multimember data is being
|
||||
masked by a low compression ratio in the last members.
|
||||
Note that the in\-place decompression of concatenated files can't be
|
||||
guaranteed to work because an arbitrarily low compression ratio of the
|
||||
last part of the data can be achieved by appending enough empty
|
||||
compressed members to a file.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
|
@ -45,7 +45,7 @@ decompress or test using only one buffer
|
|||
keep (don't delete) input files
|
||||
.TP
|
||||
\fB\-o\fR, \fB\-\-output=\fR<file>
|
||||
write to <file>, keep input files
|
||||
if reading standard input, write to <file>
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
suppress all messages
|
||||
|
@ -74,19 +74,16 @@ from standard input to standard output.
|
|||
Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,
|
||||
Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...
|
||||
.PP
|
||||
To extract all the files from archive 'foo.tar.lz', use the commands
|
||||
\&'tar \fB\-xf\fR foo.tar.lz' or 'xlunzip \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 command\-line options, I/O errors, etc), 2 to
|
||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||
error (e.g., bug) which caused xlunzip 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 xlunzip to panic.
|
||||
.SH "REPORTING BUGS"
|
||||
Report bugs to lzip\-bug@nongnu.org
|
||||
.br
|
||||
Xlunzip home page: http://www.nongnu.org/lzip/xlunzip.html
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2025 Antonio Diaz Diaz.
|
||||
Copyright \(co 2018 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.
|
||||
|
|
152
in_place.c
152
in_place.c
|
@ -1,5 +1,5 @@
|
|||
/* Xlunzip - Test tool for the lzip_decompress linux module
|
||||
Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
/* Xlunzip - Test tool for the lunzip linux module
|
||||
Copyright (C) 2016-2018 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
|
||||
|
@ -30,10 +30,10 @@
|
|||
#include "lzip.h"
|
||||
|
||||
|
||||
/* Return the number of bytes really read.
|
||||
If (value returned < size) and (errno == 0), means EOF was reached.
|
||||
/* Returns the number of bytes really read.
|
||||
If (returned value < size) and (errno == 0), means EOF was reached.
|
||||
*/
|
||||
static long readblock( const int fd, uint8_t * const buf, const long size )
|
||||
long readblock( const int fd, uint8_t * const buf, const long size )
|
||||
{
|
||||
long sz = 0;
|
||||
errno = 0;
|
||||
|
@ -49,33 +49,36 @@ static long readblock( const int fd, uint8_t * const buf, const long size )
|
|||
}
|
||||
|
||||
|
||||
/* Return the address of a malloc'd buffer containing the file data and
|
||||
/* Returns the address of a malloc'd buffer containing the file data and
|
||||
the buffer and file sizes in '*buffer_sizep' and '*file_sizep'.
|
||||
In case of error, return 0 and do not modify '*sizep'.
|
||||
In case of error, returns 0 and does not modify '*size'.
|
||||
*/
|
||||
static uint8_t * read_file( const int infd, long * const buffer_sizep,
|
||||
long * const file_sizep, const char * const filename )
|
||||
uint8_t * read_file( const int infd, long * const buffer_sizep,
|
||||
long * const file_sizep, struct Pretty_print * const pp )
|
||||
{
|
||||
long buffer_size = 1 << 20;
|
||||
uint8_t * buffer = (uint8_t *)malloc( buffer_size );
|
||||
if( !buffer ) { show_file_error( filename, mem_msg, 0 ); return 0; }
|
||||
if( !buffer )
|
||||
{ show_file_error( pp->name, "Not enough memory.", 0 ); return 0; }
|
||||
|
||||
long file_size = readblock( infd, buffer, buffer_size );
|
||||
while( file_size >= buffer_size && !errno )
|
||||
{
|
||||
if( buffer_size >= LONG_MAX )
|
||||
{ show_file_error( filename, "Input file is too large.", 0 );
|
||||
free( buffer ); return 0; }
|
||||
{ show_file_error( pp->name, "File is too large.", 0 ); free( buffer );
|
||||
return 0; }
|
||||
buffer_size = ( buffer_size <= LONG_MAX / 2 ) ? 2 * buffer_size : LONG_MAX;
|
||||
uint8_t * const tmp = (uint8_t *)realloc( buffer, buffer_size );
|
||||
if( !tmp )
|
||||
{ show_file_error( filename, mem_msg, 0 ); free( buffer ); return 0; }
|
||||
{ show_file_error( pp->name, "Not enough memory.", 0 ); free( buffer );
|
||||
return 0; }
|
||||
buffer = tmp;
|
||||
file_size += readblock( infd, buffer + file_size, buffer_size - file_size );
|
||||
}
|
||||
if( errno )
|
||||
{ show_file_error( filename, "Error reading file", errno ); free( buffer );
|
||||
{ show_file_error( pp->name, "Error reading file", errno ); free( buffer );
|
||||
return 0; }
|
||||
close( infd );
|
||||
*buffer_sizep = buffer_size;
|
||||
*file_sizep = file_size;
|
||||
return buffer;
|
||||
|
@ -84,114 +87,104 @@ static uint8_t * read_file( const int infd, long * const buffer_sizep,
|
|||
|
||||
struct File_sizes
|
||||
{
|
||||
unsigned long long csize; /* compressed size */
|
||||
unsigned long long dsize; /* decompressed size */
|
||||
unsigned long tsize; /* trailing data size */
|
||||
long members;
|
||||
long long csize;
|
||||
long long dsize;
|
||||
long trailing;
|
||||
};
|
||||
|
||||
static const char * set_file_sizes( struct File_sizes * const file_sizes,
|
||||
const uint8_t * const buffer,
|
||||
const unsigned long file_size )
|
||||
const char * set_file_sizes( struct File_sizes * const file_sizes,
|
||||
const uint8_t * const buffer, const long file_size )
|
||||
{
|
||||
if( file_size <= Lh_size ) return "File ends unexpectedly at member header.";
|
||||
if( file_size < min_member_size ) return "Input file is truncated.";
|
||||
const Lzip_header * header = (const Lzip_header *)buffer;
|
||||
if( !Lh_check_magic( *header ) )
|
||||
if( file_size < min_member_size ) return "Input file is too short.";
|
||||
const Lzip_header * header = (Lzip_header *)buffer;
|
||||
if( !Lh_verify_magic( *header ) )
|
||||
return "Bad magic number (file not in lzip format).";
|
||||
if( !Lh_check_version( *header ) )
|
||||
if( !Lh_verify_version( *header ) )
|
||||
return "Version of lzip member format not supported.";
|
||||
|
||||
file_sizes->csize = file_sizes->dsize = file_sizes->tsize = 0;
|
||||
file_sizes->members = 0;
|
||||
unsigned long pos = file_size; /* always points to a header or to EOF */
|
||||
file_sizes->csize = file_sizes->dsize = file_sizes->trailing = 0;
|
||||
long long pos = file_size; /* always points to a header or to EOF */
|
||||
while( pos >= min_member_size )
|
||||
{
|
||||
const Lzip_trailer * const trailer =
|
||||
(const Lzip_trailer *)( buffer + pos - Lt_size );
|
||||
const unsigned long long member_size = Lt_get_member_size( *trailer );
|
||||
(Lzip_trailer *)( buffer + pos - Lt_size );
|
||||
const long long member_size = Lt_get_member_size( *trailer );
|
||||
if( member_size < min_member_size || member_size > pos )
|
||||
{
|
||||
if( file_sizes->csize == 0 ) /* maybe trailing data */
|
||||
{
|
||||
if( member_size == 0 ) /* skip trailing zeros */
|
||||
while( pos > Lt_size && buffer[pos-8] == 0 ) --pos;
|
||||
else --pos;
|
||||
continue;
|
||||
}
|
||||
if( file_sizes->csize == 0 ) { --pos; continue; } /* maybe trailing data */
|
||||
return "Member size in trailer is corrupt.";
|
||||
}
|
||||
header = (const Lzip_header *)( buffer + pos - member_size );
|
||||
if( !Lh_check_magic( *header ) || !Lh_check_version( *header ) )
|
||||
header = (Lzip_header *)( buffer + pos - member_size );
|
||||
if( !Lh_verify_magic( *header ) || !Lh_verify_version( *header ) )
|
||||
{
|
||||
if( file_sizes->csize == 0 ) { --pos; continue; } /* maybe trailing data */
|
||||
return "Bad member header inside file.";
|
||||
}
|
||||
if( file_sizes->csize == 0 && file_size - pos > 0 )
|
||||
{
|
||||
file_sizes->tsize = file_size - pos;
|
||||
header = (const Lzip_header *)( buffer + pos );
|
||||
file_sizes->trailing = file_size - pos;
|
||||
header = (Lzip_header *)( buffer + pos );
|
||||
if( file_size - pos > Lh_size &&
|
||||
Lh_check_magic( *header ) && Lh_check_version( *header ) )
|
||||
Lh_verify_magic( *header ) && Lh_verify_version( *header ) )
|
||||
return "Last member in input file is truncated or corrupt.";
|
||||
}
|
||||
pos -= member_size;
|
||||
file_sizes->csize += member_size;
|
||||
file_sizes->dsize += Lt_get_data_size( *trailer );
|
||||
++file_sizes->members;
|
||||
}
|
||||
if( pos != 0 || file_sizes->csize == 0 ) return "Can't get file sizes.";
|
||||
if( file_sizes->csize + file_sizes->tsize != file_size )
|
||||
if( file_sizes->csize + file_sizes->trailing != file_size )
|
||||
return "Error getting file sizes.";
|
||||
if( file_sizes->csize > LONG_MAX ) return "File is larger than LONG_MAX.";
|
||||
if( file_sizes->dsize > LONG_MAX ) return "Data is larger than LONG_MAX.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const char * global_name; /* copy of filename for 'error' */
|
||||
const char * global_name;
|
||||
static void error(char *x) { show_file_error( global_name, x, 0 ); }
|
||||
|
||||
|
||||
/*
|
||||
* Load the compressed file at the end of the buffer used to hold the
|
||||
* decompressed data. Check that the in-place decompression does not
|
||||
* overwrite the compressed data. The buffer must be large enough to contain
|
||||
* after the decompressed data extra space for a marker, a trailer, the
|
||||
* maximum possible data expansion, and (if multimember) N-1 empty members.
|
||||
* decompressed data. Verify that the in-place decompression does not
|
||||
* overwrite the compressed data.
|
||||
*
|
||||
* |------ compressed data ------|
|
||||
* |----- compressed data ------|
|
||||
* V V
|
||||
* |----------------|-------------------|---------|
|
||||
* ^ ^ extra
|
||||
* |-------- decompressed data ---------|
|
||||
* |---------------|-------------------|--------|
|
||||
* ^ ^
|
||||
* |------- decompressed data ---------|
|
||||
*/
|
||||
|
||||
int decompress_in_place( const int infd, Pretty_print * const pp,
|
||||
int decompress_in_place( const int infd, struct Pretty_print * const pp,
|
||||
const bool testing )
|
||||
{
|
||||
long buffer_size = 0, file_size = 0;
|
||||
uint8_t * buffer = read_file( infd, &buffer_size, &file_size, pp->name );
|
||||
uint8_t * buffer = read_file( infd, &buffer_size, &file_size, pp );
|
||||
if( !buffer ) return 1;
|
||||
struct File_sizes file_sizes;
|
||||
const char * emsg = set_file_sizes( &file_sizes, buffer, file_size );
|
||||
if( emsg ) { show_file_error( pp->name, emsg, 0 ); return 2; }
|
||||
|
||||
const long csize = file_sizes.csize;
|
||||
const long dsize = file_sizes.dsize;
|
||||
/* const long extra_bytes = ( dsize >> 8 ) + 65536; wrong linux formula */
|
||||
const long extra_bytes = ( csize >> 6 ) + file_sizes.members * min_member_size;
|
||||
const long long target_buffer_size = max( dsize, csize ) + extra_bytes;
|
||||
if( target_buffer_size > LONG_MAX )
|
||||
{ show_file_error( pp->name, "Buffer is larger than LONG_MAX.", 0 );
|
||||
return 1; }
|
||||
if( buffer_size < target_buffer_size ) /* avoid realloc if big enough */
|
||||
const long long csize = file_sizes.csize;
|
||||
const long long dsize = file_sizes.dsize;
|
||||
/* const long trailing = file_sizes.trailing; */
|
||||
if( csize <= 0 || csize > LONG_MAX )
|
||||
{ show_file_error( pp->name, "File is larger than LONG_MAX.", 0 );
|
||||
return 2; }
|
||||
if( dsize < 0 || dsize > LONG_MAX )
|
||||
{ show_file_error( pp->name, "Data is larger than LONG_MAX.", 0 );
|
||||
return 2; }
|
||||
/* ( (csize-36+63) >> 6 ) + 36 never failed with single member */
|
||||
const long rextra = ( csize >> 5 ) + 72;
|
||||
if( buffer_size < dsize + rextra ) /* avoid realloc if big enough */
|
||||
{
|
||||
buffer = (uint8_t *)realloc( buffer, target_buffer_size );
|
||||
if( !buffer ) { show_file_error( pp->name, mem_msg, 0 ); return 1; }
|
||||
buffer_size = dsize + rextra;
|
||||
buffer = (uint8_t *)realloc( buffer, buffer_size );
|
||||
if( !buffer )
|
||||
{ show_file_error( pp->name, "Not enough memory.", 0 ); return 1; }
|
||||
}
|
||||
buffer_size = target_buffer_size;
|
||||
const long cbegin = buffer_size - csize; /* overwrite trailing data */
|
||||
else buffer_size = max( dsize + rextra, csize );
|
||||
const long cbegin = buffer_size - csize;
|
||||
if( cbegin > 0 ) memmove( buffer + cbegin, buffer, csize );
|
||||
|
||||
long in_pos, out_pos;
|
||||
|
@ -207,6 +200,21 @@ int decompress_in_place( const int infd, Pretty_print * const pp,
|
|||
}
|
||||
free( buffer );
|
||||
if( retval ) return retval;
|
||||
show_results( pp, in_pos, out_pos, testing );
|
||||
if( verbosity >= 1 ) Pp_show_msg( pp, 0 );
|
||||
if( verbosity >= 2 )
|
||||
{
|
||||
if( out_pos <= 0 || in_pos <= 0 )
|
||||
fputs( "no data compressed. ", stderr );
|
||||
else
|
||||
fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ",
|
||||
(double)out_pos / in_pos,
|
||||
( 100.0 * in_pos ) / out_pos,
|
||||
100.0 - ( ( 100.0 * in_pos ) / out_pos ) );
|
||||
if( verbosity >= 3 )
|
||||
fprintf( stderr, "decompressed %9lu, compressed %8lu. ",
|
||||
out_pos, in_pos );
|
||||
}
|
||||
if( verbosity >= 1 )
|
||||
fputs( testing ? "ok\n" : "done\n", stderr );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,6 @@ int lunzip(unsigned char *inbuf, long in_len,
|
|||
long *in_posp,
|
||||
void (*error)(char *x));
|
||||
|
||||
/* This internal function is required because the decompress_fn above
|
||||
* (see include/linux/decompress/generic.h) should have an out_size
|
||||
* argument to prevent overflowing outbuf in case of corruption of the
|
||||
* compressed data.
|
||||
*/
|
||||
int __lunzip(unsigned char *inbuf, long in_len,
|
||||
long (*fill)(void*, unsigned long),
|
||||
long (*flush)(void*, unsigned long),
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
/*
|
||||
* LZIP decompressor
|
||||
*
|
||||
* Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
* Copyright (C) 2016-2018 Antonio Diaz Diaz.
|
||||
*/
|
||||
|
||||
/* Return values (< 0 = Error) */
|
||||
|
@ -20,8 +20,7 @@ enum {
|
|||
LZIP_WRITE_ERROR = -9,
|
||||
LZIP_BAD_DATA = -10,
|
||||
LZIP_DATA_EOF = -11,
|
||||
LZIP_BAD_CRC = -12,
|
||||
LZIP_EMPTY_MEMBER = -13
|
||||
LZIP_BAD_CRC = -12
|
||||
};
|
||||
|
||||
int lzip_decompress(unsigned char *inbuf, long in_len,
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef _LINUX_MODULE_H
|
||||
#define _LINUX_MODULE_H
|
||||
|
||||
#define MODULE_LICENSE(_license)
|
||||
#define MODULE_AUTHOR(_author)
|
||||
#define MODULE_DESCRIPTION(_description)
|
||||
|
||||
#endif /* _LINUX_MODULE_H */
|
|
@ -1,18 +1,17 @@
|
|||
/*
|
||||
* LZIP decompressor
|
||||
*
|
||||
* Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
* Copyright (C) 2016-2018 Antonio Diaz Diaz.
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
*/
|
||||
|
||||
#include "linux_module.h"
|
||||
#include "linux_lzip.h"
|
||||
#include "linux_mm.h"
|
||||
|
||||
/*
|
||||
* STATIC_RW_DATA is used in the pre-boot environment on some architectures.
|
||||
* See include/linux/decompress/mm.h for details.
|
||||
* See <linux/decompress/mm.h> for details.
|
||||
*/
|
||||
#ifndef STATIC_RW_DATA
|
||||
#define STATIC_RW_DATA static
|
||||
|
@ -32,23 +31,23 @@ static inline State St_set_char(const State st)
|
|||
|
||||
static inline State St_set_match(const State st)
|
||||
{
|
||||
return (st < 7) ? 7 : 10;
|
||||
return ((st < 7) ? 7 : 10);
|
||||
}
|
||||
|
||||
static inline State St_set_rep(const State st)
|
||||
{
|
||||
return (st < 7) ? 8 : 11;
|
||||
return ((st < 7) ? 8 : 11);
|
||||
}
|
||||
|
||||
static inline State St_set_shortrep(const State st)
|
||||
static inline State St_set_short_rep(const State st)
|
||||
{
|
||||
return (st < 7) ? 9 : 11;
|
||||
return ((st < 7) ? 9 : 11);
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
min_dictionary_bits = 12,
|
||||
min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */
|
||||
min_dictionary_size = 1 << min_dictionary_bits,
|
||||
max_dictionary_bits = 29,
|
||||
max_dictionary_size = 1 << max_dictionary_bits,
|
||||
literal_context_bits = 3,
|
||||
|
@ -84,7 +83,7 @@ static inline int get_len_state(const int len)
|
|||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -189,12 +188,12 @@ static inline void CRC32_update_buf(uint32_t * const crc,
|
|||
|
||||
STATIC_RW_DATA const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */
|
||||
|
||||
enum { Lh_size = 6 };
|
||||
typedef uint8_t Lzip_header[Lh_size]; /* 0-3 magic bytes */
|
||||
typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */
|
||||
/* 4 version */
|
||||
/* 5 coded dictionary size */
|
||||
/* 5 coded_dict_size */
|
||||
enum { Lh_size = 6 };
|
||||
|
||||
static inline bool Lh_check_magic(const Lzip_header data)
|
||||
static inline bool Lh_verify_magic(const Lzip_header data)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -205,34 +204,34 @@ static inline bool Lh_check_magic(const Lzip_header data)
|
|||
}
|
||||
|
||||
/* detect (truncated) header */
|
||||
static inline bool Lh_check_prefix(const Lzip_header data, const int sz)
|
||||
static inline bool Lh_verify_prefix(const Lzip_header data, const int sz)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sz && i < 4; ++i)
|
||||
if (data[i] != lzip_magic[i])
|
||||
return false;
|
||||
return sz > 0;
|
||||
return (sz > 0);
|
||||
}
|
||||
|
||||
/* detect corrupt header */
|
||||
static inline bool Lh_check_corrupt(const Lzip_header data)
|
||||
static inline bool Lh_verify_corrupt(const Lzip_header data)
|
||||
{
|
||||
int matches = 0;
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (data[i] == lzip_magic[i])
|
||||
++matches;
|
||||
return matches > 1 && matches < 4;
|
||||
return (matches > 1 && matches < 4);
|
||||
}
|
||||
|
||||
static inline bool Lh_check_version(const Lzip_header data)
|
||||
static inline bool Lh_verify_version(const Lzip_header data)
|
||||
{
|
||||
return data[4] == 1;
|
||||
return (data[4] == 1);
|
||||
}
|
||||
|
||||
static inline unsigned Lh_get_dictionary_size(const Lzip_header data)
|
||||
{
|
||||
unsigned sz = 1 << (data[5] & 0x1F);
|
||||
unsigned sz = (1 << (data[5] & 0x1F));
|
||||
|
||||
if (sz > min_dictionary_size)
|
||||
sz -= (sz / 16) * ((data[5] >> 5) & 7);
|
||||
|
@ -240,11 +239,11 @@ static inline unsigned Lh_get_dictionary_size(const Lzip_header data)
|
|||
}
|
||||
|
||||
|
||||
enum { Lt_size = 20 };
|
||||
typedef uint8_t Lzip_trailer[Lt_size];
|
||||
typedef uint8_t Lzip_trailer[20];
|
||||
/* 0-3 CRC32 of the uncompressed data */
|
||||
/* 4-11 size of the uncompressed data */
|
||||
/* 12-19 member size including header and trailer */
|
||||
enum { Lt_size = 20 };
|
||||
|
||||
static inline unsigned Lt_get_data_crc(const Lzip_trailer data)
|
||||
{
|
||||
|
@ -359,17 +358,14 @@ static inline uint8_t Rd_get_byte(struct Range_decoder * const rdec)
|
|||
return rdec->buffer[rdec->pos++];
|
||||
}
|
||||
|
||||
static inline bool Rd_load(struct Range_decoder * const rdec)
|
||||
static inline void Rd_load(struct Range_decoder * const rdec)
|
||||
{
|
||||
int i;
|
||||
|
||||
rdec->code = 0;
|
||||
for (i = 0; i < 5; ++i)
|
||||
rdec->code = (rdec->code << 8) | Rd_get_byte(rdec);
|
||||
rdec->range = 0xFFFFFFFFU;
|
||||
/* check first byte of the LZMA stream */
|
||||
if (Rd_get_byte(rdec) != 0)
|
||||
return false;
|
||||
for (i = 0; i < 4; ++i) rdec->code = (rdec->code << 8) | Rd_get_byte(rdec);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void Rd_normalize(struct Range_decoder * const rdec)
|
||||
|
@ -394,7 +390,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 <<= 1; symbol += bit;
|
||||
symbol = (symbol << 1) + bit;
|
||||
rdec->code -= rdec->range & (0U - bit);
|
||||
}
|
||||
return symbol;
|
||||
|
@ -422,8 +418,9 @@ 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 = 2 | Rd_decode_bit(rdec, &bm[1]);
|
||||
unsigned symbol = 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]);
|
||||
return symbol & 7;
|
||||
|
@ -432,13 +429,14 @@ 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 = 2 | Rd_decode_bit(rdec, &bm[1]);
|
||||
unsigned symbol = 1;
|
||||
|
||||
symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
|
||||
symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
|
||||
symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
|
||||
symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
|
||||
symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
|
||||
symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
|
||||
return symbol & 0x3F;
|
||||
}
|
||||
|
||||
|
@ -464,7 +462,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 <<= 1; model += bit;
|
||||
model = (model << 1) + bit;
|
||||
symbol |= (bit << i);
|
||||
}
|
||||
return symbol;
|
||||
|
@ -474,10 +472,13 @@ 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]);
|
||||
|
||||
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;
|
||||
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);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
@ -491,7 +492,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 <<= 1; symbol += bit;
|
||||
symbol = (symbol << 1) + bit;
|
||||
if (symbol > 0xFF)
|
||||
return symbol & 0xFF;
|
||||
mask &= ~(match_bit ^ (bit << 8)); /* if( match_bit != bit ) mask = 0; */
|
||||
|
@ -503,12 +504,11 @@ static inline unsigned Rd_decode_len(struct Range_decoder * const rdec,
|
|||
const int pos_state)
|
||||
{
|
||||
if (Rd_decode_bit(rdec, &lm->choice1) == 0)
|
||||
return min_match_len +
|
||||
Rd_decode_tree3(rdec, lm->bm_low[pos_state]);
|
||||
return Rd_decode_tree3(rdec, lm->bm_low[pos_state]);
|
||||
if (Rd_decode_bit(rdec, &lm->choice2) == 0)
|
||||
return min_match_len + len_low_symbols +
|
||||
return len_low_symbols +
|
||||
Rd_decode_tree3(rdec, lm->bm_mid[pos_state]);
|
||||
return min_match_len + len_low_symbols + len_mid_symbols +
|
||||
return len_low_symbols + len_mid_symbols +
|
||||
Rd_decode_tree8(rdec, lm->bm_high);
|
||||
}
|
||||
|
||||
|
@ -637,7 +637,7 @@ static inline bool LZd_init(struct LZ_decoder * const d,
|
|||
Lm_init(&d->rep_len_model);
|
||||
|
||||
d->buffer_given = (outbuf && out_size > 0);
|
||||
d->buffer_size = d->buffer_given ? (unsigned long)out_size : dict_size;
|
||||
d->buffer_size = d->buffer_given ? out_size : dict_size;
|
||||
d->dictionary_size = min_t(unsigned long, d->buffer_size, dict_size);
|
||||
d->buffer = d->buffer_given ? outbuf : large_malloc(d->buffer_size);
|
||||
if (!d->buffer)
|
||||
|
@ -672,7 +672,7 @@ LZd_data_position(const struct LZ_decoder * const d)
|
|||
}
|
||||
|
||||
|
||||
static bool LZd_check_trailer(struct LZ_decoder * const d)
|
||||
static bool LZd_verify_trailer(struct LZ_decoder * const d)
|
||||
{
|
||||
Lzip_trailer trailer;
|
||||
int i = 0;
|
||||
|
@ -680,13 +680,13 @@ static bool LZd_check_trailer(struct LZ_decoder * const d)
|
|||
while (i < Lt_size)
|
||||
trailer[i++] = Rd_get_byte(d->rdec);
|
||||
|
||||
return Lt_get_data_crc(trailer) == LZd_crc(d) &&
|
||||
return (Lt_get_data_crc(trailer) == LZd_crc(d) &&
|
||||
Lt_get_data_size(trailer) == LZd_data_position(d) &&
|
||||
Lt_get_member_size(trailer) == Rd_member_position(d->rdec);
|
||||
Lt_get_member_size(trailer) == Rd_member_position(d->rdec));
|
||||
}
|
||||
|
||||
|
||||
/* Return value: 0 = OK, < 0 = error (see include/linux/lzip.h). */
|
||||
/* Return value: 0 = OK, < 0 = error (see <linux/lzip.h>). */
|
||||
static int LZd_decode_member(struct LZ_decoder * const d)
|
||||
{
|
||||
struct Range_decoder * const rdec = d->rdec;
|
||||
|
@ -696,8 +696,7 @@ static int LZd_decode_member(struct LZ_decoder * const d)
|
|||
unsigned rep3 = 0;
|
||||
State state = 0;
|
||||
|
||||
if (!Rd_load(rdec))
|
||||
return LZIP_BAD_DATA;
|
||||
Rd_load(rdec);
|
||||
while (!Rd_finished(rdec)) {
|
||||
int len;
|
||||
const int pos_state = LZd_data_position(d) & pos_state_mask;
|
||||
|
@ -719,7 +718,7 @@ static int LZd_decode_member(struct LZ_decoder * const d)
|
|||
if (Rd_decode_bit(rdec, &d->bm_rep[state]) != 0) {
|
||||
if (Rd_decode_bit(rdec, &d->bm_rep0[state]) == 0) {
|
||||
if (Rd_decode_bit(rdec, &d->bm_len[state][pos_state]) == 0) {
|
||||
state = St_set_shortrep(state);
|
||||
state = St_set_short_rep(state);
|
||||
LZd_put_byte(d, LZd_peek(d, rep0));
|
||||
continue;
|
||||
}
|
||||
|
@ -741,37 +740,44 @@ static int LZd_decode_member(struct LZ_decoder * const d)
|
|||
rep0 = distance;
|
||||
}
|
||||
state = St_set_rep(state);
|
||||
len = Rd_decode_len(rdec, &d->rep_len_model, pos_state);
|
||||
len = min_match_len + Rd_decode_len(rdec, &d->rep_len_model, pos_state);
|
||||
} else { /* match */
|
||||
rep3 = rep2; rep2 = rep1; rep1 = rep0;
|
||||
len = Rd_decode_len(rdec, &d->match_len_model, pos_state);
|
||||
rep0 = Rd_decode_tree6(rdec, d->bm_dis_slot[get_len_state(len)]);
|
||||
if (rep0 >= start_dis_model) {
|
||||
const unsigned dis_slot = rep0;
|
||||
unsigned distance;
|
||||
|
||||
len = min_match_len + Rd_decode_len(rdec, &d->match_len_model, pos_state);
|
||||
distance = Rd_decode_tree6(rdec, d->bm_dis_slot[get_len_state(len)]);
|
||||
if (distance >= start_dis_model) {
|
||||
const unsigned dis_slot = distance;
|
||||
const int direct_bits = (dis_slot >> 1) - 1;
|
||||
|
||||
rep0 = (2 | (dis_slot & 1)) << direct_bits;
|
||||
distance = (2 | (dis_slot & 1)) << direct_bits;
|
||||
if (dis_slot < end_dis_model)
|
||||
rep0 += Rd_decode_tree_reversed(rdec,
|
||||
d->bm_dis + (rep0 - dis_slot), direct_bits);
|
||||
distance += Rd_decode_tree_reversed(rdec,
|
||||
d->bm_dis + (distance - dis_slot), direct_bits);
|
||||
else {
|
||||
rep0 += Rd_decode(rdec, direct_bits - dis_align_bits) << dis_align_bits;
|
||||
rep0 += Rd_decode_tree_reversed4(rdec, d->bm_align);
|
||||
if (rep0 == 0xFFFFFFFFU) { /* marker found */
|
||||
distance +=
|
||||
Rd_decode(rdec, direct_bits - dis_align_bits) << dis_align_bits;
|
||||
distance += Rd_decode_tree_reversed4(rdec, d->bm_align);
|
||||
if (distance == 0xFFFFFFFFU) { /* marker found */
|
||||
Rd_normalize(rdec);
|
||||
LZd_flush_data(d);
|
||||
if (d->write_error)
|
||||
return LZIP_WRITE_ERROR;
|
||||
if (len == min_match_len) { /* End Of Stream marker */
|
||||
if (LZd_check_trailer(d))
|
||||
if (LZd_verify_trailer(d))
|
||||
return 0;
|
||||
else
|
||||
return LZIP_BAD_CRC;
|
||||
}
|
||||
if (len == min_match_len + 1) { /* Sync Flush marker */
|
||||
Rd_load(rdec);
|
||||
continue;
|
||||
}
|
||||
return LZIP_BAD_DATA; /* unknown marker */
|
||||
}
|
||||
}
|
||||
}
|
||||
rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance;
|
||||
state = St_set_match(state);
|
||||
if (rep0 >= d->dictionary_size ||
|
||||
(rep0 >= d->pos && !d->pos_wrapped)) {
|
||||
|
@ -797,7 +803,6 @@ int lzip_decompress(unsigned char *inbuf, long in_len,
|
|||
struct LZ_decoder *decoder = 0;
|
||||
int retval = 0;
|
||||
bool first_member;
|
||||
bool empty = false, multi = false;
|
||||
|
||||
if (in_posp)
|
||||
*in_posp = 0;
|
||||
|
@ -819,18 +824,18 @@ int lzip_decompress(unsigned char *inbuf, long in_len,
|
|||
if (Rd_finished(&rdec)) { /* End Of File */
|
||||
if (first_member)
|
||||
retval = LZIP_HEADER1_EOF;
|
||||
else if (Lh_check_prefix(header, size))
|
||||
else if (Lh_verify_prefix(header, size))
|
||||
retval = LZIP_HEADER2_EOF;
|
||||
break;
|
||||
}
|
||||
if (!Lh_check_magic(header)) {
|
||||
if (!Lh_verify_magic(header)) {
|
||||
if (first_member)
|
||||
retval = LZIP_BAD_MAGIC1;
|
||||
else if (Lh_check_corrupt(header))
|
||||
else if (Lh_verify_corrupt(header))
|
||||
retval = LZIP_BAD_MAGIC2;
|
||||
break;
|
||||
}
|
||||
if (!Lh_check_version(header)) {
|
||||
if (!Lh_verify_version(header)) {
|
||||
retval = LZIP_BAD_VERSION;
|
||||
break;
|
||||
}
|
||||
|
@ -851,9 +856,7 @@ int lzip_decompress(unsigned char *inbuf, long in_len,
|
|||
retval = LZd_decode_member(decoder);
|
||||
if (in_posp)
|
||||
*in_posp += Rd_member_position(&rdec);
|
||||
multi = !first_member;
|
||||
data_pos = LZd_data_position(decoder);
|
||||
if (data_pos == 0) empty = true;
|
||||
if (outptr)
|
||||
outptr += data_pos;
|
||||
if (out_posp)
|
||||
|
@ -867,14 +870,12 @@ int lzip_decompress(unsigned char *inbuf, long in_len,
|
|||
if (decoder)
|
||||
free(decoder);
|
||||
Rd_free(&rdec);
|
||||
if (empty && multi && retval == 0)
|
||||
retval = LZIP_EMPTY_MEMBER;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifndef STATIC
|
||||
EXPORT_SYMBOL_GPL(lzip_decompress);
|
||||
#endif
|
||||
MODULE_DESCRIPTION("LZIP Decompressor");
|
||||
MODULE_AUTHOR("Antonio Diaz Diaz <antonio@gnu.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif
|
124
lzip.h
124
lzip.h
|
@ -1,5 +1,5 @@
|
|||
/* Xlunzip - Test tool for the lzip_decompress linux module
|
||||
Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
/* Xlunzip - Test tool for the lunzip linux module
|
||||
Copyright (C) 2016-2018 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
|
||||
|
@ -22,43 +22,129 @@
|
|||
#define min(x,y) ((x) <= (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
void * resize_buffer( void * buf, const unsigned min_size );
|
||||
|
||||
enum {
|
||||
min_dictionary_bits = 12,
|
||||
min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */
|
||||
min_dictionary_size = 1 << min_dictionary_bits,
|
||||
max_dictionary_bits = 29,
|
||||
max_dictionary_size = 1 << max_dictionary_bits,
|
||||
min_member_size = 36 };
|
||||
|
||||
|
||||
typedef struct Pretty_print
|
||||
/* defined in main.c */
|
||||
extern int verbosity;
|
||||
|
||||
struct Pretty_print
|
||||
{
|
||||
const char * name;
|
||||
char * padded_name;
|
||||
const char * stdin_name;
|
||||
unsigned longest_name;
|
||||
bool first_post;
|
||||
} Pretty_print;
|
||||
};
|
||||
|
||||
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( len > pp->longest_name ) 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 );
|
||||
|
||||
|
||||
static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */
|
||||
|
||||
enum { Lh_size = 6 };
|
||||
typedef uint8_t Lzip_header[Lh_size]; /* 0-3 magic bytes */
|
||||
typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */
|
||||
/* 4 version */
|
||||
/* 5 coded dictionary size */
|
||||
/* 5 coded_dict_size */
|
||||
enum { Lh_size = 6 };
|
||||
|
||||
static inline bool Lh_check_magic( const Lzip_header data )
|
||||
{ return memcmp( data, lzip_magic, 4 ) == 0; }
|
||||
static inline bool Lh_verify_magic( const Lzip_header data )
|
||||
{ return ( memcmp( data, lzip_magic, 4 ) == 0 ); }
|
||||
|
||||
static inline bool Lh_check_version( const Lzip_header data )
|
||||
{ return data[4] == 1; }
|
||||
/* detect (truncated) header */
|
||||
static inline bool Lh_verify_prefix( const Lzip_header data, const int sz )
|
||||
{
|
||||
int i; for( i = 0; i < sz && i < 4; ++i )
|
||||
if( data[i] != lzip_magic[i] ) return false;
|
||||
return ( sz > 0 );
|
||||
}
|
||||
|
||||
/* detect corrupt header */
|
||||
static inline bool Lh_verify_corrupt( const Lzip_header data )
|
||||
{
|
||||
int matches = 0;
|
||||
int i; for( i = 0; i < 4; ++i )
|
||||
if( data[i] == lzip_magic[i] ) ++matches;
|
||||
return ( matches > 1 && matches < 4 );
|
||||
}
|
||||
|
||||
static inline uint8_t Lh_version( const Lzip_header data )
|
||||
{ return data[4]; }
|
||||
|
||||
static inline bool Lh_verify_version( const Lzip_header data )
|
||||
{ return ( data[4] == 1 ); }
|
||||
|
||||
static inline unsigned Lh_get_dictionary_size( const Lzip_header data )
|
||||
{
|
||||
unsigned sz = ( 1 << ( data[5] & 0x1F ) );
|
||||
if( sz > min_dictionary_size )
|
||||
sz -= ( sz / 16 ) * ( ( data[5] >> 5 ) & 7 );
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
enum { Lt_size = 20 };
|
||||
typedef uint8_t Lzip_trailer[Lt_size];
|
||||
typedef uint8_t Lzip_trailer[20];
|
||||
/* 0-3 CRC32 of the uncompressed data */
|
||||
/* 4-11 size of the uncompressed data */
|
||||
/* 12-19 member size including header and trailer */
|
||||
enum { Lt_size = 20 };
|
||||
|
||||
static inline unsigned Lt_get_data_crc( const Lzip_trailer data )
|
||||
{
|
||||
unsigned tmp = 0;
|
||||
int i; for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; }
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline unsigned long long Lt_get_data_size( const Lzip_trailer data )
|
||||
{
|
||||
|
@ -75,19 +161,13 @@ static inline unsigned long long Lt_get_member_size( 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 mem_msg = "Not enough memory.";
|
||||
|
||||
/* defined in in_place.c */
|
||||
int decompress_in_place( const int infd, Pretty_print * const pp,
|
||||
int decompress_in_place( const int infd, struct Pretty_print * const pp,
|
||||
const bool testing );
|
||||
|
||||
/* defined in main.c */
|
||||
int convert_retval( const int retval );
|
||||
long flush( void * buf, unsigned long size );
|
||||
void show_results( Pretty_print * const pp, const long in_pos,
|
||||
const long out_pos, const bool testing );
|
||||
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 );
|
||||
|
|
517
main.c
517
main.c
|
@ -1,5 +1,5 @@
|
|||
/* Xlunzip - Test tool for the lzip_decompress linux module
|
||||
Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
/* Xlunzip - Test tool for the lunzip linux module
|
||||
Copyright (C) 2016-2018 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
|
||||
|
@ -16,9 +16,9 @@
|
|||
*/
|
||||
/*
|
||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||
(file not found, invalid command-line options, I/O errors, etc), 2 to
|
||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||
error (e.g., bug) which caused xlunzip to panic.
|
||||
(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 xlunzip to panic.
|
||||
*/
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
@ -26,19 +26,18 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h> /* CHAR_BIT, SSIZE_MAX */
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h> /* SIZE_MAX */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__
|
||||
#if defined(__MSVCRT__)
|
||||
#include <io.h>
|
||||
#if defined __MSVCRT__
|
||||
#define fchmod(x,y) 0
|
||||
#define fchown(x,y,z) 0
|
||||
#define SIGHUP SIGTERM
|
||||
|
@ -50,10 +49,8 @@
|
|||
#define S_IWOTH 0
|
||||
#endif
|
||||
#endif
|
||||
#if defined __DJGPP__
|
||||
#define S_ISSOCK(x) 0
|
||||
#define S_ISVTX 0
|
||||
#endif
|
||||
#if defined(__OS2__)
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include "carg_parser.h"
|
||||
|
@ -69,48 +66,41 @@
|
|||
#error "Environments where CHAR_BIT != 8 are not supported."
|
||||
#endif
|
||||
|
||||
#if ( defined SIZE_MAX && SIZE_MAX < ULONG_MAX ) || \
|
||||
( defined SSIZE_MAX && SSIZE_MAX < LONG_MAX )
|
||||
#error "Environments where 'size_t' is narrower than 'long' are not supported."
|
||||
#endif
|
||||
int verbosity = 0;
|
||||
void cleanup_and_fail( const int retval );
|
||||
|
||||
static 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 );
|
||||
const char * const Program_name = "Xlunzip";
|
||||
const char * const program_name = "xlunzip";
|
||||
const char * const program_year = "2018";
|
||||
const char * invocation_name = 0;
|
||||
|
||||
static const char * const program_name = "xlunzip";
|
||||
static const char * const program_year = "2025";
|
||||
static const char * invocation_name = "xlunzip"; /* default value */
|
||||
|
||||
static const struct { const char * from; const char * to; } known_extensions[] = {
|
||||
const struct { const char * from; const char * to; } known_extensions[] = {
|
||||
{ ".lz", "" },
|
||||
{ ".tlz", ".tar" },
|
||||
{ 0, 0 } };
|
||||
|
||||
/* Variables used in signal handler context.
|
||||
They are not declared volatile because the handler never returns. */
|
||||
static char * output_filename = 0;
|
||||
static int outfd = -1;
|
||||
static bool delete_output_on_interrupt = false;
|
||||
char * output_filename = 0;
|
||||
int infd = -1; /* needed by the fill function */
|
||||
int outfd = -1;
|
||||
bool delete_output_on_interrupt = false;
|
||||
|
||||
|
||||
static void show_help( void )
|
||||
{
|
||||
printf( "Xlunzip is a test tool for the lzip decompression code of my lzip patch for\n"
|
||||
"linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress linux\n"
|
||||
"module as a backend. Xlunzip tests the module for stream, buffer-to-buffer,\n"
|
||||
"and mixed decompression modes, including in-place decompression (using the\n"
|
||||
"same buffer for input and output). You can use xlunzip to check that the\n"
|
||||
"module produces correct results when decompressing single member files,\n"
|
||||
"multimember files, or the concatenation of two or more compressed files.\n"
|
||||
"Xlunzip can be used with unzcrash to test the robustness of the module to\n"
|
||||
"the decompression of corrupted data.\n"
|
||||
"\nThe distributed index feature of the lzip format allows xlunzip to\n"
|
||||
"decompress concatenated files in place. This can't be guaranteed to work\n"
|
||||
"with formats like gzip or bzip2 because they can't detect whether a high\n"
|
||||
"compression ratio in the first members of the multimember data is being\n"
|
||||
"masked by a low compression ratio in the last members.\n"
|
||||
printf( "Xlunzip is a test tool for the lzip decompression code of my lzip patch\n"
|
||||
"for linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress\n"
|
||||
"linux module as a backend. Xlunzip tests the module for stream,\n"
|
||||
"buffer-to-buffer and mixed decompression modes, including in-place\n"
|
||||
"decompression (using the same buffer for input and output). You can use\n"
|
||||
"xlunzip to verify that the module produces correct results when\n"
|
||||
"decompressing single member files, multimember files, or the\n"
|
||||
"concatenation of two or more compressed files. Xlunzip can be used with\n"
|
||||
"unzcrash to test the robustness of the module to the decompression of\n"
|
||||
"corrupted data.\n"
|
||||
"\nNote that the in-place decompression of concatenated files can't be\n"
|
||||
"guaranteed to work because an arbitrarily low compression ratio of the\n"
|
||||
"last part of the data can be achieved by appending enough empty\n"
|
||||
"compressed members to a file.\n"
|
||||
"\nUsage: %s [options] [files]\n", invocation_name );
|
||||
printf( "\nOptions:\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
|
@ -120,7 +110,7 @@ static void show_help( void )
|
|||
" -f, --force overwrite existing output files\n"
|
||||
" -I, --in-place decompress or test using only one buffer\n"
|
||||
" -k, --keep keep (don't delete) input files\n"
|
||||
" -o, --output=<file> write to <file>, keep input files\n"
|
||||
" -o, --output=<file> if reading standard input, write to <file>\n"
|
||||
" -q, --quiet suppress all messages\n"
|
||||
" -t, --test test compressed file integrity\n"
|
||||
" -v, --verbose be verbose (a 2nd -v gives more)\n"
|
||||
|
@ -129,16 +119,14 @@ static void show_help( void )
|
|||
" --outsize[=<size>] pre-allocate outbuf [default 512 MiB]\n"
|
||||
" --nofill do not pass a fill function; requires --insize\n"
|
||||
" --noflush do not pass a flush function; requires --outsize\n"
|
||||
"\nIf no file names are given, or if a file is '-', xlunzip decompresses\n"
|
||||
"If no file names are given, or if a file is '-', xlunzip decompresses\n"
|
||||
"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"
|
||||
"\nTo extract all the files from archive 'foo.tar.lz', use the commands\n"
|
||||
"'tar -xf foo.tar.lz' or 'xlunzip -cd foo.tar.lz | tar -xf -'.\n"
|
||||
"\nExit status: 0 for a normal exit, 1 for environmental problems\n"
|
||||
"(file not found, invalid command-line options, I/O errors, etc), 2 to\n"
|
||||
"indicate a corrupt or invalid input file, 3 for an internal consistency\n"
|
||||
"error (e.g., bug) which caused xlunzip to panic.\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 xlunzip to panic.\n"
|
||||
"\nReport bugs to lzip-bug@nongnu.org\n"
|
||||
"Xlunzip home page: http://www.nongnu.org/lzip/xlunzip.html\n" );
|
||||
}
|
||||
|
@ -155,60 +143,23 @@ static void show_version( void )
|
|||
|
||||
|
||||
/* assure at least a minimum size for buffer 'buf' */
|
||||
static void * resize_buffer( void * buf, const unsigned min_size )
|
||||
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( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
|
||||
if( !buf )
|
||||
{
|
||||
show_error( "Not enough memory.", 0, false );
|
||||
cleanup_and_fail( 1 );
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static void Pp_init( Pretty_print * const pp,
|
||||
const char * const filenames[], const int num_filenames )
|
||||
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
|
||||
{
|
||||
pp->name = 0;
|
||||
pp->padded_name = 0;
|
||||
pp->stdin_name = "(stdin)";
|
||||
pp->longest_name = 0;
|
||||
pp->first_post = false;
|
||||
|
||||
if( verbosity <= 0 ) return;
|
||||
const unsigned stdin_name_len = strlen( pp->stdin_name );
|
||||
int i;
|
||||
for( i = 0; i < num_filenames; ++i )
|
||||
if( verbosity >= 0 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void Pp_free( Pretty_print * const pp )
|
||||
{ if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } }
|
||||
|
||||
static void Pp_set_name( Pretty_print * const pp, const char * const filename )
|
||||
{
|
||||
unsigned name_len, padded_name_len, i = 0;
|
||||
|
||||
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_show_msg( Pretty_print * const pp, const char * const msg )
|
||||
{
|
||||
if( verbosity < 0 ) return;
|
||||
if( pp->first_post )
|
||||
{
|
||||
pp->first_post = false;
|
||||
|
@ -217,63 +168,22 @@ static void Pp_show_msg( Pretty_print * const pp, const char * const msg )
|
|||
}
|
||||
if( msg ) fprintf( stderr, "%s\n", msg );
|
||||
}
|
||||
|
||||
|
||||
/* separate numbers of 5 or more digits in groups of 3 digits using '_' */
|
||||
static const char * format_num3( unsigned long long num )
|
||||
{
|
||||
enum { buffers = 8, bufsize = 4 * sizeof num, n = 10 };
|
||||
const char * const si_prefix = "kMGTPEZYRQ";
|
||||
const char * const binary_prefix = "KMGTPEZYRQ";
|
||||
static char buffer[buffers][bufsize]; /* circle of static buffers for printf */
|
||||
static int current = 0;
|
||||
int i;
|
||||
char * const buf = buffer[current++]; current %= buffers;
|
||||
char * p = buf + bufsize - 1; /* fill the buffer backwards */
|
||||
*p = 0; /* terminator */
|
||||
if( num > 9999 )
|
||||
{
|
||||
char prefix = 0; /* try binary first, then si */
|
||||
for( i = 0; i < n && num != 0 && num % 1024 == 0; ++i )
|
||||
{ num /= 1024; prefix = binary_prefix[i]; }
|
||||
if( prefix ) *(--p) = 'i';
|
||||
else
|
||||
for( i = 0; i < n && num != 0 && num % 1000 == 0; ++i )
|
||||
{ num /= 1000; prefix = si_prefix[i]; }
|
||||
if( prefix ) *(--p) = prefix;
|
||||
}
|
||||
const bool split = num >= 10000;
|
||||
|
||||
for( i = 0; ; )
|
||||
{
|
||||
*(--p) = num % 10 + '0'; num /= 10; if( num == 0 ) break;
|
||||
if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; }
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void show_option_error( const char * const arg, const char * const msg,
|
||||
const char * const option_name )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
fprintf( stderr, "%s: '%s': %s option '%s'.\n",
|
||||
program_name, arg, msg, option_name );
|
||||
}
|
||||
|
||||
|
||||
/* Recognized formats: <num>k, <num>Ki, <num>[MGTPEZYRQ][i] */
|
||||
static unsigned long getnum( const char * const arg,
|
||||
const char * const option_name,
|
||||
static unsigned long getnum( const char * const ptr,
|
||||
const unsigned long llimit,
|
||||
const unsigned long ulimit )
|
||||
{
|
||||
unsigned long result;
|
||||
char * tail;
|
||||
errno = 0;
|
||||
unsigned long result = strtoul( arg, &tail, 0 );
|
||||
if( tail == arg )
|
||||
{ show_option_error( arg, "Bad or missing numerical argument in",
|
||||
option_name ); exit( 1 ); }
|
||||
result = strtoul( ptr, &tail, 0 );
|
||||
if( tail == ptr )
|
||||
{
|
||||
show_error( "Bad or missing numerical argument.", 0, true );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if( !errno && tail[0] )
|
||||
{
|
||||
|
@ -282,8 +192,6 @@ static unsigned long getnum( const char * const arg,
|
|||
int i;
|
||||
switch( tail[0] )
|
||||
{
|
||||
case 'Q': exponent = 10; break;
|
||||
case 'R': exponent = 9; break;
|
||||
case 'Y': exponent = 8; break;
|
||||
case 'Z': exponent = 7; break;
|
||||
case 'E': exponent = 6; break;
|
||||
|
@ -295,8 +203,10 @@ static unsigned long getnum( const char * const arg,
|
|||
case 'k': if( factor == 1000 ) exponent = 1; break;
|
||||
}
|
||||
if( exponent <= 0 )
|
||||
{ show_option_error( arg, "Bad multiplier in numerical argument of",
|
||||
option_name ); exit( 1 ); }
|
||||
{
|
||||
show_error( "Bad multiplier in numerical argument.", 0, true );
|
||||
exit( 1 );
|
||||
}
|
||||
for( i = 0; i < exponent; ++i )
|
||||
{
|
||||
if( ulimit / factor >= result ) result *= factor;
|
||||
|
@ -306,10 +216,7 @@ static unsigned long getnum( const char * const arg,
|
|||
if( !errno && ( result < llimit || result > ulimit ) ) errno = ERANGE;
|
||||
if( errno )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
fprintf( stderr, "%s: '%s': Value out of limits [%s,%s] in "
|
||||
"option '%s'.\n", program_name, arg, format_num3( llimit ),
|
||||
format_num3( ulimit ), option_name );
|
||||
show_error( "Numerical argument out of limits.", 0, false );
|
||||
exit( 1 );
|
||||
}
|
||||
return result;
|
||||
|
@ -352,13 +259,13 @@ static void set_d_outname( const char * const name, const int eindex )
|
|||
strcpy( output_filename, name );
|
||||
strcat( output_filename, ".out" );
|
||||
if( verbosity >= 1 )
|
||||
fprintf( stderr, "%s: %s: Can't guess original name -- using '%s'\n",
|
||||
fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n",
|
||||
program_name, name, output_filename );
|
||||
}
|
||||
|
||||
|
||||
static int open_instream( const char * const name, struct stat * const in_statsp,
|
||||
const bool one_to_one )
|
||||
const bool no_ofile )
|
||||
{
|
||||
int infd = open( name, O_RDONLY | O_BINARY );
|
||||
if( infd < 0 )
|
||||
|
@ -367,15 +274,16 @@ static int open_instream( const char * const name, struct stat * const in_statsp
|
|||
{
|
||||
const int i = fstat( infd, in_statsp );
|
||||
const mode_t mode = in_statsp->st_mode;
|
||||
const bool can_read = i == 0 &&
|
||||
const bool can_read = ( i == 0 &&
|
||||
( S_ISBLK( mode ) || S_ISCHR( mode ) ||
|
||||
S_ISFIFO( mode ) || S_ISSOCK( mode ) );
|
||||
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) )
|
||||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
|
||||
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
fprintf( stderr, "%s: %s: Input file is not a regular file%s.\n",
|
||||
program_name, name, ( can_read && one_to_one ) ?
|
||||
",\n and neither '-c' nor '-o' were specified" : "" );
|
||||
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" : "" );
|
||||
close( infd );
|
||||
infd = -1;
|
||||
}
|
||||
|
@ -384,77 +292,53 @@ static int open_instream( const char * const name, struct stat * const in_statsp
|
|||
}
|
||||
|
||||
|
||||
static bool open_outstream( const bool force, const bool protect )
|
||||
static bool open_outstream( const bool force, const bool from_stdin )
|
||||
{
|
||||
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 = protect ? usr_rw : all_rw;
|
||||
const mode_t outfd_mode = from_stdin ? all_rw : usr_rw;
|
||||
int flags = O_APPEND | O_CREAT | O_RDWR | O_BINARY;
|
||||
if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
|
||||
|
||||
outfd = open( output_filename, flags, outfd_mode );
|
||||
if( outfd >= 0 ) delete_output_on_interrupt = true;
|
||||
else if( errno == EEXIST )
|
||||
show_file_error( output_filename,
|
||||
"Output file already exists, skipping.", 0 );
|
||||
else if( verbosity >= 0 )
|
||||
{
|
||||
if( errno == EEXIST )
|
||||
fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
|
||||
program_name, output_filename );
|
||||
else
|
||||
show_file_error( output_filename, "Can't create output file", errno );
|
||||
return outfd >= 0;
|
||||
fprintf( stderr, "%s: Can't create output file '%s': %s\n",
|
||||
program_name, output_filename, strerror( errno ) );
|
||||
}
|
||||
return ( outfd >= 0 );
|
||||
}
|
||||
|
||||
|
||||
static void set_signals( void (*action)(int) )
|
||||
void cleanup_and_fail( const int retval )
|
||||
{
|
||||
signal( SIGHUP, action );
|
||||
signal( SIGINT, action );
|
||||
signal( SIGTERM, action );
|
||||
}
|
||||
|
||||
|
||||
static void cleanup_and_fail( const int retval )
|
||||
{
|
||||
set_signals( SIG_IGN ); /* ignore signals */
|
||||
if( delete_output_on_interrupt )
|
||||
{
|
||||
delete_output_on_interrupt = false;
|
||||
show_file_error( output_filename, "Deleting output file, if it exists.", 0 );
|
||||
if( verbosity >= 0 )
|
||||
fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n",
|
||||
program_name, output_filename );
|
||||
if( outfd >= 0 ) { close( outfd ); outfd = -1; }
|
||||
if( remove( output_filename ) != 0 && errno != ENOENT )
|
||||
show_error( "warning: deletion of output file failed", errno, false );
|
||||
show_error( "WARNING: deletion of output file (apparently) failed.", 0, false );
|
||||
}
|
||||
exit( retval );
|
||||
}
|
||||
|
||||
|
||||
static void signal_handler( int sig )
|
||||
{
|
||||
if( sig ) {} /* keep compiler happy */
|
||||
show_error( "Control-C or similar caught, quitting.", 0, false );
|
||||
cleanup_and_fail( 1 );
|
||||
}
|
||||
|
||||
|
||||
static bool check_tty_in( const char * const input_filename, const int infd,
|
||||
const bool testing, int * const retval )
|
||||
{
|
||||
if( isatty( infd ) ) /* for example /dev/tty */
|
||||
{ show_file_error( input_filename,
|
||||
"I won't read compressed data from a terminal.", 0 );
|
||||
close( infd ); set_retval( retval, 2 );
|
||||
if( !testing ) cleanup_and_fail( *retval );
|
||||
return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Set permissions, owner, and times. */
|
||||
/* Set permissions, owner and times. */
|
||||
static void close_and_set_permissions( const struct stat * const in_statsp )
|
||||
{
|
||||
bool warning = false;
|
||||
if( in_statsp )
|
||||
{
|
||||
const mode_t mode = in_statsp->st_mode;
|
||||
/* fchown in many cases returns with EPERM, which can be safely ignored. */
|
||||
/* fchown will in many cases return with EPERM, which can be safely ignored. */
|
||||
if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 )
|
||||
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
|
||||
else
|
||||
|
@ -463,8 +347,10 @@ static void close_and_set_permissions( const struct stat * const in_statsp )
|
|||
warning = true;
|
||||
}
|
||||
if( close( outfd ) != 0 )
|
||||
{ show_file_error( output_filename, "Error closing output file", errno );
|
||||
cleanup_and_fail( 1 ); }
|
||||
{
|
||||
show_error( "Error closing output file", errno, false );
|
||||
cleanup_and_fail( 1 );
|
||||
}
|
||||
outfd = -1;
|
||||
delete_output_on_interrupt = false;
|
||||
if( in_statsp )
|
||||
|
@ -475,8 +361,7 @@ static void close_and_set_permissions( const struct stat * const in_statsp )
|
|||
if( utime( output_filename, &t ) != 0 ) warning = true;
|
||||
}
|
||||
if( warning && verbosity >= 1 )
|
||||
show_file_error( output_filename,
|
||||
"warning: can't change output file attributes", errno );
|
||||
show_error( "Can't change output file attributes.", 0, false );
|
||||
}
|
||||
|
||||
|
||||
|
@ -496,22 +381,19 @@ int convert_retval( const int retval )
|
|||
case LZIP_BAD_DICT_SIZE:
|
||||
case LZIP_BAD_DATA:
|
||||
case LZIP_DATA_EOF:
|
||||
case LZIP_BAD_CRC:
|
||||
case LZIP_EMPTY_MEMBER: return 2;
|
||||
case LZIP_BAD_CRC: return 2;
|
||||
default: return 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int global_infd = -1; /* needed by the fill function */
|
||||
|
||||
static long fill( void * buf, unsigned long size )
|
||||
{
|
||||
unsigned long sz = 0;
|
||||
errno = 0;
|
||||
while( sz < size )
|
||||
{
|
||||
const int n = read( global_infd, (uint8_t *)buf + sz, min( 1UL << 20, size - sz ) );
|
||||
const int n = read( infd, (uint8_t *)buf + sz, min( 1UL << 20, size - sz ) );
|
||||
if( n > 0 ) sz += n;
|
||||
else if( n == 0 ) break; /* EOF */
|
||||
else if( errno != EINTR ) break;
|
||||
|
@ -534,13 +416,13 @@ long flush( void * buf, unsigned long size )
|
|||
return sz;
|
||||
}
|
||||
|
||||
static const char * global_name; /* copy of filename for 'error' */
|
||||
const char * global_name;
|
||||
static void error(char *x) { show_file_error( global_name, x, 0 ); }
|
||||
|
||||
|
||||
static int decompress( const int infd, Pretty_print * const pp,
|
||||
const long cl_insize, const long cl_outsize,
|
||||
const bool nofill, const bool noflush, const bool testing )
|
||||
static int decompress( struct Pretty_print * const pp, const long cl_insize,
|
||||
const long cl_outsize, const bool nofill,
|
||||
const bool noflush, const bool testing )
|
||||
{
|
||||
long in_len = cl_insize;
|
||||
uint8_t * const inbuf = (in_len > 0) ? malloc( in_len ) : 0;
|
||||
|
@ -549,22 +431,19 @@ static int decompress( const int infd, Pretty_print * const pp,
|
|||
long in_pos, out_pos;
|
||||
int retval;
|
||||
if( ( in_len > 0 && !inbuf ) || ( out_size > 0 && !outbuf ) )
|
||||
{ show_error( mem_msg, 0, false ); return 1; }
|
||||
{ show_error( "Not enough memory.", 0, false ); return 1; }
|
||||
|
||||
global_infd = infd;
|
||||
if( inbuf )
|
||||
{
|
||||
const long len = fill( inbuf, in_len );
|
||||
if( len < in_len )
|
||||
{ if( errno ) { show_file_error( pp->name, "Read error", errno );
|
||||
global_infd = -1; return 1; }
|
||||
{ if( errno ) { show_file_error( pp->name, "Read error", errno ); return 1; }
|
||||
in_len = len; }
|
||||
}
|
||||
global_name = pp->name;
|
||||
retval = convert_retval( __lunzip( inbuf, in_len, nofill ? 0 : fill,
|
||||
noflush ? 0 : flush, outbuf, out_size,
|
||||
&in_pos, &out_pos, error ) );
|
||||
global_infd = -1;
|
||||
if( retval ) return retval;
|
||||
if( outbuf && noflush )
|
||||
{
|
||||
|
@ -572,14 +451,6 @@ static int decompress( const int infd, Pretty_print * const pp,
|
|||
if( len < out_pos )
|
||||
{ show_file_error( pp->name, "Write error", errno ); return 1; }
|
||||
}
|
||||
show_results( pp, in_pos, out_pos, testing );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void show_results( Pretty_print * const pp, const long in_pos,
|
||||
const long out_pos, const bool testing )
|
||||
{
|
||||
if( verbosity >= 1 ) Pp_show_msg( pp, 0 );
|
||||
if( verbosity >= 2 )
|
||||
{
|
||||
|
@ -591,14 +462,32 @@ void show_results( Pretty_print * const pp, const long in_pos,
|
|||
( 100.0 * in_pos ) / out_pos,
|
||||
100.0 - ( ( 100.0 * in_pos ) / out_pos ) );
|
||||
if( verbosity >= 3 )
|
||||
fprintf( stderr, "%9lu out, %8lu in. ", out_pos, in_pos );
|
||||
fprintf( stderr, "decompressed %9lu, compressed %8lu. ",
|
||||
out_pos, in_pos );
|
||||
}
|
||||
if( verbosity >= 1 ) fputs( testing ? "ok\n" : "done\n", stderr );
|
||||
if( verbosity >= 1 )
|
||||
fputs( testing ? "ok\n" : "done\n", stderr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void show_error( const char * const msg, const int errcode,
|
||||
const bool help )
|
||||
void signal_handler( int sig )
|
||||
{
|
||||
if( sig ) {} /* keep compiler happy */
|
||||
show_error( "Control-C or similar caught, quitting.", 0, false );
|
||||
cleanup_and_fail( 1 );
|
||||
}
|
||||
|
||||
|
||||
static void set_signals( void )
|
||||
{
|
||||
signal( SIGHUP, signal_handler );
|
||||
signal( SIGINT, signal_handler );
|
||||
signal( SIGTERM, signal_handler );
|
||||
}
|
||||
|
||||
|
||||
void show_error( const char * const msg, const int errcode, const bool help )
|
||||
{
|
||||
if( verbosity < 0 ) return;
|
||||
if( msg && msg[0] )
|
||||
|
@ -621,7 +510,7 @@ void show_file_error( const char * const filename, const char * const msg,
|
|||
}
|
||||
|
||||
|
||||
static void internal_error( const char * const msg )
|
||||
void internal_error( const char * const msg )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
|
||||
|
@ -632,19 +521,27 @@ static void internal_error( const char * const msg )
|
|||
int main( const int argc, const char * const argv[] )
|
||||
{
|
||||
const char * default_output_filename = "";
|
||||
const char ** filenames = 0;
|
||||
long cl_insize = 0;
|
||||
long cl_outsize = 0;
|
||||
int num_filenames = 0;
|
||||
int argind = 0;
|
||||
int failed_tests = 0;
|
||||
int retval = 0;
|
||||
int i;
|
||||
bool filenames_given = false;
|
||||
bool force = false;
|
||||
bool in_place = false;
|
||||
bool keep_input_files = false;
|
||||
bool nofill = false;
|
||||
bool noflush = false;
|
||||
bool stdin_used = false;
|
||||
bool testing = false;
|
||||
bool to_stdout = false;
|
||||
if( argc > 0 ) invocation_name = argv[0];
|
||||
struct Pretty_print pp;
|
||||
|
||||
enum { opt_insize = 256, opt_outsize, opt_nofill, opt_noflush };
|
||||
const ap_Option options[] =
|
||||
const struct ap_Option options[] =
|
||||
{
|
||||
{ 'c', "stdout", ap_no },
|
||||
{ 'd', "decompress", ap_no },
|
||||
|
@ -664,20 +561,19 @@ int main( const int argc, const char * const argv[] )
|
|||
{ opt_noflush, "noflush", ap_no },
|
||||
{ 0 , 0, ap_no } };
|
||||
|
||||
/* static because valgrind complains and memory management in C sucks */
|
||||
static Arg_parser parser;
|
||||
struct Arg_parser parser;
|
||||
invocation_name = argv[0];
|
||||
|
||||
if( !ap_init( &parser, argc, argv, options, 0 ) )
|
||||
{ show_error( mem_msg, 0, false ); return 1; }
|
||||
{ show_error( "Not enough memory.", 0, false ); return 1; }
|
||||
if( ap_error( &parser ) ) /* bad option */
|
||||
{ show_error( ap_error( &parser ), 0, true ); return 1; }
|
||||
|
||||
int argind = 0;
|
||||
for( ; argind < ap_arguments( &parser ); ++argind )
|
||||
{
|
||||
const int code = ap_code( &parser, argind );
|
||||
if( !code ) break; /* no more options */
|
||||
const char * const pn = ap_parsed_name( &parser, argind );
|
||||
const char * const arg = ap_argument( &parser, argind );
|
||||
if( !code ) break; /* no more options */
|
||||
switch( code )
|
||||
{
|
||||
case 'c': to_stdout = true; break;
|
||||
|
@ -686,17 +582,16 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'h': show_help(); return 0;
|
||||
case 'I': in_place = true; break;
|
||||
case 'k': keep_input_files = true; break;
|
||||
case 'n': break; /* ignored */
|
||||
case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true;
|
||||
else { default_output_filename = arg; } break;
|
||||
case 'n': break;
|
||||
case 'o': default_output_filename = arg; break;
|
||||
case 'q': verbosity = -1; break;
|
||||
case 't': testing = true; break;
|
||||
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
||||
case 'V': show_version(); return 0;
|
||||
case opt_insize:
|
||||
cl_insize = arg[0] ? getnum( arg, pn, 1, LONG_MAX ) : 16384; break;
|
||||
cl_insize = arg[0] ? getnum( arg, 1, LONG_MAX ) : 16384; break;
|
||||
case opt_outsize: cl_outsize = arg[0] ?
|
||||
getnum( arg, pn, min_dictionary_size, LONG_MAX ) : max_dictionary_size;
|
||||
getnum( arg, min_dictionary_size, LONG_MAX ) : max_dictionary_size;
|
||||
break;
|
||||
case opt_nofill: nofill = true; break;
|
||||
case opt_noflush: noflush = true; break;
|
||||
|
@ -704,113 +599,121 @@ int main( const int argc, const char * const argv[] )
|
|||
}
|
||||
} /* end process options */
|
||||
|
||||
#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__
|
||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||
setmode( STDIN_FILENO, O_BINARY );
|
||||
setmode( STDOUT_FILENO, O_BINARY );
|
||||
#endif
|
||||
|
||||
static const char ** filenames = 0;
|
||||
int num_filenames = max( 1, ap_arguments( &parser ) - argind );
|
||||
num_filenames = max( 1, ap_arguments( &parser ) - argind );
|
||||
filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] );
|
||||
filenames[0] = "-";
|
||||
|
||||
int i;
|
||||
bool filenames_given = false;
|
||||
for( i = 0; argind + i < ap_arguments( &parser ); ++i )
|
||||
{
|
||||
filenames[i] = ap_argument( &parser, argind + i );
|
||||
if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true;
|
||||
}
|
||||
|
||||
if( testing ) to_stdout = false; /* apply overrides */
|
||||
if( testing || to_stdout ) default_output_filename = "";
|
||||
if( testing )
|
||||
outfd = -1;
|
||||
|
||||
output_filename = resize_buffer( output_filename, 1 );
|
||||
output_filename[0] = 0;
|
||||
if( to_stdout && !testing ) outfd = STDOUT_FILENO;
|
||||
else outfd = -1;
|
||||
if( !to_stdout && !testing &&
|
||||
( filenames_given || default_output_filename[0] ) )
|
||||
set_signals();
|
||||
|
||||
const bool to_file = !to_stdout && !testing && default_output_filename[0];
|
||||
if( !to_stdout && !testing && ( filenames_given || to_file ) )
|
||||
set_signals( signal_handler );
|
||||
|
||||
static Pretty_print pp;
|
||||
Pp_init( &pp, filenames, num_filenames );
|
||||
|
||||
int failed_tests = 0;
|
||||
int retval = 0;
|
||||
const bool one_to_one = !to_stdout && !testing && !to_file;
|
||||
bool stdin_used = false;
|
||||
struct stat in_stats;
|
||||
output_filename = resize_buffer( output_filename, 1 );
|
||||
for( i = 0; i < num_filenames; ++i )
|
||||
{
|
||||
const char * input_filename = "";
|
||||
int infd;
|
||||
int tmp;
|
||||
struct stat in_stats;
|
||||
const struct stat * in_statsp;
|
||||
output_filename[0] = 0;
|
||||
|
||||
Pp_set_name( &pp, filenames[i] );
|
||||
if( strcmp( filenames[i], "-" ) == 0 )
|
||||
if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 )
|
||||
{
|
||||
if( stdin_used ) continue; else stdin_used = true;
|
||||
infd = STDIN_FILENO;
|
||||
if( !check_tty_in( pp.name, infd, testing, &retval ) ) continue;
|
||||
if( one_to_one ) { outfd = STDOUT_FILENO; output_filename[0] = 0; }
|
||||
}
|
||||
if( !testing )
|
||||
{
|
||||
if( to_stdout || !default_output_filename[0] )
|
||||
outfd = STDOUT_FILENO;
|
||||
else
|
||||
{
|
||||
input_filename = filenames[i];
|
||||
infd = open_instream( input_filename, &in_stats, one_to_one );
|
||||
if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
|
||||
if( !check_tty_in( pp.name, infd, testing, &retval ) ) continue;
|
||||
if( one_to_one ) /* open outfd after checking infd */
|
||||
{
|
||||
set_d_outname( input_filename, extension_index( input_filename ) );
|
||||
if( !open_outstream( force, true ) )
|
||||
{ close( infd ); set_retval( &retval, 1 ); continue; }
|
||||
}
|
||||
}
|
||||
|
||||
if( to_file && outfd < 0 ) /* open outfd after checking infd */
|
||||
{
|
||||
output_filename = resize_buffer( output_filename,
|
||||
strlen( default_output_filename ) + 1 );
|
||||
strcpy( output_filename, default_output_filename );
|
||||
if( !open_outstream( force, false ) ) return 1;
|
||||
if( !open_outstream( force, true ) )
|
||||
{
|
||||
if( retval < 1 ) retval = 1;
|
||||
close( infd ); infd = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
input_filename = filenames[i];
|
||||
infd = open_instream( input_filename, &in_stats, to_stdout || testing );
|
||||
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
|
||||
if( !testing )
|
||||
{
|
||||
if( to_stdout ) outfd = STDOUT_FILENO;
|
||||
else
|
||||
{
|
||||
set_d_outname( input_filename, extension_index( input_filename ) );
|
||||
if( !open_outstream( force, false ) )
|
||||
{
|
||||
if( retval < 1 ) retval = 1;
|
||||
close( infd ); infd = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const struct stat * const in_statsp =
|
||||
( input_filename[0] && one_to_one ) ? &in_stats : 0;
|
||||
int tmp;
|
||||
Pp_set_name( &pp, input_filename );
|
||||
if( isatty( infd ) )
|
||||
{
|
||||
show_file_error( pp.name,
|
||||
"I won't read compressed data from a terminal.", 0 );
|
||||
if( retval < 1 ) retval = 1;
|
||||
if( testing ) { close( infd ); infd = -1; continue; }
|
||||
cleanup_and_fail( retval );
|
||||
}
|
||||
|
||||
in_statsp = input_filename[0] ? &in_stats : 0;
|
||||
if( in_place )
|
||||
tmp = decompress_in_place( infd, &pp, testing );
|
||||
else
|
||||
tmp = decompress( infd, &pp, cl_insize, cl_outsize, nofill, noflush, testing );
|
||||
if( close( infd ) != 0 )
|
||||
{ show_file_error( pp.name, "Error closing input file", errno );
|
||||
set_retval( &tmp, 1 ); }
|
||||
set_retval( &retval, tmp );
|
||||
tmp = decompress( &pp, cl_insize, cl_outsize, nofill, noflush, testing );
|
||||
if( tmp > retval ) retval = tmp;
|
||||
if( tmp )
|
||||
{ if( !testing ) cleanup_and_fail( retval );
|
||||
else ++failed_tests; }
|
||||
|
||||
if( delete_output_on_interrupt && one_to_one )
|
||||
if( delete_output_on_interrupt )
|
||||
close_and_set_permissions( in_statsp );
|
||||
if( input_filename[0] && !keep_input_files && one_to_one )
|
||||
if( input_filename[0] )
|
||||
{
|
||||
close( infd ); infd = -1;
|
||||
if( !keep_input_files && !to_stdout && !testing )
|
||||
remove( input_filename );
|
||||
}
|
||||
if( delete_output_on_interrupt ) /* -o */
|
||||
close_and_set_permissions( ( retval == 0 && !stdin_used &&
|
||||
filenames_given && num_filenames == 1 ) ? &in_stats : 0 );
|
||||
else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */
|
||||
}
|
||||
if( outfd >= 0 && close( outfd ) != 0 )
|
||||
{
|
||||
show_error( "Error closing stdout", errno, false );
|
||||
set_retval( &retval, 1 );
|
||||
if( retval < 1 ) retval = 1;
|
||||
}
|
||||
if( failed_tests > 0 && verbosity >= 1 && num_filenames > 1 )
|
||||
fprintf( stderr, "%s: warning: %d %s failed the test.\n",
|
||||
program_name, failed_tests,
|
||||
( failed_tests == 1 ) ? "file" : "files" );
|
||||
free( output_filename );
|
||||
Pp_free( &pp );
|
||||
free( filenames );
|
||||
ap_free( &parser );
|
||||
return retval;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#! /bin/sh
|
||||
# check script for Xlunzip - Test tool for the lzip_decompress linux module
|
||||
# Copyright (C) 2016-2025 Antonio Diaz Diaz.
|
||||
# check script for Xlunzip - Test tool for the lunzip linux module
|
||||
# Copyright (C) 2016-2018 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
|
||||
|
@ -28,11 +28,9 @@ if [ -d tmp ] ; then rm -rf tmp ; fi
|
|||
mkdir tmp
|
||||
cd "${objdir}"/tmp || framework_failure
|
||||
|
||||
cp "${testdir}"/test.txt in || framework_failure
|
||||
cat "${testdir}"/test.txt > in || framework_failure
|
||||
in_lz="${testdir}"/test.txt.lz
|
||||
em_lz="${testdir}"/em.lz
|
||||
fox_lz="${testdir}"/fox.lz
|
||||
fnz_lz="${testdir}"/fox_nz.lz
|
||||
zero_lz="${testdir}"/zero.lz
|
||||
fail=0
|
||||
test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; }
|
||||
|
||||
|
@ -48,15 +46,8 @@ printf "testing xlunzip-%s..." "$2"
|
|||
[ $? = 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
|
||||
# these are for code coverage
|
||||
"${LZIP}" -t -- nx_file.lz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -t "" < /dev/null 2> /dev/null
|
||||
"${LZIP}" -t -- nx_file 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --help > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -n1 -V > /dev/null || test_failed $LINENO
|
||||
|
@ -81,352 +72,212 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null
|
|||
printf "\ntesting decompression..."
|
||||
|
||||
"${LZIP}" -t "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -d "${in_lz}" -o out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -cd "${in_lz}" > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d "${in_lz}" -o - > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d < "${in_lz}" > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
cp "${in_lz}" out.lz || framework_failure
|
||||
"${LZIP}" -dk out.lz || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO
|
||||
cp fox copy || framework_failure
|
||||
cp "${in_lz}" copy.lz || framework_failure
|
||||
"${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out
|
||||
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
|
||||
printf "to be overwritten" > copy || framework_failure
|
||||
"${LZIP}" -d copy.lz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ ! -e out.lz ] || test_failed $LINENO
|
||||
cmp fox copy || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -df copy.lz || test_failed $LINENO
|
||||
[ ! -e copy.lz ] || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
rm -f copy out || framework_failure
|
||||
|
||||
printf "to be overwritten" > out || framework_failure
|
||||
"${LZIP}" -df -o out < "${in_lz}" || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${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
|
||||
printf "to be overwritten" > copy || framework_failure
|
||||
"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
cp "${in_lz}" anyothername || framework_failure
|
||||
"${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null ||
|
||||
rm -f copy || framework_failure
|
||||
cat "${in_lz}" > anyothername || framework_failure
|
||||
"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null ||
|
||||
test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
cmp in anyothername.out || test_failed $LINENO
|
||||
rm -f anyothername.out || framework_failure
|
||||
rm -f copy anyothername.out || framework_failure
|
||||
|
||||
"${LZIP}" -tq in "${in_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq nx_file.lz "${in_lz}"
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq in "${in_lz}" > out
|
||||
"${LZIP}" -cdq in "${in_lz}" > copy
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cat out in | cmp in - || test_failed $LINENO # out must be empty
|
||||
"${LZIP}" -cdq nx_file.lz "${in_lz}" > out # skip nx_file, decompress in
|
||||
cat copy in | cmp in - || test_failed $LINENO
|
||||
"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
cp "${in_lz}" out.lz || framework_failure
|
||||
"${LZIP}" -dq in out.lz
|
||||
cmp in copy || test_failed $LINENO
|
||||
rm -f copy || framework_failure
|
||||
cat "${in_lz}" > copy.lz || framework_failure
|
||||
"${LZIP}" -dq in copy.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
[ -e out.lz ] || test_failed $LINENO
|
||||
[ ! -e out ] || test_failed $LINENO
|
||||
[ -e copy.lz ] || test_failed $LINENO
|
||||
[ ! -e copy ] || test_failed $LINENO
|
||||
[ ! -e in.out ] || test_failed $LINENO
|
||||
"${LZIP}" -dq nx_file.lz out.lz
|
||||
"${LZIP}" -dq nx_file.lz copy.lz
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ ! -e out.lz ] || test_failed $LINENO
|
||||
[ ! -e copy.lz ] || test_failed $LINENO
|
||||
[ ! -e nx_file ] || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
cat in in > in2 || framework_failure
|
||||
"${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > out2 || test_failed $LINENO
|
||||
[ ! -e out ] || test_failed $LINENO # override -o
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
rm -f out2 || framework_failure
|
||||
"${LZIP}" -d "${in_lz}" "${in_lz}" -o out2 || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
rm -f out2 || 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
|
||||
cmp in2 copy2 || test_failed $LINENO
|
||||
|
||||
cat "${in_lz}" "${in_lz}" > out2.lz || framework_failure
|
||||
lines=`"${LZIP}" -tvv out2.lz 2>&1 | wc -l` || test_failed $LINENO
|
||||
[ "${lines}" -eq 1 ] || test_failed $LINENO "${lines}"
|
||||
|
||||
printf "\ngarbage" >> out2.lz || framework_failure
|
||||
"${LZIP}" -tvvvv out2.lz 2> /dev/null || test_failed $LINENO
|
||||
printf "to be overwritten" > out2 || framework_failure
|
||||
"${LZIP}" -df out2.lz || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
|
||||
touch empty || framework_failure
|
||||
cp "${em_lz}" em.lz || framework_failure
|
||||
"${LZIP}" -dk em.lz || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
cat in2.lz > copy2.lz || framework_failure
|
||||
printf "\ngarbage" >> copy2.lz || framework_failure
|
||||
printf "to be overwritten" > copy2 || framework_failure
|
||||
"${LZIP}" -df copy2.lz || test_failed $LINENO
|
||||
cmp in2 copy2 || test_failed $LINENO
|
||||
|
||||
printf "\ntesting bad input..."
|
||||
|
||||
cat em.lz em.lz | "${LZIP}" -tq
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cat em.lz em.lz | "${LZIP}" -dq > em
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
cat em.lz "${in_lz}" | "${LZIP}" -tq
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cat em.lz "${in_lz}" | "${LZIP}" -dq > out
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
cat "${in_lz}" em.lz | "${LZIP}" -tq
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cat "${in_lz}" em.lz | "${LZIP}" -dq > out
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
cat em.lz em.lz > ee.lz || framework_failure
|
||||
"${LZIP}" -tq < ee.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -dq < ee.lz > em
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
"${LZIP}" -tq ee.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -dq ee.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
[ ! -e ee ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq ee.lz > em
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp empty em || test_failed $LINENO
|
||||
rm -f em || framework_failure
|
||||
cat "${in_lz}" em.lz "${in_lz}" > inein.lz || framework_failure
|
||||
"${LZIP}" -tq < inein.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -dq < inein.lz > out2
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
"${LZIP}" -tq inein.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -dq inein.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
[ ! -e inein ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq inein.lz > out2
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
rm -f out2 inein.lz em.lz || framework_failure
|
||||
|
||||
headers='LZIp LZiP LZip LzIP LzIp LziP lZIP lZIp lZiP lzIP'
|
||||
body='\001\014\000\000\101\376\367\377\377\340\000\200\000\215\357\002\322\001\000\000\000\000\000\000\000\045\000\000\000\000\000\000\000'
|
||||
cp "${in_lz}" int.lz || framework_failure
|
||||
printf "LZIP${body}" >> int.lz || framework_failure
|
||||
if "${LZIP}" -t int.lz ; then
|
||||
body='\001\014\000\203\377\373\377\377\300\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000'
|
||||
cat "${in_lz}" > int.lz
|
||||
printf "LZIP${body}" >> int.lz
|
||||
if "${LZIP}" -tq int.lz ; then
|
||||
for header in ${headers} ; do
|
||||
printf "${header}${body}" > int.lz || framework_failure
|
||||
"${LZIP}" -tq int.lz # first member
|
||||
printf "${header}${body}" > int.lz # first member
|
||||
"${LZIP}" -tq int.lz
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -tq < int.lz
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -cdq int.lz > /dev/null
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
cp "${in_lz}" int.lz || framework_failure
|
||||
printf "${header}${body}" >> int.lz || framework_failure
|
||||
"${LZIP}" -tq int.lz # trailing data
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -tq < int.lz
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
"${LZIP}" -cdq int.lz > /dev/null
|
||||
cat "${in_lz}" > int.lz
|
||||
printf "${header}${body}" >> int.lz # trailing data
|
||||
"${LZIP}" -tq int.lz
|
||||
[ $? = 2 ] || test_failed $LINENO ${header}
|
||||
done
|
||||
else
|
||||
printf "warning: skipping header test: 'printf' does not work on your system."
|
||||
printf "\nwarning: skipping header test: 'printf' does not work on your system."
|
||||
fi
|
||||
rm -f int.lz || framework_failure
|
||||
|
||||
"${LZIP}" -tq "${fnz_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
||||
for i in fox_v2.lz fox_s11.lz fox_de20.lz \
|
||||
fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do
|
||||
"${LZIP}" -tq "${testdir}"/$i
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
done
|
||||
|
||||
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 || 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=14682 count=1 2> /dev/null &&
|
||||
[ -e trunc.lz ] && cmp in2.lz trunc.lz ; then
|
||||
for i in 6 20 14664 14683 14684 14685 14686 14687 14688 ; do
|
||||
if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null &&
|
||||
[ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then
|
||||
for i in 6 20 14734 14753 14754 14755 14756 14757 14758 ; do
|
||||
dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null
|
||||
"${LZIP}" -tq trunc.lz
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -tq < trunc.lz
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -cdq trunc.lz > /dev/null
|
||||
"${LZIP}" -cdq trunc.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -dq < trunc.lz > /dev/null
|
||||
"${LZIP}" -dq < trunc.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
done
|
||||
else
|
||||
printf "warning: skipping truncation test: 'dd' does not work on your system."
|
||||
printf "\nwarning: skipping truncation test: 'dd' does not work on your system."
|
||||
fi
|
||||
rm -f trunc.lz || framework_failure
|
||||
rm -f trunc.lz out || framework_failure
|
||||
|
||||
cp "${in_lz}" ingin.lz || framework_failure
|
||||
cat "${in_lz}" > ingin.lz || framework_failure
|
||||
printf "g" >> ingin.lz || framework_failure
|
||||
cat "${in_lz}" >> ingin.lz || framework_failure
|
||||
"${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}" -dk ingin.lz || test_failed $LINENO
|
||||
cmp in ingin || test_failed $LINENO
|
||||
"${LZIP}" -cd ingin.lz > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d < ingin.lz > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
printf "\ntesting linux options..."
|
||||
|
||||
for i in "" =1 =2 =4 =16 =64 =256 =1024 =4096 =16384 =65536 ; do
|
||||
"${LZIP}" -t --insize$i "${in_lz}" || test_failed $LINENO $i
|
||||
"${LZIP}" -cd --insize$i "${in_lz}" > out || test_failed $LINENO $i
|
||||
cmp in out || test_failed $LINENO $i
|
||||
"${LZIP}" -cd --insize$i "${in_lz}" > copy || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
|
||||
for i in =1 =2 =4 =16 =64 =256 =1024 =4096 ; do
|
||||
"${LZIP}" -tq --insize$i --nofill "${in_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -cdq --insize$i --nofill "${in_lz}" > out
|
||||
"${LZIP}" -cdq --insize$i --nofill "${in_lz}" > copy
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
cmp -s in out && test_failed $LINENO $i
|
||||
cmp -s in copy && test_failed $LINENO $i
|
||||
done
|
||||
|
||||
for i in "" =16384 =65536 ; do
|
||||
"${LZIP}" -t --insize$i --nofill "${in_lz}" || test_failed $LINENO $i
|
||||
"${LZIP}" -cd --insize$i --nofill "${in_lz}" > out ||
|
||||
"${LZIP}" -cd --insize$i --nofill "${in_lz}" > copy ||
|
||||
test_failed $LINENO $i
|
||||
cmp in out || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
|
||||
for i in =18KiB =65536 =262144 ; do
|
||||
"${LZIP}" -t --outsize$i "${in_lz}" || test_failed $LINENO $i
|
||||
"${LZIP}" -cd --outsize$i "${in_lz}" > out ||
|
||||
"${LZIP}" -cd --outsize$i "${in_lz}" > copy ||
|
||||
test_failed $LINENO $i
|
||||
cmp in out || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
|
||||
for i in =36301 =65536 =262144 ; do
|
||||
for i in =36388 =65536 =262144 ; do
|
||||
"${LZIP}" -t --outsize$i --noflush "${in_lz}" ||
|
||||
test_failed $LINENO $i
|
||||
"${LZIP}" -cd --outsize$i --noflush "${in_lz}" > out ||
|
||||
"${LZIP}" -cd --outsize$i --noflush "${in_lz}" > copy ||
|
||||
test_failed $LINENO $i
|
||||
cmp in out || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
|
||||
for i in =36300 ; do
|
||||
for i in =36387 ; do
|
||||
"${LZIP}" -tq --outsize$i --noflush "${in_lz}"
|
||||
[ $? = 1 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > out
|
||||
"${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > copy
|
||||
[ $? = 1 ] || test_failed $LINENO $i
|
||||
cmp -s in out && test_failed $LINENO $i
|
||||
cmp -s in copy && test_failed $LINENO $i
|
||||
done
|
||||
|
||||
for i in =4096 =16384 ; do
|
||||
"${LZIP}" -tq --outsize$i --noflush "${in_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > out
|
||||
"${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > copy
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
cmp -s in out && test_failed $LINENO $i
|
||||
cmp -s in copy && test_failed $LINENO $i
|
||||
done
|
||||
|
||||
"${LZIP}" -t --insize --outsize=36388 --nofill --noflush "${in_lz}" ||
|
||||
test_failed $LINENO
|
||||
"${LZIP}" -cd --insize --outsize=36388 --nofill --noflush "${in_lz}" > out ||
|
||||
"${LZIP}" -cd --insize --outsize=36388 --nofill --noflush "${in_lz}" > copy ||
|
||||
test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
"${LZIP}" -tq --nofill "${in_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq --nofill "${in_lz}" > out
|
||||
"${LZIP}" -cdq --nofill "${in_lz}" > copy
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp -s in out && test_failed $LINENO
|
||||
cmp -s in copy && test_failed $LINENO
|
||||
"${LZIP}" -tq --noflush "${in_lz}"
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq --noflush "${in_lz}" > out
|
||||
"${LZIP}" -cdq --noflush "${in_lz}" > copy
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
cmp -s in out && test_failed $LINENO
|
||||
cmp -s in copy && test_failed $LINENO
|
||||
|
||||
# decompress in place
|
||||
rm -f out out2 || framework_failure
|
||||
"${LZIP}" -t --in-place "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -t --in-place < "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -d --in-place "${in_lz}" -o out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -d --in-place < "${in_lz}" -o out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place "${in_lz}" > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place < "${in_lz}" > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
"${LZIP}" -t --in-place "${in_lz}" "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -d --in-place "${in_lz}" "${in_lz}" -o out2 || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place "${in_lz}" "${in_lz}" > out2 || test_failed $LINENO
|
||||
cmp in2 out2 || test_failed $LINENO
|
||||
|
||||
# decompress multimember in place
|
||||
"${LZIP}" -cd --in-place "${in_lz}" > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
cat in in in > in3 || framework_failure
|
||||
for i in in2 in3 ; do
|
||||
"${LZIP}" -t --in-place $i.lz || test_failed $LINENO
|
||||
"${LZIP}" -t --in-place < $i.lz || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -d --in-place $i.lz -o out || test_failed $LINENO
|
||||
cmp $i out || test_failed $LINENO
|
||||
rm -f out || framework_failure
|
||||
"${LZIP}" -d --in-place < $i.lz -o out || test_failed $LINENO
|
||||
cmp $i out || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place $i.lz > out || test_failed $LINENO
|
||||
cmp $i out || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place < $i.lz > out || test_failed $LINENO
|
||||
cmp $i out || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place $i.lz > copy || test_failed $LINENO
|
||||
cmp $i copy || test_failed $LINENO
|
||||
done
|
||||
"${LZIP}" -tq --in-place ingin.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
rm -f out2 ingin.lz in2 in2.lz in3 in3.lz || framework_failure
|
||||
|
||||
cat "${in_lz}" "${em_lz}" > ine.lz || framework_failure
|
||||
"${LZIP}" -tq --in-place ine.lz
|
||||
cat "${in_lz}" "${zero_lz}" "${zero_lz}" "${zero_lz}" "${zero_lz}" \
|
||||
"${zero_lz}" "${zero_lz}" "${zero_lz}" > inz.lz || framework_failure
|
||||
"${LZIP}" -t --in-place inz.lz || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place inz.lz > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
cat "${zero_lz}" >> inz.lz || framework_failure
|
||||
"${LZIP}" -tq --in-place inz.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq --in-place ine.lz > out
|
||||
"${LZIP}" -cdq --in-place inz.lz > copy
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp empty out || test_failed $LINENO
|
||||
cat "${em_lz}" "${in_lz}" > ine.lz || framework_failure
|
||||
"${LZIP}" -tq --in-place ine.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq --in-place ine.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
cmp empty out || test_failed $LINENO
|
||||
rm -f ine.lz empty || framework_failure
|
||||
|
||||
# decompress with trailing data in place
|
||||
cat "${in_lz}" in in in in > int.lz || framework_failure
|
||||
"${LZIP}" -t --in-place int.lz || test_failed $LINENO
|
||||
"${LZIP}" -cd --in-place int.lz > out || test_failed $LINENO
|
||||
cmp in out || test_failed $LINENO
|
||||
rm -f out int.lz || framework_failure
|
||||
cmp -s in copy && test_failed $LINENO
|
||||
rm -f copy ingin.lz in2 in2.lz in3 in3.lz || framework_failure
|
||||
|
||||
echo
|
||||
if [ ${fail} = 0 ] ; then
|
||||
|
|
BIN
testsuite/fox.lz
BIN
testsuite/fox.lz
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,7 +1,8 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
@ -338,7 +339,8 @@ Public License instead of this License.
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue