diff --git a/ChangeLog b/ChangeLog index 5d52edb..74c2b8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,16 @@ -2023-12-21 Antonio Diaz Diaz +2025-01-07 Antonio Diaz Diaz - * Version 1.13-rc1 released. + * Version 1.14 released. + * main.c (decompress): Return 2 if empty member in multimember file. + (Pp_free): New function. + * check.sh: Use 'cp' instead of 'cat'. + +2024-01-21 Antonio Diaz Diaz + + * Version 1.13 released. * main.c: Reformat file diagnostics as 'PROGRAM: FILE: MESSAGE'. (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'. @@ -38,12 +46,12 @@ 2018-02-04 Antonio Diaz Diaz * Version 1.9 released. - * main.c: New option '--loose-trailing'. - * main.c (decompress): Improve corrupt header detection to HD=3. + * New option '--loose-trailing'. * Replace 'bits/byte' with inverse compression ratio in output. - * main.c: Show final diagnostic when testing multiple files. - * main.c: Do not add a second .lz extension to the arg of -o. - * main.c (lzip_decode): Show stored sizes also in hex. + * main.c (decompress): Improve corrupt header detection to HD=3. + (main): Show final diagnostic when testing multiple files. + (set_c_outname): Do not add a second '.lz' to the arg of '-o'. + (lzip_decode): Show stored sizes also in hex. Show dictionary size at verbosity level 4 (-vvvv). 2017-04-12 Antonio Diaz Diaz @@ -57,10 +65,9 @@ * Version 1.7 released. * main.c: New option '-a, --trailing-error'. * main.c (main): Delete '--output' file if infd is a terminal. - * main.c (main): Don't use stdin more than once. + (main): Don't use stdin more than once. * configure: Avoid warning on some shells when testing for gcc. - * check.sh: A POSIX shell is required to run the tests. - * check.sh: Don't check error messages. + * check.sh: Require a POSIX shell. Don't check error messages. 2015-05-26 Antonio Diaz Diaz @@ -77,16 +84,16 @@ 2013-05-27 Antonio Diaz Diaz * Version 1.4 released. + * Decompression time has been reduced by 5%. * main.c: New options '-f, --force', '-F, --recompress', '-k, --keep', and '-o, --output'. - * main.c: Accept more than one file in command line. - * Decompression time has been reduced by 5%. - * main.c: '--test' no longer needs '/dev/null'. - * Fix return value of '-d' and '-t' in case of data error. - * main.c: Change info shown at verbosity levels 2 and 3. - * Ignore option '-n, --threads' for compatibility with plzip. + Accept more than one file in command line. + (main): '--test' no longer needs '/dev/null'. + (main): Fix return value of '-d' and '-t' in case of data error. + Change info shown at verbosity levels 2 and 3. + (main): Ignore option '-n, --threads' for compatibility with plzip. * configure: Options now accept a separate argument. - * configure: Rename 'datadir' to 'datarootdir'. + Rename 'datadir' to 'datarootdir'. * Makefile.in: New targets 'install-as-lzip' and 'install-bin'. 2012-01-03 Antonio Diaz Diaz @@ -94,7 +101,7 @@ * Version 1.3 released. * Small change in '--help' output and man page. * Change quote characters in messages as advised by GNU Standards. - * main.c: Set stdin/stdout in binary mode on OS2. + * main.c (main): Set stdin/stdout in binary mode on OS2. 2011-01-05 Antonio Diaz Diaz @@ -118,8 +125,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2023 Antonio Diaz Diaz. +Copyright (C) 2010-2025 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. diff --git a/INSTALL b/INSTALL index 594420c..e500eb9 100644 --- a/INSTALL +++ b/INSTALL @@ -3,7 +3,8 @@ 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. +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 @@ -74,7 +75,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2023 Antonio Diaz Diaz. +Copyright (C) 2010-2025 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/LzmaDec.c b/LzmaDec.c index 1236bd3..bd2a45a 100644 --- a/LzmaDec.c +++ b/LzmaDec.c @@ -716,8 +716,8 @@ static bool LzmaDec_DecodeToDic(CLzmaDec *p, uint32_t dicLimit, *status = LZMA_STATUS_NEEDS_MORE_INPUT; return true; } - if (p->tempBuf[0] != 0) - return false; + /* check first byte of the LZMA stream */ + if (p->tempBuf[0] != 0) return false; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; diff --git a/Makefile.in b/Makefile.in index 4b8c791..fc59256 100644 --- a/Makefile.in +++ b/Makefile.in @@ -2,8 +2,8 @@ DISTNAME = $(pkgname)-$(pkgversion) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -m 755 -INSTALL_DATA = $(INSTALL) -m 644 INSTALL_DIR = $(INSTALL) -d -m 755 +INSTALL_DATA = $(INSTALL) -m 644 SHELL = /bin/sh CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1 @@ -30,7 +30,8 @@ main.o : main.c # prevent 'make' from trying to remake source files $(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ; -%.h %.c : ; +MAKEFLAGS += -r +.SUFFIXES : $(objs) : Makefile carg_parser.o : carg_parser.h @@ -125,8 +126,7 @@ dist : doc $(DISTNAME)/testsuite/fox.lz \ $(DISTNAME)/testsuite/fox_*.lz \ $(DISTNAME)/testsuite/test.txt.lz \ - $(DISTNAME)/testsuite/test.txt.lzma \ - $(DISTNAME)/testsuite/test_em.txt.lz + $(DISTNAME)/testsuite/test.txt.lzma rm -f $(DISTNAME) lzip -v -9 $(DISTNAME).tar diff --git a/NEWS b/NEWS index 5415fd8..e715e5e 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,4 @@ -Changes in version 1.13: +Changes in version 1.14: -File diagnostics have been reformatted as 'PROGRAM: FILE: MESSAGE'. - -Diagnostics caused by invalid arguments to command-line options now show the -argument and the name of the option. - -The variable MAKEINFO has been added to configure and Makefile.in. - -It has been documented in INSTALL that when choosing a C standard, the POSIX -features need to be enabled explicitly: - ./configure CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500' +pdlzip now exits with error status 2 if any empty member is found in a +multimember file. diff --git a/README b/README index 14f73b7..1e4ae50 100644 --- a/README +++ b/README @@ -1,30 +1,31 @@ +See the file INSTALL for compilation and installation instructions. + Description Pdlzip is a permissively licensed implementation of the lzip data compressor, intended for those who can't distribute (or even use) GPL licensed Free Software. The name of pdlzip comes from 'public domain lzip'. -Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. +Pdlzip is written in C. Lzip is a lossless data compressor with a user interface similar to the one -of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov -chain-Algorithm' (LZMA) stream format to maximize interoperability. The -maximum dictionary size is 512 MiB so that any lzip file can be decompressed -on 32-bit machines. Lzip provides accurate and robust 3-factor integrity -checking. Lzip can compress about as fast as gzip (lzip -0) or compress most -files more than bzip2 (lzip -9). Decompression speed is intermediate between -gzip and bzip2. Lzip is better than gzip and bzip2 from a data recovery -perspective. Lzip has been designed, written, and tested with great care to -replace gzip and bzip2 as the standard general-purpose compressed format for -Unix-like systems. +of gzip or bzip2. Lzip uses a simplified form of LZMA (Lempel-Ziv-Markov +chain-Algorithm) designed to achieve complete interoperability between +implementations. The maximum dictionary size is 512 MiB so that any lzip +file can be decompressed on 32-bit machines. Lzip provides accurate and +robust 3-factor integrity checking. 'lzip -0' compresses about as fast as +gzip, while 'lzip -9' compresses most files more than bzip2. Decompression +speed is intermediate between gzip and bzip2. Lzip provides better data +recovery capabilities than gzip and bzip2. Lzip has been designed, written, +and tested with great care to replace gzip and bzip2 as general-purpose +compressed format for Unix-like systems. The lzip file format is designed for data sharing and long-term archiving, taking into account both data integrity and decoder availability: - * The lzip format provides very safe integrity checking and some data - recovery means. The program lziprecover can repair bit flip errors - (one of the most common forms of data corruption) in lzip files, and - provides data recovery capabilities, including error-checked merging - of damaged copies of a file. + * The program lziprecover can repair bit flip errors (one of the most + common forms of data corruption) in lzip files, and provides data + recovery capabilities, including error-checked merging of damaged + copies of a file. * The lzip format is as simple as possible (but not simpler). The lzip manual provides the source code of a simple decompressor along with a @@ -50,18 +51,14 @@ without recompressing. Pdlzip includes public domain compression/decompression code from the LZMA SDK (Software Development Kit) written by Igor Pavlov. -I would not write non-copylefted software unless it is too simple to be -worth copylefting it, but one of the uses of the lzip format is the -interchange of information, and it is therefore desirable that even the -users of the most non-free platforms can share lzip files with everybody -else. +Pdlzip uses Arg_parser for command-line argument parsing: +http://www.nongnu.org/arg-parser/arg_parser.html -Copyright (C) 2010-2023 Antonio Diaz Diaz. +Copyright (C) 2010-2025 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, 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. diff --git a/carg_parser.c b/carg_parser.c index 8882b97..20b8a16 100644 --- a/carg_parser.c +++ b/carg_parser.c @@ -1,5 +1,5 @@ /* Arg_parser - POSIX/GNU command-line argument parser. (C version) - Copyright (C) 2006-2023 Antonio Diaz Diaz. + Copyright (C) 2006-2025 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -32,15 +32,15 @@ static void * ap_resize_buffer( void * buf, const int min_size ) } -static char push_back_record( struct Arg_parser * const ap, const int code, +static char push_back_record( Arg_parser * const ap, const int code, const char * const long_name, const char * const argument ) { - struct ap_Record * p; + ap_Record * p; void * tmp = ap_resize_buffer( ap->data, - ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); + ( ap->data_size + 1 ) * sizeof (ap_Record) ); if( !tmp ) return 0; - ap->data = (struct ap_Record *)tmp; + ap->data = (ap_Record *)tmp; p = &(ap->data[ap->data_size]); p->code = code; if( long_name ) @@ -71,7 +71,7 @@ static char push_back_record( struct Arg_parser * const ap, const int code, } -static char add_error( struct Arg_parser * const ap, const char * const msg ) +static char add_error( Arg_parser * const ap, const char * const msg ) { const int len = strlen( msg ); void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 ); @@ -83,7 +83,7 @@ static char add_error( struct Arg_parser * const ap, const char * const msg ) } -static void free_data( struct Arg_parser * const ap ) +static void free_data( Arg_parser * const ap ) { int i; for( i = 0; i < ap->data_size; ++i ) @@ -94,10 +94,9 @@ static void free_data( struct Arg_parser * const ap ) /* Return 0 only if out of memory. */ -static char parse_long_option( struct Arg_parser * const ap, +static char parse_long_option( Arg_parser * const ap, const char * const opt, const char * const arg, - const struct ap_Option options[], - int * const argindp ) + const ap_Option options[], int * const argindp ) { unsigned len; int index = -1, i; @@ -148,21 +147,21 @@ static char parse_long_option( struct Arg_parser * const ap, add_error( ap, "' requires an argument" ); return 1; } - return push_back_record( ap, options[index].code, - options[index].long_name, &opt[len+3] ); + return push_back_record( ap, options[index].code, options[index].long_name, + &opt[len+3] ); /* argument may be empty */ } - if( options[index].has_arg == ap_yes ) + if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme ) { - if( !arg || !arg[0] ) + if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) ) { add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); add_error( ap, "' requires an argument" ); return 1; } ++*argindp; - return push_back_record( ap, options[index].code, - options[index].long_name, arg ); + return push_back_record( ap, options[index].code, options[index].long_name, + arg ); /* argument may be empty */ } return push_back_record( ap, options[index].code, @@ -171,10 +170,9 @@ static char parse_long_option( struct Arg_parser * const ap, /* Return 0 only if out of memory. */ -static char parse_short_option( struct Arg_parser * const ap, +static char parse_short_option( Arg_parser * const ap, const char * const opt, const char * const arg, - const struct ap_Option options[], - int * const argindp ) + const ap_Option options[], int * const argindp ) { int cind = 1; /* character index in opt */ @@ -204,15 +202,15 @@ static char parse_short_option( struct Arg_parser * const ap, if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0; ++*argindp; cind = 0; } - else if( options[index].has_arg == ap_yes ) + else if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme ) { - if( !arg || !arg[0] ) + if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) ) { add_error( ap, "option requires an argument -- '" ); add_error( ap, code_str ); add_error( ap, "'" ); return 1; } - ++*argindp; cind = 0; + ++*argindp; cind = 0; /* argument may be empty */ if( !push_back_record( ap, c, 0, arg ) ) return 0; } else if( !push_back_record( ap, c, 0, 0 ) ) return 0; @@ -221,9 +219,9 @@ static char parse_short_option( struct Arg_parser * const ap, } -char ap_init( struct Arg_parser * const ap, +char ap_init( Arg_parser * const ap, const int argc, const char * const argv[], - const struct ap_Option options[], const char in_order ) + const ap_Option options[], const char in_order ) { const char ** non_options = 0; /* skipped non-options */ int non_options_size = 0; /* number of skipped non-options */ @@ -282,7 +280,7 @@ out: if( non_options ) free( non_options ); } -void ap_free( struct Arg_parser * const ap ) +void ap_free( Arg_parser * const ap ) { free_data( ap ); if( ap->error ) { free( ap->error ); ap->error = 0; } @@ -290,29 +288,25 @@ void ap_free( struct Arg_parser * const ap ) } -const char * ap_error( const struct Arg_parser * const ap ) - { return ap->error; } +const char * ap_error( const Arg_parser * const ap ) { return ap->error; } +int ap_arguments( const Arg_parser * const ap ) { return ap->data_size; } -int ap_arguments( const struct Arg_parser * const ap ) - { return ap->data_size; } - - -int ap_code( const struct Arg_parser * const ap, const int i ) +int ap_code( const Arg_parser * const ap, const int i ) { if( i < 0 || i >= ap_arguments( ap ) ) return 0; return ap->data[i].code; } -const char * ap_parsed_name( const struct Arg_parser * const ap, const int i ) +const char * ap_parsed_name( const Arg_parser * const ap, const int i ) { if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].parsed_name ) return ""; return ap->data[i].parsed_name; } -const char * ap_argument( const struct Arg_parser * const ap, const int i ) +const char * ap_argument( const Arg_parser * const ap, const int i ) { if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].argument ) return ""; return ap->data[i].argument; diff --git a/carg_parser.h b/carg_parser.h index ec5d3d0..28eabee 100644 --- a/carg_parser.h +++ b/carg_parser.h @@ -1,5 +1,5 @@ /* Arg_parser - POSIX/GNU command-line argument parser. (C version) - Copyright (C) 2006-2023 Antonio Diaz Diaz. + Copyright (C) 2006-2025 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -37,60 +37,65 @@ The argument '--' terminates all options; any following arguments are treated as non-option arguments, even if they begin with a hyphen. - The syntax for optional option arguments is '-' - (without whitespace), or '--='. + The syntax of options with an optional argument is + '-' (without whitespace), or + '--='. + + The syntax of options with an empty argument is '- ""', + '-- ""', or '--=""'. */ #ifdef __cplusplus extern "C" { #endif -enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; +/* ap_yme = yes but maybe empty */ +typedef enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme } ap_Has_arg; -struct ap_Option +typedef struct ap_Option { int code; /* Short option letter or code ( code != 0 ) */ const char * long_name; /* Long option name (maybe null) */ - enum ap_Has_arg has_arg; - }; + ap_Has_arg has_arg; + } ap_Option; -struct ap_Record +typedef struct ap_Record { int code; char * parsed_name; char * argument; - }; + } ap_Record; -struct Arg_parser +typedef struct Arg_parser { - struct ap_Record * data; + ap_Record * data; char * error; int data_size; int error_size; - }; + } Arg_parser; -char ap_init( struct Arg_parser * const ap, +char ap_init( Arg_parser * const ap, const int argc, const char * const argv[], - const struct ap_Option options[], const char in_order ); + const ap_Option options[], const char in_order ); -void ap_free( struct Arg_parser * const ap ); +void ap_free( Arg_parser * const ap ); -const char * ap_error( const struct Arg_parser * const ap ); +const char * ap_error( const Arg_parser * const ap ); /* The number of arguments parsed. May be different from argc. */ -int ap_arguments( const struct Arg_parser * const ap ); +int ap_arguments( const Arg_parser * const ap ); /* If ap_code( i ) is 0, ap_argument( i ) is a non-option. Else ap_argument( i ) is the option's argument (or empty). */ -int ap_code( const struct Arg_parser * const ap, const int i ); +int ap_code( const Arg_parser * const ap, const int i ); /* Full name of the option parsed (short or long). */ -const char * ap_parsed_name( const struct Arg_parser * const ap, const int i ); +const char * ap_parsed_name( const Arg_parser * const ap, const int i ); -const char * ap_argument( const struct Arg_parser * const ap, const int i ); +const char * ap_argument( const Arg_parser * const ap, const int i ); #ifdef __cplusplus } diff --git a/configure b/configure index 1f8c60f..4f3fdd2 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2023 Antonio Diaz Diaz. +# Copyright (C) 2010-2025 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute, and modify it. pkgname=pdlzip -pkgversion=1.13-rc1 +pkgversion=1.14 progname=pdlzip srctrigger=doc/${progname}.1 @@ -109,7 +109,7 @@ while [ $# != 0 ] ; do exit 1 ;; esac - # Check if the option took a separate argument + # Check whether the option took a separate argument if [ "${arg2}" = yes ] ; then if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift else echo "configure: Missing argument to '${option}'" 1>&2 @@ -171,7 +171,7 @@ echo "MAKEINFO = ${MAKEINFO}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2023 Antonio Diaz Diaz. +# Copyright (C) 2010-2025 Antonio Diaz Diaz. # This file was generated automatically by configure. Don't edit. # # This Makefile is free software: you have unlimited permission diff --git a/debian/changelog b/debian/changelog index ea827f9..bf322b7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,33 @@ +pdlzip (1.14-1) sid; urgency=medium + + * Uploading to sid. + * Merging upstream version 1.14. + * Correcting public-domain identifier in copyright. + + -- Daniel Baumann Tue, 14 Jan 2025 11:06:12 +0100 + +pdlzip (1.14~rc1-1) sid; urgency=medium + + * Uploading to sid. + * Merging upstream version 1.14~rc1. + + -- Daniel Baumann Sun, 10 Nov 2024 09:40:36 +0100 + +pdlzip (1.13-2) sid; urgency=medium + + * Uploading to sid. + * Updating to standards-version 4.7.0. + + -- Daniel Baumann Thu, 25 Jul 2024 06:44:16 +0200 + +pdlzip (1.13-1) sid; urgency=medium + + * Uploading to sid. + * Merging upstream version 1.13. + * Updating years in copyright for 2024. + + -- Daniel Baumann Wed, 31 Jan 2024 06:33:48 +0100 + pdlzip (1.13~rc1-1) sid; urgency=medium * Uploading to sid. diff --git a/debian/control b/debian/control index 3b7beea..cb4e339 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,7 @@ Maintainer: Daniel Baumann Build-Depends: debhelper-compat (= 13), Rules-Requires-Root: no -Standards-Version: 4.6.2 +Standards-Version: 4.7.0 Homepage: http://www.nongnu.org/lzip/pdlzip.html Vcs-Browser: https://git.progress-linux.org/users/daniel.baumann/debian/packages/pdlzip Vcs-Git: https://git.progress-linux.org/users/daniel.baumann/debian/packages/pdlzip diff --git a/debian/copyright b/debian/copyright index e433c95..e3a99c2 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,12 +4,12 @@ Upstream-Contact: lzip-bug@nongnu.org Source: https://download.savannah.gnu.org/releases/lzip/ Files: * -Copyright: 2010-2022 Antonio Diaz Diaz +Copyright: 2010-2024 Antonio Diaz Diaz Igor Pavlov -License: PD +License: public-domain Files: debian/* -Copyright: 2009-2022 Daniel Baumann +Copyright: 2009-2024 Daniel Baumann License: BSD-2 License: BSD-2 diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index 0e3e384..81ab168 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. -.TH PDLZIP "1" "December 2023" "pdlzip 1.13-rc1" "User Commands" +.TH PDLZIP "1" "January 2025" "pdlzip 1.14" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -9,19 +9,19 @@ pdlzip \- reduces the size of files Pdlzip is a permissively licensed implementation of the lzip data compressor, intended for those who can't distribute (or even use) GPL licensed Free Software. The name of pdlzip comes from 'public domain lzip'. -Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. +Pdlzip is written in C. .PP Lzip is a lossless data compressor with a user interface similar to the one -of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov -chain\-Algorithm' (LZMA) stream format to maximize interoperability. The -maximum dictionary size is 512 MiB so that any lzip file can be decompressed -on 32\-bit machines. Lzip provides accurate and robust 3\-factor integrity -checking. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) or compress most -files more than bzip2 (lzip \fB\-9\fR). Decompression speed is intermediate between -gzip and bzip2. Lzip is better than gzip and bzip2 from a data recovery -perspective. Lzip has been designed, written, and tested with great care to -replace gzip and bzip2 as the standard general\-purpose compressed format for -Unix\-like systems. +of gzip or bzip2. Lzip uses a simplified form of LZMA (Lempel\-Ziv\-Markov +chain\-Algorithm) designed to achieve complete interoperability between +implementations. The maximum dictionary size is 512 MiB so that any lzip +file can be decompressed on 32\-bit machines. Lzip provides accurate and +robust 3\-factor integrity checking. 'lzip \fB\-0\fR' compresses about as fast as +gzip, while 'lzip \fB\-9\fR' compresses most files more than bzip2. Decompression +speed is intermediate between gzip and bzip2. Lzip provides better data +recovery capabilities than gzip and bzip2. Lzip has been designed, written, +and tested with great care to replace gzip and bzip2 as general\-purpose +compressed format for Unix\-like systems. .PP Pdlzip is also able to decompress legacy lzma\-alone (.lzma) files. Lzma\-alone is a very bad format; it is essentially a raw LZMA stream. @@ -112,7 +112,7 @@ Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2023 Antonio Diaz Diaz. +Copyright \(co 2025 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index 7e7805a..7dc9ee3 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2023 Antonio Diaz Diaz. + Copyright (C) 2010-2025 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -188,11 +188,22 @@ static inline void Lt_set_member_size( Lzip_trailer data, unsigned long long sz { int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } +typedef struct Cl_options /* command-line options */ + { + bool ignore_trailing; + bool loose_trailing; + } Cl_options; + +static inline void Cl_options_init( Cl_options * cl_opts ) + { cl_opts->ignore_trailing = true; cl_opts->loose_trailing = false; } + + static inline void set_retval( int * retval, const int new_val ) { if( *retval < new_val ) *retval = new_val; } -static const char * const trailing_msg = "Trailing data not allowed."; +static const char * const empty_msg = "Empty member not allowed."; static const char * const mem_msg = "Not enough memory."; +static const char * const trailing_msg = "Trailing data not allowed."; /* defined in main.c */ extern int verbosity; diff --git a/main.c b/main.c index 0d3b659..f224942 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ /* Pdlzip - LZMA lossless data compressor 2009-08-14 : Igor Pavlov : Public domain - Copyright (C) 2010-2023 Antonio Diaz Diaz. + Copyright (C) 2010-2025 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -28,7 +28,7 @@ #include #include -#include /* SSIZE_MAX */ +#include /* CHAR_BIT, SSIZE_MAX */ #include #include #include /* SIZE_MAX */ @@ -85,7 +85,7 @@ static void show_file_error( const char * const filename, static void internal_error( const char * const msg ); static const char * const program_name = "pdlzip"; -static const char * const program_year = "2023"; +static const char * const program_year = "2025"; static const char * invocation_name = "pdlzip"; /* default value */ static const struct { const char * from; const char * to; } known_extensions[] = { @@ -94,13 +94,13 @@ static const struct { const char * from; const char * to; } known_extensions[] = { ".lzma", "" }, { 0, 0 } }; -struct Lzma_options +typedef struct Lzma_options { int dictionary_size; /* 4 KiB .. 512 MiB */ int match_len_limit; /* 5 .. 273 */ - }; + } Lzma_options; -enum Mode { m_compress, m_decompress, m_test }; +typedef enum Mode { m_compress, m_decompress, m_test } Mode; /* Variables used in signal handler context. They are not declared volatile because the handler never returns. */ @@ -114,18 +114,18 @@ static void show_help( void ) printf( "Pdlzip is a permissively licensed implementation of the lzip data\n" "compressor, intended for those who can't distribute (or even use) GPL\n" "licensed Free Software. The name of pdlzip comes from 'public domain lzip'.\n" - "Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer.\n" + "Pdlzip is written in C.\n" "\nLzip is a lossless data compressor with a user interface similar to the one\n" - "of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov\n" - "chain-Algorithm' (LZMA) stream format to maximize interoperability. The\n" - "maximum dictionary size is 512 MiB so that any lzip file can be decompressed\n" - "on 32-bit machines. Lzip provides accurate and robust 3-factor integrity\n" - "checking. Lzip can compress about as fast as gzip (lzip -0) or compress most\n" - "files more than bzip2 (lzip -9). Decompression speed is intermediate between\n" - "gzip and bzip2. Lzip is better than gzip and bzip2 from a data recovery\n" - "perspective. Lzip has been designed, written, and tested with great care to\n" - "replace gzip and bzip2 as the standard general-purpose compressed format for\n" - "Unix-like systems.\n" + "of gzip or bzip2. Lzip uses a simplified form of LZMA (Lempel-Ziv-Markov\n" + "chain-Algorithm) designed to achieve complete interoperability between\n" + "implementations. The maximum dictionary size is 512 MiB so that any lzip\n" + "file can be decompressed on 32-bit machines. Lzip provides accurate and\n" + "robust 3-factor integrity checking. 'lzip -0' compresses about as fast as\n" + "gzip, while 'lzip -9' compresses most files more than bzip2. Decompression\n" + "speed is intermediate between gzip and bzip2. Lzip provides better data\n" + "recovery capabilities than gzip and bzip2. Lzip has been designed, written,\n" + "and tested with great care to replace gzip and bzip2 as general-purpose\n" + "compressed format for Unix-like systems.\n" "\nPdlzip is also able to decompress legacy lzma-alone (.lzma) files.\n" "Lzma-alone is a very bad format; it is essentially a raw LZMA stream.\n" "If you keep any lzma-alone files, it is advisable to recompress them to\n" @@ -196,16 +196,16 @@ static void * resize_buffer( void * buf, const unsigned min_size ) } -struct Pretty_print +typedef struct Pretty_print { const char * name; char * padded_name; const char * stdin_name; unsigned longest_name; bool first_post; - }; + } Pretty_print; -static void Pp_init( struct Pretty_print * const pp, +static void Pp_init( Pretty_print * const pp, const char * const filenames[], const int num_filenames ) { pp->name = 0; @@ -226,8 +226,10 @@ static void Pp_init( struct Pretty_print * const pp, if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; } -static void Pp_set_name( struct Pretty_print * const pp, - const char * const filename ) +void Pp_free( Pretty_print * const pp ) + { if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } } + +static void Pp_set_name( Pretty_print * const pp, const char * const filename ) { unsigned name_len, padded_name_len, i = 0; @@ -245,10 +247,10 @@ static void Pp_set_name( struct Pretty_print * const pp, pp->first_post = true; } -static void Pp_reset( struct Pretty_print * const pp ) +static void Pp_reset( Pretty_print * const pp ) { if( pp->name && pp->name[0] ) pp->first_post = true; } -static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) +static void Pp_show_msg( Pretty_print * const pp, const char * const msg ) { if( verbosity < 0 ) return; if( pp->first_post ) @@ -268,7 +270,7 @@ static void show_header( const unsigned dictionary_size ) const char * p = ""; const char * np = " "; unsigned num = dictionary_size; - bool exact = ( num % factor == 0 ); + bool exact = num % factor == 0; int i; for( i = 0; i < n && ( num > 9999 || ( exact && num >= factor ) ); ++i ) { num /= factor; if( num % factor != 0 ) exact = false; @@ -289,7 +291,7 @@ static const char * format_num3( unsigned long long num ) char * const buf = buffer[current++]; current %= buffers; char * p = buf + bufsize - 1; /* fill the buffer backwards */ *p = 0; /* terminator */ - if( num > 1024 ) + if( num > 9999 ) { char prefix = 0; /* try binary first, then si */ for( i = 0; i < n && num != 0 && num % 1024 == 0; ++i ) @@ -335,7 +337,7 @@ static unsigned long getnum( const char * const arg, if( !errno && tail[0] ) { - const unsigned factor = ( tail[1] == 'i' ) ? 1024 : 1000; + const unsigned factor = (tail[1] == 'i') ? 1024 : 1000; int exponent = 0; /* 0 = bad multiplier */ int i; switch( tail[0] ) @@ -385,7 +387,7 @@ static int get_dict_size( const char * const arg, const char * const option_name } -static void set_mode( enum Mode * const program_modep, const enum Mode new_mode ) +static void set_mode( Mode * const program_modep, const Mode new_mode ) { if( *program_modep != m_compress && *program_modep != new_mode ) { @@ -452,13 +454,13 @@ static void set_d_outname( const char * const name, const int eindex ) static int open_instream( const char * const name, struct stat * const in_statsp, - const enum Mode program_mode, const int eindex, + const Mode program_mode, const int eindex, const bool one_to_one, const bool recompress ) { if( program_mode == m_compress && !recompress && eindex >= 0 ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: %s: Input file already has '%s' suffix.\n", + fprintf( stderr, "%s: %s: Input file already has '%s' suffix, ignored.\n", program_name, name, known_extensions[eindex].from ); return -1; } @@ -469,9 +471,9 @@ 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 && - ( S_ISBLK( mode ) || S_ISCHR( mode ) || - S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); + 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 ) ) ) { if( verbosity >= 0 ) @@ -537,7 +539,7 @@ static void signal_handler( int sig ) static bool check_tty_in( const char * const input_filename, const int infd, - const enum Mode program_mode, int * const retval ) + const Mode program_mode, int * const retval ) { if( ( program_mode == m_decompress || program_mode == m_test ) && isatty( infd ) ) /* for example /dev/tty */ @@ -549,7 +551,7 @@ static bool check_tty_in( const char * const input_filename, const int infd, return true; } -static bool check_tty_out( const enum Mode program_mode ) +static bool check_tty_out( const Mode program_mode ) { if( program_mode == m_compress && isatty( outfd ) ) { show_file_error( output_filename[0] ? @@ -567,7 +569,7 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) if( in_statsp ) { const mode_t mode = in_statsp->st_mode; - /* fchown will in many cases return with EPERM, which can be safely ignored. */ + /* fchown in many cases returns 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 @@ -593,8 +595,9 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) } -static int compress( const int infd, const struct Lzma_options * const - encoder_options, struct Pretty_print * const pp ) +static int compress( const int infd, + const Lzma_options * const encoder_options, + Pretty_print * const pp ) { int retval = 0; CLzmaEncHandle encoder = 0; @@ -616,7 +619,7 @@ static int compress( const int infd, const struct Lzma_options * const } if( writeblock( outfd, header, Lh_size ) != Lh_size ) - { show_error( "Can't write output file", errno, false ); retval = 1; } + { show_error( "Write error", errno, false ); retval = 1; } else if( LzmaEnc_Encode( encoder ) != 0 ) { Pp_show_msg( pp, "Encoder error." ); retval = 1; } @@ -684,7 +687,7 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, unsigned long long member_size = lzma_header_size, data_size = 0; uint8_t outBuf[OUT_BUF_SIZE]; int outPos = 0; - const bool thereIsSize = (unpackSize != (uint64_t)-1); + const bool thereIsSize = unpackSize != (uint64_t)-1; for (;;) { @@ -711,7 +714,7 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, unpackSize -= outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) - { show_error( "Can't write output file", errno, false ); return 1; } + { show_error( "Write error", errno, false ); return 1; } data_size += outPos; outPos = 0; @@ -731,10 +734,10 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, } -static int lzip_decode( CLzmaDec *decoder, const int infd, - struct Pretty_print * const pp, uint8_t inBuf[], +static int lzip_decode( CLzmaDec * decoder, const int infd, + Pretty_print * const pp, uint8_t inBuf[], int * const inPos, int * const inSize, - const unsigned dictionary_size ) + const unsigned dictionary_size, bool * const data0p ) { unsigned long long member_size = Lh_size, data_size = 0; uint8_t outBuf[OUT_BUF_SIZE]; @@ -762,7 +765,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, outPos += outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) - { show_error( "Can't write output file", errno, false ); return 1; } + { show_error( "Write error", errno, false ); return 1; } CRC32_update_buf( &crc, outBuf, outPos ); data_size += outPos; @@ -830,15 +833,16 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, } if( error ) return 2; show_results( data_size, member_size, td_crc, dictionary_size, true ); + *data0p = data_size == 0; return 0; } } } -static int decompress( const int infd, struct Pretty_print * const pp, - const bool ignore_trailing, const bool loose_trailing, - const bool testing ) +static int decompress( const int infd, const Cl_options * const cl_opts, + Pretty_print * const pp, + const bool from_stdin, const bool testing ) { uint64_t unpackSize = 0; CLzmaDec decoder; @@ -848,6 +852,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, bool lzip_mode = true; bool first_member; uint8_t raw_props[lzma_header_size]; + bool empty = false, multi = false; for( first_member = true; ; first_member = false ) { @@ -867,7 +872,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, else if( Lh_check_prefix( header, size ) ) { Pp_show_msg( pp, "Truncated header in multimember file." ); retval = 2; } - else if( size > 0 && !ignore_trailing ) + else if( size > 0 && !cl_opts->ignore_trailing ) { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } @@ -875,10 +880,10 @@ static int decompress( const int infd, struct Pretty_print * const pp, { if( !first_member ) { - if( !loose_trailing && Lh_check_corrupt( header ) ) + if( !cl_opts->loose_trailing && Lh_check_corrupt( header ) ) { Pp_show_msg( pp, "Corrupt header in multimember file." ); retval = 2; } - else if( !ignore_trailing ) + else if( !cl_opts->ignore_trailing ) { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } @@ -929,19 +934,23 @@ static int decompress( const int infd, struct Pretty_print * const pp, if( !LzmaDec_Init( &decoder, raw_props ) ) { Pp_show_msg( pp, mem_msg ); return 1; } + bool data0 = false; if( lzip_mode ) retval = lzip_decode( &decoder, infd, pp, inBuf, &inPos, &inSize, - dictionary_size ); + dictionary_size, &data0 ); else retval = lzma_decode( unpackSize, &decoder, infd, inBuf, &inPos, &inSize, dictionary_size, testing ); LzmaDec_Free(&decoder); if( retval != 0 || !lzip_mode ) break; + if( !from_stdin ) { multi = !first_member; if( data0 ) empty = true; } if( verbosity >= 2 ) { fputs( testing ? "ok\n" : "done\n", stderr ); Pp_reset( pp ); } } if( lzip_mode && verbosity == 1 && retval == 0 ) fputs( testing ? "ok\n" : "done\n", stderr ); + if( empty && multi && retval == 0 ) + { show_file_error( pp->name, empty_msg, 0 ); retval = 2; } return retval; } @@ -1022,7 +1031,7 @@ int main( const int argc, const char * const argv[] ) { /* Mapping from gzip/bzip2 style 0..9 compression levels to the corresponding LZMA compression parameters. */ - const struct Lzma_options option_mapping[] = + const Lzma_options option_mapping[] = { { 1 << 16, 5 }, /* -0 */ { 1 << 20, 5 }, /* -1 */ @@ -1034,20 +1043,19 @@ int main( const int argc, const char * const argv[] ) { 1 << 24, 68 }, /* -7 */ { 3 << 23, 132 }, /* -8 */ { 1 << 25, 273 } }; /* -9 */ - struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ + Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ const char * default_output_filename = ""; - enum Mode program_mode = m_compress; - int i; + Mode program_mode = m_compress; + Cl_options cl_opts; /* command-line options */ + Cl_options_init( &cl_opts ); bool force = false; - bool ignore_trailing = true; bool keep_input_files = false; - bool loose_trailing = false; bool recompress = false; bool to_stdout = false; if( argc > 0 ) invocation_name = argv[0]; enum { opt_lt = 256 }; - const struct ap_Option options[] = + const ap_Option options[] = { { '0', "fast", ap_no }, { '1', 0, ap_no }, @@ -1077,12 +1085,12 @@ int main( const int argc, const char * const argv[] ) { 'v', "verbose", ap_no }, { 'V', "version", ap_no }, { opt_lt, "loose-trailing", ap_no }, - { 0, 0, ap_no } }; + { 0, 0, ap_no } }; CRC32_init(); /* static because valgrind complains and memory management in C sucks */ - static struct Arg_parser parser; + static Arg_parser parser; if( !ap_init( &parser, argc, argv, options, 0 ) ) { show_error( mem_msg, 0, false ); return 1; } if( ap_error( &parser ) ) /* bad option */ @@ -1097,11 +1105,11 @@ int main( const int argc, const char * const argv[] ) const char * const arg = ap_argument( &parser, argind ); switch( code ) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': encoder_options = option_mapping[code-'0']; break; - case 'a': ignore_trailing = false; break; - case 'b': break; + case 'a': cl_opts.ignore_trailing = false; break; + case 'b': break; /* ignored */ case 'c': to_stdout = true; break; case 'd': set_mode( &program_mode, m_decompress ); break; case 'f': force = true; break; @@ -1110,17 +1118,17 @@ int main( const int argc, const char * const argv[] ) case 'k': keep_input_files = true; break; case 'm': encoder_options.match_len_limit = getnum( arg, pn, min_match_len_limit, max_match_len ); break; - case 'n': break; + case 'n': break; /* ignored */ case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true; else { default_output_filename = arg; } break; case 'q': verbosity = -1; break; case 's': encoder_options.dictionary_size = get_dict_size( arg, pn ); break; - case 'S': break; + case 'S': break; /* ignored */ case 't': set_mode( &program_mode, m_test ); break; case 'v': if( verbosity < 4 ) ++verbosity; break; case 'V': show_version(); return 0; - case opt_lt: loose_trailing = true; break; + case opt_lt: cl_opts.loose_trailing = true; break; default: internal_error( "uncaught option." ); } } /* end process options */ @@ -1135,6 +1143,7 @@ int main( const int argc, const char * const argv[] ) filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); filenames[0] = "-"; + int i; bool filenames_given = false; for( i = 0; argind + i < ap_arguments( &parser ); ++i ) { @@ -1156,21 +1165,22 @@ int main( const int argc, const char * const argv[] ) if( !to_stdout && program_mode != m_test && ( filenames_given || to_file ) ) set_signals( signal_handler ); - static struct Pretty_print pp; + static Pretty_print pp; Pp_init( &pp, filenames, num_filenames ); int failed_tests = 0; int retval = 0; const bool one_to_one = !to_stdout && program_mode != m_test && !to_file; bool stdin_used = false; + struct stat in_stats; for( i = 0; i < num_filenames; ++i ) { const char * input_filename = ""; int infd; - struct stat in_stats; + const bool from_stdin = strcmp( filenames[i], "-" ) == 0; Pp_set_name( &pp, filenames[i] ); - if( strcmp( filenames[i], "-" ) == 0 ) + if( from_stdin ) { if( stdin_used ) continue; else stdin_used = true; infd = STDIN_FILENO; @@ -1215,7 +1225,7 @@ int main( const int argc, const char * const argv[] ) if( program_mode == m_compress ) tmp = compress( infd, &encoder_options, &pp ); else - tmp = decompress( infd, &pp, ignore_trailing, loose_trailing, + tmp = decompress( infd, &cl_opts, &pp, from_stdin, program_mode == m_test ); if( close( infd ) != 0 ) { show_file_error( pp.name, "Error closing input file", errno ); @@ -1230,7 +1240,9 @@ int main( const int argc, const char * const argv[] ) if( input_filename[0] && !keep_input_files && one_to_one ) remove( input_filename ); } - if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); /* -o */ + 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 */ { show_error( "Error closing stdout", errno, false ); @@ -1241,6 +1253,7 @@ int main( const int argc, const char * const argv[] ) program_name, failed_tests, ( failed_tests == 1 ) ? "file" : "files" ); free( output_filename ); + Pp_free( &pp ); free( filenames ); ap_free( &parser ); return retval; diff --git a/testsuite/check.sh b/testsuite/check.sh index 8c18a1c..1760359 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh # check script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2023 Antonio Diaz Diaz. +# Copyright (C) 2010-2025 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute, and modify it. @@ -28,10 +28,10 @@ if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp cd "${objdir}"/tmp || framework_failure -cat "${testdir}"/test.txt > in || framework_failure +cp "${testdir}"/test.txt in || framework_failure in_lz="${testdir}"/test.txt.lz -in_em="${testdir}"/test_em.txt.lz fox_lz="${testdir}"/fox.lz +fnz_lz="${testdir}"/fox_nz.lz fail=0 test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } @@ -95,7 +95,7 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null printf "\ntesting decompression..." -for i in "${in_lz}" "${in_em}" "${testdir}"/test.txt.lzma ; do +for i in "${in_lz}" "${testdir}"/test.txt.lzma ; do "${LZIP}" -t "$i" || test_failed $LINENO "$i" "${LZIP}" -d "$i" -o out || test_failed $LINENO "$i" cmp in out || test_failed $LINENO "$i" @@ -108,16 +108,13 @@ for i in "${in_lz}" "${in_em}" "${testdir}"/test.txt.lzma ; do rm -f out || framework_failure done -lines=`"${LZIP}" -tvv "${in_em}" 2>&1 | wc -l` || test_failed $LINENO -[ "${lines}" -eq 8 ] || test_failed $LINENO "${lines}" - -cat "${in_lz}" > out.lz || framework_failure +cp "${in_lz}" out.lz || framework_failure "${LZIP}" -dk out.lz || test_failed $LINENO cmp in out || test_failed $LINENO rm -f out || framework_failure "${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO -cat fox > copy || framework_failure -cat "${in_lz}" > copy.lz || framework_failure +cp fox copy || framework_failure +cp "${in_lz}" copy.lz || framework_failure "${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out [ $? = 1 ] || test_failed $LINENO [ ! -e out.lz ] || test_failed $LINENO @@ -131,7 +128,6 @@ rm -f copy out || framework_failure printf "to be overwritten" > out || framework_failure "${LZIP}" -df -o out < "${in_lz}" || test_failed $LINENO cmp in out || test_failed $LINENO -rm -f out || framework_failure "${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure @@ -139,12 +135,12 @@ rm -f ./- || framework_failure cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure -cat "${in_lz}" > anyothername || framework_failure +cp "${in_lz}" anyothername || framework_failure "${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null || test_failed $LINENO cmp in out || test_failed $LINENO cmp in anyothername.out || test_failed $LINENO -rm -f out anyothername.out || framework_failure +rm -f anyothername.out || framework_failure "${LZIP}" -tq in "${in_lz}" [ $? = 2 ] || test_failed $LINENO @@ -157,7 +153,7 @@ cat out in | cmp in - || test_failed $LINENO # out must be empty [ $? = 1 ] || test_failed $LINENO cmp in out || test_failed $LINENO rm -f out || framework_failure -cat "${in_lz}" > out.lz || framework_failure +cp "${in_lz}" out.lz || framework_failure for i in 1 2 3 4 5 6 7 ; do printf "g" >> out.lz || framework_failure "${LZIP}" -atvvvv out.lz "${in_lz}" 2> /dev/null @@ -186,6 +182,9 @@ cmp in2 out2 || test_failed $LINENO rm -f out2 || framework_failure cat "${in_lz}" "${in_lz}" > out2.lz || framework_failure +lines=`"${LZIP}" -tvv out2.lz 2>&1 | wc -l` || test_failed $LINENO +[ "${lines}" -eq 2 ] || test_failed $LINENO "${lines}" + printf "\ngarbage" >> out2.lz || framework_failure "${LZIP}" -tvvvv out2.lz 2> /dev/null || test_failed $LINENO "${LZIP}" -atq out2.lz @@ -203,6 +202,20 @@ printf "to be overwritten" > out2 || framework_failure cmp in2 out2 || test_failed $LINENO rm -f out2 || framework_failure +touch empty em || framework_failure +"${LZIP}" -0 em || test_failed $LINENO +"${LZIP}" -dk em.lz || test_failed $LINENO +cmp empty em || test_failed $LINENO +cat em.lz em.lz | "${LZIP}" -t || test_failed $LINENO +cat em.lz em.lz | "${LZIP}" -d > em || test_failed $LINENO +cmp empty em || test_failed $LINENO +cat em.lz "${in_lz}" | "${LZIP}" -t || test_failed $LINENO +cat em.lz "${in_lz}" | "${LZIP}" -d > out || test_failed $LINENO +cmp in out || test_failed $LINENO +cat "${in_lz}" em.lz | "${LZIP}" -t || test_failed $LINENO +cat "${in_lz}" em.lz | "${LZIP}" -d > out || test_failed $LINENO +cmp in out || test_failed $LINENO + printf "\ntesting compression..." "${LZIP}" -c -0 in in in -o out3.lz > copy2.lz || test_failed $LINENO @@ -211,7 +224,7 @@ printf "\ntesting compression..." "${LZIP}" -d copy2.lz -o out2 || test_failed $LINENO [ -e copy2.lz ] || test_failed $LINENO cmp in2 out2 || test_failed $LINENO -rm -f in2 out2 copy2.lz || framework_failure +rm -f copy2.lz || framework_failure "${LZIP}" -cf "${in_lz}" > lzlz 2> /dev/null # /dev/null is a tty on OS/2 [ $? = 1 ] || test_failed $LINENO @@ -259,11 +272,38 @@ rm -f copy out.lz || framework_failure printf "\ntesting bad input..." +cat em.lz em.lz > ee.lz || framework_failure +"${LZIP}" -t < ee.lz || test_failed $LINENO +"${LZIP}" -d < ee.lz > em || 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 empty em || framework_failure +cat "${in_lz}" em.lz "${in_lz}" > inein.lz || framework_failure +"${LZIP}" -t < inein.lz || test_failed $LINENO +"${LZIP}" -d < inein.lz > out2 || 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 in2 out2 inein.lz em.lz || framework_failure + headers='LZIp LZiP LZip LzIP LzIp LziP lZIP lZIp lZiP lzIP' -body='\001\014\000\203\377\373\377\377\300\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000' -cat "${in_lz}" > int.lz || framework_failure +body='\001\014\000\000\101\376\367\377\377\340\000\200\000\215\357\002\322\001\000\000\000\000\000\000\000\045\000\000\000\000\000\000\000' +cp "${in_lz}" int.lz || framework_failure printf "LZIP${body}" >> int.lz || framework_failure -if "${LZIP}" -tq int.lz ; then +if "${LZIP}" -t int.lz ; then for header in ${headers} ; do printf "${header}${body}" > int.lz || framework_failure "${LZIP}" -tq int.lz # first member @@ -278,7 +318,7 @@ if "${LZIP}" -tq int.lz ; then [ $? = 2 ] || test_failed $LINENO ${header} "${LZIP}" -cdq --loose-trailing int.lz > /dev/null [ $? = 2 ] || test_failed $LINENO ${header} - cat "${in_lz}" > int.lz || framework_failure + cp "${in_lz}" int.lz || framework_failure printf "${header}${body}" >> int.lz || framework_failure "${LZIP}" -tq int.lz # trailing data [ $? = 2 ] || test_failed $LINENO ${header} @@ -300,10 +340,13 @@ if "${LZIP}" -tq int.lz ; then [ $? = 2 ] || test_failed $LINENO ${header} done else - printf "\nwarning: skipping header test: 'printf' does not work on your system." + printf "warning: skipping header test: 'printf' does not work on your system." fi rm -f int.lz || framework_failure +"${LZIP}" -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 @@ -315,13 +358,13 @@ for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do [ $? = 2 ] || test_failed $LINENO $i cmp fox out || test_failed $LINENO $i done -rm -f fox out || framework_failure +rm -f fox || framework_failure cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure -if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && - [ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then - for i in 6 20 14734 14753 14754 14755 14756 14757 14758 ; do +if dd if=in3.lz of=trunc.lz bs=14682 count=1 2> /dev/null && + [ -e trunc.lz ] && cmp in2.lz trunc.lz ; then + for i in 6 20 14664 14683 14684 14685 14686 14687 14688 ; do dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null "${LZIP}" -tq trunc.lz [ $? = 2 ] || test_failed $LINENO $i @@ -333,28 +376,32 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && [ $? = 2 ] || test_failed $LINENO $i done else - printf "\nwarning: skipping truncation test: 'dd' does not work on your system." + printf "warning: skipping truncation test: 'dd' does not work on your system." fi rm -f in2.lz in3.lz trunc.lz || framework_failure -cat "${in_lz}" > ingin.lz || framework_failure +cp "${in_lz}" ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure cat "${in_lz}" >> ingin.lz || framework_failure "${LZIP}" -atq ingin.lz [ $? = 2 ] || test_failed $LINENO "${LZIP}" -atq < ingin.lz [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -acdq ingin.lz > /dev/null +"${LZIP}" -acdq ingin.lz > out [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -adq < ingin.lz > /dev/null +cmp in out || test_failed $LINENO +"${LZIP}" -adq < ingin.lz > out [ $? = 2 ] || test_failed $LINENO +cmp in out || test_failed $LINENO "${LZIP}" -t ingin.lz || test_failed $LINENO "${LZIP}" -t < ingin.lz || test_failed $LINENO +"${LZIP}" -dk ingin.lz || test_failed $LINENO +cmp in ingin || test_failed $LINENO "${LZIP}" -cd ingin.lz > out || test_failed $LINENO cmp in out || test_failed $LINENO "${LZIP}" -d < ingin.lz > out || test_failed $LINENO cmp in out || test_failed $LINENO -rm -f out ingin.lz || framework_failure +rm -f out ingin ingin.lz || framework_failure echo if [ ${fail} = 0 ] ; then diff --git a/testsuite/fox_nz.lz b/testsuite/fox_nz.lz new file mode 100644 index 0000000..44a4b58 Binary files /dev/null and b/testsuite/fox_nz.lz differ diff --git a/testsuite/test.txt b/testsuite/test.txt index 9196a3a..423f0c0 100644 --- a/testsuite/test.txt +++ b/testsuite/test.txt @@ -1,8 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -339,8 +338,7 @@ Public License instead of this License. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/testsuite/test.txt.lz b/testsuite/test.txt.lz index 22cea6e..5dc169f 100644 Binary files a/testsuite/test.txt.lz and b/testsuite/test.txt.lz differ diff --git a/testsuite/test.txt.lzma b/testsuite/test.txt.lzma index 53e54ea..091c023 100644 Binary files a/testsuite/test.txt.lzma and b/testsuite/test.txt.lzma differ diff --git a/testsuite/test_em.txt.lz b/testsuite/test_em.txt.lz deleted file mode 100644 index 7e96250..0000000 Binary files a/testsuite/test_em.txt.lz and /dev/null differ