1
0
Fork 0

Merging upstream version 1.4~rc1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 22:11:54 +01:00
parent 61d94272f8
commit 6628968590
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
12 changed files with 83 additions and 92 deletions

View file

@ -1,3 +1,9 @@
2013-06-27 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.4-rc1 released.
* main.c (show_header): Do not show header version.
* Minor fixes.
2013-06-18 Antonio Diaz Diaz <antonio@gnu.org> 2013-06-18 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.3 released. * Version 1.3 released.

View file

@ -10,9 +10,9 @@ Procedure
--------- ---------
1. Unpack the archive if you have not done so already: 1. Unpack the archive if you have not done so already:
lzip -cd lunzip[version].tar.lz | tar -xf - tar -xf lunzip[version].tar.lz
or or
gzip -cd lunzip[version].tar.gz | tar -xf - lzip -cd lunzip[version].tar.lz | tar -xf -
This creates the directory ./lunzip[version] containing the source from This creates the directory ./lunzip[version] containing the source from
the main archive. the main archive.

View file

@ -43,7 +43,7 @@ $(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texinfo
man : $(VPATH)/doc/$(progname).1 man : $(VPATH)/doc/$(progname).1
$(VPATH)/doc/$(progname).1 : $(progname) $(VPATH)/doc/$(progname).1 : $(progname)
help2man -n 'small decompressor for lzip files' \ help2man -n 'decompressor for lzip files' \
-o $@ --no-info ./$(progname) -o $@ --no-info ./$(progname)
Makefile : $(VPATH)/configure $(VPATH)/Makefile.in Makefile : $(VPATH)/configure $(VPATH)/Makefile.in

11
NEWS
View file

@ -1,10 +1,5 @@
Changes in version 1.3: Changes in version 1.4:
Decompression time has been reduced by 1%. File version is no more shown in status messages.
File version is now shown only if verbosity >= 4. Minor fixes.
Option "-n, --threads" is now accepted and ignored for compatibility
with plzip.
"configure" now accepts options with a separate argument.

20
README
View file

@ -3,26 +3,16 @@ Description
Lunzip is a decompressor for lzip files. It is written in C and its Lunzip is a decompressor for lzip files. It is written in C and its
small size makes it well suited for embedded devices or software small size makes it well suited for embedded devices or software
installers that need to decompress files but do not need compression installers that need to decompress files but do not need compression
capabilities. capabilities. Lunzip is fully compatible with lzip-1.4 or newer.
The lzip file format is designed for long-term data archiving. It is
clean, provides very safe 4 factor integrity checking, and is backed by
the recovery capabilities of lziprecover.
Lunzip uses the same well-defined exit status values used by lzip and Lunzip uses the same well-defined exit status values used by lzip and
bzip2, which makes it safer when used in pipes or scripts than bzip2, which makes it safer when used in pipes or scripts than
decompressors returning ambiguous warning values, like gunzip. decompressors returning ambiguous warning values, like gunzip.
The 4 factor integrity checking of the lzip format guarantees that the
decompressed version of the data is identical to the original. This
guards against corruption of the compressed data, and against undetected
bugs in lunzip (hopefully very unlikely). The chances of data corruption
going undetected are microscopic. Be aware, though, that the check
occurs upon decompression, so it can only tell you that something is
wrong. It can't help you recover the original uncompressed data.
If you ever need to recover data from a damaged lzip file, try the
lziprecover program. Lziprecover makes lzip files resistant to bit-flip,
one of the most common forms of data corruption, and its recovery
capabilities contribute to make of the lzip format one of the best
options for long-term data archiving.
Lunzip replaces every file given in the command line with a decompressed Lunzip replaces every file given in the command line with a decompressed
version of itself. Each decompressed file has the same modification version of itself. Each decompressed file has the same modification
date, permissions, and, when possible, ownership as the corresponding date, permissions, and, when possible, ownership as the corresponding

4
configure vendored
View file

@ -6,9 +6,9 @@
# to copy, distribute and modify it. # to copy, distribute and modify it.
pkgname=lunzip pkgname=lunzip
pkgversion=1.3 pkgversion=1.4-rc1
progname=lunzip progname=lunzip
srctrigger=doc/lunzip.1 srctrigger=doc/${progname}.1
# clear some things potentially inherited from environment. # clear some things potentially inherited from environment.
LC_ALL=C LC_ALL=C

View file

@ -34,7 +34,7 @@ CRC32 crc32;
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
{ {
if( pp->verbosity >= 0 ) if( verbosity >= 0 )
{ {
if( pp->first_post ) if( pp->first_post )
{ {
@ -122,26 +122,23 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder,
struct Pretty_print * const pp ) struct Pretty_print * const pp )
{ {
File_trailer trailer; File_trailer trailer;
const int trailer_size = Ft_versioned_size( decoder->member_version );
const unsigned long long member_size = const unsigned long long member_size =
Rd_member_position( decoder->rdec ) + trailer_size; Rd_member_position( decoder->rdec ) + Ft_size;
bool error = false; bool error = false;
int size = Rd_read_data( decoder->rdec, trailer, trailer_size ); int size = Rd_read_data( decoder->rdec, trailer, Ft_size );
if( size < trailer_size ) if( size < Ft_size )
{ {
error = true; error = true;
if( pp->verbosity >= 0 ) if( verbosity >= 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
fprintf( stderr, "Trailer truncated at trailer position %d;" fprintf( stderr, "Trailer truncated at trailer position %d;"
" some checks may fail.\n", size ); " some checks may fail.\n", size );
} }
while( size < trailer_size ) trailer[size++] = 0; while( size < Ft_size ) trailer[size++] = 0;
} }
if( decoder->member_version == 0 ) Ft_set_member_size( trailer, member_size );
if( decoder->rdec->code != 0 ) if( decoder->rdec->code != 0 )
{ {
error = true; error = true;
@ -150,7 +147,7 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder,
if( Ft_get_data_crc( trailer ) != LZd_crc( decoder ) ) if( Ft_get_data_crc( trailer ) != LZd_crc( decoder ) )
{ {
error = true; error = true;
if( pp->verbosity >= 0 ) if( verbosity >= 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
fprintf( stderr, "CRC mismatch; trailer says %08X, data CRC is %08X.\n", fprintf( stderr, "CRC mismatch; trailer says %08X, data CRC is %08X.\n",
@ -160,7 +157,7 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder,
if( Ft_get_data_size( trailer ) != LZd_data_position( decoder ) ) if( Ft_get_data_size( trailer ) != LZd_data_position( decoder ) )
{ {
error = true; error = true;
if( pp->verbosity >= 0 ) if( verbosity >= 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX).\n", fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX).\n",
@ -170,19 +167,19 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder,
if( Ft_get_member_size( trailer ) != member_size ) if( Ft_get_member_size( trailer ) != member_size )
{ {
error = true; error = true;
if( pp->verbosity >= 0 ) if( verbosity >= 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX).\n", fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX).\n",
Ft_get_member_size( trailer ), member_size, member_size ); Ft_get_member_size( trailer ), member_size, member_size );
} }
} }
if( !error && pp->verbosity >= 2 && LZd_data_position( decoder ) > 0 && member_size > 0 ) if( !error && verbosity >= 2 && LZd_data_position( decoder ) > 0 && member_size > 0 )
fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ", fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
(double)LZd_data_position( decoder ) / member_size, (double)LZd_data_position( decoder ) / member_size,
( 8.0 * member_size ) / LZd_data_position( decoder ), ( 8.0 * member_size ) / LZd_data_position( decoder ),
100.0 * ( 1.0 - ( (double)member_size / LZd_data_position( decoder ) ) ) ); 100.0 * ( 1.0 - ( (double)member_size / LZd_data_position( decoder ) ) ) );
if( !error && pp->verbosity >= 4 ) if( !error && verbosity >= 4 )
fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ", fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ",
Ft_get_data_crc( trailer ), Ft_get_data_crc( trailer ),
Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) ); Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) );
@ -266,8 +263,7 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits; rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
if( dis_slot < end_dis_model ) if( dis_slot < end_dis_model )
rep0 += Rd_decode_tree_reversed( rdec, rep0 += Rd_decode_tree_reversed( rdec,
decoder->bm_dis + rep0 - dis_slot - 1, decoder->bm_dis + rep0 - dis_slot - 1, direct_bits );
direct_bits );
else else
{ {
rep0 += Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits; rep0 += Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;
@ -285,7 +281,7 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
{ {
Rd_load( rdec ); continue; Rd_load( rdec ); continue;
} }
if( pp->verbosity >= 0 ) if( verbosity >= 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
fprintf( stderr, "Unsupported marker code '%d'.\n", len ); fprintf( stderr, "Unsupported marker code '%d'.\n", len );

View file

@ -237,7 +237,6 @@ struct LZ_decoder
int stream_pos; /* first byte not yet written to file */ int stream_pos; /* first byte not yet written to file */
uint32_t crc; uint32_t crc;
int outfd; /* output file descriptor */ int outfd; /* output file descriptor */
int member_version;
Bit_model bm_literal[1<<literal_context_bits][0x300]; Bit_model bm_literal[1<<literal_context_bits][0x300];
Bit_model bm_match[states][pos_states]; Bit_model bm_match[states][pos_states];
@ -314,7 +313,6 @@ static inline bool LZd_init( struct LZ_decoder * const decoder,
decoder->stream_pos = 0; decoder->stream_pos = 0;
decoder->crc = 0xFFFFFFFFU; decoder->crc = 0xFFFFFFFFU;
decoder->outfd = ofd; decoder->outfd = ofd;
decoder->member_version = Fh_version( header );
Bm_array_init( decoder->bm_literal[0], (1 << literal_context_bits) * 0x300 ); Bm_array_init( decoder->bm_literal[0], (1 << literal_context_bits) * 0x300 );
Bm_array_init( decoder->bm_match[0], states * pos_states ); Bm_array_init( decoder->bm_match[0], states * pos_states );

View file

@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
.TH LUNZIP "1" "June 2013" "Lunzip 1.3" "User Commands" .TH LUNZIP "1" "July 2013" "Lunzip 1.4-rc1" "User Commands"
.SH NAME .SH NAME
Lunzip \- small decompressor for lzip files Lunzip \- decompressor for lzip files
.SH SYNOPSIS .SH SYNOPSIS
.B lunzip .B lunzip
[\fIoptions\fR] [\fIfiles\fR] [\fIoptions\fR] [\fIfiles\fR]

15
lzip.h
View file

@ -118,12 +118,11 @@ struct Pretty_print
const char * name; const char * name;
const char * stdin_name; const char * stdin_name;
int longest_name; int longest_name;
int verbosity;
bool first_post; bool first_post;
}; };
void Pp_init( struct Pretty_print * const pp, const char * const filenames[], void Pp_init( struct Pretty_print * const pp, const char * const filenames[],
const int num_filenames, const int v ); const int num_filenames );
static inline void Pp_set_name( struct Pretty_print * const pp, static inline void Pp_set_name( struct Pretty_print * const pp,
const char * const filename ) const char * const filename )
@ -193,7 +192,7 @@ static inline uint8_t Fh_version( const File_header data )
{ return data[4]; } { return data[4]; }
static inline bool Fh_verify_version( const File_header data ) static inline bool Fh_verify_version( const File_header data )
{ return ( data[4] <= 1 ); } { return ( data[4] == 1 ); }
static inline unsigned Fh_get_dictionary_size( const File_header data ) static inline unsigned Fh_get_dictionary_size( const File_header data )
{ {
@ -203,15 +202,15 @@ static inline unsigned Fh_get_dictionary_size( const File_header data )
return sz; return sz;
} }
static inline bool Fh_set_dictionary_size( File_header data, const int sz ) static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz )
{ {
if( sz >= min_dictionary_size && sz <= max_dictionary_size ) if( sz >= min_dictionary_size && sz <= max_dictionary_size )
{ {
data[5] = real_bits( sz - 1 ); data[5] = real_bits( sz - 1 );
if( sz > min_dictionary_size ) if( sz > min_dictionary_size )
{ {
const int base_size = 1 << data[5]; const unsigned base_size = 1 << data[5];
const int wedge = base_size / 16; const unsigned wedge = base_size / 16;
int i; int i;
for( i = 7; i >= 1; --i ) for( i = 7; i >= 1; --i )
if( base_size - ( i * wedge ) >= sz ) if( base_size - ( i * wedge ) >= sz )
@ -230,9 +229,6 @@ typedef uint8_t File_trailer[20];
enum { Ft_size = 20 }; enum { Ft_size = 20 };
static inline int Ft_versioned_size( const int version )
{ return ( ( version >= 1 ) ? 20 : 12 ); }
static inline unsigned Ft_get_data_crc( const File_trailer data ) static inline unsigned Ft_get_data_crc( const File_trailer data )
{ {
unsigned tmp = 0; unsigned tmp = 0;
@ -277,5 +273,6 @@ static inline void Ft_set_member_size( File_trailer data, unsigned long long sz
/* defined in main.c */ /* defined in main.c */
extern int verbosity;
void cleanup_and_fail( const int retval ); void cleanup_and_fail( const int retval );
void show_error( const char * const msg, const int errcode, const bool help ); void show_error( const char * const msg, const int errcode, const bool help );

23
main.c
View file

@ -120,7 +120,7 @@ static void show_version( void )
} }
void show_header( const File_header header ) static void show_header( const File_header header )
{ {
const char * const prefix[8] = const char * const prefix[8] =
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
@ -133,8 +133,6 @@ void show_header( const File_header header )
for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false; { num /= factor; if( num % factor != 0 ) exact = false;
p = prefix[i]; np = ""; } p = prefix[i]; np = ""; }
if( verbosity >= 4 )
fprintf( stderr, "version %d, ", Fh_version( header ) );
fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p );
} }
@ -153,8 +151,8 @@ static int extension_index( const char * const name )
} }
static int open_instream( const char * const name, static int open_instream( const char * const name, struct stat * const in_statsp,
struct stat * const in_statsp, const bool to_stdout ) const bool testing, const bool to_stdout )
{ {
int infd = -1; int infd = -1;
infd = open( name, O_RDONLY | o_binary ); infd = open( name, O_RDONLY | o_binary );
@ -171,12 +169,13 @@ static int open_instream( const char * const name,
const bool can_read = ( i == 0 && const bool can_read = ( i == 0 &&
( S_ISBLK( mode ) || S_ISCHR( mode ) || ( S_ISBLK( mode ) || S_ISCHR( mode ) ||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
if( i != 0 || ( !S_ISREG( mode ) && ( !to_stdout || !can_read ) ) ) const bool no_ofile = to_stdout || testing;
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
program_name, name, program_name, name,
( can_read && !to_stdout ) ? ( can_read && !no_ofile ) ?
" and '--stdout' was not specified" : "" ); " and '--stdout' was not specified" : "" );
close( infd ); close( infd );
infd = -1; infd = -1;
@ -308,7 +307,8 @@ static int decompress( const int infd, struct Pretty_print * const pp,
if( Rd_finished( &rdec ) ) /* End Of File */ if( Rd_finished( &rdec ) ) /* End Of File */
{ {
if( first_member ) if( first_member )
{ Pp_show_msg( pp, "Error reading member header" ); retval = 1; } { Pp_show_msg( pp, "File ends unexpectedly at member header" );
retval = 2; }
break; break;
} }
if( !Fh_verify_magic( header ) ) if( !Fh_verify_magic( header ) )
@ -381,14 +381,13 @@ static void set_signals( void )
void Pp_init( struct Pretty_print * const pp, const char * const filenames[], void Pp_init( struct Pretty_print * const pp, const char * const filenames[],
const int num_filenames, const int v ) const int num_filenames )
{ {
unsigned stdin_name_len; unsigned stdin_name_len;
int i; int i;
pp->name = 0; pp->name = 0;
pp->stdin_name = "(stdin)"; pp->stdin_name = "(stdin)";
pp->longest_name = 0; pp->longest_name = 0;
pp->verbosity = v;
pp->first_post = false; pp->first_post = false;
stdin_name_len = strlen( pp->stdin_name ); stdin_name_len = strlen( pp->stdin_name );
@ -513,7 +512,7 @@ int main( const int argc, const char * const argv[] )
( filenames_given || default_output_filename[0] ) ) ( filenames_given || default_output_filename[0] ) )
set_signals(); set_signals();
Pp_init( &pp, filenames, num_filenames, verbosity ); Pp_init( &pp, filenames, num_filenames );
output_filename = resize_buffer( output_filename, 1 ); output_filename = resize_buffer( output_filename, 1 );
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
@ -549,7 +548,7 @@ int main( const int argc, const char * const argv[] )
else else
{ {
input_filename = filenames[i]; input_filename = filenames[i];
infd = open_instream( input_filename, &in_stats, to_stdout ); infd = open_instream( input_filename, &in_stats, testing, to_stdout );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
if( !testing ) if( !testing )
{ {

View file

@ -22,43 +22,53 @@ mkdir tmp
cd "${objdir}"/tmp cd "${objdir}"/tmp
cat "${testdir}"/test.txt > in || framework_failure cat "${testdir}"/test.txt > in || framework_failure
cat in in > in2 || framework_failure in_lz="${testdir}"/test.txt.lz
cat "${testdir}"/test.txt.lz > in.lz || framework_failure
cat in.lz in.lz > in2.lz || framework_failure
fail=0 fail=0
printf "testing lunzip-%s..." "$2" printf "testing lunzip-%s..." "$2"
"${LZIP}" -t "${testdir}"/test.txt.lz || fail=1 "${LZIP}" -tq in
"${LZIP}" -cd "${testdir}"/test.txt.lz > copy || fail=1 if [ $? = 2 ] ; then printf . ; else fail=1 ; printf - ; fi
"${LZIP}" -tq < in
if [ $? = 2 ] ; then printf . ; else fail=1 ; printf - ; fi
"${LZIP}" -cdq in
if [ $? = 2 ] ; then printf . ; else fail=1 ; printf - ; fi
"${LZIP}" -cdq < in
if [ $? = 2 ] ; then printf . ; else fail=1 ; printf - ; fi
dd if="${in_lz}" bs=1 count=6 2> /dev/null | "${LZIP}" -tq
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
dd if="${in_lz}" bs=1 count=20 2> /dev/null | "${LZIP}" -tq
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -t "${in_lz}" || fail=1
"${LZIP}" -cd "${in_lz}" > copy || fail=1
cmp in copy || fail=1 cmp in copy || fail=1
printf . printf .
"${LZIP}" -t in2.lz || fail=1
printf .
"${LZIP}" -cd in2.lz > copy2 || fail=1
cmp in2 copy2 || fail=1
printf .
cat in2.lz > copy2.lz || framework_failure
printf "garbage" >> copy2.lz || framework_failure
printf "to be overwritten" > copy2 || framework_failure
"${LZIP}" -t copy2.lz || fail=1
printf .
"${LZIP}" -dfk copy2.lz || fail=1
cmp in2 copy2 || fail=1
printf .
printf "to be overwritten" > copy || framework_failure printf "to be overwritten" > copy || framework_failure
"${LZIP}" -df -o copy < in.lz || fail=1 "${LZIP}" -df -o copy < "${in_lz}" || fail=1
cmp in copy || fail=1 cmp in copy || fail=1
printf . printf .
cat in.lz > anyothername || framework_failure cat "${in_lz}" > anyothername || framework_failure
"${LZIP}" -d anyothername || fail=1 "${LZIP}" -d anyothername || fail=1
cmp in anyothername.out || fail=1 cmp in anyothername.out || fail=1
printf . printf .
cat in in > in2 || framework_failure
cat "${in_lz}" "${in_lz}" > copy2.lz || framework_failure
"${LZIP}" -t copy2.lz || fail=1
printf .
"${LZIP}" -cd copy2.lz > copy2 || fail=1
cmp in2 copy2 || fail=1
printf .
printf "garbage" >> copy2.lz || framework_failure
printf "to be overwritten" > copy2 || framework_failure
"${LZIP}" -dfk copy2.lz || fail=1
cmp in2 copy2 || fail=1
printf .
echo echo
if [ ${fail} = 0 ] ; then if [ ${fail} = 0 ] ; then
echo "tests completed successfully." echo "tests completed successfully."