1
0
Fork 0

Merging upstream version 1.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 21:59:59 +01:00
parent 35b91aaaf0
commit 20b93ffd7c
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
15 changed files with 284 additions and 262 deletions

View file

@ -1,3 +1,13 @@
2012-02-26 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.1 released.
* main.c (decompress): Print only one status line for each
multi-member file when only one '-v' is specified.
* main.c (close_and_set_permissions): Inability to change output
file attributes has been downgraded from error to warning.
* Changed quote characters in messages as advised by GNU Standards.
* configure: 'datadir' renamed to 'datarootdir'.
2011-01-17 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.0 released.
@ -5,7 +15,7 @@
* Created from the decompression code of clzip 1.1.
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 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

24
INSTALL
View file

@ -18,7 +18,7 @@ This creates the directory ./lunzip[version] containing the source from
the main archive.
2. Change to lunzip directory and run configure.
(Try `configure --help' for usage instructions).
(Try 'configure --help' for usage instructions).
cd lunzip[version]
./configure
@ -27,30 +27,30 @@ the main archive.
make
4. Optionally, type `make check' to run the tests that come with lunzip.
4. Optionally, type 'make check' to run the tests that come with lunzip.
5. Type `make install' to install the program and any data files and
5. Type 'make install' to install the program and any data files and
documentation.
Another way
-----------
You can also compile lunzip into a separate directory. To do this, you
must use a version of `make' that supports the `VPATH' variable, such
as GNU `make'. `cd' to the directory where you want the 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.
must use a version of 'make' that supports the 'VPATH' variable, such
as GNU 'make'. 'cd' to the directory where you want the object files
and executables to go and run the 'configure' script. 'configure'
automatically checks for the source code in '.', in '..' and 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 sources. Usually 'configure' can determine that directory
automatically.
After running `configure', you can run `make' and `make install' as
After running 'configure', you can run 'make' and 'make install' as
explained above.
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy,
distribute and modify it.

View file

@ -16,10 +16,10 @@ objs = carg_parser.o decoder.o main.o
all : $(progname)
$(progname) : $(objs)
$(CC) $(LDFLAGS) -o $@ $^
$(CC) $(LDFLAGS) -o $@ $(objs)
$(progname)_profiled : $(objs)
$(CC) $(LDFLAGS) -pg -o $@ $^
$(CC) $(LDFLAGS) -pg -o $@ $(objs)
main.o : main.c
$(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $<
@ -92,6 +92,7 @@ dist : doc
$(DISTNAME)/doc/$(progname).1 \
$(DISTNAME)/testsuite/check.sh \
$(DISTNAME)/testsuite/test.txt \
$(DISTNAME)/testsuite/test_sync.lz \
$(DISTNAME)/testsuite/test_v[01].lz \
$(DISTNAME)/*.h \
$(DISTNAME)/*.c

14
NEWS
View file

@ -1,5 +1,13 @@
Changes in version 1.0:
Changes in version 1.1:
Initial release.
Print only one status line for each multimember file when only one "-v"
is specified.
Created from the decompression code of clzip 1.1.
Inability to change output file attributes has been downgraded from
error to warning.
Quote characters in messages have been changed as advised by GNU Coding
Standards.
Configure option "--datadir" has been renamed to "--datarootdir" to
follow GNU Standards.

5
README
View file

@ -5,6 +5,9 @@ small size makes it well suited for embedded devices or software
installers that need to decompress files but do not need compression
capabilities.
If you ever need to recover data from a damaged lzip file, try the
lziprecover program.
Lunzip replaces every file given in the command line with a decompressed
version of itself. Each decompressed file has the same modification
date, permissions, and, when possible, ownership as the corresponding
@ -32,7 +35,7 @@ few tens of KiB larger than the dictionary size used to compress that
file.
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy,
distribute and modify it.

View file

@ -1,5 +1,6 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
Antonio Diaz Diaz.
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -31,7 +32,7 @@
#include "carg_parser.h"
/* assure at least a minimum size for buffer `buf' */
/* assure at least a minimum size for buffer 'buf' */
static void * ap_resize_buffer( void * buf, const int min_size )
{
if( buf ) buf = realloc( buf, min_size );
@ -108,31 +109,31 @@ static char parse_long_option( struct Arg_parser * const ap,
if( ambig && !exact )
{
add_error( ap, "option `" ); add_error( ap, opt );
add_error( ap, "option '" ); add_error( ap, opt );
add_error( ap, "' is ambiguous" );
return 1;
}
if( index < 0 ) /* nothing found */
{
add_error( ap, "unrecognized option `" ); add_error( ap, opt );
add_error( ap, "unrecognized option '" ); add_error( ap, opt );
add_error( ap, "'" );
return 1;
}
++*argindp;
if( opt[len+2] ) /* `--<long_option>=<argument>' syntax */
if( opt[len+2] ) /* '--<long_option>=<argument>' syntax */
{
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].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].name );
add_error( ap, "' requires an argument" );
return 1;
}
@ -143,7 +144,7 @@ static char parse_long_option( struct Arg_parser * const ap,
{
if( !arg || !arg[0] )
{
add_error( ap, "option `--" ); add_error( ap, options[index].name );
add_error( ap, "option '--" ); add_error( ap, options[index].name );
add_error( ap, "' requires an argument" );
return 1;
}

View file

@ -1,5 +1,6 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
Antonio Diaz Diaz.
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -25,13 +26,13 @@
Public License.
*/
/* Arg_parser reads the arguments in `argv' and creates a number of
/* Arg_parser reads the arguments in 'argv' and creates a number of
option codes, option arguments and non-option arguments.
In case of error, `ap_error' returns a non-null pointer to an error
In case of error, 'ap_error' returns a non-null pointer to an error
message.
`options' is an array of `struct ap_Option' terminated by an element
'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.
@ -40,13 +41,13 @@
were specified before all the non-option arguments for the purposes
of parsing, even if the user of your program intermixed option and
non-option arguments. If you want the arguments in the exact order
the user typed them, call `ap_init' with `in_order' = true.
the user typed them, call 'ap_init' with 'in_order' = true.
The argument `--' terminates all options; any following arguments are
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 `-<short_option><argument>'
(without whitespace), or `--<long_option>=<argument>'.
The syntax for optional option arguments is '-<short_option><argument>'
(without whitespace), or '--<long_option>=<argument>'.
*/
#ifdef __cplusplus

60
configure vendored
View file

@ -1,6 +1,6 @@
#! /bin/sh
# configure script for Lunzip - Decompressor for lzip files
# Copyright (C) 2010, 2011 Antonio Diaz Diaz.
# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz.
#
# This configure script is free software: you have unlimited permission
# to copy, distribute and modify it.
@ -8,7 +8,7 @@
args=
no_create=
pkgname=lunzip
pkgversion=1.0
pkgversion=1.1
progname=lunzip
srctrigger=lunzip.h
@ -19,10 +19,9 @@ srcdir=
prefix=/usr/local
exec_prefix='$(prefix)'
bindir='$(exec_prefix)/bin'
datadir='$(prefix)/share'
infodir='$(datadir)/info'
mandir='$(datadir)/man'
sysconfdir='$(prefix)/etc'
datarootdir='$(prefix)/share'
infodir='$(datarootdir)/info'
mandir='$(datarootdir)/man'
CC=
CPPFLAGS=
CFLAGS='-Wall -W -O2'
@ -40,12 +39,12 @@ while [ -n "$1" ] ; do
# Split out the argument for options that take them
case ${option} in
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,'` ;;
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
esac
# Process the options
case ${option} in
--help | --he* | -h)
--help | -h)
echo "Usage: configure [options]"
echo
echo "Options: [defaults in brackets]"
@ -55,42 +54,31 @@ while [ -n "$1" ] ; do
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}]"
echo " --datadir=DIR base directory for doc and data [${datadir}]"
echo " --datarootdir=DIR base directory for doc and data [${datarootdir}]"
echo " --infodir=DIR info files directory [${infodir}]"
echo " --mandir=DIR man pages directory [${mandir}]"
echo " --sysconfdir=DIR read-only single-machine data directory [${sysconfdir}]"
echo " CC=COMPILER C compiler to use [gcc]"
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]"
echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]"
echo
exit 0 ;;
--version | --ve* | -V)
--version | -V)
echo "Configure script for ${pkgname} version ${pkgversion}"
exit 0 ;;
--srcdir* | --sr*)
srcdir=`echo ${optarg} | sed -e 's,/$,,'` ;;
--prefix* | --pr*)
prefix=`echo ${optarg} | sed -e 's,/$,,'` ;;
--exec-prefix* | --ex*)
exec_prefix=`echo ${optarg} | sed -e 's,/$,,'` ;;
--bindir* | --bi*)
bindir=`echo ${optarg} | sed -e 's,/$,,'` ;;
--datadir* | --da*)
datadir=`echo ${optarg} | sed -e 's,/$,,'` ;;
--infodir* | --inf*)
infodir=`echo ${optarg} | sed -e 's,/$,,'` ;;
--mandir* | --ma*)
mandir=`echo ${optarg} | sed -e 's,/$,,'` ;;
--sysconfdir* | --sy*)
sysconfdir=`echo ${optarg} | sed -e 's,/$,,'` ;;
--no-create | --no-c*)
no_create=yes ;;
--srcdir=*) srcdir=${optarg} ;;
--prefix=*) prefix=${optarg} ;;
--exec-prefix=*) exec_prefix=${optarg} ;;
--bindir=*) bindir=${optarg} ;;
--datarootdir=*) datarootdir=${optarg} ;;
--infodir=*) infodir=${optarg} ;;
--mandir=*) mandir=${optarg} ;;
--no-create) no_create=yes ;;
CC=*) CC=${optarg} ;;
CC=*) CC=${optarg} ;;
CPPFLAGS=*) CPPFLAGS=${optarg} ;;
CFLAGS=*) CFLAGS=${optarg} ;;
LDFLAGS=*) LDFLAGS=${optarg} ;;
CFLAGS=*) CFLAGS=${optarg} ;;
LDFLAGS=*) LDFLAGS=${optarg} ;;
--* | *=* | *-*-*) ;;
*)
@ -154,10 +142,9 @@ echo "VPATH = ${srcdir}"
echo "prefix = ${prefix}"
echo "exec_prefix = ${exec_prefix}"
echo "bindir = ${bindir}"
echo "datadir = ${datadir}"
echo "datarootdir = ${datarootdir}"
echo "infodir = ${infodir}"
echo "mandir = ${mandir}"
echo "sysconfdir = ${sysconfdir}"
echo "CC = ${CC}"
echo "CPPFLAGS = ${CPPFLAGS}"
echo "CFLAGS = ${CFLAGS}"
@ -165,7 +152,7 @@ echo "LDFLAGS = ${LDFLAGS}"
rm -f Makefile
cat > Makefile << EOF
# Makefile for Lunzip - Decompressor for lzip files
# Copyright (C) 2010, 2011 Antonio Diaz Diaz.
# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz.
# This file was generated automatically by configure. Do not edit.
#
# This Makefile is free software: you have unlimited permission
@ -178,10 +165,9 @@ VPATH = ${srcdir}
prefix = ${prefix}
exec_prefix = ${exec_prefix}
bindir = ${bindir}
datadir = ${datadir}
datarootdir = ${datarootdir}
infodir = ${infodir}
mandir = ${mandir}
sysconfdir = ${sysconfdir}
CC = ${CC}
CPPFLAGS = ${CPPFLAGS}
CFLAGS = ${CFLAGS}

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 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
@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "lunzip.h"
#include "decoder.h"
@ -30,6 +31,46 @@
CRC32 crc32;
/* Returns the number of bytes really read.
If (returned value < size) and (errno == 0), means EOF was reached.
*/
static int readblock( const int fd, uint8_t * const buf, const int size )
{
int rest = size;
while( true )
{
int n;
errno = 0;
if( rest <= 0 ) break;
n = read( fd, buf + size - rest, rest );
if( n > 0 ) rest -= n;
else if( n == 0 ) break;
else if( errno != EINTR && errno != EAGAIN ) break;
}
return ( rest > 0 ) ? size - rest : size;
}
/* Returns the number of bytes really written.
If (returned value < size), it is always an error.
*/
static int writeblock( const int fd, const uint8_t * const buf, const int size )
{
int rest = size;
while( true )
{
int n;
errno = 0;
if( rest <= 0 ) break;
n = write( fd, buf + size - rest, rest );
if( n > 0 ) rest -= n;
else if( n < 0 && errno != EINTR && errno != EAGAIN ) break;
}
return ( rest > 0 ) ? size - rest : size;
}
bool Rd_read_block( struct Range_decoder * const rdec )
{
if( !rdec->at_stream_end )
@ -50,10 +91,10 @@ void LZd_flush_data( struct LZ_decoder * const decoder )
const int size = decoder->pos - decoder->stream_pos;
if( size > 0 )
{
CRC32_update_buf( &decoder->crc_, decoder->buffer + decoder->stream_pos, size );
CRC32_update_buf( &decoder->crc, decoder->buffer + decoder->stream_pos, size );
if( decoder->outfd >= 0 &&
writeblock( decoder->outfd, decoder->buffer + decoder->stream_pos, size ) != size )
{ show_error( "write error", errno, false ); cleanup_and_fail( 1 ); }
{ show_error( "Write error", errno, false ); cleanup_and_fail( 1 ); }
if( decoder->pos >= decoder->buffer_size )
{ decoder->partial_data_pos += decoder->pos; decoder->pos = 0; }
decoder->stream_pos = decoder->pos;
@ -64,31 +105,26 @@ void LZd_flush_data( struct LZ_decoder * const decoder )
bool LZd_verify_trailer( struct LZ_decoder * const decoder,
struct Pretty_print * const pp )
{
int i;
File_trailer trailer;
const int trailer_size = Ft_versioned_size( decoder->member_version );
const long long member_size =
Rd_member_position( decoder->range_decoder ) + trailer_size;
bool error = false;
for( i = 0; i < trailer_size && !error; ++i )
int size = Rd_read_data( decoder->range_decoder, trailer, trailer_size );
if( size < trailer_size )
{
if( !Rd_finished( decoder->range_decoder ) )
trailer[i] = Rd_get_byte( decoder->range_decoder );
else
error = true;
if( pp->verbosity >= 0 )
{
error = true;
if( pp->verbosity >= 0 )
{
Pp_show_msg( pp, 0 );
fprintf( stderr, "Trailer truncated at trailer position %d;"
" some checks may fail.\n", i );
}
for( ; i < trailer_size; ++i ) trailer[i] = 0;
Pp_show_msg( pp, 0 );
fprintf( stderr, "Trailer truncated at trailer position %d;"
" some checks may fail.\n", size );
}
while( size < trailer_size ) trailer[size++] = 0;
}
if( decoder->member_version == 0 ) Ft_set_member_size( trailer, member_size );
if( !Rd_code_is_zero( decoder->range_decoder ) )
if( decoder->range_decoder->code != 0 )
{
error = true;
Pp_show_msg( pp, "Range decoder final code is not zero" );
@ -124,12 +160,12 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder,
Ft_get_member_size( trailer ), member_size, member_size );
}
}
if( !error && pp->verbosity >= 4 && LZd_data_position( decoder ) > 0 && member_size > 0 )
if( !error && pp->verbosity >= 3 && LZd_data_position( decoder ) > 0 && member_size > 0 )
fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
(double)LZd_data_position( decoder ) / member_size,
( 8.0 * member_size ) / LZd_data_position( decoder ),
100.0 * ( 1.0 - ( (double)member_size / LZd_data_position( decoder ) ) ) );
if( !error && pp->verbosity >= 3 )
if( !error && pp->verbosity >= 4 )
fprintf( stderr, "data CRC %08X, data size %9lld, member size %8lld. ",
(unsigned int)Ft_get_data_crc( trailer ),
Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) );
@ -149,11 +185,9 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
State state = 0;
Rd_load( decoder->range_decoder );
while( true )
while( !Rd_finished( decoder->range_decoder ) )
{
const int pos_state = LZd_data_position( decoder ) & pos_state_mask;
if( Rd_finished( decoder->range_decoder ) )
{ LZd_flush_data( decoder ); return 2; }
if( Rd_decode_bit( decoder->range_decoder, &decoder->bm_match[state][pos_state] ) == 0 )
{
const uint8_t prev_byte = LZd_get_prev_byte( decoder );
@ -230,7 +264,7 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
if( pp->verbosity >= 0 )
{
Pp_show_msg( pp, 0 );
fprintf( stderr, "Unsupported marker code `%d'.\n", len );
fprintf( stderr, "Unsupported marker code '%d'.\n", len );
}
return 4;
}
@ -245,4 +279,6 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
LZd_copy_block( decoder, rep0, len );
}
}
LZd_flush_data( decoder );
return 2;
}

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 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
@ -31,33 +31,27 @@ struct Range_decoder
bool Rd_read_block( struct Range_decoder * const rdec );
static inline void Rd_init( struct Range_decoder * const rdec, const int ifd )
static inline bool Rd_init( struct Range_decoder * const rdec, const int ifd )
{
rdec->partial_member_pos = 0;
rdec->buffer = (uint8_t *)malloc( rd_buffer_size );
if( !rdec->buffer )
{
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
cleanup_and_fail( 1 );
}
if( !rdec->buffer ) return false;
rdec->pos = 0;
rdec->stream_pos = 0;
rdec->code = 0;
rdec->range = 0xFFFFFFFFU;
rdec->infd = ifd;
rdec->at_stream_end = false;
return true;
}
static inline void Rd_free( struct Range_decoder * const rdec )
{ free( rdec->buffer ); rdec->buffer = 0; }
static inline bool Rd_code_is_zero( struct Range_decoder * const rdec )
{ return ( rdec->code == 0 ); }
{ free( rdec->buffer ); }
static inline bool Rd_finished( struct Range_decoder * const rdec )
{ return rdec->pos >= rdec->stream_pos && !Rd_read_block( rdec ); }
static inline long long Rd_member_position( struct Range_decoder * const rdec )
static inline long long Rd_member_position( const struct Range_decoder * const rdec )
{ return rdec->partial_member_pos + rdec->pos; }
static inline void Rd_reset_member_position( struct Range_decoder * const rdec )
@ -65,10 +59,24 @@ static inline void Rd_reset_member_position( struct Range_decoder * const rdec )
static inline uint8_t Rd_get_byte( struct Range_decoder * const rdec )
{
if( Rd_finished( rdec ) ) return 0;
if( Rd_finished( rdec ) ) return 0x55; /* make code != 0 */
return rdec->buffer[rdec->pos++];
}
static inline int Rd_read_data( struct Range_decoder * const rdec,
uint8_t * const outbuf, const int size )
{
int rest = size;
while( rest > 0 && !Rd_finished( rdec ) )
{
const int rd = min( rest, rdec->stream_pos - rdec->pos );
memcpy( outbuf + size - rest, rdec->buffer + rdec->pos, rd );
rdec->pos += rd;
rest -= rd;
}
return ( rest > 0 ) ? size - rest : size;
}
static inline void Rd_load( struct Range_decoder * const rdec )
{
int i;
@ -223,27 +231,27 @@ struct Literal_decoder
Bit_model bm_literal[1<<literal_context_bits][0x300];
};
static inline void Lid_init( struct Literal_decoder * const literal_decoder )
static inline void Lid_init( struct Literal_decoder * const lidec )
{
int i, j;
for( i = 0; i < 1<<literal_context_bits; ++i )
for( j = 0; j < 0x300; ++j )
Bm_init( &literal_decoder->bm_literal[i][j] );
Bm_init( &lidec->bm_literal[i][j] );
}
static inline int Lid_state( const int prev_byte )
static inline int Lid_state( const uint8_t prev_byte )
{ return ( prev_byte >> ( 8 - literal_context_bits ) ); }
static inline uint8_t Lid_decode( struct Literal_decoder * const literal_decoder,
static inline uint8_t Lid_decode( struct Literal_decoder * const lidec,
struct Range_decoder * const rdec,
const uint8_t prev_byte )
{ return Rd_decode_tree( rdec, literal_decoder->bm_literal[Lid_state(prev_byte)], 8 ); }
{ return Rd_decode_tree( rdec, lidec->bm_literal[Lid_state(prev_byte)], 8 ); }
static inline uint8_t Lid_decode_matched( struct Literal_decoder * const literal_decoder,
static inline uint8_t Lid_decode_matched( struct Literal_decoder * const lidec,
struct Range_decoder * const rdec,
const uint8_t prev_byte,
const uint8_t match_byte )
{ return Rd_decode_matched( rdec, literal_decoder->bm_literal[Lid_state(prev_byte)], match_byte ); }
{ return Rd_decode_matched( rdec, lidec->bm_literal[Lid_state(prev_byte)], match_byte ); }
struct LZ_decoder
@ -254,7 +262,7 @@ struct LZ_decoder
uint8_t * buffer; /* output buffer */
int pos; /* current pos in buffer */
int stream_pos; /* first byte not yet written to file */
uint32_t crc_;
uint32_t crc;
int outfd; /* output file descriptor */
int member_version;
@ -279,14 +287,14 @@ void LZd_flush_data( struct LZ_decoder * const decoder );
bool LZd_verify_trailer( struct LZ_decoder * const decoder,
struct Pretty_print * const pp );
static inline uint8_t LZd_get_prev_byte( struct LZ_decoder * const decoder )
{
const int i =
( ( decoder->pos > 0 ) ? decoder->pos : decoder->buffer_size ) - 1;
return decoder->buffer[i];
}
static inline uint8_t LZd_get_prev_byte( const struct LZ_decoder * const decoder )
{
const int i =
( ( decoder->pos > 0 ) ? decoder->pos : decoder->buffer_size ) - 1;
return decoder->buffer[i];
}
static inline uint8_t LZd_get_byte( struct LZ_decoder * const decoder,
static inline uint8_t LZd_get_byte( const struct LZ_decoder * const decoder,
const int distance )
{
int i = decoder->pos - distance - 1;
@ -320,7 +328,7 @@ static inline void LZd_copy_block( struct LZ_decoder * const decoder,
}
}
static inline void LZd_init( struct LZ_decoder * const decoder,
static inline bool LZd_init( struct LZ_decoder * const decoder,
const File_header header,
struct Range_decoder * const rdec, const int ofd )
{
@ -329,14 +337,10 @@ static inline void LZd_init( struct LZ_decoder * const decoder,
decoder->dictionary_size = Fh_get_dictionary_size( header );
decoder->buffer_size = max( 65536, decoder->dictionary_size );
decoder->buffer = (uint8_t *)malloc( decoder->buffer_size );
if( !decoder->buffer )
{
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
cleanup_and_fail( 1 );
}
if( !decoder->buffer ) return false;
decoder->pos = 0;
decoder->stream_pos = 0;
decoder->crc_ = 0xFFFFFFFFU;
decoder->crc = 0xFFFFFFFFU;
decoder->outfd = ofd;
decoder->member_version = Fh_version( header );
@ -365,15 +369,16 @@ static inline void LZd_init( struct LZ_decoder * const decoder,
Led_init( &decoder->rep_match_len_decoder );
Lid_init( &decoder->literal_decoder );
decoder->buffer[decoder->buffer_size-1] = 0; /* prev_byte of first_byte */
return true;
}
static inline void LZd_free( struct LZ_decoder * const decoder )
{ free( decoder->buffer ); decoder->buffer = 0; }
{ free( decoder->buffer ); }
static inline uint32_t LZd_crc( struct LZ_decoder * const decoder )
{ return decoder->crc_ ^ 0xFFFFFFFFU; }
static inline uint32_t LZd_crc( const struct LZ_decoder * const decoder )
{ return decoder->crc ^ 0xFFFFFFFFU; }
static inline long long LZd_data_position( struct LZ_decoder * const decoder )
static inline long long LZd_data_position( const struct LZ_decoder * const decoder )
{ return decoder->partial_data_pos + decoder->pos; }
int LZd_decode_member( struct LZ_decoder * const decoder,

View file

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
.TH LUNZIP "1" "January 2011" "Lunzip 1.0" "User Commands"
.TH LUNZIP "1" "February 2012" "Lunzip 1.1" "User Commands"
.SH NAME
Lunzip \- small decompressor for lzip files
.SH SYNOPSIS
@ -46,7 +46,7 @@ Report bugs to lzip\-bug@nongnu.org
.br
Lunzip home page: http://www.nongnu.org/lzip/lunzip.html
.SH COPYRIGHT
Copyright \(co 2011 Antonio Diaz Diaz.
Copyright \(co 2012 Antonio Diaz Diaz.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
.br
This is free software: you are free to change and redistribute it.

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 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
@ -56,6 +56,7 @@ static inline void St_set_short_rep( State * const st )
*st = next[*st];
}
enum {
min_dictionary_bits = 12,
min_dictionary_size = 1 << min_dictionary_bits,
@ -107,7 +108,7 @@ static inline void Bm_init( Bit_model * const probability )
struct Pretty_print
{
const char * name_;
const char * name;
const char * stdin_name;
int longest_name;
int verbosity;
@ -121,13 +122,13 @@ static inline void Pp_set_name( struct Pretty_print * const pp,
const char * const filename )
{
if( filename && filename[0] && strcmp( filename, "-" ) )
pp->name_ = filename;
else pp->name_ = pp->stdin_name;
pp->name = filename;
else pp->name = pp->stdin_name;
pp->first_post = true;
}
static inline void Pp_reset( struct Pretty_print * const pp )
{ if( pp->name_ && pp->name_[0] ) pp->first_post = true; }
{ if( pp->name && pp->name[0] ) pp->first_post = true; }
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg );
@ -159,11 +160,11 @@ static inline void CRC32_update_buf( uint32_t * crc, const uint8_t * const buffe
}
static inline int real_bits( const int value )
static inline int real_bits( const unsigned int value )
{
int bits = 0, i, mask;
for( i = 1, mask = 1; mask > 0; ++i, mask <<= 1 )
if( value & mask ) bits = i;
int bits = 0, i = 1;
unsigned int mask = 1;
for( ; mask > 0; ++i, mask <<= 1 ) if( value & mask ) bits = i;
return bits;
}
@ -172,19 +173,14 @@ static const uint8_t magic_string[4] = { 'L', 'Z', 'I', 'P' };
typedef uint8_t File_header[6]; /* 0-3 magic bytes */
/* 4 version */
/* 5 coded_dict_size; */
/* 5 coded_dict_size */
enum { Fh_size = 6 };
static inline void Fh_set_magic( File_header data )
{
memcpy( data, magic_string, 4 );
data[4] = 1;
}
{ memcpy( data, magic_string, 4 ); data[4] = 1; }
static inline bool Fh_verify_magic( const File_header data )
{
return ( memcmp( data, magic_string, 4 ) == 0 );
}
{ return ( memcmp( data, magic_string, 4 ) == 0 ); }
static inline uint8_t Fh_version( const File_header data )
{ return data[4]; }
@ -276,5 +272,3 @@ static inline void Ft_set_member_size( File_trailer data, long long sz )
/* defined in main.c */
void cleanup_and_fail( const int retval );
void show_error( const char * const msg, const int errcode, const bool help );
int readblock( const int fd, uint8_t * const buf, const int size );
int writeblock( const int fd, const uint8_t * const buf, const int size );

175
main.c
View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
Copyright (C) 2010, 2011, 2012 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
@ -24,14 +24,14 @@
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <utime.h>
#include <sys/stat.h>
@ -63,7 +63,7 @@ long long int llabs( long long int number );
const char * const Program_name = "Lunzip";
const char * const program_name = "lunzip";
const char * const program_year = "2011";
const char * const program_year = "2012";
const char * invocation_name = 0;
#ifdef O_BINARY
@ -80,11 +80,13 @@ struct { const char * from; const char * to; } const known_extensions[] = {
char * output_filename = 0;
int outfd = -1;
int verbosity = 0;
const mode_t usr_rw = S_IRUSR | S_IWUSR;
const mode_t all_rw = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
mode_t outfd_mode = S_IRUSR | S_IWUSR;
bool delete_output_on_interrupt = false;
/* assure at least a minimum size for buffer `buf' */
/* assure at least a minimum size for buffer 'buf' */
static void * resize_buffer( void * buf, const int min_size )
{
if( buf ) buf = realloc( buf, min_size );
@ -102,21 +104,21 @@ static void show_help()
{
printf( "%s - Decompressor for lzip files.\n", Program_name );
printf( "\nUsage: %s [options] [files]\n", invocation_name );
printf( "\nOptions:\n" );
printf( " -h, --help display this help and exit\n" );
printf( " -V, --version output version information and exit\n" );
printf( " -c, --stdout send output to standard output\n" );
printf( " -d, --decompress decompress (this is the default)\n" );
printf( " -f, --force overwrite existing output files\n" );
printf( " -k, --keep keep (don't delete) input files\n" );
printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
printf( " -q, --quiet suppress all messages\n" );
printf( " -t, --test test compressed file integrity\n" );
printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" );
printf( "If no file names are given, %s decompresses from standard input to\n", program_name );
printf( "standard output.\n" );
printf( "\nReport bugs to lzip-bug@nongnu.org\n" );
printf( "Lunzip home page: http://www.nongnu.org/lzip/lunzip.html\n" );
printf( "\nOptions:\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" -c, --stdout send output to standard output\n"
" -d, --decompress decompress (this is the default)\n"
" -f, --force overwrite existing output files\n"
" -k, --keep keep (don't delete) input files\n"
" -o, --output=<file> if reading stdin, place the output into <file>\n"
" -q, --quiet suppress all messages\n"
" -t, --test test compressed file integrity\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n"
"If no file names are given, lunzip decompresses from standard input to\n"
"standard output.\n"
"\nReport bugs to lzip-bug@nongnu.org\n"
"Lunzip home page: http://www.nongnu.org/lzip/lunzip.html\n" );
}
@ -124,9 +126,9 @@ static void show_version()
{
printf( "%s %s\n", Program_name, PROGVERSION );
printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n" );
printf( "This is free software: you are free to change and redistribute it.\n" );
printf( "There is NO WARRANTY, to the extent permitted by law.\n" );
printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n" );
}
@ -137,11 +139,12 @@ static const char * format_num( long long num )
enum { buf_size = 16, factor = 1024 };
static char buf[buf_size];
const char *p = "";
bool exact = ( num % factor == 0 );
int i;
for( i = 0; i < 8 && ( llabs( num ) > 9999 ||
( llabs( num ) >= factor && num % factor == 0 ) ); ++i )
{ num /= factor; p = prefix[i]; }
( exact && llabs( num ) >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; }
snprintf( buf, buf_size, "%lld %s", num, p );
return buf;
}
@ -155,7 +158,7 @@ static int open_instream( const char * const name,
if( infd < 0 )
{
if( verbosity >= 0 )
fprintf( stderr, "%s: Can't open input file `%s': %s.\n",
fprintf( stderr, "%s: Can't open input file '%s': %s.\n",
program_name, name, strerror( errno ) );
}
else
@ -168,10 +171,10 @@ static int open_instream( const char * const name,
if( i != 0 || ( !S_ISREG( mode ) && ( !to_stdout || !can_read ) ) )
{
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,
( can_read && !to_stdout ) ?
" and `--stdout' was not specified" : "" );
" and '--stdout' was not specified" : "" );
close( infd );
infd = -1;
}
@ -213,8 +216,8 @@ static void set_d_outname( const char * const name )
output_filename = resize_buffer( output_filename, strlen( name ) + 4 + 1 );
strcpy( output_filename, name );
strcat( output_filename, ".out" );
if( verbosity >= 0 )
fprintf( stderr, "%s: Can't guess original name for `%s' -- using `%s'.\n",
if( verbosity >= 1 )
fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n",
program_name, name, output_filename );
}
@ -228,10 +231,10 @@ static bool open_outstream( const bool force )
if( outfd < 0 && verbosity >= 0 )
{
if( errno == EEXIST )
fprintf( stderr, "%s: Output file %s already exists, skipping.\n",
fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
program_name, output_filename );
else
fprintf( stderr, "%s: Can't create output file `%s': %s.\n",
fprintf( stderr, "%s: Can't create output file '%s': %s.\n",
program_name, output_filename, strerror( errno ) );
}
return ( outfd >= 0 );
@ -244,10 +247,10 @@ void cleanup_and_fail( const int retval )
{
delete_output_on_interrupt = false;
if( verbosity >= 0 )
fprintf( stderr, "%s: Deleting output file `%s', if it exists.\n",
fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n",
program_name, output_filename );
if( outfd >= 0 ) { close( outfd ); outfd = -1; }
if( remove( output_filename ) != 0 )
if( remove( output_filename ) != 0 && errno != ENOENT )
show_error( "WARNING: deletion of output file (apparently) failed.", 0, false );
}
exit( retval );
@ -257,31 +260,26 @@ void cleanup_and_fail( const int retval )
/* Set permissions, owner and times. */
static void close_and_set_permissions( const struct stat * const in_statsp )
{
bool error = false;
bool warning = false;
if( in_statsp )
{
/* fchown will in many cases return with EPERM, which can be safely ignored. */
if( ( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) != 0 &&
errno != EPERM ) ||
fchmod( outfd, in_statsp->st_mode ) != 0 )
error = true;
/* fchown will in many cases return with EPERM, which can be safely ignored. */
fchmod( outfd, in_statsp->st_mode ) != 0 ) warning = true;
}
if( close( outfd ) == 0 ) outfd = -1;
else cleanup_and_fail( 1 );
if( close( outfd ) != 0 ) cleanup_and_fail( 1 );
outfd = -1;
delete_output_on_interrupt = false;
if( !in_statsp ) return;
if( !error )
if( in_statsp )
{
struct utimbuf t;
t.actime = in_statsp->st_atime;
t.modtime = in_statsp->st_mtime;
if( utime( output_filename, &t ) != 0 ) error = true;
if( utime( output_filename, &t ) != 0 ) warning = true;
}
if( error )
{
if( warning && verbosity >= 1 )
show_error( "Can't change output file attributes.", 0, false );
cleanup_and_fail( 1 );
}
}
@ -290,17 +288,20 @@ static int decompress( const int infd, struct Pretty_print * const pp,
{
long long partial_file_pos = 0;
struct Range_decoder rdec;
int retval = 0, i, result;
int retval = 0, result;
bool first_member;
Rd_init( &rdec, infd );
if( !Rd_init( &rdec, infd ) )
{
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
cleanup_and_fail( 1 );
}
for( first_member = true; ; first_member = false, Pp_reset( pp ) )
{
File_header header;
struct LZ_decoder decoder;
Rd_reset_member_position( &rdec );
for( i = 0; i < Fh_size; ++i )
header[i] = Rd_get_byte( &rdec );
Rd_read_data( &rdec, header, Fh_size );
if( Rd_finished( &rdec ) ) /* End Of File */
{
if( first_member )
@ -326,7 +327,7 @@ static int decompress( const int infd, struct Pretty_print * const pp,
{ Pp_show_msg( pp, "Invalid dictionary size in member header" );
retval = 2; break; }
if( verbosity >= 1 )
if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
{
Pp_show_msg( pp, 0 );
if( verbosity >= 2 )
@ -334,8 +335,12 @@ static int decompress( const int infd, struct Pretty_print * const pp,
Fh_version( header ),
format_num( Fh_get_dictionary_size( header ) ) );
}
LZd_init( &decoder, header, &rdec, outfd );
if( !LZd_init( &decoder, header, &rdec, outfd ) )
{
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
cleanup_and_fail( 1 );
}
result = LZd_decode_member( &decoder, pp );
partial_file_pos += Rd_member_position( &rdec );
LZd_free( &decoder );
@ -352,11 +357,14 @@ static int decompress( const int infd, struct Pretty_print * const pp,
}
retval = 2; break;
}
if( verbosity >= 1 )
if( verbosity >= 2 )
{ if( testing ) fprintf( stderr, "ok\n" );
else fprintf( stderr, "done\n" ); }
}
Rd_free( &rdec );
if( verbosity == 1 && retval == 0 )
{ if( testing ) fprintf( stderr, "ok\n" );
else fprintf( stderr, "done\n" ); }
return retval;
}
@ -382,7 +390,7 @@ void Pp_init( struct Pretty_print * const pp, const char * const filenames[],
{
unsigned int stdin_name_len;
int i;
pp->name_ = 0;
pp->name = 0;
pp->stdin_name = "(stdin)";
pp->longest_name = 0;
pp->verbosity = v;
@ -407,8 +415,8 @@ void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
{
int i, len;
pp->first_post = false;
fprintf( stderr, " %s: ", pp->name_ );
len = pp->longest_name - strlen( pp->name_ );
fprintf( stderr, " %s: ", pp->name );
len = pp->longest_name - strlen( pp->name );
for( i = 0; i < len; ++i ) fprintf( stderr, " " );
if( !msg ) fflush( stderr );
}
@ -428,7 +436,7 @@ void show_error( const char * const msg, const int errcode, const bool help )
fprintf( stderr, "\n" );
}
if( help && invocation_name && invocation_name[0] )
fprintf( stderr, "Try `%s --help' for more information.\n",
fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name );
}
}
@ -442,45 +450,6 @@ void internal_error( const char * const msg )
}
/* Returns the number of bytes really read.
If (returned value < size) and (errno == 0), means EOF was reached.
*/
int readblock( const int fd, uint8_t * const buf, const int size )
{
int rest = size;
while( true )
{
int n;
errno = 0;
if( rest <= 0 ) break;
n = read( fd, buf + size - rest, rest );
if( n > 0 ) rest -= n;
else if( n == 0 ) break;
else if( errno != EINTR && errno != EAGAIN ) break;
}
return ( rest > 0 ) ? size - rest : size;
}
/* Returns the number of bytes really written.
If (returned value < size), it is always an error.
*/
int writeblock( const int fd, const uint8_t * const buf, const int size )
{
int rest = size;
while( true )
{
int n;
errno = 0;
if( rest <= 0 ) break;
n = write( fd, buf + size - rest, rest );
if( n > 0 ) rest -= n;
else if( errno && errno != EINTR && errno != EAGAIN ) break;
}
return ( rest > 0 ) ? size - rest : size;
}
int main( const int argc, const char * const argv[] )
{
const char * input_filename = "";
@ -516,6 +485,7 @@ int main( const int argc, const char * const argv[] )
invocation_name = argv[0];
CRC32_init();
if( !ap_init( &parser, argc, argv, options, 0 ) )
{ show_error( "Memory exhausted.", 0, false ); return 1; }
if( ap_error( &parser ) ) /* bad option */
@ -547,6 +517,9 @@ int main( const int argc, const char * const argv[] )
_fsetmode( stdout, "b" );
#endif
if( testing )
outfd = -1;
for( ; argind < ap_arguments( &parser ); ++argind )
{
if( strcmp( ap_argument( &parser, argind ), "-" ) )
@ -567,8 +540,6 @@ int main( const int argc, const char * const argv[] )
set_signals();
Pp_init( &pp, filenames, num_filenames, verbosity );
if( testing )
outfd = -1;
output_filename = resize_buffer( output_filename, 1 );
for( i = 0; i < num_filenames; ++i )
@ -591,7 +562,7 @@ int main( const int argc, const char * const argv[] )
output_filename = resize_buffer( output_filename,
strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename );
outfd_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
outfd_mode = all_rw;
if( !open_outstream( force ) )
{
if( outfd == -1 && retval < 1 ) retval = 1;
@ -612,7 +583,7 @@ int main( const int argc, const char * const argv[] )
else
{
set_d_outname( input_filename );
outfd_mode = S_IRUSR | S_IWUSR;
outfd_mode = usr_rw;
if( !open_outstream( force ) )
{
if( outfd == -1 && retval < 1 ) retval = 1;

View file

@ -1,6 +1,6 @@
#! /bin/sh
# check script for Lunzip - Decompressor for lzip files
# Copyright (C) 2010, 2011 Antonio Diaz Diaz.
# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz.
#
# This script is free software: you have unlimited permission
# to copy, distribute and modify it.
@ -19,7 +19,6 @@ fi
if [ -d tmp ] ; then rm -rf tmp ; fi
mkdir tmp
printf "testing lunzip-%s..." "$2"
cd "${objdir}"/tmp
cat "${testdir}"/test.txt > in || framework_failure
@ -28,6 +27,8 @@ cat "${testdir}"/test_v1.lz > in.lz || framework_failure
cat in.lz in.lz > in2.lz || framework_failure
fail=0
printf "testing lunzip-%s..." "$2"
"${LZIP}" -t "${testdir}"/test_v0.lz || fail=1
printf .
"${LZIP}" -cd "${testdir}"/test_v0.lz > copy || fail=1
@ -40,6 +41,12 @@ printf .
cmp in copy || fail=1
printf .
"${LZIP}" -t "${testdir}"/test_sync.lz || fail=1
printf .
"${LZIP}" -cd "${testdir}"/test_sync.lz > copy || fail=1
cmp in copy || fail=1
printf .
"${LZIP}" -t in2.lz || fail=1
printf .
"${LZIP}" -cd in2.lz > copy2 || fail=1
@ -55,14 +62,13 @@ printf .
cmp in2 copy2 || fail=1
printf .
cat in.lz > out.lz || framework_failure
printf "to be overwritten" > copy || framework_failure
"${LZIP}" -df -o copy < out.lz || fail=1
"${LZIP}" -df -o copy < in.lz || fail=1
cmp in copy || fail=1
printf .
cat in.lz > anyothername || framework_failure
"${LZIP}" -q anyothername || fail=1
"${LZIP}" -d anyothername || fail=1
cmp in anyothername.out || fail=1
printf .

BIN
testsuite/test_sync.lz Normal file

Binary file not shown.