diff --git a/AUTHORS b/AUTHORS index 6db2128..6b1c0dd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ Pdlzip was written by Antonio Diaz Diaz. -Pdlzip includes public domain compression/decompression code from the LZMA -SDK (Software Development Kit) written by Igor Pavlov. +Pdlzip includes public domain (de)compression code from the LZMA SDK +(Software Development Kit) written by Igor Pavlov. diff --git a/COPYING b/COPYING deleted file mode 100644 index 57f0e34..0000000 --- a/COPYING +++ /dev/null @@ -1,19 +0,0 @@ - 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 74c2b8c..d4fcfeb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,107 +1,39 @@ -2025-01-07 Antonio Diaz Diaz - - * Version 1.14 released. - * main.c (decompress): Return 2 if empty member in multimember file. - (Pp_free): New function. - * check.sh: Use 'cp' instead of 'cat'. - -2024-01-21 Antonio Diaz Diaz - - * Version 1.13 released. - * main.c: Reformat file diagnostics as 'PROGRAM: FILE: MESSAGE'. - (show_option_error): New function showing argument and option name. - (main): Make -o preserve date/mode/owner if 1 input file. - * lzip.h: Rename verify_* to check_*. - * configure, Makefile.in: New variable 'MAKEINFO'. - * INSTALL: Document use of CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500'. - -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. - * 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. - * 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. - * 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. - * New option '--loose-trailing'. - * Replace 'bits/byte' with inverse compression ratio in output. - * 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 - - * Version 1.8 released. - * main.c: Continue testing if any input file is a terminal. - * main.c (decompress): Improve detection of trailing data. - -2016-05-16 Antonio Diaz Diaz - - * Version 1.7 released. - * main.c: New option '-a, --trailing-error'. - * main.c (main): Delete '--output' file if infd is a terminal. - (main): Don't use stdin more than once. - * configure: Avoid warning on some shells when testing for gcc. - * check.sh: Require a POSIX shell. Don't check error messages. - 2015-05-26 Antonio Diaz Diaz * Version 1.6 released. * main.c (close_and_set_permissions): Behave like 'cp -p'. - * Makefile.in: New targets 'install*-compress'. + * Makefile.in: Added new targets 'install*-compress'. 2013-09-14 Antonio Diaz Diaz * Version 1.5 released. - * main.c (show_header): Don't show header version in lzip mode. + * main.c (show_header): Do not show header version in lzip mode. * Minor fixes. 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: Accept more than one file in command line. * Decompression time has been reduced by 5%. - * main.c: New options '-f, --force', '-F, --recompress', - '-k, --keep', and '-o, --output'. - 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. + * 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. + * Ignore option '-n, --threads' for compatibility with plzip. * configure: Options now accept a separate argument. - Rename 'datadir' to 'datarootdir'. - * Makefile.in: New targets 'install-as-lzip' and 'install-bin'. + * configure: 'datadir' renamed to 'datarootdir'. + * Makefile.in: Added new target 'install-as-lzip'. + * Makefile.in: Added new target 'install-bin'. 2012-01-03 Antonio Diaz Diaz * Version 1.3 released. * Small change in '--help' output and man page. - * Change quote characters in messages as advised by GNU Standards. - * main.c (main): Set stdin/stdout in binary mode on OS2. + * Changed 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 @@ -111,7 +43,7 @@ 2010-08-19 Antonio Diaz Diaz * Version 1.1 released. - * main.c: Add support for decompression of lzma-alone files. + * main.c: Added 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 @@ -125,7 +57,8 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010-2025 Antonio Diaz Diaz. +Copyright (C) 2010-2015 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 e500eb9..489393d 100644 --- a/INSTALL +++ b/INSTALL @@ -1,14 +1,9 @@ Requirements ------------ -You will need a C99 compiler. (gcc 3.3.6 or newer is recommended). -I use gcc 6.1.0 and 3.3.6, but the code should compile with any standards -compliant compiler. -Gcc is available at http://gcc.gnu.org -Lzip is available at http://www.nongnu.org/lzip/lzip.html - -The operating system must allow signal handlers read access to objects with -static storage duration so that the cleanup handler for Control-C can delete -the partial output file. +You will need a C compiler. +I use gcc 4.9.1 and 4.1.2, but the code should compile with any +standards compliant compiler. +Gcc is available at http://gcc.gnu.org. Procedure @@ -19,8 +14,8 @@ Procedure or lzip -cd pdlzip[version].tar.lz | tar -xf - -This creates the directory ./pdlzip[version] containing the source code -extracted from the archive. +This creates the directory ./pdlzip[version] containing the source from +the main archive. 2. Change to pdlzip directory and run configure. (Try 'configure --help' for usage instructions). @@ -28,14 +23,6 @@ extracted from the 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' - 3. Run make. make @@ -43,15 +30,14 @@ extracted from the 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. You need root privileges to install into a prefix owned - by root. + documentation. Or type 'make install-compress', which additionally compresses the - man page after installation. - (Installing compressed docs may become the default in the future). + man page after installation. (Installing compressed docs may become + the default in the future). - You can install only the program or the man page by typing - 'make install-bin' or 'make install-man' respectively. + You can install only the program or the man page by typing 'make + install-bin' or 'make install-man' respectively. Instead of 'make install', you can type 'make install-as-lzip' to install the program and any data files and documentation, and link @@ -61,21 +47,21 @@ extracted from the archive. Another way ----------- You can also compile pdlzip into a separate directory. -To do this, you must use a version of 'make' that supports the variable -'VPATH', such as GNU 'make'. 'cd' to the directory where you want the +To do this, you must use a version of 'make' that supports the 'VPATH' +variable, such as GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run the 'configure' script. -'configure' automatically checks for the source code in '.', in '..', and +'configure' automatically checks for the source code in '.', in '..' and in the directory that 'configure' is in. -'configure' recognizes the option '--srcdir=DIR' to control where to look -for the source code. Usually 'configure' can determine that directory +'configure' recognizes the option '--srcdir=DIR' to control where to +look for the sources. Usually 'configure' can determine that directory automatically. After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010-2025 Antonio Diaz Diaz. +Copyright (C) 2010-2015 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/LzFind.c b/LzFind.c index c312927..8e660f3 100644 --- a/LzFind.c +++ b/LzFind.c @@ -4,7 +4,6 @@ #define _FILE_OFFSET_BITS 64 #include -#include #include #include #include diff --git a/LzmaDec.c b/LzmaDec.c index bd2a45a..cc4279d 100644 --- a/LzmaDec.c +++ b/LzmaDec.c @@ -4,7 +4,6 @@ #define _FILE_OFFSET_BITS 64 #include -#include #include #include #include @@ -716,8 +715,8 @@ static bool LzmaDec_DecodeToDic(CLzmaDec *p, uint32_t dicLimit, *status = LZMA_STATUS_NEEDS_MORE_INPUT; return true; } - /* check first byte of the LZMA stream */ - if (p->tempBuf[0] != 0) return false; + if (p->tempBuf[0] != 0) + return false; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; diff --git a/LzmaEnc.c b/LzmaEnc.c index f59c001..fb5df7a 100644 --- a/LzmaEnc.c +++ b/LzmaEnc.c @@ -3,7 +3,6 @@ #define _FILE_OFFSET_BITS 64 -#include #include #include #include @@ -1352,7 +1351,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; - Lzip_trailer trailer; + File_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,23 +1361,23 @@ 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); - 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 ) + 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 ) p->rc.res = SZ_ERROR_WRITE; if( verbosity >= 1 ) { unsigned long long in_size = p->nowPos64; - 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 ); + 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" ); else - fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved, " - "%llu in, %llu out.\n", + fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " + "%5.2f%% saved, %llu in, %llu out.\n", (double)in_size / out_size, - ( 100.0 * out_size ) / in_size, - 100.0 - ( ( 100.0 * out_size ) / in_size ), + ( 8.0 * out_size ) / in_size, + 100.0 * ( 1.0 - ( (double)out_size / in_size ) ), in_size, out_size ); } } diff --git a/LzmaEnc.h b/LzmaEnc.h index b607be8..1b18df7 100644 --- a/LzmaEnc.h +++ b/LzmaEnc.h @@ -5,6 +5,7 @@ /* ---------- 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 fc59256..1b4ab5b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -2,10 +2,9 @@ DISTNAME = $(pkgname)-$(pkgversion) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -m 755 -INSTALL_DIR = $(INSTALL) -d -m 755 INSTALL_DATA = $(INSTALL) -m 644 +INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh -CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1 objs = carg_parser.o LzFind.o LzmaEnc.o LzmaDec.o main.o @@ -13,14 +12,13 @@ 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) $(progname) : $(objs) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(objs) + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(objs) main.o : main.c $(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< @@ -28,11 +26,6 @@ main.o : main.c %.o : %.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -# prevent 'make' from trying to remake source files -$(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ; -MAKEFLAGS += -r -.SUFFIXES : - $(objs) : Makefile carg_parser.o : carg_parser.h LzmaDec.o : lzip.h LzmaDec.h @@ -40,12 +33,13 @@ 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 @@ -74,9 +68,7 @@ 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" - -if $(CAN_RUN_INSTALLINFO) ; then \ - install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ - fi + -install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" install-info-compress : install-info lzip -v -9 "$(DESTDIR)$(infodir)/$(pkgname).info" @@ -99,9 +91,7 @@ uninstall-bin : -rm -f "$(DESTDIR)$(bindir)/$(progname)" uninstall-info : - -if $(CAN_RUN_INSTALLINFO) ; then \ - install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \ - fi + -install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* uninstall-man : @@ -111,7 +101,6 @@ 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 \ @@ -119,14 +108,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/fox.lz \ - $(DISTNAME)/testsuite/fox_*.lz \ $(DISTNAME)/testsuite/test.txt.lz \ - $(DISTNAME)/testsuite/test.txt.lzma + $(DISTNAME)/testsuite/test.txt.lzma \ + $(DISTNAME)/*.h \ + $(DISTNAME)/*.c rm -f $(DISTNAME) lzip -v -9 $(DISTNAME).tar diff --git a/NEWS b/NEWS index e715e5e..12715c0 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,8 @@ -Changes in version 1.14: +Changes in version 1.6: -pdlzip now exits with error status 2 if any empty member is found in a -multimember file. +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 targets "install-compress", "install-strip-compress" and +"install-man-compress" have been added to the Makefile. diff --git a/README b/README index 1e4ae50..a7cbbd2 100644 --- a/README +++ b/README @@ -1,64 +1,59 @@ -See the file INSTALL for compilation and installation instructions. - Description -Pdlzip is a permissively licensed implementation of the lzip data -compressor, intended for those who can't distribute (or even use) GPL -licensed Free Software. The name of pdlzip comes from 'public domain lzip'. -Pdlzip is written in C. +Pdlzip is a lossless data compressor with a user interface similar to +the one of lzip, bzip2 or gzip. -Lzip is a lossless data compressor with a user interface similar to the one -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. +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. -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 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 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. - * 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 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. -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. +Lzma-alone is a very bad format. If you keep any lzma-alone files, it is +advisable to recompress them to lzip format. -Pdlzip includes public domain compression/decompression code from the LZMA -SDK (Software Development Kit) written by Igor Pavlov. +Pdlzip is written in C. -Pdlzip uses Arg_parser for command-line argument parsing: -http://www.nongnu.org/arg-parser/arg_parser.html +Pdlzip includes public domain (de)compression 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-2025 Antonio Diaz Diaz. +Copyright (C) 2010-2015 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, -distribute, and modify it. +distribute and modify it. -The file Makefile.in is a data file used by configure to produce the Makefile. -It has the same copyright owner and permissions that configure itself. +The file Makefile.in is a data file used by configure to produce the +Makefile. It has the same copyright owner and permissions that configure +itself. diff --git a/carg_parser.c b/carg_parser.c index 20b8a16..8d74ea6 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-2025 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command line argument parser. (C version) + Copyright (C) 2006-2015 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 @@ -32,46 +32,28 @@ static void * ap_resize_buffer( void * buf, const int min_size ) } -static char push_back_record( Arg_parser * const ap, const int code, - const char * const long_name, - const char * const argument ) +static char push_back_record( struct Arg_parser * const ap, + const int code, const char * const argument ) { - ap_Record * p; + const int len = strlen( argument ); + struct ap_Record * p; void * tmp = ap_resize_buffer( ap->data, - ( ap->data_size + 1 ) * sizeof (ap_Record) ); + ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); if( !tmp ) return 0; - ap->data = (ap_Record *)tmp; + ap->data = (struct ap_Record *)tmp; p = &(ap->data[ap->data_size]); p->code = code; - if( long_name ) - { - const int len = strlen( long_name ); - p->parsed_name = (char *)malloc( len + 2 + 1 ); - if( !p->parsed_name ) return 0; - p->parsed_name[0] = p->parsed_name[1] = '-'; - strncpy( p->parsed_name + 2, long_name, len + 1 ); - } - else if( code > 0 && code < 256 ) - { - p->parsed_name = (char *)malloc( 2 + 1 ); - if( !p->parsed_name ) return 0; - p->parsed_name[0] = '-'; p->parsed_name[1] = code; p->parsed_name[2] = 0; - } - else p->parsed_name = 0; - if( argument ) - { - 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; + 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 ); ++ap->data_size; return 1; } -static char add_error( Arg_parser * const ap, const char * const msg ) +static char add_error( struct Arg_parser * const ap, const char * const msg ) { const int len = strlen( msg ); void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 ); @@ -83,20 +65,19 @@ static char add_error( Arg_parser * const ap, const char * const msg ) } -static void free_data( Arg_parser * const ap ) +static void free_data( struct Arg_parser * const ap ) { int i; - for( i = 0; i < ap->data_size; ++i ) - { free( ap->data[i].argument ); free( ap->data[i].parsed_name ); } + for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument ); if( ap->data ) { free( ap->data ); ap->data = 0; } ap->data_size = 0; } -/* Return 0 only if out of memory. */ -static char parse_long_option( Arg_parser * const ap, +static char parse_long_option( struct Arg_parser * const ap, const char * const opt, const char * const arg, - const ap_Option options[], int * const argindp ) + const struct ap_Option options[], + int * const argindp ) { unsigned len; int index = -1, i; @@ -106,15 +87,14 @@ static char parse_long_option( Arg_parser * const ap, /* Test all long options for either exact match or abbreviated matches. */ for( i = 0; options[i].code != 0; ++i ) - if( options[i].long_name && - strncmp( options[i].long_name, &opt[2], len ) == 0 ) + if( options[i].name && strncmp( options[i].name, &opt[2], len ) == 0 ) { - if( strlen( options[i].long_name ) == len ) /* Exact match found */ + if( strlen( options[i].name ) == len ) /* Exact match found */ { index = i; exact = 1; break; } else if( index < 0 ) index = i; /* First nonexact match found */ else if( options[index].code != options[i].code || 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 ) @@ -137,55 +117,52 @@ static char parse_long_option( Arg_parser * const ap, { if( options[index].has_arg == ap_no ) { - add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); + add_error( ap, "option '--" ); add_error( ap, options[index].name ); add_error( ap, "' doesn't allow an argument" ); return 1; } if( options[index].has_arg == ap_yes && !opt[len+3] ) { - add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); + add_error( ap, "option '--" ); add_error( ap, options[index].name ); add_error( ap, "' requires an argument" ); return 1; } - return push_back_record( ap, options[index].code, options[index].long_name, - &opt[len+3] ); /* argument may be empty */ + return push_back_record( ap, options[index].code, &opt[len+3] ); } - if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme ) + if( options[index].has_arg == ap_yes ) { - if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) ) + if( !arg || !arg[0] ) { - add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); + add_error( ap, "option '--" ); add_error( ap, options[index].name ); add_error( ap, "' requires an argument" ); return 1; } ++*argindp; - return push_back_record( ap, options[index].code, options[index].long_name, - arg ); /* argument may be empty */ + return push_back_record( ap, options[index].code, arg ); } - return push_back_record( ap, options[index].code, - options[index].long_name, 0 ); + return push_back_record( ap, options[index].code, "" ); } -/* Return 0 only if out of memory. */ -static char parse_short_option( Arg_parser * const ap, +static char parse_short_option( struct Arg_parser * const ap, const char * const opt, const char * const arg, - const ap_Option options[], int * const argindp ) + const struct ap_Option options[], + int * const argindp ) { int cind = 1; /* character index in opt */ while( cind > 0 ) { int index = -1, i; - const unsigned char c = opt[cind]; + const unsigned char code = opt[cind]; char code_str[2]; - code_str[0] = c; code_str[1] = 0; + code_str[0] = code; code_str[1] = 0; - if( c != 0 ) + if( code != 0 ) for( i = 0; options[i].code; ++i ) - if( c == options[i].code ) + if( code == options[i].code ) { index = i; break; } if( index < 0 ) @@ -199,34 +176,34 @@ static char parse_short_option( Arg_parser * const ap, if( options[index].has_arg != ap_no && cind > 0 && opt[cind] ) { - if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0; + if( !push_back_record( ap, code, &opt[cind] ) ) return 0; ++*argindp; cind = 0; } - else if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme ) + else if( options[index].has_arg == ap_yes ) { - if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) ) + if( !arg || !arg[0] ) { add_error( ap, "option requires an argument -- '" ); add_error( ap, code_str ); add_error( ap, "'" ); return 1; } - ++*argindp; cind = 0; /* argument may be empty */ - if( !push_back_record( ap, c, 0, arg ) ) return 0; + ++*argindp; cind = 0; + if( !push_back_record( ap, code, arg ) ) return 0; } - else if( !push_back_record( ap, c, 0, 0 ) ) return 0; + else if( !push_back_record( ap, code, "" ) ) return 0; } return 1; } -char ap_init( Arg_parser * const ap, +char ap_init( struct Arg_parser * const ap, const int argc, const char * const argv[], - const ap_Option options[], const char in_order ) + const struct ap_Option options[], const char in_order ) { const char ** non_options = 0; /* skipped non-options */ int non_options_size = 0; /* number of skipped non-options */ int argind = 1; /* index in argv */ - char done = 0; /* false until success */ + int i; ap->data = 0; ap->error = 0; @@ -246,41 +223,38 @@ char ap_init( Arg_parser * const ap, if( ch2 == '-' ) { if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */ - else if( !parse_long_option( ap, opt, arg, options, &argind ) ) goto out; + else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0; } - else if( !parse_short_option( ap, opt, arg, options, &argind ) ) goto out; + else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0; if( ap->error ) break; } else { - if( in_order ) - { if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; } - else + if( !in_order ) { void * tmp = ap_resize_buffer( non_options, ( non_options_size + 1 ) * sizeof *non_options ); - if( !tmp ) goto out; + if( !tmp ) return 0; non_options = (const char **)tmp; non_options[non_options_size++] = argv[argind++]; } + else if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; } } if( ap->error ) free_data( ap ); else { - int i; for( i = 0; i < non_options_size; ++i ) - if( !push_back_record( ap, 0, 0, non_options[i] ) ) goto out; + if( !push_back_record( ap, 0, non_options[i] ) ) return 0; while( argind < argc ) - if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; + if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; } - done = 1; -out: if( non_options ) free( non_options ); - return done; + if( non_options ) free( non_options ); + return 1; } -void ap_free( Arg_parser * const ap ) +void ap_free( struct Arg_parser * const ap ) { free_data( ap ); if( ap->error ) { free( ap->error ); ap->error = 0; } @@ -288,26 +262,23 @@ void ap_free( Arg_parser * const ap ) } -const char * ap_error( const Arg_parser * const ap ) { return ap->error; } +const char * ap_error( const struct Arg_parser * const ap ) + { return ap->error; } -int ap_arguments( const Arg_parser * const ap ) { return ap->data_size; } -int ap_code( const Arg_parser * const ap, const int i ) +int ap_arguments( const struct Arg_parser * const ap ) + { return ap->data_size; } + + +int ap_code( const struct Arg_parser * const ap, const int i ) { - if( i < 0 || i >= ap_arguments( ap ) ) return 0; - return ap->data[i].code; + if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code; + else return 0; } -const char * ap_parsed_name( const Arg_parser * const ap, const int i ) +const char * ap_argument( const struct Arg_parser * const ap, const int i ) { - if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].parsed_name ) return ""; - return ap->data[i].parsed_name; - } - - -const char * ap_argument( const Arg_parser * const ap, const int i ) - { - if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].argument ) return ""; - return ap->data[i].argument; + if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument; + else return ""; } diff --git a/carg_parser.h b/carg_parser.h index 28eabee..ed4d9c5 100644 --- a/carg_parser.h +++ b/carg_parser.h @@ -1,101 +1,92 @@ -/* Arg_parser - POSIX/GNU command-line argument parser. (C version) - Copyright (C) 2006-2025 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command line argument parser. (C version) + Copyright (C) 2006-2015 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 long_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 of options with an optional argument is - '-' (without whitespace), or - '--='. - - The syntax of options with an empty argument is '- ""', - '-- ""', or '--=""'. + The syntax for optional option arguments is '-' + (without whitespace), or '--='. */ #ifdef __cplusplus extern "C" { #endif -/* ap_yme = yes but maybe empty */ -typedef enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme } ap_Has_arg; +enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; -typedef struct ap_Option +struct ap_Option { int code; /* Short option letter or code ( code != 0 ) */ - const char * long_name; /* Long option name (maybe null) */ - ap_Has_arg has_arg; - } ap_Option; + const char * name; /* Long option name (maybe null) */ + enum ap_Has_arg has_arg; + }; -typedef struct ap_Record +struct ap_Record { int code; - char * parsed_name; char * argument; - } ap_Record; + }; -typedef struct Arg_parser +struct Arg_parser { - ap_Record * data; + struct ap_Record * data; char * error; int data_size; int error_size; - } Arg_parser; + }; -char ap_init( Arg_parser * const ap, +char ap_init( struct Arg_parser * const ap, const int argc, const char * const argv[], - const ap_Option options[], const char in_order ); + const struct ap_Option options[], const char in_order ); -void ap_free( Arg_parser * const ap ); +void ap_free( struct Arg_parser * const ap ); -const char * ap_error( const Arg_parser * const ap ); +const char * ap_error( const struct Arg_parser * const ap ); -/* The number of arguments parsed. May be different from argc. */ -int ap_arguments( const Arg_parser * const ap ); + /* The number of arguments parsed (may be different from argc) */ +int ap_arguments( const struct Arg_parser * const ap ); -/* If ap_code( i ) is 0, ap_argument( i ) is a non-option. - Else ap_argument( i ) is the option's argument (or empty). */ -int ap_code( const Arg_parser * const ap, const int i ); + /* 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 ); -/* Full name of the option parsed (short or long). */ -const char * ap_parsed_name( const Arg_parser * const ap, const int i ); - -const char * ap_argument( const Arg_parser * const ap, const int i ); +const char * ap_argument( const struct Arg_parser * const ap, const int i ); #ifdef __cplusplus } diff --git a/configure b/configure index 4f3fdd2..40db552 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Pdlzip - LZMA lossless data compressor -# Copyright (C) 2010-2025 Antonio Diaz Diaz. +# Copyright (C) 2010-2015 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.14 +pkgversion=1.6 progname=pdlzip srctrigger=doc/${progname}.1 @@ -24,10 +24,13 @@ CC=gcc CPPFLAGS= CFLAGS='-Wall -W -O2' LDFLAGS= -MAKEINFO=makeinfo # checking whether we are using GNU C. -/bin/sh -c "${CC} --version" > /dev/null 2>&1 || { CC=cc ; CFLAGS=-O2 ; } +${CC} --version > /dev/null 2>&1 +if [ $? != 0 ] ; then + CC=cc + CFLAGS='-W -O2' +fi # Loop over all args args= @@ -39,26 +42,22 @@ while [ $# != 0 ] ; do shift # Add the argument quoted to args - if [ -z "${args}" ] ; then args="\"${option}\"" - else args="${args} \"${option}\"" ; fi + args="${args} \"${option}\"" # Split out the argument for options that take them case ${option} in - *=*) optarg=`echo "${option}" | sed -e 's,^[^=]*=,,;s,/$,,'` ;; + *=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;; esac # Process the options case ${option} in --help | -h) - echo "Usage: $0 [OPTION]... [VAR=VALUE]..." + echo "Usage: configure [options]" echo - 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 "Options: [defaults in brackets]" echo " -h, --help display this help and exit" echo " -V, --version output version information and exit" - echo " --srcdir=DIR find the source code in DIR [. or ..]" + echo " --srcdir=DIR find the sources in DIR [. or ..]" echo " --prefix=DIR install into DIR [${prefix}]" echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]" echo " --bindir=DIR user executables directory [${bindir}]" @@ -66,11 +65,9 @@ while [ $# != 0 ] ; do echo " --infodir=DIR info files directory [${infodir}]" echo " --mandir=DIR man pages directory [${mandir}]" echo " CC=COMPILER C compiler to use [${CC}]" - echo " CPPFLAGS=OPTIONS command-line options for the preprocessor [${CPPFLAGS}]" - echo " CFLAGS=OPTIONS command-line options for the C compiler [${CFLAGS}]" - echo " CFLAGS+=OPTIONS append options to the current value of CFLAGS" - echo " LDFLAGS=OPTIONS command-line options for the linker [${LDFLAGS}]" - echo " MAKEINFO=NAME makeinfo program to use [${MAKEINFO}]" + echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]" + echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]" + echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]" echo exit 0 ;; --version | -V) @@ -93,12 +90,10 @@ while [ $# != 0 ] ; do --mandir=*) mandir=${optarg} ;; --no-create) no_create=yes ;; - CC=*) CC=${optarg} ;; - CPPFLAGS=*) CPPFLAGS=${optarg} ;; - CFLAGS=*) CFLAGS=${optarg} ;; - CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;; - LDFLAGS=*) LDFLAGS=${optarg} ;; - MAKEINFO=*) MAKEINFO=${optarg} ;; + CC=*) CC=${optarg} ;; + CPPFLAGS=*) CPPFLAGS=${optarg} ;; + CFLAGS=*) CFLAGS=${optarg} ;; + LDFLAGS=*) LDFLAGS=${optarg} ;; --*) echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;; @@ -109,7 +104,7 @@ while [ $# != 0 ] ; do exit 1 ;; esac - # Check whether the option took a separate argument + # Check if the option took a separate argument if [ "${arg2}" = yes ] ; then if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift else echo "configure: Missing argument to '${option}'" 1>&2 @@ -118,19 +113,19 @@ while [ $# != 0 ] ; do fi done -# Find the source code, if location was not specified. +# Find the source files, if location was not specified. srcdirtext= if [ -z "${srcdir}" ] ; then srcdirtext="or . or .." ; srcdir=. if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi if [ ! -r "${srcdir}/${srctrigger}" ] ; then ## the sed command below emulates the dirname command - srcdir=`echo "$0" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` fi fi if [ ! -r "${srcdir}/${srctrigger}" ] ; then - echo "configure: Can't find source code in ${srcdir} ${srcdirtext}" 1>&2 + echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" 1>&2 echo "configure: (At least ${srctrigger} is missing)." 1>&2 exit 1 fi @@ -144,13 +139,13 @@ if [ -z "${no_create}" ] ; then rm -f config.status cat > config.status << EOF #! /bin/sh -# This file was generated automatically by configure. Don't edit. +# This file was generated automatically by configure. Do not edit. # Run this file to recreate the current configuration. # # This script is free software: you have unlimited permission -# to copy, distribute, and modify it. +# to copy, distribute and modify it. -exec /bin/sh "$0" ${args} --no-create +exec /bin/sh $0 ${args} --no-create EOF chmod +x config.status fi @@ -167,15 +162,14 @@ 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-2025 Antonio Diaz Diaz. -# This file was generated automatically by configure. Don't edit. +# Copyright (C) 2010-2015 Antonio Diaz Diaz. +# This file was generated automatically by configure. Do not edit. # # This Makefile is free software: you have unlimited permission -# to copy, distribute, and modify it. +# to copy, distribute and modify it. pkgname = ${pkgname} pkgversion = ${pkgversion} @@ -191,7 +185,6 @@ 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 81ab168..0c97f2c 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,33 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. -.TH PDLZIP "1" "January 2025" "pdlzip 1.14" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. +.TH PDLZIP "1" "May 2015" "pdlzip 1.6" "User Commands" .SH NAME pdlzip \- reduces the size of files .SH SYNOPSIS .B pdlzip [\fI\,options\/\fR] [\fI\,files\/\fR] .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. -.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 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. -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 \- 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. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR @@ -36,14 +18,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 -write to standard output, keep input files +send output to standard output .TP \fB\-d\fR, \fB\-\-decompress\fR -decompress, test compressed file integrity +decompress .TP \fB\-f\fR, \fB\-\-force\fR overwrite existing output files @@ -58,7 +37,7 @@ keep (don't delete) input files set match length limit in bytes [36] .TP \fB\-o\fR, \fB\-\-output=\fR -write to , keep input files +if reading stdin, place the output into .TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages @@ -72,47 +51,35 @@ test compressed file integrity \fB\-v\fR, \fB\-\-verbose\fR be verbose (a 2nd \fB\-v\fR gives more) .TP -\fB\-0\fR .. \fB\-9\fR +\fB\-1\fR .. \fB\-9\fR set compression level [default 6] .TP \fB\-\-fast\fR -alias for \fB\-0\fR +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. +If no file names are given, 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. +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 +options directly to achieve optimal performance. For example, \fB\-9m64\fR +usually compresses executables more (and faster) than \fB\-9\fR. .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. -.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 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. +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. .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 2025 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. License 2\-clause BSD. .br diff --git a/lzip.h b/lzip.h index 7dc9ee3..3b8d172 100644 --- a/lzip.h +++ b/lzip.h @@ -1,37 +1,42 @@ -/* Pdlzip - LZMA lossless data compressor - Copyright (C) 2010-2025 Antonio Diaz Diaz. +/* Pdlzip - LZMA lossless data compressor + Copyright (C) 2010-2015 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 __cplusplus +enum Bool { false = 0, true = 1 }; +typedef enum Bool bool; +#endif + #ifndef max #define max(x,y) ((x) >= (y) ? (x) : (y)) #endif +#ifndef min + #define min(x,y) ((x) <= (y) ? (x) : (y)) +#endif typedef int State; enum { min_dictionary_bits = 12, - min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */ + min_dictionary_size = 1 << min_dictionary_bits, max_dictionary_bits = 29, max_dictionary_size = 1 << max_dictionary_bits, - 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, len_low_bits = 3, @@ -47,6 +52,48 @@ enum { min_match_len_limit = 5 }; +struct Pretty_print + { + const char * 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->stdin_name = "(stdin)"; + pp->longest_name = 0; + pp->first_post = false; + stdin_name_len = strlen( pp->stdin_name ); + + for( i = 0; i < num_filenames; ++i ) + { + const char * const s = filenames[i]; + const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); + if( len > pp->longest_name ) pp->longest_name = len; + } + if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; + } + +static inline void Pp_set_name( struct Pretty_print * const pp, + const char * const filename ) + { + if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) + pp->name = filename; + else pp->name = pp->stdin_name; + 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; @@ -64,24 +111,16 @@ 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 ) { int i; - uint32_t c = *crc; for( i = 0; i < size; ++i ) - c = crc32[(c^buffer[i])&0xFF] ^ ( c >> 8 ); - *crc = c; + *crc = crc32[(*crc^buffer[i])&0xFF] ^ ( *crc >> 8 ); } -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; @@ -90,125 +129,100 @@ static inline int real_bits( unsigned value ) } -static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ +static const uint8_t magic_string[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ -enum { Lh_size = 6 }; -typedef uint8_t Lzip_header[Lh_size]; /* 0-3 magic bytes */ +typedef uint8_t File_header[6]; /* 0-3 magic bytes */ /* 4 version */ - /* 5 coded dictionary size */ + /* 5 coded_dict_size */ +enum { Fh_size = 6 }; -static inline void Lh_set_magic( Lzip_header data ) - { memcpy( data, lzip_magic, 4 ); data[4] = 1; } +static inline void Fh_set_magic( File_header data ) + { memcpy( data, magic_string, 4 ); data[4] = 1; } -static inline bool Lh_check_magic( const Lzip_header data ) - { return memcmp( data, lzip_magic, 4 ) == 0; } +static inline bool Fh_verify_magic( const File_header data ) + { return ( memcmp( data, magic_string, 4 ) == 0 ); } -/* detect (truncated) header */ -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; - } - -/* detect corrupt header */ -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; - } - -static inline uint8_t Lh_version( const Lzip_header data ) +static inline uint8_t Fh_version( const File_header data ) { return data[4]; } -static inline bool Lh_check_version( const Lzip_header data ) - { return data[4] == 1; } +static inline bool Fh_verify_version( const File_header data ) + { return ( data[4] == 1 ); } -static inline unsigned Lh_get_dictionary_size( const Lzip_header data ) +static inline unsigned Fh_get_dictionary_size( const File_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; } -static inline bool Lh_set_dictionary_size( Lzip_header data, const unsigned sz ) +static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) { - if( !isvalid_ds( sz ) ) return false; - data[5] = real_bits( sz - 1 ); - if( sz > min_dictionary_size ) + if( sz >= min_dictionary_size && sz <= max_dictionary_size ) { - const unsigned base_size = 1 << data[5]; - const unsigned fraction = base_size / 16; - unsigned i; - for( i = 7; i >= 1; --i ) - if( base_size - ( i * fraction ) >= sz ) - { data[5] |= i << 5; break; } + 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; } - return true; + return false; } -enum { Lt_size = 20 }; -typedef uint8_t Lzip_trailer[Lt_size]; +typedef uint8_t File_trailer[20]; /* 0-3 CRC32 of the uncompressed data */ /* 4-11 size of the uncompressed data */ /* 12-19 member size including header and trailer */ -static inline unsigned Lt_get_data_crc( const Lzip_trailer data ) +enum { Ft_size = 20 }; + +static inline unsigned Ft_get_data_crc( const File_trailer data ) { unsigned tmp = 0; int i; for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Lt_set_data_crc( Lzip_trailer data, unsigned crc ) +static inline void Ft_set_data_crc( File_trailer data, unsigned crc ) { int i; for( i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } -static inline unsigned long long Lt_get_data_size( const Lzip_trailer data ) +static inline unsigned long long Ft_get_data_size( const File_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 Lt_set_data_size( Lzip_trailer data, unsigned long long sz ) +static inline void Ft_set_data_size( File_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 Lt_get_member_size( const Lzip_trailer data ) +static inline unsigned long long Ft_get_member_size( const File_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 Lt_set_member_size( Lzip_trailer data, unsigned long long sz ) +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; } } -typedef struct Cl_options /* command-line options */ - { - bool ignore_trailing; - bool loose_trailing; - } Cl_options; - -static inline void Cl_options_init( Cl_options * cl_opts ) - { cl_opts->ignore_trailing = true; cl_opts->loose_trailing = false; } - - -static inline void set_retval( int * retval, const int new_val ) - { if( *retval < new_val ) *retval = new_val; } - -static const char * const empty_msg = "Empty member not allowed."; -static const char * const mem_msg = "Not enough memory."; -static const char * const trailing_msg = "Trailing data not allowed."; +/* defined in main.c */ +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; -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 ); +void cleanup_and_fail( const int retval ); +void show_error( const char * const msg, const int errcode, const bool help ); +void internal_error( const char * const msg ); #define SZ_OK 0 diff --git a/main.c b/main.c index f224942..7972e7d 100644 --- a/main.c +++ b/main.c @@ -1,61 +1,55 @@ -/* Pdlzip - LZMA lossless data compressor - 2009-08-14 : Igor Pavlov : Public domain - Copyright (C) 2010-2025 Antonio Diaz Diaz. +/* Pdlzip - LZMA lossless data compressor + 2009-08-14 : Igor Pavlov : Public domain + Copyright (C) 2010-2015 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 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. + 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 #include #include -#include /* CHAR_BIT, SSIZE_MAX */ +#include #include -#include -#include /* SIZE_MAX */ +#include #include #include #include #include #include #include -#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__ +#if defined(__MSVCRT__) #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 -#endif -#if defined __DJGPP__ -#define S_ISSOCK(x) 0 -#define S_ISVTX 0 -#endif +#if defined(__OS2__) +#include #endif #include "carg_parser.h" @@ -71,105 +65,72 @@ #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, - 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_name = "pdlzip"; +const char * const program_year = "2015"; +const char * invocation_name = 0; -static const char * const program_name = "pdlzip"; -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[] = { +struct { const char * from; const char * to; } const known_extensions[] = { { ".lz", "" }, { ".tlz", ".tar" }, { ".lzma", "" }, { 0, 0 } }; -typedef struct Lzma_options +struct Lzma_options { int dictionary_size; /* 4 KiB .. 512 MiB */ int match_len_limit; /* 5 .. 273 */ - } Lzma_options; + }; -typedef enum Mode { m_compress, m_decompress, m_test } Mode; +enum Mode { m_compress, m_decompress, m_test }; -/* Variables used in signal handler context. - They are not declared volatile because the handler never returns. */ -static char * output_filename = 0; -static int outfd = -1; -static bool delete_output_on_interrupt = false; +char * output_filename = 0; +int 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( "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.\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 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" - "lzip format. Lziprecover can convert some lzma-alone files to lzip format\n" - "without recompressing.\n" + 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" "\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" - " -a, --trailing-error exit with error status if trailing data\n" - " -c, --stdout write to standard output, keep input files\n" - " -d, --decompress decompress, test compressed file integrity\n" + " -c, --stdout send output to standard output\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= write to , keep input files\n" + " -o, --output= if reading stdin, place the output into \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" " -v, --verbose be verbose (a 2nd -v gives more)\n" - " -0 .. -9 set compression level [default 6]\n" - " --fast alias for -0\n" + " -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" - "\nIf no file names are given, or if a file is '-', pdlzip compresses or\n" - "decompresses from standard input to standard output.\n" + "If no file names are given, pdlzip compresses or decompresses\n" + "from standard input to standard output.\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" - "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\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" + "The 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" + "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" + "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" "\nReport bugs to lzip-bug@nongnu.org\n" "Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" ); } @@ -186,164 +147,45 @@ static void show_version( void ) } -/* 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( mem_msg, 0, false ); cleanup_and_fail( 1 ); } - return buf; - } - - -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( Pretty_print * const pp, - const char * const filenames[], const int num_filenames ) - { - pp->name = 0; - pp->padded_name = 0; - pp->stdin_name = "(stdin)"; - pp->longest_name = 0; - pp->first_post = false; - - if( verbosity <= 0 ) return; - const unsigned stdin_name_len = strlen( pp->stdin_name ); - int i; - for( i = 0; i < num_filenames; ++i ) - { - const char * const s = filenames[i]; - const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); - if( pp->longest_name < len ) pp->longest_name = len; - } - if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; - } - -void Pp_free( Pretty_print * const pp ) - { if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } } - -static void Pp_set_name( Pretty_print * const pp, const char * const filename ) - { - unsigned name_len, padded_name_len, i = 0; - - if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) - pp->name = filename; - else pp->name = pp->stdin_name; - name_len = strlen( pp->name ); - padded_name_len = max( name_len, pp->longest_name ) + 4; - pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 ); - while( i < 2 ) pp->padded_name[i++] = ' '; - while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; } - pp->padded_name[i++] = ':'; - while( i < padded_name_len ) pp->padded_name[i++] = ' '; - pp->padded_name[i] = 0; - pp->first_post = true; - } - -static void Pp_reset( Pretty_print * const pp ) - { if( pp->name && pp->name[0] ) pp->first_post = true; } - -static void Pp_show_msg( Pretty_print * const pp, const char * const msg ) - { - if( verbosity < 0 ) return; - if( pp->first_post ) - { - pp->first_post = false; - fputs( pp->padded_name, stderr ); - if( !msg ) fflush( stderr ); - } - if( msg ) fprintf( stderr, "%s\n", msg ); - } - - static void show_header( const unsigned dictionary_size ) { - enum { factor = 1024, n = 3 }; - const char * const prefix[n] = { "Ki", "Mi", "Gi" }; + 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; - bool exact = num % factor == 0; + unsigned num = dictionary_size, i; + bool exact = ( num % factor == 0 ); - int i; for( i = 0; i < n && ( num > 9999 || ( exact && num >= factor ) ); ++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, "dict %s%4u %sB, ", np, num, p ); + fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); } -/* separate numbers of 5 or more digits in groups of 3 digits using '_' */ -static const char * format_num3( unsigned long long num ) - { - enum { buffers = 8, bufsize = 4 * sizeof num, n = 10 }; - const char * const si_prefix = "kMGTPEZYRQ"; - const char * const binary_prefix = "KMGTPEZYRQ"; - static char buffer[buffers][bufsize]; /* circle of static buffers for printf */ - static int current = 0; - int i; - char * const buf = buffer[current++]; current %= buffers; - char * p = buf + bufsize - 1; /* fill the buffer backwards */ - *p = 0; /* terminator */ - if( num > 9999 ) - { - char prefix = 0; /* try binary first, then si */ - for( i = 0; i < n && num != 0 && num % 1024 == 0; ++i ) - { num /= 1024; prefix = binary_prefix[i]; } - if( prefix ) *(--p) = 'i'; - else - for( i = 0; i < n && num != 0 && num % 1000 == 0; ++i ) - { num /= 1000; prefix = si_prefix[i]; } - if( prefix ) *(--p) = prefix; - } - const bool split = num >= 10000; - - for( i = 0; ; ) - { - *(--p) = num % 10 + '0'; num /= 10; if( num == 0 ) break; - if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; } - } - return p; - } - - -void show_option_error( const char * const arg, const char * const msg, - const char * const option_name ) - { - if( verbosity >= 0 ) - fprintf( stderr, "%s: '%s': %s option '%s'.\n", - program_name, arg, msg, option_name ); - } - - -/* Recognized formats: k, Ki, [MGTPEZYRQ][i] */ -static unsigned long getnum( const char * const arg, - const char * const option_name, +static unsigned long getnum( const char * const ptr, const unsigned long llimit, const unsigned long ulimit ) { + unsigned long result; char * tail; errno = 0; - unsigned long result = strtoul( arg, &tail, 0 ); - if( tail == arg ) - { show_option_error( arg, "Bad or missing numerical argument in", - option_name ); exit( 1 ); } + result = strtoul( ptr, &tail, 0 ); + if( tail == ptr ) + { + show_error( "Bad or missing numerical argument.", 0, true ); + exit( 1 ); + } if( !errno && tail[0] ) { - const unsigned factor = (tail[1] == 'i') ? 1024 : 1000; - int exponent = 0; /* 0 = bad multiplier */ - int i; + int factor = ( tail[1] == 'i' ) ? 1024 : 1000; + int exponent = 0, i; + bool bad_multiplier = false; switch( tail[0] ) { - case 'Q': exponent = 10; break; - case 'R': exponent = 9; break; + case ' ': break; case 'Y': exponent = 8; break; case 'Z': exponent = 7; break; case 'E': exponent = 6; break; @@ -351,12 +193,17 @@ static unsigned long getnum( const char * const arg, case 'T': exponent = 4; break; case 'G': exponent = 3; break; case 'M': exponent = 2; break; - case 'K': if( factor == 1024 ) exponent = 1; break; - case 'k': if( factor == 1000 ) exponent = 1; 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; + } + if( bad_multiplier ) + { + show_error( "Bad multiplier in numerical argument.", 0, true ); + exit( 1 ); } - if( exponent <= 0 ) - { 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; @@ -366,81 +213,120 @@ static unsigned long getnum( const char * const arg, if( !errno && ( result < llimit || result > ulimit ) ) errno = ERANGE; if( errno ) { - if( verbosity >= 0 ) - fprintf( stderr, "%s: '%s': Value out of limits [%s,%s] in " - "option '%s'.\n", program_name, arg, format_num3( llimit ), - format_num3( ulimit ), option_name ); + show_error( "Numerical argument out of limits.", 0, false ); exit( 1 ); } return result; } -static int get_dict_size( const char * const arg, const char * const option_name ) +static int get_dict_size( const char * const arg ) { char * tail; - const long bits = strtol( arg, &tail, 0 ); + const int bits = strtol( arg, &tail, 0 ); if( bits >= min_dictionary_bits && - bits <= max_dictionary_bits_c && *tail == 0 ) - return 1 << bits; - return getnum( arg, option_name, min_dictionary_size, max_dictionary_size_c ); - } - - -static void set_mode( Mode * const program_modep, const 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; + bits <= max_dictionary_bits && *tail == 0 ) + return ( 1 << bits ); + return getnum( arg, min_dictionary_size, max_dictionary_size ); } static int extension_index( const char * const name ) { - int eindex; - for( eindex = 0; known_extensions[eindex].from; ++eindex ) + int i; + for( i = 0; known_extensions[i].from; ++i ) { - const char * const ext = known_extensions[eindex].from; + const char * const ext = known_extensions[i].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 eindex; + return i; } return -1; } -static void set_c_outname( const char * const name, const bool filenames_given, - const bool force_ext ) +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 ) { - /* 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 || - ( !filenames_given && extension_index( output_filename ) < 0 ) ) - strcat( output_filename, known_extensions[0].from ); + 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 ); + } + else + { + 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 ) ); + } + 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 ) ) ); + 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" : "" ); + close( infd ); + infd = -1; + } + } + } + return infd; } -static void set_d_outname( const char * const name, const int eindex ) +/* assure at least a minimum size for buffer 'buf' */ +static void * resize_buffer( void * buf, const int 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 i ) { const unsigned name_len = strlen( name ); - if( eindex >= 0 ) + if( i >= 0 ) { - const char * const from = known_extensions[eindex].from; + const char * const from = known_extensions[i].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 ); + strlen( known_extensions[0].to ) + 1 ); strcpy( output_filename, name ); - strcpy( output_filename + name_len - from_len, known_extensions[eindex].to ); + strcpy( output_filename + name_len - from_len, known_extensions[i].to ); return; } } @@ -448,128 +334,71 @@ static void set_d_outname( const char * const name, const int eindex ) strcpy( output_filename, name ); strcat( output_filename, ".out" ); if( verbosity >= 1 ) - fprintf( stderr, "%s: %s: Can't guess original name -- using '%s'\n", + fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n", program_name, name, output_filename ); } -static int open_instream( const char * const name, struct stat * const in_statsp, - const Mode program_mode, const int eindex, - const bool one_to_one, const bool recompress ) +static bool open_outstream( const bool force ) { - if( program_mode == m_compress && !recompress && eindex >= 0 ) - { - if( verbosity >= 0 ) - fprintf( stderr, "%s: %s: Input file already has '%s' suffix, ignored.\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 - { - 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: %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" : "" ); - close( infd ); - infd = -1; - } - } - return infd; - } - - -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 = protect ? usr_rw : all_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 ) delete_output_on_interrupt = true; - 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; + if( outfd < 0 && 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 ); } -static void set_signals( void (*action)(int) ) +static bool check_tty( const int infd, const enum Mode program_mode ) { - signal( SIGHUP, action ); - signal( SIGINT, action ); - signal( SIGTERM, action ); + 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_error( "I won't read compressed data from a terminal.", 0, true ); + return false; + } + return true; } -static void cleanup_and_fail( const int retval ) +void cleanup_and_fail( const int retval ) { - set_signals( SIG_IGN ); /* ignore signals */ if( delete_output_on_interrupt ) { delete_output_on_interrupt = false; - show_file_error( output_filename, "Deleting output file, if it exists.", 0 ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n", + program_name, output_filename ); if( outfd >= 0 ) { close( outfd ); outfd = -1; } if( remove( output_filename ) != 0 && errno != ENOENT ) - show_error( "warning: deletion of output file failed", errno, false ); + show_error( "WARNING: deletion of output file (apparently) failed.", 0, false ); } exit( retval ); } -static void signal_handler( int sig ) - { - if( sig ) {} /* keep compiler happy */ - show_error( "Control-C or similar caught, quitting.", 0, false ); - cleanup_and_fail( 1 ); - } - - -static bool check_tty_in( const char * const input_filename, const int infd, - const 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, 2 ); - if( program_mode != m_test ) cleanup_and_fail( *retval ); - return false; } - return true; - } - -static bool check_tty_out( const 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. */ + /* Set permissions, owner and times. */ static void close_and_set_permissions( const struct stat * const in_statsp ) { bool warning = false; if( in_statsp ) { const mode_t mode = in_statsp->st_mode; - /* fchown in many cases returns with EPERM, which can be safely ignored. */ + /* fchown will in many cases return with EPERM, which can be safely ignored. */ if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 ) { if( fchmod( outfd, mode ) != 0 ) warning = true; } else @@ -577,9 +406,7 @@ 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 ) - { show_file_error( output_filename, "Error closing output file", errno ); - cleanup_and_fail( 1 ); } + if( close( outfd ) != 0 ) cleanup_and_fail( 1 ); outfd = -1; delete_output_on_interrupt = false; if( in_statsp ) @@ -590,25 +417,23 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) if( utime( output_filename, &t ) != 0 ) warning = true; } if( warning && verbosity >= 1 ) - show_file_error( output_filename, - "warning: can't change output file attributes", errno ); + show_error( "Can't change output file attributes.", 0, false ); } -static int compress( const int infd, - const Lzma_options * const encoder_options, - Pretty_print * const pp ) +static int compress( const struct Lzma_options * const encoder_options, + const int infd, struct Pretty_print * const pp ) { int retval = 0; CLzmaEncHandle encoder = 0; - Lzip_header header; - Lh_set_magic( header ); + File_header header; + Fh_set_magic( header ); if( verbosity >= 1 ) Pp_show_msg( pp, 0 ); - if( Lh_set_dictionary_size( header, encoder_options->dictionary_size ) && + if( Fh_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( Lh_get_dictionary_size( header ), + encoder = LzmaEnc_Init( Fh_get_dictionary_size( header ), encoder_options->match_len_limit, infd, outfd ); else internal_error( "invalid argument to encoder." ); @@ -618,8 +443,8 @@ static int compress( const int infd, return 1; } - if( writeblock( outfd, header, Lh_size ) != Lh_size ) - { show_error( "Write error", errno, false ); retval = 1; } + if( writeblock( outfd, header, Fh_size ) != Fh_size ) + { show_error( "Can not write output file", errno, false ); retval = 1; } else if( LzmaEnc_Encode( encoder ) != 0 ) { Pp_show_msg( pp, "Encoder error." ); retval = 1; } @@ -628,28 +453,6 @@ static int compress( const int infd, } -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) @@ -681,13 +484,12 @@ 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 unsigned dictionary_size, - const bool testing ) + int * const inSize, const bool testing ) { - unsigned long long member_size = lzma_header_size, data_size = 0; + unsigned long long total_in = lzma_header_size, total_out = 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 (;;) { @@ -709,14 +511,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; - member_size += inProcessed; + total_in += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) - { show_error( "Write error", errno, false ); return 1; } + { show_error( "Can not write output file", errno, false ); return 1; } - data_size += outPos; + total_out += outPos; outPos = 0; if( ( inProcessed == 0 && outProcessed == 0 ) || @@ -725,21 +527,23 @@ 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; } - show_results( data_size, member_size, 0, dictionary_size, false ); + if( verbosity >= 2 ) + { fprintf( stderr, "lzma-alone, " ); show_header( decoder->dicBufSize ); } + if( verbosity >= 3 ) + fprintf( stderr, "uncompressed size %9llu, compressed size %8llu. ", + total_out, total_in ); if( verbosity >= 1 ) - fputs( testing ? "(apparently) ok\n" : "(apparently) done\n", stderr ); + fprintf( stderr, testing ? "(apparently) ok\n" : "(apparently) done\n" ); return 0; } } } -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 ) +static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[], + int * const inPos, int * const inSize ) { - unsigned long long member_size = Lh_size, data_size = 0; + unsigned long long total_in = Fh_size, total_out = 0; uint8_t outBuf[OUT_BUF_SIZE]; int outPos = 0; uint32_t crc = 0xFFFFFFFFU; @@ -754,95 +558,85 @@ static int lzip_decode( CLzmaDec * decoder, const int infd, if( *inPos >= *inSize && !read_inbuf( infd, inBuf, inPos, inSize ) ) return 1; if( *inPos >= *inSize ) - { Pp_show_msg( pp, "Unexpected EOF." ); return 2; } + { show_error( "Unexpected EOF.", 0, false ); return 2; } inProcessed = *inSize - *inPos; if( !LzmaDec_DecodeToBuf( decoder, outBuf + outPos, &outProcessed, inBuf + *inPos, &inProcessed, finishMode, &status ) ) - { Pp_show_msg( pp, "Data error." ); return 2; } + { show_error( "Data error.", 0, false ); return 2; } *inPos += inProcessed; - member_size += inProcessed; + total_in += inProcessed; outPos += outProcessed; if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) - { show_error( "Write error", errno, false ); return 1; } + { show_error( "Can not write output file", errno, false ); return 1; } CRC32_update_buf( &crc, outBuf, outPos ); - data_size += outPos; + total_out += outPos; outPos = 0; if (inProcessed == 0 && outProcessed == 0) { - Lzip_trailer trailer; + 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 ) - { Pp_show_msg( pp, "Data error." ); return 2; } - if( *inSize - *inPos < Lt_size && + { show_error( "Data error.", 0, false ); return 2; } + if( *inSize - *inPos < Ft_size && !read_inbuf( infd, inBuf, inPos, inSize ) ) return 1; - if( *inSize - *inPos < Lt_size ) + 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 ); - } + fprintf( stderr, "Trailer truncated at trailer position %u;" + " some checks may fail.\n", + (unsigned)(*inSize - *inPos) ); + for( i = *inSize - *inPos; i < Ft_size; ++i ) + inBuf[*inPos+i] = 0; } - for( i = 0; i < Lt_size && *inPos < *inSize; ++i ) + for( i = 0; i < Ft_size; ++i ) trailer[i] = inBuf[(*inPos)++]; - member_size += i; - while( i < Lt_size ) trailer[i++] = 0; - crc ^= 0xFFFFFFFFU; - td_crc = Lt_get_data_crc( trailer ); - if( td_crc != crc ) + total_in += Ft_size; + if( Ft_get_data_crc( trailer ) != ( crc ^ 0xFFFFFFFFU ) ) { error = true; if( verbosity >= 0 ) - { - Pp_show_msg( pp, 0 ); - fprintf( stderr, "CRC mismatch; stored %08X, computed %08X\n", - td_crc, crc ); - } + fprintf( stderr, "CRC mismatch; trailer says %08X, data crc is %08X.\n", + Ft_get_data_crc( trailer ), crc ^ 0xFFFFFFFFU ); } - td_size = Lt_get_data_size( trailer ); - if( td_size != data_size ) + if( Ft_get_data_size( trailer ) != total_out ) { error = true; if( verbosity >= 0 ) - { - 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 ); - } + fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX).\n", + Ft_get_data_size( trailer ), total_out, total_out ); } - tm_size = Lt_get_member_size( trailer ); - if( tm_size != member_size ) + if( Ft_get_member_size( trailer ) != total_in ) { error = true; if( verbosity >= 0 ) - { - 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 ); - } + 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 ) + 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, "data CRC %08X, data size %9llu, member size %8llu. ", + Ft_get_data_crc( trailer ), + Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) ); 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, const Cl_options * const cl_opts, - Pretty_print * const pp, - const bool from_stdin, const bool testing ) +static int decompress( const int infd, struct Pretty_print * const pp, + const bool testing ) { uint64_t unpackSize = 0; CLzmaDec decoder; @@ -852,114 +646,127 @@ static int decompress( const int infd, const Cl_options * const cl_opts, 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 ) { int i; - unsigned dictionary_size = 0; /* keep gcc 3.3.6 quiet */ - Lzip_header header; + unsigned dictionary_size = 0; + File_header header; if( inSize - inPos < lzma_header_size && !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; - 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 */ + if( inSize - inPos <= Fh_size ) /* End Of File */ { if( first_member ) - { show_file_error( pp->name, "File ends unexpectedly at member header.", 0 ); + { Pp_show_msg( pp, "File ends unexpectedly at member header." ); retval = 2; } - else if( Lh_check_prefix( header, size ) ) - { Pp_show_msg( pp, "Truncated header in multimember file." ); - retval = 2; } - else if( size > 0 && !cl_opts->ignore_trailing ) - { Pp_show_msg( pp, trailing_msg ); retval = 2; } break; } - if( !Lh_check_magic( header ) ) + for( i = 0; i < Fh_size; ++i ) raw_props[i] = header[i] = inBuf[inPos++]; + if( !Fh_verify_magic( header ) ) { - if( !first_member ) + if( !first_member ) break; /* trailing garbage */ + if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */ { - if( !cl_opts->loose_trailing && Lh_check_corrupt( header ) ) - { Pp_show_msg( pp, "Corrupt header in multimember file." ); - retval = 2; } - else if( !cl_opts->ignore_trailing ) - { Pp_show_msg( pp, trailing_msg ); retval = 2; } - break; - } - if( inSize - inPos >= lzma_header_size - Lh_size ) /* try lzma-alone */ - { - for( i = Lh_size; i < lzma_header_size; ++i ) + 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 ) { - show_file_error( pp->name, - "Bad magic number (file not in lzip format).", 0 ); + Pp_show_msg( pp, "Bad magic number (file not in lzip format)." ); retval = 2; break; } } if( lzip_mode ) { - if( !Lh_check_version( header ) ) + int ds, i; + if( !Fh_verify_version( header ) ) { if( verbosity >= 0 ) { Pp_show_msg( pp, 0 ); fprintf( stderr, "Version %d member format not supported.\n", - Lh_version( header ) ); } + Fh_version( header ) ); } retval = 2; break; } - dictionary_size = Lh_get_dictionary_size( header ); - if( !isvalid_ds( dictionary_size ) ) + dictionary_size = Fh_get_dictionary_size( header ); + if( dictionary_size < min_dictionary_size || + dictionary_size > max_dictionary_size ) { Pp_show_msg( pp, "Invalid dictionary size in member header." ); retval = 2; break; } raw_props[0] = 93; /* (45 * 2) + (9 * 0) + 3 */ - int ds = dictionary_size; + ds = dictionary_size; for( i = 1; i <= 4; ++i ) { raw_props[i] = ds & 0xFF; ds >>= 8; } } if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) - Pp_show_msg( pp, 0 ); + { Pp_show_msg( pp, 0 ); + if( lzip_mode && verbosity >= 3 ) show_header( dictionary_size ); } if( !LzmaDec_Init( &decoder, raw_props ) ) - { Pp_show_msg( pp, mem_msg ); return 1; } - bool data0 = false; + { + show_error( "Not enough memory.", 0, false ); + cleanup_and_fail( 1 ); + } if( lzip_mode ) - retval = lzip_decode( &decoder, infd, pp, inBuf, &inPos, &inSize, - dictionary_size, &data0 ); + retval = lzip_decode( &decoder, infd, inBuf, &inPos, &inSize ); else - retval = lzma_decode( unpackSize, &decoder, infd, inBuf, &inPos, - &inSize, dictionary_size, testing ); + retval = lzma_decode( unpackSize, &decoder, infd, + inBuf, &inPos, &inSize, 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 ); } + { fprintf( stderr, testing ? "ok\n" : "done\n" ); 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; } + fprintf( stderr, testing ? "ok\n" : "done\n" ); return 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 ); + } + + +static void set_signals( void ) + { + signal( SIGHUP, signal_handler ); + signal( SIGINT, signal_handler ); + signal( SIGTERM, signal_handler ); + } + + CRC32 crc32; -/* Return the number of bytes really read. - If (value returned < size) and (errno == 0), means EOF was reached. +void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) + { + if( verbosity >= 0 ) + { + if( pp->first_post ) + { + int i, len; + pp->first_post = false; + fprintf( stderr, " %s: ", pp->name ); + len = pp->longest_name - strlen( pp->name ); + for( i = 0; i < len; ++i ) fprintf( 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. */ int readblock( const int fd, uint8_t * const buf, const int size ) { @@ -977,8 +784,8 @@ int readblock( const int fd, uint8_t * const buf, const int size ) } -/* Return the number of bytes really written. - If (value returned < size), it is always an error. +/* Returns the number of bytes really written. + If (returned value < size), it is always an error. */ int writeblock( const int fd, const uint8_t * const buf, const int size ) { @@ -995,31 +802,24 @@ int writeblock( const int fd, const uint8_t * const buf, const int size ) } -static 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%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 ); - } - - -static void show_file_error( const char * const filename, - const char * const msg, const int errcode ) +void show_error( const char * const msg, const int errcode, const bool help ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg, - ( errcode > 0 ) ? ": " : "", - ( errcode > 0 ) ? strerror( errcode ) : "" ); + { + 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 ); + } } -static void internal_error( const char * const msg ) +void internal_error( const char * const msg ) { if( verbosity >= 0 ) fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); @@ -1029,11 +829,11 @@ static void internal_error( const char * const msg ) 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 Lzma_options option_mapping[] = + /* Mapping from gzip/bzip2 style 1..9 compression modes + to the corresponding LZMA compression modes. */ + const struct Lzma_options option_mapping[] = { - { 1 << 16, 5 }, /* -0 */ + { 1 << 20, 5 }, /* -0 */ { 1 << 20, 5 }, /* -1 */ { 3 << 19, 6 }, /* -2 */ { 1 << 21, 8 }, /* -3 */ @@ -1043,217 +843,209 @@ int main( const int argc, const char * const argv[] ) { 1 << 24, 68 }, /* -7 */ { 3 << 23, 132 }, /* -8 */ { 1 << 25, 273 } }; /* -9 */ - Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ + struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ + const char * input_filename = ""; const char * default_output_filename = ""; - Mode program_mode = m_compress; - Cl_options cl_opts; /* command-line options */ - Cl_options_init( &cl_opts ); + const char ** filenames = 0; + int num_filenames = 0; + int infd = -1; + enum Mode program_mode = m_compress; + int argind = 0; + int retval = 0; + int i; + bool filenames_given = false; bool force = false; bool keep_input_files = false; bool recompress = false; bool to_stdout = false; - if( argc > 0 ) invocation_name = argv[0]; + struct Pretty_print pp; - enum { opt_lt = 256 }; - const ap_Option options[] = + 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 }, - { opt_lt, "loose-trailing", 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 }, + { '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 } }; + struct Arg_parser parser; + + invocation_name = argv[0]; CRC32_init(); - /* static because valgrind complains and memory management in C sucks */ - static Arg_parser parser; if( !ap_init( &parser, argc, argv, options, 0 ) ) - { show_error( mem_msg, 0, false ); return 1; } + { show_error( "Not enough memory.", 0, false ); return 1; } if( ap_error( &parser ) ) /* bad option */ { show_error( ap_error( &parser ), 0, true ); return 1; } - int argind = 0; for( ; argind < ap_arguments( &parser ); ++argind ) { const int code = ap_code( &parser, argind ); - if( !code ) break; /* no more options */ - const char * const pn = ap_parsed_name( &parser, argind ); const char * const arg = ap_argument( &parser, argind ); + if( !code ) break; /* no more options */ switch( code ) { - case '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': cl_opts.ignore_trailing = false; break; - case 'b': break; /* ignored */ + case 'b': break; case 'c': to_stdout = true; break; - case 'd': set_mode( &program_mode, m_decompress ); break; + case 'd': program_mode = m_decompress; break; case 'f': force = true; break; case 'F': recompress = true; break; case 'h': show_help(); return 0; 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; /* ignored */ - case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true; - else { default_output_filename = arg; } break; + getnum( arg, min_match_len_limit, max_match_len ); break; + case 'n': break; + case 'o': default_output_filename = arg; break; case 'q': verbosity = -1; break; - case 's': encoder_options.dictionary_size = get_dict_size( arg, pn ); + case 's': encoder_options.dictionary_size = get_dict_size( arg ); break; - case 'S': break; /* ignored */ - case 't': set_mode( &program_mode, m_test ); break; + case 'S': break; + case 't': program_mode = m_test; break; case 'v': if( verbosity < 4 ) ++verbosity; break; case 'V': show_version(); return 0; - case opt_lt: cl_opts.loose_trailing = true; break; - default: internal_error( "uncaught option." ); + default : internal_error( "uncaught option." ); } } /* end process options */ -#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__ +#if defined(__MSVCRT__) || defined(__OS2__) setmode( STDIN_FILENO, O_BINARY ); setmode( STDOUT_FILENO, O_BINARY ); #endif - static const char ** filenames = 0; - int num_filenames = max( 1, ap_arguments( &parser ) - argind ); + 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] = "-"; - int i; - bool filenames_given = false; for( i = 0; argind + i < ap_arguments( &parser ); ++i ) { filenames[i] = ap_argument( &parser, argind + i ); if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true; } - if( 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] ) ) + set_signals(); - 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 ); - - static Pretty_print pp; Pp_init( &pp, filenames, num_filenames ); - int failed_tests = 0; - int retval = 0; - const bool one_to_one = !to_stdout && program_mode != m_test && !to_file; - bool stdin_used = false; - struct stat in_stats; + output_filename = resize_buffer( output_filename, 1 ); for( i = 0; i < num_filenames; ++i ) { - const char * input_filename = ""; - int infd; - const bool from_stdin = strcmp( filenames[i], "-" ) == 0; + int tmp; + struct stat in_stats; + const struct stat * in_statsp; + output_filename[0] = 0; - Pp_set_name( &pp, filenames[i] ); - if( from_stdin ) + if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) { - if( stdin_used ) continue; else stdin_used = true; + input_filename = ""; infd = STDIN_FILENO; - if( !check_tty_in( pp.name, infd, program_mode, &retval ) ) continue; - if( one_to_one ) { outfd = STDOUT_FILENO; output_filename[0] = 0; } + 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 ); + else + { + output_filename = resize_buffer( output_filename, + strlen( default_output_filename ) + 1 ); + strcpy( output_filename, default_output_filename ); + } + outfd_mode = all_rw; + if( !open_outstream( force ) ) + { + if( retval < 1 ) retval = 1; + close( infd ); infd = -1; + continue; + } + } + } } else { - const int eindex = extension_index( input_filename = filenames[i] ); + const int eindex = extension_index( filenames[i] ); + input_filename = filenames[i]; infd = open_instream( input_filename, &in_stats, program_mode, - 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 checking infd */ + eindex, recompress, to_stdout ); + if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } + if( program_mode != m_test ) { - 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; } + if( to_stdout ) outfd = STDOUT_FILENO; + else + { + 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( retval < 1 ) retval = 1; + close( infd ); infd = -1; + continue; + } + } } } - if( one_to_one && !check_tty_out( program_mode ) ) - { set_retval( &retval, 1 ); return retval; } /* don't delete a tty */ + if( !check_tty( infd, program_mode ) ) return 1; - if( to_file && outfd < 0 ) /* open outfd after checking infd */ - { - 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 */ - } - - const struct stat * const in_statsp = - ( input_filename[0] && one_to_one ) ? &in_stats : 0; - int tmp; + 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( infd, &encoder_options, &pp ); + tmp = compress( &encoder_options, infd, &pp ); else - 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 ); - set_retval( &tmp, 1 ); } - set_retval( &retval, tmp ); - if( tmp ) - { if( program_mode != m_test ) cleanup_and_fail( retval ); - else ++failed_tests; } + tmp = decompress( infd, &pp, program_mode == m_test ); + if( tmp > retval ) retval = tmp; + if( tmp && program_mode != m_test ) cleanup_and_fail( retval ); - if( delete_output_on_interrupt && one_to_one ) + if( delete_output_on_interrupt ) close_and_set_permissions( in_statsp ); - if( input_filename[0] && !keep_input_files && one_to_one ) - remove( input_filename ); + if( input_filename[0] ) + { + close( infd ); infd = -1; + if( !keep_input_files && !to_stdout && program_mode != m_test ) + remove( input_filename ); + } } - if( delete_output_on_interrupt ) /* -o */ - close_and_set_permissions( ( retval == 0 && !stdin_used && - filenames_given && num_filenames == 1 ) ? &in_stats : 0 ); - else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */ + if( outfd >= 0 && close( outfd ) != 0 ) { - show_error( "Error closing stdout", errno, false ); - set_retval( &retval, 1 ); + show_error( "Can't close 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 ); - Pp_free( &pp ); free( filenames ); ap_free( &parser ); return retval; diff --git a/testsuite/check.sh b/testsuite/check.sh index 1760359..3fab78e 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-2025 Antonio Diaz Diaz. +# Copyright (C) 2010-2015 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 @@ -17,391 +17,121 @@ if [ ! -f "${LZIP}" ] || [ ! -x "${LZIP}" ] ; then exit 1 fi -[ -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 - } - if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp -cd "${objdir}"/tmp || framework_failure +cd "${objdir}"/tmp -cp "${testdir}"/test.txt in || framework_failure +cat "${testdir}"/test.txt > in || framework_failure in_lz="${testdir}"/test.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)" ; } printf "testing pdlzip-%s..." "$2" -"${LZIP}" -fkqm4 in -[ $? = 1 ] || test_failed $LINENO -[ ! -e in.lz ] || test_failed $LINENO -"${LZIP}" -fkqm274 in -[ $? = 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 ] || test_failed $LINENO $i - [ ! -e in.lz ] || test_failed $LINENO $i -done -"${LZIP}" -tq in -[ $? = 2 ] || test_failed $LINENO -"${LZIP}" -tq < in -[ $? = 2 ] || test_failed $LINENO +"${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}" -cdq in -[ $? = 2 ] || test_failed $LINENO +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -cdq < in -[ $? = 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}" -cdt "${in_lz}" 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 -"${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 +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 -printf "\ntesting decompression..." +"${LZIP}" -t "${in_lz}" || fail=1 +"${LZIP}" -cd "${in_lz}" > copy || fail=1 +cmp in copy || fail=1 +printf . -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" - "${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 +"${LZIP}" -t "${testdir}"/test.txt.lzma || fail=1 +"${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || fail=1 +cmp in copy || fail=1 +printf . -cp "${in_lz}" out.lz || framework_failure -"${LZIP}" -dk out.lz || test_failed $LINENO -cmp in out || test_failed $LINENO -rm -f out || framework_failure -"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO -cp fox copy || framework_failure -cp "${in_lz}" copy.lz || framework_failure -"${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out -[ $? = 1 ] || test_failed $LINENO -[ ! -e out.lz ] || test_failed $LINENO -cmp fox copy || test_failed $LINENO -cmp in out || test_failed $LINENO -"${LZIP}" -df copy.lz || test_failed $LINENO -[ ! -e copy.lz ] || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f copy out || framework_failure +cat "${in_lz}" > copy.lz || framework_failure +printf "to be overwritten" > copy || framework_failure +"${LZIP}" -df copy.lz || fail=1 +cmp in copy || fail=1 +printf . -printf "to be overwritten" > out || framework_failure -"${LZIP}" -df -o out < "${in_lz}" || test_failed $LINENO -cmp in out || test_failed $LINENO -"${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO -cmp in ./- || test_failed $LINENO -rm -f ./- || framework_failure -"${LZIP}" -d -o ./- < "${in_lz}" || test_failed $LINENO -cmp in ./- || test_failed $LINENO -rm -f ./- || framework_failure +printf "to be overwritten" > copy || framework_failure +"${LZIP}" -df -o copy < "${in_lz}" || fail=1 +cmp in copy || fail=1 +printf . -cp "${in_lz}" anyothername || framework_failure -"${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null || - test_failed $LINENO -cmp in out || test_failed $LINENO -cmp in anyothername.out || test_failed $LINENO -rm -f anyothername.out || framework_failure - -"${LZIP}" -tq in "${in_lz}" -[ $? = 2 ] || test_failed $LINENO -"${LZIP}" -tq nx_file.lz "${in_lz}" -[ $? = 1 ] || test_failed $LINENO -"${LZIP}" -cdq in "${in_lz}" > out -[ $? = 2 ] || test_failed $LINENO -cat out in | cmp in - || test_failed $LINENO # out must be empty -"${LZIP}" -cdq nx_file.lz "${in_lz}" > out # skip nx_file, decompress in -[ $? = 1 ] || test_failed $LINENO -cmp in out || test_failed $LINENO -rm -f out || 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 - [ $? = 2 ] || test_failed $LINENO $i -done -"${LZIP}" -dq in out.lz -[ $? = 2 ] || 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 out.lz -[ $? = 1 ] || test_failed $LINENO -[ ! -e out.lz ] || test_failed $LINENO -[ ! -e nx_file ] || test_failed $LINENO -cmp in out || test_failed $LINENO -rm -f out || framework_failure +"${LZIP}" -s16 < in > anyothername || fail=1 +"${LZIP}" -d anyothername || fail=1 +cmp in anyothername.out || fail=1 +printf . cat in in > in2 || framework_failure -"${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO -"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > out2 || test_failed $LINENO -[ ! -e out ] || test_failed $LINENO # override -o -cmp in2 out2 || test_failed $LINENO -rm -f out2 || framework_failure -"${LZIP}" -d "${in_lz}" "${in_lz}" -o out2 || test_failed $LINENO -cmp in2 out2 || test_failed $LINENO -rm -f out2 || framework_failure +"${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 . -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 "garbage" >> copy2.lz || framework_failure +printf "to be overwritten" > copy2 || framework_failure +"${LZIP}" -df copy2.lz || fail=1 +cmp in2 copy2 || fail=1 +printf . -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 < out2.lz -[ $? = 2 ] || test_failed $LINENO -"${LZIP}" -adkq out2.lz -[ $? = 2 ] || test_failed $LINENO -[ ! -e out2 ] || test_failed $LINENO -"${LZIP}" -adkq -o out2 < out2.lz -[ $? = 2 ] || test_failed $LINENO -[ ! -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 - -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 -[ ! -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 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}" > 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 -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 +"${LZIP}" -cfq "${in_lz}" > out +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 . 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 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 - [ ! -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 - - "${LZIP}" -$i -s16 < in > out || test_failed $LINENO $i - "${LZIP}" -d < out > copy || test_failed $LINENO $i - cmp in copy || 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 + "${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 done -rm -f copy out.lz || framework_failure +printf . -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\000\101\376\367\377\377\340\000\200\000\215\357\002\322\001\000\000\000\000\000\000\000\045\000\000\000\000\000\000\000' -cp "${in_lz}" int.lz || framework_failure -printf "LZIP${body}" >> int.lz || framework_failure -if "${LZIP}" -t int.lz ; then - for header in ${headers} ; do - 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} - "${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} - cp "${in_lz}" int.lz || framework_failure - printf "${header}${body}" >> int.lz || framework_failure - "${LZIP}" -tq int.lz # trailing data - [ $? = 2 ] || test_failed $LINENO ${header} - "${LZIP}" -tq < int.lz - [ $? = 2 ] || test_failed $LINENO ${header} - "${LZIP}" -cdq int.lz > /dev/null - [ $? = 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 "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 - [ $? = 2 ] || test_failed $LINENO $i +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 done +printf . -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 +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 done -rm -f fox || framework_failure +printf . -cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure -cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure -if dd if=in3.lz of=trunc.lz bs=14682 count=1 2> /dev/null && - [ -e trunc.lz ] && cmp in2.lz trunc.lz ; then - for i in 6 20 14664 14683 14684 14685 14686 14687 14688 ; do - dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null - "${LZIP}" -tq trunc.lz - [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -tq < trunc.lz - [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -cdq trunc.lz > /dev/null - [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -dq < trunc.lz > /dev/null - [ $? = 2 ] || test_failed $LINENO $i - done -else - printf "warning: skipping truncation test: 'dd' does not work on your system." -fi -rm -f in2.lz in3.lz trunc.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 > out -[ $? = 2 ] || test_failed $LINENO -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 ingin.lz || framework_failure +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 +done +printf . echo if [ ${fail} = 0 ] ; then diff --git a/testsuite/fox.lz b/testsuite/fox.lz deleted file mode 100644 index 509da82..0000000 Binary files a/testsuite/fox.lz and /dev/null differ diff --git a/testsuite/fox_bcrc.lz b/testsuite/fox_bcrc.lz deleted file mode 100644 index 8f6a7c4..0000000 Binary files a/testsuite/fox_bcrc.lz and /dev/null differ diff --git a/testsuite/fox_crc0.lz b/testsuite/fox_crc0.lz deleted file mode 100644 index 1abe926..0000000 Binary files a/testsuite/fox_crc0.lz and /dev/null differ diff --git a/testsuite/fox_das46.lz b/testsuite/fox_das46.lz deleted file mode 100644 index 43ed9f9..0000000 Binary files a/testsuite/fox_das46.lz and /dev/null differ diff --git a/testsuite/fox_de20.lz b/testsuite/fox_de20.lz deleted file mode 100644 index 10949d8..0000000 Binary files a/testsuite/fox_de20.lz and /dev/null differ diff --git a/testsuite/fox_mes81.lz b/testsuite/fox_mes81.lz deleted file mode 100644 index d50ef2e..0000000 Binary files a/testsuite/fox_mes81.lz and /dev/null differ diff --git a/testsuite/fox_nz.lz b/testsuite/fox_nz.lz deleted file mode 100644 index 44a4b58..0000000 Binary files a/testsuite/fox_nz.lz and /dev/null differ diff --git a/testsuite/fox_s11.lz b/testsuite/fox_s11.lz deleted file mode 100644 index dca909c..0000000 Binary files a/testsuite/fox_s11.lz and /dev/null differ diff --git a/testsuite/fox_v2.lz b/testsuite/fox_v2.lz deleted file mode 100644 index 8620981..0000000 Binary files a/testsuite/fox_v2.lz and /dev/null differ diff --git a/testsuite/test.txt b/testsuite/test.txt index 423f0c0..9196a3a 100644 --- a/testsuite/test.txt +++ b/testsuite/test.txt @@ -1,7 +1,8 @@ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -338,7 +339,8 @@ Public License instead of this License. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/testsuite/test.txt.lz b/testsuite/test.txt.lz index 5dc169f..41d2e39 100644 Binary files a/testsuite/test.txt.lz and b/testsuite/test.txt.lz differ diff --git a/testsuite/test.txt.lzma b/testsuite/test.txt.lzma index 091c023..77f2b87 100644 Binary files a/testsuite/test.txt.lzma and b/testsuite/test.txt.lzma differ