From d24e3d2e19b79cf553cf5792b0c96398f80f755f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:16 +0100 Subject: [PATCH 01/10] Merging upstream version 0.8. Signed-off-by: Daniel Baumann --- ChangeLog | 15 ++- INSTALL | 19 ++-- Makefile.in | 9 +- NEWS | 19 +++- README | 21 ++-- carg_parser.c | 112 +++++++++++++------- carg_parser.h | 16 +-- configure | 25 +++-- decompress_lunzip.c | 5 +- doc/xlunzip.1 | 16 +-- in_place.c | 26 ++--- linux_lzip.h | 2 +- lzip.h | 18 ++-- lzip_decompress.c | 67 ++++++------ main.c | 245 ++++++++++++++++++++++++++------------------ testsuite/check.sh | 234 ++++++++++++++++++++++-------------------- 16 files changed, 487 insertions(+), 362 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7b6ede5..0c8da07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2024-01-18 Antonio Diaz Diaz + + * Version 0.8 released. + * main.c: Reformat file diagnostics as 'PROGRAM: FILE: MESSAGE'. + (getnum): Show option name and valid range if error. + (show_option_error): New function showing argument and option name. + (main): Make -o preserve date/mode/owner if 1 input file. + * lzip.h: Rename verify_* to check_*. + * configure, Makefile.in: New variable 'MAKEINFO'. + * INSTALL: Document use of CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500'. + 2021-01-01 Antonio Diaz Diaz * Version 0.7 released. @@ -22,7 +33,7 @@ * main.c: Set a valid invocation_name even if argc == 0. * Document extraction from tar.lz in '--help' output and man page. * main.c: Compile on DOS with DJGPP. - * configure: Accept appending to CFLAGS, 'CFLAGS+=OPTIONS'. + * configure: Accept appending to CFLAGS; 'CFLAGS+=OPTIONS'. * testsuite: Add 9 new test files. 2018-09-18 Antonio Diaz Diaz @@ -56,7 +67,7 @@ * Tests the code shipped in linux patches before june 2018. -Copyright (C) 2016-2021 Antonio Diaz Diaz. +Copyright (C) 2016-2024 Antonio Diaz Diaz. This file is a collection of facts, and thus it is not copyrightable, but just in case, you have unlimited permission to copy, distribute, and diff --git a/INSTALL b/INSTALL index 6c8bfa7..ae611fb 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Requirements ------------ You will need a C99 compiler. (gcc 3.3.6 or newer is recommended). -I use gcc 6.1.0 and 4.1.2, but the code should compile with any standards +I use gcc 6.1.0 and 3.3.6, but the code should compile with any standards compliant compiler. Gcc is available at http://gcc.gnu.org. @@ -18,8 +18,8 @@ Procedure or lzip -cd xlunzip[version].tar.lz | tar -xf - -This creates the directory ./xlunzip[version] containing the source from -the main archive. +This creates the directory ./xlunzip[version] containing the source code +extracted from the archive. 2. Change to xlunzip directory and run configure. (Try 'configure --help' for usage instructions). @@ -27,6 +27,10 @@ the main archive. cd xlunzip[version] ./configure + If you choose a C standard, enable the POSIX features explicitly: + + ./configure CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500' + If you are compiling on MinGW, use: ./configure CFLAGS+='-D __USE_MINGW_ANSI_STDIO' @@ -38,7 +42,8 @@ the main archive. 4. Optionally, type 'make check' to run the tests that come with xlunzip. 5. Type 'make install' to install the program and any data files and - documentation. + documentation. You need root privileges to install into a prefix owned + by root. Or type 'make install-compress', which additionally compresses the man page after installation. @@ -61,15 +66,15 @@ object files and executables to go and run the 'configure' script. 'configure' automatically checks for the source code in '.', in '..', and in the directory that 'configure' is in. -'configure' recognizes the option '--srcdir=DIR' to control where to -look for the sources. Usually 'configure' can determine that directory +'configure' recognizes the option '--srcdir=DIR' to control where to look +for the source code. Usually 'configure' can determine that directory automatically. After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2016-2021 Antonio Diaz Diaz. +Copyright (C) 2016-2024 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/Makefile.in b/Makefile.in index 1270170..3df0e26 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20,7 +20,7 @@ objs = carg_parser.o decompress_lunzip.o in_place.o lzip_decompress.o main.o all : $(progname) $(progname) : $(objs) - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(objs) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(objs) main.o : main.c $(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< @@ -28,6 +28,10 @@ main.o : main.c %.o : %.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< +# prevent 'make' from trying to remake source files +$(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ; +%.h %.c : ; + $(objs) : Makefile carg_parser.o : carg_parser.h decompress_lunzip.o : linux_lzip.h linux_lunzip.h linux_mm.h lzip_decompress.c @@ -35,13 +39,12 @@ in_place.o : linux_lunzip.h lzip.h lzip_decompress.o : linux_module.h linux_lzip.h linux_mm.h main.o : carg_parser.h linux_lzip.h linux_lunzip.h lzip.h - doc : man info : $(VPATH)/doc/$(pkgname).info $(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texi - cd $(VPATH)/doc && makeinfo $(pkgname).texi + cd $(VPATH)/doc && $(MAKEINFO) $(pkgname).texi man : $(VPATH)/doc/$(progname).1 diff --git a/NEWS b/NEWS index 7125322..f96a2f3 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,18 @@ -Changes in version 0.7: +Changes in version 0.8: -Xlunzip now does not even open the output file if the input file is a terminal. +File diagnostics have been reformatted as 'PROGRAM: FILE: MESSAGE'. + +In case of error in a numerical argument to a command line option, lunzip +now shows the name of the option and the range of valid values. + +Diagnostics caused by invalid arguments to command-line options now show the +argument and the name of the option. + +The option '-o, --output' now preserves dates, permissions, and ownership of +the file, when decompressing exactly one file. + +The variable MAKEINFO has been added to configure and Makefile.in. + +It has been documented in INSTALL that when choosing a C standard, the POSIX +features need to be enabled explicitly: + ./configure CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500' diff --git a/README b/README index 7395a92..00c45ee 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ Xlunzip is a test tool for the lzip decompression code of my lzip patch for linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress linux module as a backend. Xlunzip tests the module for stream, buffer-to-buffer, and mixed decompression modes, including in-place decompression (using the -same buffer for input and output). You can use xlunzip to verify that the +same buffer for input and output). You can use xlunzip to check that the module produces correct results when decompressing single member files, multimember files, or the concatenation of two or more compressed files. Xlunzip can be used with unzcrash to test the robustness of the module to @@ -26,7 +26,7 @@ Lzip related components in the kernel ===================================== The lzip_decompress module in lib/lzip_decompress.c provides a versatile -lzip decompression function able to do buffer to buffer decompression or +lzip decompression function able to do buffer-to-buffer decompression or stream decompression with fill and flush callback functions. The usage of the function is documented in include/linux/lzip.h. @@ -76,7 +76,7 @@ address | * ,' All we need to know to calculate the minimum required extra space is: The maximum expansion ratio. - The size of the last part of a member required to verify integrity. + The size of the last part of a member required to check integrity. For multimember data, the overhead per member. (36 bytes for lzip). The maximum expansion ratio of LZMA data is of about 1.4%. Rounding this up @@ -87,22 +87,21 @@ required to decompress lzip data in place is: Using the compressed size to calculate the extra_bytes (as in the formula above) may slightly overestimate the amount of space required in the worst -case. But calculating the extra_bytes from the uncompressed size (as does -linux currently) is wrong (and inefficient for high compression ratios). The -formula used in arch/x86/boot/header.S +case (maximum expansion). But calculating the extra_bytes from the +uncompressed size (as does linux currently) is wrong (and inefficient for +high compression ratios). The formula used in arch/x86/boot/header.S: - extra_bytes = ( uncompressed_size >> 8 ) + 65536 + extra_bytes = ( uncompressed_size >> 8 ) + 131072 fails to decompress 1 MB of zeros followed by 8 MB of random data, wastes memory for compression ratios larger than 4:1, and does not even consider multimember data. -Copyright (C) 2016-2021 Antonio Diaz Diaz. +Copyright (C) 2016-2024 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. -The file Makefile.in is a data file used by configure to produce the -Makefile. It has the same copyright owner and permissions that configure -itself. +The file Makefile.in is a data file used by configure to produce the Makefile. +It has the same copyright owner and permissions that configure itself. diff --git a/carg_parser.c b/carg_parser.c index d0c05d5..edb4eb9 100644 --- a/carg_parser.c +++ b/carg_parser.c @@ -1,5 +1,5 @@ -/* Arg_parser - POSIX/GNU command line argument parser. (C version) - Copyright (C) 2006-2021 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command-line argument parser. (C version) + Copyright (C) 2006-2024 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -32,10 +32,10 @@ static void * ap_resize_buffer( void * buf, const int min_size ) } -static char push_back_record( struct Arg_parser * const ap, - const int code, const char * const argument ) +static char push_back_record( struct Arg_parser * const ap, const int code, + const char * const long_name, + const char * const argument ) { - const int len = strlen( argument ); struct ap_Record * p; void * tmp = ap_resize_buffer( ap->data, ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); @@ -43,11 +43,29 @@ static char push_back_record( struct Arg_parser * const ap, ap->data = (struct ap_Record *)tmp; p = &(ap->data[ap->data_size]); p->code = code; - p->argument = 0; - tmp = ap_resize_buffer( p->argument, len + 1 ); - if( !tmp ) return 0; - p->argument = (char *)tmp; - strncpy( p->argument, argument, len + 1 ); + if( long_name ) + { + const int len = strlen( long_name ); + p->parsed_name = (char *)malloc( len + 2 + 1 ); + if( !p->parsed_name ) return 0; + p->parsed_name[0] = p->parsed_name[1] = '-'; + strncpy( p->parsed_name + 2, long_name, len + 1 ); + } + else if( code > 0 && code < 256 ) + { + p->parsed_name = (char *)malloc( 2 + 1 ); + if( !p->parsed_name ) return 0; + p->parsed_name[0] = '-'; p->parsed_name[1] = code; p->parsed_name[2] = 0; + } + else p->parsed_name = 0; + if( argument ) + { + const int len = strlen( argument ); + p->argument = (char *)malloc( len + 1 ); + if( !p->argument ) { free( p->parsed_name ); return 0; } + strncpy( p->argument, argument, len + 1 ); + } + else p->argument = 0; ++ap->data_size; return 1; } @@ -68,12 +86,14 @@ static char add_error( struct Arg_parser * const ap, const char * const msg ) static void free_data( struct Arg_parser * const ap ) { int i; - for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument ); + for( i = 0; i < ap->data_size; ++i ) + { free( ap->data[i].argument ); free( ap->data[i].parsed_name ); } if( ap->data ) { free( ap->data ); ap->data = 0; } ap->data_size = 0; } +/* Return 0 only if out of memory. */ static char parse_long_option( struct Arg_parser * const ap, const char * const opt, const char * const arg, const struct ap_Option options[], @@ -87,9 +107,10 @@ static char parse_long_option( struct Arg_parser * const ap, /* Test all long options for either exact match or abbreviated matches. */ for( i = 0; options[i].code != 0; ++i ) - if( options[i].name && strncmp( options[i].name, &opt[2], len ) == 0 ) + if( options[i].long_name && + strncmp( options[i].long_name, &opt[2], len ) == 0 ) { - if( strlen( options[i].name ) == len ) /* Exact match found */ + if( strlen( options[i].long_name ) == len ) /* Exact match found */ { index = i; exact = 1; break; } else if( index < 0 ) index = i; /* First nonexact match found */ else if( options[index].code != options[i].code || @@ -117,35 +138,39 @@ static char parse_long_option( struct Arg_parser * const ap, { if( options[index].has_arg == ap_no ) { - add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); add_error( ap, "' doesn't allow an argument" ); return 1; } if( options[index].has_arg == ap_yes && !opt[len+3] ) { - add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); add_error( ap, "' requires an argument" ); return 1; } - return push_back_record( ap, options[index].code, &opt[len+3] ); + return push_back_record( ap, options[index].code, + options[index].long_name, &opt[len+3] ); } if( options[index].has_arg == ap_yes ) { if( !arg || !arg[0] ) { - add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); add_error( ap, "' requires an argument" ); return 1; } ++*argindp; - return push_back_record( ap, options[index].code, arg ); + return push_back_record( ap, options[index].code, + options[index].long_name, arg ); } - return push_back_record( ap, options[index].code, "" ); + return push_back_record( ap, options[index].code, + options[index].long_name, 0 ); } +/* Return 0 only if out of memory. */ static char parse_short_option( struct Arg_parser * const ap, const char * const opt, const char * const arg, const struct ap_Option options[], @@ -156,13 +181,13 @@ static char parse_short_option( struct Arg_parser * const ap, while( cind > 0 ) { int index = -1, i; - const unsigned char code = opt[cind]; + const unsigned char c = opt[cind]; char code_str[2]; - code_str[0] = code; code_str[1] = 0; + code_str[0] = c; code_str[1] = 0; - if( code != 0 ) + if( c != 0 ) for( i = 0; options[i].code; ++i ) - if( code == options[i].code ) + if( c == options[i].code ) { index = i; break; } if( index < 0 ) @@ -176,7 +201,7 @@ static char parse_short_option( struct Arg_parser * const ap, if( options[index].has_arg != ap_no && cind > 0 && opt[cind] ) { - if( !push_back_record( ap, code, &opt[cind] ) ) return 0; + if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0; ++*argindp; cind = 0; } else if( options[index].has_arg == ap_yes ) @@ -188,9 +213,9 @@ static char parse_short_option( struct Arg_parser * const ap, return 1; } ++*argindp; cind = 0; - if( !push_back_record( ap, code, arg ) ) return 0; + if( !push_back_record( ap, c, 0, arg ) ) return 0; } - else if( !push_back_record( ap, code, "" ) ) return 0; + else if( !push_back_record( ap, c, 0, 0 ) ) return 0; } return 1; } @@ -203,7 +228,7 @@ char ap_init( struct Arg_parser * const ap, const char ** non_options = 0; /* skipped non-options */ int non_options_size = 0; /* number of skipped non-options */ int argind = 1; /* index in argv */ - int i; + char done = 0; /* false until success */ ap->data = 0; ap->error = 0; @@ -223,20 +248,20 @@ char ap_init( struct Arg_parser * const ap, if( ch2 == '-' ) { if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */ - else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0; + else if( !parse_long_option( ap, opt, arg, options, &argind ) ) goto out; } - else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0; + else if( !parse_short_option( ap, opt, arg, options, &argind ) ) goto out; if( ap->error ) break; } else { if( in_order ) - { if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; } + { if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; } else { void * tmp = ap_resize_buffer( non_options, ( non_options_size + 1 ) * sizeof *non_options ); - if( !tmp ) return 0; + if( !tmp ) goto out; non_options = (const char **)tmp; non_options[non_options_size++] = argv[argind++]; } @@ -245,13 +270,15 @@ char ap_init( struct Arg_parser * const ap, if( ap->error ) free_data( ap ); else { + int i; for( i = 0; i < non_options_size; ++i ) - if( !push_back_record( ap, 0, non_options[i] ) ) return 0; + if( !push_back_record( ap, 0, 0, non_options[i] ) ) goto out; while( argind < argc ) - if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; + if( !push_back_record( ap, 0, 0, argv[argind++] ) ) goto out; } - if( non_options ) free( non_options ); - return 1; + done = 1; +out: if( non_options ) free( non_options ); + return done; } @@ -273,13 +300,20 @@ int ap_arguments( const struct Arg_parser * const ap ) int ap_code( const struct Arg_parser * const ap, const int i ) { - if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code; - else return 0; + if( i < 0 || i >= ap_arguments( ap ) ) return 0; + return ap->data[i].code; + } + + +const char * ap_parsed_name( const struct Arg_parser * const ap, const int i ) + { + if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].parsed_name ) return ""; + return ap->data[i].parsed_name; } const char * ap_argument( const struct Arg_parser * const ap, const int i ) { - if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument; - else return ""; + if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].argument ) return ""; + return ap->data[i].argument; } diff --git a/carg_parser.h b/carg_parser.h index c5f2352..69ce271 100644 --- a/carg_parser.h +++ b/carg_parser.h @@ -1,5 +1,5 @@ -/* Arg_parser - POSIX/GNU command line argument parser. (C version) - Copyright (C) 2006-2021 Antonio Diaz Diaz. +/* Arg_parser - POSIX/GNU command-line argument parser. (C version) + Copyright (C) 2006-2024 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -24,9 +24,9 @@ message. 'options' is an array of 'struct ap_Option' terminated by an element - containing a code which is zero. A null name means a short-only - option. A code value outside the unsigned char range means a - long-only option. + containing a code which is zero. A null long_name means a short-only + option. A code value outside the unsigned char range means a long-only + option. Arg_parser normally makes it appear as if all the option arguments were specified before all the non-option arguments for the purposes @@ -50,7 +50,7 @@ enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; struct ap_Option { int code; /* Short option letter or code ( code != 0 ) */ - const char * name; /* Long option name (maybe null) */ + const char * long_name; /* Long option name (maybe null) */ enum ap_Has_arg has_arg; }; @@ -58,6 +58,7 @@ struct ap_Option struct ap_Record { int code; + char * parsed_name; char * argument; }; @@ -86,6 +87,9 @@ int ap_arguments( const struct Arg_parser * const ap ); Else ap_argument( i ) is the option's argument (or empty). */ int ap_code( const struct Arg_parser * const ap, const int i ); +/* Full name of the option parsed (short or long). */ +const char * ap_parsed_name( const struct Arg_parser * const ap, const int i ); + const char * ap_argument( const struct Arg_parser * const ap, const int i ); #ifdef __cplusplus diff --git a/configure b/configure index b33c121..d13ea80 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Xlunzip - Test tool for the lzip_decompress linux module -# Copyright (C) 2016-2021 Antonio Diaz Diaz. +# Copyright (C) 2016-2024 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute, and modify it. pkgname=xlunzip -pkgversion=0.7 +pkgversion=0.8 progname=xlunzip srctrigger=doc/${progname}.1 @@ -24,6 +24,7 @@ CC=gcc CPPFLAGS= CFLAGS='-Wall -W -O2' LDFLAGS= +MAKEINFO=makeinfo # checking whether we are using GNU C. /bin/sh -c "${CC} --version" > /dev/null 2>&1 || { CC=cc ; CFLAGS=-O2 ; } @@ -57,7 +58,7 @@ while [ $# != 0 ] ; do echo "Options and variables: [defaults in brackets]" echo " -h, --help display this help and exit" echo " -V, --version output version information and exit" - echo " --srcdir=DIR find the sources in DIR [. or ..]" + echo " --srcdir=DIR find the source code in DIR [. or ..]" echo " --prefix=DIR install into DIR [${prefix}]" echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]" echo " --bindir=DIR user executables directory [${bindir}]" @@ -65,10 +66,11 @@ while [ $# != 0 ] ; do echo " --infodir=DIR info files directory [${infodir}]" echo " --mandir=DIR man pages directory [${mandir}]" echo " CC=COMPILER C compiler to use [${CC}]" - echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]" - echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]" + echo " CPPFLAGS=OPTIONS command-line options for the preprocessor [${CPPFLAGS}]" + echo " CFLAGS=OPTIONS command-line options for the C compiler [${CFLAGS}]" echo " CFLAGS+=OPTIONS append options to the current value of CFLAGS" - echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]" + echo " LDFLAGS=OPTIONS command-line options for the linker [${LDFLAGS}]" + echo " MAKEINFO=NAME makeinfo program to use [${MAKEINFO}]" echo exit 0 ;; --version | -V) @@ -96,6 +98,7 @@ while [ $# != 0 ] ; do CFLAGS=*) CFLAGS=${optarg} ;; CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;; LDFLAGS=*) LDFLAGS=${optarg} ;; + MAKEINFO=*) MAKEINFO=${optarg} ;; --*) echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;; @@ -115,7 +118,7 @@ while [ $# != 0 ] ; do fi done -# Find the source files, if location was not specified. +# Find the source code, if location was not specified. srcdirtext= if [ -z "${srcdir}" ] ; then srcdirtext="or . or .." ; srcdir=. @@ -127,7 +130,7 @@ if [ -z "${srcdir}" ] ; then fi if [ ! -r "${srcdir}/${srctrigger}" ] ; then - echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" 1>&2 + echo "configure: Can't find source code in ${srcdir} ${srcdirtext}" 1>&2 echo "configure: (At least ${srctrigger} is missing)." 1>&2 exit 1 fi @@ -147,7 +150,7 @@ if [ -z "${no_create}" ] ; then # This script is free software: you have unlimited permission # to copy, distribute, and modify it. -exec /bin/sh $0 ${args} --no-create +exec /bin/sh "$0" ${args} --no-create EOF chmod +x config.status fi @@ -164,10 +167,11 @@ echo "CC = ${CC}" echo "CPPFLAGS = ${CPPFLAGS}" echo "CFLAGS = ${CFLAGS}" echo "LDFLAGS = ${LDFLAGS}" +echo "MAKEINFO = ${MAKEINFO}" rm -f Makefile cat > Makefile << EOF # Makefile for Xlunzip - Test tool for the lzip_decompress linux module -# Copyright (C) 2016-2021 Antonio Diaz Diaz. +# Copyright (C) 2016-2024 Antonio Diaz Diaz. # This file was generated automatically by configure. Don't edit. # # This Makefile is free software: you have unlimited permission @@ -187,6 +191,7 @@ CC = ${CC} CPPFLAGS = ${CPPFLAGS} CFLAGS = ${CFLAGS} LDFLAGS = ${LDFLAGS} +MAKEINFO = ${MAKEINFO} EOF cat "${srcdir}/Makefile.in" >> Makefile diff --git a/decompress_lunzip.c b/decompress_lunzip.c index 9586bb5..3425997 100644 --- a/decompress_lunzip.c +++ b/decompress_lunzip.c @@ -1,7 +1,7 @@ /* * Wrapper for decompressing LZIP-compressed kernel, initramfs, and initrd * - * Copyright (C) 2016-2021 Antonio Diaz Diaz. + * Copyright (C) 2016-2024 Antonio Diaz Diaz. * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ @@ -62,8 +62,7 @@ STATIC int INIT __lunzip(unsigned char *inbuf, long in_len, case LZIP_BAD_CRC: error("CRC mismatch in LZIP-compressed data."); break; - default: - error("Bug in the LZIP decompressor."); + default: error("Bug in the LZIP decompressor."); } return retval; } diff --git a/doc/xlunzip.1 b/doc/xlunzip.1 index 51c800d..1f870a8 100644 --- a/doc/xlunzip.1 +++ b/doc/xlunzip.1 @@ -1,5 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16. -.TH XLUNZIP "1" "January 2021" "xlunzip 0.7" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH XLUNZIP "1" "January 2024" "xlunzip 0.8" "User Commands" .SH NAME xlunzip \- test tool for the lzip_decompress linux module .SH SYNOPSIS @@ -10,7 +10,7 @@ Xlunzip is a test tool for the lzip decompression code of my lzip patch for linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress linux module as a backend. Xlunzip tests the module for stream, buffer\-to\-buffer, and mixed decompression modes, including in\-place decompression (using the -same buffer for input and output). You can use xlunzip to verify that the +same buffer for input and output). You can use xlunzip to check that the module produces correct results when decompressing single member files, multimember files, or the concatenation of two or more compressed files. Xlunzip can be used with unzcrash to test the robustness of the module to @@ -77,16 +77,16 @@ Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc... To extract all the files from archive 'foo.tar.lz', use the commands \&'tar \fB\-xf\fR foo.tar.lz' or 'xlunzip \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'. .PP -Exit status: 0 for a normal exit, 1 for environmental problems (file -not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or -invalid input file, 3 for an internal consistency error (eg, bug) which -caused xlunzip to panic. +Exit status: 0 for a normal exit, 1 for environmental problems +(file not found, invalid command\-line options, I/O errors, etc), 2 to +indicate a corrupt or invalid input file, 3 for an internal consistency +error (e.g., bug) which caused xlunzip to panic. .SH "REPORTING BUGS" Report bugs to lzip\-bug@nongnu.org .br Xlunzip home page: http://www.nongnu.org/lzip/xlunzip.html .SH COPYRIGHT -Copyright \(co 2021 Antonio Diaz Diaz. +Copyright \(co 2024 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later .br This is free software: you are free to change and redistribute it. diff --git a/in_place.c b/in_place.c index 1f2fe22..11b9cbc 100644 --- a/in_place.c +++ b/in_place.c @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2021 Antonio Diaz Diaz. + Copyright (C) 2016-2024 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,8 +30,8 @@ #include "lzip.h" -/* Returns the number of bytes really read. - If (returned value < size) and (errno == 0), means EOF was reached. +/* Return the number of bytes really read. + If (value returned < size) and (errno == 0), means EOF was reached. */ static long readblock( const int fd, uint8_t * const buf, const long size ) { @@ -49,9 +49,9 @@ static long readblock( const int fd, uint8_t * const buf, const long size ) } -/* Returns the address of a malloc'd buffer containing the file data and +/* Return the address of a malloc'd buffer containing the file data and the buffer and file sizes in '*buffer_sizep' and '*file_sizep'. - In case of error, returns 0 and does not modify '*size'. + In case of error, return 0 and do not modify '*sizep'. */ static uint8_t * read_file( const int infd, long * const buffer_sizep, long * const file_sizep, const char * const filename ) @@ -64,8 +64,8 @@ static uint8_t * read_file( const int infd, long * const buffer_sizep, while( file_size >= buffer_size && !errno ) { if( buffer_size >= LONG_MAX ) - { show_file_error( filename, "File is too large.", 0 ); free( buffer ); - return 0; } + { show_file_error( filename, "Input file is too large.", 0 ); + free( buffer ); return 0; } buffer_size = ( buffer_size <= LONG_MAX / 2 ) ? 2 * buffer_size : LONG_MAX; uint8_t * const tmp = (uint8_t *)realloc( buffer, buffer_size ); if( !tmp ) @@ -97,9 +97,9 @@ static const char * set_file_sizes( struct File_sizes * const file_sizes, if( file_size <= Lh_size ) return "File ends unexpectedly at member header."; if( file_size < min_member_size ) return "Input file is too short."; const Lzip_header * header = (const Lzip_header *)buffer; - if( !Lh_verify_magic( *header ) ) + if( !Lh_check_magic( *header ) ) return "Bad magic number (file not in lzip format)."; - if( !Lh_verify_version( *header ) ) + if( !Lh_check_version( *header ) ) return "Version of lzip member format not supported."; file_sizes->csize = file_sizes->dsize = file_sizes->tsize = 0; @@ -122,7 +122,7 @@ static const char * set_file_sizes( struct File_sizes * const file_sizes, return "Member size in trailer is corrupt."; } header = (const Lzip_header *)( buffer + pos - member_size ); - if( !Lh_verify_magic( *header ) || !Lh_verify_version( *header ) ) + if( !Lh_check_magic( *header ) || !Lh_check_version( *header ) ) { if( file_sizes->csize == 0 ) { --pos; continue; } /* maybe trailing data */ return "Bad member header inside file."; @@ -132,7 +132,7 @@ static const char * set_file_sizes( struct File_sizes * const file_sizes, file_sizes->tsize = file_size - pos; header = (const Lzip_header *)( buffer + pos ); if( file_size - pos > Lh_size && - Lh_verify_magic( *header ) && Lh_verify_version( *header ) ) + Lh_check_magic( *header ) && Lh_check_version( *header ) ) return "Last member in input file is truncated or corrupt."; } pos -= member_size; @@ -155,7 +155,7 @@ static void error(char *x) { show_file_error( global_name, x, 0 ); } /* * Load the compressed file at the end of the buffer used to hold the - * decompressed data. Verify that the in-place decompression does not + * decompressed data. Check that the in-place decompression does not * overwrite the compressed data. The buffer must be large enough to contain * after the decompressed data extra space for a marker, a trailer, the * maximum possible data expansion, and (if multimember) N-1 empty members. @@ -180,7 +180,7 @@ int decompress_in_place( const int infd, struct Pretty_print * const pp, const long csize = file_sizes.csize; const long dsize = file_sizes.dsize; /* const long extra_bytes = ( dsize >> 8 ) + 65536; wrong linux formula */ - const long extra_bytes = ( csize >> 6 ) + file_sizes.members * 36; + const long extra_bytes = ( csize >> 6 ) + file_sizes.members * min_member_size; const long long target_buffer_size = max( dsize, csize ) + extra_bytes; if( target_buffer_size > LONG_MAX ) { show_file_error( pp->name, "Buffer is larger than LONG_MAX.", 0 ); diff --git a/linux_lzip.h b/linux_lzip.h index 398ef84..abd0d0c 100644 --- a/linux_lzip.h +++ b/linux_lzip.h @@ -4,7 +4,7 @@ /* * LZIP decompressor * - * Copyright (C) 2016-2021 Antonio Diaz Diaz. + * Copyright (C) 2016-2024 Antonio Diaz Diaz. */ /* Return values (< 0 = Error) */ diff --git a/lzip.h b/lzip.h index 15713ec..46a22d0 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2021 Antonio Diaz Diaz. + Copyright (C) 2016-2024 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -42,23 +42,23 @@ struct Pretty_print static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ -typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */ +enum { Lh_size = 6 }; +typedef uint8_t Lzip_header[Lh_size]; /* 0-3 magic bytes */ /* 4 version */ /* 5 coded dictionary size */ -enum { Lh_size = 6 }; -static inline bool Lh_verify_magic( const Lzip_header data ) - { return ( memcmp( data, lzip_magic, 4 ) == 0 ); } +static inline bool Lh_check_magic( const Lzip_header data ) + { return memcmp( data, lzip_magic, 4 ) == 0; } -static inline bool Lh_verify_version( const Lzip_header data ) - { return ( data[4] == 1 ); } +static inline bool Lh_check_version( const Lzip_header data ) + { return data[4] == 1; } -typedef uint8_t Lzip_trailer[20]; +enum { Lt_size = 20 }; +typedef uint8_t Lzip_trailer[Lt_size]; /* 0-3 CRC32 of the uncompressed data */ /* 4-11 size of the uncompressed data */ /* 12-19 member size including header and trailer */ -enum { Lt_size = 20 }; static inline unsigned long long Lt_get_data_size( const Lzip_trailer data ) { diff --git a/lzip_decompress.c b/lzip_decompress.c index 157a798..492523d 100644 --- a/lzip_decompress.c +++ b/lzip_decompress.c @@ -1,7 +1,7 @@ /* * LZIP decompressor * - * Copyright (C) 2016-2021 Antonio Diaz Diaz. + * Copyright (C) 2016-2024 Antonio Diaz Diaz. * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ @@ -32,17 +32,17 @@ static inline State St_set_char(const State st) static inline State St_set_match(const State st) { - return ((st < 7) ? 7 : 10); + return (st < 7) ? 7 : 10; } static inline State St_set_rep(const State st) { - return ((st < 7) ? 8 : 11); + return (st < 7) ? 8 : 11; } static inline State St_set_short_rep(const State st) { - return ((st < 7) ? 9 : 11); + return (st < 7) ? 9 : 11; } @@ -189,12 +189,12 @@ static inline void CRC32_update_buf(uint32_t * const crc, STATIC_RW_DATA const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ -typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */ +enum { Lh_size = 6 }; +typedef uint8_t Lzip_header[Lh_size]; /* 0-3 magic bytes */ /* 4 version */ /* 5 coded dictionary size */ -enum { Lh_size = 6 }; -static inline bool Lh_verify_magic(const Lzip_header data) +static inline bool Lh_check_magic(const Lzip_header data) { int i; @@ -205,34 +205,34 @@ static inline bool Lh_verify_magic(const Lzip_header data) } /* detect (truncated) header */ -static inline bool Lh_verify_prefix(const Lzip_header data, const int sz) +static inline bool Lh_check_prefix(const Lzip_header data, const int sz) { int i; for (i = 0; i < sz && i < 4; ++i) if (data[i] != lzip_magic[i]) return false; - return (sz > 0); + return sz > 0; } /* detect corrupt header */ -static inline bool Lh_verify_corrupt(const Lzip_header data) +static inline bool Lh_check_corrupt(const Lzip_header data) { int matches = 0; int i; for (i = 0; i < 4; ++i) if (data[i] == lzip_magic[i]) ++matches; - return (matches > 1 && matches < 4); + return matches > 1 && matches < 4; } -static inline bool Lh_verify_version(const Lzip_header data) +static inline bool Lh_check_version(const Lzip_header data) { - return (data[4] == 1); + return data[4] == 1; } static inline unsigned Lh_get_dictionary_size(const Lzip_header data) { - unsigned sz = (1 << (data[5] & 0x1F)); + unsigned sz = 1 << (data[5] & 0x1F); if (sz > min_dictionary_size) sz -= (sz / 16) * ((data[5] >> 5) & 7); @@ -240,11 +240,11 @@ static inline unsigned Lh_get_dictionary_size(const Lzip_header data) } -typedef uint8_t Lzip_trailer[20]; +enum { Lt_size = 20 }; +typedef uint8_t Lzip_trailer[Lt_size]; /* 0-3 CRC32 of the uncompressed data */ /* 4-11 size of the uncompressed data */ /* 12-19 member size including header and trailer */ -enum { Lt_size = 20 }; static inline unsigned Lt_get_data_crc(const Lzip_trailer data) { @@ -364,9 +364,9 @@ static inline void Rd_load(struct Range_decoder * const rdec) int i; rdec->code = 0; - for (i = 0; i < 5; ++i) - rdec->code = (rdec->code << 8) | Rd_get_byte(rdec); rdec->range = 0xFFFFFFFFU; + Rd_get_byte(rdec); /* discard first byte of the LZMA stream */ + for (i = 0; i < 4; ++i) rdec->code = (rdec->code << 8) | Rd_get_byte(rdec); } static inline void Rd_normalize(struct Range_decoder * const rdec) @@ -500,11 +500,12 @@ static inline unsigned Rd_decode_len(struct Range_decoder * const rdec, const int pos_state) { if (Rd_decode_bit(rdec, &lm->choice1) == 0) - return Rd_decode_tree3(rdec, lm->bm_low[pos_state]); + return min_match_len + + Rd_decode_tree3(rdec, lm->bm_low[pos_state]); if (Rd_decode_bit(rdec, &lm->choice2) == 0) - return len_low_symbols + + return min_match_len + len_low_symbols + Rd_decode_tree3(rdec, lm->bm_mid[pos_state]); - return len_low_symbols + len_mid_symbols + + return min_match_len + len_low_symbols + len_mid_symbols + Rd_decode_tree8(rdec, lm->bm_high); } @@ -668,7 +669,7 @@ LZd_data_position(const struct LZ_decoder * const d) } -static bool LZd_verify_trailer(struct LZ_decoder * const d) +static bool LZd_check_trailer(struct LZ_decoder * const d) { Lzip_trailer trailer; int i = 0; @@ -676,9 +677,9 @@ static bool LZd_verify_trailer(struct LZ_decoder * const d) while (i < Lt_size) trailer[i++] = Rd_get_byte(d->rdec); - return (Lt_get_data_crc(trailer) == LZd_crc(d) && + return Lt_get_data_crc(trailer) == LZd_crc(d) && Lt_get_data_size(trailer) == LZd_data_position(d) && - Lt_get_member_size(trailer) == Rd_member_position(d->rdec)); + Lt_get_member_size(trailer) == Rd_member_position(d->rdec); } @@ -736,11 +737,11 @@ static int LZd_decode_member(struct LZ_decoder * const d) rep0 = distance; } state = St_set_rep(state); - len = min_match_len + Rd_decode_len(rdec, &d->rep_len_model, pos_state); + len = Rd_decode_len(rdec, &d->rep_len_model, pos_state); } else { /* match */ unsigned distance; - len = min_match_len + Rd_decode_len(rdec, &d->match_len_model, pos_state); + len = Rd_decode_len(rdec, &d->match_len_model, pos_state); distance = Rd_decode_tree6(rdec, d->bm_dis_slot[get_len_state(len)]); if (distance >= start_dis_model) { const unsigned dis_slot = distance; @@ -760,15 +761,11 @@ static int LZd_decode_member(struct LZ_decoder * const d) if (d->write_error) return LZIP_WRITE_ERROR; if (len == min_match_len) { /* End Of Stream marker */ - if (LZd_verify_trailer(d)) + if (LZd_check_trailer(d)) return 0; else return LZIP_BAD_CRC; } - if (len == min_match_len + 1) { /* Sync Flush marker */ - Rd_load(rdec); - continue; - } return LZIP_BAD_DATA; /* unknown marker */ } } @@ -820,18 +817,18 @@ int lzip_decompress(unsigned char *inbuf, long in_len, if (Rd_finished(&rdec)) { /* End Of File */ if (first_member) retval = LZIP_HEADER1_EOF; - else if (Lh_verify_prefix(header, size)) + else if (Lh_check_prefix(header, size)) retval = LZIP_HEADER2_EOF; break; } - if (!Lh_verify_magic(header)) { + if (!Lh_check_magic(header)) { if (first_member) retval = LZIP_BAD_MAGIC1; - else if (Lh_verify_corrupt(header)) + else if (Lh_check_corrupt(header)) retval = LZIP_BAD_MAGIC2; break; } - if (!Lh_verify_version(header)) { + if (!Lh_check_version(header)) { retval = LZIP_BAD_VERSION; break; } diff --git a/main.c b/main.c index dc403da..67d011f 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2021 Antonio Diaz Diaz. + Copyright (C) 2016-2024 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,9 +16,9 @@ */ /* Exit status: 0 for a normal exit, 1 for environmental problems - (file not found, invalid flags, I/O errors, etc), 2 to indicate a - corrupt or invalid input file, 3 for an internal consistency error - (eg, bug) which caused xlunzip to panic. + (file not found, invalid command-line options, I/O errors, etc), 2 to + indicate a corrupt or invalid input file, 3 for an internal consistency + error (e.g., bug) which caused xlunzip to panic. */ #define _FILE_OFFSET_BITS 64 @@ -26,19 +26,19 @@ #include #include #include -#include +#include /* SSIZE_MAX */ #include #include -#include +#include /* SIZE_MAX */ #include #include #include #include #include #include -#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) +#if defined __MSVCRT__ || defined __OS2__ || defined __DJGPP__ #include -#if defined(__MSVCRT__) +#if defined __MSVCRT__ #define fchmod(x,y) 0 #define fchown(x,y,z) 0 #define SIGHUP SIGTERM @@ -50,7 +50,7 @@ #define S_IWOTH 0 #endif #endif -#if defined(__DJGPP__) +#if defined __DJGPP__ #define S_ISSOCK(x) 0 #define S_ISVTX 0 #endif @@ -69,13 +69,18 @@ #error "Environments where CHAR_BIT != 8 are not supported." #endif +#if ( defined SIZE_MAX && SIZE_MAX < ULONG_MAX ) || \ + ( defined SSIZE_MAX && SSIZE_MAX < LONG_MAX ) +#error "Environments where 'size_t' is narrower than 'long' are not supported." +#endif + static int verbosity = 0; static void cleanup_and_fail( const int retval ); static void show_error( const char * const msg, const int errcode, const bool help ); static const char * const program_name = "xlunzip"; -static const char * const program_year = "2021"; +static const char * const program_year = "2024"; static const char * invocation_name = "xlunzip"; /* default value */ static const struct { const char * from; const char * to; } known_extensions[] = { @@ -83,8 +88,6 @@ static const struct { const char * from; const char * to; } known_extensions[] = { ".tlz", ".tar" }, { 0, 0 } }; -static int infd = -1; /* needed by the fill function */ - /* Variables used in signal handler context. They are not declared volatile because the handler never returns. */ static char * output_filename = 0; @@ -98,7 +101,7 @@ static void show_help( void ) "linux. Xlunzip is similar to lunzip, but it uses the lzip_decompress linux\n" "module as a backend. Xlunzip tests the module for stream, buffer-to-buffer,\n" "and mixed decompression modes, including in-place decompression (using the\n" - "same buffer for input and output). You can use xlunzip to verify that the\n" + "same buffer for input and output). You can use xlunzip to check that the\n" "module produces correct results when decompressing single member files,\n" "multimember files, or the concatenation of two or more compressed files.\n" "Xlunzip can be used with unzcrash to test the robustness of the module to\n" @@ -132,10 +135,10 @@ static void show_help( void ) "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" "\nTo extract all the files from archive 'foo.tar.lz', use the commands\n" "'tar -xf foo.tar.lz' or 'xlunzip -cd foo.tar.lz | tar -xf -'.\n" - "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" - "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n" - "invalid input file, 3 for an internal consistency error (eg, bug) which\n" - "caused xlunzip to panic.\n" + "\nExit status: 0 for a normal exit, 1 for environmental problems\n" + "(file not found, invalid command-line options, I/O errors, etc), 2 to\n" + "indicate a corrupt or invalid input file, 3 for an internal consistency\n" + "error (e.g., bug) which caused xlunzip to panic.\n" "\nReport bugs to lzip-bug@nongnu.org\n" "Xlunzip home page: http://www.nongnu.org/lzip/xlunzip.html\n" ); } @@ -164,8 +167,6 @@ static void * resize_buffer( void * buf, const unsigned min_size ) static void Pp_init( struct Pretty_print * const pp, const char * const filenames[], const int num_filenames ) { - unsigned stdin_name_len; - int i; pp->name = 0; pp->padded_name = 0; pp->stdin_name = "(stdin)"; @@ -173,7 +174,8 @@ static void Pp_init( struct Pretty_print * const pp, pp->first_post = false; if( verbosity <= 0 ) return; - stdin_name_len = strlen( pp->stdin_name ); + const unsigned stdin_name_len = strlen( pp->stdin_name ); + int i; for( i = 0; i < num_filenames; ++i ) { const char * const s = filenames[i]; @@ -204,32 +206,72 @@ static void Pp_set_name( struct Pretty_print * const pp, static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) { - if( verbosity >= 0 ) + if( verbosity < 0 ) return; + if( pp->first_post ) { - if( pp->first_post ) - { - pp->first_post = false; - fputs( pp->padded_name, stderr ); - if( !msg ) fflush( stderr ); - } - if( msg ) fprintf( stderr, "%s\n", msg ); + pp->first_post = false; + fputs( pp->padded_name, stderr ); + if( !msg ) fflush( stderr ); } + if( msg ) fprintf( stderr, "%s\n", msg ); } -static unsigned long getnum( const char * const ptr, +/* 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 > 1024 ) + { + 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, const unsigned long llimit, const unsigned long ulimit ) { - unsigned long result; char * tail; errno = 0; - result = strtoul( ptr, &tail, 0 ); - if( tail == ptr ) - { - show_error( "Bad or missing numerical argument.", 0, true ); - exit( 1 ); - } + unsigned long result = strtoul( arg, &tail, 0 ); + if( tail == arg ) + { show_option_error( arg, "Bad or missing numerical argument in", + option_name ); exit( 1 ); } if( !errno && tail[0] ) { @@ -238,6 +280,8 @@ static unsigned long getnum( const char * const ptr, int i; switch( tail[0] ) { + case 'Q': exponent = 10; break; + case 'R': exponent = 9; break; case 'Y': exponent = 8; break; case 'Z': exponent = 7; break; case 'E': exponent = 6; break; @@ -249,10 +293,8 @@ static unsigned long getnum( const char * const ptr, case 'k': if( factor == 1000 ) exponent = 1; break; } if( exponent <= 0 ) - { - show_error( "Bad multiplier in numerical argument.", 0, true ); - exit( 1 ); - } + { show_option_error( arg, "Bad multiplier in numerical argument of", + option_name ); exit( 1 ); } for( i = 0; i < exponent; ++i ) { if( ulimit / factor >= result ) result *= factor; @@ -262,7 +304,10 @@ static unsigned long getnum( const char * const ptr, if( !errno && ( result < llimit || result > ulimit ) ) errno = ERANGE; if( errno ) { - show_error( "Numerical argument out of limits.", 0, false ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: '%s': Value out of limits [%s,%s] in " + "option '%s'.\n", program_name, arg, format_num3( llimit ), + format_num3( ulimit ), option_name ); exit( 1 ); } return result; @@ -305,7 +350,7 @@ static void set_d_outname( const char * const name, const int eindex ) strcpy( output_filename, name ); strcat( output_filename, ".out" ); if( verbosity >= 1 ) - fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n", + fprintf( stderr, "%s: %s: Can't guess original name -- using '%s'\n", program_name, name, output_filename ); } @@ -326,9 +371,9 @@ static int open_instream( const char * const name, struct stat * const in_statsp if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) ) { if( verbosity >= 0 ) - fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", + fprintf( stderr, "%s: %s: Input file is not a regular file%s.\n", program_name, name, ( can_read && one_to_one ) ? - ",\n and neither '-c' nor '-o' were specified" : "" ); + ",\n and neither '-c' nor '-o' were specified" : "" ); close( infd ); infd = -1; } @@ -347,16 +392,12 @@ static bool open_outstream( const bool force, const bool protect ) outfd = open( output_filename, flags, outfd_mode ); if( outfd >= 0 ) delete_output_on_interrupt = true; - else if( verbosity >= 0 ) - { - if( errno == EEXIST ) - fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n", - program_name, output_filename ); - else - fprintf( stderr, "%s: Can't create output file '%s': %s\n", - program_name, output_filename, strerror( errno ) ); - } - return ( outfd >= 0 ); + else if( errno == EEXIST ) + show_file_error( output_filename, + "Output file already exists, skipping.", 0 ); + else + show_file_error( output_filename, "Can't create output file", errno ); + return outfd >= 0; } @@ -374,12 +415,10 @@ static void cleanup_and_fail( const int retval ) if( delete_output_on_interrupt ) { delete_output_on_interrupt = false; - if( verbosity >= 0 ) - fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n", - program_name, output_filename ); + show_file_error( output_filename, "Deleting output file, if it exists.", 0 ); if( outfd >= 0 ) { close( outfd ); outfd = -1; } if( remove( output_filename ) != 0 && errno != ENOENT ) - show_error( "WARNING: deletion of output file (apparently) failed.", 0, false ); + show_error( "warning: deletion of output file failed", errno, false ); } exit( retval ); } @@ -399,7 +438,7 @@ static bool check_tty_in( const char * const input_filename, const int infd, if( isatty( infd ) ) /* for example /dev/tty */ { show_file_error( input_filename, "I won't read compressed data from a terminal.", 0 ); - close( infd ); set_retval( retval, 1 ); + close( infd ); set_retval( retval, 2 ); if( !testing ) cleanup_and_fail( *retval ); return false; } return true; @@ -413,7 +452,7 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) if( in_statsp ) { const mode_t mode = in_statsp->st_mode; - /* fchown will in many cases return with EPERM, which can be safely ignored. */ + /* fchown in many cases returns with EPERM, which can be safely ignored. */ if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 ) { if( fchmod( outfd, mode ) != 0 ) warning = true; } else @@ -422,10 +461,8 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) warning = true; } if( close( outfd ) != 0 ) - { - show_error( "Error closing output file", errno, false ); - cleanup_and_fail( 1 ); - } + { show_file_error( output_filename, "Error closing output file", errno ); + cleanup_and_fail( 1 ); } outfd = -1; delete_output_on_interrupt = false; if( in_statsp ) @@ -436,7 +473,8 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) if( utime( output_filename, &t ) != 0 ) warning = true; } if( warning && verbosity >= 1 ) - show_error( "Can't change output file attributes.", 0, false ); + show_file_error( output_filename, + "warning: can't change output file attributes", errno ); } @@ -462,13 +500,15 @@ int convert_retval( const int retval ) } +static int global_infd = -1; /* needed by the fill function */ + static long fill( void * buf, unsigned long size ) { unsigned long sz = 0; errno = 0; while( sz < size ) { - const int n = read( infd, (uint8_t *)buf + sz, min( 1UL << 20, size - sz ) ); + const int n = read( global_infd, (uint8_t *)buf + sz, min( 1UL << 20, size - sz ) ); if( n > 0 ) sz += n; else if( n == 0 ) break; /* EOF */ else if( errno != EINTR ) break; @@ -495,9 +535,9 @@ static const char * global_name; /* copy of filename for 'error' */ static void error(char *x) { show_file_error( global_name, x, 0 ); } -static int decompress( struct Pretty_print * const pp, const long cl_insize, - const long cl_outsize, const bool nofill, - const bool noflush, const bool testing ) +static int decompress( const int infd, struct Pretty_print * const pp, + const long cl_insize, const long cl_outsize, + const bool nofill, const bool noflush, const bool testing ) { long in_len = cl_insize; uint8_t * const inbuf = (in_len > 0) ? malloc( in_len ) : 0; @@ -508,17 +548,20 @@ static int decompress( struct Pretty_print * const pp, const long cl_insize, if( ( in_len > 0 && !inbuf ) || ( out_size > 0 && !outbuf ) ) { show_error( mem_msg, 0, false ); return 1; } + global_infd = infd; if( inbuf ) { const long len = fill( inbuf, in_len ); if( len < in_len ) - { if( errno ) { show_file_error( pp->name, "Read error", errno ); return 1; } + { if( errno ) { show_file_error( pp->name, "Read error", errno ); + global_infd = -1; return 1; } in_len = len; } } global_name = pp->name; retval = convert_retval( __lunzip( inbuf, in_len, nofill ? 0 : fill, noflush ? 0 : flush, outbuf, out_size, &in_pos, &out_pos, error ) ); + global_infd = -1; if( retval ) return retval; if( outbuf && noflush ) { @@ -586,25 +629,17 @@ static void internal_error( const char * const msg ) int main( const int argc, const char * const argv[] ) { const char * default_output_filename = ""; - static struct Arg_parser parser; /* static because valgrind complains */ - static struct Pretty_print pp; /* and memory management in C sucks */ - static const char ** filenames = 0; long cl_insize = 0; long cl_outsize = 0; - int num_filenames = 0; - int argind = 0; - int failed_tests = 0; - int retval = 0; int i; - bool filenames_given = false; bool force = false; bool in_place = false; bool keep_input_files = false; bool nofill = false; bool noflush = false; - bool stdin_used = false; bool testing = false; bool to_stdout = false; + if( argc > 0 ) invocation_name = argv[0]; enum { opt_insize = 256, opt_outsize, opt_nofill, opt_noflush }; const struct ap_Option options[] = @@ -621,24 +656,26 @@ int main( const int argc, const char * const argv[] ) { 't', "test", ap_no }, { 'v', "verbose", ap_no }, { 'V', "version", ap_no }, - { opt_insize, "insize", ap_maybe }, + { opt_insize, "insize", ap_maybe }, { opt_outsize, "outsize", ap_maybe }, - { opt_nofill, "nofill", ap_no }, + { opt_nofill, "nofill", ap_no }, { opt_noflush, "noflush", ap_no }, - { 0 , 0, ap_no } }; - - if( argc > 0 ) invocation_name = argv[0]; + { 0, 0, ap_no } }; + /* static because valgrind complains and memory management in C sucks */ + static struct Arg_parser parser; if( !ap_init( &parser, argc, argv, options, 0 ) ) { show_error( mem_msg, 0, false ); return 1; } if( ap_error( &parser ) ) /* bad option */ { show_error( ap_error( &parser ), 0, true ); return 1; } + int argind = 0; for( ; argind < ap_arguments( &parser ); ++argind ) { const int code = ap_code( &parser, argind ); - const char * const arg = ap_argument( &parser, argind ); if( !code ) break; /* no more options */ + const char * const pn = ap_parsed_name( &parser, argind ); + const char * const arg = ap_argument( &parser, argind ); switch( code ) { case 'c': to_stdout = true; break; @@ -655,25 +692,27 @@ int main( const int argc, const char * const argv[] ) case 'v': if( verbosity < 4 ) ++verbosity; break; case 'V': show_version(); return 0; case opt_insize: - cl_insize = arg[0] ? getnum( arg, 1, LONG_MAX ) : 16384; break; + cl_insize = arg[0] ? getnum( arg, pn, 1, LONG_MAX ) : 16384; break; case opt_outsize: cl_outsize = arg[0] ? - getnum( arg, min_dictionary_size, LONG_MAX ) : max_dictionary_size; + getnum( arg, pn, min_dictionary_size, LONG_MAX ) : max_dictionary_size; break; case opt_nofill: nofill = true; break; case opt_noflush: noflush = 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__ || defined __DJGPP__ setmode( STDIN_FILENO, O_BINARY ); setmode( STDOUT_FILENO, O_BINARY ); #endif - num_filenames = max( 1, ap_arguments( &parser ) - argind ); + static const char ** filenames = 0; + int num_filenames = max( 1, ap_arguments( &parser ) - argind ); filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); filenames[0] = "-"; + bool filenames_given = false; for( i = 0; argind + i < ap_arguments( &parser ); ++i ) { filenames[i] = ap_argument( &parser, argind + i ); @@ -692,15 +731,18 @@ int main( const int argc, const char * const argv[] ) if( !to_stdout && !testing && ( filenames_given || to_file ) ) set_signals( signal_handler ); + static struct Pretty_print pp; Pp_init( &pp, filenames, num_filenames ); + int failed_tests = 0; + int retval = 0; const bool one_to_one = !to_stdout && !testing && !to_file; + bool stdin_used = false; + struct stat in_stats; for( i = 0; i < num_filenames; ++i ) { const char * input_filename = ""; - int tmp; - struct stat in_stats; - const struct stat * in_statsp; + int infd; Pp_set_name( &pp, filenames[i] ); if( strcmp( filenames[i], "-" ) == 0 ) @@ -716,15 +758,15 @@ int main( const int argc, const char * const argv[] ) infd = open_instream( input_filename, &in_stats, one_to_one ); if( infd < 0 ) { set_retval( &retval, 1 ); continue; } if( !check_tty_in( pp.name, infd, testing, &retval ) ) continue; - if( one_to_one ) /* open outfd after verifying infd */ + if( one_to_one ) /* open outfd after checking infd */ { set_d_outname( input_filename, extension_index( input_filename ) ); if( !open_outstream( force, true ) ) - { close( infd ); infd = -1; set_retval( &retval, 1 ); continue; } + { close( infd ); set_retval( &retval, 1 ); continue; } } } - if( to_file && outfd < 0 ) /* open outfd after verifying infd */ + if( to_file && outfd < 0 ) /* open outfd after checking infd */ { output_filename = resize_buffer( output_filename, strlen( default_output_filename ) + 1 ); @@ -732,15 +774,16 @@ int main( const int argc, const char * const argv[] ) if( !open_outstream( force, false ) ) return 1; } - in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0; + const struct stat * const in_statsp = + ( input_filename[0] && one_to_one ) ? &in_stats : 0; + int tmp; if( in_place ) tmp = decompress_in_place( infd, &pp, testing ); else - tmp = decompress( &pp, cl_insize, cl_outsize, nofill, noflush, testing ); + tmp = decompress( infd, &pp, cl_insize, cl_outsize, nofill, noflush, testing ); if( close( infd ) != 0 ) { show_file_error( pp.name, "Error closing input file", errno ); set_retval( &tmp, 1 ); } - infd = -1; set_retval( &retval, tmp ); if( tmp ) { if( !testing ) cleanup_and_fail( retval ); @@ -751,7 +794,9 @@ int main( const int argc, const char * const argv[] ) if( input_filename[0] && !keep_input_files && one_to_one ) remove( input_filename ); } - if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); /* -o */ + if( delete_output_on_interrupt ) /* -o */ + close_and_set_permissions( ( retval == 0 && !stdin_used && + filenames_given && num_filenames == 1 ) ? &in_stats : 0 ); else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */ { show_error( "Error closing stdout", errno, false ); diff --git a/testsuite/check.sh b/testsuite/check.sh index 5609a88..050ccda 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh # check script for Xlunzip - Test tool for the lzip_decompress linux module -# Copyright (C) 2016-2021 Antonio Diaz Diaz. +# Copyright (C) 2016-2024 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute, and modify it. @@ -82,33 +82,41 @@ printf "\ntesting decompression..." for i in "${in_lz}" "${in_em}" ; do "${LZIP}" -t "$i" || test_failed $LINENO "$i" - "${LZIP}" -d "$i" -o copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - "${LZIP}" -cd "$i" > copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - "${LZIP}" -d "$i" -o - > copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - "${LZIP}" -d < "$i" > copy || test_failed $LINENO "$i" - cmp in copy || test_failed $LINENO "$i" - rm -f copy || framework_failure + "${LZIP}" -d "$i" -o out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + "${LZIP}" -cd "$i" > out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + "${LZIP}" -d "$i" -o - > out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + "${LZIP}" -d < "$i" > out || test_failed $LINENO "$i" + cmp in out || test_failed $LINENO "$i" + rm -f out || framework_failure done +lines=`"${LZIP}" -tvv "${in_em}" 2>&1 | wc -l` || test_failed $LINENO +[ "${lines}" -eq 1 ] || test_failed $LINENO "${lines}" + +cat "${in_lz}" > out.lz || framework_failure +"${LZIP}" -dk out.lz || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out || framework_failure +"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO +cat fox > copy || framework_failure cat "${in_lz}" > copy.lz || framework_failure -"${LZIP}" -dk copy.lz || test_failed $LINENO -cmp in copy || test_failed $LINENO -printf "to be overwritten" > copy || framework_failure -"${LZIP}" -d copy.lz 2> /dev/null +"${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 -printf "to be overwritten" > copy || framework_failure -"${LZIP}" -d -o copy < "${in_lz}" 2> /dev/null -[ $? = 1 ] || test_failed $LINENO -"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f out copy || framework_failure +printf "to be overwritten" > out || framework_failure +"${LZIP}" -df -o out < "${in_lz}" || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out || framework_failure "${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure @@ -117,70 +125,71 @@ cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure cat "${in_lz}" > anyothername || framework_failure -"${LZIP}" -dv - anyothername - < "${in_lz}" > copy 2> /dev/null || +"${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null || test_failed $LINENO -cmp in copy || test_failed $LINENO +cmp in out || test_failed $LINENO cmp in anyothername.out || test_failed $LINENO -rm -f copy anyothername.out || framework_failure +rm -f out anyothername.out || framework_failure "${LZIP}" -tq in "${in_lz}" [ $? = 2 ] || test_failed $LINENO "${LZIP}" -tq nx_file.lz "${in_lz}" [ $? = 1 ] || test_failed $LINENO -"${LZIP}" -cdq in "${in_lz}" > copy +"${LZIP}" -cdq in "${in_lz}" > out [ $? = 2 ] || test_failed $LINENO -cat copy in | cmp in - || test_failed $LINENO -"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy +cat out in | cmp in - || test_failed $LINENO # out must be empty +"${LZIP}" -cdq nx_file.lz "${in_lz}" > out # skip nx_file, decompress in [ $? = 1 ] || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f copy || framework_failure -cat "${in_lz}" > copy.lz || framework_failure -"${LZIP}" -dq in copy.lz +cmp in out || test_failed $LINENO +rm -f out || framework_failure +cat "${in_lz}" > out.lz || framework_failure +"${LZIP}" -dq in out.lz [ $? = 2 ] || test_failed $LINENO -[ -e copy.lz ] || test_failed $LINENO -[ ! -e copy ] || test_failed $LINENO +[ -e out.lz ] || test_failed $LINENO +[ ! -e out ] || test_failed $LINENO [ ! -e in.out ] || test_failed $LINENO -"${LZIP}" -dq nx_file.lz copy.lz +"${LZIP}" -dq nx_file.lz out.lz [ $? = 1 ] || test_failed $LINENO -[ ! -e copy.lz ] || test_failed $LINENO +[ ! -e out.lz ] || test_failed $LINENO [ ! -e nx_file ] || test_failed $LINENO -cmp in copy || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out || framework_failure cat in in > in2 || framework_failure "${LZIP}" -t "${in_lz}" "${in_lz}" || test_failed $LINENO -"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > copy2 || test_failed $LINENO +"${LZIP}" -cd "${in_lz}" "${in_lz}" -o out > out2 || test_failed $LINENO [ ! -e out ] || test_failed $LINENO # override -o -cmp in2 copy2 || test_failed $LINENO -rm -f copy2 || framework_failure -"${LZIP}" -d "${in_lz}" "${in_lz}" -o copy2 || test_failed $LINENO -cmp in2 copy2 || test_failed $LINENO -rm -f copy2 || framework_failure +cmp in2 out2 || test_failed $LINENO +rm -f out2 || framework_failure +"${LZIP}" -d "${in_lz}" "${in_lz}" -o out2 || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO +rm -f out2 || framework_failure -cat "${in_lz}" "${in_lz}" > copy2.lz || framework_failure -printf "\ngarbage" >> copy2.lz || framework_failure -"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO -printf "to be overwritten" > copy2 || framework_failure -"${LZIP}" -df copy2.lz || test_failed $LINENO -cmp in2 copy2 || test_failed $LINENO +cat "${in_lz}" "${in_lz}" > out2.lz || framework_failure +printf "\ngarbage" >> out2.lz || framework_failure +"${LZIP}" -tvvvv out2.lz 2> /dev/null || test_failed $LINENO +printf "to be overwritten" > out2 || framework_failure +"${LZIP}" -df out2.lz || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO printf "\ntesting bad input..." headers='LZIp LZiP LZip LzIP LzIp LziP lZIP lZIp lZiP lzIP' body='\001\014\000\203\377\373\377\377\300\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000' -cat "${in_lz}" > int.lz -printf "LZIP${body}" >> int.lz +cat "${in_lz}" > int.lz || framework_failure +printf "LZIP${body}" >> int.lz || framework_failure if "${LZIP}" -tq int.lz ; then for header in ${headers} ; do - printf "${header}${body}" > int.lz # first member - "${LZIP}" -tq int.lz + printf "${header}${body}" > int.lz || framework_failure + "${LZIP}" -tq int.lz # first member [ $? = 2 ] || test_failed $LINENO ${header} "${LZIP}" -tq < int.lz [ $? = 2 ] || test_failed $LINENO ${header} "${LZIP}" -cdq int.lz > /dev/null [ $? = 2 ] || test_failed $LINENO ${header} - cat "${in_lz}" > int.lz - printf "${header}${body}" >> int.lz # trailing data - "${LZIP}" -tq int.lz + cat "${in_lz}" > int.lz || framework_failure + printf "${header}${body}" >> int.lz || framework_failure + "${LZIP}" -tq int.lz # trailing data [ $? = 2 ] || test_failed $LINENO ${header} "${LZIP}" -tq < int.lz [ $? = 2 ] || test_failed $LINENO ${header} @@ -198,7 +207,6 @@ for i in fox_v2.lz fox_s11.lz fox_de20.lz \ [ $? = 2 ] || test_failed $LINENO $i done -"${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do "${LZIP}" -cdq "${testdir}"/$i > out [ $? = 2 ] || test_failed $LINENO $i @@ -216,153 +224,153 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && [ $? = 2 ] || test_failed $LINENO $i "${LZIP}" -tq < trunc.lz [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -cdq trunc.lz > out + "${LZIP}" -cdq trunc.lz > /dev/null [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -dq < trunc.lz > out + "${LZIP}" -dq < trunc.lz > /dev/null [ $? = 2 ] || test_failed $LINENO $i done else printf "\nwarning: skipping truncation test: 'dd' does not work on your system." fi -rm -f trunc.lz out || framework_failure +rm -f trunc.lz || framework_failure cat "${in_lz}" > ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure cat "${in_lz}" >> ingin.lz || framework_failure "${LZIP}" -t ingin.lz || test_failed $LINENO "${LZIP}" -t < ingin.lz || test_failed $LINENO -"${LZIP}" -cd ingin.lz > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO +"${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 printf "\ntesting linux options..." for i in "" =1 =2 =4 =16 =64 =256 =1024 =4096 =16384 =65536 ; do "${LZIP}" -t --insize$i "${in_lz}" || test_failed $LINENO $i - "${LZIP}" -cd --insize$i "${in_lz}" > copy || test_failed $LINENO $i - cmp in copy || test_failed $LINENO $i + "${LZIP}" -cd --insize$i "${in_lz}" > out || test_failed $LINENO $i + cmp in out || test_failed $LINENO $i done for i in =1 =2 =4 =16 =64 =256 =1024 =4096 ; do "${LZIP}" -tq --insize$i --nofill "${in_lz}" [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -cdq --insize$i --nofill "${in_lz}" > copy + "${LZIP}" -cdq --insize$i --nofill "${in_lz}" > out [ $? = 2 ] || test_failed $LINENO $i - cmp -s in copy && test_failed $LINENO $i + cmp -s in out && test_failed $LINENO $i done for i in "" =16384 =65536 ; do "${LZIP}" -t --insize$i --nofill "${in_lz}" || test_failed $LINENO $i - "${LZIP}" -cd --insize$i --nofill "${in_lz}" > copy || + "${LZIP}" -cd --insize$i --nofill "${in_lz}" > out || test_failed $LINENO $i - cmp in copy || test_failed $LINENO $i + cmp in out || test_failed $LINENO $i done for i in =18KiB =65536 =262144 ; do "${LZIP}" -t --outsize$i "${in_lz}" || test_failed $LINENO $i - "${LZIP}" -cd --outsize$i "${in_lz}" > copy || + "${LZIP}" -cd --outsize$i "${in_lz}" > out || test_failed $LINENO $i - cmp in copy || test_failed $LINENO $i + cmp in out || test_failed $LINENO $i done for i in =36388 =65536 =262144 ; do "${LZIP}" -t --outsize$i --noflush "${in_lz}" || test_failed $LINENO $i - "${LZIP}" -cd --outsize$i --noflush "${in_lz}" > copy || + "${LZIP}" -cd --outsize$i --noflush "${in_lz}" > out || test_failed $LINENO $i - cmp in copy || test_failed $LINENO $i + cmp in out || test_failed $LINENO $i done for i in =36387 ; do "${LZIP}" -tq --outsize$i --noflush "${in_lz}" [ $? = 1 ] || test_failed $LINENO $i - "${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > copy + "${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > out [ $? = 1 ] || test_failed $LINENO $i - cmp -s in copy && test_failed $LINENO $i + cmp -s in out && test_failed $LINENO $i done for i in =4096 =16384 ; do "${LZIP}" -tq --outsize$i --noflush "${in_lz}" [ $? = 2 ] || test_failed $LINENO $i - "${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > copy + "${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > out [ $? = 2 ] || test_failed $LINENO $i - cmp -s in copy && test_failed $LINENO $i + cmp -s in out && test_failed $LINENO $i done "${LZIP}" -t --insize --outsize=36388 --nofill --noflush "${in_lz}" || test_failed $LINENO -"${LZIP}" -cd --insize --outsize=36388 --nofill --noflush "${in_lz}" > copy || +"${LZIP}" -cd --insize --outsize=36388 --nofill --noflush "${in_lz}" > out || test_failed $LINENO -cmp in copy || test_failed $LINENO +cmp in out || test_failed $LINENO "${LZIP}" -tq --nofill "${in_lz}" [ $? = 2 ] || test_failed $LINENO -"${LZIP}" -cdq --nofill "${in_lz}" > copy +"${LZIP}" -cdq --nofill "${in_lz}" > out [ $? = 2 ] || test_failed $LINENO -cmp -s in copy && test_failed $LINENO +cmp -s in out && test_failed $LINENO "${LZIP}" -tq --noflush "${in_lz}" [ $? = 1 ] || test_failed $LINENO -"${LZIP}" -cdq --noflush "${in_lz}" > copy +"${LZIP}" -cdq --noflush "${in_lz}" > out [ $? = 1 ] || test_failed $LINENO -cmp -s in copy && test_failed $LINENO +cmp -s in out && test_failed $LINENO # decompress in place -rm -f copy copy2 || framework_failure +rm -f out out2 || framework_failure "${LZIP}" -t --in-place "${in_lz}" || test_failed $LINENO "${LZIP}" -t --in-place < "${in_lz}" || test_failed $LINENO -"${LZIP}" -d --in-place "${in_lz}" -o copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f copy || framework_failure -"${LZIP}" -d --in-place < "${in_lz}" -o copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -"${LZIP}" -cd --in-place "${in_lz}" > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -"${LZIP}" -cd --in-place < "${in_lz}" > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO +"${LZIP}" -d --in-place "${in_lz}" -o out || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out || framework_failure +"${LZIP}" -d --in-place < "${in_lz}" -o out || test_failed $LINENO +cmp in out || test_failed $LINENO +"${LZIP}" -cd --in-place "${in_lz}" > out || test_failed $LINENO +cmp in out || test_failed $LINENO +"${LZIP}" -cd --in-place < "${in_lz}" > out || test_failed $LINENO +cmp in out || test_failed $LINENO "${LZIP}" -t --in-place "${in_lz}" "${in_lz}" || test_failed $LINENO -"${LZIP}" -d --in-place "${in_lz}" "${in_lz}" -o copy2 || test_failed $LINENO -cmp in2 copy2 || test_failed $LINENO -"${LZIP}" -cd --in-place "${in_lz}" "${in_lz}" > copy2 || test_failed $LINENO -cmp in2 copy2 || test_failed $LINENO +"${LZIP}" -d --in-place "${in_lz}" "${in_lz}" -o out2 || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO +"${LZIP}" -cd --in-place "${in_lz}" "${in_lz}" > out2 || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO # decompress multimember in place cat in in in > in3 || framework_failure for i in in2 in3 ; do "${LZIP}" -t --in-place $i.lz || test_failed $LINENO "${LZIP}" -t --in-place < $i.lz || test_failed $LINENO - rm -f copy || framework_failure - "${LZIP}" -d --in-place $i.lz -o copy || test_failed $LINENO - cmp $i copy || test_failed $LINENO - rm -f copy || framework_failure - "${LZIP}" -d --in-place < $i.lz -o copy || test_failed $LINENO - cmp $i copy || test_failed $LINENO - "${LZIP}" -cd --in-place $i.lz > copy || test_failed $LINENO - cmp $i copy || test_failed $LINENO - "${LZIP}" -cd --in-place < $i.lz > copy || test_failed $LINENO - cmp $i copy || test_failed $LINENO + rm -f out || framework_failure + "${LZIP}" -d --in-place $i.lz -o out || test_failed $LINENO + cmp $i out || test_failed $LINENO + rm -f out || framework_failure + "${LZIP}" -d --in-place < $i.lz -o out || test_failed $LINENO + cmp $i out || test_failed $LINENO + "${LZIP}" -cd --in-place $i.lz > out || test_failed $LINENO + cmp $i out || test_failed $LINENO + "${LZIP}" -cd --in-place < $i.lz > out || test_failed $LINENO + cmp $i out || test_failed $LINENO done "${LZIP}" -tq --in-place ingin.lz [ $? = 2 ] || test_failed $LINENO -rm -f copy copy2 ingin.lz in2 in2.lz in3 in3.lz || framework_failure +rm -f out out2 ingin.lz in2 in2.lz in3 in3.lz || framework_failure cat "${in_lz}" > inz.lz || framework_failure counter=0 while [ ${counter} -lt 20 ] ; do cat "${zero_lz}" >> inz.lz || framework_failure "${LZIP}" -t --in-place inz.lz || test_failed $LINENO - "${LZIP}" -cd --in-place inz.lz > copy || test_failed $LINENO - cmp in copy || test_failed $LINENO + "${LZIP}" -cd --in-place inz.lz > out || test_failed $LINENO + cmp in out || test_failed $LINENO counter=$((counter+1)) done -rm -f copy inz.lz || framework_failure +rm -f out inz.lz || framework_failure # decompress with trailing data in place cat "${in_lz}" in in in in > int.lz || framework_failure "${LZIP}" -t --in-place int.lz || test_failed $LINENO -"${LZIP}" -cd --in-place int.lz > copy || test_failed $LINENO -cmp in copy || test_failed $LINENO -rm -f copy int.lz || framework_failure +"${LZIP}" -cd --in-place int.lz > out || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out int.lz || framework_failure echo if [ ${fail} = 0 ] ; then From 265453a85fdaffb2eeec0812701d98e250b84196 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:16 +0100 Subject: [PATCH 02/10] Minimizing debhelper build-depends for trixie. Signed-off-by: Daniel Baumann --- debian/control | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/control b/debian/control index c1345fd..5bb83aa 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,6 @@ Section: utils Priority: optional Maintainer: Daniel Baumann Build-Depends: - debhelper (>= 13.1~), debhelper-compat (= 13), Rules-Requires-Root: no Standards-Version: 4.6.2 From 62a1b9ec196db56eadb53abc16be93151a6f9e69 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:16 +0100 Subject: [PATCH 03/10] Adding patch to avoid overriding build-environment. Signed-off-by: Daniel Baumann --- debian/patches/debian/0001-build.patch | 21 +++++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 22 insertions(+) create mode 100644 debian/patches/debian/0001-build.patch create mode 100644 debian/patches/series diff --git a/debian/patches/debian/0001-build.patch b/debian/patches/debian/0001-build.patch new file mode 100644 index 0000000..2033f45 --- /dev/null +++ b/debian/patches/debian/0001-build.patch @@ -0,0 +1,21 @@ +Author: Daniel Baumann +Description: Avoid overwriting build-environment. + +diff -Naurp xlunzip.orig/configure xlunzip/configure +--- xlunzip.orig/configure ++++ xlunzip/configure +@@ -20,10 +20,10 @@ bindir='$(exec_prefix)/bin' + datarootdir='$(prefix)/share' + infodir='$(datarootdir)/info' + mandir='$(datarootdir)/man' +-CC=gcc +-CPPFLAGS= +-CFLAGS='-Wall -W -O2' +-LDFLAGS= ++#CC=gcc ++#CPPFLAGS= ++#CFLAGS='-Wall -W -O2' ++#LDFLAGS= + MAKEINFO=makeinfo + + # checking whether we are using GNU C. diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..655df63 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +debian/0001-build.patch From 5356e174219743ef0172686d839ec9ac515a7008 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:17 +0100 Subject: [PATCH 04/10] Disabling testsuite for now as the current upstream release misses some files for it to run at all. Signed-off-by: Daniel Baumann --- debian/rules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/rules b/debian/rules index b6ef33e..97d1448 100755 --- a/debian/rules +++ b/debian/rules @@ -18,3 +18,6 @@ execute_after_dh_auto_install: mv debian/xlunzip/usr/share/man/man1/xlunzip.1 debian/xlunzip/usr/share/man/man1/lzip.xlunzip.1 ln -s /usr/share/man/man1/lzip.xlunzip.1.gz debian/xlunzip/usr/share/man/man1/xlunzip.1.gz + +override_dh_auto_test: + # disabled: incomplete upstream testsuite From ab5475d7301b4bb065005d818cc1838556e371f4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:17 +0100 Subject: [PATCH 05/10] Releasing debian version 0.8-1. Signed-off-by: Daniel Baumann --- debian/changelog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/debian/changelog b/debian/changelog index 263bd7f..e400849 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +xlunzip (0.8-1) sid; urgency=medium + + * Uploading to sid. + * Merging upstream version 0.8. + * Minimizing debhelper build-depends for trixie. + * Adding patch to avoid overriding build-environment. + * Disabling testsuite for now as the current upstream release misses + some files for it to run at all. + + -- Daniel Baumann Tue, 23 Jan 2024 06:51:16 +0100 + xlunzip (0.7-7) sid; urgency=medium * Uploading to sid. From 661f9413d90c125cafdc4637ac47c00464fdebfc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:30 +0100 Subject: [PATCH 06/10] Updating years in copyright for 2024. Signed-off-by: Daniel Baumann --- debian/copyright | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/copyright b/debian/copyright index 26077af..4e721d0 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,15 +4,15 @@ Upstream-Contact: lzip-bug@nongnu.org Source: https://download.savannah.gnu.org/releases/lzip/xlunzip Files: * -Copyright: 2016-2021 Antonio Diaz Diaz +Copyright: 2016-2024 Antonio Diaz Diaz License: GPL-2+ Files: carg_parser.* -Copyright: 2006-2021 Antonio Diaz Diaz +Copyright: 2006-2024 Antonio Diaz Diaz License: BSD-2-clause Files: debian/* -Copyright: 2018-2022 Daniel Baumann +Copyright: 2018-2024 Daniel Baumann License: GPL-2+ License: BSD-2-clause From be436b83f91ed3cf36ff11d483477b1d8c81198e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:30 +0100 Subject: [PATCH 07/10] Updating to standards-version 4.7.0. Signed-off-by: Daniel Baumann --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 5bb83aa..c5396b2 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,7 @@ Maintainer: Daniel Baumann Build-Depends: debhelper-compat (= 13), Rules-Requires-Root: no -Standards-Version: 4.6.2 +Standards-Version: 4.7.0 Homepage: http://www.nongnu.org/lzip/xlunzip.html Vcs-Browser: https://git.progress-linux.org/users/daniel.baumann/debian/packages/xlunzip Vcs-Git: https://git.progress-linux.org/users/daniel.baumann/debian/packages/xlunzip From bdc3a79f2b7c1f9f51567d1e4b3f130df553b607 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:30 +0100 Subject: [PATCH 08/10] Releasing debian version 0.8-2. Signed-off-by: Daniel Baumann --- debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index e400849..b4e2ca4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +xlunzip (0.8-2) sid; urgency=medium + + * Uploading to sid. + * Updating years in copyright for 2024. + * Updating to standards-version 4.7.0. + + -- Daniel Baumann Thu, 25 Jul 2024 06:55:11 +0200 + xlunzip (0.8-1) sid; urgency=medium * Uploading to sid. From 26c5e8d334179f9e599aea1b266470b511f0e883 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:41 +0100 Subject: [PATCH 09/10] Merging upstream version 0.9. Signed-off-by: Daniel Baumann --- COPYING | 3 +- ChangeLog | 15 +++- INSTALL | 5 +- Makefile.in | 10 +-- NEWS | 21 ++--- README | 8 +- carg_parser.c | 62 +++++++------- carg_parser.h | 45 +++++----- configure | 8 +- decompress_lunzip.c | 5 +- doc/xlunzip.1 | 4 +- in_place.c | 6 +- linux_lzip.h | 5 +- lzip.h | 10 +-- lzip_decompress.c | 44 +++++----- main.c | 58 +++++++------ testsuite/check.sh | 156 ++++++++++++++++++++++++----------- testsuite/{zero.lz => em.lz} | Bin testsuite/fox_nz.lz | Bin 0 -> 80 bytes testsuite/test.txt | 6 +- testsuite/test.txt.lz | Bin 7376 -> 7341 bytes testsuite/test_em.txt.lz | Bin 14024 -> 0 bytes 22 files changed, 270 insertions(+), 201 deletions(-) rename testsuite/{zero.lz => em.lz} (100%) create mode 100644 testsuite/fox_nz.lz delete mode 100644 testsuite/test_em.txt.lz diff --git a/COPYING b/COPYING index 4ad17ae..42fe735 100644 --- a/COPYING +++ b/COPYING @@ -1,8 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/ChangeLog b/ChangeLog index 0c8da07..e908633 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2025-01-06 Antonio Diaz Diaz + + * Version 0.9 released. + * main.c (decompress): Return 2 if empty member in multimember file. + (Pp_free): New function. + * lzip_decompress.c (Rd_load): Check first byte of the LZMA stream. + * check.sh: Use 'cp' instead of 'cat'. + 2024-01-18 Antonio Diaz Diaz * Version 0.8 released. @@ -67,8 +75,7 @@ * Tests the code shipped in linux patches before june 2018. -Copyright (C) 2016-2024 Antonio Diaz Diaz. +Copyright (C) 2016-2025 Antonio Diaz Diaz. -This file is a collection of facts, and thus it is not copyrightable, -but just in case, you have unlimited permission to copy, distribute, and -modify it. +This file is a collection of facts, and thus it is not copyrightable, but just +in case, you have unlimited permission to copy, distribute, and modify it. diff --git a/INSTALL b/INSTALL index ae611fb..b706e0c 100644 --- a/INSTALL +++ b/INSTALL @@ -3,7 +3,8 @@ Requirements You will need a C99 compiler. (gcc 3.3.6 or newer is recommended). I use gcc 6.1.0 and 3.3.6, but the code should compile with any standards compliant compiler. -Gcc is available at http://gcc.gnu.org. +Gcc is available at http://gcc.gnu.org +Lzip is available at http://www.nongnu.org/lzip/lzip.html The operating system must allow signal handlers read access to objects with static storage duration so that the cleanup handler for Control-C can delete @@ -74,7 +75,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2016-2024 Antonio Diaz Diaz. +Copyright (C) 2016-2025 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/Makefile.in b/Makefile.in index 3df0e26..8988726 100644 --- a/Makefile.in +++ b/Makefile.in @@ -2,8 +2,8 @@ DISTNAME = $(pkgname)-$(pkgversion) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -m 755 -INSTALL_DATA = $(INSTALL) -m 644 INSTALL_DIR = $(INSTALL) -d -m 755 +INSTALL_DATA = $(INSTALL) -m 644 SHELL = /bin/sh CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1 @@ -30,7 +30,8 @@ main.o : main.c # prevent 'make' from trying to remake source files $(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ; -%.h %.c : ; +MAKEFLAGS += -r +.SUFFIXES : $(objs) : Makefile carg_parser.o : carg_parser.h @@ -122,11 +123,10 @@ dist : doc $(DISTNAME)/*.c \ $(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/test.txt \ + $(DISTNAME)/testsuite/em.lz \ $(DISTNAME)/testsuite/fox.lz \ $(DISTNAME)/testsuite/fox_*.lz \ - $(DISTNAME)/testsuite/zero.lz \ - $(DISTNAME)/testsuite/test.txt.lz \ - $(DISTNAME)/testsuite/test_em.txt.lz + $(DISTNAME)/testsuite/test.txt.lz rm -f $(DISTNAME) lzip -v -9 $(DISTNAME).tar diff --git a/NEWS b/NEWS index f96a2f3..81d5c0c 100644 --- a/NEWS +++ b/NEWS @@ -1,18 +1,7 @@ -Changes in version 0.8: +Changes in version 0.9: -File diagnostics have been reformatted as 'PROGRAM: FILE: MESSAGE'. +xlunzip now exits with error status 2 if any empty member is found in a +multimember file. -In case of error in a numerical argument to a command line option, lunzip -now shows the name of the option and the range of valid values. - -Diagnostics caused by invalid arguments to command-line options now show the -argument and the name of the option. - -The option '-o, --output' now preserves dates, permissions, and ownership of -the file, when decompressing exactly one file. - -The variable MAKEINFO has been added to configure and Makefile.in. - -It has been documented in INSTALL that when choosing a C standard, the POSIX -features need to be enabled explicitly: - ./configure CFLAGS+='--std=c99 -D_XOPEN_SOURCE=500' +xlunzip now exits with error status 2 if the first byte of the LZMA stream +is not 0. diff --git a/README b/README index 00c45ee..1c8af3e 100644 --- a/README +++ b/README @@ -1,3 +1,5 @@ +See the file INSTALL for compilation and installation instructions. + Description Xlunzip is a test tool for the lzip decompression code of my lzip patch for @@ -98,7 +100,11 @@ memory for compression ratios larger than 4:1, and does not even consider multimember data. -Copyright (C) 2016-2024 Antonio Diaz Diaz. +Xlunzip uses Arg_parser for command-line argument parsing: +http://www.nongnu.org/arg-parser/arg_parser.html + + +Copyright (C) 2016-2025 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute, and modify it. diff --git a/carg_parser.c b/carg_parser.c index edb4eb9..20b8a16 100644 --- a/carg_parser.c +++ b/carg_parser.c @@ -1,5 +1,5 @@ /* Arg_parser - POSIX/GNU command-line argument parser. (C version) - Copyright (C) 2006-2024 Antonio Diaz Diaz. + Copyright (C) 2006-2025 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -32,15 +32,15 @@ static void * ap_resize_buffer( void * buf, const int min_size ) } -static char push_back_record( struct Arg_parser * const ap, const int code, +static char push_back_record( Arg_parser * const ap, const int code, const char * const long_name, const char * const argument ) { - struct ap_Record * p; + ap_Record * p; void * tmp = ap_resize_buffer( ap->data, - ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); + ( ap->data_size + 1 ) * sizeof (ap_Record) ); if( !tmp ) return 0; - ap->data = (struct ap_Record *)tmp; + ap->data = (ap_Record *)tmp; p = &(ap->data[ap->data_size]); p->code = code; if( long_name ) @@ -71,7 +71,7 @@ static char push_back_record( struct Arg_parser * const ap, const int code, } -static char add_error( struct Arg_parser * const ap, const char * const msg ) +static char add_error( Arg_parser * const ap, const char * const msg ) { const int len = strlen( msg ); void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 ); @@ -83,7 +83,7 @@ static char add_error( struct Arg_parser * const ap, const char * const msg ) } -static void free_data( struct Arg_parser * const ap ) +static void free_data( Arg_parser * const ap ) { int i; for( i = 0; i < ap->data_size; ++i ) @@ -94,10 +94,9 @@ static void free_data( struct Arg_parser * const ap ) /* Return 0 only if out of memory. */ -static char parse_long_option( struct Arg_parser * const ap, +static char parse_long_option( Arg_parser * const ap, const char * const opt, const char * const arg, - const struct ap_Option options[], - int * const argindp ) + const ap_Option options[], int * const argindp ) { unsigned len; int index = -1, i; @@ -148,21 +147,21 @@ static char parse_long_option( struct Arg_parser * const ap, add_error( ap, "' requires an argument" ); return 1; } - return push_back_record( ap, options[index].code, - options[index].long_name, &opt[len+3] ); + return push_back_record( ap, options[index].code, options[index].long_name, + &opt[len+3] ); /* argument may be empty */ } - if( options[index].has_arg == ap_yes ) + if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme ) { - if( !arg || !arg[0] ) + if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) ) { add_error( ap, "option '--" ); add_error( ap, options[index].long_name ); add_error( ap, "' requires an argument" ); return 1; } ++*argindp; - return push_back_record( ap, options[index].code, - options[index].long_name, arg ); + return push_back_record( ap, options[index].code, options[index].long_name, + arg ); /* argument may be empty */ } return push_back_record( ap, options[index].code, @@ -171,10 +170,9 @@ static char parse_long_option( struct Arg_parser * const ap, /* Return 0 only if out of memory. */ -static char parse_short_option( struct Arg_parser * const ap, +static char parse_short_option( Arg_parser * const ap, const char * const opt, const char * const arg, - const struct ap_Option options[], - int * const argindp ) + const ap_Option options[], int * const argindp ) { int cind = 1; /* character index in opt */ @@ -204,15 +202,15 @@ static char parse_short_option( struct Arg_parser * const ap, if( !push_back_record( ap, c, 0, &opt[cind] ) ) return 0; ++*argindp; cind = 0; } - else if( options[index].has_arg == ap_yes ) + else if( options[index].has_arg == ap_yes || options[index].has_arg == ap_yme ) { - if( !arg || !arg[0] ) + if( !arg || ( options[index].has_arg == ap_yes && !arg[0] ) ) { add_error( ap, "option requires an argument -- '" ); add_error( ap, code_str ); add_error( ap, "'" ); return 1; } - ++*argindp; cind = 0; + ++*argindp; cind = 0; /* argument may be empty */ if( !push_back_record( ap, c, 0, arg ) ) return 0; } else if( !push_back_record( ap, c, 0, 0 ) ) return 0; @@ -221,9 +219,9 @@ static char parse_short_option( struct Arg_parser * const ap, } -char ap_init( struct Arg_parser * const ap, +char ap_init( Arg_parser * const ap, const int argc, const char * const argv[], - const struct ap_Option options[], const char in_order ) + const ap_Option options[], const char in_order ) { const char ** non_options = 0; /* skipped non-options */ int non_options_size = 0; /* number of skipped non-options */ @@ -282,7 +280,7 @@ out: if( non_options ) free( non_options ); } -void ap_free( struct Arg_parser * const ap ) +void ap_free( Arg_parser * const ap ) { free_data( ap ); if( ap->error ) { free( ap->error ); ap->error = 0; } @@ -290,29 +288,25 @@ void ap_free( struct Arg_parser * const ap ) } -const char * ap_error( const struct Arg_parser * const ap ) - { return ap->error; } +const char * ap_error( const Arg_parser * const ap ) { return ap->error; } +int ap_arguments( const Arg_parser * const ap ) { return ap->data_size; } -int ap_arguments( const struct Arg_parser * const ap ) - { return ap->data_size; } - - -int ap_code( const struct Arg_parser * const ap, const int i ) +int ap_code( const Arg_parser * const ap, const int i ) { if( i < 0 || i >= ap_arguments( ap ) ) return 0; return ap->data[i].code; } -const char * ap_parsed_name( const struct Arg_parser * const ap, const int i ) +const char * ap_parsed_name( const Arg_parser * const ap, const int i ) { if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].parsed_name ) return ""; return ap->data[i].parsed_name; } -const char * ap_argument( const struct Arg_parser * const ap, const int i ) +const char * ap_argument( const Arg_parser * const ap, const int i ) { if( i < 0 || i >= ap_arguments( ap ) || !ap->data[i].argument ) return ""; return ap->data[i].argument; diff --git a/carg_parser.h b/carg_parser.h index 69ce271..28eabee 100644 --- a/carg_parser.h +++ b/carg_parser.h @@ -1,5 +1,5 @@ /* Arg_parser - POSIX/GNU command-line argument parser. (C version) - Copyright (C) 2006-2024 Antonio Diaz Diaz. + Copyright (C) 2006-2025 Antonio Diaz Diaz. This library is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -37,60 +37,65 @@ The argument '--' terminates all options; any following arguments are treated as non-option arguments, even if they begin with a hyphen. - The syntax for optional option arguments is '-' - (without whitespace), or '--='. + The syntax of options with an optional argument is + '-' (without whitespace), or + '--='. + + The syntax of options with an empty argument is '- ""', + '-- ""', or '--=""'. */ #ifdef __cplusplus extern "C" { #endif -enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; +/* ap_yme = yes but maybe empty */ +typedef enum ap_Has_arg { ap_no, ap_yes, ap_maybe, ap_yme } ap_Has_arg; -struct ap_Option +typedef struct ap_Option { int code; /* Short option letter or code ( code != 0 ) */ const char * long_name; /* Long option name (maybe null) */ - enum ap_Has_arg has_arg; - }; + ap_Has_arg has_arg; + } ap_Option; -struct ap_Record +typedef struct ap_Record { int code; char * parsed_name; char * argument; - }; + } ap_Record; -struct Arg_parser +typedef struct Arg_parser { - struct ap_Record * data; + ap_Record * data; char * error; int data_size; int error_size; - }; + } Arg_parser; -char ap_init( struct Arg_parser * const ap, +char ap_init( Arg_parser * const ap, const int argc, const char * const argv[], - const struct ap_Option options[], const char in_order ); + const ap_Option options[], const char in_order ); -void ap_free( struct Arg_parser * const ap ); +void ap_free( Arg_parser * const ap ); -const char * ap_error( const struct Arg_parser * const ap ); +const char * ap_error( const Arg_parser * const ap ); /* The number of arguments parsed. May be different from argc. */ -int ap_arguments( const struct Arg_parser * const ap ); +int ap_arguments( const Arg_parser * const ap ); /* If ap_code( i ) is 0, ap_argument( i ) is a non-option. Else ap_argument( i ) is the option's argument (or empty). */ -int ap_code( const struct Arg_parser * const ap, const int i ); +int ap_code( const Arg_parser * const ap, const int i ); /* Full name of the option parsed (short or long). */ -const char * ap_parsed_name( const struct Arg_parser * const ap, const int i ); +const char * ap_parsed_name( const Arg_parser * const ap, const int i ); -const char * ap_argument( const struct Arg_parser * const ap, const int i ); +const char * ap_argument( const Arg_parser * const ap, const int i ); #ifdef __cplusplus } diff --git a/configure b/configure index d13ea80..fbdc084 100755 --- a/configure +++ b/configure @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Xlunzip - Test tool for the lzip_decompress linux module -# Copyright (C) 2016-2024 Antonio Diaz Diaz. +# Copyright (C) 2016-2025 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute, and modify it. pkgname=xlunzip -pkgversion=0.8 +pkgversion=0.9 progname=xlunzip srctrigger=doc/${progname}.1 @@ -109,7 +109,7 @@ while [ $# != 0 ] ; do exit 1 ;; esac - # Check if the option took a separate argument + # Check whether the option took a separate argument if [ "${arg2}" = yes ] ; then if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift else echo "configure: Missing argument to '${option}'" 1>&2 @@ -171,7 +171,7 @@ echo "MAKEINFO = ${MAKEINFO}" rm -f Makefile cat > Makefile << EOF # Makefile for Xlunzip - Test tool for the lzip_decompress linux module -# Copyright (C) 2016-2024 Antonio Diaz Diaz. +# Copyright (C) 2016-2025 Antonio Diaz Diaz. # This file was generated automatically by configure. Don't edit. # # This Makefile is free software: you have unlimited permission diff --git a/decompress_lunzip.c b/decompress_lunzip.c index 3425997..7019477 100644 --- a/decompress_lunzip.c +++ b/decompress_lunzip.c @@ -1,7 +1,7 @@ /* * Wrapper for decompressing LZIP-compressed kernel, initramfs, and initrd * - * Copyright (C) 2016-2024 Antonio Diaz Diaz. + * Copyright (C) 2016-2025 Antonio Diaz Diaz. * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ @@ -62,6 +62,9 @@ STATIC int INIT __lunzip(unsigned char *inbuf, long in_len, case LZIP_BAD_CRC: error("CRC mismatch in LZIP-compressed data."); break; + case LZIP_EMPTY_MEMBER: + error("Empty member in LZIP multimember data."); + break; default: error("Bug in the LZIP decompressor."); } return retval; diff --git a/doc/xlunzip.1 b/doc/xlunzip.1 index 1f870a8..6100b17 100644 --- a/doc/xlunzip.1 +++ b/doc/xlunzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. -.TH XLUNZIP "1" "January 2024" "xlunzip 0.8" "User Commands" +.TH XLUNZIP "1" "January 2025" "xlunzip 0.9" "User Commands" .SH NAME xlunzip \- test tool for the lzip_decompress linux module .SH SYNOPSIS @@ -86,7 +86,7 @@ Report bugs to lzip\-bug@nongnu.org .br Xlunzip home page: http://www.nongnu.org/lzip/xlunzip.html .SH COPYRIGHT -Copyright \(co 2024 Antonio Diaz Diaz. +Copyright \(co 2025 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later .br This is free software: you are free to change and redistribute it. diff --git a/in_place.c b/in_place.c index 11b9cbc..167c10f 100644 --- a/in_place.c +++ b/in_place.c @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2024 Antonio Diaz Diaz. + Copyright (C) 2016-2025 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -95,7 +95,7 @@ static const char * set_file_sizes( struct File_sizes * const file_sizes, const unsigned long file_size ) { if( file_size <= Lh_size ) return "File ends unexpectedly at member header."; - if( file_size < min_member_size ) return "Input file is too short."; + if( file_size < min_member_size ) return "Input file is truncated."; const Lzip_header * header = (const Lzip_header *)buffer; if( !Lh_check_magic( *header ) ) return "Bad magic number (file not in lzip format)."; @@ -167,7 +167,7 @@ static void error(char *x) { show_file_error( global_name, x, 0 ); } * |-------- decompressed data ---------| */ -int decompress_in_place( const int infd, struct Pretty_print * const pp, +int decompress_in_place( const int infd, Pretty_print * const pp, const bool testing ) { long buffer_size = 0, file_size = 0; diff --git a/linux_lzip.h b/linux_lzip.h index abd0d0c..7fb5635 100644 --- a/linux_lzip.h +++ b/linux_lzip.h @@ -4,7 +4,7 @@ /* * LZIP decompressor * - * Copyright (C) 2016-2024 Antonio Diaz Diaz. + * Copyright (C) 2016-2025 Antonio Diaz Diaz. */ /* Return values (< 0 = Error) */ @@ -20,7 +20,8 @@ enum { LZIP_WRITE_ERROR = -9, LZIP_BAD_DATA = -10, LZIP_DATA_EOF = -11, - LZIP_BAD_CRC = -12 + LZIP_BAD_CRC = -12, + LZIP_EMPTY_MEMBER = -13 }; int lzip_decompress(unsigned char *inbuf, long in_len, diff --git a/lzip.h b/lzip.h index 46a22d0..087f1e7 100644 --- a/lzip.h +++ b/lzip.h @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2024 Antonio Diaz Diaz. + Copyright (C) 2016-2025 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,14 +30,14 @@ enum { min_member_size = 36 }; -struct Pretty_print +typedef struct Pretty_print { const char * name; char * padded_name; const char * stdin_name; unsigned longest_name; bool first_post; - }; + } Pretty_print; static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ @@ -81,13 +81,13 @@ static inline void set_retval( int * retval, const int new_val ) static const char * const mem_msg = "Not enough memory."; /* defined in in_place.c */ -int decompress_in_place( const int infd, struct Pretty_print * const pp, +int decompress_in_place( const int infd, Pretty_print * const pp, const bool testing ); /* defined in main.c */ int convert_retval( const int retval ); long flush( void * buf, unsigned long size ); -void show_results( struct Pretty_print * const pp, const long in_pos, +void show_results( Pretty_print * const pp, const long in_pos, const long out_pos, const bool testing ); void show_file_error( const char * const filename, const char * const msg, const int errcode ); diff --git a/lzip_decompress.c b/lzip_decompress.c index 492523d..f2d22ee 100644 --- a/lzip_decompress.c +++ b/lzip_decompress.c @@ -1,7 +1,7 @@ /* * LZIP decompressor * - * Copyright (C) 2016-2024 Antonio Diaz Diaz. + * Copyright (C) 2016-2025 Antonio Diaz Diaz. * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ @@ -40,7 +40,7 @@ static inline State St_set_rep(const State st) return (st < 7) ? 8 : 11; } -static inline State St_set_short_rep(const State st) +static inline State St_set_shortrep(const State st) { return (st < 7) ? 9 : 11; } @@ -359,14 +359,17 @@ static inline uint8_t Rd_get_byte(struct Range_decoder * const rdec) return rdec->buffer[rdec->pos++]; } -static inline void Rd_load(struct Range_decoder * const rdec) +static inline bool Rd_load(struct Range_decoder * const rdec) { int i; rdec->code = 0; rdec->range = 0xFFFFFFFFU; - Rd_get_byte(rdec); /* discard first byte of the LZMA stream */ + /* check first byte of the LZMA stream */ + if (Rd_get_byte(rdec) != 0) + return false; for (i = 0; i < 4; ++i) rdec->code = (rdec->code << 8) | Rd_get_byte(rdec); + return true; } static inline void Rd_normalize(struct Range_decoder * const rdec) @@ -693,7 +696,8 @@ static int LZd_decode_member(struct LZ_decoder * const d) unsigned rep3 = 0; State state = 0; - Rd_load(rdec); + if (!Rd_load(rdec)) + return LZIP_BAD_DATA; while (!Rd_finished(rdec)) { int len; const int pos_state = LZd_data_position(d) & pos_state_mask; @@ -715,7 +719,7 @@ static int LZd_decode_member(struct LZ_decoder * const d) if (Rd_decode_bit(rdec, &d->bm_rep[state]) != 0) { if (Rd_decode_bit(rdec, &d->bm_rep0[state]) == 0) { if (Rd_decode_bit(rdec, &d->bm_len[state][pos_state]) == 0) { - state = St_set_short_rep(state); + state = St_set_shortrep(state); LZd_put_byte(d, LZd_peek(d, rep0)); continue; } @@ -739,23 +743,21 @@ static int LZd_decode_member(struct LZ_decoder * const d) state = St_set_rep(state); len = Rd_decode_len(rdec, &d->rep_len_model, pos_state); } else { /* match */ - unsigned distance; - + rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Rd_decode_len(rdec, &d->match_len_model, pos_state); - distance = Rd_decode_tree6(rdec, d->bm_dis_slot[get_len_state(len)]); - if (distance >= start_dis_model) { - const unsigned dis_slot = distance; + rep0 = Rd_decode_tree6(rdec, d->bm_dis_slot[get_len_state(len)]); + if (rep0 >= start_dis_model) { + const unsigned dis_slot = rep0; const int direct_bits = (dis_slot >> 1) - 1; - distance = (2 | (dis_slot & 1)) << direct_bits; + rep0 = (2 | (dis_slot & 1)) << direct_bits; if (dis_slot < end_dis_model) - distance += Rd_decode_tree_reversed(rdec, - d->bm_dis + (distance - dis_slot), direct_bits); + rep0 += Rd_decode_tree_reversed(rdec, + d->bm_dis + (rep0 - dis_slot), direct_bits); else { - distance += - Rd_decode(rdec, direct_bits - dis_align_bits) << dis_align_bits; - distance += Rd_decode_tree_reversed4(rdec, d->bm_align); - if (distance == 0xFFFFFFFFU) { /* marker found */ + rep0 += Rd_decode(rdec, direct_bits - dis_align_bits) << dis_align_bits; + rep0 += Rd_decode_tree_reversed4(rdec, d->bm_align); + if (rep0 == 0xFFFFFFFFU) { /* marker found */ Rd_normalize(rdec); LZd_flush_data(d); if (d->write_error) @@ -770,7 +772,6 @@ static int LZd_decode_member(struct LZ_decoder * const d) } } } - rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance; state = St_set_match(state); if (rep0 >= d->dictionary_size || (rep0 >= d->pos && !d->pos_wrapped)) { @@ -796,6 +797,7 @@ int lzip_decompress(unsigned char *inbuf, long in_len, struct LZ_decoder *decoder = 0; int retval = 0; bool first_member; + bool empty = false, multi = false; if (in_posp) *in_posp = 0; @@ -849,7 +851,9 @@ int lzip_decompress(unsigned char *inbuf, long in_len, retval = LZd_decode_member(decoder); if (in_posp) *in_posp += Rd_member_position(&rdec); + multi = !first_member; data_pos = LZd_data_position(decoder); + if (data_pos == 0) empty = true; if (outptr) outptr += data_pos; if (out_posp) @@ -863,6 +867,8 @@ int lzip_decompress(unsigned char *inbuf, long in_len, if (decoder) free(decoder); Rd_free(&rdec); + if (empty && multi && retval == 0) + retval = LZIP_EMPTY_MEMBER; return retval; } diff --git a/main.c b/main.c index 67d011f..252f419 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2024 Antonio Diaz Diaz. + Copyright (C) 2016-2025 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ #include #include #include -#include /* SSIZE_MAX */ +#include /* CHAR_BIT, SSIZE_MAX */ #include #include #include /* SIZE_MAX */ @@ -80,7 +80,7 @@ static void show_error( const char * const msg, const int errcode, const bool help ); static const char * const program_name = "xlunzip"; -static const char * const program_year = "2024"; +static const char * const program_year = "2025"; static const char * invocation_name = "xlunzip"; /* default value */ static const struct { const char * from; const char * to; } known_extensions[] = { @@ -164,7 +164,7 @@ static void * resize_buffer( void * buf, const unsigned min_size ) } -static void Pp_init( struct Pretty_print * const pp, +static void Pp_init( Pretty_print * const pp, const char * const filenames[], const int num_filenames ) { pp->name = 0; @@ -185,8 +185,10 @@ static void Pp_init( struct Pretty_print * const pp, if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; } -static void Pp_set_name( struct Pretty_print * const pp, - const char * const filename ) +void Pp_free( Pretty_print * const pp ) + { if( pp->padded_name ) { free( pp->padded_name ); pp->padded_name = 0; } } + +static void Pp_set_name( Pretty_print * const pp, const char * const filename ) { unsigned name_len, padded_name_len, i = 0; @@ -204,7 +206,7 @@ static void Pp_set_name( struct Pretty_print * const pp, pp->first_post = true; } -static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) +static void Pp_show_msg( Pretty_print * const pp, const char * const msg ) { if( verbosity < 0 ) return; if( pp->first_post ) @@ -229,7 +231,7 @@ static const char * format_num3( unsigned long long num ) char * const buf = buffer[current++]; current %= buffers; char * p = buf + bufsize - 1; /* fill the buffer backwards */ *p = 0; /* terminator */ - if( num > 1024 ) + if( num > 9999 ) { char prefix = 0; /* try binary first, then si */ for( i = 0; i < n && num != 0 && num % 1024 == 0; ++i ) @@ -275,7 +277,7 @@ static unsigned long getnum( const char * const arg, if( !errno && tail[0] ) { - const unsigned factor = ( tail[1] == 'i' ) ? 1024 : 1000; + const unsigned factor = (tail[1] == 'i') ? 1024 : 1000; int exponent = 0; /* 0 = bad multiplier */ int i; switch( tail[0] ) @@ -365,9 +367,9 @@ static int open_instream( const char * const name, struct stat * const in_statsp { const int i = fstat( infd, in_statsp ); const mode_t mode = in_statsp->st_mode; - const bool can_read = ( i == 0 && - ( S_ISBLK( mode ) || S_ISCHR( mode ) || - S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); + const bool can_read = i == 0 && + ( S_ISBLK( mode ) || S_ISCHR( mode ) || + S_ISFIFO( mode ) || S_ISSOCK( mode ) ); if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) ) { if( verbosity >= 0 ) @@ -482,10 +484,10 @@ int convert_retval( const int retval ) { switch( retval ) { - case 0: return 0; + case 0: return 0; case LZIP_OOM_INBUF: case LZIP_OOM_OUTBUF: - case LZIP_WRITE_ERROR: return 1; + case LZIP_WRITE_ERROR: return 1; case LZIP_HEADER1_EOF: case LZIP_HEADER2_EOF: case LZIP_BAD_MAGIC1: @@ -494,8 +496,9 @@ int convert_retval( const int retval ) case LZIP_BAD_DICT_SIZE: case LZIP_BAD_DATA: case LZIP_DATA_EOF: - case LZIP_BAD_CRC: return 2; - default: return 3; + case LZIP_BAD_CRC: + case LZIP_EMPTY_MEMBER: return 2; + default: return 3; } } @@ -519,7 +522,7 @@ static long fill( void * buf, unsigned long size ) long flush( void * buf, unsigned long size ) { - unsigned long sz = ( outfd >= 0 ) ? 0 : size; + unsigned long sz = (outfd >= 0) ? 0 : size; errno = 0; while( sz < size ) { @@ -535,7 +538,7 @@ static const char * global_name; /* copy of filename for 'error' */ static void error(char *x) { show_file_error( global_name, x, 0 ); } -static int decompress( const int infd, struct Pretty_print * const pp, +static int decompress( const int infd, Pretty_print * const pp, const long cl_insize, const long cl_outsize, const bool nofill, const bool noflush, const bool testing ) { @@ -574,7 +577,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, } -void show_results( struct Pretty_print * const pp, const long in_pos, +void show_results( Pretty_print * const pp, const long in_pos, const long out_pos, const bool testing ) { if( verbosity >= 1 ) Pp_show_msg( pp, 0 ); @@ -631,7 +634,6 @@ int main( const int argc, const char * const argv[] ) const char * default_output_filename = ""; long cl_insize = 0; long cl_outsize = 0; - int i; bool force = false; bool in_place = false; bool keep_input_files = false; @@ -642,7 +644,7 @@ int main( const int argc, const char * const argv[] ) if( argc > 0 ) invocation_name = argv[0]; enum { opt_insize = 256, opt_outsize, opt_nofill, opt_noflush }; - const struct ap_Option options[] = + const ap_Option options[] = { { 'c', "stdout", ap_no }, { 'd', "decompress", ap_no }, @@ -656,14 +658,14 @@ int main( const int argc, const char * const argv[] ) { 't', "test", ap_no }, { 'v', "verbose", ap_no }, { 'V', "version", ap_no }, - { opt_insize, "insize", ap_maybe }, - { opt_outsize, "outsize", ap_maybe }, + { opt_insize, "insize", ap_maybe }, + { opt_outsize, "outsize", ap_maybe }, { opt_nofill, "nofill", ap_no }, { opt_noflush, "noflush", ap_no }, - { 0, 0, ap_no } }; + { 0, 0, ap_no } }; /* static because valgrind complains and memory management in C sucks */ - static struct Arg_parser parser; + static Arg_parser parser; if( !ap_init( &parser, argc, argv, options, 0 ) ) { show_error( mem_msg, 0, false ); return 1; } if( ap_error( &parser ) ) /* bad option */ @@ -684,7 +686,7 @@ int main( const int argc, const char * const argv[] ) case 'h': show_help(); return 0; case 'I': in_place = true; break; case 'k': keep_input_files = true; break; - case 'n': break; + case 'n': break; /* ignored */ case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true; else { default_output_filename = arg; } break; case 'q': verbosity = -1; break; @@ -712,6 +714,7 @@ int main( const int argc, const char * const argv[] ) filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); filenames[0] = "-"; + int i; bool filenames_given = false; for( i = 0; argind + i < ap_arguments( &parser ); ++i ) { @@ -731,7 +734,7 @@ int main( const int argc, const char * const argv[] ) if( !to_stdout && !testing && ( filenames_given || to_file ) ) set_signals( signal_handler ); - static struct Pretty_print pp; + static Pretty_print pp; Pp_init( &pp, filenames, num_filenames ); int failed_tests = 0; @@ -807,6 +810,7 @@ int main( const int argc, const char * const argv[] ) program_name, failed_tests, ( failed_tests == 1 ) ? "file" : "files" ); free( output_filename ); + Pp_free( &pp ); free( filenames ); ap_free( &parser ); return retval; diff --git a/testsuite/check.sh b/testsuite/check.sh index 050ccda..65ca993 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh # check script for Xlunzip - Test tool for the lzip_decompress linux module -# Copyright (C) 2016-2024 Antonio Diaz Diaz. +# Copyright (C) 2016-2025 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute, and modify it. @@ -28,11 +28,11 @@ if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp cd "${objdir}"/tmp || framework_failure -cat "${testdir}"/test.txt > in || framework_failure +cp "${testdir}"/test.txt in || framework_failure in_lz="${testdir}"/test.txt.lz -in_em="${testdir}"/test_em.txt.lz +em_lz="${testdir}"/em.lz fox_lz="${testdir}"/fox.lz -zero_lz="${testdir}"/zero.lz +fnz_lz="${testdir}"/fox_nz.lz fail=0 test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } @@ -80,29 +80,24 @@ printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null printf "\ntesting decompression..." -for i in "${in_lz}" "${in_em}" ; 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 "${in_lz}" || test_failed $LINENO +"${LZIP}" -d "${in_lz}" -o out || test_failed $LINENO +cmp in out || test_failed $LINENO +"${LZIP}" -cd "${in_lz}" > out || test_failed $LINENO +cmp in out || test_failed $LINENO +"${LZIP}" -d "${in_lz}" -o - > out || test_failed $LINENO +cmp in out || test_failed $LINENO +"${LZIP}" -d < "${in_lz}" > out || test_failed $LINENO +cmp in out || test_failed $LINENO +rm -f out || framework_failure -lines=`"${LZIP}" -tvv "${in_em}" 2>&1 | wc -l` || test_failed $LINENO -[ "${lines}" -eq 1 ] || test_failed $LINENO "${lines}" - -cat "${in_lz}" > out.lz || framework_failure +cp "${in_lz}" out.lz || framework_failure "${LZIP}" -dk out.lz || test_failed $LINENO cmp in out || test_failed $LINENO rm -f out || framework_failure "${LZIP}" -cd "${fox_lz}" > fox || test_failed $LINENO -cat fox > copy || framework_failure -cat "${in_lz}" > copy.lz || framework_failure +cp fox copy || framework_failure +cp "${in_lz}" copy.lz || framework_failure "${LZIP}" -d copy.lz out.lz 2> /dev/null # skip copy, decompress out [ $? = 1 ] || test_failed $LINENO [ ! -e out.lz ] || test_failed $LINENO @@ -116,7 +111,6 @@ rm -f copy out || framework_failure printf "to be overwritten" > out || framework_failure "${LZIP}" -df -o out < "${in_lz}" || test_failed $LINENO cmp in out || test_failed $LINENO -rm -f out || framework_failure "${LZIP}" -d -o ./- "${in_lz}" || test_failed $LINENO cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure @@ -124,12 +118,12 @@ rm -f ./- || framework_failure cmp in ./- || test_failed $LINENO rm -f ./- || framework_failure -cat "${in_lz}" > anyothername || framework_failure +cp "${in_lz}" anyothername || framework_failure "${LZIP}" -dv - anyothername - < "${in_lz}" > out 2> /dev/null || test_failed $LINENO cmp in out || test_failed $LINENO cmp in anyothername.out || test_failed $LINENO -rm -f out anyothername.out || framework_failure +rm -f anyothername.out || framework_failure "${LZIP}" -tq in "${in_lz}" [ $? = 2 ] || test_failed $LINENO @@ -142,7 +136,7 @@ cat out in | cmp in - || test_failed $LINENO # out must be empty [ $? = 1 ] || test_failed $LINENO cmp in out || test_failed $LINENO rm -f out || framework_failure -cat "${in_lz}" > out.lz || framework_failure +cp "${in_lz}" out.lz || framework_failure "${LZIP}" -dq in out.lz [ $? = 2 ] || test_failed $LINENO [ -e out.lz ] || test_failed $LINENO @@ -166,19 +160,73 @@ cmp in2 out2 || test_failed $LINENO rm -f out2 || framework_failure cat "${in_lz}" "${in_lz}" > out2.lz || framework_failure +lines=`"${LZIP}" -tvv out2.lz 2>&1 | wc -l` || test_failed $LINENO +[ "${lines}" -eq 1 ] || test_failed $LINENO "${lines}" + printf "\ngarbage" >> out2.lz || framework_failure "${LZIP}" -tvvvv out2.lz 2> /dev/null || test_failed $LINENO printf "to be overwritten" > out2 || framework_failure "${LZIP}" -df out2.lz || test_failed $LINENO cmp in2 out2 || test_failed $LINENO +touch empty || framework_failure +cp "${em_lz}" em.lz || framework_failure +"${LZIP}" -dk em.lz || test_failed $LINENO +cmp empty em || test_failed $LINENO + printf "\ntesting bad input..." +cat em.lz em.lz | "${LZIP}" -tq +[ $? = 2 ] || test_failed $LINENO +cat em.lz em.lz | "${LZIP}" -dq > em +[ $? = 2 ] || test_failed $LINENO +cmp empty em || test_failed $LINENO +cat em.lz "${in_lz}" | "${LZIP}" -tq +[ $? = 2 ] || test_failed $LINENO +cat em.lz "${in_lz}" | "${LZIP}" -dq > out +[ $? = 2 ] || test_failed $LINENO +cmp in out || test_failed $LINENO +cat "${in_lz}" em.lz | "${LZIP}" -tq +[ $? = 2 ] || test_failed $LINENO +cat "${in_lz}" em.lz | "${LZIP}" -dq > out +[ $? = 2 ] || test_failed $LINENO +cmp in out || test_failed $LINENO +cat em.lz em.lz > ee.lz || framework_failure +"${LZIP}" -tq < ee.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -dq < ee.lz > em +[ $? = 2 ] || test_failed $LINENO +cmp empty em || test_failed $LINENO +"${LZIP}" -tq ee.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -dq ee.lz +[ $? = 2 ] || test_failed $LINENO +[ ! -e ee ] || test_failed $LINENO +"${LZIP}" -cdq ee.lz > em +[ $? = 2 ] || test_failed $LINENO +cmp empty em || test_failed $LINENO +rm -f em || framework_failure +cat "${in_lz}" em.lz "${in_lz}" > inein.lz || framework_failure +"${LZIP}" -tq < inein.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -dq < inein.lz > out2 +[ $? = 2 ] || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO +"${LZIP}" -tq inein.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -dq inein.lz +[ $? = 2 ] || test_failed $LINENO +[ ! -e inein ] || test_failed $LINENO +"${LZIP}" -cdq inein.lz > out2 +[ $? = 2 ] || test_failed $LINENO +cmp in2 out2 || test_failed $LINENO +rm -f out2 inein.lz em.lz || framework_failure + headers='LZIp LZiP LZip LzIP LzIp LziP lZIP lZIp lZiP lzIP' -body='\001\014\000\203\377\373\377\377\300\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000' -cat "${in_lz}" > int.lz || framework_failure +body='\001\014\000\000\101\376\367\377\377\340\000\200\000\215\357\002\322\001\000\000\000\000\000\000\000\045\000\000\000\000\000\000\000' +cp "${in_lz}" int.lz || framework_failure printf "LZIP${body}" >> int.lz || framework_failure -if "${LZIP}" -tq int.lz ; then +if "${LZIP}" -t int.lz ; then for header in ${headers} ; do printf "${header}${body}" > int.lz || framework_failure "${LZIP}" -tq int.lz # first member @@ -187,7 +235,7 @@ if "${LZIP}" -tq int.lz ; then [ $? = 2 ] || test_failed $LINENO ${header} "${LZIP}" -cdq int.lz > /dev/null [ $? = 2 ] || test_failed $LINENO ${header} - cat "${in_lz}" > int.lz || framework_failure + cp "${in_lz}" int.lz || framework_failure printf "${header}${body}" >> int.lz || framework_failure "${LZIP}" -tq int.lz # trailing data [ $? = 2 ] || test_failed $LINENO ${header} @@ -197,10 +245,13 @@ if "${LZIP}" -tq int.lz ; then [ $? = 2 ] || test_failed $LINENO ${header} done else - printf "\nwarning: skipping header test: 'printf' does not work on your system." + printf "warning: skipping header test: 'printf' does not work on your system." fi rm -f int.lz || framework_failure +"${LZIP}" -tq "${fnz_lz}" +[ $? = 2 ] || test_failed $LINENO + for i in fox_v2.lz fox_s11.lz fox_de20.lz \ fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do "${LZIP}" -tq "${testdir}"/$i @@ -212,13 +263,13 @@ for i in fox_bcrc.lz fox_crc0.lz fox_das46.lz fox_mes81.lz ; do [ $? = 2 ] || test_failed $LINENO $i cmp fox out || test_failed $LINENO $i done -rm -f fox out || framework_failure +rm -f fox || framework_failure cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure -if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && - [ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then - for i in 6 20 14734 14753 14754 14755 14756 14757 14758 ; do +if dd if=in3.lz of=trunc.lz bs=14682 count=1 2> /dev/null && + [ -e trunc.lz ] && cmp in2.lz trunc.lz ; then + for i in 6 20 14664 14683 14684 14685 14686 14687 14688 ; do dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null "${LZIP}" -tq trunc.lz [ $? = 2 ] || test_failed $LINENO $i @@ -230,15 +281,17 @@ if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && [ $? = 2 ] || test_failed $LINENO $i done else - printf "\nwarning: skipping truncation test: 'dd' does not work on your system." + printf "warning: skipping truncation test: 'dd' does not work on your system." fi rm -f trunc.lz || framework_failure -cat "${in_lz}" > ingin.lz || framework_failure +cp "${in_lz}" ingin.lz || framework_failure printf "g" >> ingin.lz || framework_failure cat "${in_lz}" >> ingin.lz || framework_failure "${LZIP}" -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 @@ -274,7 +327,7 @@ for i in =18KiB =65536 =262144 ; do cmp in out || test_failed $LINENO $i done -for i in =36388 =65536 =262144 ; do +for i in =36301 =65536 =262144 ; do "${LZIP}" -t --outsize$i --noflush "${in_lz}" || test_failed $LINENO $i "${LZIP}" -cd --outsize$i --noflush "${in_lz}" > out || @@ -282,7 +335,7 @@ for i in =36388 =65536 =262144 ; do cmp in out || test_failed $LINENO $i done -for i in =36387 ; do +for i in =36300 ; do "${LZIP}" -tq --outsize$i --noflush "${in_lz}" [ $? = 1 ] || test_failed $LINENO $i "${LZIP}" -cdq --outsize$i --noflush "${in_lz}" > out @@ -352,18 +405,21 @@ for i in in2 in3 ; do done "${LZIP}" -tq --in-place ingin.lz [ $? = 2 ] || test_failed $LINENO -rm -f out out2 ingin.lz in2 in2.lz in3 in3.lz || framework_failure +rm -f out2 ingin.lz in2 in2.lz in3 in3.lz || framework_failure -cat "${in_lz}" > inz.lz || framework_failure -counter=0 -while [ ${counter} -lt 20 ] ; do - cat "${zero_lz}" >> inz.lz || framework_failure - "${LZIP}" -t --in-place inz.lz || test_failed $LINENO - "${LZIP}" -cd --in-place inz.lz > out || test_failed $LINENO - cmp in out || test_failed $LINENO - counter=$((counter+1)) -done -rm -f out inz.lz || framework_failure +cat "${in_lz}" "${em_lz}" > ine.lz || framework_failure +"${LZIP}" -tq --in-place ine.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -cdq --in-place ine.lz > out +[ $? = 2 ] || test_failed $LINENO +cmp empty out || test_failed $LINENO +cat "${em_lz}" "${in_lz}" > ine.lz || framework_failure +"${LZIP}" -tq --in-place ine.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -cdq --in-place ine.lz > out +[ $? = 2 ] || test_failed $LINENO +cmp empty out || test_failed $LINENO +rm -f ine.lz empty || framework_failure # decompress with trailing data in place cat "${in_lz}" in in in in > int.lz || framework_failure diff --git a/testsuite/zero.lz b/testsuite/em.lz similarity index 100% rename from testsuite/zero.lz rename to testsuite/em.lz diff --git a/testsuite/fox_nz.lz b/testsuite/fox_nz.lz new file mode 100644 index 0000000000000000000000000000000000000000..44a4b58b881d207627f6081d8ad04708c25400dc GIT binary patch literal 80 zcmeZ?@(f_)Nz{_!Sj4QF_R+iI=pxqtde3fNQjl6}^5c>03rDkGci1v_+dL64QRjTU cIqmVA>95u)|NqywfFbKlz-wIw2nc}E0AJQ0O8@`> literal 0 HcmV?d00001 diff --git a/testsuite/test.txt b/testsuite/test.txt index 9196a3a..423f0c0 100644 --- a/testsuite/test.txt +++ b/testsuite/test.txt @@ -1,8 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -339,8 +338,7 @@ Public License instead of this License. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/testsuite/test.txt.lz b/testsuite/test.txt.lz index 22cea6e4d2a58b4dcb006541dcdb8defabba0cbb..5dc169f7fb6e952f17e7a21ce3691eeaac2fb3aa 100644 GIT binary patch delta 7294 zcmV-^9D(D|IjuR6Zhys3yJ(c8peBW%f-elXuLG8+YcW?HC;m#{D%pU^WiRDBah9%H zoNKDm$X*ivN}frZPJV^dtsX$0%Z^SSxrOZEO@c$q7owY! z`W;W~c7VLKKJvfUJ)mGF=tySp{PxY$8`#(o1p?=vxoYM*hkx#@T($B}rE}wqiNbai zPkS|>8W_N@+GNU=i-?`g4gP^bKc=(O|BTS>tf}Y}sWaDOa9)@f3Z>pC@4M?MqsMyf z$l9a4FCJZ;`)tQ5Wbrs^K<$Gkx9@N*`^#x7IXK%ex=T%-ID=$T@CGUn*XOjK7%aI^ z{P$K|lLRk7DSwY<;3s2ge)hV`mKFEf_=bs$Oa|MsKB4EOEq5 zbi#35GkG6xskoc^ai7hojVayH{;Ap%0D7qkn{2{=+J9YtzU8rM;x_SA8&KAYW1k_h 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 I000000MqzJBme*a diff --git a/testsuite/test_em.txt.lz b/testsuite/test_em.txt.lz deleted file mode 100644 index 7e96250d9ec70bc7d8cb173f438c76be447e6b6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14024 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 Gt^OBPlQ$#) From 0c057f26066f0924a2aeabbe16185d4c48c5ba35 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 17 Feb 2025 22:53:41 +0100 Subject: [PATCH 10/10] Releasing debian version 0.9-1. Signed-off-by: Daniel Baumann --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index b4e2ca4..952981e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +xlunzip (0.9-1) sid; urgency=medium + + * Uploading to sid. + * Merging upstream version 0.9. + + -- Daniel Baumann Tue, 14 Jan 2025 11:02:22 +0100 + xlunzip (0.8-2) sid; urgency=medium * Uploading to sid.