From 29d0941b9831c793ef72b165109c12c676cf48c4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:21:39 +0100 Subject: [PATCH 01/10] Adding upstream version 1.7. Signed-off-by: Daniel Baumann --- ChangeLog | 14 ++- INSTALL | 4 +- LzFind.c | 1 + LzmaDec.c | 1 + LzmaEnc.c | 3 +- Makefile.in | 9 +- NEWS | 15 +-- README | 13 ++- carg_parser.c | 2 +- carg_parser.h | 2 +- configure | 14 +-- doc/pdlzip.1 | 31 ++++-- lzip.h | 50 +++++---- main.c | 225 ++++++++++++++++++++++------------------ testsuite/check.sh | 104 +++++++++++++------ testsuite/test.txt.lz | Bin 7376 -> 7376 bytes testsuite/test.txt.lzma | Bin 7399 -> 7363 bytes 17 files changed, 298 insertions(+), 190 deletions(-) diff --git a/ChangeLog b/ChangeLog index d4fcfeb..b05668d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-05-16 Antonio Diaz Diaz + + * Version 1.7 released. + * main.c: Added new option '-a, --trailing-error'. + * main.c (main): Delete '--output' file if infd is a terminal. + * main.c (main): Don't use stdin more than once. + * configure: Avoid warning on some shells when testing for gcc. + * testsuite/check.sh: A POSIX shell is required to run the tests. + * testsuite/check.sh: Don't check error messages. + 2015-05-26 Antonio Diaz Diaz * Version 1.6 released. @@ -7,7 +17,7 @@ 2013-09-14 Antonio Diaz Diaz * Version 1.5 released. - * main.c (show_header): Do not show header version in lzip mode. + * main.c (show_header): Don't show header version in lzip mode. * Minor fixes. 2013-05-27 Antonio Diaz Diaz @@ -57,7 +67,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2015 Antonio Diaz Diaz. +Copyright (C) 2010-2016 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 diff --git a/INSTALL b/INSTALL index 489393d..bfa113e 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Requirements ------------ You will need a C compiler. -I use gcc 4.9.1 and 4.1.2, but the code should compile with any +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. @@ -61,7 +61,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2015 Antonio Diaz Diaz. +Copyright (C) 2010-2016 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/LzFind.c b/LzFind.c index 8e660f3..c312927 100644 --- a/LzFind.c +++ b/LzFind.c @@ -4,6 +4,7 @@ #define _FILE_OFFSET_BITS 64 #include +#include #include #include #include diff --git a/LzmaDec.c b/LzmaDec.c index cc4279d..1236bd3 100644 --- a/LzmaDec.c +++ b/LzmaDec.c @@ -4,6 +4,7 @@ #define _FILE_OFFSET_BITS 64 #include +#include #include #include #include diff --git a/LzmaEnc.c b/LzmaEnc.c index fb5df7a..e931a3d 100644 --- a/LzmaEnc.c +++ b/LzmaEnc.c @@ -3,6 +3,7 @@ #define _FILE_OFFSET_BITS 64 +#include #include #include #include @@ -1371,7 +1372,7 @@ static void LZe_full_flush(CLzmaEnc *p, uint32_t posState) unsigned long long in_size = p->nowPos64; unsigned long long out_size = p->rc.processed + Fh_size + Ft_size; if( in_size <= 0 || out_size <= 0 ) - fprintf( stderr, " no data compressed.\n" ); + fputs( " no data compressed.\n", stderr ); else fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " "%5.2f%% saved, %llu in, %llu out.\n", diff --git a/Makefile.in b/Makefile.in index 1b4ab5b..d028174 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,6 +5,7 @@ INSTALL_PROGRAM = $(INSTALL) -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 LzFind.o LzmaEnc.o LzmaDec.o main.o @@ -68,7 +69,9 @@ install-info : if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* $(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info" - -install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" + -if $(CAN_RUN_INSTALLINFO) ; then \ + install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ + fi install-info-compress : install-info lzip -v -9 "$(DESTDIR)$(infodir)/$(pkgname).info" @@ -91,7 +94,9 @@ uninstall-bin : -rm -f "$(DESTDIR)$(bindir)/$(progname)" uninstall-info : - -install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" + -if $(CAN_RUN_INSTALLINFO) ; then \ + install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ + fi -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* uninstall-man : diff --git a/NEWS b/NEWS index 12715c0..5ffa79b 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,11 @@ -Changes in version 1.6: +Changes in version 1.7: -Copying of file dates, permissions, and ownership now behaves like "cp -p". -(If the user ID or the group ID can't be duplicated, the file permission -bits S_ISUID and S_ISGID are cleared). +The option "-a, --trailing-error", which makes pdlzip exit with error +status 2 if any remaining input is detected after decompressing the last +member, has been added. -The targets "install-compress", "install-strip-compress" and -"install-man-compress" have been added to the Makefile. +When decompressing, the file specified with the '--output' option is now +deleted if the input is a terminal. + +A harmless check failure on Windows, caused by the failed comparison of +a message in text mode, has been fixed. diff --git a/README b/README index a7cbbd2..ab5e4b1 100644 --- a/README +++ b/README @@ -5,8 +5,9 @@ the one of lzip, bzip2 or gzip. Pdlzip uses the lzip file format; the files produced by pdlzip are (hope)fully compatible with lzip-1.4 or newer. Pdlzip is in fact a -"public domain" version of the lzip data compressor, intended for those -who can't distribute (or even use) GPL licensed Free Software. +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"). The lzip file format is designed for data sharing and long-term archiving, taking into account both data integrity and decoder @@ -34,8 +35,10 @@ the help of lziprecover, losing an entire archive just because of a corrupt byte near the beginning is a thing of the past. Pdlzip is also able to decompress legacy lzma-alone (.lzma) files. -Lzma-alone is a very bad format. If you keep any lzma-alone files, it is -advisable to recompress them to lzip format. +Lzma-alone is a very bad format; it is essentially a raw LZMA stream. +If you keep any lzma-alone files, it is advisable to recompress them to +lzip format. Lziprecover can convert lzma-alone files to lzip format +without recompressing. Pdlzip is written in C. @@ -49,7 +52,7 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2015 Antonio Diaz Diaz. +Copyright (C) 2010-2016 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/carg_parser.c b/carg_parser.c index 8d74ea6..3d4e89f 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-2015 Antonio Diaz Diaz. + Copyright (C) 2006-2016 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/carg_parser.h b/carg_parser.h index ed4d9c5..e918942 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-2015 Antonio Diaz Diaz. + Copyright (C) 2006-2016 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/configure b/configure index 40db552..cab895f 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2015 Antonio Diaz Diaz. +# Copyright (C) 2010-2016 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. pkgname=pdlzip -pkgversion=1.6 +pkgversion=1.7 progname=pdlzip srctrigger=doc/${progname}.1 @@ -26,8 +26,8 @@ CFLAGS='-Wall -W -O2' LDFLAGS= # checking whether we are using GNU C. -${CC} --version > /dev/null 2>&1 -if [ $? != 0 ] ; then +if /bin/sh -c "${CC} --version" > /dev/null 2>&1 ; then true +else CC=cc CFLAGS='-W -O2' fi @@ -139,7 +139,7 @@ if [ -z "${no_create}" ] ; then rm -f config.status cat > config.status << EOF #! /bin/sh -# This file was generated automatically by configure. Do not edit. +# This file was generated automatically by configure. Don't edit. # Run this file to recreate the current configuration. # # This script is free software: you have unlimited permission @@ -165,8 +165,8 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2015 Antonio Diaz Diaz. -# This file was generated automatically by configure. Do not edit. +# Copyright (C) 2010-2016 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. diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index 0c97f2c..8e76b32 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,15 +1,18 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH PDLZIP "1" "May 2015" "pdlzip 1.6" "User Commands" +.TH PDLZIP "1" "May 2016" "pdlzip 1.7" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS .B pdlzip [\fI\,options\/\fR] [\fI\,files\/\fR] .SH DESCRIPTION -Pdlzip \- A "public domain" version of the lzip data compressor -also able to decompress legacy lzma\-alone (.lzma) files. -Lzma\-alone is a very bad format. If you keep any lzma\-alone files, it is -advisable to recompress them to lzip format. +Pdlzip \- A permissively licensed implementation of the lzip data +compressor also able to decompress legacy lzma\-alone (.lzma) files. +.PP +Lzma\-alone is a very bad format; it is essentially a raw LZMA stream. +If you keep any lzma\-alone files, it is advisable to recompress them to +lzip format. Lziprecover can convert lzma\-alone files to lzip format +without recompressing. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR @@ -18,8 +21,11 @@ display this help and exit \fB\-V\fR, \fB\-\-version\fR output version information and exit .TP +\fB\-a\fR, \fB\-\-trailing\-error\fR +exit with error status if trailing data +.TP \fB\-c\fR, \fB\-\-stdout\fR -send output to standard output +write to standard output, keep input files .TP \fB\-d\fR, \fB\-\-decompress\fR decompress @@ -37,7 +43,7 @@ keep (don't delete) input files set match length limit in bytes [36] .TP \fB\-o\fR, \fB\-\-output=\fR -if reading stdin, place the output into +if reading standard input, write to .TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages @@ -60,13 +66,16 @@ alias for \fB\-1\fR \fB\-\-best\fR alias for \fB\-9\fR .PP -If no file names are given, pdlzip compresses or decompresses -from standard input to standard output. +If no file names are given, or if a file is '\-', pdlzip compresses or +decompresses 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... +Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12 +to 2^27 bytes. +.PP The bidimensional parameter space of LZMA can't be mapped to a linear scale optimal for all files. If your files are large, very repetitive, -etc, you may need to use the \fB\-\-match\-length\fR and \fB\-\-dictionary\-size\fR +etc, you may need to use the \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR options directly to achieve optimal performance. For example, \fB\-9m64\fR usually compresses executables more (and faster) than \fB\-9\fR. .PP @@ -79,7 +88,7 @@ Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2015 Antonio Diaz Diaz. +Copyright \(co 2016 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index 3b8d172..f84c53c 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2015 Antonio Diaz Diaz. + Copyright (C) 2010-2016 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -17,11 +17,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef __cplusplus -enum Bool { false = 0, true = 1 }; -typedef enum Bool bool; -#endif - #ifndef max #define max(x,y) ((x) >= (y) ? (x) : (y)) #endif @@ -34,9 +29,10 @@ typedef int State; enum { min_dictionary_bits = 12, min_dictionary_size = 1 << min_dictionary_bits, - max_dictionary_bits = 29, + max_dictionary_bits = 27, /* kDicLogSizeMaxCompress */ max_dictionary_size = 1 << max_dictionary_bits, literal_context_bits = 3, + literal_pos_state_bits = 0, /* not used */ pos_state_bits = 2, len_low_bits = 3, @@ -61,7 +57,8 @@ struct Pretty_print }; static inline void Pp_init( struct Pretty_print * const pp, - const char * const filenames[], const int num_filenames ) + const char * const filenames[], + const int num_filenames, const int verbosity ) { unsigned stdin_name_len; int i; @@ -71,6 +68,7 @@ static inline void Pp_init( struct Pretty_print * const pp, pp->first_post = false; stdin_name_len = strlen( pp->stdin_name ); + if( verbosity <= 0 ) return; for( i = 0; i < num_filenames; ++i ) { const char * const s = filenames[i]; @@ -121,6 +119,11 @@ static inline void CRC32_update_buf( uint32_t * const crc, } +static inline bool isvalid_ds( const unsigned dictionary_size ) + { return ( dictionary_size >= min_dictionary_size && + dictionary_size <= max_dictionary_size ); } + + static inline int real_bits( unsigned value ) { int bits = 0; @@ -142,6 +145,14 @@ static inline void Fh_set_magic( File_header data ) static inline bool Fh_verify_magic( const File_header data ) { return ( memcmp( data, magic_string, 4 ) == 0 ); } +/* detect truncated header */ +static inline bool Fh_verify_prefix( const File_header data, const int size ) + { + int i; for( i = 0; i < size && i < 4; ++i ) + if( data[i] != magic_string[i] ) return false; + return ( size > 0 ); + } + static inline uint8_t Fh_version( const File_header data ) { return data[4]; } @@ -158,21 +169,18 @@ static inline unsigned Fh_get_dictionary_size( const File_header data ) static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) { - if( sz >= min_dictionary_size && sz <= max_dictionary_size ) + if( !isvalid_ds( sz ) ) return false; + data[5] = real_bits( sz - 1 ); + if( sz > min_dictionary_size ) { - data[5] = real_bits( sz - 1 ); - if( sz > min_dictionary_size ) - { - const unsigned base_size = 1 << data[5]; - const unsigned fraction = base_size / 16; - int i; - for( i = 7; i >= 1; --i ) - if( base_size - ( i * fraction ) >= sz ) - { data[5] |= ( i << 5 ); break; } - } - return true; + const unsigned base_size = 1 << data[5]; + const unsigned fraction = base_size / 16; + int i; + for( i = 7; i >= 1; --i ) + if( base_size - ( i * fraction ) >= sz ) + { data[5] |= ( i << 5 ); break; } } - return false; + return true; } diff --git a/main.c b/main.c index 7972e7d..5e09fe0 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-2015 Antonio Diaz Diaz. + Copyright (C) 2010-2016 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -65,10 +66,11 @@ #error "Environments where CHAR_BIT != 8 are not supported." #endif +int verbosity = 0; const char * const Program_name = "Pdlzip"; const char * const program_name = "pdlzip"; -const char * const program_year = "2015"; +const char * const program_year = "2016"; const char * invocation_name = 0; struct { const char * from; const char * to; } const known_extensions[] = { @@ -87,30 +89,29 @@ enum Mode { m_compress, m_decompress, m_test }; char * output_filename = 0; int outfd = -1; -int verbosity = 0; -const mode_t usr_rw = S_IRUSR | S_IWUSR; -const mode_t all_rw = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; -mode_t outfd_mode = S_IRUSR | S_IWUSR; bool delete_output_on_interrupt = false; static void show_help( void ) { - printf( "%s - A \"public domain\" version of the lzip data compressor\n", Program_name ); - printf( "also able to decompress legacy lzma-alone (.lzma) files.\n" - "Lzma-alone is a very bad format. If you keep any lzma-alone files, it is\n" - "advisable to recompress them to lzip format.\n" + printf( "%s - A permissively licensed implementation of the lzip data\n", Program_name ); + printf( "compressor also able to decompress legacy lzma-alone (.lzma) files.\n" + "\nLzma-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" + "lzip format. Lziprecover can convert lzma-alone files to lzip format\n" + "without recompressing.\n" "\nUsage: %s [options] [files]\n", invocation_name ); printf( "\nOptions:\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" - " -c, --stdout send output to standard output\n" + " -a, --trailing-error exit with error status if trailing data\n" + " -c, --stdout write to standard output, keep input files\n" " -d, --decompress decompress\n" " -f, --force overwrite existing output files\n" " -F, --recompress force re-compression of compressed files\n" " -k, --keep keep (don't delete) input files\n" " -m, --match-length= set match length limit in bytes [36]\n" - " -o, --output= if reading stdin, place the output into \n" + " -o, --output= if reading standard input, write to \n" " -q, --quiet suppress all messages\n" " -s, --dictionary-size= set dictionary size limit in bytes [8 MiB]\n" " -t, --test test compressed file integrity\n" @@ -118,13 +119,15 @@ static void show_help( void ) " -1 .. -9 set compression level [default 6]\n" " --fast alias for -1\n" " --best alias for -9\n" - "If no file names are given, pdlzip compresses or decompresses\n" - "from standard input to standard output.\n" + "If no file names are given, or if a file is '-', pdlzip compresses or\n" + "decompresses from standard input to standard output.\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" - "The bidimensional parameter space of LZMA can't be mapped to a linear\n" + "Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12\n" + "to 2^27 bytes.\n" + "\nThe bidimensional parameter space of LZMA can't be mapped to a linear\n" "scale optimal for all files. If your files are large, very repetitive,\n" - "etc, you may need to use the --match-length and --dictionary-size\n" + "etc, you may need to use the --dictionary-size and --match-length\n" "options directly to achieve optimal performance. For example, -9m64\n" "usually compresses executables more (and faster) than -9.\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" @@ -149,18 +152,21 @@ static void show_version( void ) static void show_header( const unsigned dictionary_size ) { - const char * const prefix[8] = - { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; - enum { factor = 1024 }; - const char * p = ""; - const char * np = " "; - unsigned num = dictionary_size, i; - bool exact = ( num % factor == 0 ); + if( verbosity >= 3 ) + { + const char * const prefix[8] = + { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; + enum { factor = 1024 }; + const char * p = ""; + const char * np = " "; + unsigned num = dictionary_size, i; + bool exact = ( num % factor == 0 ); - for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) - { num /= factor; if( num % factor != 0 ) exact = false; - p = prefix[i]; np = ""; } - fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); + for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) + { num /= factor; if( num % factor != 0 ) exact = false; + p = prefix[i]; np = ""; } + fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); + } } @@ -180,12 +186,11 @@ static unsigned long getnum( const char * const ptr, if( !errno && tail[0] ) { - int factor = ( tail[1] == 'i' ) ? 1024 : 1000; - int exponent = 0, i; - bool bad_multiplier = false; + const int factor = ( tail[1] == 'i' ) ? 1024 : 1000; + int exponent = 0; /* 0 = bad multiplier */ + int i; switch( tail[0] ) { - case ' ': break; case 'Y': exponent = 8; break; case 'Z': exponent = 7; break; case 'E': exponent = 6; break; @@ -193,13 +198,10 @@ static unsigned long getnum( const char * const ptr, case 'T': exponent = 4; break; case 'G': exponent = 3; break; case 'M': exponent = 2; break; - case 'K': if( factor == 1024 ) exponent = 1; else bad_multiplier = true; - break; - case 'k': if( factor == 1000 ) exponent = 1; else bad_multiplier = true; - break; - default : bad_multiplier = true; + case 'K': if( factor == 1024 ) exponent = 1; break; + case 'k': if( factor == 1000 ) exponent = 1; break; } - if( bad_multiplier ) + if( exponent <= 0 ) { show_error( "Bad multiplier in numerical argument.", 0, true ); exit( 1 ); @@ -264,7 +266,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp if( infd < 0 ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: Can't open input file '%s': %s.\n", + fprintf( stderr, "%s: Can't open input file '%s': %s\n", program_name, name, strerror( errno ) ); } else @@ -274,14 +276,14 @@ static int open_instream( const char * const name, struct stat * const in_statsp const bool can_read = ( i == 0 && ( S_ISBLK( mode ) || S_ISCHR( mode ) || S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); - const bool no_ofile = to_stdout || program_mode == m_test; + const bool no_ofile = ( to_stdout || program_mode == m_test ); if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) ) { if( verbosity >= 0 ) fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", program_name, name, ( can_read && !no_ofile ) ? - " and '--stdout' was not specified" : "" ); + ",\n and '--stdout' was not specified" : "" ); close( infd ); infd = -1; } @@ -334,24 +336,28 @@ static void set_d_outname( const char * const name, const int i ) strcpy( output_filename, name ); strcat( output_filename, ".out" ); if( verbosity >= 1 ) - fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n", + fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n", program_name, name, output_filename ); } -static bool open_outstream( const bool force ) +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 = from_stdin ? all_rw : usr_rw; int flags = O_CREAT | O_WRONLY | O_BINARY; if( force ) flags |= O_TRUNC; else flags |= O_EXCL; outfd = open( output_filename, flags, outfd_mode ); - if( outfd < 0 && verbosity >= 0 ) + if( outfd >= 0 ) delete_output_on_interrupt = true; + else if( verbosity >= 0 ) { if( errno == EEXIST ) fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n", program_name, output_filename ); else - fprintf( stderr, "%s: Can't create output file '%s': %s.\n", + fprintf( stderr, "%s: Can't create output file '%s': %s\n", program_name, output_filename, strerror( errno ) ); } return ( outfd >= 0 ); @@ -406,7 +412,11 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) fchmod( outfd, mode & ~( S_ISUID | S_ISGID | S_ISVTX ) ) != 0 ) warning = true; } - if( close( outfd ) != 0 ) cleanup_and_fail( 1 ); + if( close( outfd ) != 0 ) + { + show_error( "Error closing output file", errno, false ); + cleanup_and_fail( 1 ); + } outfd = -1; delete_output_on_interrupt = false; if( in_statsp ) @@ -444,7 +454,7 @@ static int compress( const struct Lzma_options * const encoder_options, } if( writeblock( outfd, header, Fh_size ) != Fh_size ) - { show_error( "Can not write output file", errno, false ); retval = 1; } + { show_error( "Can't write output file", errno, false ); retval = 1; } else if( LzmaEnc_Encode( encoder ) != 0 ) { Pp_show_msg( pp, "Encoder error." ); retval = 1; } @@ -516,7 +526,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 not write output file", errno, false ); return 1; } + { show_error( "Can't write output file", errno, false ); return 1; } total_out += outPos; outPos = 0; @@ -527,13 +537,18 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, if( ( thereIsSize && unpackSize != 0 ) || ( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) ) { show_error( "Data error.", 0, false ); return 2; } - if( verbosity >= 2 ) - { fprintf( stderr, "lzma-alone, " ); show_header( decoder->dicBufSize ); } - if( verbosity >= 3 ) + if( verbosity >= 2 && total_out > 0 && total_in > 0 ) + fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ", + (double)total_out / total_in, + ( 8.0 * total_in ) / total_out, + 100.0 * ( 1.0 - ( (double)total_in / total_out ) ) ); + if( verbosity >= 4 ) fprintf( stderr, "uncompressed size %9llu, compressed size %8llu. ", total_out, total_in ); + if( verbosity >= 2 ) + fputs( "lzma-alone, ", stderr ); if( verbosity >= 1 ) - fprintf( stderr, testing ? "(apparently) ok\n" : "(apparently) done\n" ); + fputs( testing ? "(apparently) ok\n" : "(apparently) done\n", stderr ); return 0; } } @@ -569,7 +584,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], outPos += outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) - { show_error( "Can not write output file", errno, false ); return 1; } + { show_error( "Can't write output file", errno, false ); return 1; } CRC32_update_buf( &crc, outBuf, outPos ); total_out += outPos; @@ -598,25 +613,26 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], for( i = 0; i < Ft_size; ++i ) trailer[i] = inBuf[(*inPos)++]; total_in += Ft_size; - if( Ft_get_data_crc( trailer ) != ( crc ^ 0xFFFFFFFFU ) ) + crc ^= 0xFFFFFFFFU; + if( Ft_get_data_crc( trailer ) != crc ) { error = true; if( verbosity >= 0 ) - fprintf( stderr, "CRC mismatch; trailer says %08X, data crc is %08X.\n", - Ft_get_data_crc( trailer ), crc ^ 0xFFFFFFFFU ); + fprintf( stderr, "CRC mismatch; trailer says %08X, data crc is %08X\n", + Ft_get_data_crc( trailer ), crc ); } if( Ft_get_data_size( trailer ) != total_out ) { error = true; if( verbosity >= 0 ) - fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX).\n", + fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX)\n", Ft_get_data_size( trailer ), total_out, total_out ); } if( Ft_get_member_size( trailer ) != total_in ) { error = true; if( verbosity >= 0 ) - fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX).\n", + fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX)\n", Ft_get_member_size( trailer ), total_in, total_in ); } if( !error && verbosity >= 2 && total_out > 0 && total_in > 0 ) @@ -626,8 +642,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], 100.0 * ( 1.0 - ( (double)total_in / total_out ) ) ); if( !error && verbosity >= 4 ) fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ", - Ft_get_data_crc( trailer ), - Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) ); + crc, total_out, total_in ); if( error ) return 2; return 0; } @@ -636,7 +651,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], static int decompress( const int infd, struct Pretty_print * const pp, - const bool testing ) + const bool ignore_trailing, const bool testing ) { uint64_t unpackSize = 0; CLzmaDec decoder; @@ -649,31 +664,43 @@ static int decompress( const int infd, struct Pretty_print * const pp, for( first_member = true; ; first_member = false ) { - int i; - unsigned dictionary_size = 0; + int i, size; + unsigned dictionary_size; File_header header; if( inSize - inPos < lzma_header_size && !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; - if( inSize - inPos <= Fh_size ) /* End Of File */ + size = inSize - inPos; + for( i = 0; i < size && i < Fh_size; ++i ) + raw_props[i] = header[i] = inBuf[inPos++]; + if( size <= Fh_size ) /* End Of File */ { - if( first_member ) + if( first_member || Fh_verify_prefix( header, size ) ) { Pp_show_msg( pp, "File ends unexpectedly at member header." ); retval = 2; } break; } - for( i = 0; i < Fh_size; ++i ) raw_props[i] = header[i] = inBuf[inPos++]; if( !Fh_verify_magic( header ) ) { - if( !first_member ) break; /* trailing garbage */ + if( !first_member ) + { + if( !ignore_trailing ) + { Pp_show_msg( pp, "Trailing data not allowed." ); retval = 2; } + break; + } if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */ { for( i = Fh_size; i < lzma_header_size; ++i ) raw_props[i] = inBuf[inPos++]; - for( i = 0; i < 8; ++i ) - unpackSize += (uint64_t)raw_props[LZMA_PROPS_SIZE+i] << (i * 8); if( ( raw_props[12] == 0 || raw_props[12] == 0xFF ) && raw_props[12] == raw_props[11] && raw_props[0] < (9 * 5 * 5) ) + { lzip_mode = false; + dictionary_size = 0; + for( i = 4; i >= 1; --i ) + { dictionary_size <<= 8; dictionary_size += raw_props[i]; } + for( i = 7; i >= 0; --i ) + { unpackSize <<= 8; unpackSize += raw_props[LZMA_PROPS_SIZE+i]; } + } } if( lzip_mode ) { @@ -693,8 +720,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, retval = 2; break; } dictionary_size = Fh_get_dictionary_size( header ); - if( dictionary_size < min_dictionary_size || - dictionary_size > max_dictionary_size ) + if( !isvalid_ds( dictionary_size ) ) { Pp_show_msg( pp, "Invalid dictionary size in member header." ); retval = 2; break; } @@ -704,14 +730,10 @@ static int decompress( const int infd, struct Pretty_print * const pp, } if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) - { Pp_show_msg( pp, 0 ); - if( lzip_mode && verbosity >= 3 ) show_header( dictionary_size ); } + { Pp_show_msg( pp, 0 ); show_header( dictionary_size ); } if( !LzmaDec_Init( &decoder, raw_props ) ) - { - show_error( "Not enough memory.", 0, false ); - cleanup_and_fail( 1 ); - } + { Pp_show_msg( pp, "Not enough memory." ); return 1; } if( lzip_mode ) retval = lzip_decode( &decoder, infd, inBuf, &inPos, &inSize ); else @@ -720,10 +742,10 @@ static int decompress( const int infd, struct Pretty_print * const pp, LzmaDec_Free(&decoder); if( retval != 0 || !lzip_mode ) break; if( verbosity >= 2 ) - { fprintf( stderr, testing ? "ok\n" : "done\n" ); Pp_reset( pp ); } + { fputs( testing ? "ok\n" : "done\n", stderr ); Pp_reset( pp ); } } if( lzip_mode && verbosity == 1 && retval == 0 ) - fprintf( stderr, testing ? "ok\n" : "done\n" ); + fputs( testing ? "ok\n" : "done\n", stderr ); return retval; } @@ -753,11 +775,11 @@ void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) { if( pp->first_post ) { - int i, len; + unsigned i; pp->first_post = false; fprintf( stderr, " %s: ", pp->name ); - len = pp->longest_name - strlen( pp->name ); - for( i = 0; i < len; ++i ) fprintf( stderr, " " ); + for( i = strlen( pp->name ); i < pp->longest_name; ++i ) + fputc( ' ', stderr ); if( !msg ) fflush( stderr ); } if( msg ) fprintf( stderr, "%s\n", msg ); @@ -804,18 +826,16 @@ int writeblock( const int fd, const uint8_t * const buf, const int size ) void show_error( const char * const msg, const int errcode, const bool help ) { - if( verbosity >= 0 ) + if( verbosity < 0 ) return; + if( msg && msg[0] ) { - if( msg && msg[0] ) - { - fprintf( stderr, "%s: %s", program_name, msg ); - if( errcode > 0 ) fprintf( stderr, ": %s.", strerror( errcode ) ); - fprintf( stderr, "\n" ); - } - if( help ) - fprintf( stderr, "Try '%s --help' for more information.\n", - invocation_name ); + fprintf( stderr, "%s: %s", program_name, msg ); + if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); + fputc( '\n', stderr ); } + if( help ) + fprintf( stderr, "Try '%s --help' for more information.\n", + invocation_name ); } @@ -855,7 +875,9 @@ int main( const int argc, const char * const argv[] ) int i; bool filenames_given = false; bool force = false; + bool ignore_trailing = true; bool keep_input_files = false; + bool stdin_used = false; bool recompress = false; bool to_stdout = false; struct Pretty_print pp; @@ -872,6 +894,7 @@ int main( const int argc, const char * const argv[] ) { '7', 0, ap_no }, { '8', 0, ap_no }, { '9', "best", ap_no }, + { 'a', "trailing-error", ap_no }, { 'b', "member-size", ap_yes }, { 'c', "stdout", ap_no }, { 'd', "decompress", ap_no }, @@ -910,6 +933,7 @@ int main( const int argc, const char * const argv[] ) 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 'c': to_stdout = true; break; case 'd': program_mode = m_decompress; break; @@ -954,7 +978,7 @@ int main( const int argc, const char * const argv[] ) ( filenames_given || default_output_filename[0] ) ) set_signals(); - Pp_init( &pp, filenames, num_filenames ); + Pp_init( &pp, filenames, num_filenames, verbosity ); output_filename = resize_buffer( output_filename, 1 ); for( i = 0; i < num_filenames; ++i ) @@ -966,6 +990,7 @@ int main( const int argc, const char * const argv[] ) if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) { + if( stdin_used ) continue; else stdin_used = true; input_filename = ""; infd = STDIN_FILENO; if( program_mode != m_test ) @@ -982,8 +1007,7 @@ int main( const int argc, const char * const argv[] ) strlen( default_output_filename ) + 1 ); strcpy( output_filename, default_output_filename ); } - outfd_mode = all_rw; - if( !open_outstream( force ) ) + if( !open_outstream( force, true ) ) { if( retval < 1 ) retval = 1; close( infd ); infd = -1; @@ -1007,8 +1031,7 @@ int main( const int argc, const char * const argv[] ) if( program_mode == m_compress ) set_c_outname( input_filename ); else set_d_outname( input_filename, eindex ); - outfd_mode = usr_rw; - if( !open_outstream( force ) ) + if( !open_outstream( force, false ) ) { if( retval < 1 ) retval = 1; close( infd ); infd = -1; @@ -1018,16 +1041,18 @@ int main( const int argc, const char * const argv[] ) } } - if( !check_tty( infd, program_mode ) ) return 1; + if( !check_tty( infd, program_mode ) ) + { + if( retval < 1 ) retval = 1; + cleanup_and_fail( retval ); + } - if( output_filename[0] && !to_stdout && program_mode != m_test ) - delete_output_on_interrupt = true; in_statsp = input_filename[0] ? &in_stats : 0; Pp_set_name( &pp, input_filename ); if( program_mode == m_compress ) tmp = compress( &encoder_options, infd, &pp ); else - tmp = decompress( infd, &pp, program_mode == m_test ); + tmp = decompress( infd, &pp, ignore_trailing, program_mode == m_test ); if( tmp > retval ) retval = tmp; if( tmp && program_mode != m_test ) cleanup_and_fail( retval ); diff --git a/testsuite/check.sh b/testsuite/check.sh index 3fab78e..1147256 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-2015 Antonio Diaz Diaz. +# Copyright (C) 2010-2016 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -17,9 +17,16 @@ if [ ! -f "${LZIP}" ] || [ ! -x "${LZIP}" ] ; then exit 1 fi +if [ -e "${LZIP}" ] 2> /dev/null ; then true +else + echo "$0: a POSIX shell is required to run the tests" + echo "Try bash -c \"$0 $1 $2\"" + exit 1 +fi + if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp -cd "${objdir}"/tmp +cd "${objdir}"/tmp || framework_failure cat "${testdir}"/test.txt > in || framework_failure in_lz="${testdir}"/test.txt.lz @@ -27,25 +34,22 @@ fail=0 printf "testing pdlzip-%s..." "$2" -"${LZIP}" -cqm4 in > /dev/null -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cqm274 in > /dev/null -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cqs-1 in > /dev/null -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cqs0 in > /dev/null -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cqs4095 in > /dev/null -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cqs513MiB in > /dev/null -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -printf " in: Bad magic number (file not in lzip format).\n" > msg -"${LZIP}" -t in 2> out -if [ $? = 2 ] && cmp out msg ; then printf . ; else printf - ; fail=1 ; fi -printf " (stdin): Bad magic number (file not in lzip format).\n" > msg -"${LZIP}" -t < in 2> out -if [ $? = 2 ] && cmp out msg ; then printf . ; else printf - ; fail=1 ; fi -rm -f out msg +"${LZIP}" -fkqm4 in +if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -fkqm274 in +if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -fkqs-1 in +if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -fkqs0 in +if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -fkqs4095 in +if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -fkqs513MiB in +if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -tq in +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -tq < in +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -cdq in if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -cdq < in @@ -55,47 +59,85 @@ if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi dd if="${in_lz}" bs=1 count=20 2> /dev/null | "${LZIP}" -tq if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -t "${in_lz}" || fail=1 +printf "\ntesting decompression..." + +"${LZIP}" -t "${in_lz}" +if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -cd "${in_lz}" > copy || fail=1 cmp in copy || fail=1 printf . -"${LZIP}" -t "${testdir}"/test.txt.lzma || fail=1 +"${LZIP}" -t "${testdir}"/test.txt.lzma +if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || fail=1 cmp in copy || fail=1 printf . +rm -f copy cat "${in_lz}" > copy.lz || framework_failure -printf "to be overwritten" > copy || framework_failure -"${LZIP}" -df copy.lz || fail=1 +"${LZIP}" -dk copy.lz || fail=1 cmp in copy || fail=1 -printf . +printf "to be overwritten" > copy || framework_failure +"${LZIP}" -dq copy.lz +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -df copy.lz +if [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; then + printf . ; else printf - ; fail=1 ; fi printf "to be overwritten" > copy || framework_failure "${LZIP}" -df -o copy < "${in_lz}" || fail=1 cmp in copy || fail=1 printf . +rm -f copy "${LZIP}" -s16 < in > anyothername || fail=1 -"${LZIP}" -d anyothername || fail=1 -cmp in anyothername.out || fail=1 -printf . +"${LZIP}" -d -o copy - anyothername - < "${in_lz}" +if [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; then + printf . ; else printf - ; fail=1 ; fi +rm -f copy anyothername.out + +"${LZIP}" -tq in "${in_lz}" +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -tq foo.lz "${in_lz}" +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -cdq in "${in_lz}" > copy +if [ $? = 2 ] && cat copy in | cmp in - ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -cdq foo.lz "${in_lz}" > copy +if [ $? = 1 ] && cmp in copy ; then printf . ; else printf - ; fail=1 ; fi +rm -f copy +cat "${in_lz}" > copy.lz || framework_failure +"${LZIP}" -dq in copy.lz +if [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; then + printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -dq foo.lz copy.lz +if [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e foo ] && cmp in copy ; then + printf . ; else printf - ; fail=1 ; fi cat in in > in2 || framework_failure "${LZIP}" -s16 -o copy2 < in2 || fail=1 "${LZIP}" -t copy2.lz || fail=1 -printf . "${LZIP}" -cd copy2.lz > copy2 || fail=1 cmp in2 copy2 || fail=1 printf . printf "garbage" >> copy2.lz || framework_failure +rm -f copy2 +"${LZIP}" -atq copy2.lz +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -atq < copy2.lz +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -adkq copy2.lz +if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -adkq -o copy2 < copy2.lz +if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi printf "to be overwritten" > copy2 || framework_failure "${LZIP}" -df copy2.lz || fail=1 cmp in2 copy2 || fail=1 printf . -"${LZIP}" -cfq "${in_lz}" > out +printf "\ntesting compression..." + +"${LZIP}" -cfq "${in_lz}" > out # /dev/null is a tty on OS/2 if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -cF -s16 "${in_lz}" > out || fail=1 "${LZIP}" -cd out | "${LZIP}" -d > copy || fail=1 diff --git a/testsuite/test.txt.lz b/testsuite/test.txt.lz index 41d2e39999a92cd871d646a4ae00ba25ef067cc4..22cea6e4d2a58b4dcb006541dcdb8defabba0cbb 100644 GIT binary patch delta 15 Wcmca$dBKv+C(1K`@%=`&Q!)TBtOex& delta 15 Wcmca$dBKv+C(1K`@xw;8Q!)TBu?6M; diff --git a/testsuite/test.txt.lzma b/testsuite/test.txt.lzma index 77f2b871d1bd984f46cf5dfa0210f92c19d18cd3..53e54ea1bb33582950062681b4e5590065948a28 100644 GIT binary patch delta 7313 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 delta 7350 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 cCP1QO0q)J67;le3tpH*k!yLvpxSyxNB{r; From 8fbfbdc103f88e18c069de7b3a4c574edb216018 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:22:52 +0100 Subject: [PATCH 02/10] Adding upstream version 1.8. Signed-off-by: Daniel Baumann --- COPYING | 19 ++++ ChangeLog | 8 +- INSTALL | 2 +- Makefile.in | 10 +- NEWS | 13 +-- README | 14 +-- carg_parser.c | 9 +- carg_parser.h | 2 +- configure | 21 +++-- doc/pdlzip.1 | 6 +- lzip.h | 18 +++- main.c | 99 ++++++++++--------- testsuite/check.sh | 231 +++++++++++++++++++++++++++------------------ 13 files changed, 269 insertions(+), 183 deletions(-) create mode 100644 COPYING diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b741254 --- /dev/null +++ b/COPYING @@ -0,0 +1,19 @@ + Pdlzip - LZMA lossless data compressor + Copyright (C) Antonio Diaz Diaz. + Pdlzip includes public domain (de)compression code from the LZMA SDK + (Software Development Kit) written by Igor Pavlov. + + This program is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/ChangeLog b/ChangeLog index b05668d..9d6c5c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-04-12 Antonio Diaz Diaz + + * Version 1.8 released. + * main.c: Continue testing if any input file is a terminal. + * main.c (decompress): Improved detection of trailing data. + 2016-05-16 Antonio Diaz Diaz * Version 1.7 released. @@ -67,7 +73,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2016 Antonio Diaz Diaz. +Copyright (C) 2010-2017 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 diff --git a/INSTALL b/INSTALL index bfa113e..419e1af 100644 --- a/INSTALL +++ b/INSTALL @@ -61,7 +61,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2016 Antonio Diaz Diaz. +Copyright (C) 2010-2017 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/Makefile.in b/Makefile.in index d028174..e720a0d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,7 +13,8 @@ objs = carg_parser.o LzFind.o LzmaEnc.o LzmaDec.o main.o .PHONY : all install install-bin install-info install-man \ install-strip install-compress install-strip-compress \ install-bin-strip install-info-compress install-man-compress \ - install-as-lzip uninstall uninstall-bin uninstall-info uninstall-man \ + install-as-lzip \ + uninstall uninstall-bin uninstall-info uninstall-man \ doc info man check dist clean distclean all : $(progname) @@ -106,6 +107,7 @@ dist : doc ln -sf $(VPATH) $(DISTNAME) tar -Hustar --owner=root --group=root -cvf $(DISTNAME).tar \ $(DISTNAME)/AUTHORS \ + $(DISTNAME)/COPYING \ $(DISTNAME)/ChangeLog \ $(DISTNAME)/INSTALL \ $(DISTNAME)/Makefile.in \ @@ -113,12 +115,12 @@ dist : doc $(DISTNAME)/README \ $(DISTNAME)/configure \ $(DISTNAME)/doc/$(progname).1 \ + $(DISTNAME)/*.h \ + $(DISTNAME)/*.c \ $(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/test.txt \ $(DISTNAME)/testsuite/test.txt.lz \ - $(DISTNAME)/testsuite/test.txt.lzma \ - $(DISTNAME)/*.h \ - $(DISTNAME)/*.c + $(DISTNAME)/testsuite/test.txt.lzma rm -f $(DISTNAME) lzip -v -9 $(DISTNAME).tar diff --git a/NEWS b/NEWS index 5ffa79b..e1cbb03 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,6 @@ -Changes in version 1.7: +Changes in version 1.8: -The option "-a, --trailing-error", which makes pdlzip exit with error -status 2 if any remaining input is detected after decompressing the last -member, has been added. +In test mode, pdlzip now continues checking the rest of the files if any +input file is a terminal. -When decompressing, the file specified with the '--output' option is now -deleted if the input is a terminal. - -A harmless check failure on Windows, caused by the failed comparison of -a message in text mode, has been fixed. +Trailing data shorter than a lzip header are now also reported. diff --git a/README b/README index ab5e4b1..e392d71 100644 --- a/README +++ b/README @@ -20,11 +20,11 @@ availability: merging of damaged copies of a file. * The lzip format is as simple as possible (but not simpler). The - lzip manual provides the code of a simple decompressor along with a - detailed explanation of how it works, so that with the only help of - the lzip manual it would be possible for a digital archaeologist to - extract the data from a lzip file long after quantum computers - eventually render LZMA obsolete. + lzip manual provides the source code of a simple decompressor along + with a detailed explanation of how it works, so that with the only + help of the lzip manual it would be possible for a digital + archaeologist to extract the data from a lzip file long after + quantum computers eventually render LZMA obsolete. * Additionally the lzip reference implementation is copylefted, which guarantees that it will remain free forever. @@ -37,7 +37,7 @@ corrupt byte near the beginning is a thing of the past. Pdlzip is also able to decompress legacy lzma-alone (.lzma) files. Lzma-alone is a very bad format; it is essentially a raw LZMA stream. If you keep any lzma-alone files, it is advisable to recompress them to -lzip format. Lziprecover can convert lzma-alone files to lzip format +lzip format. Lziprecover can convert some lzma-alone files to lzip format without recompressing. Pdlzip is written in C. @@ -52,7 +52,7 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2016 Antonio Diaz Diaz. +Copyright (C) 2010-2017 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/carg_parser.c b/carg_parser.c index 3d4e89f..6850643 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-2016 Antonio Diaz Diaz. + Copyright (C) 2006-2017 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -94,7 +94,7 @@ static char parse_long_option( struct Arg_parser * const ap, else if( index < 0 ) index = i; /* First nonexact match found */ else if( options[index].code != options[i].code || options[index].has_arg != options[i].has_arg ) - ambig = 1; /* Second or later nonexact match found */ + ambig = 1; /* Second or later nonexact match found */ } if( ambig && !exact ) @@ -230,7 +230,9 @@ char ap_init( struct Arg_parser * const ap, } else { - if( !in_order ) + if( in_order ) + { 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 ); @@ -238,7 +240,6 @@ char ap_init( struct Arg_parser * const ap, non_options = (const char **)tmp; non_options[non_options_size++] = argv[argind++]; } - else if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; } } if( ap->error ) free_data( ap ); diff --git a/carg_parser.h b/carg_parser.h index e918942..c4ce31d 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-2016 Antonio Diaz Diaz. + Copyright (C) 2006-2017 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/configure b/configure index cab895f..4380dac 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2016 Antonio Diaz Diaz. +# Copyright (C) 2010-2017 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. pkgname=pdlzip -pkgversion=1.7 +pkgversion=1.8 progname=pdlzip srctrigger=doc/${progname}.1 @@ -26,11 +26,11 @@ CFLAGS='-Wall -W -O2' LDFLAGS= # checking whether we are using GNU C. -if /bin/sh -c "${CC} --version" > /dev/null 2>&1 ; then true -else +/bin/sh -c "${CC} --version" > /dev/null 2>&1 || + { CC=cc - CFLAGS='-W -O2' -fi + CFLAGS=-O2 + } # Loop over all args args= @@ -52,9 +52,12 @@ while [ $# != 0 ] ; do # Process the options case ${option} in --help | -h) - echo "Usage: configure [options]" + echo "Usage: $0 [OPTION]... [VAR=VALUE]..." echo - echo "Options: [defaults in brackets]" + echo "To assign makefile variables (e.g., CC, CFLAGS...), specify them as" + echo "arguments to configure in the form VAR=VALUE." + echo + 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 sources in DIR [. or ..]" @@ -165,7 +168,7 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2016 Antonio Diaz Diaz. +# Copyright (C) 2010-2017 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/doc/pdlzip.1 b/doc/pdlzip.1 index 8e76b32..155e5c5 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH PDLZIP "1" "May 2016" "pdlzip 1.7" "User Commands" +.TH PDLZIP "1" "April 2017" "pdlzip 1.8" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -11,7 +11,7 @@ compressor also able to decompress legacy lzma\-alone (.lzma) files. .PP Lzma\-alone is a very bad format; it is essentially a raw LZMA stream. If you keep any lzma\-alone files, it is advisable to recompress them to -lzip format. Lziprecover can convert lzma\-alone files to lzip format +lzip format. Lziprecover can convert some lzma\-alone files to lzip format without recompressing. .SH OPTIONS .TP @@ -88,7 +88,7 @@ Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2016 Antonio Diaz Diaz. +Copyright \(co 2017 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index f84c53c..631599d 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2016 Antonio Diaz Diaz. + Copyright (C) 2010-2017 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -29,8 +29,10 @@ typedef int State; enum { min_dictionary_bits = 12, min_dictionary_size = 1 << min_dictionary_bits, - max_dictionary_bits = 27, /* kDicLogSizeMaxCompress */ + max_dictionary_bits = 29, max_dictionary_size = 1 << max_dictionary_bits, + max_dictionary_bits_c = 27, /* kDicLogSizeMaxCompress */ + max_dictionary_size_c = 1 << max_dictionary_bits_c, literal_context_bits = 3, literal_pos_state_bits = 0, /* not used */ pos_state_bits = 2, @@ -66,9 +68,9 @@ static inline void Pp_init( struct Pretty_print * const pp, pp->stdin_name = "(stdin)"; pp->longest_name = 0; pp->first_post = false; - stdin_name_len = strlen( pp->stdin_name ); if( verbosity <= 0 ) return; + stdin_name_len = strlen( pp->stdin_name ); for( i = 0; i < num_filenames; ++i ) { const char * const s = filenames[i]; @@ -114,8 +116,10 @@ static inline void CRC32_update_buf( uint32_t * const crc, const int size ) { int i; + uint32_t c = *crc; for( i = 0; i < size; ++i ) - *crc = crc32[(*crc^buffer[i])&0xFF] ^ ( *crc >> 8 ); + c = crc32[(c^buffer[i])&0xFF] ^ ( c >> 8 ); + *crc = c; } @@ -175,7 +179,7 @@ static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) { const unsigned base_size = 1 << data[5]; const unsigned fraction = base_size / 16; - int i; + unsigned i; for( i = 7; i >= 1; --i ) if( base_size - ( i * fraction ) >= sz ) { data[5] |= ( i << 5 ); break; } @@ -222,6 +226,8 @@ static inline void Ft_set_member_size( File_trailer data, unsigned long long sz { int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } +static const char * const trailing_msg = "Trailing data not allowed."; + /* defined in main.c */ int readblock( const int fd, uint8_t * const buf, const int size ); int writeblock( const int fd, const uint8_t * const buf, const int size ); @@ -230,6 +236,8 @@ int writeblock( const int fd, const uint8_t * const buf, const int size ); extern int verbosity; void cleanup_and_fail( const int retval ); void show_error( const char * const msg, const int errcode, const bool help ); +void show_file_error( const char * const filename, const char * const msg, + const int errcode ); void internal_error( const char * const msg ); #define SZ_OK 0 diff --git a/main.c b/main.c index 5e09fe0..de8e12e 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-2016 Antonio Diaz Diaz. + Copyright (C) 2010-2017 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -70,10 +70,10 @@ int verbosity = 0; const char * const Program_name = "Pdlzip"; const char * const program_name = "pdlzip"; -const char * const program_year = "2016"; +const char * const program_year = "2017"; const char * invocation_name = 0; -struct { const char * from; const char * to; } const known_extensions[] = { +const struct { const char * from; const char * to; } known_extensions[] = { { ".lz", "" }, { ".tlz", ".tar" }, { ".lzma", "" }, @@ -98,7 +98,7 @@ static void show_help( void ) printf( "compressor also able to decompress legacy lzma-alone (.lzma) files.\n" "\nLzma-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" - "lzip format. Lziprecover can convert lzma-alone files to lzip format\n" + "lzip format. Lziprecover can convert some lzma-alone files to lzip format\n" "without recompressing.\n" "\nUsage: %s [options] [files]\n", invocation_name ); printf( "\nOptions:\n" @@ -154,9 +154,9 @@ static void show_header( const unsigned dictionary_size ) { if( verbosity >= 3 ) { + enum { factor = 1024 }; const char * const prefix[8] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; - enum { factor = 1024 }; const char * p = ""; const char * np = " "; unsigned num = dictionary_size, i; @@ -165,7 +165,7 @@ static void show_header( const unsigned dictionary_size ) for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) { num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; np = ""; } - fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); + fprintf( stderr, "dictionary %s%4u %sB. ", np, num, p ); } } @@ -186,7 +186,7 @@ static unsigned long getnum( const char * const ptr, if( !errno && tail[0] ) { - const int 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] ) @@ -225,25 +225,25 @@ static unsigned long getnum( const char * const ptr, static int get_dict_size( const char * const arg ) { char * tail; - const int bits = strtol( arg, &tail, 0 ); + const long bits = strtol( arg, &tail, 0 ); if( bits >= min_dictionary_bits && - bits <= max_dictionary_bits && *tail == 0 ) + bits <= max_dictionary_bits_c && *tail == 0 ) return ( 1 << bits ); - return getnum( arg, min_dictionary_size, max_dictionary_size ); + return getnum( arg, min_dictionary_size, max_dictionary_size_c ); } static int extension_index( const char * const name ) { - int i; - for( i = 0; known_extensions[i].from; ++i ) + int eindex; + for( eindex = 0; known_extensions[eindex].from; ++eindex ) { - const char * const ext = known_extensions[i].from; + const char * const ext = known_extensions[eindex].from; const unsigned name_len = strlen( name ); const unsigned ext_len = strlen( ext ); if( name_len > ext_len && strncmp( name + name_len - ext_len, ext, ext_len ) == 0 ) - return i; + return eindex; } return -1; } @@ -264,11 +264,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp { infd = open( name, O_RDONLY | O_BINARY ); if( infd < 0 ) - { - if( verbosity >= 0 ) - fprintf( stderr, "%s: Can't open input file '%s': %s\n", - program_name, name, strerror( errno ) ); - } + show_file_error( name, "Can't open input file", errno ); else { const int i = fstat( infd, in_statsp ); @@ -294,7 +290,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp /* assure at least a minimum size for buffer 'buf' */ -static void * resize_buffer( void * buf, const int min_size ) +static void * resize_buffer( void * buf, const unsigned min_size ) { if( buf ) buf = realloc( buf, min_size ); else buf = malloc( min_size ); @@ -316,19 +312,19 @@ static void set_c_outname( const char * const name ) } -static void set_d_outname( const char * const name, const int i ) +static void set_d_outname( const char * const name, const int eindex ) { const unsigned name_len = strlen( name ); - if( i >= 0 ) + if( eindex >= 0 ) { - const char * const from = known_extensions[i].from; + const char * const from = known_extensions[eindex].from; const unsigned from_len = strlen( from ); if( name_len > from_len ) { output_filename = resize_buffer( output_filename, name_len + - strlen( known_extensions[0].to ) + 1 ); + strlen( known_extensions[eindex].to ) + 1 ); strcpy( output_filename, name ); - strcpy( output_filename + name_len - from_len, known_extensions[i].to ); + strcpy( output_filename + name_len - from_len, known_extensions[eindex].to ); return; } } @@ -364,7 +360,8 @@ static bool open_outstream( const bool force, const bool from_stdin ) } -static bool check_tty( const int infd, const enum Mode program_mode ) +static bool check_tty( const char * const input_filename, const int infd, + const enum Mode program_mode ) { if( program_mode == m_compress && isatty( outfd ) ) { @@ -374,7 +371,8 @@ static bool check_tty( const int infd, const enum Mode program_mode ) if( ( program_mode == m_decompress || program_mode == m_test ) && isatty( infd ) ) { - show_error( "I won't read compressed data from a terminal.", 0, true ); + show_file_error( input_filename, + "I won't read compressed data from a terminal.", 0 ); return false; } return true; @@ -432,7 +430,7 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) static int compress( const struct Lzma_options * const encoder_options, - const int infd, struct Pretty_print * const pp ) + struct Pretty_print * const pp, const int infd ) { int retval = 0; CLzmaEncHandle encoder = 0; @@ -604,9 +602,8 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], { error = true; if( verbosity >= 0 ) - fprintf( stderr, "Trailer truncated at trailer position %u;" - " some checks may fail.\n", - (unsigned)(*inSize - *inPos) ); + fprintf( stderr, "Trailer truncated at trailer position %d;" + " some checks may fail.\n", *inSize - *inPos ); for( i = *inSize - *inPos; i < Ft_size; ++i ) inBuf[*inPos+i] = 0; } @@ -641,7 +638,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], ( 8.0 * total_in ) / total_out, 100.0 * ( 1.0 - ( (double)total_in / total_out ) ) ); if( !error && verbosity >= 4 ) - fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ", + fprintf( stderr, "CRC %08X, decompressed %9llu, compressed %8llu. ", crc, total_out, total_in ); if( error ) return 2; return 0; @@ -677,6 +674,8 @@ static int decompress( const int infd, struct Pretty_print * const pp, if( first_member || Fh_verify_prefix( header, size ) ) { Pp_show_msg( pp, "File ends unexpectedly at member header." ); retval = 2; } + else if( size > 0 && !ignore_trailing ) + { show_file_error( pp->name, trailing_msg, 0 ); retval = 2; } break; } if( !Fh_verify_magic( header ) ) @@ -684,7 +683,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, if( !first_member ) { if( !ignore_trailing ) - { Pp_show_msg( pp, "Trailing data not allowed." ); retval = 2; } + { show_file_error( pp->name, trailing_msg, 0 ); retval = 2; } break; } if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */ @@ -704,7 +703,8 @@ static int decompress( const int infd, struct Pretty_print * const pp, } if( lzip_mode ) { - Pp_show_msg( pp, "Bad magic number (file not in lzip format)." ); + show_file_error( pp->name, + "Bad magic number (file not in lzip format).", 0 ); retval = 2; break; } } @@ -839,6 +839,16 @@ 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 ) + { + if( verbosity < 0 ) return; + fprintf( stderr, "%s: %s: %s", program_name, filename, msg ); + if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); + fputc( '\n', stderr ); + } + + void internal_error( const char * const msg ) { if( verbosity >= 0 ) @@ -864,7 +874,6 @@ int main( const int argc, const char * const argv[] ) { 3 << 23, 132 }, /* -8 */ { 1 << 25, 273 } }; /* -9 */ struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ - const char * input_filename = ""; const char * default_output_filename = ""; const char ** filenames = 0; int num_filenames = 0; @@ -877,8 +886,8 @@ int main( const int argc, const char * const argv[] ) bool force = false; bool ignore_trailing = true; bool keep_input_files = false; - bool stdin_used = false; bool recompress = false; + bool stdin_used = false; bool to_stdout = false; struct Pretty_print pp; @@ -961,9 +970,6 @@ int main( const int argc, const char * const argv[] ) setmode( STDOUT_FILENO, O_BINARY ); #endif - if( program_mode == m_test ) - outfd = -1; - num_filenames = max( 1, ap_arguments( &parser ) - argind ); filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); filenames[0] = "-"; @@ -974,6 +980,9 @@ int main( const int argc, const char * const argv[] ) if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true; } + if( program_mode == m_test ) + outfd = -1; + if( !to_stdout && program_mode != m_test && ( filenames_given || default_output_filename[0] ) ) set_signals(); @@ -983,6 +992,7 @@ int main( const int argc, const char * const argv[] ) output_filename = resize_buffer( output_filename, 1 ); for( i = 0; i < num_filenames; ++i ) { + const char * input_filename = ""; int tmp; struct stat in_stats; const struct stat * in_statsp; @@ -991,7 +1001,6 @@ int main( const int argc, const char * const argv[] ) if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) { if( stdin_used ) continue; else stdin_used = true; - input_filename = ""; infd = STDIN_FILENO; if( program_mode != m_test ) { @@ -1018,8 +1027,7 @@ int main( const int argc, const char * const argv[] ) } else { - const int eindex = extension_index( filenames[i] ); - input_filename = filenames[i]; + const int eindex = extension_index( input_filename = filenames[i] ); infd = open_instream( input_filename, &in_stats, program_mode, eindex, recompress, to_stdout ); if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } @@ -1041,16 +1049,17 @@ int main( const int argc, const char * const argv[] ) } } - if( !check_tty( infd, program_mode ) ) + Pp_set_name( &pp, input_filename ); + if( !check_tty( pp.name, infd, program_mode ) ) { if( retval < 1 ) retval = 1; + if( program_mode == m_test ) { close( infd ); infd = -1; continue; } cleanup_and_fail( retval ); } in_statsp = input_filename[0] ? &in_stats : 0; - Pp_set_name( &pp, input_filename ); if( program_mode == m_compress ) - tmp = compress( &encoder_options, infd, &pp ); + tmp = compress( &encoder_options, &pp, infd ); else tmp = decompress( infd, &pp, ignore_trailing, program_mode == m_test ); if( tmp > retval ) retval = tmp; diff --git a/testsuite/check.sh b/testsuite/check.sh index 1147256..82e609a 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-2016 Antonio Diaz Diaz. +# Copyright (C) 2010-2017 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -17,12 +17,12 @@ if [ ! -f "${LZIP}" ] || [ ! -x "${LZIP}" ] ; then exit 1 fi -if [ -e "${LZIP}" ] 2> /dev/null ; then true -else +[ -e "${LZIP}" ] 2> /dev/null || + { echo "$0: a POSIX shell is required to run the tests" echo "Try bash -c \"$0 $1 $2\"" exit 1 -fi + } if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp @@ -31,149 +31,192 @@ cd "${objdir}"/tmp || framework_failure cat "${testdir}"/test.txt > in || framework_failure in_lz="${testdir}"/test.txt.lz fail=0 +test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } printf "testing pdlzip-%s..." "$2" "${LZIP}" -fkqm4 in -if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO "${LZIP}" -fkqm274 in -if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -fkqs-1 in -if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -fkqs0 in -if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -fkqs4095 in -if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -fkqs513MiB in -if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi +{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO +for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do + "${LZIP}" -fkqs $i in + { [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO $i +done "${LZIP}" -tq in -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO "${LZIP}" -tq < in -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO "${LZIP}" -cdq in -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO "${LZIP}" -cdq < in -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -dd if="${in_lz}" bs=1 count=6 2> /dev/null | "${LZIP}" -tq -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -dd if="${in_lz}" bs=1 count=20 2> /dev/null | "${LZIP}" -tq -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO +# these are for code coverage +"${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 +"${LZIP}" -m 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -z 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --bad_option 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --t 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --test=2 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --output= 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --output 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +printf "LZIP\001-.............................." | "${LZIP}" -t 2> /dev/null +printf "LZIP\002-.............................." | "${LZIP}" -t 2> /dev/null +printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null printf "\ntesting decompression..." -"${LZIP}" -t "${in_lz}" -if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cd "${in_lz}" > copy || fail=1 -cmp in copy || fail=1 -printf . +"${LZIP}" -t "${in_lz}" || test_failed $LINENO +"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO -"${LZIP}" -t "${testdir}"/test.txt.lzma -if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || fail=1 -cmp in copy || fail=1 -printf . +"${LZIP}" -t "${testdir}"/test.txt.lzma || test_failed $LINENO +"${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO rm -f copy cat "${in_lz}" > copy.lz || framework_failure -"${LZIP}" -dk copy.lz || fail=1 -cmp in copy || fail=1 +"${LZIP}" -dk copy.lz || test_failed $LINENO +cmp in copy || test_failed $LINENO printf "to be overwritten" > copy || framework_failure -"${LZIP}" -dq copy.lz -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -d copy.lz 2> /dev/null +[ $? = 1 ] || test_failed $LINENO "${LZIP}" -df copy.lz -if [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; then - printf . ; else printf - ; fail=1 ; fi +{ [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; } || test_failed $LINENO printf "to be overwritten" > copy || framework_failure -"${LZIP}" -df -o copy < "${in_lz}" || fail=1 -cmp in copy || fail=1 -printf . +"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO +cmp in copy || test_failed $LINENO rm -f copy -"${LZIP}" -s16 < in > anyothername || fail=1 -"${LZIP}" -d -o copy - anyothername - < "${in_lz}" -if [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; then - printf . ; else printf - ; fail=1 ; fi +"${LZIP}" -s16 < in > anyothername || test_failed $LINENO +"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null +{ [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; } || + test_failed $LINENO rm -f copy anyothername.out "${LZIP}" -tq in "${in_lz}" -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -tq foo.lz "${in_lz}" -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -tq nx_file.lz "${in_lz}" +[ $? = 1 ] || test_failed $LINENO "${LZIP}" -cdq in "${in_lz}" > copy -if [ $? = 2 ] && cat copy in | cmp in - ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cdq foo.lz "${in_lz}" > copy -if [ $? = 1 ] && cmp in copy ; then printf . ; else printf - ; fail=1 ; fi +{ [ $? = 2 ] && cat copy in | cmp in - ; } || test_failed $LINENO +"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy +{ [ $? = 1 ] && cmp in copy ; } || test_failed $LINENO rm -f copy cat "${in_lz}" > copy.lz || framework_failure +for i in 1 2 3 4 5 6 7 ; do + printf "g" >> copy.lz || framework_failure + "${LZIP}" -atvvvv copy.lz "${in_lz}" 2> /dev/null + [ $? = 2 ] || test_failed $LINENO $i +done "${LZIP}" -dq in copy.lz -if [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; then - printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -dq foo.lz copy.lz -if [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e foo ] && cmp in copy ; then - printf . ; else printf - ; fail=1 ; fi +{ [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; } || + test_failed $LINENO +"${LZIP}" -dq nx_file.lz copy.lz +{ [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e nx_file ] && cmp in copy ; } || + test_failed $LINENO cat in in > in2 || framework_failure -"${LZIP}" -s16 -o copy2 < in2 || fail=1 -"${LZIP}" -t copy2.lz || fail=1 -"${LZIP}" -cd copy2.lz > copy2 || fail=1 -cmp in2 copy2 || fail=1 -printf . +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 -printf "garbage" >> copy2.lz || framework_failure +"${LZIP}" -s16 --output=copy2 < in2 || test_failed $LINENO +"${LZIP}" -t copy2.lz || test_failed $LINENO +"${LZIP}" -cd copy2.lz > copy2 || test_failed $LINENO +cmp in2 copy2 || test_failed $LINENO + +printf "\ngarbage" >> copy2.lz || framework_failure +"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO rm -f copy2 "${LZIP}" -atq copy2.lz -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO "${LZIP}" -atq < copy2.lz -if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +[ $? = 2 ] || test_failed $LINENO "${LZIP}" -adkq copy2.lz -if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi +{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO "${LZIP}" -adkq -o copy2 < copy2.lz -if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi +{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO printf "to be overwritten" > copy2 || framework_failure -"${LZIP}" -df copy2.lz || fail=1 -cmp in2 copy2 || fail=1 -printf . +"${LZIP}" -df copy2.lz || test_failed $LINENO +cmp in2 copy2 || test_failed $LINENO printf "\ntesting compression..." -"${LZIP}" -cfq "${in_lz}" > out # /dev/null is a tty on OS/2 -if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${LZIP}" -cF -s16 "${in_lz}" > out || fail=1 -"${LZIP}" -cd out | "${LZIP}" -d > copy || fail=1 -cmp in copy || fail=1 -printf . +"${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2 +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -cFvvm36 -s16 "${in_lz}" > out 2> /dev/null || test_failed $LINENO +"${LZIP}" -cd out | "${LZIP}" -d > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do - "${LZIP}" -k -$i -s16 in || fail=1 - mv -f in.lz copy.lz || fail=1 - printf "garbage" >> copy.lz || fail=1 - "${LZIP}" -df copy.lz || fail=1 - cmp in copy || fail=1 + "${LZIP}" -k -$i -s16 in || test_failed $LINENO $i + mv -f in.lz copy.lz || test_failed $LINENO $i + printf "garbage" >> copy.lz || framework_failure + "${LZIP}" -df copy.lz || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i done -printf . for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do - "${LZIP}" -c -$i -s16 in > out || fail=1 - printf "g" >> out || fail=1 - "${LZIP}" -cd out > copy || fail=1 - cmp in copy || fail=1 + "${LZIP}" -c -$i -s16 in > out || test_failed $LINENO $i + printf "g" >> out || framework_failure + "${LZIP}" -cd out > copy || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i done -printf . for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do - "${LZIP}" -$i -s16 < in > out || fail=1 - "${LZIP}" -d < out > copy || fail=1 - cmp in copy || fail=1 + "${LZIP}" -$i -s16 < in > out || test_failed $LINENO $i + "${LZIP}" -d < out > copy || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i done -printf . for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do - "${LZIP}" -f -$i -s16 -o out < in || fail=1 - "${LZIP}" -df -o copy < out.lz || fail=1 - cmp in copy || fail=1 + "${LZIP}" -f -$i -s16 -o out < in || test_failed $LINENO $i + "${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i done -printf . + +printf "\ntesting bad input..." + +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 + dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null + "${LZIP}" -t trunc.lz 2> /dev/null + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -tq < trunc.lz + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -cdq trunc.lz > out + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -dq < trunc.lz > out + [ $? = 2 ] || test_failed $LINENO $i + done +else + printf "\nwarning: skipping truncation test: 'dd' does not work on your system." +fi + +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}" -d < ingin.lz > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO echo if [ ${fail} = 0 ] ; then From d2ef351ac9bf5828ac05acc4836f571984413eb4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:23:49 +0100 Subject: [PATCH 03/10] Adding upstream version 1.9. Signed-off-by: Daniel Baumann --- ChangeLog | 17 +- INSTALL | 2 +- LzmaEnc.c | 10 +- NEWS | 28 +++- README | 4 +- carg_parser.c | 2 +- carg_parser.h | 2 +- configure | 6 +- doc/pdlzip.1 | 7 +- lzip.h | 39 ++++- main.c | 393 +++++++++++++++++++++++++-------------------- testsuite/check.sh | 35 +++- 12 files changed, 340 insertions(+), 205 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9d6c5c3..d90a18f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2018-02-04 Antonio Diaz Diaz + + * Version 1.9 released. + * main.c: Added new option '--loose-trailing'. + * main.c (decompress): Improved corrupt header detection to HD=3. + * Replaced 'bits/byte' with inverse compression ratio in output. + * main.c: 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. + Show dictionary size at verbosity level 4 (-vvvv). + 2017-04-12 Antonio Diaz Diaz * Version 1.8 released. @@ -11,8 +22,8 @@ * main.c (main): Delete '--output' file if infd is a terminal. * main.c (main): Don't use stdin more than once. * configure: Avoid warning on some shells when testing for gcc. - * testsuite/check.sh: A POSIX shell is required to run the tests. - * testsuite/check.sh: Don't check error messages. + * check.sh: A POSIX shell is required to run the tests. + * check.sh: Don't check error messages. 2015-05-26 Antonio Diaz Diaz @@ -73,7 +84,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2017 Antonio Diaz Diaz. +Copyright (C) 2010-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 diff --git a/INSTALL b/INSTALL index 419e1af..327c502 100644 --- a/INSTALL +++ b/INSTALL @@ -61,7 +61,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2017 Antonio Diaz Diaz. +Copyright (C) 2010-2018 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/LzmaEnc.c b/LzmaEnc.c index e931a3d..1dd8ea1 100644 --- a/LzmaEnc.c +++ b/LzmaEnc.c @@ -1371,14 +1371,14 @@ static void LZe_full_flush(CLzmaEnc *p, uint32_t posState) { unsigned long long in_size = p->nowPos64; unsigned long long out_size = p->rc.processed + Fh_size + Ft_size; - if( in_size <= 0 || out_size <= 0 ) + if( in_size == 0 || out_size == 0 ) fputs( " no data compressed.\n", stderr ); else - fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " - "%5.2f%% saved, %llu in, %llu out.\n", + fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved, " + "%llu in, %llu out.\n", (double)in_size / out_size, - ( 8.0 * out_size ) / in_size, - 100.0 * ( 1.0 - ( (double)out_size / in_size ) ), + ( 100.0 * out_size ) / in_size, + 100.0 - ( ( 100.0 * out_size ) / in_size ), in_size, out_size ); } } diff --git a/NEWS b/NEWS index e1cbb03..d99cfae 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,26 @@ -Changes in version 1.8: +Changes in version 1.9: -In test mode, pdlzip now continues checking the rest of the files if any -input file is a terminal. +The option '--loose-trailing', has been added. -Trailing data shorter than a lzip header are now also reported. +The test used by pdlzip to discriminate trailing data from a corrupt +header in multimember or concatenated files has been improved to a +Hamming distance (HD) of 3, and the 3 bit flips must happen in different +magic bytes for the test to fail. As a consequence some kinds of files +no longer can be appended to a lzip file as trailing data unless the +'--loose-trailing' option is used when decompressing. +Lziprecover can be used to remove conflicting trailing data from a file. + +The 'bits/byte' ratio has been replaced with the inverse compression +ratio in the output. + +A final diagnostic is now shown at verbosity level 1 (-v) or higher if +any file fails the test when testing multiple files. + +A second '.lz' extension is no longer added to the argument of '-o' if +it already ends in '.lz' or '.tlz'. + +In case of (de)compressed size mismatch, the stored size is now also +shown in hexadecimal to ease visual comparison. + +The dictionary size is now shown at verbosity level 4 (-vvvv) when +decompressing or testing. diff --git a/README b/README index e392d71..517adcf 100644 --- a/README +++ b/README @@ -14,7 +14,7 @@ archiving, taking into account both data integrity and decoder availability: * The lzip format provides very safe integrity checking and some data - recovery means. The lziprecover program can repair bit-flip errors + recovery means. The lziprecover program can repair bit flip errors (one of the most common forms of data corruption) in lzip files, and provides data recovery capabilities, including error-checked merging of damaged copies of a file. @@ -52,7 +52,7 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2017 Antonio Diaz Diaz. +Copyright (C) 2010-2018 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/carg_parser.c b/carg_parser.c index 6850643..10ad4dc 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-2017 Antonio Diaz Diaz. + 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 diff --git a/carg_parser.h b/carg_parser.h index c4ce31d..e1c70dd 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-2017 Antonio Diaz Diaz. + 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 diff --git a/configure b/configure index 4380dac..75f55bd 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2017 Antonio Diaz Diaz. +# Copyright (C) 2010-2018 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. pkgname=pdlzip -pkgversion=1.8 +pkgversion=1.9 progname=pdlzip srctrigger=doc/${progname}.1 @@ -168,7 +168,7 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2017 Antonio Diaz Diaz. +# Copyright (C) 2010-2018 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/doc/pdlzip.1 b/doc/pdlzip.1 index 155e5c5..e971323 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH PDLZIP "1" "April 2017" "pdlzip 1.8" "User Commands" +.TH PDLZIP "1" "February 2018" "pdlzip 1.9" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -65,6 +65,9 @@ alias for \fB\-1\fR .TP \fB\-\-best\fR alias for \fB\-9\fR +.TP +\fB\-\-loose\-trailing\fR +allow trailing data seeming corrupt header .PP If no file names are given, or if a file is '\-', pdlzip compresses or decompresses from standard input to standard output. @@ -88,7 +91,7 @@ Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2017 Antonio Diaz Diaz. +Copyright \(co 2018 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index 631599d..0f65f30 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2017 Antonio Diaz Diaz. + Copyright (C) 2010-2018 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -24,6 +24,8 @@ #define min(x,y) ((x) <= (y) ? (x) : (y)) #endif +void * resize_buffer( void * buf, const unsigned min_size ); + typedef int State; enum { @@ -50,9 +52,13 @@ enum { min_match_len_limit = 5 }; +/* 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; @@ -60,11 +66,12 @@ struct Pretty_print static inline void Pp_init( struct Pretty_print * const pp, const char * const filenames[], - const int num_filenames, const int verbosity ) + 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; @@ -83,9 +90,19 @@ static inline void Pp_init( struct Pretty_print * const pp, 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; } @@ -149,12 +166,21 @@ static inline void Fh_set_magic( File_header data ) static inline bool Fh_verify_magic( const File_header data ) { return ( memcmp( data, magic_string, 4 ) == 0 ); } -/* detect truncated header */ -static inline bool Fh_verify_prefix( const File_header data, const int size ) +/* detect (truncated) header */ +static inline bool Fh_verify_prefix( const File_header data, const int sz ) { - int i; for( i = 0; i < size && i < 4; ++i ) + int i; for( i = 0; i < sz && i < 4; ++i ) if( data[i] != magic_string[i] ) return false; - return ( size > 0 ); + return ( sz > 0 ); + } + +/* detect corrupt header */ +static inline bool Fh_verify_corrupt( const File_header data ) + { + int matches = 0; + int i; for( i = 0; i < 4; ++i ) + if( data[i] == magic_string[i] ) ++matches; + return ( matches > 1 && matches < 4 ); } static inline uint8_t Fh_version( const File_header data ) @@ -233,7 +259,6 @@ int readblock( const int fd, uint8_t * const buf, const int size ); int writeblock( const int fd, const uint8_t * const buf, const int size ); /* defined in main.c */ -extern int verbosity; void cleanup_and_fail( const int retval ); void show_error( const char * const msg, const int errcode, const bool help ); void show_file_error( const char * const filename, const char * const msg, diff --git a/main.c b/main.c index de8e12e..4803491 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-2017 Antonio Diaz Diaz. + Copyright (C) 2010-2018 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -70,7 +70,7 @@ int verbosity = 0; const char * const Program_name = "Pdlzip"; const char * const program_name = "pdlzip"; -const char * const program_year = "2017"; +const char * const program_year = "2018"; const char * invocation_name = 0; const struct { const char * from; const char * to; } known_extensions[] = { @@ -119,6 +119,7 @@ static void show_help( void ) " -1 .. -9 set compression level [default 6]\n" " --fast alias for -1\n" " --best alias for -9\n" + " --loose-trailing allow trailing data seeming corrupt header\n" "If no file names are given, or if a file is '-', pdlzip compresses or\n" "decompresses from standard input to standard output.\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" @@ -150,23 +151,49 @@ static void show_version( void ) } +/* assure at least a minimum size for buffer 'buf' */ +void * resize_buffer( void * buf, const unsigned min_size ) + { + if( buf ) buf = realloc( buf, min_size ); + else buf = malloc( min_size ); + if( !buf ) + { + show_error( "Not enough memory.", 0, false ); + cleanup_and_fail( 1 ); + } + return buf; + } + + +void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) + { + if( verbosity >= 0 ) + { + if( pp->first_post ) + { + pp->first_post = false; + fputs( pp->padded_name, stderr ); + if( !msg ) fflush( stderr ); + } + if( msg ) fprintf( stderr, "%s\n", msg ); + } + } + + static void show_header( const unsigned dictionary_size ) { - if( verbosity >= 3 ) - { - enum { factor = 1024 }; - const char * const prefix[8] = - { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; - const char * p = ""; - const char * np = " "; - unsigned num = dictionary_size, i; - bool exact = ( num % factor == 0 ); + enum { factor = 1024 }; + const char * const prefix[8] = + { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; + const char * p = ""; + const char * np = " "; + unsigned num = dictionary_size; + bool exact = ( num % factor == 0 ); - for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) - { num /= factor; if( num % factor != 0 ) exact = false; - p = prefix[i]; np = ""; } - fprintf( stderr, "dictionary %s%4u %sB. ", np, num, p ); - } + int i; for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) + { num /= factor; if( num % factor != 0 ) exact = false; + p = prefix[i]; np = ""; } + fprintf( stderr, "dictionary %s%4u %sB, ", np, num, p ); } @@ -249,6 +276,41 @@ static int extension_index( const char * const name ) } +static void set_c_outname( const char * const name, const bool force_ext ) + { + output_filename = resize_buffer( output_filename, strlen( name ) + + strlen( known_extensions[0].from ) + 1 ); + strcpy( output_filename, name ); + if( force_ext || extension_index( output_filename ) < 0 ) + strcat( output_filename, known_extensions[0].from ); + } + + +static void set_d_outname( const char * const name, const int eindex ) + { + const unsigned name_len = strlen( name ); + if( eindex >= 0 ) + { + const char * const from = known_extensions[eindex].from; + const unsigned from_len = strlen( from ); + if( name_len > from_len ) + { + output_filename = resize_buffer( output_filename, name_len + + strlen( known_extensions[eindex].to ) + 1 ); + strcpy( output_filename, name ); + strcpy( output_filename + name_len - from_len, known_extensions[eindex].to ); + return; + } + } + output_filename = resize_buffer( output_filename, name_len + 4 + 1 ); + strcpy( output_filename, name ); + strcat( output_filename, ".out" ); + if( verbosity >= 1 ) + 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 enum Mode program_mode, const int eindex, const bool recompress, const bool to_stdout ) @@ -289,54 +351,6 @@ static int open_instream( const char * const name, struct stat * const in_statsp } -/* assure at least a minimum size for buffer 'buf' */ -static void * resize_buffer( void * buf, const unsigned min_size ) - { - if( buf ) buf = realloc( buf, min_size ); - else buf = malloc( min_size ); - if( !buf ) - { - show_error( "Not enough memory.", 0, false ); - cleanup_and_fail( 1 ); - } - return buf; - } - - -static void set_c_outname( const char * const name ) - { - output_filename = resize_buffer( output_filename, strlen( name ) + - strlen( known_extensions[0].from ) + 1 ); - strcpy( output_filename, name ); - strcat( output_filename, known_extensions[0].from ); - } - - -static void set_d_outname( const char * const name, const int eindex ) - { - const unsigned name_len = strlen( name ); - if( eindex >= 0 ) - { - const char * const from = known_extensions[eindex].from; - const unsigned from_len = strlen( from ); - if( name_len > from_len ) - { - output_filename = resize_buffer( output_filename, name_len + - strlen( known_extensions[eindex].to ) + 1 ); - strcpy( output_filename, name ); - strcpy( output_filename + name_len - from_len, known_extensions[eindex].to ); - return; - } - } - output_filename = resize_buffer( output_filename, name_len + 4 + 1 ); - strcpy( output_filename, name ); - strcat( output_filename, ".out" ); - if( verbosity >= 1 ) - fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n", - program_name, name, output_filename ); - } - - static bool open_outstream( const bool force, const bool from_stdin ) { const mode_t usr_rw = S_IRUSR | S_IWUSR; @@ -492,9 +506,10 @@ enum { lzma_header_size = LZMA_PROPS_SIZE + 8 }; static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, uint8_t inBuf[], int * const inPos, - int * const inSize, const bool testing ) + int * const inSize, const unsigned dictionary_size, + const bool testing ) { - unsigned long long total_in = lzma_header_size, total_out = 0; + 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); @@ -519,14 +534,14 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, inBuf + *inPos, &inProcessed, finishMode, &status ) ) { show_error( "Data error.", 0, false ); return 2; } *inPos += inProcessed; - total_in += inProcessed; + member_size += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) { show_error( "Can't write output file", errno, false ); return 1; } - total_out += outPos; + data_size += outPos; outPos = 0; if( ( inProcessed == 0 && outProcessed == 0 ) || @@ -535,16 +550,21 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, if( ( thereIsSize && unpackSize != 0 ) || ( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) ) { show_error( "Data error.", 0, false ); return 2; } - if( verbosity >= 2 && total_out > 0 && total_in > 0 ) - fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ", - (double)total_out / total_in, - ( 8.0 * total_in ) / total_out, - 100.0 * ( 1.0 - ( (double)total_in / total_out ) ) ); - if( verbosity >= 4 ) - fprintf( stderr, "uncompressed size %9llu, compressed size %8llu. ", - total_out, total_in ); if( verbosity >= 2 ) + { + if( verbosity >= 4 ) show_header( dictionary_size ); + if( data_size == 0 || member_size == 0 ) + fputs( "no data compressed. ", stderr ); + else + fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", + (double)data_size / member_size, + ( 100.0 * member_size ) / data_size, + 100.0 - ( ( 100.0 * member_size ) / data_size ) ); + if( verbosity >= 3 ) + fprintf( stderr, "decompressed %9llu, compressed %8llu. ", + data_size, member_size ); fputs( "lzma-alone, ", stderr ); + } if( verbosity >= 1 ) fputs( testing ? "(apparently) ok\n" : "(apparently) done\n", stderr ); return 0; @@ -553,10 +573,12 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, } -static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], - int * const inPos, int * const inSize ) +static int lzip_decode( CLzmaDec *decoder, const int infd, + struct Pretty_print * const pp, uint8_t inBuf[], + int * const inPos, int * const inSize, + const unsigned dictionary_size ) { - unsigned long long total_in = Fh_size, total_out = 0; + unsigned long long member_size = Fh_size, data_size = 0; uint8_t outBuf[OUT_BUF_SIZE]; int outPos = 0; uint32_t crc = 0xFFFFFFFFU; @@ -571,76 +593,99 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], if( *inPos >= *inSize && !read_inbuf( infd, inBuf, inPos, inSize ) ) return 1; if( *inPos >= *inSize ) - { show_error( "Unexpected EOF.", 0, false ); return 2; } + { Pp_show_msg( pp, "Unexpected EOF." ); return 2; } inProcessed = *inSize - *inPos; if( !LzmaDec_DecodeToBuf( decoder, outBuf + outPos, &outProcessed, inBuf + *inPos, &inProcessed, finishMode, &status ) ) - { show_error( "Data error.", 0, false ); return 2; } + { Pp_show_msg( pp, "Data error." ); return 2; } *inPos += inProcessed; - total_in += inProcessed; + member_size += inProcessed; outPos += outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) { show_error( "Can't write output file", errno, false ); return 1; } CRC32_update_buf( &crc, outBuf, outPos ); - total_out += outPos; + data_size += outPos; outPos = 0; if (inProcessed == 0 && outProcessed == 0) { File_trailer trailer; int i; + unsigned td_crc; + unsigned long long td_size, tm_size; bool error = false; if( status != LZMA_STATUS_FINISHED_WITH_MARK ) - { show_error( "Data error.", 0, false ); return 2; } + { Pp_show_msg( pp, "Data error." ); return 2; } if( *inSize - *inPos < Ft_size && !read_inbuf( infd, inBuf, inPos, inSize ) ) return 1; if( *inSize - *inPos < Ft_size ) { error = true; if( verbosity >= 0 ) + { + Pp_show_msg( pp, 0 ); fprintf( stderr, "Trailer truncated at trailer position %d;" " some checks may fail.\n", *inSize - *inPos ); - for( i = *inSize - *inPos; i < Ft_size; ++i ) - inBuf[*inPos+i] = 0; + } } - for( i = 0; i < Ft_size; ++i ) + for( i = 0; i < Ft_size && *inPos < *inSize; ++i ) trailer[i] = inBuf[(*inPos)++]; - total_in += Ft_size; + member_size += i; + while( i < Ft_size ) trailer[i++] = 0; crc ^= 0xFFFFFFFFU; - if( Ft_get_data_crc( trailer ) != crc ) + td_crc = Ft_get_data_crc( trailer ); + if( td_crc != crc ) { error = true; if( verbosity >= 0 ) - fprintf( stderr, "CRC mismatch; trailer says %08X, data crc is %08X\n", - Ft_get_data_crc( trailer ), crc ); + { + Pp_show_msg( pp, 0 ); + fprintf( stderr, "CRC mismatch; stored %08X, computed %08X\n", + td_crc, crc ); + } } - if( Ft_get_data_size( trailer ) != total_out ) + td_size = Ft_get_data_size( trailer ); + if( td_size != data_size ) { error = true; if( verbosity >= 0 ) - fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX)\n", - Ft_get_data_size( trailer ), total_out, total_out ); + { + Pp_show_msg( pp, 0 ); + fprintf( stderr, "Data size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n", + td_size, td_size, data_size, data_size ); + } } - if( Ft_get_member_size( trailer ) != total_in ) + tm_size = Ft_get_member_size( trailer ); + if( tm_size != member_size ) { error = true; if( verbosity >= 0 ) - fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX)\n", - Ft_get_member_size( trailer ), total_in, total_in ); + { + Pp_show_msg( pp, 0 ); + fprintf( stderr, "Member size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n", + tm_size, tm_size, member_size, member_size ); + } } - if( !error && verbosity >= 2 && total_out > 0 && total_in > 0 ) - fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ", - (double)total_out / total_in, - ( 8.0 * total_in ) / total_out, - 100.0 * ( 1.0 - ( (double)total_in / total_out ) ) ); - if( !error && verbosity >= 4 ) - fprintf( stderr, "CRC %08X, decompressed %9llu, compressed %8llu. ", - crc, total_out, total_in ); if( error ) return 2; + if( verbosity >= 2 ) + { + if( verbosity >= 4 ) show_header( dictionary_size ); + if( data_size == 0 || member_size == 0 ) + fputs( "no data compressed. ", stderr ); + else + fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", + (double)data_size / member_size, + ( 100.0 * member_size ) / data_size, + 100.0 - ( ( 100.0 * member_size ) / data_size ) ); + if( verbosity >= 4 ) fprintf( stderr, "CRC %08X, ", td_crc ); + if( verbosity >= 3 ) + fprintf( stderr, "decompressed %9llu, compressed %8llu. ", + data_size, member_size ); + } return 0; } } @@ -648,7 +693,8 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], static int decompress( const int infd, struct Pretty_print * const pp, - const bool ignore_trailing, const bool testing ) + const bool ignore_trailing, const bool loose_trailing, + const bool testing ) { uint64_t unpackSize = 0; CLzmaDec decoder; @@ -671,19 +717,25 @@ static int decompress( const int infd, struct Pretty_print * const pp, raw_props[i] = header[i] = inBuf[inPos++]; if( size <= Fh_size ) /* End Of File */ { - if( first_member || Fh_verify_prefix( header, size ) ) - { Pp_show_msg( pp, "File ends unexpectedly at member header." ); + if( first_member ) + { show_file_error( pp->name, "File ends unexpectedly at member header.", 0 ); + retval = 2; } + else if( Fh_verify_prefix( header, size ) ) + { Pp_show_msg( pp, "Truncated header in multimember file." ); retval = 2; } else if( size > 0 && !ignore_trailing ) - { show_file_error( pp->name, trailing_msg, 0 ); retval = 2; } + { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } if( !Fh_verify_magic( header ) ) { if( !first_member ) { - if( !ignore_trailing ) - { show_file_error( pp->name, trailing_msg, 0 ); retval = 2; } + if( !loose_trailing && Fh_verify_corrupt( header ) ) + { Pp_show_msg( pp, "Corrupt header in multimember file." ); + retval = 2; } + else if( !ignore_trailing ) + { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */ @@ -730,15 +782,16 @@ static int decompress( const int infd, struct Pretty_print * const pp, } if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) - { Pp_show_msg( pp, 0 ); show_header( dictionary_size ); } + Pp_show_msg( pp, 0 ); if( !LzmaDec_Init( &decoder, raw_props ) ) { Pp_show_msg( pp, "Not enough memory." ); return 1; } if( lzip_mode ) - retval = lzip_decode( &decoder, infd, inBuf, &inPos, &inSize ); + retval = lzip_decode( &decoder, infd, pp, inBuf, &inPos, &inSize, + dictionary_size ); else - retval = lzma_decode( unpackSize, &decoder, infd, - inBuf, &inPos, &inSize, testing ); + retval = lzma_decode( unpackSize, &decoder, infd, inBuf, &inPos, + &inSize, dictionary_size, testing ); LzmaDec_Free(&decoder); if( retval != 0 || !lzip_mode ) break; if( verbosity >= 2 ) @@ -769,24 +822,6 @@ static void set_signals( void ) CRC32 crc32; -void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) - { - if( verbosity >= 0 ) - { - if( pp->first_post ) - { - unsigned i; - pp->first_post = false; - fprintf( stderr, " %s: ", pp->name ); - for( i = strlen( pp->name ); i < pp->longest_name; ++i ) - fputc( ' ', stderr ); - if( !msg ) fflush( stderr ); - } - if( msg ) fprintf( stderr, "%s\n", msg ); - } - } - - /* Returns the number of bytes really read. If (returned value < size) and (errno == 0), means EOF was reached. */ @@ -877,50 +912,53 @@ int main( const int argc, const char * const argv[] ) const char * default_output_filename = ""; const char ** filenames = 0; int num_filenames = 0; - int infd = -1; enum Mode program_mode = m_compress; int argind = 0; + int failed_tests = 0; int retval = 0; int i; bool filenames_given = false; bool force = false; bool ignore_trailing = true; bool keep_input_files = false; + bool loose_trailing = false; bool recompress = false; bool stdin_used = false; bool to_stdout = false; struct Pretty_print pp; + enum { opt_lt = 256 }; const struct ap_Option options[] = { - { '0', "fast", ap_no }, - { '1', 0, ap_no }, - { '2', 0, ap_no }, - { '3', 0, ap_no }, - { '4', 0, ap_no }, - { '5', 0, ap_no }, - { '6', 0, ap_no }, - { '7', 0, ap_no }, - { '8', 0, ap_no }, - { '9', "best", ap_no }, - { 'a', "trailing-error", ap_no }, - { 'b', "member-size", ap_yes }, - { 'c', "stdout", ap_no }, - { 'd', "decompress", ap_no }, - { 'f', "force", ap_no }, - { 'F', "recompress", ap_no }, - { 'h', "help", ap_no }, - { 'k', "keep", ap_no }, - { 'm', "match-length", ap_yes }, - { 'n', "threads", ap_yes }, - { 'o', "output", ap_yes }, - { 'q', "quiet", ap_no }, - { 's', "dictionary-size", ap_yes }, - { 'S', "volume-size", ap_yes }, - { 't', "test", ap_no }, - { 'v', "verbose", ap_no }, - { 'V', "version", ap_no }, - { 0 , 0, ap_no } }; + { '0', "fast", ap_no }, + { '1', 0, ap_no }, + { '2', 0, ap_no }, + { '3', 0, ap_no }, + { '4', 0, ap_no }, + { '5', 0, ap_no }, + { '6', 0, ap_no }, + { '7', 0, ap_no }, + { '8', 0, ap_no }, + { '9', "best", ap_no }, + { 'a', "trailing-error", ap_no }, + { 'b', "member-size", ap_yes }, + { 'c', "stdout", ap_no }, + { 'd', "decompress", ap_no }, + { 'f', "force", ap_no }, + { 'F', "recompress", ap_no }, + { 'h', "help", ap_no }, + { 'k', "keep", ap_no }, + { 'm', "match-length", ap_yes }, + { 'n', "threads", ap_yes }, + { 'o', "output", ap_yes }, + { 'q', "quiet", ap_no }, + { 's', "dictionary-size", ap_yes }, + { 'S', "volume-size", ap_yes }, + { 't', "test", ap_no }, + { 'v', "verbose", ap_no }, + { 'V', "version", ap_no }, + { opt_lt, "loose-trailing", ap_no }, + { 0 , 0, ap_no } }; struct Arg_parser parser; @@ -961,6 +999,7 @@ int main( const int argc, const char * const argv[] ) case 't': 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; default : internal_error( "uncaught option." ); } } /* end process options */ @@ -987,12 +1026,13 @@ int main( const int argc, const char * const argv[] ) ( filenames_given || default_output_filename[0] ) ) set_signals(); - Pp_init( &pp, filenames, num_filenames, verbosity ); + Pp_init( &pp, filenames, num_filenames ); 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; @@ -1009,17 +1049,17 @@ int main( const int argc, const char * const argv[] ) else { if( program_mode == m_compress ) - set_c_outname( default_output_filename ); + set_c_outname( default_output_filename, false ); else { output_filename = resize_buffer( output_filename, - strlen( default_output_filename ) + 1 ); + strlen( default_output_filename ) + 1 ); strcpy( output_filename, default_output_filename ); } if( !open_outstream( force, true ) ) { if( retval < 1 ) retval = 1; - close( infd ); infd = -1; + close( infd ); continue; } } @@ -1037,12 +1077,12 @@ int main( const int argc, const char * const argv[] ) else { if( program_mode == m_compress ) - set_c_outname( input_filename ); + set_c_outname( input_filename, true ); else set_d_outname( input_filename, eindex ); if( !open_outstream( force, false ) ) { if( retval < 1 ) retval = 1; - close( infd ); infd = -1; + close( infd ); continue; } } @@ -1053,7 +1093,7 @@ int main( const int argc, const char * const argv[] ) if( !check_tty( pp.name, infd, program_mode ) ) { if( retval < 1 ) retval = 1; - if( program_mode == m_test ) { close( infd ); infd = -1; continue; } + if( program_mode == m_test ) { close( infd ); continue; } cleanup_and_fail( retval ); } @@ -1061,24 +1101,31 @@ int main( const int argc, const char * const argv[] ) if( program_mode == m_compress ) tmp = compress( &encoder_options, &pp, infd ); else - tmp = decompress( infd, &pp, ignore_trailing, program_mode == m_test ); + tmp = decompress( infd, &pp, ignore_trailing, + loose_trailing, program_mode == m_test ); if( tmp > retval ) retval = tmp; - if( tmp && program_mode != m_test ) cleanup_and_fail( retval ); + if( tmp ) + { if( program_mode != m_test ) cleanup_and_fail( retval ); + else ++failed_tests; } if( delete_output_on_interrupt ) close_and_set_permissions( in_statsp ); if( input_filename[0] ) { - close( infd ); infd = -1; + close( infd ); if( !keep_input_files && !to_stdout && program_mode != m_test ) remove( input_filename ); } } if( outfd >= 0 && close( outfd ) != 0 ) { - show_error( "Can't close stdout", errno, false ); + show_error( "Error closing stdout", errno, false ); 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 ); free( filenames ); ap_free( &parser ); diff --git a/testsuite/check.sh b/testsuite/check.sh index 82e609a..406c6e0 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-2017 Antonio Diaz Diaz. +# Copyright (C) 2010-2018 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -51,6 +51,8 @@ done [ $? = 2 ] || test_failed $LINENO "${LZIP}" -cdq < in [ $? = 2 ] || test_failed $LINENO +"${LZIP}" -dq -o in < "${in_lz}" +[ $? = 1 ] || test_failed $LINENO # these are for code coverage "${LZIP}" -t -- nx_file 2> /dev/null [ $? = 1 ] || test_failed $LINENO @@ -133,7 +135,7 @@ cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure "${LZIP}" -cd in2.lz > copy2 || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO -"${LZIP}" -s16 --output=copy2 < in2 || test_failed $LINENO +"${LZIP}" -s16 --output=copy2.lz < in2 || test_failed $LINENO "${LZIP}" -t copy2.lz || test_failed $LINENO "${LZIP}" -cd copy2.lz > copy2 || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO @@ -190,12 +192,37 @@ done printf "\ntesting bad input..." +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}" > in0.lz +printf "LZIP${body}" >> in0.lz +if "${LZIP}" -tq in0.lz ; then + for header in ${headers} ; do + printf "${header}${body}" > in0.lz # first member + "${LZIP}" -tq in0.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -tq --loose-trailing in0.lz + [ $? = 2 ] || test_failed $LINENO ${header} + cat "${in_lz}" > in0.lz + printf "${header}${body}" >> in0.lz # trailing data + "${LZIP}" -tq in0.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -t --loose-trailing in0.lz + [ $? = 0 ] || test_failed $LINENO ${header} + "${LZIP}" -tq --loose-trailing --trailing-error in0.lz + [ $? = 2 ] || test_failed $LINENO ${header} + done +else + printf "\nwarning: skipping header test: 'printf' does not work on your system." +fi +rm -f in0.lz + 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 dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null - "${LZIP}" -t trunc.lz 2> /dev/null + "${LZIP}" -tq trunc.lz [ $? = 2 ] || test_failed $LINENO $i "${LZIP}" -tq < trunc.lz [ $? = 2 ] || test_failed $LINENO $i @@ -207,6 +234,7 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && else printf "\nwarning: skipping truncation test: 'dd' does not work on your system." fi +rm -f in3.lz trunc.lz cat "${in_lz}" > ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure @@ -217,6 +245,7 @@ cmp in copy || test_failed $LINENO "${LZIP}" -t < ingin.lz || test_failed $LINENO "${LZIP}" -d < ingin.lz > copy || test_failed $LINENO cmp in copy || test_failed $LINENO +rm -f ingin.lz echo if [ ${fail} = 0 ] ; then From 187580aeb96f4f9e5fce786c17b59f9d99108490 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:24:32 +0100 Subject: [PATCH 04/10] Adding upstream version 1.10. Signed-off-by: Daniel Baumann --- ChangeLog | 12 +++- INSTALL | 14 ++++- LzmaEnc.c | 12 ++-- NEWS | 30 +++------ README | 38 +++++------ carg_parser.c | 2 +- carg_parser.h | 2 +- configure | 16 ++--- doc/pdlzip.1 | 24 +++++-- lzip.h | 53 ++++++++-------- main.c | 153 ++++++++++++++++++++++++++------------------- testsuite/check.sh | 113 ++++++++++++++++++++++----------- 12 files changed, 276 insertions(+), 193 deletions(-) diff --git a/ChangeLog b/ChangeLog index d90a18f..2491c1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2019-01-01 Antonio Diaz Diaz + + * Version 1.10 released. + * File_* renamed to Lzip_*. + * main.c: Document option -0 and make it use a 64 KiB dict size. + * main.c (main): Check return value of close( infd ). + * main.c: Compile on DOS with DJGPP. + * configure: Accept appending to CFLAGS, 'CFLAGS+=OPTIONS'. + * INSTALL: Document use of CFLAGS+='-D __USE_MINGW_ANSI_STDIO'. + 2018-02-04 Antonio Diaz Diaz * Version 1.9 released. @@ -84,7 +94,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2018 Antonio Diaz Diaz. +Copyright (C) 2010-2019 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 diff --git a/INSTALL b/INSTALL index 327c502..5ad7128 100644 --- a/INSTALL +++ b/INSTALL @@ -1,10 +1,14 @@ Requirements ------------ You will need a C compiler. -I use gcc 5.3.0 and 4.1.2, but the code should compile with any -standards compliant 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. +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. + Procedure --------- @@ -23,6 +27,10 @@ the main archive. cd pdlzip[version] ./configure + If you are compiling on MinGW, use: + + ./configure CFLAGS+='-D __USE_MINGW_ANSI_STDIO' + 3. Run make. make @@ -61,7 +69,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2018 Antonio Diaz Diaz. +Copyright (C) 2010-2019 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/LzmaEnc.c b/LzmaEnc.c index 1dd8ea1..f59c001 100644 --- a/LzmaEnc.c +++ b/LzmaEnc.c @@ -1352,7 +1352,7 @@ static uint32_t GetOptimumFast(CLzmaEnc *p, uint32_t *backRes) static void LZe_full_flush(CLzmaEnc *p, uint32_t posState) { const uint32_t len = LZMA_MATCH_LEN_MIN; - File_trailer trailer; + Lzip_trailer trailer; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; @@ -1362,15 +1362,15 @@ static void LZe_full_flush(CLzmaEnc *p, uint32_t posState) RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); - Ft_set_data_crc( trailer, p->matchFinderBase.crc ^ 0xFFFFFFFFU ); - Ft_set_data_size( trailer, p->nowPos64 ); - Ft_set_member_size( trailer, p->rc.processed + Fh_size + Ft_size ); - if( writeblock( p->rc.outfd, trailer, Ft_size ) != Ft_size ) + Lt_set_data_crc( trailer, p->matchFinderBase.crc ^ 0xFFFFFFFFU ); + Lt_set_data_size( trailer, p->nowPos64 ); + Lt_set_member_size( trailer, p->rc.processed + Lh_size + Lt_size ); + if( writeblock( p->rc.outfd, trailer, Lt_size ) != Lt_size ) p->rc.res = SZ_ERROR_WRITE; if( verbosity >= 1 ) { unsigned long long in_size = p->nowPos64; - unsigned long long out_size = p->rc.processed + Fh_size + Ft_size; + unsigned long long out_size = p->rc.processed + Lh_size + Lt_size; if( in_size == 0 || out_size == 0 ) fputs( " no data compressed.\n", stderr ); else diff --git a/NEWS b/NEWS index d99cfae..bd181ae 100644 --- a/NEWS +++ b/NEWS @@ -1,26 +1,14 @@ -Changes in version 1.9: +Changes in version 1.10: -The option '--loose-trailing', has been added. +Compression level '-0' now uses a dictionary size of 64 KiB instead of +1 MiB. -The test used by pdlzip to discriminate trailing data from a corrupt -header in multimember or concatenated files has been improved to a -Hamming distance (HD) of 3, and the 3 bit flips must happen in different -magic bytes for the test to fail. As a consequence some kinds of files -no longer can be appended to a lzip file as trailing data unless the -'--loose-trailing' option is used when decompressing. -Lziprecover can be used to remove conflicting trailing data from a file. +Errors are now also checked when closing the input file. -The 'bits/byte' ratio has been replaced with the inverse compression -ratio in the output. +Pdlzip now compiles on DOS with DJGPP. (Patch from Robert Riebisch). -A final diagnostic is now shown at verbosity level 1 (-v) or higher if -any file fails the test when testing multiple files. +The configure script now accepts appending options to CFLAGS using the +syntax 'CFLAGS+=OPTIONS'. -A second '.lz' extension is no longer added to the argument of '-o' if -it already ends in '.lz' or '.tlz'. - -In case of (de)compressed size mismatch, the stored size is now also -shown in hexadecimal to ease visual comparison. - -The dictionary size is now shown at verbosity level 4 (-vvvv) when -decompressing or testing. +It has been documented in INSTALL the use of +CFLAGS+='-D __USE_MINGW_ANSI_STDIO' when compiling on MinGW. diff --git a/README b/README index 517adcf..6c29e49 100644 --- a/README +++ b/README @@ -1,17 +1,21 @@ Description -Pdlzip is a lossless data compressor with a user interface similar to -the one of lzip, bzip2 or gzip. +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 uses the lzip file format; the files produced by pdlzip are -(hope)fully compatible with lzip-1.4 or newer. Pdlzip is in fact 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"). +Lzip is a lossless data compressor with a user interface similar to the +one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0) +or compress most files more than bzip2 (lzip -9). Decompression speed is +intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 +from a data recovery perspective. Lzip has been designed, written and +tested with great care to replace gzip and bzip2 as the standard +general-purpose compressed format for unix-like systems. -The lzip file format is designed for data sharing and long-term -archiving, taking into account both data integrity and decoder -availability: +The lzip file format is designed for data sharing and long-term archiving, +taking into account both data integrity and decoder availability: * The lzip format provides very safe integrity checking and some data recovery means. The lziprecover program can repair bit flip errors @@ -20,11 +24,11 @@ availability: merging of damaged copies of a file. * The lzip format is as simple as possible (but not simpler). The - lzip manual provides the source code of a simple decompressor along - with a detailed explanation of how it works, so that with the only - help of the lzip manual it would be possible for a digital - archaeologist to extract the data from a lzip file long after - quantum computers eventually render LZMA obsolete. + lzip manual provides the source code of a simple decompressor + along with a detailed explanation of how it works, so that with + the only help of the lzip manual it would be possible for a + digital archaeologist to extract the data from a lzip file long + after quantum computers eventually render LZMA obsolete. * Additionally the lzip reference implementation is copylefted, which guarantees that it will remain free forever. @@ -40,8 +44,6 @@ If you keep any lzma-alone files, it is advisable to recompress them to lzip format. Lziprecover can convert some lzma-alone files to lzip format without recompressing. -Pdlzip is written in C. - Pdlzip includes public domain (de)compression code from the LZMA SDK (Software Development Kit) written by Igor Pavlov. @@ -52,7 +54,7 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2018 Antonio Diaz Diaz. +Copyright (C) 2010-2019 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/carg_parser.c b/carg_parser.c index 10ad4dc..ce01d7b 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-2018 Antonio Diaz Diaz. + Copyright (C) 2006-2019 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/carg_parser.h b/carg_parser.h index e1c70dd..dcae2de 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-2018 Antonio Diaz Diaz. + Copyright (C) 2006-2019 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/configure b/configure index 75f55bd..53ee546 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2018 Antonio Diaz Diaz. +# Copyright (C) 2010-2019 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. pkgname=pdlzip -pkgversion=1.9 +pkgversion=1.10 progname=pdlzip srctrigger=doc/${progname}.1 @@ -70,6 +70,7 @@ while [ $# != 0 ] ; do 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 exit 0 ;; @@ -93,10 +94,11 @@ while [ $# != 0 ] ; do --mandir=*) mandir=${optarg} ;; --no-create) no_create=yes ;; - CC=*) CC=${optarg} ;; - CPPFLAGS=*) CPPFLAGS=${optarg} ;; - CFLAGS=*) CFLAGS=${optarg} ;; - LDFLAGS=*) LDFLAGS=${optarg} ;; + CC=*) CC=${optarg} ;; + CPPFLAGS=*) CPPFLAGS=${optarg} ;; + CFLAGS=*) CFLAGS=${optarg} ;; + CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;; + LDFLAGS=*) LDFLAGS=${optarg} ;; --*) echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;; @@ -168,7 +170,7 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2018 Antonio Diaz Diaz. +# Copyright (C) 2010-2019 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/doc/pdlzip.1 b/doc/pdlzip.1 index e971323..e160d37 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,14 +1,26 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH PDLZIP "1" "February 2018" "pdlzip 1.9" "User Commands" +.TH PDLZIP "1" "January 2019" "pdlzip 1.10" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS .B pdlzip [\fI\,options\/\fR] [\fI\,files\/\fR] .SH DESCRIPTION -Pdlzip \- A permissively licensed implementation of the lzip data -compressor also able to decompress legacy lzma\-alone (.lzma) 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. .PP +Lzip is a lossless data compressor with a user interface similar to the +one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) +or compress most files more than bzip2 (lzip \fB\-9\fR). Decompression speed is +intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 +from a data recovery perspective. Lzip has been designed, written and +tested with great care to replace gzip and bzip2 as the standard +general\-purpose compressed format for unix\-like systems. +.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. If you keep any lzma\-alone files, it is advisable to recompress them to lzip format. Lziprecover can convert some lzma\-alone files to lzip format @@ -57,11 +69,11 @@ test compressed file integrity \fB\-v\fR, \fB\-\-verbose\fR be verbose (a 2nd \fB\-v\fR gives more) .TP -\fB\-1\fR .. \fB\-9\fR +\fB\-0\fR .. \fB\-9\fR set compression level [default 6] .TP \fB\-\-fast\fR -alias for \fB\-1\fR +alias for \fB\-0\fR .TP \fB\-\-best\fR alias for \fB\-9\fR @@ -91,7 +103,7 @@ Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2018 Antonio Diaz Diaz. +Copyright \(co 2019 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index 0f65f30..f0147fb 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2018 Antonio Diaz Diaz. + Copyright (C) 2010-2019 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -55,7 +55,7 @@ enum { /* defined in main.c */ extern int verbosity; -struct Pretty_print +struct Pretty_print /* requires global var 'int verbosity' */ { const char * name; char * padded_name; @@ -82,7 +82,7 @@ static inline void Pp_init( struct Pretty_print * const pp, { 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 < len ) pp->longest_name = len; } if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; } @@ -153,43 +153,43 @@ static inline int real_bits( unsigned value ) } -static const uint8_t magic_string[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ +static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ -typedef uint8_t File_header[6]; /* 0-3 magic bytes */ +typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */ /* 4 version */ /* 5 coded_dict_size */ -enum { Fh_size = 6 }; +enum { Lh_size = 6 }; -static inline void Fh_set_magic( File_header data ) - { memcpy( data, magic_string, 4 ); data[4] = 1; } +static inline void Lh_set_magic( Lzip_header data ) + { memcpy( data, lzip_magic, 4 ); data[4] = 1; } -static inline bool Fh_verify_magic( const File_header data ) - { return ( memcmp( data, magic_string, 4 ) == 0 ); } +static inline bool Lh_verify_magic( const Lzip_header data ) + { return ( memcmp( data, lzip_magic, 4 ) == 0 ); } /* detect (truncated) header */ -static inline bool Fh_verify_prefix( const File_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] != magic_string[i] ) return false; + if( data[i] != lzip_magic[i] ) return false; return ( sz > 0 ); } /* detect corrupt header */ -static inline bool Fh_verify_corrupt( const File_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] == magic_string[i] ) ++matches; + if( data[i] == lzip_magic[i] ) ++matches; return ( matches > 1 && matches < 4 ); } -static inline uint8_t Fh_version( const File_header data ) +static inline uint8_t Lh_version( const Lzip_header data ) { return data[4]; } -static inline bool Fh_verify_version( const File_header data ) +static inline bool Lh_verify_version( const Lzip_header data ) { return ( data[4] == 1 ); } -static inline unsigned Fh_get_dictionary_size( const File_header data ) +static inline unsigned Lh_get_dictionary_size( const Lzip_header data ) { unsigned sz = ( 1 << ( data[5] & 0x1F ) ); if( sz > min_dictionary_size ) @@ -197,7 +197,7 @@ static inline unsigned Fh_get_dictionary_size( const File_header data ) return sz; } -static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) +static inline bool Lh_set_dictionary_size( Lzip_header data, const unsigned sz ) { if( !isvalid_ds( sz ) ) return false; data[5] = real_bits( sz - 1 ); @@ -214,41 +214,40 @@ static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) } -typedef uint8_t File_trailer[20]; +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 }; -enum { Ft_size = 20 }; - -static inline unsigned Ft_get_data_crc( const File_trailer data ) +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 void Ft_set_data_crc( File_trailer data, unsigned crc ) +static inline void Lt_set_data_crc( Lzip_trailer data, unsigned crc ) { int i; for( i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } -static inline unsigned long long Ft_get_data_size( const File_trailer data ) +static inline unsigned long long Lt_get_data_size( const Lzip_trailer data ) { unsigned long long tmp = 0; int i; for( i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_data_size( File_trailer data, unsigned long long sz ) +static inline void Lt_set_data_size( Lzip_trailer data, unsigned long long sz ) { int i; for( i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } -static inline unsigned long long Ft_get_member_size( const File_trailer data ) +static inline unsigned long long Lt_get_member_size( const Lzip_trailer data ) { unsigned long long tmp = 0; int i; for( i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_member_size( File_trailer data, unsigned long long sz ) +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; } } diff --git a/main.c b/main.c index 4803491..a9195d4 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-2018 Antonio Diaz Diaz. + Copyright (C) 2010-2019 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -38,19 +38,24 @@ #include #include #include -#if defined(__MSVCRT__) +#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) #include +#if defined(__MSVCRT__) #define fchmod(x,y) 0 #define fchown(x,y,z) 0 #define SIGHUP SIGTERM #define S_ISSOCK(x) 0 +#ifndef S_IRGRP #define S_IRGRP 0 #define S_IWGRP 0 #define S_IROTH 0 #define S_IWOTH 0 #endif -#if defined(__OS2__) -#include +#endif +#if defined(__DJGPP__) +#define S_ISSOCK(x) 0 +#define S_ISVTX 0 +#endif #endif #include "carg_parser.h" @@ -68,9 +73,8 @@ int verbosity = 0; -const char * const Program_name = "Pdlzip"; const char * const program_name = "pdlzip"; -const char * const program_year = "2018"; +const char * const program_year = "2019"; const char * invocation_name = 0; const struct { const char * from; const char * to; } known_extensions[] = { @@ -87,6 +91,8 @@ struct Lzma_options enum Mode { m_compress, m_decompress, m_test }; +/* Variables used in signal handler context. + They are not declared volatile because the handler never returns. */ char * output_filename = 0; int outfd = -1; bool delete_output_on_interrupt = false; @@ -94,9 +100,20 @@ bool delete_output_on_interrupt = false; static void show_help( void ) { - printf( "%s - A permissively licensed implementation of the lzip data\n", Program_name ); - printf( "compressor also able to decompress legacy lzma-alone (.lzma) files.\n" - "\nLzma-alone is a very bad format; it is essentially a raw LZMA stream.\n" + 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\n" + "lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4\n" + "or newer.\n" + "\nLzip is a lossless data compressor with a user interface similar to the\n" + "one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0)\n" + "or compress most files more than bzip2 (lzip -9). Decompression speed is\n" + "intermediate between gzip and bzip2. Lzip is better than gzip and bzip2\n" + "from a data recovery perspective. Lzip has been designed, written and\n" + "tested with great care to replace gzip and bzip2 as the standard\n" + "general-purpose compressed format for unix-like systems.\n" + "\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" "lzip format. Lziprecover can convert some lzma-alone files to lzip format\n" "without recompressing.\n" @@ -116,8 +133,8 @@ static void show_help( void ) " -s, --dictionary-size= set dictionary size limit in bytes [8 MiB]\n" " -t, --test test compressed file integrity\n" " -v, --verbose be verbose (a 2nd -v gives more)\n" - " -1 .. -9 set compression level [default 6]\n" - " --fast alias for -1\n" + " -0 .. -9 set compression level [default 6]\n" + " --fast alias for -0\n" " --best alias for -9\n" " --loose-trailing allow trailing data seeming corrupt header\n" "If no file names are given, or if a file is '-', pdlzip compresses or\n" @@ -255,7 +272,7 @@ static int get_dict_size( const char * const arg ) const long bits = strtol( arg, &tail, 0 ); if( bits >= min_dictionary_bits && bits <= max_dictionary_bits_c && *tail == 0 ) - return ( 1 << bits ); + return 1 << bits; return getnum( arg, min_dictionary_size, max_dictionary_size_c ); } @@ -393,8 +410,17 @@ static bool check_tty( const char * const input_filename, const int infd, } +static void set_signals( void (*action)(int) ) + { + signal( SIGHUP, action ); + signal( SIGINT, action ); + signal( SIGTERM, action ); + } + + void cleanup_and_fail( const int retval ) { + set_signals( SIG_IGN ); /* ignore signals */ if( delete_output_on_interrupt ) { delete_output_on_interrupt = false; @@ -409,6 +435,14 @@ void cleanup_and_fail( const int retval ) } +void signal_handler( int sig ) + { + if( sig ) {} /* keep compiler happy */ + show_error( "Control-C or similar caught, quitting.", 0, false ); + cleanup_and_fail( 1 ); + } + + /* Set permissions, owner and times. */ static void close_and_set_permissions( const struct stat * const in_statsp ) { @@ -448,14 +482,14 @@ static int compress( const struct Lzma_options * const encoder_options, { int retval = 0; CLzmaEncHandle encoder = 0; - File_header header; - Fh_set_magic( header ); + Lzip_header header; + Lh_set_magic( header ); if( verbosity >= 1 ) Pp_show_msg( pp, 0 ); - if( Fh_set_dictionary_size( header, encoder_options->dictionary_size ) && + if( Lh_set_dictionary_size( header, encoder_options->dictionary_size ) && encoder_options->match_len_limit >= min_match_len_limit && encoder_options->match_len_limit <= max_match_len ) - encoder = LzmaEnc_Init( Fh_get_dictionary_size( header ), + encoder = LzmaEnc_Init( Lh_get_dictionary_size( header ), encoder_options->match_len_limit, infd, outfd ); else internal_error( "invalid argument to encoder." ); @@ -465,7 +499,7 @@ static int compress( const struct Lzma_options * const encoder_options, return 1; } - if( writeblock( outfd, header, Fh_size ) != Fh_size ) + if( writeblock( outfd, header, Lh_size ) != Lh_size ) { show_error( "Can't write output file", errno, false ); retval = 1; } else if( LzmaEnc_Encode( encoder ) != 0 ) @@ -578,7 +612,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, int * const inPos, int * const inSize, const unsigned dictionary_size ) { - unsigned long long member_size = Fh_size, data_size = 0; + unsigned long long member_size = Lh_size, data_size = 0; uint8_t outBuf[OUT_BUF_SIZE]; int outPos = 0; uint32_t crc = 0xFFFFFFFFU; @@ -612,7 +646,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, if (inProcessed == 0 && outProcessed == 0) { - File_trailer trailer; + Lzip_trailer trailer; int i; unsigned td_crc; unsigned long long td_size, tm_size; @@ -620,9 +654,9 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, if( status != LZMA_STATUS_FINISHED_WITH_MARK ) { Pp_show_msg( pp, "Data error." ); return 2; } - if( *inSize - *inPos < Ft_size && + if( *inSize - *inPos < Lt_size && !read_inbuf( infd, inBuf, inPos, inSize ) ) return 1; - if( *inSize - *inPos < Ft_size ) + if( *inSize - *inPos < Lt_size ) { error = true; if( verbosity >= 0 ) @@ -632,12 +666,12 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, " some checks may fail.\n", *inSize - *inPos ); } } - for( i = 0; i < Ft_size && *inPos < *inSize; ++i ) + for( i = 0; i < Lt_size && *inPos < *inSize; ++i ) trailer[i] = inBuf[(*inPos)++]; member_size += i; - while( i < Ft_size ) trailer[i++] = 0; + while( i < Lt_size ) trailer[i++] = 0; crc ^= 0xFFFFFFFFU; - td_crc = Ft_get_data_crc( trailer ); + td_crc = Lt_get_data_crc( trailer ); if( td_crc != crc ) { error = true; @@ -648,7 +682,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, td_crc, crc ); } } - td_size = Ft_get_data_size( trailer ); + td_size = Lt_get_data_size( trailer ); if( td_size != data_size ) { error = true; @@ -659,7 +693,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, td_size, td_size, data_size, data_size ); } } - tm_size = Ft_get_member_size( trailer ); + tm_size = Lt_get_member_size( trailer ); if( tm_size != member_size ) { error = true; @@ -709,38 +743,38 @@ static int decompress( const int infd, struct Pretty_print * const pp, { int i, size; unsigned dictionary_size; - File_header header; + Lzip_header header; if( inSize - inPos < lzma_header_size && !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; size = inSize - inPos; - for( i = 0; i < size && i < Fh_size; ++i ) + for( i = 0; i < size && i < Lh_size; ++i ) raw_props[i] = header[i] = inBuf[inPos++]; - if( size <= Fh_size ) /* End Of File */ + if( size <= Lh_size ) /* End Of File */ { if( first_member ) { show_file_error( pp->name, "File ends unexpectedly at member header.", 0 ); retval = 2; } - else if( Fh_verify_prefix( header, size ) ) + else if( Lh_verify_prefix( header, size ) ) { Pp_show_msg( pp, "Truncated header in multimember file." ); retval = 2; } else if( size > 0 && !ignore_trailing ) { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } - if( !Fh_verify_magic( header ) ) + if( !Lh_verify_magic( header ) ) { if( !first_member ) { - if( !loose_trailing && Fh_verify_corrupt( header ) ) + if( !loose_trailing && Lh_verify_corrupt( header ) ) { Pp_show_msg( pp, "Corrupt header in multimember file." ); retval = 2; } else if( !ignore_trailing ) { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } - if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */ + if( inSize - inPos >= lzma_header_size - Lh_size ) /* try lzma-alone */ { - for( i = Fh_size; i < lzma_header_size; ++i ) + for( i = Lh_size; i < lzma_header_size; ++i ) raw_props[i] = inBuf[inPos++]; if( ( raw_props[12] == 0 || raw_props[12] == 0xFF ) && raw_props[12] == raw_props[11] && raw_props[0] < (9 * 5 * 5) ) @@ -763,15 +797,15 @@ static int decompress( const int infd, struct Pretty_print * const pp, if( lzip_mode ) { int ds, i; - if( !Fh_verify_version( header ) ) + if( !Lh_verify_version( header ) ) { if( verbosity >= 0 ) { Pp_show_msg( pp, 0 ); fprintf( stderr, "Version %d member format not supported.\n", - Fh_version( header ) ); } + Lh_version( header ) ); } retval = 2; break; } - dictionary_size = Fh_get_dictionary_size( header ); + dictionary_size = Lh_get_dictionary_size( header ); if( !isvalid_ds( dictionary_size ) ) { Pp_show_msg( pp, "Invalid dictionary size in member header." ); retval = 2; break; } @@ -803,22 +837,6 @@ static int decompress( const int infd, struct Pretty_print * const pp, } -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 ); - } - - CRC32 crc32; @@ -863,11 +881,9 @@ void show_error( const char * const msg, const int errcode, const bool help ) { if( verbosity < 0 ) return; if( msg && msg[0] ) - { - fprintf( stderr, "%s: %s", program_name, msg ); - if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); - fputc( '\n', stderr ); - } + fprintf( stderr, "%s: %s%s%s\n", program_name, msg, + ( errcode > 0 ) ? ": " : "", + ( errcode > 0 ) ? strerror( errcode ) : "" ); if( help ) fprintf( stderr, "Try '%s --help' for more information.\n", invocation_name ); @@ -877,10 +893,10 @@ 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 ) { - if( verbosity < 0 ) return; - fprintf( stderr, "%s: %s: %s", program_name, filename, msg ); - if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); - fputc( '\n', stderr ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg, + ( errcode > 0 ) ? ": " : "", + ( errcode > 0 ) ? strerror( errcode ) : "" ); } @@ -898,7 +914,7 @@ int main( const int argc, const char * const argv[] ) to the corresponding LZMA compression modes. */ const struct Lzma_options option_mapping[] = { - { 1 << 20, 5 }, /* -0 */ + { 1 << 16, 5 }, /* -0 */ { 1 << 20, 5 }, /* -1 */ { 3 << 19, 6 }, /* -2 */ { 1 << 21, 8 }, /* -3 */ @@ -1004,7 +1020,7 @@ int main( const int argc, const char * const argv[] ) } } /* end process options */ -#if defined(__MSVCRT__) || defined(__OS2__) +#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) setmode( STDIN_FILENO, O_BINARY ); setmode( STDOUT_FILENO, O_BINARY ); #endif @@ -1024,7 +1040,7 @@ int main( const int argc, const char * const argv[] ) if( !to_stdout && program_mode != m_test && ( filenames_given || default_output_filename[0] ) ) - set_signals(); + set_signals( signal_handler ); Pp_init( &pp, filenames, num_filenames ); @@ -1103,6 +1119,12 @@ int main( const int argc, const char * const argv[] ) else tmp = decompress( infd, &pp, ignore_trailing, loose_trailing, program_mode == m_test ); + if( close( infd ) != 0 ) + { + show_error( input_filename[0] ? "Error closing input file" : + "Error closing stdin", errno, false ); + if( tmp < 1 ) tmp = 1; + } if( tmp > retval ) retval = tmp; if( tmp ) { if( program_mode != m_test ) cleanup_and_fail( retval ); @@ -1112,7 +1134,6 @@ int main( const int argc, const char * const argv[] ) close_and_set_permissions( in_statsp ); if( input_filename[0] ) { - close( infd ); if( !keep_input_files && !to_stdout && program_mode != m_test ) remove( input_filename ); } diff --git a/testsuite/check.sh b/testsuite/check.sh index 406c6e0..c3d859c 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-2018 Antonio Diaz Diaz. +# Copyright (C) 2010-2019 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -36,12 +36,15 @@ test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } printf "testing pdlzip-%s..." "$2" "${LZIP}" -fkqm4 in -{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO +[ $? = 1 ] || test_failed $LINENO +[ ! -e in.lz ] || test_failed $LINENO "${LZIP}" -fkqm274 in -{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO +[ $? = 1 ] || test_failed $LINENO +[ ! -e in.lz ] || test_failed $LINENO for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do "${LZIP}" -fkqs $i in - { [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO $i + [ $? = 1 ] || test_failed $LINENO $i + [ ! -e in.lz ] || test_failed $LINENO $i done "${LZIP}" -tq in [ $? = 2 ] || test_failed $LINENO @@ -86,36 +89,46 @@ cmp in copy || test_failed $LINENO "${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || test_failed $LINENO cmp in copy || test_failed $LINENO -rm -f copy +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 -"${LZIP}" -df copy.lz -{ [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; } || 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 || framework_failure +cat "${in_lz}" > copy.lz || framework_failure +"${LZIP}" -d -S100k copy.lz || test_failed $LINENO # ignore -S +[ ! -e copy.lz ] || test_failed $LINENO +cmp in copy || test_failed $LINENO printf "to be overwritten" > copy || framework_failure "${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO cmp in copy || test_failed $LINENO -rm -f copy +rm -f copy || framework_failure "${LZIP}" -s16 < in > anyothername || test_failed $LINENO -"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null -{ [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; } || +"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null || test_failed $LINENO -rm -f copy anyothername.out +cmp in copy || test_failed $LINENO +cmp in anyothername.out || test_failed $LINENO +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}" > copy -{ [ $? = 2 ] && cat copy in | cmp in - ; } || test_failed $LINENO +[ $? = 2 ] || test_failed $LINENO +cat copy in | cmp in - || test_failed $LINENO "${LZIP}" -cdq nx_file.lz "${in_lz}" > copy -{ [ $? = 1 ] && cmp in copy ; } || test_failed $LINENO -rm -f copy +[ $? = 1 ] || test_failed $LINENO +cmp in copy || test_failed $LINENO +rm -f copy || framework_failure cat "${in_lz}" > copy.lz || framework_failure for i in 1 2 3 4 5 6 7 ; do printf "g" >> copy.lz || framework_failure @@ -123,11 +136,15 @@ for i in 1 2 3 4 5 6 7 ; do [ $? = 2 ] || test_failed $LINENO $i done "${LZIP}" -dq in copy.lz -{ [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; } || - test_failed $LINENO +[ $? = 2 ] || 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 copy.lz -{ [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e nx_file ] && cmp in copy ; } || - test_failed $LINENO +[ $? = 1 ] || test_failed $LINENO +[ ! -e copy.lz ] || test_failed $LINENO +[ ! -e nx_file ] || test_failed $LINENO +cmp in copy || test_failed $LINENO cat in in > in2 || framework_failure cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure @@ -142,18 +159,21 @@ cmp in2 copy2 || test_failed $LINENO printf "\ngarbage" >> copy2.lz || framework_failure "${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO -rm -f copy2 +rm -f copy2 || framework_failure "${LZIP}" -atq copy2.lz [ $? = 2 ] || test_failed $LINENO "${LZIP}" -atq < copy2.lz [ $? = 2 ] || test_failed $LINENO "${LZIP}" -adkq copy2.lz -{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO +[ $? = 2 ] || test_failed $LINENO +[ ! -e copy2 ] || test_failed $LINENO "${LZIP}" -adkq -o copy2 < copy2.lz -{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO +[ $? = 2 ] || test_failed $LINENO +[ ! -e copy2 ] || test_failed $LINENO printf "to be overwritten" > copy2 || framework_failure "${LZIP}" -df copy2.lz || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO +rm -f in2 copy2 || framework_failure printf "\ntesting compression..." @@ -189,33 +209,54 @@ for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do "${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i done +rm -f out.lz || framework_failure printf "\ntesting bad input..." 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}" > in0.lz -printf "LZIP${body}" >> in0.lz -if "${LZIP}" -tq in0.lz ; then +cat "${in_lz}" > int.lz +printf "LZIP${body}" >> int.lz +if "${LZIP}" -tq int.lz ; then for header in ${headers} ; do - printf "${header}${body}" > in0.lz # first member - "${LZIP}" -tq in0.lz + printf "${header}${body}" > int.lz # first member + "${LZIP}" -tq int.lz [ $? = 2 ] || test_failed $LINENO ${header} - "${LZIP}" -tq --loose-trailing in0.lz + "${LZIP}" -tq < int.lz [ $? = 2 ] || test_failed $LINENO ${header} - cat "${in_lz}" > in0.lz - printf "${header}${body}" >> in0.lz # trailing data - "${LZIP}" -tq in0.lz + "${LZIP}" -cdq int.lz > /dev/null [ $? = 2 ] || test_failed $LINENO ${header} - "${LZIP}" -t --loose-trailing in0.lz - [ $? = 0 ] || test_failed $LINENO ${header} - "${LZIP}" -tq --loose-trailing --trailing-error in0.lz + "${LZIP}" -tq --loose-trailing int.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -tq --loose-trailing < int.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -cdq --loose-trailing int.lz > /dev/null + [ $? = 2 ] || test_failed $LINENO ${header} + cat "${in_lz}" > int.lz + printf "${header}${body}" >> int.lz # trailing data + "${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} + "${LZIP}" -t --loose-trailing int.lz || + test_failed $LINENO ${header} + "${LZIP}" -t --loose-trailing < int.lz || + test_failed $LINENO ${header} + "${LZIP}" -cd --loose-trailing int.lz > /dev/null || + test_failed $LINENO ${header} + "${LZIP}" -tq --loose-trailing --trailing-error int.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -tq --loose-trailing --trailing-error < int.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -cdq --loose-trailing --trailing-error int.lz > /dev/null [ $? = 2 ] || test_failed $LINENO ${header} done else printf "\nwarning: skipping header test: 'printf' does not work on your system." fi -rm -f in0.lz +rm -f int.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 && @@ -234,7 +275,7 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && else printf "\nwarning: skipping truncation test: 'dd' does not work on your system." fi -rm -f in3.lz trunc.lz +rm -f in2.lz in3.lz trunc.lz out || framework_failure cat "${in_lz}" > ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure @@ -245,7 +286,7 @@ cmp in copy || test_failed $LINENO "${LZIP}" -t < ingin.lz || test_failed $LINENO "${LZIP}" -d < ingin.lz > copy || test_failed $LINENO cmp in copy || test_failed $LINENO -rm -f ingin.lz +rm -f copy ingin.lz || framework_failure echo if [ ${fail} = 0 ] ; then From 90a9130b80f15e11b0becc3e9e264cce24805efa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:26:07 +0100 Subject: [PATCH 05/10] Adding upstream version 1.11. Signed-off-by: Daniel Baumann --- AUTHORS | 4 +- COPYING | 30 +-- ChangeLog | 50 +++-- INSTALL | 22 +- Makefile.in | 9 +- NEWS | 34 ++- README | 52 ++--- carg_parser.c | 26 +-- carg_parser.h | 66 +++--- configure | 25 +-- doc/pdlzip.1 | 36 ++-- lzip.h | 106 ++------- main.c | 448 ++++++++++++++++++++++----------------- testsuite/check.sh | 132 ++++++++---- testsuite/fox.lz | Bin 0 -> 80 bytes testsuite/fox_bcrc.lz | Bin 0 -> 80 bytes testsuite/fox_crc0.lz | Bin 0 -> 80 bytes testsuite/fox_das46.lz | Bin 0 -> 80 bytes testsuite/fox_de20.lz | Bin 0 -> 80 bytes testsuite/fox_mes81.lz | Bin 0 -> 80 bytes testsuite/fox_s11.lz | Bin 0 -> 80 bytes testsuite/fox_v2.lz | Bin 0 -> 80 bytes testsuite/test_em.txt.lz | Bin 0 -> 14024 bytes 23 files changed, 560 insertions(+), 480 deletions(-) create mode 100644 testsuite/fox.lz create mode 100644 testsuite/fox_bcrc.lz create mode 100644 testsuite/fox_crc0.lz create mode 100644 testsuite/fox_das46.lz create mode 100644 testsuite/fox_de20.lz create mode 100644 testsuite/fox_mes81.lz create mode 100644 testsuite/fox_s11.lz create mode 100644 testsuite/fox_v2.lz create mode 100644 testsuite/test_em.txt.lz diff --git a/AUTHORS b/AUTHORS index 6b1c0dd..6db2128 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ Pdlzip was written by Antonio Diaz Diaz. -Pdlzip includes public domain (de)compression code from the LZMA SDK -(Software Development Kit) written by Igor Pavlov. +Pdlzip includes public domain compression/decompression code from the LZMA +SDK (Software Development Kit) written by Igor Pavlov. diff --git a/COPYING b/COPYING index b741254..57f0e34 100644 --- a/COPYING +++ b/COPYING @@ -1,19 +1,19 @@ - Pdlzip - LZMA lossless data compressor - Copyright (C) Antonio Diaz Diaz. - Pdlzip includes public domain (de)compression code from the LZMA SDK - (Software Development Kit) written by Igor Pavlov. + Pdlzip - LZMA lossless data compressor + Copyright (C) Antonio Diaz Diaz. + Pdlzip includes public domain (de)compression code from the LZMA SDK + (Software Development Kit) written by Igor Pavlov. - This program is free software. Redistribution and use in source and - binary forms, with or without modification, are permitted provided - that the following conditions are met: + This program is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/ChangeLog b/ChangeLog index 2491c1b..1b5efdd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,20 @@ +2021-01-01 Antonio Diaz Diaz + + * Version 1.11 released. + * main.c (main): Report an error if a file name is empty. + Make '-o' behave like '-c', but writing to file instead of stdout. + Make '-c' and '-o' check whether the output is a terminal only once. + Do not open output if input is a terminal. + * Don't allow mixing different operations (-d and -t). + * Replace 'decompressed', 'compressed' with 'out', 'in' in output. + * Document extraction from tar.lz in '--help' output and man page. + * main.c: Set a valid invocation_name even if argc == 0. + * testsuite: Add 9 new test files. + 2019-01-01 Antonio Diaz Diaz * Version 1.10 released. - * File_* renamed to Lzip_*. + * Rename File_* to Lzip_*. * main.c: Document option -0 and make it use a 64 KiB dict size. * main.c (main): Check return value of close( infd ). * main.c: Compile on DOS with DJGPP. @@ -11,9 +24,9 @@ 2018-02-04 Antonio Diaz Diaz * Version 1.9 released. - * main.c: Added new option '--loose-trailing'. - * main.c (decompress): Improved corrupt header detection to HD=3. - * Replaced 'bits/byte' with inverse compression ratio in output. + * main.c: New option '--loose-trailing'. + * main.c (decompress): Improve corrupt header detection to HD=3. + * Replace 'bits/byte' with inverse compression ratio in output. * main.c: Show final diagnostic when testing multiple files. * main.c: Do not add a second .lz extension to the arg of -o. * main.c (lzip_decode): Show stored sizes also in hex. @@ -23,12 +36,12 @@ * Version 1.8 released. * main.c: Continue testing if any input file is a terminal. - * main.c (decompress): Improved detection of trailing data. + * main.c (decompress): Improve detection of trailing data. 2016-05-16 Antonio Diaz Diaz * Version 1.7 released. - * main.c: Added new option '-a, --trailing-error'. + * main.c: New option '-a, --trailing-error'. * main.c (main): Delete '--output' file if infd is a terminal. * main.c (main): Don't use stdin more than once. * configure: Avoid warning on some shells when testing for gcc. @@ -39,7 +52,7 @@ * Version 1.6 released. * main.c (close_and_set_permissions): Behave like 'cp -p'. - * Makefile.in: Added new targets 'install*-compress'. + * Makefile.in: New targets 'install*-compress'. 2013-09-14 Antonio Diaz Diaz @@ -50,26 +63,23 @@ 2013-05-27 Antonio Diaz Diaz * Version 1.4 released. - * main.c: Added new option '-f, --force'. - * main.c: Added new option '-F, --recompress'. - * main.c: Added new option '-k, --keep'. - * main.c: Added new option '-o, --output'. + * main.c: New options '-f, --force', '-F, --recompress', + '-k, --keep', and '-o, --output'. * main.c: Accept more than one file in command line. * Decompression time has been reduced by 5%. * main.c: '--test' no longer needs '/dev/null'. - * Fixed return value of '-d' and '-t' in case of data error. - * main.c: Changed info shown at verbosity levels 2 and 3. + * Fix return value of '-d' and '-t' in case of data error. + * main.c: Change info shown at verbosity levels 2 and 3. * Ignore option '-n, --threads' for compatibility with plzip. * configure: Options now accept a separate argument. - * configure: 'datadir' renamed to 'datarootdir'. - * Makefile.in: Added new target 'install-as-lzip'. - * Makefile.in: Added new target 'install-bin'. + * configure: Rename 'datadir' to 'datarootdir'. + * Makefile.in: New targets 'install-as-lzip' and 'install-bin'. 2012-01-03 Antonio Diaz Diaz * Version 1.3 released. * Small change in '--help' output and man page. - * Changed quote characters in messages as advised by GNU Standards. + * Change quote characters in messages as advised by GNU Standards. * main.c: Set stdin/stdout in binary mode on OS2. 2011-01-05 Antonio Diaz Diaz @@ -80,7 +90,7 @@ 2010-08-19 Antonio Diaz Diaz * Version 1.1 released. - * main.c: Added support for decompression of lzma-alone files. + * main.c: Add support for decompression of lzma-alone files. * main.c: Match length limit set by options -1 to -8 has been reduced to extend range of use towards gzip. Lower numbers now compress less but faster. (-1 now takes 43% less time for only @@ -94,8 +104,8 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2019 Antonio Diaz Diaz. +Copyright (C) 2010-2021 Antonio Diaz Diaz. This file is a collection of facts, and thus it is not copyrightable, -but just in case, you have unlimited permission to copy, distribute and +but just in case, you have unlimited permission to copy, distribute, and modify it. diff --git a/INSTALL b/INSTALL index 5ad7128..d06e04d 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Requirements ------------ -You will need a C compiler. -I use gcc 5.3.0 and 4.1.2, but the code should compile with any standards +You will need a C99 compiler. (gcc 3.3.6 or newer is recommended). +I use gcc 6.1.0 and 4.1.2, but the code should compile with any standards compliant compiler. Gcc is available at http://gcc.gnu.org. @@ -41,11 +41,11 @@ the main archive. documentation. Or type 'make install-compress', which additionally compresses the - man page after installation. (Installing compressed docs may become - the default in the future). + man page after installation. + (Installing compressed docs may become the default in the future). - You can install only the program or the man page by typing 'make - install-bin' or 'make install-man' respectively. + You can install only the program or the man page by typing + 'make install-bin' or 'make install-man' respectively. Instead of 'make install', you can type 'make install-as-lzip' to install the program and any data files and documentation, and link @@ -55,10 +55,10 @@ the main archive. Another way ----------- You can also compile pdlzip into a separate directory. -To do this, you must use a version of 'make' that supports the 'VPATH' -variable, such as GNU 'make'. 'cd' to the directory where you want the +To do this, you must use a version of 'make' that supports the variable +'VPATH', such as GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run the 'configure' script. -'configure' automatically checks for the source code in '.', in '..' and +'configure' automatically checks for the source code in '.', in '..', and in the directory that 'configure' is in. 'configure' recognizes the option '--srcdir=DIR' to control where to @@ -69,7 +69,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2019 Antonio Diaz Diaz. +Copyright (C) 2010-2021 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, -distribute and modify it. +distribute, and modify it. diff --git a/Makefile.in b/Makefile.in index e720a0d..ec334f3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -71,7 +71,7 @@ install-info : -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* $(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info" -if $(CAN_RUN_INSTALLINFO) ; then \ - install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ + install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ fi install-info-compress : install-info @@ -96,7 +96,7 @@ uninstall-bin : uninstall-info : -if $(CAN_RUN_INSTALLINFO) ; then \ - install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ + install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ fi -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* @@ -119,8 +119,11 @@ dist : doc $(DISTNAME)/*.c \ $(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/test.txt \ + $(DISTNAME)/testsuite/fox.lz \ + $(DISTNAME)/testsuite/fox_*.lz \ $(DISTNAME)/testsuite/test.txt.lz \ - $(DISTNAME)/testsuite/test.txt.lzma + $(DISTNAME)/testsuite/test.txt.lzma \ + $(DISTNAME)/testsuite/test_em.txt.lz rm -f $(DISTNAME) lzip -v -9 $(DISTNAME).tar diff --git a/NEWS b/NEWS index bd181ae..76ecbb3 100644 --- a/NEWS +++ b/NEWS @@ -1,14 +1,30 @@ -Changes in version 1.10: +Changes in version 1.11: -Compression level '-0' now uses a dictionary size of 64 KiB instead of -1 MiB. +Pdlzip now reports an error if a file name is empty (pdlzip -t ""). -Errors are now also checked when closing the input file. +Option '-o, --output' now behaves like '-c, --stdout', but sending the +output unconditionally to a file instead of to standard output. See the new +description of '-o' in the manual. This change is backwards compatible only +when (de)compressing from standard input alone. Therefore commands like: + pdlzip -o foo.lz - bar < foo +must now be split into: + pdlzip -o foo.lz - < foo + pdlzip bar +or rewritten as: + pdlzip - bar < foo > foo.lz -Pdlzip now compiles on DOS with DJGPP. (Patch from Robert Riebisch). +When using '-c' or '-o', pdlzip now checks whether the output is a terminal +only once. -The configure script now accepts appending options to CFLAGS using the -syntax 'CFLAGS+=OPTIONS'. +Pdlzip now does not even open the output file if the input file is a terminal. -It has been documented in INSTALL the use of -CFLAGS+='-D __USE_MINGW_ANSI_STDIO' when compiling on MinGW. +It is now an error to specify two different operations in the command line +(--decompress and --test). + +The words 'decompressed' and 'compressed' have been replaced with the +shorter 'out' and 'in' in the verbose output when decompressing or testing. + +The commands needed to extract files from a tar.lz archive have been +documented in the output of '--help' and in the man page. + +9 new test files have been added to the testsuite. diff --git a/README b/README index 6c29e49..1a843ab 100644 --- a/README +++ b/README @@ -6,37 +6,39 @@ licensed Free Software. (The name of pdlzip comes from 'public domain lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. -Lzip is a lossless data compressor with a user interface similar to the -one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0) -or compress most files more than bzip2 (lzip -9). Decompression speed is -intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 -from a data recovery perspective. Lzip has been designed, written and -tested with great care to replace gzip and bzip2 as the standard -general-purpose compressed format for unix-like systems. +Lzip is a lossless data compressor with a user interface similar to the one +of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov +chain-Algorithm' (LZMA) stream format, chosen to maximize safety and +interoperability. Lzip can compress about as fast as gzip (lzip -0) or +compress most files more than bzip2 (lzip -9). Decompression speed is +intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from +a data recovery perspective. Lzip has been designed, written, and tested +with great care to replace gzip and bzip2 as the standard general-purpose +compressed format for unix-like systems. The lzip file format is designed for data sharing and long-term archiving, taking into account both data integrity and decoder availability: * The lzip format provides very safe integrity checking and some data - recovery means. The lziprecover program can repair bit flip errors - (one of the most common forms of data corruption) in lzip files, - and provides data recovery capabilities, including error-checked - merging of damaged copies of a file. + recovery means. The program lziprecover can repair bit flip errors + (one of the most common forms of data corruption) in lzip files, and + provides data recovery capabilities, including error-checked merging + of damaged copies of a file. - * The lzip format is as simple as possible (but not simpler). The - lzip manual provides the source code of a simple decompressor - along with a detailed explanation of how it works, so that with - the only help of the lzip manual it would be possible for a - digital archaeologist to extract the data from a lzip file long - after quantum computers eventually render LZMA obsolete. + * The lzip format is as simple as possible (but not simpler). The lzip + manual provides the source code of a simple decompressor along with a + detailed explanation of how it works, so that with the only help of the + lzip manual it would be possible for a digital archaeologist to extract + the data from a lzip file long after quantum computers eventually + render LZMA obsolete. * Additionally the lzip reference implementation is copylefted, which guarantees that it will remain free forever. -A nice feature of the lzip format is that a corrupt byte is easier to -repair the nearer it is from the beginning of the file. Therefore, with -the help of lziprecover, losing an entire archive just because of a -corrupt byte near the beginning is a thing of the past. +A nice feature of the lzip format is that a corrupt byte is easier to repair +the nearer it is from the beginning of the file. Therefore, with the help of +lziprecover, losing an entire archive just because of a corrupt byte near +the beginning is a thing of the past. Pdlzip is also able to decompress legacy lzma-alone (.lzma) files. Lzma-alone is a very bad format; it is essentially a raw LZMA stream. @@ -44,8 +46,8 @@ If you keep any lzma-alone files, it is advisable to recompress them to lzip format. Lziprecover can convert some lzma-alone files to lzip format without recompressing. -Pdlzip includes public domain (de)compression code from the LZMA SDK -(Software Development Kit) written by Igor Pavlov. +Pdlzip includes public domain compression/decompression code from the LZMA +SDK (Software Development Kit) written by Igor Pavlov. I would not write non-copylefted software unless it is too simple to be worth copylefting it, but one of the uses of the lzip format is the @@ -54,10 +56,10 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2019 Antonio Diaz Diaz. +Copyright (C) 2010-2021 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, -distribute and modify it. +distribute, and modify it. The file Makefile.in is a data file used by configure to produce the Makefile. It has the same copyright owner and permissions that configure diff --git a/carg_parser.c b/carg_parser.c index ce01d7b..d0c05d5 100644 --- a/carg_parser.c +++ b/carg_parser.c @@ -1,20 +1,20 @@ -/* Arg_parser - POSIX/GNU command line argument parser. (C version) - Copyright (C) 2006-2019 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command line argument parser. (C version) + Copyright (C) 2006-2021 Antonio Diaz Diaz. - This library is free software. Redistribution and use in source and - binary forms, with or without modification, are permitted provided - that the following conditions are met: + This library is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include diff --git a/carg_parser.h b/carg_parser.h index dcae2de..c5f2352 100644 --- a/carg_parser.h +++ b/carg_parser.h @@ -1,44 +1,44 @@ -/* Arg_parser - POSIX/GNU command line argument parser. (C version) - Copyright (C) 2006-2019 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command line argument parser. (C version) + Copyright (C) 2006-2021 Antonio Diaz Diaz. - This library is free software. Redistribution and use in source and - binary forms, with or without modification, are permitted provided - that the following conditions are met: + This library is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -/* Arg_parser reads the arguments in 'argv' and creates a number of - option codes, option arguments and non-option arguments. +/* Arg_parser reads the arguments in 'argv' and creates a number of + option codes, option arguments, and non-option arguments. - In case of error, 'ap_error' returns a non-null pointer to an error - message. + In case of error, 'ap_error' returns a non-null pointer to an error + message. - 'options' is an array of 'struct ap_Option' terminated by an element - containing a code which is zero. A null name means a short-only - option. A code value outside the unsigned char range means a - long-only option. + 'options' is an array of 'struct ap_Option' terminated by an element + containing a code which is zero. A null name means a short-only + option. A code value outside the unsigned char range means a + long-only option. - Arg_parser normally makes it appear as if all the option arguments - were specified before all the non-option arguments for the purposes - of parsing, even if the user of your program intermixed option and - non-option arguments. If you want the arguments in the exact order - the user typed them, call 'ap_init' with 'in_order' = true. + Arg_parser normally makes it appear as if all the option arguments + were specified before all the non-option arguments for the purposes + of parsing, even if the user of your program intermixed option and + non-option arguments. If you want the arguments in the exact order + the user typed them, call 'ap_init' with 'in_order' = true. - The argument '--' terminates all options; any following arguments are - treated as non-option arguments, even if they begin with a hyphen. + The argument '--' terminates all options; any following arguments are + treated as non-option arguments, even if they begin with a hyphen. - The syntax for optional option arguments is '-' - (without whitespace), or '--='. + The syntax for optional option arguments is '-' + (without whitespace), or '--='. */ #ifdef __cplusplus @@ -79,11 +79,11 @@ void ap_free( struct Arg_parser * const ap ); const char * ap_error( const struct Arg_parser * const ap ); - /* The number of arguments parsed (may be different from argc) */ +/* The number of arguments parsed. May be different from argc. */ int ap_arguments( const struct Arg_parser * const ap ); - /* If ap_code( i ) is 0, ap_argument( i ) is a non-option. - Else ap_argument( i ) is the option's argument (or empty). */ +/* If ap_code( i ) is 0, ap_argument( i ) is a non-option. + Else ap_argument( i ) is the option's argument (or empty). */ int ap_code( const struct Arg_parser * const ap, const int i ); const char * ap_argument( const struct Arg_parser * const ap, const int i ); diff --git a/configure b/configure index 53ee546..8baa082 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2019 Antonio Diaz Diaz. +# Copyright (C) 2010-2021 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission -# to copy, distribute and modify it. +# to copy, distribute, and modify it. pkgname=pdlzip -pkgversion=1.10 +pkgversion=1.11 progname=pdlzip srctrigger=doc/${progname}.1 @@ -26,11 +26,7 @@ CFLAGS='-Wall -W -O2' LDFLAGS= # checking whether we are using GNU C. -/bin/sh -c "${CC} --version" > /dev/null 2>&1 || - { - CC=cc - CFLAGS=-O2 - } +/bin/sh -c "${CC} --version" > /dev/null 2>&1 || { CC=cc ; CFLAGS=-O2 ; } # Loop over all args args= @@ -42,11 +38,12 @@ while [ $# != 0 ] ; do shift # Add the argument quoted to args - args="${args} \"${option}\"" + if [ -z "${args}" ] ; then args="\"${option}\"" + else args="${args} \"${option}\"" ; fi # Split out the argument for options that take them case ${option} in - *=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;; + *=*) optarg=`echo "${option}" | sed -e 's,^[^=]*=,,;s,/$,,'` ;; esac # Process the options @@ -125,7 +122,7 @@ if [ -z "${srcdir}" ] ; then if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi if [ ! -r "${srcdir}/${srctrigger}" ] ; then ## the sed command below emulates the dirname command - srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + srcdir=`echo "$0" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` fi fi @@ -148,7 +145,7 @@ if [ -z "${no_create}" ] ; then # Run this file to recreate the current configuration. # # This script is free software: you have unlimited permission -# to copy, distribute and modify it. +# to copy, distribute, and modify it. exec /bin/sh $0 ${args} --no-create EOF @@ -170,11 +167,11 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2019 Antonio Diaz Diaz. +# Copyright (C) 2010-2021 Antonio Diaz Diaz. # This file was generated automatically by configure. Don't edit. # # This Makefile is free software: you have unlimited permission -# to copy, distribute and modify it. +# to copy, distribute, and modify it. pkgname = ${pkgname} pkgversion = ${pkgversion} diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index e160d37..8586d88 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH PDLZIP "1" "January 2019" "pdlzip 1.10" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16. +.TH PDLZIP "1" "January 2021" "pdlzip 1.11" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -12,13 +12,15 @@ licensed Free Software. (The name of pdlzip comes from 'public domain lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. .PP -Lzip is a lossless data compressor with a user interface similar to the -one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) -or compress most files more than bzip2 (lzip \fB\-9\fR). Decompression speed is -intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 -from a data recovery perspective. Lzip has been designed, written and -tested with great care to replace gzip and bzip2 as the standard -general\-purpose compressed format for unix\-like systems. +Lzip is a lossless data compressor with a user interface similar to the one +of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov +chain\-Algorithm' (LZMA) stream format, chosen to maximize safety and +interoperability. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) or +compress most files more than bzip2 (lzip \fB\-9\fR). Decompression speed is +intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from +a data recovery perspective. Lzip has been designed, written, and tested +with great care to replace gzip and bzip2 as the standard general\-purpose +compressed format for unix\-like systems. .PP Pdlzip is also able to decompress legacy lzma\-alone (.lzma) files. Lzma\-alone is a very bad format; it is essentially a raw LZMA stream. @@ -55,7 +57,7 @@ keep (don't delete) input files set match length limit in bytes [36] .TP \fB\-o\fR, \fB\-\-output=\fR -if reading standard input, write to +write to , keep input files .TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages @@ -90,20 +92,26 @@ to 2^27 bytes. .PP The bidimensional parameter space of LZMA can't be mapped to a linear scale optimal for all files. If your files are large, very repetitive, -etc, you may need to use the \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR -options directly to achieve optimal performance. For example, \fB\-9m64\fR -usually compresses executables more (and faster) than \fB\-9\fR. +etc, you may need to use the options \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR +directly to achieve optimal performance. For example, \fB\-9m64\fR usually +compresses executables more (and faster) than \fB\-9\fR. +.PP +To extract all the files from archive 'foo.tar.lz', use the commands +\&'tar \fB\-xf\fR foo.tar.lz' or 'pdlzip \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'. .PP Exit status: 0 for a normal exit, 1 for environmental problems (file not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or invalid input file, 3 for an internal consistency error (eg, bug) which caused pdlzip to panic. +.PP +Pdlzip includes public domain compression/decompression code from the LZMA +SDK (Software Development Kit) written by Igor Pavlov. .SH "REPORTING BUGS" Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2019 Antonio Diaz Diaz. +Copyright \(co 2021 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index f0147fb..db45f0b 100644 --- a/lzip.h +++ b/lzip.h @@ -1,36 +1,31 @@ -/* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2019 Antonio Diaz Diaz. +/* Pdlzip - LZMA lossless data compressor + Copyright (C) 2010-2021 Antonio Diaz Diaz. - This program is free software. Redistribution and use in source and - binary forms, with or without modification, are permitted provided - that the following conditions are met: + This program is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef max #define max(x,y) ((x) >= (y) ? (x) : (y)) #endif -#ifndef min - #define min(x,y) ((x) <= (y) ? (x) : (y)) -#endif - -void * resize_buffer( void * buf, const unsigned min_size ); typedef int State; enum { min_dictionary_bits = 12, - min_dictionary_size = 1 << min_dictionary_bits, + min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */ max_dictionary_bits = 29, max_dictionary_size = 1 << max_dictionary_bits, max_dictionary_bits_c = 27, /* kDicLogSizeMaxCompress */ @@ -52,65 +47,6 @@ enum { min_match_len_limit = 5 }; -/* defined in main.c */ -extern int verbosity; - -struct Pretty_print /* requires global var 'int verbosity' */ - { - const char * name; - char * padded_name; - const char * stdin_name; - unsigned longest_name; - bool first_post; - }; - -static inline void Pp_init( struct Pretty_print * const pp, - const char * const filenames[], - const int num_filenames ) - { - unsigned stdin_name_len; - int i; - pp->name = 0; - pp->padded_name = 0; - pp->stdin_name = "(stdin)"; - pp->longest_name = 0; - pp->first_post = false; - - if( verbosity <= 0 ) return; - stdin_name_len = strlen( pp->stdin_name ); - for( i = 0; i < num_filenames; ++i ) - { - const char * const s = filenames[i]; - const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); - if( pp->longest_name < len ) pp->longest_name = len; - } - if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; - } - -static inline void Pp_set_name( struct Pretty_print * const pp, - const char * const filename ) - { - unsigned name_len, padded_name_len, i = 0; - - if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) - pp->name = filename; - else pp->name = pp->stdin_name; - name_len = strlen( pp->name ); - padded_name_len = max( name_len, pp->longest_name ) + 4; - pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 ); - while( i < 2 ) pp->padded_name[i++] = ' '; - while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; } - pp->padded_name[i++] = ':'; - while( i < padded_name_len ) pp->padded_name[i++] = ' '; - pp->padded_name[i] = 0; - pp->first_post = true; - } - -static inline void Pp_reset( struct Pretty_print * const pp ) - { if( pp->name && pp->name[0] ) pp->first_post = true; } -void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ); - - typedef uint32_t CRC32[256]; /* Table of CRCs of all 8-bit messages. */ extern CRC32 crc32; @@ -157,7 +93,7 @@ static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */ /* 4 version */ - /* 5 coded_dict_size */ + /* 5 coded dictionary size */ enum { Lh_size = 6 }; static inline void Lh_set_magic( Lzip_header data ) @@ -251,19 +187,17 @@ static inline void Lt_set_member_size( Lzip_trailer data, unsigned long long sz { int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } +static inline void set_retval( int * retval, const int new_val ) + { if( *retval < new_val ) *retval = new_val; } + static const char * const trailing_msg = "Trailing data not allowed."; +static const char * const mem_msg = "Not enough memory."; /* defined in main.c */ +extern int verbosity; int readblock( const int fd, uint8_t * const buf, const int size ); int writeblock( const int fd, const uint8_t * const buf, const int size ); -/* defined in main.c */ -void cleanup_and_fail( const int retval ); -void show_error( const char * const msg, const int errcode, const bool help ); -void show_file_error( const char * const filename, const char * const msg, - const int errcode ); -void internal_error( const char * const msg ); - #define SZ_OK 0 #define SZ_ERROR_READ 8 diff --git a/main.c b/main.c index a9195d4..41933df 100644 --- a/main.c +++ b/main.c @@ -1,27 +1,27 @@ -/* Pdlzip - LZMA lossless data compressor - 2009-08-14 : Igor Pavlov : Public domain - Copyright (C) 2010-2019 Antonio Diaz Diaz. +/* Pdlzip - LZMA lossless data compressor + 2009-08-14 : Igor Pavlov : Public domain + Copyright (C) 2010-2021 Antonio Diaz Diaz. - This program is free software. Redistribution and use in source and - binary forms, with or without modification, are permitted provided - that the following conditions are met: + This program is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* - Exit status: 0 for a normal exit, 1 for environmental problems - (file not found, invalid flags, I/O errors, etc), 2 to indicate a - corrupt or invalid input file, 3 for an internal consistency error - (eg, bug) which caused pdlzip to panic. + Exit status: 0 for a normal exit, 1 for environmental problems + (file not found, invalid flags, I/O errors, etc), 2 to indicate a + corrupt or invalid input file, 3 for an internal consistency error + (eg, bug) which caused pdlzip to panic. */ #define _FILE_OFFSET_BITS 64 @@ -72,12 +72,18 @@ #endif int verbosity = 0; +static void cleanup_and_fail( const int retval ); +static void show_error( const char * const msg, const int errcode, + const bool help ); +static void show_file_error( const char * const filename, + const char * const msg, const int errcode ); +static void internal_error( const char * const msg ); -const char * const program_name = "pdlzip"; -const char * const program_year = "2019"; -const char * invocation_name = 0; +static const char * const program_name = "pdlzip"; +static const char * const program_year = "2021"; +static const char * invocation_name = "pdlzip"; /* default value */ -const struct { const char * from; const char * to; } known_extensions[] = { +static const struct { const char * from; const char * to; } known_extensions[] = { { ".lz", "" }, { ".tlz", ".tar" }, { ".lzma", "" }, @@ -93,9 +99,9 @@ enum Mode { m_compress, m_decompress, m_test }; /* Variables used in signal handler context. They are not declared volatile because the handler never returns. */ -char * output_filename = 0; -int outfd = -1; -bool delete_output_on_interrupt = false; +static char * output_filename = 0; +static int outfd = -1; +static bool delete_output_on_interrupt = false; static void show_help( void ) @@ -105,13 +111,15 @@ static void show_help( void ) "licensed Free Software. (The name of pdlzip comes from 'public domain\n" "lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4\n" "or newer.\n" - "\nLzip is a lossless data compressor with a user interface similar to the\n" - "one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0)\n" - "or compress most files more than bzip2 (lzip -9). Decompression speed is\n" - "intermediate between gzip and bzip2. Lzip is better than gzip and bzip2\n" - "from a data recovery perspective. Lzip has been designed, written and\n" - "tested with great care to replace gzip and bzip2 as the standard\n" - "general-purpose compressed format for unix-like systems.\n" + "\nLzip is a lossless data compressor with a user interface similar to the one\n" + "of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov\n" + "chain-Algorithm' (LZMA) stream format, chosen to maximize safety and\n" + "interoperability. Lzip can compress about as fast as gzip (lzip -0) or\n" + "compress most files more than bzip2 (lzip -9). Decompression speed is\n" + "intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from\n" + "a data recovery perspective. Lzip has been designed, written, and tested\n" + "with great care to replace gzip and bzip2 as the standard general-purpose\n" + "compressed format for unix-like systems.\n" "\nPdlzip is also able to decompress legacy lzma-alone (.lzma) files.\n" "Lzma-alone is a very bad format; it is essentially a raw LZMA stream.\n" "If you keep any lzma-alone files, it is advisable to recompress them to\n" @@ -128,7 +136,7 @@ static void show_help( void ) " -F, --recompress force re-compression of compressed files\n" " -k, --keep keep (don't delete) input files\n" " -m, --match-length= set match length limit in bytes [36]\n" - " -o, --output= if reading standard input, write to \n" + " -o, --output= write to , keep input files\n" " -q, --quiet suppress all messages\n" " -s, --dictionary-size= set dictionary size limit in bytes [8 MiB]\n" " -t, --test test compressed file integrity\n" @@ -137,7 +145,7 @@ static void show_help( void ) " --fast alias for -0\n" " --best alias for -9\n" " --loose-trailing allow trailing data seeming corrupt header\n" - "If no file names are given, or if a file is '-', pdlzip compresses or\n" + "\nIf no file names are given, or if a file is '-', pdlzip compresses or\n" "decompresses from standard input to standard output.\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" @@ -145,13 +153,17 @@ static void show_help( void ) "to 2^27 bytes.\n" "\nThe bidimensional parameter space of LZMA can't be mapped to a linear\n" "scale optimal for all files. If your files are large, very repetitive,\n" - "etc, you may need to use the --dictionary-size and --match-length\n" - "options directly to achieve optimal performance. For example, -9m64\n" - "usually compresses executables more (and faster) than -9.\n" + "etc, you may need to use the options --dictionary-size and --match-length\n" + "directly to achieve optimal performance. For example, -9m64 usually\n" + "compresses executables more (and faster) than -9.\n" + "\nTo extract all the files from archive 'foo.tar.lz', use the commands\n" + "'tar -xf foo.tar.lz' or 'pdlzip -cd foo.tar.lz | tar -xf -'.\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n" "invalid input file, 3 for an internal consistency error (eg, bug) which\n" "caused pdlzip to panic.\n" + "\nPdlzip includes public domain compression/decompression code from the LZMA\n" + "SDK (Software Development Kit) written by Igor Pavlov.\n" "\nReport bugs to lzip-bug@nongnu.org\n" "Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" ); } @@ -169,20 +181,69 @@ static void show_version( void ) /* assure at least a minimum size for buffer 'buf' */ -void * resize_buffer( void * buf, const unsigned min_size ) +static void * resize_buffer( void * buf, const unsigned min_size ) { if( buf ) buf = realloc( buf, min_size ); else buf = malloc( min_size ); - if( !buf ) - { - show_error( "Not enough memory.", 0, false ); - cleanup_and_fail( 1 ); - } + if( !buf ) { show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); } return buf; } -void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) +struct Pretty_print + { + const char * name; + char * padded_name; + const char * stdin_name; + unsigned longest_name; + bool first_post; + }; + +static void Pp_init( struct Pretty_print * const pp, + const char * const filenames[], const int num_filenames ) + { + unsigned stdin_name_len; + int i; + pp->name = 0; + pp->padded_name = 0; + pp->stdin_name = "(stdin)"; + pp->longest_name = 0; + pp->first_post = false; + + if( verbosity <= 0 ) return; + stdin_name_len = strlen( pp->stdin_name ); + for( i = 0; i < num_filenames; ++i ) + { + const char * const s = filenames[i]; + const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); + if( pp->longest_name < len ) pp->longest_name = len; + } + if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; + } + +static void Pp_set_name( struct Pretty_print * const pp, + const char * const filename ) + { + unsigned name_len, padded_name_len, i = 0; + + if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) + pp->name = filename; + else pp->name = pp->stdin_name; + name_len = strlen( pp->name ); + padded_name_len = max( name_len, pp->longest_name ) + 4; + pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 ); + while( i < 2 ) pp->padded_name[i++] = ' '; + while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; } + pp->padded_name[i++] = ':'; + while( i < padded_name_len ) pp->padded_name[i++] = ' '; + pp->padded_name[i] = 0; + pp->first_post = true; + } + +static void Pp_reset( struct Pretty_print * const pp ) + { if( pp->name && pp->name[0] ) pp->first_post = true; } + +static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) { if( verbosity >= 0 ) { @@ -210,7 +271,7 @@ static void show_header( const unsigned dictionary_size ) int i; for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) { num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; np = ""; } - fprintf( stderr, "dictionary %s%4u %sB, ", np, num, p ); + fprintf( stderr, "dict %s%4u %sB, ", np, num, p ); } @@ -277,6 +338,17 @@ static int get_dict_size( const char * const arg ) } +static void set_mode( enum Mode * const program_modep, const enum Mode new_mode ) + { + if( *program_modep != m_compress && *program_modep != new_mode ) + { + show_error( "Only one operation can be specified.", 0, true ); + exit( 1 ); + } + *program_modep = new_mode; + } + + static int extension_index( const char * const name ) { int eindex; @@ -293,12 +365,16 @@ static int extension_index( const char * const name ) } -static void set_c_outname( const char * const name, const bool force_ext ) +static void set_c_outname( const char * const name, const bool filenames_given, + const bool force_ext ) { + /* zupdate < 1.9 depends on lzip adding the extension '.lz' to name when + reading from standard input. */ output_filename = resize_buffer( output_filename, strlen( name ) + strlen( known_extensions[0].from ) + 1 ); strcpy( output_filename, name ); - if( force_ext || extension_index( output_filename ) < 0 ) + if( force_ext || + ( !filenames_given && extension_index( output_filename ) < 0 ) ) strcat( output_filename, known_extensions[0].from ); } @@ -330,7 +406,7 @@ static void set_d_outname( const char * const name, const int eindex ) static int open_instream( const char * const name, struct stat * const in_statsp, const enum Mode program_mode, const int eindex, - const bool recompress, const bool to_stdout ) + const bool one_to_one, const bool recompress ) { int infd = -1; if( program_mode == m_compress && !recompress && eindex >= 0 ) @@ -351,14 +427,12 @@ static int open_instream( const char * const name, struct stat * const in_statsp const bool can_read = ( i == 0 && ( S_ISBLK( mode ) || S_ISCHR( mode ) || S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); - const bool no_ofile = ( to_stdout || program_mode == m_test ); - if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) ) + if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) ) { if( verbosity >= 0 ) fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", - program_name, name, - ( can_read && !no_ofile ) ? - ",\n and '--stdout' was not specified" : "" ); + program_name, name, ( can_read && one_to_one ) ? + ",\n and neither '-c' nor '-o' were specified" : "" ); close( infd ); infd = -1; } @@ -368,11 +442,11 @@ static int open_instream( const char * const name, struct stat * const in_statsp } -static bool open_outstream( const bool force, const bool from_stdin ) +static bool open_outstream( const bool force, const bool protect ) { const mode_t usr_rw = S_IRUSR | S_IWUSR; const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - const mode_t outfd_mode = from_stdin ? all_rw : usr_rw; + const mode_t outfd_mode = protect ? usr_rw : all_rw; int flags = O_CREAT | O_WRONLY | O_BINARY; if( force ) flags |= O_TRUNC; else flags |= O_EXCL; @@ -391,25 +465,6 @@ static bool open_outstream( const bool force, const bool from_stdin ) } -static bool check_tty( const char * const input_filename, const int infd, - const enum Mode program_mode ) - { - if( program_mode == m_compress && isatty( outfd ) ) - { - show_error( "I won't write compressed data to a terminal.", 0, true ); - return false; - } - if( ( program_mode == m_decompress || program_mode == m_test ) && - isatty( infd ) ) - { - show_file_error( input_filename, - "I won't read compressed data from a terminal.", 0 ); - return false; - } - return true; - } - - static void set_signals( void (*action)(int) ) { signal( SIGHUP, action ); @@ -418,7 +473,7 @@ static void set_signals( void (*action)(int) ) } -void cleanup_and_fail( const int retval ) +static void cleanup_and_fail( const int retval ) { set_signals( SIG_IGN ); /* ignore signals */ if( delete_output_on_interrupt ) @@ -435,7 +490,7 @@ void cleanup_and_fail( const int retval ) } -void signal_handler( int sig ) +static void signal_handler( int sig ) { if( sig ) {} /* keep compiler happy */ show_error( "Control-C or similar caught, quitting.", 0, false ); @@ -443,7 +498,31 @@ void signal_handler( int sig ) } - /* Set permissions, owner and times. */ +static bool check_tty_in( const char * const input_filename, const int infd, + const enum Mode program_mode, int * const retval ) + { + if( ( program_mode == m_decompress || program_mode == m_test ) && + isatty( infd ) ) /* for example /dev/tty */ + { show_file_error( input_filename, + "I won't read compressed data from a terminal.", 0 ); + close( infd ); set_retval( retval, 1 ); + if( program_mode != m_test ) cleanup_and_fail( *retval ); + return false; } + return true; + } + +static bool check_tty_out( const enum Mode program_mode ) + { + if( program_mode == m_compress && isatty( outfd ) ) + { show_file_error( output_filename[0] ? + output_filename : "(stdout)", + "I won't write compressed data to a terminal.", 0 ); + return false; } + return true; + } + + +/* Set permissions, owner, and times. */ static void close_and_set_permissions( const struct stat * const in_statsp ) { bool warning = false; @@ -509,6 +588,28 @@ static int compress( const struct Lzma_options * const encoder_options, } +static void show_results( const long long data_size, + const long long member_size, const unsigned crc, + const unsigned dictionary_size, const bool lzip_mode ) + { + if( verbosity >= 2 ) + { + if( verbosity >= 4 ) show_header( dictionary_size ); + if( data_size == 0 || member_size == 0 ) + fputs( "no data compressed. ", stderr ); + else + fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", + (double)data_size / member_size, + ( 100.0 * member_size ) / data_size, + 100.0 - ( ( 100.0 * member_size ) / data_size ) ); + if( verbosity >= 4 && lzip_mode ) fprintf( stderr, "CRC %08X, ", crc ); + if( verbosity >= 3 ) + fprintf( stderr, "%9llu out, %8llu in. ", data_size, member_size ); + if( !lzip_mode ) fputs( "lzma-alone, ", stderr ); + } + } + + #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) @@ -584,21 +685,7 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd, if( ( thereIsSize && unpackSize != 0 ) || ( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) ) { show_error( "Data error.", 0, false ); return 2; } - if( verbosity >= 2 ) - { - if( verbosity >= 4 ) show_header( dictionary_size ); - if( data_size == 0 || member_size == 0 ) - fputs( "no data compressed. ", stderr ); - else - fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", - (double)data_size / member_size, - ( 100.0 * member_size ) / data_size, - 100.0 - ( ( 100.0 * member_size ) / data_size ) ); - if( verbosity >= 3 ) - fprintf( stderr, "decompressed %9llu, compressed %8llu. ", - data_size, member_size ); - fputs( "lzma-alone, ", stderr ); - } + show_results( data_size, member_size, 0, dictionary_size, false ); if( verbosity >= 1 ) fputs( testing ? "(apparently) ok\n" : "(apparently) done\n", stderr ); return 0; @@ -705,21 +792,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, } } if( error ) return 2; - if( verbosity >= 2 ) - { - if( verbosity >= 4 ) show_header( dictionary_size ); - if( data_size == 0 || member_size == 0 ) - fputs( "no data compressed. ", stderr ); - else - fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", - (double)data_size / member_size, - ( 100.0 * member_size ) / data_size, - 100.0 - ( ( 100.0 * member_size ) / data_size ) ); - if( verbosity >= 4 ) fprintf( stderr, "CRC %08X, ", td_crc ); - if( verbosity >= 3 ) - fprintf( stderr, "decompressed %9llu, compressed %8llu. ", - data_size, member_size ); - } + show_results( data_size, member_size, td_crc, dictionary_size, true ); return 0; } } @@ -742,7 +815,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, for( first_member = true; ; first_member = false ) { int i, size; - unsigned dictionary_size; + unsigned dictionary_size = 0; /* keep gcc 3.3.6 happy */ Lzip_header header; if( inSize - inPos < lzma_header_size && !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; @@ -819,7 +892,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, Pp_show_msg( pp, 0 ); if( !LzmaDec_Init( &decoder, raw_props ) ) - { Pp_show_msg( pp, "Not enough memory." ); return 1; } + { Pp_show_msg( pp, mem_msg ); return 1; } if( lzip_mode ) retval = lzip_decode( &decoder, infd, pp, inBuf, &inPos, &inSize, dictionary_size ); @@ -877,7 +950,8 @@ int writeblock( const int fd, const uint8_t * const buf, const int size ) } -void show_error( const char * const msg, const int errcode, const bool help ) +static void show_error( const char * const msg, const int errcode, + const bool help ) { if( verbosity < 0 ) return; if( msg && msg[0] ) @@ -890,8 +964,8 @@ void show_error( const char * const msg, const int errcode, const bool help ) } -void show_file_error( const char * const filename, const char * const msg, - const int errcode ) +static void show_file_error( const char * const filename, + const char * const msg, const int errcode ) { if( verbosity >= 0 ) fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg, @@ -900,7 +974,7 @@ void show_file_error( const char * const filename, const char * const msg, } -void internal_error( const char * const msg ) +static void internal_error( const char * const msg ) { if( verbosity >= 0 ) fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); @@ -926,7 +1000,9 @@ int main( const int argc, const char * const argv[] ) { 1 << 25, 273 } }; /* -9 */ struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ const char * default_output_filename = ""; - const char ** filenames = 0; + static struct Arg_parser parser; /* static because valgrind complains */ + static struct Pretty_print pp; /* and memory management in C sucks */ + static const char ** filenames = 0; int num_filenames = 0; enum Mode program_mode = m_compress; int argind = 0; @@ -941,20 +1017,19 @@ int main( const int argc, const char * const argv[] ) bool recompress = false; bool stdin_used = false; bool to_stdout = false; - struct Pretty_print pp; enum { opt_lt = 256 }; const struct ap_Option options[] = { { '0', "fast", ap_no }, - { '1', 0, ap_no }, - { '2', 0, ap_no }, - { '3', 0, ap_no }, - { '4', 0, ap_no }, - { '5', 0, ap_no }, - { '6', 0, ap_no }, - { '7', 0, ap_no }, - { '8', 0, ap_no }, + { '1', 0, ap_no }, + { '2', 0, ap_no }, + { '3', 0, ap_no }, + { '4', 0, ap_no }, + { '5', 0, ap_no }, + { '6', 0, ap_no }, + { '7', 0, ap_no }, + { '8', 0, ap_no }, { '9', "best", ap_no }, { 'a', "trailing-error", ap_no }, { 'b', "member-size", ap_yes }, @@ -974,15 +1049,13 @@ int main( const int argc, const char * const argv[] ) { 'v', "verbose", ap_no }, { 'V', "version", ap_no }, { opt_lt, "loose-trailing", ap_no }, - { 0 , 0, ap_no } }; + { 0, 0, ap_no } }; - struct Arg_parser parser; - - invocation_name = argv[0]; + if( argc > 0 ) invocation_name = argv[0]; CRC32_init(); if( !ap_init( &parser, argc, argv, options, 0 ) ) - { show_error( "Not enough memory.", 0, false ); return 1; } + { show_error( mem_msg, 0, false ); return 1; } if( ap_error( &parser ) ) /* bad option */ { show_error( ap_error( &parser ), 0, true ); return 1; } @@ -999,7 +1072,7 @@ int main( const int argc, const char * const argv[] ) case 'a': ignore_trailing = false; break; case 'b': break; case 'c': to_stdout = true; break; - case 'd': program_mode = m_decompress; break; + case 'd': set_mode( &program_mode, m_decompress ); break; case 'f': force = true; break; case 'F': recompress = true; break; case 'h': show_help(); return 0; @@ -1007,12 +1080,13 @@ int main( const int argc, const char * const argv[] ) case 'm': encoder_options.match_len_limit = getnum( arg, min_match_len_limit, max_match_len ); break; case 'n': break; - case 'o': default_output_filename = arg; break; + case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true; + else { default_output_filename = arg; } break; case 'q': verbosity = -1; break; case 's': encoder_options.dictionary_size = get_dict_size( arg ); break; case 'S': break; - case 't': program_mode = m_test; break; + case 't': set_mode( &program_mode, m_test ); break; case 'v': if( verbosity < 4 ) ++verbosity; break; case 'V': show_version(); return 0; case opt_lt: loose_trailing = true; break; @@ -1035,16 +1109,23 @@ int main( const int argc, const char * const argv[] ) if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true; } - if( program_mode == m_test ) - outfd = -1; + if( program_mode == m_test ) to_stdout = false; /* apply overrides */ + if( program_mode == m_test || to_stdout ) default_output_filename = ""; - if( !to_stdout && program_mode != m_test && - ( filenames_given || default_output_filename[0] ) ) + output_filename = resize_buffer( output_filename, 1 ); + output_filename[0] = 0; + if( to_stdout && program_mode != m_test ) /* check tty only once */ + { outfd = STDOUT_FILENO; if( !check_tty_out( program_mode ) ) return 1; } + else outfd = -1; + + const bool to_file = !to_stdout && program_mode != m_test && + default_output_filename[0]; + if( !to_stdout && program_mode != m_test && ( filenames_given || to_file ) ) set_signals( signal_handler ); Pp_init( &pp, filenames, num_filenames ); - output_filename = resize_buffer( output_filename, 1 ); + const bool one_to_one = !to_stdout && program_mode != m_test && !to_file; for( i = 0; i < num_filenames; ++i ) { const char * input_filename = ""; @@ -1052,96 +1133,71 @@ int main( const int argc, const char * const argv[] ) int tmp; struct stat in_stats; const struct stat * in_statsp; - output_filename[0] = 0; - if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) + Pp_set_name( &pp, filenames[i] ); + if( strcmp( filenames[i], "-" ) == 0 ) { if( stdin_used ) continue; else stdin_used = true; infd = STDIN_FILENO; - if( program_mode != m_test ) - { - if( to_stdout || !default_output_filename[0] ) - outfd = STDOUT_FILENO; - else - { - if( program_mode == m_compress ) - set_c_outname( default_output_filename, false ); - else - { - output_filename = resize_buffer( output_filename, - strlen( default_output_filename ) + 1 ); - strcpy( output_filename, default_output_filename ); - } - if( !open_outstream( force, true ) ) - { - if( retval < 1 ) retval = 1; - close( infd ); - continue; - } - } - } + if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue; + if( one_to_one ) { outfd = STDOUT_FILENO; output_filename[0] = 0; } } else { const int eindex = extension_index( input_filename = filenames[i] ); infd = open_instream( input_filename, &in_stats, program_mode, - eindex, recompress, to_stdout ); - if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } - if( program_mode != m_test ) + eindex, one_to_one, recompress ); + if( infd < 0 ) { set_retval( &retval, 1 ); continue; } + if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue; + if( one_to_one ) /* open outfd after verifying infd */ { - if( to_stdout ) outfd = STDOUT_FILENO; - else - { - if( program_mode == m_compress ) - set_c_outname( input_filename, true ); - else set_d_outname( input_filename, eindex ); - if( !open_outstream( force, false ) ) - { - if( retval < 1 ) retval = 1; - close( infd ); - continue; - } - } + if( program_mode == m_compress ) + set_c_outname( input_filename, true, true ); + else set_d_outname( input_filename, eindex ); + if( !open_outstream( force, true ) ) + { close( infd ); set_retval( &retval, 1 ); continue; } } } - Pp_set_name( &pp, input_filename ); - if( !check_tty( pp.name, infd, program_mode ) ) + if( one_to_one && !check_tty_out( program_mode ) ) + { set_retval( &retval, 1 ); return retval; } /* don't delete a tty */ + + if( to_file && outfd < 0 ) /* open outfd after verifying infd */ { - if( retval < 1 ) retval = 1; - if( program_mode == m_test ) { close( infd ); continue; } - cleanup_and_fail( retval ); + if( program_mode == m_compress ) set_c_outname( default_output_filename, + filenames_given, false ); + else + { output_filename = resize_buffer( output_filename, + strlen( default_output_filename ) + 1 ); + strcpy( output_filename, default_output_filename ); } + if( !open_outstream( force, false ) || !check_tty_out( program_mode ) ) + return 1; /* check tty only once and don't try to delete a tty */ } - in_statsp = input_filename[0] ? &in_stats : 0; + in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0; if( program_mode == m_compress ) tmp = compress( &encoder_options, &pp, infd ); else tmp = decompress( infd, &pp, ignore_trailing, loose_trailing, program_mode == m_test ); if( close( infd ) != 0 ) - { - show_error( input_filename[0] ? "Error closing input file" : - "Error closing stdin", errno, false ); - if( tmp < 1 ) tmp = 1; - } - if( tmp > retval ) retval = tmp; + { show_file_error( pp.name, "Error closing input file", errno ); + set_retval( &tmp, 1 ); } + set_retval( &retval, tmp ); if( tmp ) { if( program_mode != m_test ) cleanup_and_fail( retval ); else ++failed_tests; } - if( delete_output_on_interrupt ) + if( delete_output_on_interrupt && one_to_one ) close_and_set_permissions( in_statsp ); - if( input_filename[0] ) - { - if( !keep_input_files && !to_stdout && program_mode != m_test ) - remove( input_filename ); - } + if( input_filename[0] && !keep_input_files && one_to_one ) + remove( input_filename ); } - if( outfd >= 0 && close( outfd ) != 0 ) + if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); /* -o */ + else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */ { show_error( "Error closing stdout", errno, false ); - if( retval < 1 ) retval = 1; + set_retval( &retval, 1 ); } if( failed_tests > 0 && verbosity >= 1 && num_filenames > 1 ) fprintf( stderr, "%s: warning: %d %s failed the test.\n", diff --git a/testsuite/check.sh b/testsuite/check.sh index c3d859c..80de80c 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,9 +1,9 @@ #! /bin/sh # check script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2019 Antonio Diaz Diaz. +# Copyright (C) 2010-2021 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission -# to copy, distribute and modify it. +# to copy, distribute, and modify it. LC_ALL=C export LC_ALL @@ -30,6 +30,8 @@ cd "${objdir}"/tmp || framework_failure cat "${testdir}"/test.txt > in || framework_failure in_lz="${testdir}"/test.txt.lz +in_em="${testdir}"/test_em.txt.lz +fox_lz="${testdir}"/fox.lz fail=0 test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } @@ -56,8 +58,20 @@ done [ $? = 2 ] || test_failed $LINENO "${LZIP}" -dq -o in < "${in_lz}" [ $? = 1 ] || test_failed $LINENO +"${LZIP}" -dq -o in "${in_lz}" +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -dq -o out nx_file.lz +[ $? = 1 ] || test_failed $LINENO +[ ! -e out ] || test_failed $LINENO +"${LZIP}" -q -o out.lz nx_file +[ $? = 1 ] || test_failed $LINENO +[ ! -e out.lz ] || test_failed $LINENO # these are for code coverage -"${LZIP}" -t -- nx_file 2> /dev/null +"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -t -- nx_file.lz 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -t "" < /dev/null 2> /dev/null [ $? = 1 ] || test_failed $LINENO "${LZIP}" --help > /dev/null || test_failed $LINENO "${LZIP}" -n1 -V > /dev/null || test_failed $LINENO @@ -81,15 +95,22 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null printf "\ntesting decompression..." -"${LZIP}" -t "${in_lz}" || test_failed $LINENO -"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO +for i in "${in_lz}" "${in_em}" "${testdir}"/test.txt.lzma ; do + "${LZIP}" -t "$i" || test_failed $LINENO "$i" + "${LZIP}" -d "$i" -o copy || test_failed $LINENO "$i" + cmp in copy || test_failed $LINENO "$i" + "${LZIP}" -cd "$i" > copy || test_failed $LINENO "$i" + cmp in copy || test_failed $LINENO "$i" + "${LZIP}" -d "$i" -o - > copy || test_failed $LINENO "$i" + cmp in copy || test_failed $LINENO "$i" + "${LZIP}" -d < "$i" > copy || test_failed $LINENO "$i" + cmp in copy || test_failed $LINENO "$i" + rm -f copy || framework_failure +done -"${LZIP}" -t "${testdir}"/test.txt.lzma || test_failed $LINENO -"${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO +lines=$("${LZIP}" -tvv "${in_em}" 2>&1 | wc -l) || test_failed $LINENO +[ "${lines}" -eq 8 ] || test_failed $LINENO "${lines}" -rm -f copy || framework_failure cat "${in_lz}" > copy.lz || framework_failure "${LZIP}" -dk copy.lz || test_failed $LINENO cmp in copy || test_failed $LINENO @@ -100,19 +121,21 @@ printf "to be overwritten" > copy || framework_failure [ ! -e copy.lz ] || test_failed $LINENO cmp in copy || test_failed $LINENO -rm -f copy || framework_failure -cat "${in_lz}" > copy.lz || framework_failure -"${LZIP}" -d -S100k copy.lz || test_failed $LINENO # ignore -S -[ ! -e copy.lz ] || test_failed $LINENO -cmp in copy || test_failed $LINENO - printf "to be overwritten" > copy || framework_failure +"${LZIP}" -d -o copy < "${in_lz}" 2> /dev/null +[ $? = 1 ] || test_failed $LINENO "${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO cmp in copy || test_failed $LINENO +rm -f out copy || framework_failure +"${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO +cmp in ./- || test_failed $LINENO +rm -f ./- || framework_failure +"${LZIP}" -d -o ./- < "${in_lz}" || test_failed $LINENO +cmp in ./- || test_failed $LINENO +rm -f ./- || framework_failure -rm -f copy || framework_failure -"${LZIP}" -s16 < in > anyothername || test_failed $LINENO -"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null || +cat "${in_lz}" > anyothername || framework_failure +"${LZIP}" -dv - anyothername - < "${in_lz}" > copy 2> /dev/null || test_failed $LINENO cmp in copy || test_failed $LINENO cmp in anyothername.out || test_failed $LINENO @@ -147,19 +170,18 @@ done cmp in copy || test_failed $LINENO cat in in > in2 || framework_failure -cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure -"${LZIP}" -t in2.lz || test_failed $LINENO -"${LZIP}" -cd in2.lz > copy2 || test_failed $LINENO +"${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO +"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > copy2 || test_failed $LINENO +[ ! -e out ] || test_failed $LINENO # override -o cmp in2 copy2 || test_failed $LINENO - -"${LZIP}" -s16 --output=copy2.lz < in2 || test_failed $LINENO -"${LZIP}" -t copy2.lz || test_failed $LINENO -"${LZIP}" -cd copy2.lz > copy2 || test_failed $LINENO +rm -f copy2 || framework_failure +"${LZIP}" -d "${in_lz}" "${in_lz}" -o copy2 || test_failed $LINENO cmp in2 copy2 || test_failed $LINENO +rm -f copy2 || framework_failure +cat "${in_lz}" "${in_lz}" > copy2.lz || framework_failure printf "\ngarbage" >> copy2.lz || framework_failure "${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO -rm -f copy2 || framework_failure "${LZIP}" -atq copy2.lz [ $? = 2 ] || test_failed $LINENO "${LZIP}" -atq < copy2.lz @@ -179,37 +201,46 @@ printf "\ntesting compression..." "${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2 [ $? = 1 ] || test_failed $LINENO -"${LZIP}" -cFvvm36 -s16 "${in_lz}" > out 2> /dev/null || test_failed $LINENO +"${LZIP}" -Fvvm36 -o - -s16 "${in_lz}" > out 2> /dev/null || test_failed $LINENO "${LZIP}" -cd out | "${LZIP}" -d > copy || test_failed $LINENO cmp in copy || test_failed $LINENO +"${LZIP}" -0 -o ./- in || test_failed $LINENO +"${LZIP}" -cd ./- | cmp in - || test_failed $LINENO +rm -f ./- || framework_failure +"${LZIP}" -0 -o ./- < in || test_failed $LINENO # add .lz +[ ! -e ./- ] || test_failed $LINENO +"${LZIP}" -cd -- -.lz | cmp in - || test_failed $LINENO +rm -f ./-.lz || framework_failure + for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do "${LZIP}" -k -$i -s16 in || test_failed $LINENO $i mv -f in.lz copy.lz || test_failed $LINENO $i printf "garbage" >> copy.lz || framework_failure "${LZIP}" -df copy.lz || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i -done -for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do - "${LZIP}" -c -$i -s16 in > out || test_failed $LINENO $i + "${LZIP}" -$i -s16 in -c > out || test_failed $LINENO $i + "${LZIP}" -$i -s16 in -o o_out || test_failed $LINENO $i # don't add .lz + [ ! -e o_out.lz ] || test_failed $LINENO + cmp out o_out || test_failed $LINENO $i + rm -f o_out || framework_failure printf "g" >> out || framework_failure "${LZIP}" -cd out > copy || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i -done -for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do "${LZIP}" -$i -s16 < in > out || test_failed $LINENO $i "${LZIP}" -d < out > copy || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i -done -for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do - "${LZIP}" -f -$i -s16 -o out < in || test_failed $LINENO $i + rm -f out || framework_failure + printf "to be overwritten" > out.lz || framework_failure + "${LZIP}" -f -$i -s16 -o out < in || test_failed $LINENO $i # add .lz + [ ! -e out ] || test_failed $LINENO "${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i done -rm -f out.lz || framework_failure +rm -f out out.lz || framework_failure printf "\ntesting bad input..." @@ -258,6 +289,21 @@ else fi rm -f int.lz || framework_failure +for i in fox_v2.lz fox_s11.lz fox_de20.lz \ + fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do + "${LZIP}" -tq "${testdir}"/$i + [ $? = 2 ] || test_failed $LINENO $i +done + +"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO +for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do + "${LZIP}" -cdq "${testdir}"/$i > out + [ $? = 2 ] || test_failed $LINENO $i + cmp fox out || test_failed $LINENO $i +done +rm -f fox out || framework_failure + +cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && [ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then @@ -280,13 +326,21 @@ rm -f in2.lz in3.lz trunc.lz out || framework_failure cat "${in_lz}" > ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure cat "${in_lz}" >> ingin.lz || framework_failure +"${LZIP}" -atq ingin.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -atq < ingin.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -acdq ingin.lz > out +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -adq < ingin.lz > out +[ $? = 2 ] || test_failed $LINENO "${LZIP}" -t ingin.lz || test_failed $LINENO +"${LZIP}" -t < ingin.lz || test_failed $LINENO "${LZIP}" -cd ingin.lz > copy || test_failed $LINENO cmp in copy || test_failed $LINENO -"${LZIP}" -t < ingin.lz || test_failed $LINENO "${LZIP}" -d < ingin.lz > copy || test_failed $LINENO cmp in copy || test_failed $LINENO -rm -f copy ingin.lz || framework_failure +rm -f copy ingin.lz out || framework_failure echo if [ ${fail} = 0 ] ; then diff --git a/testsuite/fox.lz b/testsuite/fox.lz new file mode 100644 index 0000000000000000000000000000000000000000..509da8268a3fd054415089a646cdcfd00d3eee7a GIT binary patch literal 80 zcmeZ?@(f_)VbGG|Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2nc}E07J|k>Hq)$ literal 0 HcmV?d00001 diff --git a/testsuite/fox_bcrc.lz b/testsuite/fox_bcrc.lz new file mode 100644 index 0000000000000000000000000000000000000000..8f6a7c4af4b808a1ed873b58d5d9a343a722edcd GIT binary patch literal 80 zcmeZ?@(f_)VbGG|Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFb)#z-wIw2nc}E07Kv&>i_@% literal 0 HcmV?d00001 diff --git a/testsuite/fox_crc0.lz b/testsuite/fox_crc0.lz new file mode 100644 index 0000000000000000000000000000000000000000..1abe92689f2fb57212633f41962e53f4297bd5a2 GIT binary patch literal 80 zcmeZ?@(f_)VbGG|Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU bIqmVA>95u)|NqywfB^(_!6XAi0F(v*7bP5d literal 0 HcmV?d00001 diff --git a/testsuite/fox_das46.lz b/testsuite/fox_das46.lz new file mode 100644 index 0000000000000000000000000000000000000000..43ed9f9503c4e8c298e6bf671f669b56e24162a2 GIT binary patch literal 80 zcmeZ?@(f_)VbGG|Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-v7Q2nc}E07Kj!>i_@% literal 0 HcmV?d00001 diff --git a/testsuite/fox_de20.lz b/testsuite/fox_de20.lz new file mode 100644 index 0000000000000000000000000000000000000000..10949d888f0e1c630fc860b3a8c8eb0bee7f77bf GIT binary patch literal 80 zcmeZ?@(f_)VbGG|Sj4QF_R+iI=pxpCde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2nc}E07H--=>Px# literal 0 HcmV?d00001 diff --git a/testsuite/fox_mes81.lz b/testsuite/fox_mes81.lz new file mode 100644 index 0000000000000000000000000000000000000000..d50ef2e2fa7a5160a77c814344218585e865f266 GIT binary patch literal 80 zcmeZ?@(f_)VbGG|Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2ndAI07KLs>i_@% literal 0 HcmV?d00001 diff --git a/testsuite/fox_s11.lz b/testsuite/fox_s11.lz new file mode 100644 index 0000000000000000000000000000000000000000..dca909c62a44e1b011404dbd5afe0af47c3bb6e7 GIT binary patch literal 80 zcmeZ?@(f_)X3&!2Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2nc}E07HQu=>Px# literal 0 HcmV?d00001 diff --git a/testsuite/fox_v2.lz b/testsuite/fox_v2.lz new file mode 100644 index 0000000000000000000000000000000000000000..8620981714096152fff6673aa04060f251bdad44 GIT binary patch literal 80 zcmeZ?@(f_&VbGG|Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2nc}E07Mub>i_@% literal 0 HcmV?d00001 diff --git a/testsuite/test_em.txt.lz b/testsuite/test_em.txt.lz new file mode 100644 index 0000000000000000000000000000000000000000..7e96250d9ec70bc7d8cb173f438c76be447e6b6f GIT binary patch literal 14024 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 Gt^OBPlQ$#) literal 0 HcmV?d00001 From 863474307266ab2697db960a4fc2e3c4e77ff96b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:26:43 +0100 Subject: [PATCH 06/10] Adding upstream version 1.12. Signed-off-by: Daniel Baumann --- ChangeLog | 9 +- INSTALL | 4 +- LzmaEnc.h | 1 - Makefile.in | 2 +- NEWS | 32 +------ README | 22 ++--- carg_parser.c | 110 +++++++++++++++--------- carg_parser.h | 14 +-- configure | 6 +- doc/pdlzip.1 | 26 +++--- lzip.h | 3 +- main.c | 206 +++++++++++++++++++++++++++------------------ testsuite/check.sh | 18 ++-- 13 files changed, 257 insertions(+), 196 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b5efdd..fe563fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-01-21 Antonio Diaz Diaz + + * Version 1.12 released. + * main.c (getnum): Show option name and valid range if error. + 2021-01-01 Antonio Diaz Diaz * Version 1.11 released. @@ -18,7 +23,7 @@ * main.c: Document option -0 and make it use a 64 KiB dict size. * main.c (main): Check return value of close( infd ). * main.c: Compile on DOS with DJGPP. - * configure: Accept appending to CFLAGS, 'CFLAGS+=OPTIONS'. + * configure: Accept appending to CFLAGS; 'CFLAGS+=OPTIONS'. * INSTALL: Document use of CFLAGS+='-D __USE_MINGW_ANSI_STDIO'. 2018-02-04 Antonio Diaz Diaz @@ -104,7 +109,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2021 Antonio Diaz Diaz. +Copyright (C) 2010-2022 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 diff --git a/INSTALL b/INSTALL index d06e04d..131c9a7 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Requirements ------------ You will need a C99 compiler. (gcc 3.3.6 or newer is recommended). -I use gcc 6.1.0 and 4.1.2, but the code should compile with any standards +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. @@ -69,7 +69,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2021 Antonio Diaz Diaz. +Copyright (C) 2010-2022 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/LzmaEnc.h b/LzmaEnc.h index 1b18df7..b607be8 100644 --- a/LzmaEnc.h +++ b/LzmaEnc.h @@ -5,7 +5,6 @@ /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: -Returns: SZ_OK - OK SZ_ERROR_WRITE - Write callback error. */ diff --git a/Makefile.in b/Makefile.in index ec334f3..33e0a65 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20,7 +20,7 @@ objs = carg_parser.o LzFind.o LzmaEnc.o LzmaDec.o main.o all : $(progname) $(progname) : $(objs) - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(objs) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(objs) main.o : main.c $(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< diff --git a/NEWS b/NEWS index 76ecbb3..85cff1d 100644 --- a/NEWS +++ b/NEWS @@ -1,30 +1,4 @@ -Changes in version 1.11: +Changes in version 1.12: -Pdlzip now reports an error if a file name is empty (pdlzip -t ""). - -Option '-o, --output' now behaves like '-c, --stdout', but sending the -output unconditionally to a file instead of to standard output. See the new -description of '-o' in the manual. This change is backwards compatible only -when (de)compressing from standard input alone. Therefore commands like: - pdlzip -o foo.lz - bar < foo -must now be split into: - pdlzip -o foo.lz - < foo - pdlzip bar -or rewritten as: - pdlzip - bar < foo > foo.lz - -When using '-c' or '-o', pdlzip now checks whether the output is a terminal -only once. - -Pdlzip now does not even open the output file if the input file is a terminal. - -It is now an error to specify two different operations in the command line -(--decompress and --test). - -The words 'decompressed' and 'compressed' have been replaced with the -shorter 'out' and 'in' in the verbose output when decompressing or testing. - -The commands needed to extract files from a tar.lz archive have been -documented in the output of '--help' and in the man page. - -9 new test files have been added to the testsuite. +In case of error in a numerical argument to a command line option, pdlzip +now shows the name of the option and the range of valid values. diff --git a/README b/README index 1a843ab..0aa6bfd 100644 --- a/README +++ b/README @@ -2,19 +2,19 @@ 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. +licensed Free Software. The name of pdlzip comes from 'public domain lzip'. +Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. Lzip is a lossless data compressor with a user interface similar to the one of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov -chain-Algorithm' (LZMA) stream format, chosen to maximize safety and -interoperability. Lzip can compress about as fast as gzip (lzip -0) or -compress most files more than bzip2 (lzip -9). Decompression speed is -intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from -a data recovery perspective. Lzip has been designed, written, and tested -with great care to replace gzip and bzip2 as the standard general-purpose -compressed format for unix-like systems. +chain-Algorithm' (LZMA) stream format and provides a 3 factor integrity +checking to maximize interoperability and optimize safety. Lzip can compress +about as fast as gzip (lzip -0) or compress most files more than bzip2 +(lzip -9). Decompression speed is intermediate between gzip and bzip2. +Lzip is better than gzip and bzip2 from a data recovery perspective. Lzip +has been designed, written, and tested with great care to replace gzip and +bzip2 as the standard general-purpose compressed format for unix-like +systems. The lzip file format is designed for data sharing and long-term archiving, taking into account both data integrity and decoder availability: @@ -56,7 +56,7 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2021 Antonio Diaz Diaz. +Copyright (C) 2010-2022 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/carg_parser.c b/carg_parser.c index d0c05d5..181ba23 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-2021 Antonio Diaz Diaz. + Copyright (C) 2006-2022 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -32,10 +32,10 @@ static void * ap_resize_buffer( void * buf, const int min_size ) } -static char push_back_record( struct Arg_parser * const ap, - const int code, const char * const argument ) +static char push_back_record( struct Arg_parser * const ap, const int code, + const char * const long_name, + const char * const argument ) { - const int len = strlen( argument ); struct ap_Record * p; void * tmp = ap_resize_buffer( ap->data, ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); @@ -43,11 +43,29 @@ static char push_back_record( struct Arg_parser * const ap, 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 ); + 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 ) + { + const int len = strlen( argument ); + p->argument = (char *)malloc( len + 1 ); + if( !p->argument ) { free( p->parsed_name ); return 0; } + strncpy( p->argument, argument, len + 1 ); + } + else p->argument = 0; ++ap->data_size; return 1; } @@ -68,12 +86,14 @@ static char add_error( struct Arg_parser * const ap, const char * const msg ) static void free_data( struct Arg_parser * const ap ) { int i; - for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument ); + for( i = 0; i < ap->data_size; ++i ) + { free( ap->data[i].argument ); free( ap->data[i].parsed_name ); } 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( struct Arg_parser * const ap, const char * const opt, const char * const arg, const struct ap_Option options[], @@ -87,9 +107,10 @@ static char parse_long_option( struct 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].name && strncmp( options[i].name, &opt[2], len ) == 0 ) + if( options[i].long_name && + strncmp( options[i].long_name, &opt[2], len ) == 0 ) { - if( strlen( options[i].name ) == len ) /* Exact match found */ + if( strlen( options[i].long_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 || @@ -117,35 +138,39 @@ static char parse_long_option( struct Arg_parser * const ap, { if( options[index].has_arg == ap_no ) { - add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "option '--" ); add_error( ap, options[index].long_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].name ); + add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); add_error( ap, "' requires an argument" ); return 1; } - return push_back_record( ap, options[index].code, &opt[len+3] ); + return push_back_record( ap, options[index].code, + options[index].long_name, &opt[len+3] ); } if( options[index].has_arg == ap_yes ) { if( !arg || !arg[0] ) { - add_error( ap, "option '--" ); add_error( ap, options[index].name ); + 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, arg ); + return push_back_record( ap, options[index].code, + options[index].long_name, arg ); } - return push_back_record( ap, options[index].code, "" ); + return push_back_record( ap, options[index].code, + options[index].long_name, 0 ); } +/* Return 0 only if out of memory. */ static char parse_short_option( struct Arg_parser * const ap, const char * const opt, const char * const arg, const struct ap_Option options[], @@ -156,13 +181,13 @@ static char parse_short_option( struct Arg_parser * const ap, while( cind > 0 ) { int index = -1, i; - const unsigned char code = opt[cind]; + const unsigned char c = opt[cind]; char code_str[2]; - code_str[0] = code; code_str[1] = 0; + code_str[0] = c; code_str[1] = 0; - if( code != 0 ) + if( c != 0 ) for( i = 0; options[i].code; ++i ) - if( code == options[i].code ) + if( c == options[i].code ) { index = i; break; } if( index < 0 ) @@ -176,7 +201,7 @@ static char parse_short_option( struct Arg_parser * const ap, if( options[index].has_arg != ap_no && cind > 0 && opt[cind] ) { - if( !push_back_record( ap, code, &opt[cind] ) ) return 0; + if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0; ++*argindp; cind = 0; } else if( options[index].has_arg == ap_yes ) @@ -188,9 +213,9 @@ static char parse_short_option( struct Arg_parser * const ap, return 1; } ++*argindp; cind = 0; - if( !push_back_record( ap, code, arg ) ) return 0; + if( !push_back_record( ap, c, 0, arg ) ) return 0; } - else if( !push_back_record( ap, code, "" ) ) return 0; + else if( !push_back_record( ap, c, 0, 0 ) ) return 0; } return 1; } @@ -203,7 +228,7 @@ char ap_init( struct Arg_parser * const ap, const char ** non_options = 0; /* skipped non-options */ int non_options_size = 0; /* number of skipped non-options */ int argind = 1; /* index in argv */ - int i; + char done = 0; /* false until success */ ap->data = 0; ap->error = 0; @@ -223,20 +248,20 @@ char ap_init( struct Arg_parser * const ap, if( ch2 == '-' ) { if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */ - else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0; + else if( !parse_long_option( ap, opt, arg, options, &argind ) ) goto out; } - else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0; + else if( !parse_short_option( ap, opt, arg, options, &argind ) ) goto out; if( ap->error ) break; } else { if( in_order ) - { if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; } + { if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; } else { void * tmp = ap_resize_buffer( non_options, ( non_options_size + 1 ) * sizeof *non_options ); - if( !tmp ) return 0; + if( !tmp ) goto out; non_options = (const char **)tmp; non_options[non_options_size++] = argv[argind++]; } @@ -245,13 +270,15 @@ char ap_init( struct 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, non_options[i] ) ) return 0; + if( !push_back_record( ap, 0, 0, non_options[i] ) ) goto out; while( argind < argc ) - if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; + if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; } - if( non_options ) free( non_options ); - return 1; + done = 1; +out: if( non_options ) free( non_options ); + return done; } @@ -273,13 +300,20 @@ int ap_arguments( const struct Arg_parser * const ap ) int ap_code( const struct Arg_parser * const ap, const int i ) { - if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code; - else return 0; + 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 ) + { + 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 ) { - if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument; - else return ""; + 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 c5f2352..0c64861 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-2021 Antonio Diaz Diaz. + Copyright (C) 2006-2022 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -24,9 +24,9 @@ message. 'options' is an array of 'struct ap_Option' terminated by an element - containing a code which is zero. A null name means a short-only - option. A code value outside the unsigned char range means a - long-only option. + 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. Arg_parser normally makes it appear as if all the option arguments were specified before all the non-option arguments for the purposes @@ -50,7 +50,7 @@ enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; struct ap_Option { int code; /* Short option letter or code ( code != 0 ) */ - const char * name; /* Long option name (maybe null) */ + const char * long_name; /* Long option name (maybe null) */ enum ap_Has_arg has_arg; }; @@ -58,6 +58,7 @@ struct ap_Option struct ap_Record { int code; + char * parsed_name; char * argument; }; @@ -86,6 +87,9 @@ int ap_arguments( const struct Arg_parser * const ap ); Else ap_argument( i ) is the option's argument (or empty). */ 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 struct Arg_parser * const ap, const int i ); + const char * ap_argument( const struct Arg_parser * const ap, const int i ); #ifdef __cplusplus diff --git a/configure b/configure index 8baa082..2a74adb 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2021 Antonio Diaz Diaz. +# Copyright (C) 2010-2022 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute, and modify it. pkgname=pdlzip -pkgversion=1.11 +pkgversion=1.12 progname=pdlzip srctrigger=doc/${progname}.1 @@ -167,7 +167,7 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2021 Antonio Diaz Diaz. +# Copyright (C) 2010-2022 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/doc/pdlzip.1 b/doc/pdlzip.1 index 8586d88..57a144f 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16. -.TH PDLZIP "1" "January 2021" "pdlzip 1.11" "User Commands" +.TH PDLZIP "1" "January 2022" "pdlzip 1.12" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -8,19 +8,19 @@ pdlzip \- reduces the size of files .SH 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. +licensed Free Software. The name of pdlzip comes from 'public domain lzip'. +Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. .PP Lzip is a lossless data compressor with a user interface similar to the one of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov -chain\-Algorithm' (LZMA) stream format, chosen to maximize safety and -interoperability. Lzip can compress about as fast as gzip (lzip \fB\-0\fR) or -compress most files more than bzip2 (lzip \fB\-9\fR). Decompression speed is -intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from -a data recovery perspective. Lzip has been designed, written, and tested -with great care to replace gzip and bzip2 as the standard general\-purpose -compressed format for unix\-like systems. +chain\-Algorithm' (LZMA) stream format and provides a 3 factor integrity +checking to maximize interoperability and optimize safety. Lzip can compress +about as fast as gzip (lzip \fB\-0\fR) or compress most files more than bzip2 +(lzip \fB\-9\fR). Decompression speed is intermediate between gzip and bzip2. +Lzip is better than gzip and bzip2 from a data recovery perspective. Lzip +has been designed, written, and tested with great care to replace gzip and +bzip2 as the standard general\-purpose compressed format for unix\-like +systems. .PP Pdlzip is also able to decompress legacy lzma\-alone (.lzma) files. Lzma\-alone is a very bad format; it is essentially a raw LZMA stream. @@ -101,7 +101,7 @@ To extract all the files from archive 'foo.tar.lz', use the commands .PP Exit status: 0 for a normal exit, 1 for environmental problems (file not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or -invalid input file, 3 for an internal consistency error (eg, bug) which +invalid input file, 3 for an internal consistency error (e.g., bug) which caused pdlzip to panic. .PP Pdlzip includes public domain compression/decompression code from the LZMA @@ -111,7 +111,7 @@ Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2021 Antonio Diaz Diaz. +Copyright \(co 2022 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index db45f0b..eed4e1c 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2021 Antonio Diaz Diaz. + Copyright (C) 2010-2022 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -64,6 +64,7 @@ static inline void CRC32_init( void ) } } +/* about as fast as it is possible without messing with endianness */ static inline void CRC32_update_buf( uint32_t * const crc, const uint8_t * const buffer, const int size ) diff --git a/main.c b/main.c index 41933df..b0fab06 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-2021 Antonio Diaz Diaz. + Copyright (C) 2010-2022 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -21,7 +21,7 @@ Exit status: 0 for a normal exit, 1 for environmental problems (file not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or invalid input file, 3 for an internal consistency error - (eg, bug) which caused pdlzip to panic. + (e.g., bug) which caused pdlzip to panic. */ #define _FILE_OFFSET_BITS 64 @@ -38,9 +38,9 @@ #include #include #include -#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) +#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__ #include -#if defined(__MSVCRT__) +#if defined __MSVCRT__ #define fchmod(x,y) 0 #define fchown(x,y,z) 0 #define SIGHUP SIGTERM @@ -52,7 +52,7 @@ #define S_IWOTH 0 #endif #endif -#if defined(__DJGPP__) +#if defined __DJGPP__ #define S_ISSOCK(x) 0 #define S_ISVTX 0 #endif @@ -71,6 +71,11 @@ #error "Environments where CHAR_BIT != 8 are not supported." #endif +#if ( defined SIZE_MAX && SIZE_MAX < UINT_MAX ) || \ + ( defined SSIZE_MAX && SSIZE_MAX < INT_MAX ) +#error "Environments where 'size_t' is narrower than 'int' are not supported." +#endif + int verbosity = 0; static void cleanup_and_fail( const int retval ); static void show_error( const char * const msg, const int errcode, @@ -80,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 = "2021"; +static const char * const program_year = "2022"; static const char * invocation_name = "pdlzip"; /* default value */ static const struct { const char * from; const char * to; } known_extensions[] = { @@ -108,18 +113,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\n" - "lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4\n" - "or newer.\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" "\nLzip is a lossless data compressor with a user interface similar to the one\n" "of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov\n" - "chain-Algorithm' (LZMA) stream format, chosen to maximize safety and\n" - "interoperability. Lzip can compress about as fast as gzip (lzip -0) or\n" - "compress most files more than bzip2 (lzip -9). Decompression speed is\n" - "intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 from\n" - "a data recovery perspective. Lzip has been designed, written, and tested\n" - "with great care to replace gzip and bzip2 as the standard general-purpose\n" - "compressed format for unix-like systems.\n" + "chain-Algorithm' (LZMA) stream format and provides a 3 factor integrity\n" + "checking to maximize interoperability and optimize safety. Lzip can compress\n" + "about as fast as gzip (lzip -0) or compress most files more than bzip2\n" + "(lzip -9). Decompression speed is intermediate between gzip and bzip2.\n" + "Lzip is better than gzip and bzip2 from a data recovery perspective. Lzip\n" + "has been designed, written, and tested with great care to replace gzip and\n" + "bzip2 as the standard general-purpose compressed format for unix-like\n" + "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" @@ -160,7 +165,7 @@ static void show_help( void ) "'tar -xf foo.tar.lz' or 'pdlzip -cd foo.tar.lz | tar -xf -'.\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n" - "invalid input file, 3 for an internal consistency error (eg, bug) which\n" + "invalid input file, 3 for an internal consistency error (e.g., bug) which\n" "caused pdlzip to panic.\n" "\nPdlzip includes public domain compression/decompression code from the LZMA\n" "SDK (Software Development Kit) written by Igor Pavlov.\n" @@ -202,8 +207,6 @@ struct Pretty_print static void Pp_init( struct Pretty_print * const pp, const char * const filenames[], const int num_filenames ) { - unsigned stdin_name_len; - int i; pp->name = 0; pp->padded_name = 0; pp->stdin_name = "(stdin)"; @@ -211,7 +214,8 @@ static void Pp_init( struct Pretty_print * const pp, pp->first_post = false; if( verbosity <= 0 ) return; - stdin_name_len = strlen( pp->stdin_name ); + const unsigned stdin_name_len = strlen( pp->stdin_name ); + int i; for( i = 0; i < num_filenames; ++i ) { const char * const s = filenames[i]; @@ -245,16 +249,14 @@ static void Pp_reset( struct Pretty_print * const pp ) static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) { - if( verbosity >= 0 ) + if( verbosity < 0 ) return; + if( pp->first_post ) { - if( pp->first_post ) - { - pp->first_post = false; - fputs( pp->padded_name, stderr ); - if( !msg ) fflush( stderr ); - } - if( msg ) fprintf( stderr, "%s\n", msg ); + pp->first_post = false; + fputs( pp->padded_name, stderr ); + if( !msg ) fflush( stderr ); } + if( msg ) fprintf( stderr, "%s\n", msg ); } @@ -275,17 +277,53 @@ static void show_header( const unsigned dictionary_size ) } -static unsigned long getnum( const char * const ptr, +/* separate large numbers >= 100_000 in groups of 3 digits using '_' */ +static const char * format_num3( unsigned long long num ) + { + const char * const si_prefix = "kMGTPEZY"; + const char * const binary_prefix = "KMGTPEZY"; + enum { buffers = 8, bufsize = 4 * sizeof (long long) }; + 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 > 1024 ) + { + char prefix = 0; /* try binary first, then si */ + for( i = 0; i < 8 && num >= 1024 && num % 1024 == 0; ++i ) + { num /= 1024; prefix = binary_prefix[i]; } + if( prefix ) *(--p) = 'i'; + else + for( i = 0; i < 8 && num >= 1000 && num % 1000 == 0; ++i ) + { num /= 1000; prefix = si_prefix[i]; } + if( prefix ) *(--p) = prefix; + } + const bool split = num >= 100000; + + for( i = 0; ; ) + { + *(--p) = num % 10 + '0'; num /= 10; if( num == 0 ) break; + if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; } + } + return p; + } + + +static unsigned long getnum( const char * const arg, + const char * const option_name, const unsigned long llimit, const unsigned long ulimit ) { - unsigned long result; char * tail; errno = 0; - result = strtoul( ptr, &tail, 0 ); - if( tail == ptr ) + unsigned long result = strtoul( arg, &tail, 0 ); + if( tail == arg ) { - show_error( "Bad or missing numerical argument.", 0, true ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: Bad or missing numerical argument in " + "option '%s'.\n", program_name, option_name ); exit( 1 ); } @@ -308,7 +346,9 @@ static unsigned long getnum( const char * const ptr, } if( exponent <= 0 ) { - show_error( "Bad multiplier in numerical argument.", 0, true ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: Bad multiplier in numerical argument of " + "option '%s'.\n", program_name, option_name ); exit( 1 ); } for( i = 0; i < exponent; ++i ) @@ -320,21 +360,24 @@ static unsigned long getnum( const char * const ptr, if( !errno && ( result < llimit || result > ulimit ) ) errno = ERANGE; if( errno ) { - show_error( "Numerical argument out of limits.", 0, false ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: Numerical argument out of limits [%s,%s] " + "in option '%s'.\n", program_name, format_num3( llimit ), + format_num3( ulimit ), option_name ); exit( 1 ); } return result; } -static int get_dict_size( const char * const arg ) +static int get_dict_size( const char * const arg, const char * const option_name ) { char * tail; const long bits = strtol( arg, &tail, 0 ); if( bits >= min_dictionary_bits && bits <= max_dictionary_bits_c && *tail == 0 ) return 1 << bits; - return getnum( arg, min_dictionary_size, max_dictionary_size_c ); + return getnum( arg, option_name, min_dictionary_size, max_dictionary_size_c ); } @@ -408,34 +451,31 @@ static int open_instream( const char * const name, struct stat * const in_statsp const enum Mode program_mode, const int eindex, const bool one_to_one, const bool recompress ) { - int infd = -1; if( program_mode == m_compress && !recompress && eindex >= 0 ) { if( verbosity >= 0 ) fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", program_name, name, known_extensions[eindex].from ); + return -1; } + int infd = open( name, O_RDONLY | O_BINARY ); + if( infd < 0 ) + show_file_error( name, "Can't open input file", errno ); else { - infd = open( name, O_RDONLY | O_BINARY ); - if( infd < 0 ) - show_file_error( name, "Can't open input file", errno ); - else + 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 ) ) ); + if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) ) { - 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 ) ) ); - if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) ) - { - if( verbosity >= 0 ) - fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", - program_name, name, ( can_read && one_to_one ) ? - ",\n and neither '-c' nor '-o' were specified" : "" ); - close( infd ); - infd = -1; - } + if( verbosity >= 0 ) + fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", + program_name, name, ( can_read && one_to_one ) ? + ",\n and neither '-c' nor '-o' were specified" : "" ); + close( infd ); + infd = -1; } } return infd; @@ -505,7 +545,7 @@ static bool check_tty_in( const char * const input_filename, const int infd, isatty( infd ) ) /* for example /dev/tty */ { show_file_error( input_filename, "I won't read compressed data from a terminal.", 0 ); - close( infd ); set_retval( retval, 1 ); + close( infd ); set_retval( retval, 2 ); if( program_mode != m_test ) cleanup_and_fail( *retval ); return false; } return true; @@ -814,12 +854,12 @@ static int decompress( const int infd, struct Pretty_print * const pp, for( first_member = true; ; first_member = false ) { - int i, size; + int i; unsigned dictionary_size = 0; /* keep gcc 3.3.6 happy */ Lzip_header header; if( inSize - inPos < lzma_header_size && !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; - size = inSize - inPos; + const int size = inSize - inPos; for( i = 0; i < size && i < Lh_size; ++i ) raw_props[i] = header[i] = inBuf[inPos++]; if( size <= Lh_size ) /* End Of File */ @@ -869,7 +909,6 @@ static int decompress( const int infd, struct Pretty_print * const pp, } if( lzip_mode ) { - int ds, i; if( !Lh_verify_version( header ) ) { if( verbosity >= 0 ) @@ -884,7 +923,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, retval = 2; break; } raw_props[0] = 93; /* (45 * 2) + (9 * 0) + 3 */ - ds = dictionary_size; + int ds = dictionary_size; for( i = 1; i <= 4; ++i ) { raw_props[i] = ds & 0xFF; ds >>= 8; } } @@ -913,8 +952,8 @@ static int decompress( const int infd, struct Pretty_print * const pp, CRC32 crc32; -/* Returns the number of bytes really read. - If (returned value < size) and (errno == 0), means EOF was reached. +/* Return the number of bytes really read. + If (value returned < size) and (errno == 0), means EOF was reached. */ int readblock( const int fd, uint8_t * const buf, const int size ) { @@ -932,8 +971,8 @@ int readblock( const int fd, uint8_t * const buf, const int size ) } -/* Returns the number of bytes really written. - If (returned value < size), it is always an error. +/* Return the number of bytes really written. + If (value returned < size), it is always an error. */ int writeblock( const int fd, const uint8_t * const buf, const int size ) { @@ -1000,23 +1039,15 @@ int main( const int argc, const char * const argv[] ) { 1 << 25, 273 } }; /* -9 */ struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ const char * default_output_filename = ""; - static struct Arg_parser parser; /* static because valgrind complains */ - static struct Pretty_print pp; /* and memory management in C sucks */ - static const char ** filenames = 0; - int num_filenames = 0; enum Mode program_mode = m_compress; - int argind = 0; - int failed_tests = 0; - int retval = 0; int i; - bool filenames_given = false; bool force = false; bool ignore_trailing = true; bool keep_input_files = false; bool loose_trailing = false; bool recompress = false; - bool stdin_used = false; bool to_stdout = false; + if( argc > 0 ) invocation_name = argv[0]; enum { opt_lt = 256 }; const struct ap_Option options[] = @@ -1051,19 +1082,22 @@ int main( const int argc, const char * const argv[] ) { opt_lt, "loose-trailing", ap_no }, { 0, 0, ap_no } }; - if( argc > 0 ) invocation_name = argv[0]; CRC32_init(); + /* static because valgrind complains and memory management in C sucks */ + static struct 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 */ { 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 ); - const char * const arg = ap_argument( &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 ); switch( code ) { case '0': case '1': case '2': case '3': case '4': @@ -1078,12 +1112,12 @@ int main( const int argc, const char * const argv[] ) case 'h': show_help(); return 0; case 'k': keep_input_files = true; break; case 'm': encoder_options.match_len_limit = - getnum( arg, min_match_len_limit, max_match_len ); break; + getnum( arg, pn, min_match_len_limit, max_match_len ); break; case 'n': break; case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true; else { default_output_filename = arg; } break; case 'q': verbosity = -1; break; - case 's': encoder_options.dictionary_size = get_dict_size( arg ); + case 's': encoder_options.dictionary_size = get_dict_size( arg, pn ); break; case 'S': break; case 't': set_mode( &program_mode, m_test ); break; @@ -1094,15 +1128,17 @@ int main( const int argc, const char * const argv[] ) } } /* end process options */ -#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) +#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__ setmode( STDIN_FILENO, O_BINARY ); setmode( STDOUT_FILENO, O_BINARY ); #endif - num_filenames = max( 1, ap_arguments( &parser ) - argind ); + static const char ** filenames = 0; + int num_filenames = max( 1, ap_arguments( &parser ) - argind ); filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); filenames[0] = "-"; + bool filenames_given = false; for( i = 0; argind + i < ap_arguments( &parser ); ++i ) { filenames[i] = ap_argument( &parser, argind + i ); @@ -1123,16 +1159,18 @@ 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; 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; for( i = 0; i < num_filenames; ++i ) { const char * input_filename = ""; int infd; - int tmp; struct stat in_stats; - const struct stat * in_statsp; Pp_set_name( &pp, filenames[i] ); if( strcmp( filenames[i], "-" ) == 0 ) @@ -1174,7 +1212,9 @@ int main( const int argc, const char * const argv[] ) return 1; /* check tty only once and don't try to delete a tty */ } - in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0; + const struct stat * const in_statsp = + ( input_filename[0] && one_to_one ) ? &in_stats : 0; + int tmp; if( program_mode == m_compress ) tmp = compress( &encoder_options, &pp, infd ); else diff --git a/testsuite/check.sh b/testsuite/check.sh index 80de80c..c2e22a7 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-2021 Antonio Diaz Diaz. +# Copyright (C) 2010-2022 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute, and modify it. @@ -92,6 +92,7 @@ done printf "LZIP\001-.............................." | "${LZIP}" -t 2> /dev/null printf "LZIP\002-.............................." | "${LZIP}" -t 2> /dev/null printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null +rm -f out || framework_failure printf "\ntesting decompression..." @@ -111,19 +112,23 @@ done lines=$("${LZIP}" -tvv "${in_em}" 2>&1 | wc -l) || test_failed $LINENO [ "${lines}" -eq 8 ] || test_failed $LINENO "${lines}" +"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO 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 +cat fox > copy || framework_failure +cat "${in_lz}" > out.lz || framework_failure +rm -f out || framework_failure +"${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out [ $? = 1 ] || 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 out || framework_failure printf "to be overwritten" > copy || framework_failure -"${LZIP}" -d -o copy < "${in_lz}" 2> /dev/null -[ $? = 1 ] || test_failed $LINENO "${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO cmp in copy || test_failed $LINENO rm -f out copy || framework_failure @@ -147,7 +152,7 @@ rm -f copy anyothername.out || framework_failure [ $? = 1 ] || test_failed $LINENO "${LZIP}" -cdq in "${in_lz}" > copy [ $? = 2 ] || test_failed $LINENO -cat copy in | cmp in - || test_failed $LINENO +cat copy in | cmp in - || test_failed $LINENO # copy must be empty "${LZIP}" -cdq nx_file.lz "${in_lz}" > copy [ $? = 1 ] || test_failed $LINENO cmp in copy || test_failed $LINENO @@ -295,7 +300,6 @@ for i in fox_v2.lz fox_s11.lz fox_de20.lz \ [ $? = 2 ] || test_failed $LINENO $i done -"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do "${LZIP}" -cdq "${testdir}"/$i > out [ $? = 2 ] || test_failed $LINENO $i From 5bc01b13394a2f667130b2063e373751730c05ec Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:27:37 +0100 Subject: [PATCH 07/10] Adding upstream version 1.13~rc1. Signed-off-by: Daniel Baumann --- ChangeLog | 11 ++- INSTALL | 17 +++-- Makefile.in | 7 +- NEWS | 14 +++- README | 19 ++--- carg_parser.c | 4 +- carg_parser.h | 4 +- configure | 25 ++++--- doc/pdlzip.1 | 47 ++++++------ lzip.h | 34 ++++----- main.c | 177 ++++++++++++++++++++++---------------------- testsuite/check.sh | 180 ++++++++++++++++++++++++--------------------- 12 files changed, 289 insertions(+), 250 deletions(-) diff --git a/ChangeLog b/ChangeLog index fe563fc..5d52edb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2023-12-21 Antonio Diaz Diaz + + * Version 1.13-rc1 released. + * main.c: Reformat file diagnostics as 'PROGRAM: FILE: MESSAGE'. + (show_option_error): New function showing argument and option name. + * lzip.h: Rename verify_* to check_*. + * configure, Makefile.in: New variable 'MAKEINFO'. + * INSTALL: Document use of CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500'. + 2022-01-21 Antonio Diaz Diaz * Version 1.12 released. @@ -109,7 +118,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2022 Antonio Diaz Diaz. +Copyright (C) 2010-2023 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 diff --git a/INSTALL b/INSTALL index 131c9a7..594420c 100644 --- a/INSTALL +++ b/INSTALL @@ -18,8 +18,8 @@ Procedure or lzip -cd pdlzip[version].tar.lz | tar -xf - -This creates the directory ./pdlzip[version] containing the source from -the main archive. +This creates the directory ./pdlzip[version] containing the source code +extracted from the archive. 2. Change to pdlzip directory and run configure. (Try 'configure --help' for usage instructions). @@ -27,6 +27,10 @@ the main archive. cd pdlzip[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' @@ -38,7 +42,8 @@ the main archive. 4. Optionally, type 'make check' to run the tests that come with pdlzip. 5. Type 'make install' to install the program and any data files and - documentation. + documentation. You need root privileges to install into a prefix owned + by root. Or type 'make install-compress', which additionally compresses the man page after installation. @@ -61,15 +66,15 @@ object files and executables to go and run the 'configure' script. '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 sources. Usually 'configure' can determine that directory +'configure' recognizes the option '--srcdir=DIR' to control where to look +for the source code. Usually 'configure' can determine that directory automatically. After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2022 Antonio Diaz Diaz. +Copyright (C) 2010-2023 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/Makefile.in b/Makefile.in index 33e0a65..4b8c791 100644 --- a/Makefile.in +++ b/Makefile.in @@ -28,6 +28,10 @@ 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 : ; +%.h %.c : ; + $(objs) : Makefile carg_parser.o : carg_parser.h LzmaDec.o : lzip.h LzmaDec.h @@ -35,13 +39,12 @@ LzFind.o : lzip.h LzFind.h LzmaEnc.o : lzip.h LzFind.h LzmaEnc.h main.o : carg_parser.h lzip.h LzmaDec.h LzmaEnc.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 diff --git a/NEWS b/NEWS index 85cff1d..5415fd8 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,12 @@ -Changes in version 1.12: +Changes in version 1.13: -In case of error in a numerical argument to a command line option, pdlzip -now shows the name of the option and the range of valid values. +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' diff --git a/README b/README index 0aa6bfd..14f73b7 100644 --- a/README +++ b/README @@ -7,14 +7,15 @@ Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. Lzip is a lossless data compressor with a user interface similar to the one of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov -chain-Algorithm' (LZMA) stream format and provides a 3 factor integrity -checking to maximize interoperability and optimize safety. 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. +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. The lzip file format is designed for data sharing and long-term archiving, taking into account both data integrity and decoder availability: @@ -56,7 +57,7 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2022 Antonio Diaz Diaz. +Copyright (C) 2010-2023 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/carg_parser.c b/carg_parser.c index 181ba23..8882b97 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-2022 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command-line argument parser. (C version) + Copyright (C) 2006-2023 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/carg_parser.h b/carg_parser.h index 0c64861..ec5d3d0 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-2022 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command-line argument parser. (C version) + Copyright (C) 2006-2023 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/configure b/configure index 2a74adb..1f8c60f 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2022 Antonio Diaz Diaz. +# Copyright (C) 2010-2023 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute, and modify it. pkgname=pdlzip -pkgversion=1.12 +pkgversion=1.13-rc1 progname=pdlzip srctrigger=doc/${progname}.1 @@ -24,6 +24,7 @@ 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 ; } @@ -57,7 +58,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 sources in DIR [. or ..]" + echo " --srcdir=DIR find the source code 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}]" @@ -65,10 +66,11 @@ 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 " 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 " LDFLAGS=OPTIONS command-line options for the linker [${LDFLAGS}]" + echo " MAKEINFO=NAME makeinfo program to use [${MAKEINFO}]" echo exit 0 ;; --version | -V) @@ -96,6 +98,7 @@ while [ $# != 0 ] ; do CFLAGS=*) CFLAGS=${optarg} ;; CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;; LDFLAGS=*) LDFLAGS=${optarg} ;; + MAKEINFO=*) MAKEINFO=${optarg} ;; --*) echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;; @@ -115,7 +118,7 @@ while [ $# != 0 ] ; do fi done -# Find the source files, if location was not specified. +# Find the source code, if location was not specified. srcdirtext= if [ -z "${srcdir}" ] ; then srcdirtext="or . or .." ; srcdir=. @@ -127,7 +130,7 @@ if [ -z "${srcdir}" ] ; then fi if [ ! -r "${srcdir}/${srctrigger}" ] ; then - echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" 1>&2 + echo "configure: Can't find source code in ${srcdir} ${srcdirtext}" 1>&2 echo "configure: (At least ${srctrigger} is missing)." 1>&2 exit 1 fi @@ -147,7 +150,7 @@ if [ -z "${no_create}" ] ; then # This script is free software: you have unlimited permission # 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 @@ -164,10 +167,11 @@ echo "CC = ${CC}" echo "CPPFLAGS = ${CPPFLAGS}" echo "CFLAGS = ${CFLAGS}" echo "LDFLAGS = ${LDFLAGS}" +echo "MAKEINFO = ${MAKEINFO}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2022 Antonio Diaz Diaz. +# Copyright (C) 2010-2023 Antonio Diaz Diaz. # This file was generated automatically by configure. Don't edit. # # This Makefile is free software: you have unlimited permission @@ -187,6 +191,7 @@ CC = ${CC} CPPFLAGS = ${CPPFLAGS} CFLAGS = ${CFLAGS} LDFLAGS = ${LDFLAGS} +MAKEINFO = ${MAKEINFO} EOF cat "${srcdir}/Makefile.in" >> Makefile diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index 57a144f..0e3e384 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16. -.TH PDLZIP "1" "January 2022" "pdlzip 1.12" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH PDLZIP "1" "December 2023" "pdlzip 1.13-rc1" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -13,14 +13,15 @@ Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer. .PP Lzip is a lossless data compressor with a user interface similar to the one of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov -chain\-Algorithm' (LZMA) stream format and provides a 3 factor integrity -checking to maximize interoperability and optimize safety. 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. +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. .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. @@ -42,7 +43,7 @@ exit with error status if trailing data write to standard output, keep input files .TP \fB\-d\fR, \fB\-\-decompress\fR -decompress +decompress, test compressed file integrity .TP \fB\-f\fR, \fB\-\-force\fR overwrite existing output files @@ -87,22 +88,22 @@ If no file names are given, or if a file is '\-', pdlzip compresses or decompresses 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... -Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12 -to 2^27 bytes. +Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12 to +2^27 bytes. .PP -The bidimensional parameter space of LZMA can't be mapped to a linear -scale optimal for all files. If your files are large, very repetitive, -etc, you may need to use the options \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR -directly to achieve optimal performance. For example, \fB\-9m64\fR usually -compresses executables more (and faster) than \fB\-9\fR. +The bidimensional parameter space of LZMA can't be mapped to a linear scale +optimal for all files. If your files are large, very repetitive, etc, you +may need to use the options \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR directly +to achieve optimal performance. For example, \fB\-9m64\fR usually compresses +executables more (and faster) than \fB\-9\fR. .PP To extract all the files from archive 'foo.tar.lz', use the commands \&'tar \fB\-xf\fR foo.tar.lz' or 'pdlzip \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'. .PP -Exit status: 0 for a normal exit, 1 for environmental problems (file -not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or -invalid input file, 3 for an internal consistency error (e.g., bug) which -caused pdlzip to panic. +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 pdlzip to panic. .PP Pdlzip includes public domain compression/decompression code from the LZMA SDK (Software Development Kit) written by Igor Pavlov. @@ -111,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 2022 Antonio Diaz Diaz. +Copyright \(co 2023 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index eed4e1c..7e7805a 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2022 Antonio Diaz Diaz. + Copyright (C) 2010-2023 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -78,8 +78,8 @@ static inline void CRC32_update_buf( uint32_t * const crc, static inline bool isvalid_ds( const unsigned dictionary_size ) - { return ( dictionary_size >= min_dictionary_size && - dictionary_size <= max_dictionary_size ); } + { return dictionary_size >= min_dictionary_size && + dictionary_size <= max_dictionary_size; } static inline int real_bits( unsigned value ) @@ -92,43 +92,43 @@ static inline int real_bits( unsigned value ) static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ -typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */ +enum { Lh_size = 6 }; +typedef uint8_t Lzip_header[Lh_size]; /* 0-3 magic bytes */ /* 4 version */ /* 5 coded dictionary size */ -enum { Lh_size = 6 }; static inline void Lh_set_magic( Lzip_header data ) { memcpy( data, lzip_magic, 4 ); data[4] = 1; } -static inline bool Lh_verify_magic( const Lzip_header data ) - { return ( memcmp( data, lzip_magic, 4 ) == 0 ); } +static inline bool Lh_check_magic( const Lzip_header data ) + { return memcmp( data, lzip_magic, 4 ) == 0; } /* detect (truncated) header */ -static inline bool Lh_verify_prefix( const Lzip_header data, const int sz ) +static inline bool Lh_check_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_verify_corrupt( const Lzip_header data ) +static inline bool Lh_check_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 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 bool Lh_check_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 ) ); + unsigned sz = 1 << ( data[5] & 0x1F ); if( sz > min_dictionary_size ) sz -= ( sz / 16 ) * ( ( data[5] >> 5 ) & 7 ); return sz; @@ -145,17 +145,17 @@ static inline bool Lh_set_dictionary_size( Lzip_header data, const unsigned sz ) unsigned i; for( i = 7; i >= 1; --i ) if( base_size - ( i * fraction ) >= sz ) - { data[5] |= ( i << 5 ); break; } + { data[5] |= i << 5; break; } } return true; } -typedef uint8_t Lzip_trailer[20]; +enum { Lt_size = 20 }; +typedef uint8_t Lzip_trailer[Lt_size]; /* 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 ) { diff --git a/main.c b/main.c index b0fab06..0d3b659 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-2022 Antonio Diaz Diaz. + Copyright (C) 2010-2023 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -19,19 +19,19 @@ */ /* 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 - (e.g., bug) which caused pdlzip to panic. + (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 pdlzip to panic. */ #define _FILE_OFFSET_BITS 64 #include #include -#include +#include /* SSIZE_MAX */ #include #include -#include +#include /* SIZE_MAX */ #include #include #include @@ -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 = "2022"; +static const char * const program_year = "2023"; static const char * invocation_name = "pdlzip"; /* default value */ static const struct { const char * from; const char * to; } known_extensions[] = { @@ -117,14 +117,15 @@ static void show_help( void ) "Pdlzip is written in C and is (hope)fully compatible with lzip 1.4 or newer.\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 and provides a 3 factor integrity\n" - "checking to maximize interoperability and optimize safety. Lzip can compress\n" - "about as fast as gzip (lzip -0) or compress most files more than bzip2\n" - "(lzip -9). Decompression speed is intermediate between gzip and bzip2.\n" - "Lzip is better than gzip and bzip2 from a data recovery perspective. Lzip\n" - "has been designed, written, and tested with great care to replace gzip and\n" - "bzip2 as the standard general-purpose compressed format for unix-like\n" - "systems.\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" "\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" @@ -136,7 +137,7 @@ static void show_help( void ) " -V, --version output version information and exit\n" " -a, --trailing-error exit with error status if trailing data\n" " -c, --stdout write to standard output, keep input files\n" - " -d, --decompress decompress\n" + " -d, --decompress decompress, test compressed file integrity\n" " -f, --force overwrite existing output files\n" " -F, --recompress force re-compression of compressed files\n" " -k, --keep keep (don't delete) input files\n" @@ -154,19 +155,19 @@ static void show_help( void ) "decompresses from standard input to standard output.\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" - "Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12\n" - "to 2^27 bytes.\n" - "\nThe bidimensional parameter space of LZMA can't be mapped to a linear\n" - "scale optimal for all files. If your files are large, very repetitive,\n" - "etc, you may need to use the options --dictionary-size and --match-length\n" - "directly to achieve optimal performance. For example, -9m64 usually\n" - "compresses executables more (and faster) than -9.\n" + "Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12 to\n" + "2^27 bytes.\n" + "\nThe bidimensional parameter space of LZMA can't be mapped to a linear scale\n" + "optimal for all files. If your files are large, very repetitive, etc, you\n" + "may need to use the options --dictionary-size and --match-length directly\n" + "to achieve optimal performance. For example, -9m64 usually compresses\n" + "executables more (and faster) than -9.\n" "\nTo extract all the files from archive 'foo.tar.lz', use the commands\n" "'tar -xf foo.tar.lz' or 'pdlzip -cd foo.tar.lz | tar -xf -'.\n" - "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" - "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n" - "invalid input file, 3 for an internal consistency error (e.g., bug) which\n" - "caused pdlzip to panic.\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 pdlzip to panic.\n" "\nPdlzip includes public domain compression/decompression code from the LZMA\n" "SDK (Software Development Kit) written by Igor Pavlov.\n" "\nReport bugs to lzip-bug@nongnu.org\n" @@ -262,27 +263,26 @@ static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg static void show_header( const unsigned dictionary_size ) { - enum { factor = 1024 }; - const char * const prefix[8] = - { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; + enum { factor = 1024, n = 3 }; + const char * const prefix[n] = { "Ki", "Mi", "Gi" }; const char * p = ""; const char * np = " "; unsigned num = dictionary_size; bool exact = ( num % factor == 0 ); - int i; for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) + int i; for( i = 0; i < n && ( num > 9999 || ( exact && num >= factor ) ); ++i ) { num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; np = ""; } fprintf( stderr, "dict %s%4u %sB, ", np, num, p ); } -/* separate large numbers >= 100_000 in groups of 3 digits using '_' */ +/* separate numbers of 5 or more digits in groups of 3 digits using '_' */ static const char * format_num3( unsigned long long num ) { - const char * const si_prefix = "kMGTPEZY"; - const char * const binary_prefix = "KMGTPEZY"; - enum { buffers = 8, bufsize = 4 * sizeof (long long) }; + 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; @@ -292,15 +292,15 @@ static const char * format_num3( unsigned long long num ) if( num > 1024 ) { char prefix = 0; /* try binary first, then si */ - for( i = 0; i < 8 && num >= 1024 && num % 1024 == 0; ++i ) + 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 < 8 && num >= 1000 && num % 1000 == 0; ++i ) + 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 >= 100000; + const bool split = num >= 10000; for( i = 0; ; ) { @@ -311,6 +311,16 @@ static const char * format_num3( unsigned long long num ) } +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: k, Ki, [MGTPEZYRQ][i] */ static unsigned long getnum( const char * const arg, const char * const option_name, const unsigned long llimit, @@ -320,12 +330,8 @@ static unsigned long getnum( const char * const arg, errno = 0; unsigned long result = strtoul( arg, &tail, 0 ); if( tail == arg ) - { - if( verbosity >= 0 ) - fprintf( stderr, "%s: Bad or missing numerical argument in " - "option '%s'.\n", program_name, option_name ); - exit( 1 ); - } + { show_option_error( arg, "Bad or missing numerical argument in", + option_name ); exit( 1 ); } if( !errno && tail[0] ) { @@ -334,6 +340,8 @@ 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; @@ -345,12 +353,8 @@ static unsigned long getnum( const char * const arg, case 'k': if( factor == 1000 ) exponent = 1; break; } if( exponent <= 0 ) - { - if( verbosity >= 0 ) - fprintf( stderr, "%s: Bad multiplier in numerical argument of " - "option '%s'.\n", program_name, option_name ); - exit( 1 ); - } + { show_option_error( arg, "Bad multiplier in numerical argument of", + option_name ); exit( 1 ); } for( i = 0; i < exponent; ++i ) { if( ulimit / factor >= result ) result *= factor; @@ -361,8 +365,8 @@ static unsigned long getnum( const char * const arg, if( errno ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: Numerical argument out of limits [%s,%s] " - "in option '%s'.\n", program_name, format_num3( llimit ), + 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 ); exit( 1 ); } @@ -442,7 +446,7 @@ 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: Can't guess original name for '%s' -- using '%s'\n", + fprintf( stderr, "%s: %s: Can't guess original name -- using '%s'\n", program_name, name, output_filename ); } @@ -454,7 +458,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp if( program_mode == m_compress && !recompress && eindex >= 0 ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", + fprintf( stderr, "%s: %s: Input file already has '%s' suffix.\n", program_name, name, known_extensions[eindex].from ); return -1; } @@ -471,9 +475,9 @@ static int open_instream( const char * const name, struct stat * const in_statsp if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", + 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" : "" ); + ",\n and neither '-c' nor '-o' were specified" : "" ); close( infd ); infd = -1; } @@ -492,16 +496,12 @@ static bool open_outstream( const bool force, const bool protect ) outfd = open( output_filename, flags, outfd_mode ); if( outfd >= 0 ) delete_output_on_interrupt = true; - else if( verbosity >= 0 ) - { - if( errno == EEXIST ) - fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n", - program_name, output_filename ); - else - fprintf( stderr, "%s: Can't create output file '%s': %s\n", - program_name, output_filename, strerror( errno ) ); - } - return ( outfd >= 0 ); + else if( errno == EEXIST ) + show_file_error( output_filename, + "Output file already exists, skipping.", 0 ); + else + show_file_error( output_filename, "Can't create output file", errno ); + return outfd >= 0; } @@ -519,12 +519,10 @@ static void cleanup_and_fail( const int retval ) if( delete_output_on_interrupt ) { delete_output_on_interrupt = false; - if( verbosity >= 0 ) - fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n", - program_name, output_filename ); + show_file_error( output_filename, "Deleting output file, if it exists.", 0 ); if( outfd >= 0 ) { close( outfd ); outfd = -1; } if( remove( output_filename ) != 0 && errno != ENOENT ) - show_error( "WARNING: deletion of output file (apparently) failed.", 0, false ); + show_error( "warning: deletion of output file failed", errno, false ); } exit( retval ); } @@ -578,10 +576,8 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) warning = true; } if( close( outfd ) != 0 ) - { - show_error( "Error closing output file", errno, false ); - cleanup_and_fail( 1 ); - } + { show_file_error( output_filename, "Error closing output file", errno ); + cleanup_and_fail( 1 ); } outfd = -1; delete_output_on_interrupt = false; if( in_statsp ) @@ -592,12 +588,13 @@ 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_error( "Can't change output file attributes.", 0, false ); + show_file_error( output_filename, + "warning: can't change output file attributes", errno ); } -static int compress( const struct Lzma_options * const encoder_options, - struct Pretty_print * const pp, const int infd ) +static int compress( const int infd, const struct Lzma_options * const + encoder_options, struct Pretty_print * const pp ) { int retval = 0; CLzmaEncHandle encoder = 0; @@ -855,7 +852,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, for( first_member = true; ; first_member = false ) { int i; - unsigned dictionary_size = 0; /* keep gcc 3.3.6 happy */ + unsigned dictionary_size = 0; /* keep gcc 3.3.6 quiet */ Lzip_header header; if( inSize - inPos < lzma_header_size && !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; @@ -867,18 +864,18 @@ static int decompress( const int infd, struct Pretty_print * const pp, if( first_member ) { show_file_error( pp->name, "File ends unexpectedly at member header.", 0 ); retval = 2; } - else if( Lh_verify_prefix( header, size ) ) + else if( Lh_check_prefix( header, size ) ) { Pp_show_msg( pp, "Truncated header in multimember file." ); retval = 2; } else if( size > 0 && !ignore_trailing ) { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } - if( !Lh_verify_magic( header ) ) + if( !Lh_check_magic( header ) ) { if( !first_member ) { - if( !loose_trailing && Lh_verify_corrupt( header ) ) + if( !loose_trailing && Lh_check_corrupt( header ) ) { Pp_show_msg( pp, "Corrupt header in multimember file." ); retval = 2; } else if( !ignore_trailing ) @@ -909,7 +906,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, } if( lzip_mode ) { - if( !Lh_verify_version( header ) ) + if( !Lh_check_version( header ) ) { if( verbosity >= 0 ) { Pp_show_msg( pp, 0 ); @@ -1023,8 +1020,8 @@ static void internal_error( const char * const msg ) int main( const int argc, const char * const argv[] ) { - /* Mapping from gzip/bzip2 style 1..9 compression modes - to the corresponding LZMA compression modes. */ + /* Mapping from gzip/bzip2 style 0..9 compression levels to the + corresponding LZMA compression parameters. */ const struct Lzma_options option_mapping[] = { { 1 << 16, 5 }, /* -0 */ @@ -1124,7 +1121,7 @@ int main( const int argc, const char * const argv[] ) case 'v': if( verbosity < 4 ) ++verbosity; break; case 'V': show_version(); return 0; case opt_lt: loose_trailing = true; break; - default : internal_error( "uncaught option." ); + default: internal_error( "uncaught option." ); } } /* end process options */ @@ -1187,7 +1184,7 @@ int main( const int argc, const char * const argv[] ) eindex, one_to_one, recompress ); if( infd < 0 ) { set_retval( &retval, 1 ); continue; } if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue; - if( one_to_one ) /* open outfd after verifying infd */ + if( one_to_one ) /* open outfd after checking infd */ { if( program_mode == m_compress ) set_c_outname( input_filename, true, true ); @@ -1200,7 +1197,7 @@ int main( const int argc, const char * const argv[] ) if( one_to_one && !check_tty_out( program_mode ) ) { set_retval( &retval, 1 ); return retval; } /* don't delete a tty */ - if( to_file && outfd < 0 ) /* open outfd after verifying infd */ + if( to_file && outfd < 0 ) /* open outfd after checking infd */ { if( program_mode == m_compress ) set_c_outname( default_output_filename, filenames_given, false ); @@ -1216,10 +1213,10 @@ int main( const int argc, const char * const argv[] ) ( input_filename[0] && one_to_one ) ? &in_stats : 0; int tmp; if( program_mode == m_compress ) - tmp = compress( &encoder_options, &pp, infd ); + tmp = compress( infd, &encoder_options, &pp ); else - tmp = decompress( infd, &pp, ignore_trailing, - loose_trailing, program_mode == m_test ); + tmp = decompress( infd, &pp, ignore_trailing, loose_trailing, + program_mode == m_test ); if( close( infd ) != 0 ) { show_file_error( pp.name, "Error closing input file", errno ); set_retval( &tmp, 1 ); } diff --git a/testsuite/check.sh b/testsuite/check.sh index c2e22a7..8c18a1c 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-2022 Antonio Diaz Diaz. +# Copyright (C) 2010-2023 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute, and modify it. @@ -67,7 +67,7 @@ done [ $? = 1 ] || test_failed $LINENO [ ! -e out.lz ] || test_failed $LINENO # these are for code coverage -"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null +"${LZIP}" -cdt "${in_lz}" 2> /dev/null [ $? = 1 ] || test_failed $LINENO "${LZIP}" -t -- nx_file.lz 2> /dev/null [ $? = 1 ] || test_failed $LINENO @@ -92,46 +92,46 @@ done printf "LZIP\001-.............................." | "${LZIP}" -t 2> /dev/null printf "LZIP\002-.............................." | "${LZIP}" -t 2> /dev/null printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null -rm -f out || framework_failure printf "\ntesting decompression..." for i in "${in_lz}" "${in_em}" "${testdir}"/test.txt.lzma ; do "${LZIP}" -t "$i" || test_failed $LINENO "$i" - "${LZIP}" -d "$i" -o copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - "${LZIP}" -cd "$i" > copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - "${LZIP}" -d "$i" -o - > copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - "${LZIP}" -d < "$i" > copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - rm -f copy || framework_failure + "${LZIP}" -d "$i" -o out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + "${LZIP}" -cd "$i" > out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + "${LZIP}" -d "$i" -o - > out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + "${LZIP}" -d < "$i" > out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + rm -f out || framework_failure done -lines=$("${LZIP}" -tvv "${in_em}" 2>&1 | wc -l) || test_failed $LINENO +lines=`"${LZIP}" -tvv "${in_em}" 2>&1 | wc -l` || test_failed $LINENO [ "${lines}" -eq 8 ] || test_failed $LINENO "${lines}" -"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO -cat "${in_lz}" > copy.lz || framework_failure -"${LZIP}" -dk copy.lz || test_failed $LINENO -cmp in copy || test_failed $LINENO -cat fox > copy || framework_failure cat "${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 "${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out [ $? = 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 out || framework_failure +rm -f copy out || framework_failure -printf "to be overwritten" > copy || framework_failure -"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f out copy || framework_failure +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 @@ -140,75 +140,85 @@ cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure cat "${in_lz}" > anyothername || framework_failure -"${LZIP}" -dv - anyothername - < "${in_lz}" > copy 2> /dev/null || +"${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null || test_failed $LINENO -cmp in copy || test_failed $LINENO +cmp in out || test_failed $LINENO cmp in anyothername.out || test_failed $LINENO -rm -f copy anyothername.out || framework_failure +rm -f out 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}" > copy +"${LZIP}" -cdq in "${in_lz}" > out [ $? = 2 ] || test_failed $LINENO -cat copy in | cmp in - || test_failed $LINENO # copy must be empty -"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy +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 [ $? = 1 ] || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f copy || framework_failure -cat "${in_lz}" > copy.lz || framework_failure +cmp in out || test_failed $LINENO +rm -f out || framework_failure +cat "${in_lz}" > out.lz || framework_failure for i in 1 2 3 4 5 6 7 ; do - printf "g" >> copy.lz || framework_failure - "${LZIP}" -atvvvv copy.lz "${in_lz}" 2> /dev/null + printf "g" >> out.lz || framework_failure + "${LZIP}" -atvvvv out.lz "${in_lz}" 2> /dev/null [ $? = 2 ] || test_failed $LINENO $i done -"${LZIP}" -dq in copy.lz +"${LZIP}" -dq in out.lz [ $? = 2 ] || test_failed $LINENO -[ -e copy.lz ] || test_failed $LINENO -[ ! -e copy ] || test_failed $LINENO +[ -e out.lz ] || test_failed $LINENO +[ ! -e out ] || test_failed $LINENO [ ! -e in.out ] || test_failed $LINENO -"${LZIP}" -dq nx_file.lz copy.lz +"${LZIP}" -dq nx_file.lz out.lz [ $? = 1 ] || test_failed $LINENO -[ ! -e copy.lz ] || test_failed $LINENO +[ ! -e out.lz ] || test_failed $LINENO [ ! -e nx_file ] || test_failed $LINENO -cmp in copy || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out || framework_failure cat in in > in2 || framework_failure "${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO -"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > copy2 || test_failed $LINENO +"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > out2 || test_failed $LINENO [ ! -e out ] || test_failed $LINENO # override -o -cmp in2 copy2 || test_failed $LINENO -rm -f copy2 || framework_failure -"${LZIP}" -d "${in_lz}" "${in_lz}" -o copy2 || test_failed $LINENO -cmp in2 copy2 || test_failed $LINENO -rm -f copy2 || framework_failure +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}" > copy2.lz || framework_failure -printf "\ngarbage" >> copy2.lz || framework_failure -"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO -"${LZIP}" -atq copy2.lz +cat "${in_lz}" "${in_lz}" > out2.lz || framework_failure +printf "\ngarbage" >> out2.lz || framework_failure +"${LZIP}" -tvvvv out2.lz 2> /dev/null || test_failed $LINENO +"${LZIP}" -atq out2.lz [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -atq < copy2.lz +"${LZIP}" -atq < out2.lz [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -adkq copy2.lz +"${LZIP}" -adkq out2.lz [ $? = 2 ] || test_failed $LINENO -[ ! -e copy2 ] || test_failed $LINENO -"${LZIP}" -adkq -o copy2 < copy2.lz +[ ! -e out2 ] || test_failed $LINENO +"${LZIP}" -adkq -o out2 < out2.lz [ $? = 2 ] || test_failed $LINENO -[ ! -e copy2 ] || test_failed $LINENO -printf "to be overwritten" > copy2 || framework_failure -"${LZIP}" -df copy2.lz || test_failed $LINENO -cmp in2 copy2 || test_failed $LINENO -rm -f in2 copy2 || framework_failure +[ ! -e out2 ] || test_failed $LINENO +printf "to be overwritten" > out2 || framework_failure +"${LZIP}" -df out2.lz || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO +rm -f out2 || framework_failure printf "\ntesting compression..." -"${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2 +"${LZIP}" -c -0 in in in -o out3.lz > copy2.lz || test_failed $LINENO +[ ! -e out3.lz ] || test_failed $LINENO # override -o +"${LZIP}" -0f in in --output=copy2.lz || test_failed $LINENO +"${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 + +"${LZIP}" -cf "${in_lz}" > lzlz 2> /dev/null # /dev/null is a tty on OS/2 [ $? = 1 ] || test_failed $LINENO -"${LZIP}" -Fvvm36 -o - -s16 "${in_lz}" > out 2> /dev/null || test_failed $LINENO -"${LZIP}" -cd out | "${LZIP}" -d > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO +"${LZIP}" -Fvvm36 -o - -s16 "${in_lz}" > lzlz 2> /dev/null || test_failed $LINENO +"${LZIP}" -cd lzlz | "${LZIP}" -d > out || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f lzlz out || framework_failure "${LZIP}" -0 -o ./- in || test_failed $LINENO "${LZIP}" -cd ./- | cmp in - || test_failed $LINENO @@ -220,10 +230,10 @@ rm -f ./-.lz || framework_failure for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do "${LZIP}" -k -$i -s16 in || test_failed $LINENO $i - mv -f in.lz copy.lz || test_failed $LINENO $i - printf "garbage" >> copy.lz || framework_failure - "${LZIP}" -df copy.lz || test_failed $LINENO $i - cmp in copy || test_failed $LINENO $i + mv in.lz out.lz || test_failed $LINENO $i + printf "garbage" >> out.lz || framework_failure + "${LZIP}" -df out.lz || test_failed $LINENO $i + cmp in out || test_failed $LINENO $i "${LZIP}" -$i -s16 in -c > out || test_failed $LINENO $i "${LZIP}" -$i -s16 in -o o_out || test_failed $LINENO $i # don't add .lz @@ -245,18 +255,18 @@ for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do "${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i cmp in copy || test_failed $LINENO $i done -rm -f out out.lz || framework_failure +rm -f copy out.lz || framework_failure printf "\ntesting bad input..." 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 -printf "LZIP${body}" >> int.lz +cat "${in_lz}" > int.lz || framework_failure +printf "LZIP${body}" >> int.lz || framework_failure if "${LZIP}" -tq int.lz ; then for header in ${headers} ; do - printf "${header}${body}" > int.lz # first member - "${LZIP}" -tq int.lz + printf "${header}${body}" > int.lz || framework_failure + "${LZIP}" -tq int.lz # first member [ $? = 2 ] || test_failed $LINENO ${header} "${LZIP}" -tq < int.lz [ $? = 2 ] || test_failed $LINENO ${header} @@ -268,9 +278,9 @@ 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 - printf "${header}${body}" >> int.lz # trailing data - "${LZIP}" -tq int.lz + cat "${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} @@ -317,15 +327,15 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && [ $? = 2 ] || test_failed $LINENO $i "${LZIP}" -tq < trunc.lz [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -cdq trunc.lz > out + "${LZIP}" -cdq trunc.lz > /dev/null [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -dq < trunc.lz > out + "${LZIP}" -dq < trunc.lz > /dev/null [ $? = 2 ] || test_failed $LINENO $i done else printf "\nwarning: skipping truncation test: 'dd' does not work on your system." fi -rm -f in2.lz in3.lz trunc.lz out || framework_failure +rm -f in2.lz in3.lz trunc.lz || framework_failure cat "${in_lz}" > ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure @@ -334,17 +344,17 @@ cat "${in_lz}" >> ingin.lz || framework_failure [ $? = 2 ] || test_failed $LINENO "${LZIP}" -atq < ingin.lz [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -acdq ingin.lz > out +"${LZIP}" -acdq ingin.lz > /dev/null [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -adq < ingin.lz > out +"${LZIP}" -adq < ingin.lz > /dev/null [ $? = 2 ] || test_failed $LINENO "${LZIP}" -t ingin.lz || test_failed $LINENO "${LZIP}" -t < ingin.lz || test_failed $LINENO -"${LZIP}" -cd ingin.lz > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f copy ingin.lz out || framework_failure +"${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 echo if [ ${fail} = 0 ] ; then From fbed39bb6452afa8df98dfdf515e24a1b80e4d4c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:27:56 +0100 Subject: [PATCH 08/10] Adding upstream version 1.13. Signed-off-by: Daniel Baumann --- ChangeLog | 12 ++++++------ INSTALL | 2 +- NEWS | 3 +++ README | 9 ++++----- carg_parser.c | 2 +- carg_parser.h | 2 +- configure | 6 +++--- doc/pdlzip.1 | 6 +++--- lzip.h | 2 +- main.c | 14 ++++++++------ testsuite/check.sh | 2 +- 11 files changed, 32 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d52edb..bc4b2e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ -2023-12-21 Antonio Diaz Diaz +2024-01-21 Antonio Diaz Diaz - * Version 1.13-rc1 released. + * 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'. @@ -118,8 +119,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2023 Antonio Diaz Diaz. +Copyright (C) 2010-2024 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..1da0402 100644 --- a/INSTALL +++ b/INSTALL @@ -74,7 +74,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2023 Antonio Diaz Diaz. +Copyright (C) 2010-2024 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/NEWS b/NEWS index 5415fd8..c719405 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ 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 option '-o, --output' now preserves dates, permissions, and ownership of +the file when (de)compressing exactly one file. + 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 diff --git a/README b/README index 14f73b7..dba78b8 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ 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 and is compatible with lzip 1.4 or newer. Lzip is a lossless data compressor with a user interface similar to the one of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Markov @@ -57,11 +57,10 @@ users of the most non-free platforms can share lzip files with everybody else. -Copyright (C) 2010-2023 Antonio Diaz Diaz. +Copyright (C) 2010-2024 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..edb4eb9 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-2024 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/carg_parser.h b/carg_parser.h index ec5d3d0..69ce271 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-2024 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/configure b/configure index 1f8c60f..2a5e46e 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-2024 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.13 progname=pdlzip srctrigger=doc/${progname}.1 @@ -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-2024 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/doc/pdlzip.1 b/doc/pdlzip.1 index 0e3e384..1a16448 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 2024" "pdlzip 1.13" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -9,7 +9,7 @@ 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 and is compatible with lzip 1.4 or newer. .PP Lzip is a lossless data compressor with a user interface similar to the one of gzip or bzip2. Lzip uses a simplified form of the 'Lempel\-Ziv\-Markov @@ -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 2024 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index 7e7805a..a1c78ab 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-2024 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided diff --git a/main.c b/main.c index 0d3b659..6d0fcc1 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-2024 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -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 = "2024"; static const char * invocation_name = "pdlzip"; /* default value */ static const struct { const char * from; const char * to; } known_extensions[] = { @@ -114,7 +114,7 @@ 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 and is compatible with lzip 1.4 or newer.\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" @@ -567,7 +567,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 @@ -1163,11 +1163,11 @@ int main( const int argc, const char * const argv[] ) 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; Pp_set_name( &pp, filenames[i] ); if( strcmp( filenames[i], "-" ) == 0 ) @@ -1230,7 +1230,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 ); diff --git a/testsuite/check.sh b/testsuite/check.sh index 8c18a1c..6b7522e 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-2024 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute, and modify it. From 16040e6d0a8948559b02d57f8227952d7259e13a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:28:22 +0100 Subject: [PATCH 09/10] Adding upstream version 1.14~rc1. Signed-off-by: Daniel Baumann --- ChangeLog | 38 ++++++++------- LzmaDec.c | 4 +- Makefile.in | 8 ++-- NEWS | 17 ++----- README | 28 +++++------ carg_parser.c | 18 +++---- carg_parser.h | 11 +++-- configure | 4 +- doc/pdlzip.1 | 24 +++++----- lzip.h | 11 +++++ main.c | 101 ++++++++++++++++++++++----------------- testsuite/check.sh | 100 ++++++++++++++++++++++++++++---------- testsuite/fox_nz.lz | Bin 0 -> 80 bytes testsuite/test.txt | 6 +-- testsuite/test.txt.lz | Bin 7376 -> 7341 bytes testsuite/test.txt.lzma | Bin 7363 -> 7328 bytes testsuite/test_em.txt.lz | Bin 14024 -> 0 bytes 17 files changed, 216 insertions(+), 154 deletions(-) create mode 100644 testsuite/fox_nz.lz delete mode 100644 testsuite/test_em.txt.lz diff --git a/ChangeLog b/ChangeLog index bc4b2e7..abdeed0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2024-11-08 Antonio Diaz Diaz + + * Version 1.14-rc1 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. @@ -39,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 @@ -58,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 @@ -78,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 @@ -95,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 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 c719405..e715e5e 100644 --- a/NEWS +++ b/NEWS @@ -1,15 +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 option '-o, --output' now preserves dates, permissions, and ownership of -the file when (de)compressing exactly one file. - -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 dba78b8..ed2815c 100644 --- a/README +++ b/README @@ -3,19 +3,19 @@ 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 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: @@ -50,12 +50,6 @@ 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. - Copyright (C) 2010-2024 Antonio Diaz Diaz. diff --git a/carg_parser.c b/carg_parser.c index edb4eb9..e16fa73 100644 --- a/carg_parser.c +++ b/carg_parser.c @@ -148,21 +148,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, @@ -204,15 +204,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; diff --git a/carg_parser.h b/carg_parser.h index 69ce271..65a6d7d 100644 --- a/carg_parser.h +++ b/carg_parser.h @@ -37,15 +37,20 @@ 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 */ +enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme }; struct ap_Option { diff --git a/configure b/configure index 2a5e46e..9f6e7da 100755 --- a/configure +++ b/configure @@ -6,7 +6,7 @@ # to copy, distribute, and modify it. pkgname=pdlzip -pkgversion=1.13 +pkgversion=1.14-rc1 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 diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index 1a16448..15fb29a 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" "January 2024" "pdlzip 1.13" "User Commands" +.TH PDLZIP "1" "November 2024" "pdlzip 1.14-rc1" "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 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. diff --git a/lzip.h b/lzip.h index a1c78ab..74b8019 100644 --- a/lzip.h +++ b/lzip.h @@ -188,9 +188,20 @@ 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; } } +struct Cl_options /* command-line options */ + { + bool ignore_trailing; + bool loose_trailing; + }; + +static inline void Cl_options_init( struct 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 empty_msg = "Empty member not allowed."; static const char * const trailing_msg = "Trailing data not allowed."; static const char * const mem_msg = "Not enough memory."; diff --git a/main.c b/main.c index 6d0fcc1..722ebe3 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,7 @@ #include #include -#include /* SSIZE_MAX */ +#include /* CHAR_BIT, SSIZE_MAX */ #include #include #include /* SIZE_MAX */ @@ -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 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" @@ -226,6 +226,9 @@ static void Pp_init( struct Pretty_print * const pp, if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; } +void Pp_free( struct Pretty_print * const pp ) + { if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } } + static void Pp_set_name( struct Pretty_print * const pp, const char * const filename ) { @@ -268,7 +271,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; @@ -277,7 +280,7 @@ static void show_header( const unsigned dictionary_size ) } -/* separate numbers of 5 or more digits in groups of 3 digits using '_' */ +/* separate numbers of 6 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 }; @@ -289,7 +292,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 ) @@ -300,7 +303,7 @@ static const char * format_num3( unsigned long long num ) { num /= 1000; prefix = si_prefix[i]; } if( prefix ) *(--p) = prefix; } - const bool split = num >= 10000; + const bool split = num >= 100000; for( i = 0; ; ) { @@ -335,7 +338,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] ) @@ -458,7 +461,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp 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 +472,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 ) @@ -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; @@ -734,7 +737,7 @@ 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[], 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 struct Cl_options * const cl_opts, + struct 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; } @@ -1038,10 +1047,10 @@ int main( const int argc, const char * const argv[] ) const char * default_output_filename = ""; enum Mode program_mode = m_compress; int i; + struct 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]; @@ -1077,7 +1086,7 @@ 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(); @@ -1097,11 +1106,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 +1119,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 */ @@ -1168,9 +1177,10 @@ int main( const int argc, const char * const argv[] ) { const char * input_filename = ""; int infd; + 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 ); @@ -1243,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 6b7522e..0651ab3 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -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 @@ -139,7 +136,7 @@ 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 @@ -157,7 +154,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 +183,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 +203,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 +225,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 +273,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 +319,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 +341,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 +359,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 +377,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 0000000000000000000000000000000000000000..44a4b58b881d207627f6081d8ad04708c25400dc GIT binary patch literal 80 zcmeZ?@(f_)Nz{_!Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2nc}E0AJQ0O8@`> literal 0 HcmV?d00001 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 22cea6e4d2a58b4dcb006541dcdb8defabba0cbb..5dc169f7fb6e952f17e7a21ce3691eeaac2fb3aa 100644 GIT binary patch delta 7294 zcmV-^9D(D|IjuR6Zhys3yJ(c8peBW%f-elXuLG8+YcW?HC;m#{D%pU^WiRDBah9%H zoNKDm$X*ivN}frZPJV^dtsX$0%Z^SSxrOZEO@c$q7owY! z`W;W~c7VLKKJvfUJ)mGF=tySp{PxY$8`#(o1p?=vxoYM*hkx#@T($B}rE}wqiNbai zPkS|>8W_N@+GNU=i-?`g4gP^bKc=(O|BTS>tf}Y}sWaDOa9)@f3Z>pC@4M?MqsMyf z$l9a4FCJZ;`)tQ5Wbrs^K<$Gkx9@N*`^#x7IXK%ex=T%-ID=$T@CGUn*XOjK7%aI^ z{P$K|lLRk7DSwY<;3s2ge)hV`mKFEf_=bs$Oa|MsKB4EOEq5 zbi#35GkG6xskoc^ai7hojVayH{;Ap%0D7qkn{2{=+J9YtzU8rM;x_SA8&KAYW1k_h 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 I000000MqzJBme*a diff --git a/testsuite/test.txt.lzma b/testsuite/test.txt.lzma index 53e54ea1bb33582950062681b4e5590065948a28..091c0234c81ed4ea0c074725c5d737f98e852af3 100644 GIT binary patch delta 7274 zcmV-w9F^n4IiNX^b$`WAyJ(c8peBW%f-elXuLG8+YcW?HC;m#{D%pU^WiRDBah9%H zoNKDm$X*ivN}frZPJV^dtsX$0%Z^SSxrOZEO@c$q7owY! z`W;W~c7VLKKJvfUJ)mGF=tySp{PxY$8`#(o1p?=vxoYM*hkx#@T($B}rE}wqiNbai zPkS|>8W_N@+GNU=i-?`g4gP^bKc=(O|BTS>tf}Y}sWaDOa9)@f3Z>pC@4M?MqsMyf z$l9a4FCJZ;`)tQ5Wbrs^K<$Gkx9@N*`^#x7IXK%ex=T%-ID=$T@CGUn*XOjK7%aI^ z{P$K|lLRk7DSwY<;3s2ge)hV`mKFEf_=bs$Oa|MsKB4EOEq5 zbi#35GkG6xskoc^ai7hojVayH{;Ap%0D7qkn{2{=+J9YtzU8rM;x_SA8&KAYW1k_h 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 diff --git a/testsuite/test_em.txt.lz b/testsuite/test_em.txt.lz deleted file mode 100644 index 7e96250d9ec70bc7d8cb173f438c76be447e6b6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14024 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 Gt^OBPlQ$#) From b64391bed2828414ca6f14bf24687151140941c0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 23 Feb 2025 19:28:33 +0100 Subject: [PATCH 10/10] Adding upstream version 1.14. Signed-off-by: Daniel Baumann --- ChangeLog | 6 ++--- INSTALL | 5 ++-- README | 16 ++++++----- carg_parser.c | 44 +++++++++++++------------------ carg_parser.h | 36 ++++++++++++------------- configure | 6 ++--- doc/pdlzip.1 | 4 +-- lzip.h | 10 +++---- main.c | 66 +++++++++++++++++++++++----------------------- testsuite/check.sh | 5 ++-- 10 files changed, 98 insertions(+), 100 deletions(-) diff --git a/ChangeLog b/ChangeLog index abdeed0..74c2b8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ -2024-11-08 Antonio Diaz Diaz +2025-01-07 Antonio Diaz Diaz - * Version 1.14-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'. @@ -125,7 +125,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2024 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. diff --git a/INSTALL b/INSTALL index 1da0402..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-2024 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/README b/README index ed2815c..1e4ae50 100644 --- a/README +++ b/README @@ -1,3 +1,5 @@ +See the file INSTALL for compilation and installation instructions. + Description Pdlzip is a permissively licensed implementation of the lzip data @@ -20,11 +22,10 @@ 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,8 +51,11 @@ without recompressing. Pdlzip includes public domain compression/decompression code from the LZMA SDK (Software Development Kit) written by Igor Pavlov. +Pdlzip uses Arg_parser for command-line argument parsing: +http://www.nongnu.org/arg-parser/arg_parser.html -Copyright (C) 2010-2024 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/carg_parser.c b/carg_parser.c index e16fa73..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-2024 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; @@ -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 */ @@ -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 65a6d7d..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-2024 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 @@ -50,52 +50,52 @@ extern "C" { #endif /* ap_yme = yes but maybe empty */ -enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme }; +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 9f6e7da..4f3fdd2 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2024 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.14-rc1 +pkgversion=1.14 progname=pdlzip srctrigger=doc/${progname}.1 @@ -171,7 +171,7 @@ echo "MAKEINFO = ${MAKEINFO}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2024 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/doc/pdlzip.1 b/doc/pdlzip.1 index 15fb29a..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" "November 2024" "pdlzip 1.14-rc1" "User Commands" +.TH PDLZIP "1" "January 2025" "pdlzip 1.14" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS @@ -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 2024 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 74b8019..7dc9ee3 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2024 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,13 +188,13 @@ 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; } } -struct Cl_options /* command-line options */ +typedef struct Cl_options /* command-line options */ { bool ignore_trailing; bool loose_trailing; - }; + } Cl_options; -static inline void Cl_options_init( struct Cl_options * cl_opts ) +static inline void Cl_options_init( Cl_options * cl_opts ) { cl_opts->ignore_trailing = true; cl_opts->loose_trailing = false; } @@ -202,8 +202,8 @@ static inline void set_retval( int * retval, const int new_val ) { if( *retval < new_val ) *retval = new_val; } static const char * const empty_msg = "Empty member not allowed."; -static const char * const trailing_msg = "Trailing data 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 722ebe3..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-2024 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 @@ -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 = "2024"; +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. */ @@ -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,11 +226,10 @@ static void Pp_init( struct Pretty_print * const pp, if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; } -void Pp_free( struct Pretty_print * const pp ) +void Pp_free( Pretty_print * const pp ) { if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } } -static void Pp_set_name( struct Pretty_print * const pp, - const char * const filename ) +static void Pp_set_name( Pretty_print * const pp, const char * const filename ) { unsigned name_len, padded_name_len, i = 0; @@ -248,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 ) @@ -280,7 +279,7 @@ static void show_header( const unsigned dictionary_size ) } -/* separate numbers of 6 or more digits in groups of 3 digits using '_' */ +/* 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 }; @@ -303,7 +302,7 @@ static const char * format_num3( unsigned long long num ) { num /= 1000; prefix = si_prefix[i]; } if( prefix ) *(--p) = prefix; } - const bool split = num >= 100000; + const bool split = num >= 10000; for( i = 0; ; ) { @@ -388,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 ) { @@ -455,7 +454,7 @@ static void set_d_outname( const char * const name, const int eindex ) static int open_instream( const char * const name, struct stat * const in_statsp, - const enum Mode program_mode, const int eindex, + const Mode program_mode, const int eindex, const bool one_to_one, const bool recompress ) { if( program_mode == m_compress && !recompress && eindex >= 0 ) @@ -540,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 */ @@ -552,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] ? @@ -596,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; @@ -734,8 +734,8 @@ 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, bool * const data0p ) { @@ -840,8 +840,8 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, } -static int decompress( const int infd, const struct Cl_options * const cl_opts, - struct Pretty_print * const pp, +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; @@ -1031,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 */ @@ -1043,11 +1043,10 @@ 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; - struct Cl_options cl_opts; /* command-line options */ + Mode program_mode = m_compress; + Cl_options cl_opts; /* command-line options */ Cl_options_init( &cl_opts ); bool force = false; bool keep_input_files = false; @@ -1056,7 +1055,7 @@ int main( const int argc, const char * const argv[] ) 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 }, @@ -1091,7 +1090,7 @@ int main( const int argc, const char * const argv[] ) 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 */ @@ -1144,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 ) { @@ -1165,7 +1165,7 @@ 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; diff --git a/testsuite/check.sh b/testsuite/check.sh index 0651ab3..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-2024 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. @@ -128,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 @@ -141,7 +140,7 @@ cp "${in_lz}" anyothername || framework_failure 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