diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | INSTALL | 14 | ||||
-rw-r--r-- | LzmaEnc.c | 12 | ||||
-rw-r--r-- | NEWS | 30 | ||||
-rw-r--r-- | README | 38 | ||||
-rw-r--r-- | carg_parser.c | 2 | ||||
-rw-r--r-- | carg_parser.h | 2 | ||||
-rwxr-xr-x | configure | 16 | ||||
-rw-r--r-- | doc/pdlzip.1 | 24 | ||||
-rw-r--r-- | lzip.h | 53 | ||||
-rw-r--r-- | main.c | 153 | ||||
-rwxr-xr-x | testsuite/check.sh | 113 |
12 files changed, 276 insertions, 193 deletions
@@ -1,3 +1,13 @@ +2019-01-01 Antonio Diaz Diaz <antonio@gnu.org> + + * 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 <antonio@gnu.org> * 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 @@ -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. @@ -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 @@ -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. @@ -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 @@ -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 @@ -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; } } @@ -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 <unistd.h> #include <utime.h> #include <sys/stat.h> -#if defined(__MSVCRT__) +#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) #include <io.h> +#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 <io.h> +#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=<bytes> 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 < int.lz + [ $? = 2 ] || test_failed $LINENO ${header} + "${LZIP}" -cdq int.lz > /dev/null + [ $? = 2 ] || test_failed $LINENO ${header} + "${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}" -tq --loose-trailing in0.lz + "${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} - cat "${in_lz}" > in0.lz - printf "${header}${body}" >> in0.lz # trailing data - "${LZIP}" -tq in0.lz + "${LZIP}" -tq --loose-trailing --trailing-error < int.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 + "${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 |