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> 2011-01-17 Antonio Diaz Diaz <ant_diaz@teleline.es>
* Version 1.0 released. * Version 1.0 released.
@ -5,7 +15,7 @@
* Created from the decompression code of clzip 1.1. * 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, 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 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. the main archive.
2. Change to lunzip directory and run configure. 2. Change to lunzip directory and run configure.
(Try `configure --help' for usage instructions). (Try 'configure --help' for usage instructions).
cd lunzip[version] cd lunzip[version]
./configure ./configure
@ -27,30 +27,30 @@ the main archive.
make 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. documentation.
Another way Another way
----------- -----------
You can also compile lunzip into a separate directory. To do this, you 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 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 as GNU 'make'. 'cd' to the directory where you want the object files
and executables to go and run the `configure' script. `configure' and executables to go and run the 'configure' script. 'configure'
automatically checks for the source code in `.', in `..' and in the automatically checks for the source code in '.', in '..' and in the
directory that `configure' is in. directory that 'configure' is in.
`configure' recognizes the option `--srcdir=DIR' to control where to 'configure' recognizes the option '--srcdir=DIR' to control where to
look for the sources. Usually `configure' can determine that directory look for the sources. Usually 'configure' can determine that directory
automatically. 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. 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, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute and modify it.

View file

@ -16,10 +16,10 @@ objs = carg_parser.o decoder.o main.o
all : $(progname) all : $(progname)
$(progname) : $(objs) $(progname) : $(objs)
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $(objs)
$(progname)_profiled : $(objs) $(progname)_profiled : $(objs)
$(CC) $(LDFLAGS) -pg -o $@ $^ $(CC) $(LDFLAGS) -pg -o $@ $(objs)
main.o : main.c main.o : main.c
$(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< $(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $<
@ -92,6 +92,7 @@ dist : doc
$(DISTNAME)/doc/$(progname).1 \ $(DISTNAME)/doc/$(progname).1 \
$(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/check.sh \
$(DISTNAME)/testsuite/test.txt \ $(DISTNAME)/testsuite/test.txt \
$(DISTNAME)/testsuite/test_sync.lz \
$(DISTNAME)/testsuite/test_v[01].lz \ $(DISTNAME)/testsuite/test_v[01].lz \
$(DISTNAME)/*.h \ $(DISTNAME)/*.h \
$(DISTNAME)/*.c $(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 installers that need to decompress files but do not need compression
capabilities. 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 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
@ -32,7 +35,7 @@ few tens of KiB larger than the dictionary size used to compress that
file. 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, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute and modify it.

View file

@ -1,5 +1,6 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* 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 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 it under the terms of the GNU General Public License as published by
@ -31,7 +32,7 @@
#include "carg_parser.h" #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 ) static void * ap_resize_buffer( void * buf, const int min_size )
{ {
if( buf ) buf = realloc( buf, 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 ) if( ambig && !exact )
{ {
add_error( ap, "option `" ); add_error( ap, opt ); add_error( ap, "option '" ); add_error( ap, opt );
add_error( ap, "' is ambiguous" ); add_error( ap, "' is ambiguous" );
return 1; return 1;
} }
if( index < 0 ) /* nothing found */ 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, "'" ); add_error( ap, "'" );
return 1; return 1;
} }
++*argindp; ++*argindp;
if( opt[len+2] ) /* `--<long_option>=<argument>' syntax */ if( opt[len+2] ) /* '--<long_option>=<argument>' syntax */
{ {
if( options[index].has_arg == ap_no ) 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" ); add_error( ap, "' doesn't allow an argument" );
return 1; return 1;
} }
if( options[index].has_arg == ap_yes && !opt[len+3] ) 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" ); add_error( ap, "' requires an argument" );
return 1; return 1;
} }
@ -143,7 +144,7 @@ static char parse_long_option( struct Arg_parser * const ap,
{ {
if( !arg || !arg[0] ) 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" ); add_error( ap, "' requires an argument" );
return 1; return 1;
} }

View file

@ -1,5 +1,6 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* 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 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 it under the terms of the GNU General Public License as published by
@ -25,13 +26,13 @@
Public License. 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. 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. 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 containing a code which is zero. A null name means a short-only
option. A code value outside the unsigned char range means a option. A code value outside the unsigned char range means a
long-only option. long-only option.
@ -40,13 +41,13 @@
were specified before all the non-option arguments for the purposes were specified before all the non-option arguments for the purposes
of parsing, even if the user of your program intermixed option and of parsing, even if the user of your program intermixed option and
non-option arguments. If you want the arguments in the exact order 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. treated as non-option arguments, even if they begin with a hyphen.
The syntax for optional option arguments is `-<short_option><argument>' The syntax for optional option arguments is '-<short_option><argument>'
(without whitespace), or `--<long_option>=<argument>'. (without whitespace), or '--<long_option>=<argument>'.
*/ */
#ifdef __cplusplus #ifdef __cplusplus

60
configure vendored
View file

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

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files /* 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 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 it under the terms of the GNU General Public License as published by
@ -23,6 +23,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "lunzip.h" #include "lunzip.h"
#include "decoder.h" #include "decoder.h"
@ -30,6 +31,46 @@
CRC32 crc32; 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 ) bool Rd_read_block( struct Range_decoder * const rdec )
{ {
if( !rdec->at_stream_end ) 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; const int size = decoder->pos - decoder->stream_pos;
if( size > 0 ) 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 && if( decoder->outfd >= 0 &&
writeblock( decoder->outfd, decoder->buffer + decoder->stream_pos, size ) != size ) 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 ) if( decoder->pos >= decoder->buffer_size )
{ decoder->partial_data_pos += decoder->pos; decoder->pos = 0; } { decoder->partial_data_pos += decoder->pos; decoder->pos = 0; }
decoder->stream_pos = decoder->pos; 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, bool LZd_verify_trailer( struct LZ_decoder * const decoder,
struct Pretty_print * const pp ) struct Pretty_print * const pp )
{ {
int i;
File_trailer trailer; File_trailer trailer;
const int trailer_size = Ft_versioned_size( decoder->member_version ); const int trailer_size = Ft_versioned_size( decoder->member_version );
const long long member_size = const long long member_size =
Rd_member_position( decoder->range_decoder ) + trailer_size; Rd_member_position( decoder->range_decoder ) + trailer_size;
bool error = false; 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 ) ) error = true;
trailer[i] = Rd_get_byte( decoder->range_decoder ); if( pp->verbosity >= 0 )
else
{ {
error = true; Pp_show_msg( pp, 0 );
if( pp->verbosity >= 0 ) fprintf( stderr, "Trailer truncated at trailer position %d;"
{ " some checks may fail.\n", size );
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;
} }
while( size < trailer_size ) trailer[size++] = 0;
} }
if( decoder->member_version == 0 ) Ft_set_member_size( trailer, member_size ); 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; error = true;
Pp_show_msg( pp, "Range decoder final code is not zero" ); 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 ); 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. ", 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 >= 3 ) if( !error && pp->verbosity >= 4 )
fprintf( stderr, "data CRC %08X, data size %9lld, member size %8lld. ", fprintf( stderr, "data CRC %08X, data size %9lld, member size %8lld. ",
(unsigned int)Ft_get_data_crc( trailer ), (unsigned int)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 ) );
@ -149,11 +185,9 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
State state = 0; State state = 0;
Rd_load( decoder->range_decoder ); Rd_load( decoder->range_decoder );
while( true ) while( !Rd_finished( decoder->range_decoder ) )
{ {
const int pos_state = LZd_data_position( decoder ) & pos_state_mask; 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 ) if( Rd_decode_bit( decoder->range_decoder, &decoder->bm_match[state][pos_state] ) == 0 )
{ {
const uint8_t prev_byte = LZd_get_prev_byte( decoder ); 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 ) if( pp->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 );
} }
return 4; return 4;
} }
@ -245,4 +279,6 @@ int LZd_decode_member( struct LZ_decoder * const decoder,
LZd_copy_block( decoder, rep0, len ); LZd_copy_block( decoder, rep0, len );
} }
} }
LZd_flush_data( decoder );
return 2;
} }

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files /* 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 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 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 ); 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->partial_member_pos = 0;
rdec->buffer = (uint8_t *)malloc( rd_buffer_size ); rdec->buffer = (uint8_t *)malloc( rd_buffer_size );
if( !rdec->buffer ) if( !rdec->buffer ) return false;
{
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
cleanup_and_fail( 1 );
}
rdec->pos = 0; rdec->pos = 0;
rdec->stream_pos = 0; rdec->stream_pos = 0;
rdec->code = 0; rdec->code = 0;
rdec->range = 0xFFFFFFFFU; rdec->range = 0xFFFFFFFFU;
rdec->infd = ifd; rdec->infd = ifd;
rdec->at_stream_end = false; rdec->at_stream_end = false;
return true;
} }
static inline void Rd_free( struct Range_decoder * const rdec ) static inline void Rd_free( struct Range_decoder * const rdec )
{ free( rdec->buffer ); rdec->buffer = 0; } { free( rdec->buffer ); }
static inline bool Rd_code_is_zero( struct Range_decoder * const rdec )
{ return ( rdec->code == 0 ); }
static inline bool Rd_finished( struct Range_decoder * const rdec ) static inline bool Rd_finished( struct Range_decoder * const rdec )
{ return rdec->pos >= rdec->stream_pos && !Rd_read_block( 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; } { return rdec->partial_member_pos + rdec->pos; }
static inline void Rd_reset_member_position( struct Range_decoder * const rdec ) 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 ) 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++]; 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 ) static inline void Rd_load( struct Range_decoder * const rdec )
{ {
int i; int i;
@ -223,27 +231,27 @@ struct Literal_decoder
Bit_model bm_literal[1<<literal_context_bits][0x300]; 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; int i, j;
for( i = 0; i < 1<<literal_context_bits; ++i ) for( i = 0; i < 1<<literal_context_bits; ++i )
for( j = 0; j < 0x300; ++j ) 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 ) ); } { 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, struct Range_decoder * const rdec,
const uint8_t prev_byte ) 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, struct Range_decoder * const rdec,
const uint8_t prev_byte, const uint8_t prev_byte,
const uint8_t match_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 struct LZ_decoder
@ -254,7 +262,7 @@ struct LZ_decoder
uint8_t * buffer; /* output buffer */ uint8_t * buffer; /* output buffer */
int pos; /* current pos in buffer */ int pos; /* current pos in buffer */
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; 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, bool LZd_verify_trailer( struct LZ_decoder * const decoder,
struct Pretty_print * const pp ); struct Pretty_print * const pp );
static inline uint8_t LZd_get_prev_byte( struct LZ_decoder * const decoder ) static inline uint8_t LZd_get_prev_byte( const struct LZ_decoder * const decoder )
{ {
const int i = const int i =
( ( decoder->pos > 0 ) ? decoder->pos : decoder->buffer_size ) - 1; ( ( decoder->pos > 0 ) ? decoder->pos : decoder->buffer_size ) - 1;
return decoder->buffer[i]; 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 ) const int distance )
{ {
int i = decoder->pos - distance - 1; 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, const File_header header,
struct Range_decoder * const rdec, const int ofd ) 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->dictionary_size = Fh_get_dictionary_size( header );
decoder->buffer_size = max( 65536, decoder->dictionary_size ); decoder->buffer_size = max( 65536, decoder->dictionary_size );
decoder->buffer = (uint8_t *)malloc( decoder->buffer_size ); decoder->buffer = (uint8_t *)malloc( decoder->buffer_size );
if( !decoder->buffer ) if( !decoder->buffer ) return false;
{
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
cleanup_and_fail( 1 );
}
decoder->pos = 0; decoder->pos = 0;
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 ); 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 ); Led_init( &decoder->rep_match_len_decoder );
Lid_init( &decoder->literal_decoder ); Lid_init( &decoder->literal_decoder );
decoder->buffer[decoder->buffer_size-1] = 0; /* prev_byte of first_byte */ decoder->buffer[decoder->buffer_size-1] = 0; /* prev_byte of first_byte */
return true;
} }
static inline void LZd_free( struct LZ_decoder * const decoder ) 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 ) static inline uint32_t LZd_crc( const struct LZ_decoder * const decoder )
{ return decoder->crc_ ^ 0xFFFFFFFFU; } { 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; } { return decoder->partial_data_pos + decoder->pos; }
int LZd_decode_member( struct LZ_decoder * const decoder, 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. .\" 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 .SH NAME
Lunzip \- small decompressor for lzip files Lunzip \- small decompressor for lzip files
.SH SYNOPSIS .SH SYNOPSIS
@ -46,7 +46,7 @@ Report bugs to lzip\-bug@nongnu.org
.br .br
Lunzip home page: http://www.nongnu.org/lzip/lunzip.html Lunzip home page: http://www.nongnu.org/lzip/lunzip.html
.SH COPYRIGHT .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> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
.br .br
This is free software: you are free to change and redistribute it. This is free software: you are free to change and redistribute it.

View file

@ -1,5 +1,5 @@
/* Lunzip - Decompressor for lzip files /* 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 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 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]; *st = next[*st];
} }
enum { enum {
min_dictionary_bits = 12, min_dictionary_bits = 12,
min_dictionary_size = 1 << min_dictionary_bits, min_dictionary_size = 1 << min_dictionary_bits,
@ -107,7 +108,7 @@ static inline void Bm_init( Bit_model * const probability )
struct Pretty_print 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; int verbosity;
@ -121,13 +122,13 @@ static inline void Pp_set_name( struct Pretty_print * const pp,
const char * const filename ) const char * const filename )
{ {
if( filename && filename[0] && strcmp( filename, "-" ) ) if( filename && filename[0] && strcmp( filename, "-" ) )
pp->name_ = filename; pp->name = filename;
else pp->name_ = pp->stdin_name; else pp->name = pp->stdin_name;
pp->first_post = true; pp->first_post = true;
} }
static inline void Pp_reset( struct Pretty_print * const pp ) 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 ); 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; int bits = 0, i = 1;
for( i = 1, mask = 1; mask > 0; ++i, mask <<= 1 ) unsigned int mask = 1;
if( value & mask ) bits = i; for( ; mask > 0; ++i, mask <<= 1 ) if( value & mask ) bits = i;
return bits; 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 */ typedef uint8_t File_header[6]; /* 0-3 magic bytes */
/* 4 version */ /* 4 version */
/* 5 coded_dict_size; */ /* 5 coded_dict_size */
enum { Fh_size = 6 }; enum { Fh_size = 6 };
static inline void Fh_set_magic( File_header data ) 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 ) 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 ) static inline uint8_t Fh_version( const File_header data )
{ return data[4]; } { return data[4]; }
@ -276,5 +272,3 @@ static inline void Ft_set_member_size( File_trailer data, long long sz )
/* defined in main.c */ /* defined in main.c */
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 );
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 /* 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 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 it under the terms of the GNU General Public License as published by
@ -24,14 +24,14 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <signal.h> #include <signal.h>
#include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#include <sys/stat.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_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; const char * invocation_name = 0;
#ifdef O_BINARY #ifdef O_BINARY
@ -80,11 +80,13 @@ struct { const char * from; const char * to; } const known_extensions[] = {
char * output_filename = 0; char * output_filename = 0;
int outfd = -1; int outfd = -1;
int verbosity = 0; 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; mode_t outfd_mode = S_IRUSR | S_IWUSR;
bool delete_output_on_interrupt = false; 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 ) static void * resize_buffer( void * buf, const int min_size )
{ {
if( buf ) buf = realloc( buf, 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( "%s - Decompressor for lzip files.\n", Program_name );
printf( "\nUsage: %s [options] [files]\n", invocation_name ); printf( "\nUsage: %s [options] [files]\n", invocation_name );
printf( "\nOptions:\n" ); printf( "\nOptions:\n"
printf( " -h, --help display this help and exit\n" ); " -h, --help display this help and exit\n"
printf( " -V, --version output version information and exit\n" ); " -V, --version output version information and exit\n"
printf( " -c, --stdout send output to standard output\n" ); " -c, --stdout send output to standard output\n"
printf( " -d, --decompress decompress (this is the default)\n" ); " -d, --decompress decompress (this is the default)\n"
printf( " -f, --force overwrite existing output files\n" ); " -f, --force overwrite existing output files\n"
printf( " -k, --keep keep (don't delete) input files\n" ); " -k, --keep keep (don't delete) input files\n"
printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" ); " -o, --output=<file> if reading stdin, place the output into <file>\n"
printf( " -q, --quiet suppress all messages\n" ); " -q, --quiet suppress all messages\n"
printf( " -t, --test test compressed file integrity\n" ); " -t, --test test compressed file integrity\n"
printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" ); " -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 ); "If no file names are given, lunzip decompresses from standard input to\n"
printf( "standard output.\n" ); "standard output.\n"
printf( "\nReport bugs to lzip-bug@nongnu.org\n" ); "\nReport bugs to lzip-bug@nongnu.org\n"
printf( "Lunzip home page: http://www.nongnu.org/lzip/lunzip.html\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( "%s %s\n", Program_name, PROGVERSION );
printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); 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( "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" ); "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" ); "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 }; enum { buf_size = 16, factor = 1024 };
static char buf[buf_size]; static char buf[buf_size];
const char *p = ""; const char *p = "";
bool exact = ( num % factor == 0 );
int i; int i;
for( i = 0; i < 8 && ( llabs( num ) > 9999 || for( i = 0; i < 8 && ( llabs( num ) > 9999 ||
( llabs( num ) >= factor && num % factor == 0 ) ); ++i ) ( exact && llabs( num ) >= factor ) ); ++i )
{ num /= factor; p = prefix[i]; } { num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; }
snprintf( buf, buf_size, "%lld %s", num, p ); snprintf( buf, buf_size, "%lld %s", num, p );
return buf; return buf;
} }
@ -155,7 +158,7 @@ static int open_instream( const char * const name,
if( infd < 0 ) if( infd < 0 )
{ {
if( verbosity >= 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 ) ); program_name, name, strerror( errno ) );
} }
else else
@ -168,10 +171,10 @@ static int open_instream( const char * const name,
if( i != 0 || ( !S_ISREG( mode ) && ( !to_stdout || !can_read ) ) ) if( i != 0 || ( !S_ISREG( mode ) && ( !to_stdout || !can_read ) ) )
{ {
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 && !to_stdout ) ?
" and `--stdout' was not specified" : "" ); " and '--stdout' was not specified" : "" );
close( infd ); close( infd );
infd = -1; 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 ); output_filename = resize_buffer( output_filename, strlen( name ) + 4 + 1 );
strcpy( output_filename, name ); strcpy( output_filename, name );
strcat( output_filename, ".out" ); strcat( output_filename, ".out" );
if( verbosity >= 0 ) if( verbosity >= 1 )
fprintf( stderr, "%s: Can't guess original name for `%s' -- using `%s'.\n", fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n",
program_name, name, output_filename ); program_name, name, output_filename );
} }
@ -228,10 +231,10 @@ static bool open_outstream( const bool force )
if( outfd < 0 && verbosity >= 0 ) if( outfd < 0 && verbosity >= 0 )
{ {
if( errno == EEXIST ) 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 ); program_name, output_filename );
else 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 ) ); program_name, output_filename, strerror( errno ) );
} }
return ( outfd >= 0 ); return ( outfd >= 0 );
@ -244,10 +247,10 @@ void cleanup_and_fail( const int retval )
{ {
delete_output_on_interrupt = false; delete_output_on_interrupt = false;
if( verbosity >= 0 ) 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 ); program_name, output_filename );
if( outfd >= 0 ) { close( outfd ); outfd = -1; } 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 ); show_error( "WARNING: deletion of output file (apparently) failed.", 0, false );
} }
exit( retval ); exit( retval );
@ -257,31 +260,26 @@ void cleanup_and_fail( const int retval )
/* Set permissions, owner and times. */ /* Set permissions, owner and times. */
static void close_and_set_permissions( const struct stat * const in_statsp ) static void close_and_set_permissions( const struct stat * const in_statsp )
{ {
bool error = false; bool warning = false;
if( in_statsp ) 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 && if( ( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) != 0 &&
errno != EPERM ) || errno != EPERM ) ||
fchmod( outfd, in_statsp->st_mode ) != 0 ) fchmod( outfd, in_statsp->st_mode ) != 0 ) warning = true;
error = true;
/* fchown will in many cases return with EPERM, which can be safely ignored. */
} }
if( close( outfd ) == 0 ) outfd = -1; if( close( outfd ) != 0 ) cleanup_and_fail( 1 );
else cleanup_and_fail( 1 ); outfd = -1;
delete_output_on_interrupt = false; delete_output_on_interrupt = false;
if( !in_statsp ) return; if( in_statsp )
if( !error )
{ {
struct utimbuf t; struct utimbuf t;
t.actime = in_statsp->st_atime; t.actime = in_statsp->st_atime;
t.modtime = in_statsp->st_mtime; 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 ); 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; long long partial_file_pos = 0;
struct Range_decoder rdec; struct Range_decoder rdec;
int retval = 0, i, result; int retval = 0, result;
bool first_member; 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 ) ) for( first_member = true; ; first_member = false, Pp_reset( pp ) )
{ {
File_header header; File_header header;
struct LZ_decoder decoder; struct LZ_decoder decoder;
Rd_reset_member_position( &rdec ); Rd_reset_member_position( &rdec );
for( i = 0; i < Fh_size; ++i ) Rd_read_data( &rdec, header, Fh_size );
header[i] = Rd_get_byte( &rdec );
if( Rd_finished( &rdec ) ) /* End Of File */ if( Rd_finished( &rdec ) ) /* End Of File */
{ {
if( first_member ) 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" ); { Pp_show_msg( pp, "Invalid dictionary size in member header" );
retval = 2; break; } retval = 2; break; }
if( verbosity >= 1 ) if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
if( verbosity >= 2 ) if( verbosity >= 2 )
@ -334,8 +335,12 @@ static int decompress( const int infd, struct Pretty_print * const pp,
Fh_version( header ), Fh_version( header ),
format_num( Fh_get_dictionary_size( 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 ); result = LZd_decode_member( &decoder, pp );
partial_file_pos += Rd_member_position( &rdec ); partial_file_pos += Rd_member_position( &rdec );
LZd_free( &decoder ); LZd_free( &decoder );
@ -352,11 +357,14 @@ static int decompress( const int infd, struct Pretty_print * const pp,
} }
retval = 2; break; retval = 2; break;
} }
if( verbosity >= 1 ) if( verbosity >= 2 )
{ if( testing ) fprintf( stderr, "ok\n" ); { if( testing ) fprintf( stderr, "ok\n" );
else fprintf( stderr, "done\n" ); } else fprintf( stderr, "done\n" ); }
} }
Rd_free( &rdec ); Rd_free( &rdec );
if( verbosity == 1 && retval == 0 )
{ if( testing ) fprintf( stderr, "ok\n" );
else fprintf( stderr, "done\n" ); }
return retval; return retval;
} }
@ -382,7 +390,7 @@ void Pp_init( struct Pretty_print * const pp, const char * const filenames[],
{ {
unsigned int stdin_name_len; unsigned int 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->verbosity = v;
@ -407,8 +415,8 @@ void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
{ {
int i, len; int i, len;
pp->first_post = false; pp->first_post = false;
fprintf( stderr, " %s: ", pp->name_ ); fprintf( stderr, " %s: ", pp->name );
len = pp->longest_name - strlen( pp->name_ ); len = pp->longest_name - strlen( pp->name );
for( i = 0; i < len; ++i ) fprintf( stderr, " " ); for( i = 0; i < len; ++i ) fprintf( stderr, " " );
if( !msg ) fflush( 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" ); fprintf( stderr, "\n" );
} }
if( help && invocation_name && invocation_name[0] ) 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 ); 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[] ) int main( const int argc, const char * const argv[] )
{ {
const char * input_filename = ""; const char * input_filename = "";
@ -516,6 +485,7 @@ int main( const int argc, const char * const argv[] )
invocation_name = argv[0]; invocation_name = argv[0];
CRC32_init(); CRC32_init();
if( !ap_init( &parser, argc, argv, options, 0 ) ) if( !ap_init( &parser, argc, argv, options, 0 ) )
{ show_error( "Memory exhausted.", 0, false ); return 1; } { show_error( "Memory exhausted.", 0, false ); return 1; }
if( ap_error( &parser ) ) /* bad option */ if( ap_error( &parser ) ) /* bad option */
@ -547,6 +517,9 @@ int main( const int argc, const char * const argv[] )
_fsetmode( stdout, "b" ); _fsetmode( stdout, "b" );
#endif #endif
if( testing )
outfd = -1;
for( ; argind < ap_arguments( &parser ); ++argind ) for( ; argind < ap_arguments( &parser ); ++argind )
{ {
if( strcmp( ap_argument( &parser, argind ), "-" ) ) if( strcmp( ap_argument( &parser, argind ), "-" ) )
@ -567,8 +540,6 @@ int main( const int argc, const char * const argv[] )
set_signals(); set_signals();
Pp_init( &pp, filenames, num_filenames, verbosity ); Pp_init( &pp, filenames, num_filenames, verbosity );
if( testing )
outfd = -1;
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 )
@ -591,7 +562,7 @@ int main( const int argc, const char * const argv[] )
output_filename = resize_buffer( output_filename, output_filename = resize_buffer( output_filename,
strlen( default_output_filename ) + 1 ); strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename ); 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( !open_outstream( force ) )
{ {
if( outfd == -1 && retval < 1 ) retval = 1; if( outfd == -1 && retval < 1 ) retval = 1;
@ -612,7 +583,7 @@ int main( const int argc, const char * const argv[] )
else else
{ {
set_d_outname( input_filename ); set_d_outname( input_filename );
outfd_mode = S_IRUSR | S_IWUSR; outfd_mode = usr_rw;
if( !open_outstream( force ) ) if( !open_outstream( force ) )
{ {
if( outfd == -1 && retval < 1 ) retval = 1; if( outfd == -1 && retval < 1 ) retval = 1;

View file

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

BIN
testsuite/test_sync.lz Normal file

Binary file not shown.