Merging upstream version 1.6.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
ee79238874
commit
d41db2478f
22 changed files with 748 additions and 400 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,12 @@
|
|||
2017-04-12 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.6 released.
|
||||
* The option '-l, --list' has been ported from lziprecover.
|
||||
* Don't allow mixing different operations (-d, -l or -t).
|
||||
* main.cc: Continue testing if any input file is a terminal.
|
||||
* file_index.cc: Improve detection of bad dict and trailing data.
|
||||
* lzip.h: Unified messages for bad magic, trailing data, etc.
|
||||
|
||||
2016-05-14 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.5 released.
|
||||
|
@ -139,7 +148,7 @@
|
|||
until something better appears on the net.
|
||||
|
||||
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
|
2
INSTALL
2
INSTALL
|
@ -65,7 +65,7 @@ After running 'configure', you can run 'make' and 'make install' as
|
|||
explained above.
|
||||
|
||||
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 Antonio Diaz Diaz.
|
||||
|
||||
This file is free documentation: you have unlimited permission to copy,
|
||||
distribute and modify it.
|
||||
|
|
14
Makefile.in
14
Makefile.in
|
@ -8,14 +8,15 @@ LIBS = -llz -lpthread
|
|||
SHELL = /bin/sh
|
||||
CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1
|
||||
|
||||
objs = arg_parser.o file_index.o compress.o dec_stdout.o dec_stream.o \
|
||||
decompress.o main.o
|
||||
objs = arg_parser.o file_index.o list.o compress.o dec_stdout.o \
|
||||
dec_stream.o decompress.o main.o
|
||||
|
||||
|
||||
.PHONY : all install install-bin install-info install-man \
|
||||
install-strip install-compress install-strip-compress \
|
||||
install-bin-strip install-info-compress install-man-compress \
|
||||
install-as-lzip uninstall uninstall-bin uninstall-info uninstall-man \
|
||||
install-as-lzip \
|
||||
uninstall uninstall-bin uninstall-info uninstall-man \
|
||||
doc info man check dist clean distclean
|
||||
|
||||
all : $(progname)
|
||||
|
@ -36,6 +37,7 @@ dec_stdout.o : lzip.h file_index.h
|
|||
dec_stream.o : lzip.h
|
||||
decompress.o : lzip.h file_index.h
|
||||
file_index.o : lzip.h file_index.h
|
||||
list.o : lzip.h file_index.h
|
||||
main.o : arg_parser.h lzip.h
|
||||
|
||||
|
||||
|
@ -120,11 +122,11 @@ dist : doc
|
|||
$(DISTNAME)/doc/$(progname).1 \
|
||||
$(DISTNAME)/doc/$(pkgname).info \
|
||||
$(DISTNAME)/doc/$(pkgname).texi \
|
||||
$(DISTNAME)/*.h \
|
||||
$(DISTNAME)/*.cc \
|
||||
$(DISTNAME)/testsuite/check.sh \
|
||||
$(DISTNAME)/testsuite/test.txt \
|
||||
$(DISTNAME)/testsuite/test.txt.lz \
|
||||
$(DISTNAME)/*.h \
|
||||
$(DISTNAME)/*.cc
|
||||
$(DISTNAME)/testsuite/test.txt.lz
|
||||
rm -f $(DISTNAME)
|
||||
lzip -v -9 $(DISTNAME).tar
|
||||
|
||||
|
|
17
NEWS
17
NEWS
|
@ -1,14 +1,9 @@
|
|||
Changes in version 1.5:
|
||||
Changes in version 1.6:
|
||||
|
||||
The option "-a, --trailing-error", which makes plzip exit with error
|
||||
status 2 if any remaining input is detected after decompressing the last
|
||||
member, has been added.
|
||||
The option '-l, --list' has been ported from lziprecover.
|
||||
|
||||
When decompressing, the file specified with the '--output' option is now
|
||||
deleted if the input is a terminal.
|
||||
It is now an error to specify two or more different operations in the
|
||||
command line (--decompress, --list or --test).
|
||||
|
||||
The new chapters "Trailing data" and "Examples" have been added to the
|
||||
manual.
|
||||
|
||||
A harmless check failure on Windows, caused by the failed comparison of
|
||||
a message in text mode, has been fixed.
|
||||
In test mode, plzip now continues checking the rest of the files if any
|
||||
input file is a terminal.
|
||||
|
|
12
README
12
README
|
@ -35,11 +35,11 @@ availability:
|
|||
merging of damaged copies of a file.
|
||||
|
||||
* The lzip format is as simple as possible (but not simpler). The
|
||||
lzip manual provides the code of a simple decompressor along with a
|
||||
detailed explanation of how it works, so that with the only help of
|
||||
the lzip manual it would be possible for a digital archaeologist to
|
||||
extract the data from a lzip file long after quantum computers
|
||||
eventually render LZMA obsolete.
|
||||
lzip manual provides the source code of a simple decompressor along
|
||||
with a detailed explanation of how it works, so that with the only
|
||||
help of the lzip manual it would be possible for a digital
|
||||
archaeologist to extract the data from a lzip file long after
|
||||
quantum computers eventually render LZMA obsolete.
|
||||
|
||||
* Additionally the lzip reference implementation is copylefted, which
|
||||
guarantees that it will remain free forever.
|
||||
|
@ -88,7 +88,7 @@ corresponding uncompressed files. Integrity testing of concatenated
|
|||
compressed files is also supported.
|
||||
|
||||
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 Antonio Diaz Diaz.
|
||||
|
||||
This file is free documentation: you have unlimited permission to copy,
|
||||
distribute and modify it.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
|
||||
Copyright (C) 2006-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2006-2017 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software. Redistribution and use in source and
|
||||
binary forms, with or without modification, are permitted provided
|
||||
|
@ -142,7 +142,7 @@ Arg_parser::Arg_parser( const int argc, const char * const argv[],
|
|||
{
|
||||
if( argc < 2 || !argv || !options ) return;
|
||||
|
||||
std::vector< std::string > non_options; // skipped non-options
|
||||
std::vector< const char * > non_options; // skipped non-options
|
||||
int argind = 1; // index in argv
|
||||
|
||||
while( argind < argc )
|
||||
|
@ -163,17 +163,17 @@ Arg_parser::Arg_parser( const int argc, const char * const argv[],
|
|||
}
|
||||
else
|
||||
{
|
||||
if( !in_order ) non_options.push_back( argv[argind++] );
|
||||
else { data.push_back( Record() ); data.back().argument = argv[argind++]; }
|
||||
if( in_order ) data.push_back( Record( argv[argind++] ) );
|
||||
else non_options.push_back( argv[argind++] );
|
||||
}
|
||||
}
|
||||
if( error_.size() ) data.clear();
|
||||
else
|
||||
{
|
||||
for( unsigned i = 0; i < non_options.size(); ++i )
|
||||
{ data.push_back( Record() ); data.back().argument.swap( non_options[i] ); }
|
||||
data.push_back( Record( non_options[i] ) );
|
||||
while( argind < argc )
|
||||
{ data.push_back( Record() ); data.back().argument = argv[argind++]; }
|
||||
data.push_back( Record( argv[argind++] ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,5 +192,5 @@ Arg_parser::Arg_parser( const char * const opt, const char * const arg,
|
|||
parse_short_option( opt, arg, options, argind );
|
||||
if( error_.size() ) data.clear();
|
||||
}
|
||||
else { data.push_back( Record() ); data.back().argument = opt; }
|
||||
else data.push_back( Record( opt ) );
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
|
||||
Copyright (C) 2006-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2006-2017 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software. Redistribution and use in source and
|
||||
binary forms, with or without modification, are permitted provided
|
||||
|
@ -57,7 +57,8 @@ private:
|
|||
{
|
||||
int code;
|
||||
std::string argument;
|
||||
explicit Record( const int c = 0 ) : code( c ) {}
|
||||
explicit Record( const int c ) : code( c ) {}
|
||||
explicit Record( const char * const arg ) : code( 0 ), argument( arg ) {}
|
||||
};
|
||||
|
||||
std::string error_;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009 Laszlo Ersek.
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
|
21
configure
vendored
21
configure
vendored
|
@ -1,12 +1,12 @@
|
|||
#! /bin/sh
|
||||
# configure script for Plzip - Parallel compressor compatible with lzip
|
||||
# Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
# Copyright (C) 2009-2017 Antonio Diaz Diaz.
|
||||
#
|
||||
# This configure script is free software: you have unlimited permission
|
||||
# to copy, distribute and modify it.
|
||||
|
||||
pkgname=plzip
|
||||
pkgversion=1.5
|
||||
pkgversion=1.6
|
||||
progname=plzip
|
||||
srctrigger=doc/${pkgname}.texi
|
||||
|
||||
|
@ -26,11 +26,11 @@ CXXFLAGS='-Wall -W -O2'
|
|||
LDFLAGS=
|
||||
|
||||
# checking whether we are using GNU C++.
|
||||
if /bin/sh -c "${CXX} --version" > /dev/null 2>&1 ; then true
|
||||
else
|
||||
/bin/sh -c "${CXX} --version" > /dev/null 2>&1 ||
|
||||
{
|
||||
CXX=c++
|
||||
CXXFLAGS='-W -O2'
|
||||
fi
|
||||
CXXFLAGS=-O2
|
||||
}
|
||||
|
||||
# Loop over all args
|
||||
args=
|
||||
|
@ -52,9 +52,12 @@ while [ $# != 0 ] ; do
|
|||
# Process the options
|
||||
case ${option} in
|
||||
--help | -h)
|
||||
echo "Usage: configure [options]"
|
||||
echo "Usage: $0 [OPTION]... [VAR=VALUE]..."
|
||||
echo
|
||||
echo "Options: [defaults in brackets]"
|
||||
echo "To assign makefile variables (e.g., CXX, CXXFLAGS...), specify them as"
|
||||
echo "arguments to configure in the form VAR=VALUE."
|
||||
echo
|
||||
echo "Options and variables: [defaults in brackets]"
|
||||
echo " -h, --help display this help and exit"
|
||||
echo " -V, --version output version information and exit"
|
||||
echo " --srcdir=DIR find the sources in DIR [. or ..]"
|
||||
|
@ -165,7 +168,7 @@ echo "LDFLAGS = ${LDFLAGS}"
|
|||
rm -f Makefile
|
||||
cat > Makefile << EOF
|
||||
# Makefile for Plzip - Parallel compressor compatible with lzip
|
||||
# Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
# Copyright (C) 2009-2017 Antonio Diaz Diaz.
|
||||
# This file was generated automatically by configure. Don't edit.
|
||||
#
|
||||
# This Makefile is free software: you have unlimited permission
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009 Laszlo Ersek.
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -298,15 +298,15 @@ int dec_stdout( const int num_workers, const int infd, const int outfd,
|
|||
delete[] worker_threads;
|
||||
delete[] worker_args;
|
||||
|
||||
const unsigned long long in_size = file_index.file_end();
|
||||
const unsigned long long out_size = file_index.data_end();
|
||||
const unsigned long long in_size = file_index.cdata_size();
|
||||
const unsigned long long out_size = file_index.udata_size();
|
||||
if( verbosity >= 2 && out_size > 0 && in_size > 0 )
|
||||
std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
|
||||
(double)out_size / in_size,
|
||||
( 8.0 * in_size ) / out_size,
|
||||
100.0 * ( 1.0 - ( (double)in_size / out_size ) ) );
|
||||
if( verbosity >= 4 )
|
||||
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
||||
std::fprintf( stderr, "decompressed %9llu, compressed %9llu. ",
|
||||
out_size, in_size );
|
||||
|
||||
if( verbosity >= 1 ) std::fputs( "done\n", stderr );
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009 Laszlo Ersek.
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -267,16 +267,13 @@ extern "C" void * dsplitter_s( void * arg )
|
|||
{ pp( "Input file is too short." ); cleanup_and_fail( 2 ); }
|
||||
const File_header & header = *(File_header *)buffer;
|
||||
if( !header.verify_magic() )
|
||||
{ pp( "Bad magic number (file not in lzip format)." ); cleanup_and_fail( 2 ); }
|
||||
{ pp( bad_magic_msg ); cleanup_and_fail( 2 ); }
|
||||
if( !header.verify_version() )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
{ pp();
|
||||
std::fprintf( stderr, "Version %d member format not supported.\n",
|
||||
header.version() ); }
|
||||
cleanup_and_fail( 2 );
|
||||
}
|
||||
show_header( header.dictionary_size() );
|
||||
{ pp( bad_version( header.version() ) ); cleanup_and_fail( 2 ); }
|
||||
const unsigned dictionary_size = header.dictionary_size();
|
||||
if( !isvalid_ds( dictionary_size ) )
|
||||
{ pp( bad_dict_msg ); cleanup_and_fail( 2 ); }
|
||||
show_header( dictionary_size );
|
||||
|
||||
unsigned long long partial_member_size = 0;
|
||||
while( true )
|
||||
|
@ -293,13 +290,10 @@ extern "C" void * dsplitter_s( void * arg )
|
|||
{ // header found
|
||||
const File_header & header = *(File_header *)(buffer + newpos);
|
||||
if( !header.verify_version() )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
{ pp();
|
||||
std::fprintf( stderr, "Version %d member format not supported.\n",
|
||||
header.version() ); }
|
||||
cleanup_and_fail( 2 );
|
||||
}
|
||||
{ pp( bad_version( header.version() ) ); cleanup_and_fail( 2 ); }
|
||||
const unsigned dictionary_size = header.dictionary_size();
|
||||
if( !isvalid_ds( dictionary_size ) )
|
||||
{ pp( bad_dict_msg ); cleanup_and_fail( 2 ); }
|
||||
uint8_t * const data = new( std::nothrow ) uint8_t[newpos - pos];
|
||||
if( !data ) { pp( "Not enough memory." ); cleanup_and_fail(); }
|
||||
std::memcpy( data, buffer + pos, newpos - pos );
|
||||
|
@ -367,7 +361,7 @@ extern "C" void * dworker_s( void * arg )
|
|||
{ pp( "Not enough memory." ); cleanup_and_fail(); }
|
||||
unsigned long long partial_out_size = 0;
|
||||
int new_pos = 0;
|
||||
bool trailing_garbage_found = false;
|
||||
bool trailing_data_found = false;
|
||||
|
||||
while( true )
|
||||
{
|
||||
|
@ -376,7 +370,7 @@ extern "C" void * dworker_s( void * arg )
|
|||
if( !ipacket->data ) LZ_decompress_finish( decoder );
|
||||
|
||||
int written = 0;
|
||||
while( !trailing_garbage_found )
|
||||
while( !trailing_data_found )
|
||||
{
|
||||
if( LZ_decompress_write_size( decoder ) > 0 && written < ipacket->size )
|
||||
{
|
||||
|
@ -387,7 +381,7 @@ extern "C" void * dworker_s( void * arg )
|
|||
if( written > ipacket->size )
|
||||
internal_error( "ipacket size exceeded in worker." );
|
||||
}
|
||||
while( !trailing_garbage_found ) // read and pack decompressed data
|
||||
while( !trailing_data_found ) // read and pack decompressed data
|
||||
{
|
||||
const int rd = LZ_decompress_read( decoder, new_data + new_pos,
|
||||
max_packet_size - new_pos );
|
||||
|
@ -395,9 +389,9 @@ extern "C" void * dworker_s( void * arg )
|
|||
{
|
||||
if( LZ_decompress_errno( decoder ) == LZ_header_error )
|
||||
{
|
||||
trailing_garbage_found = true;
|
||||
trailing_data_found = true;
|
||||
if( !ignore_trailing )
|
||||
{ pp( "Trailing data not allowed." ); cleanup_and_fail( 2 ); }
|
||||
{ pp( trailing_msg ); cleanup_and_fail( 2 ); }
|
||||
}
|
||||
else
|
||||
cleanup_and_fail( decompress_read_error( decoder, pp, worker_id ) );
|
||||
|
@ -405,7 +399,7 @@ extern "C" void * dworker_s( void * arg )
|
|||
else new_pos += rd;
|
||||
if( new_pos > max_packet_size )
|
||||
internal_error( "opacket size exceeded in worker." );
|
||||
if( new_pos == max_packet_size || trailing_garbage_found ||
|
||||
if( new_pos == max_packet_size || trailing_data_found ||
|
||||
LZ_decompress_finished( decoder ) == 1 )
|
||||
{
|
||||
if( !testing && new_pos > 0 ) // make data packet
|
||||
|
@ -417,8 +411,7 @@ extern "C" void * dworker_s( void * arg )
|
|||
}
|
||||
partial_out_size += new_pos;
|
||||
new_pos = 0;
|
||||
if( trailing_garbage_found ||
|
||||
LZ_decompress_finished( decoder ) == 1 )
|
||||
if( trailing_data_found || LZ_decompress_finished( decoder ) == 1 )
|
||||
{
|
||||
if( !testing ) // end of member token
|
||||
courier.collect_packet( new Packet, worker_id );
|
||||
|
@ -525,7 +518,7 @@ int dec_stream( const int num_workers, const int infd, const int outfd,
|
|||
( 8.0 * in_size ) / out_size,
|
||||
100.0 * ( 1.0 - ( (double)in_size / out_size ) ) );
|
||||
if( verbosity >= 4 )
|
||||
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
||||
std::fprintf( stderr, "decompressed %9llu, compressed %9llu. ",
|
||||
out_size, in_size );
|
||||
|
||||
if( verbosity >= 1 ) std::fputs( (outfd < 0) ? "ok\n" : "done\n", stderr );
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009 Laszlo Ersek.
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -266,15 +266,15 @@ int decompress( int num_workers, const int infd, const int outfd,
|
|||
delete[] worker_threads;
|
||||
delete[] worker_args;
|
||||
|
||||
const unsigned long long in_size = file_index.file_end();
|
||||
const unsigned long long out_size = file_index.data_end();
|
||||
const unsigned long long in_size = file_index.cdata_size();
|
||||
const unsigned long long out_size = file_index.udata_size();
|
||||
if( verbosity >= 2 && out_size > 0 && in_size > 0 )
|
||||
std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
|
||||
(double)out_size / in_size,
|
||||
( 8.0 * in_size ) / out_size,
|
||||
100.0 * ( 1.0 - ( (double)in_size / out_size ) ) );
|
||||
if( verbosity >= 4 )
|
||||
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
||||
std::fprintf( stderr, "decompressed %9llu, compressed %9llu. ",
|
||||
out_size, in_size );
|
||||
|
||||
if( verbosity >= 1 ) std::fputs( (outfd < 0) ? "ok\n" : "done\n", stderr );
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
|
||||
.TH PLZIP "1" "May 2016" "plzip 1.5" "User Commands"
|
||||
.TH PLZIP "1" "April 2017" "plzip 1.6" "User Commands"
|
||||
.SH NAME
|
||||
plzip \- reduces the size of files
|
||||
.SH SYNOPSIS
|
||||
|
@ -36,6 +36,9 @@ force re\-compression of compressed files
|
|||
\fB\-k\fR, \fB\-\-keep\fR
|
||||
keep (don't delete) input files
|
||||
.TP
|
||||
\fB\-l\fR, \fB\-\-list\fR
|
||||
print (un)compressed file sizes
|
||||
.TP
|
||||
\fB\-m\fR, \fB\-\-match\-length=\fR<bytes>
|
||||
set match length limit in bytes [36]
|
||||
.TP
|
||||
|
@ -89,8 +92,8 @@ Plzip home page: http://www.nongnu.org/lzip/plzip.html
|
|||
.SH COPYRIGHT
|
||||
Copyright \(co 2009 Laszlo Ersek.
|
||||
.br
|
||||
Copyright \(co 2016 Antonio Diaz Diaz.
|
||||
Using lzlib 1.8
|
||||
Copyright \(co 2017 Antonio Diaz Diaz.
|
||||
Using lzlib 1.9
|
||||
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
|
||||
.br
|
||||
This is free software: you are free to change and redistribute it.
|
||||
|
|
|
@ -11,7 +11,7 @@ File: plzip.info, Node: Top, Next: Introduction, Up: (dir)
|
|||
Plzip Manual
|
||||
************
|
||||
|
||||
This manual is for Plzip (version 1.5, 14 May 2016).
|
||||
This manual is for Plzip (version 1.6, 12 April 2017).
|
||||
|
||||
* Menu:
|
||||
|
||||
|
@ -27,7 +27,7 @@ This manual is for Plzip (version 1.5, 14 May 2016).
|
|||
* Concept index:: Index of concepts
|
||||
|
||||
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 Antonio Diaz Diaz.
|
||||
|
||||
This manual is free documentation: you have unlimited permission to
|
||||
copy, distribute and modify it.
|
||||
|
@ -65,11 +65,11 @@ availability:
|
|||
(lziprecover)Data safety.
|
||||
|
||||
* The lzip format is as simple as possible (but not simpler). The
|
||||
lzip manual provides the code of a simple decompressor along with
|
||||
a detailed explanation of how it works, so that with the only help
|
||||
of the lzip manual it would be possible for a digital
|
||||
archaeologist to extract the data from a lzip file long after
|
||||
quantum computers eventually render LZMA obsolete.
|
||||
lzip manual provides the source code of a simple decompressor
|
||||
along with a detailed explanation of how it works, so that with
|
||||
the only help of the lzip manual it would be possible for a
|
||||
digital archaeologist to extract the data from a lzip file long
|
||||
after quantum computers eventually render LZMA obsolete.
|
||||
|
||||
* Additionally the lzip reference implementation is copylefted, which
|
||||
guarantees that it will remain free forever.
|
||||
|
@ -117,6 +117,10 @@ two or more compressed files. The result is the concatenation of the
|
|||
corresponding uncompressed files. Integrity testing of concatenated
|
||||
compressed files is also supported.
|
||||
|
||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may
|
||||
never have been compressed. Decompressed is used to refer to data which
|
||||
have undergone the process of decompression.
|
||||
|
||||
|
||||
File: plzip.info, Node: Invoking plzip, Next: Program design, Prev: Introduction, Up: Top
|
||||
|
||||
|
@ -185,6 +189,21 @@ command line.
|
|||
Keep (don't delete) input files during compression or
|
||||
decompression.
|
||||
|
||||
'-l'
|
||||
'--list'
|
||||
Print the uncompressed size, compressed size and percentage saved
|
||||
of the specified file(s). Trailing data are ignored. The values
|
||||
produced are correct even for multimember files. If more than one
|
||||
file is given, a final line containing the cumulative sizes is
|
||||
printed. With '-v', the dictionary size, the number of members in
|
||||
the file, and the amount of trailing data (if any) are also
|
||||
printed. With '-vv', the positions and sizes of each member in
|
||||
multimember files are also printed. '-lq' can be used to verify
|
||||
quickly (without decompressing) the structural integrity of the
|
||||
specified files. (Use '--test' to verify the data integrity).
|
||||
'-alq' additionally verifies that none of the specified files
|
||||
contain trailing data.
|
||||
|
||||
'-m BYTES'
|
||||
'--match-length=BYTES'
|
||||
Set the match length limit in bytes. After a match this long is
|
||||
|
@ -236,8 +255,10 @@ command line.
|
|||
Check integrity of the specified file(s), but don't decompress
|
||||
them. This really performs a trial decompression and throws away
|
||||
the result. Use it together with '-v' to see information about
|
||||
the file(s). If a file fails the test, plzip may be unable to
|
||||
check the rest of the files.
|
||||
the file(s). If a file does not exist, can't be opened, or is a
|
||||
terminal, plzip continues checking the rest of the files. If a
|
||||
file fails the test, plzip may be unable to check the rest of the
|
||||
files.
|
||||
|
||||
'-v'
|
||||
'--verbose'
|
||||
|
@ -420,9 +441,6 @@ following:
|
|||
* For decompression of a regular (seekable) file to another regular
|
||||
file, or for testing of a regular file; the dictionary size.
|
||||
|
||||
(Note that regular files with more than 1024 bytes of trailing
|
||||
data are treated as non-seekable).
|
||||
|
||||
* For testing of a non-seekable file or of standard input; the
|
||||
dictionary size plus up to 5 MiB.
|
||||
|
||||
|
@ -474,16 +492,21 @@ File: plzip.info, Node: Trailing data, Next: Examples, Prev: Minimum file siz
|
|||
7 Extra data appended to the file
|
||||
*********************************
|
||||
|
||||
Sometimes extra data is found appended to a lzip file after the last
|
||||
Sometimes extra data are found appended to a lzip file after the last
|
||||
member. Such trailing data may be:
|
||||
|
||||
* Padding added to make the file size a multiple of some block size,
|
||||
for example when writing to a tape.
|
||||
|
||||
* Garbage added by some not totally successful copy operation.
|
||||
for example when writing to a tape. It is safe to append any
|
||||
amount of padding zero bytes to a lzip file.
|
||||
|
||||
* Useful data added by the user; a cryptographically secure hash, a
|
||||
description of file contents, etc.
|
||||
description of file contents, etc. It is safe to append any amount
|
||||
of text to a lzip file as long as the text does not begin with the
|
||||
string "LZIP", and does not contain any zero bytes (null
|
||||
characters). Nonzero bytes and zero bytes can't be safely mixed in
|
||||
trailing data.
|
||||
|
||||
* Garbage added by some not totally successful copy operation.
|
||||
|
||||
* Malicious data added to the file in order to make its total size
|
||||
and hash value (for a chosen hash) coincide with those of another
|
||||
|
@ -496,8 +519,12 @@ member. Such trailing data may be:
|
|||
the corruption of the integrity information itself. Therefore it
|
||||
can be considered to be below the noise level.
|
||||
|
||||
Trailing data are in no way part of the lzip file format, but tools
|
||||
reading lzip files are expected to behave as correctly and usefully as
|
||||
possible in the presence of trailing data.
|
||||
|
||||
Trailing data can be safely ignored in most cases. In some cases,
|
||||
like that of user-added data, it is expected to be ignored. In those
|
||||
like that of user-added data, they are expected to be ignored. In those
|
||||
cases where a file containing trailing data must be rejected, the option
|
||||
'--trailing-error' can be used. *Note --trailing-error::.
|
||||
|
||||
|
@ -545,8 +572,8 @@ Example 5: Compress a whole device in /dev/sdc and send the output to
|
|||
plzip -c /dev/sdc > file.lz
|
||||
|
||||
|
||||
Example 6: The right way of concatenating compressed files. *Note
|
||||
Trailing data::.
|
||||
Example 6: The right way of concatenating the decompressed output of two
|
||||
or more compressed files. *Note Trailing data::.
|
||||
|
||||
Don't do this
|
||||
cat file1.lz file2.lz file3.lz | plzip -d
|
||||
|
@ -607,19 +634,19 @@ Concept index
|
|||
|
||||
Tag Table:
|
||||
Node: Top221
|
||||
Node: Introduction1101
|
||||
Node: Invoking plzip5078
|
||||
Ref: --trailing-error5647
|
||||
Ref: --data-size5890
|
||||
Node: Program design11683
|
||||
Node: File format13270
|
||||
Node: Memory requirements15702
|
||||
Node: Minimum file sizes16811
|
||||
Node: Trailing data18737
|
||||
Node: Examples20121
|
||||
Ref: concat-example21286
|
||||
Node: Problems21823
|
||||
Node: Concept index22349
|
||||
Node: Introduction1103
|
||||
Node: Invoking plzip5274
|
||||
Ref: --trailing-error5843
|
||||
Ref: --data-size6086
|
||||
Node: Program design12796
|
||||
Node: File format14383
|
||||
Node: Memory requirements16815
|
||||
Node: Minimum file sizes17815
|
||||
Node: Trailing data19741
|
||||
Node: Examples21648
|
||||
Ref: concat-example22813
|
||||
Node: Problems23388
|
||||
Node: Concept index23914
|
||||
|
||||
End Tag Table
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
@finalout
|
||||
@c %**end of header
|
||||
|
||||
@set UPDATED 14 May 2016
|
||||
@set VERSION 1.5
|
||||
@set UPDATED 12 April 2017
|
||||
@set VERSION 1.6
|
||||
|
||||
@dircategory Data Compression
|
||||
@direntry
|
||||
|
@ -48,7 +48,7 @@ This manual is for Plzip (version @value{VERSION}, @value{UPDATED}).
|
|||
@end menu
|
||||
|
||||
@sp 1
|
||||
Copyright @copyright{} 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright @copyright{} 2009-2017 Antonio Diaz Diaz.
|
||||
|
||||
This manual is free documentation: you have unlimited permission
|
||||
to copy, distribute and modify it.
|
||||
|
@ -90,10 +90,10 @@ including error-checked merging of damaged copies of a file.
|
|||
|
||||
@item
|
||||
The lzip format is as simple as possible (but not simpler). The lzip
|
||||
manual provides the code of a simple decompressor along with a detailed
|
||||
explanation of how it works, so that with the only help of the lzip
|
||||
manual it would be possible for a digital archaeologist to extract the
|
||||
data from a lzip file long after quantum computers eventually render
|
||||
manual provides the source code of a simple decompressor along with a
|
||||
detailed explanation of how it works, so that with the only help of the
|
||||
lzip manual it would be possible for a digital archaeologist to extract
|
||||
the data from a lzip file long after quantum computers eventually render
|
||||
LZMA obsolete.
|
||||
|
||||
@item
|
||||
|
@ -146,6 +146,10 @@ or more compressed files. The result is the concatenation of the
|
|||
corresponding uncompressed files. Integrity testing of concatenated
|
||||
compressed files is also supported.
|
||||
|
||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
|
||||
have been compressed. Decompressed is used to refer to data which have
|
||||
undergone the process of decompression.
|
||||
|
||||
|
||||
@node Invoking plzip
|
||||
@chapter Invoking plzip
|
||||
|
@ -220,6 +224,20 @@ Force re-compression of files whose name already has the @samp{.lz} or
|
|||
@itemx --keep
|
||||
Keep (don't delete) input files during compression or decompression.
|
||||
|
||||
@item -l
|
||||
@itemx --list
|
||||
Print the uncompressed size, compressed size and percentage saved of the
|
||||
specified file(s). Trailing data are ignored. The values produced are
|
||||
correct even for multimember files. If more than one file is given, a
|
||||
final line containing the cumulative sizes is printed. With @samp{-v},
|
||||
the dictionary size, the number of members in the file, and the amount
|
||||
of trailing data (if any) are also printed. With @samp{-vv}, the
|
||||
positions and sizes of each member in multimember files are also
|
||||
printed. @samp{-lq} can be used to verify quickly (without
|
||||
decompressing) the structural integrity of the specified files. (Use
|
||||
@samp{--test} to verify the data integrity). @samp{-alq} additionally
|
||||
verifies that none of the specified files contain trailing data.
|
||||
|
||||
@item -m @var{bytes}
|
||||
@itemx --match-length=@var{bytes}
|
||||
Set the match length limit in bytes. After a match this long is found,
|
||||
|
@ -267,8 +285,9 @@ is affected at compression time by the choice of dictionary size limit.
|
|||
Check integrity of the specified file(s), but don't decompress them.
|
||||
This really performs a trial decompression and throws away the result.
|
||||
Use it together with @samp{-v} to see information about the file(s). If
|
||||
a file fails the test, plzip may be unable to check the rest of the
|
||||
files.
|
||||
a file does not exist, can't be opened, or is a terminal, plzip
|
||||
continues checking the rest of the files. If a file fails the test,
|
||||
plzip may be unable to check the rest of the files.
|
||||
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
|
@ -469,9 +488,6 @@ times the data size. Default is 136 MiB.
|
|||
For decompression of a regular (seekable) file to another regular file,
|
||||
or for testing of a regular file; the dictionary size.
|
||||
|
||||
(Note that regular files with more than 1024 bytes of trailing data are
|
||||
treated as non-seekable).
|
||||
|
||||
@item
|
||||
For testing of a non-seekable file or of standard input; the dictionary
|
||||
size plus up to 5 MiB.
|
||||
|
@ -526,20 +542,24 @@ data size for each level:
|
|||
@chapter Extra data appended to the file
|
||||
@cindex trailing data
|
||||
|
||||
Sometimes extra data is found appended to a lzip file after the last
|
||||
Sometimes extra data are found appended to a lzip file after the last
|
||||
member. Such trailing data may be:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Padding added to make the file size a multiple of some block size, for
|
||||
example when writing to a tape.
|
||||
|
||||
@item
|
||||
Garbage added by some not totally successful copy operation.
|
||||
example when writing to a tape. It is safe to append any amount of
|
||||
padding zero bytes to a lzip file.
|
||||
|
||||
@item
|
||||
Useful data added by the user; a cryptographically secure hash, a
|
||||
description of file contents, etc.
|
||||
description of file contents, etc. It is safe to append any amount of
|
||||
text to a lzip file as long as the text does not begin with the string
|
||||
"LZIP", and does not contain any zero bytes (null characters). Nonzero
|
||||
bytes and zero bytes can't be safely mixed in trailing data.
|
||||
|
||||
@item
|
||||
Garbage added by some not totally successful copy operation.
|
||||
|
||||
@item
|
||||
Malicious data added to the file in order to make its total size and
|
||||
|
@ -554,8 +574,12 @@ integrity information itself. Therefore it can be considered to be below
|
|||
the noise level.
|
||||
@end itemize
|
||||
|
||||
Trailing data are in no way part of the lzip file format, but tools
|
||||
reading lzip files are expected to behave as correctly and usefully as
|
||||
possible in the presence of trailing data.
|
||||
|
||||
Trailing data can be safely ignored in most cases. In some cases, like
|
||||
that of user-added data, it is expected to be ignored. In those cases
|
||||
that of user-added data, they are expected to be ignored. In those cases
|
||||
where a file containing trailing data must be rejected, the option
|
||||
@samp{--trailing-error} can be used. @xref{--trailing-error}.
|
||||
|
||||
|
@ -620,8 +644,8 @@ plzip -c /dev/sdc > file.lz
|
|||
@sp 1
|
||||
@anchor{concat-example}
|
||||
@noindent
|
||||
Example 6: The right way of concatenating compressed files.
|
||||
@xref{Trailing data}.
|
||||
Example 6: The right way of concatenating the decompressed output of two
|
||||
or more compressed files. @xref{Trailing data}.
|
||||
|
||||
@example
|
||||
Don't do this
|
||||
|
|
124
file_index.cc
124
file_index.cc
|
@ -1,5 +1,5 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -15,6 +15,8 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
|
@ -29,6 +31,8 @@
|
|||
#include "file_index.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
int seek_read( const int fd, uint8_t * const buf, const int size,
|
||||
const long long pos )
|
||||
{
|
||||
|
@ -37,6 +41,8 @@ int seek_read( const int fd, uint8_t * const buf, const int size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
void File_index::set_errno_error( const char * const msg )
|
||||
{
|
||||
|
@ -44,20 +50,75 @@ void File_index::set_errno_error( const char * const msg )
|
|||
retval_ = 1;
|
||||
}
|
||||
|
||||
void File_index::set_num_error( const char * const msg1, unsigned long long num,
|
||||
const char * const msg2 )
|
||||
void File_index::set_num_error( const char * const msg, unsigned long long num )
|
||||
{
|
||||
char buf[80];
|
||||
snprintf( buf, sizeof buf, "%s%llu%s", msg1, num, msg2 );
|
||||
snprintf( buf, sizeof buf, "%s%llu", msg, num );
|
||||
error_ = buf;
|
||||
retval_ = member_vector.empty() ? 1 : 2; // maybe trailing data
|
||||
retval_ = 2;
|
||||
}
|
||||
|
||||
|
||||
File_index::File_index( const int infd, const bool ignore_garbage )
|
||||
: retval_( 0 )
|
||||
// If successful, push last member and set pos to member header.
|
||||
bool File_index::skip_trailing_data( const int fd, long long & pos )
|
||||
{
|
||||
enum { block_size = 16384,
|
||||
buffer_size = block_size + File_trailer::size - 1 + File_header::size };
|
||||
uint8_t buffer[buffer_size];
|
||||
if( pos < min_member_size ) return false;
|
||||
int bsize = pos % block_size; // total bytes in buffer
|
||||
if( bsize <= buffer_size - block_size ) bsize += block_size;
|
||||
int search_size = bsize; // bytes to search for trailer
|
||||
int rd_size = bsize; // bytes to read from file
|
||||
unsigned long long ipos = pos - rd_size; // aligned to block_size
|
||||
|
||||
while( true )
|
||||
{
|
||||
if( seek_read( fd, buffer, rd_size, ipos ) != rd_size )
|
||||
{ set_errno_error( "Error seeking member trailer: " ); return false; }
|
||||
const uint8_t max_msb = ( ipos + search_size ) >> 56;
|
||||
for( int i = search_size; i >= File_trailer::size; --i )
|
||||
if( buffer[i-1] <= max_msb ) // most significant byte of member_size
|
||||
{
|
||||
File_trailer & trailer =
|
||||
*(File_trailer *)( buffer + i - File_trailer::size );
|
||||
const unsigned long long member_size = trailer.member_size();
|
||||
if( member_size == 0 )
|
||||
{ while( i > File_trailer::size && buffer[i-9] == 0 ) --i; continue; }
|
||||
if( member_size < min_member_size || member_size > ipos + i )
|
||||
continue;
|
||||
File_header header;
|
||||
if( seek_read( fd, header.data, File_header::size,
|
||||
ipos + i - member_size ) != File_header::size )
|
||||
{ set_errno_error( "Error reading member header: " ); return false; }
|
||||
const unsigned dictionary_size = header.dictionary_size();
|
||||
if( !header.verify_magic() || !header.verify_version() ||
|
||||
!isvalid_ds( dictionary_size ) ) continue;
|
||||
if( (*(File_header *)( buffer + i )).verify_prefix( bsize - i ) )
|
||||
{
|
||||
error_ = "Last member in input file is truncated or corrupt.";
|
||||
retval_ = 2; return false;
|
||||
}
|
||||
pos = ipos + i - member_size;
|
||||
member_vector.push_back( Member( 0, trailer.data_size(), pos,
|
||||
member_size, dictionary_size ) );
|
||||
return true;
|
||||
}
|
||||
if( ipos <= 0 )
|
||||
{ set_num_error( "Member size in trailer is corrupt at pos ", pos - 8 );
|
||||
return false; }
|
||||
bsize = buffer_size;
|
||||
search_size = bsize - File_header::size;
|
||||
rd_size = block_size;
|
||||
ipos -= rd_size;
|
||||
std::memcpy( buffer + rd_size, buffer, buffer_size - rd_size );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File_index::File_index( const int infd, const bool ignore_trailing )
|
||||
: isize( lseek( infd, 0, SEEK_END ) ), retval_( 0 )
|
||||
{
|
||||
const long long isize = lseek( infd, 0, SEEK_END );
|
||||
if( isize < 0 )
|
||||
{ set_errno_error( "Input file is not seekable: " ); return; }
|
||||
if( isize < min_member_size )
|
||||
|
@ -70,55 +131,46 @@ File_index::File_index( const int infd, const bool ignore_garbage )
|
|||
if( seek_read( infd, header.data, File_header::size, 0 ) != File_header::size )
|
||||
{ set_errno_error( "Error reading member header: " ); return; }
|
||||
if( !header.verify_magic() )
|
||||
{ error_ = "Bad magic number (file not in lzip format).";
|
||||
retval_ = 2; return; }
|
||||
{ error_ = bad_magic_msg; retval_ = 2; return; }
|
||||
if( !header.verify_version() )
|
||||
{ set_num_error( "Version ", header.version(),
|
||||
" member format not supported." ); retval_ = 2; return; }
|
||||
{ error_ = bad_version( header.version() ); retval_ = 2; return; }
|
||||
if( !isvalid_ds( header.dictionary_size() ) )
|
||||
{ error_ = bad_dict_msg; retval_ = 2; return; }
|
||||
|
||||
long long pos = isize; // always points to a header or to EOF
|
||||
const long long max_garbage = 1024;
|
||||
while( pos >= min_member_size )
|
||||
{
|
||||
File_trailer trailer;
|
||||
if( seek_read( infd, trailer.data, File_trailer::size,
|
||||
pos - File_trailer::size ) != File_trailer::size )
|
||||
{ set_errno_error( "Error reading member trailer: " ); break; }
|
||||
const long long member_size = trailer.member_size();
|
||||
if( member_size < min_member_size || member_size > pos )
|
||||
const unsigned long long member_size = trailer.member_size();
|
||||
if( member_size < min_member_size || member_size > (unsigned long long)pos )
|
||||
{
|
||||
if( member_vector.empty() && isize - pos < max_garbage )
|
||||
{
|
||||
if( ignore_garbage ) { --pos; continue; } // maybe trailing data
|
||||
error_ = "Trailing data not allowed."; retval_ = 2; return;
|
||||
}
|
||||
if( !member_vector.empty() )
|
||||
set_num_error( "Member size in trailer is corrupt at pos ", pos - 8 );
|
||||
else if( skip_trailing_data( infd, pos ) )
|
||||
{ if( ignore_trailing ) continue;
|
||||
error_ = trailing_msg; retval_ = 2; return; }
|
||||
break;
|
||||
}
|
||||
if( seek_read( infd, header.data, File_header::size,
|
||||
pos - member_size ) != File_header::size )
|
||||
{ set_errno_error( "Error reading member header: " ); break; }
|
||||
if( !header.verify_magic() || !header.verify_version() )
|
||||
const unsigned dictionary_size = header.dictionary_size();
|
||||
if( !header.verify_magic() || !header.verify_version() ||
|
||||
!isvalid_ds( dictionary_size ) )
|
||||
{
|
||||
if( member_vector.empty() && isize - pos < max_garbage )
|
||||
{
|
||||
if( ignore_garbage ) { --pos; continue; } // maybe trailing data
|
||||
error_ = "Trailing data not allowed."; retval_ = 2; return;
|
||||
}
|
||||
if( !member_vector.empty() )
|
||||
set_num_error( "Bad header at pos ", pos - member_size );
|
||||
else if( skip_trailing_data( infd, pos ) )
|
||||
{ if( ignore_trailing ) continue;
|
||||
error_ = trailing_msg; retval_ = 2; return; }
|
||||
break;
|
||||
}
|
||||
const unsigned dictionary_size = header.dictionary_size();
|
||||
if( member_vector.empty() && isize - pos > File_header::size &&
|
||||
seek_read( infd, header.data, File_header::size, pos ) == File_header::size &&
|
||||
header.verify_magic() && header.verify_version() )
|
||||
{
|
||||
error_ = "Last member in input file is truncated or corrupt.";
|
||||
retval_ = 2; break;
|
||||
}
|
||||
pos -= member_size;
|
||||
member_vector.push_back( Member( 0, trailer.data_size(),
|
||||
pos, member_size, dictionary_size ) );
|
||||
member_vector.push_back( Member( 0, trailer.data_size(), pos,
|
||||
member_size, dictionary_size ) );
|
||||
}
|
||||
if( pos != 0 || member_vector.empty() )
|
||||
{
|
||||
|
|
25
file_index.h
25
file_index.h
|
@ -1,5 +1,5 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -50,26 +50,31 @@ class File_index
|
|||
|
||||
std::vector< Member > member_vector;
|
||||
std::string error_;
|
||||
const long long isize;
|
||||
int retval_;
|
||||
|
||||
void set_errno_error( const char * const msg );
|
||||
void set_num_error( const char * const msg1, unsigned long long num,
|
||||
const char * const msg2 = "" );
|
||||
void set_num_error( const char * const msg, unsigned long long num );
|
||||
bool skip_trailing_data( const int fd, long long & pos );
|
||||
|
||||
public:
|
||||
File_index( const int infd, const bool ignore_garbage );
|
||||
File_index( const int infd, const bool ignore_trailing );
|
||||
|
||||
long members() const { return member_vector.size(); }
|
||||
const std::string & error() const { return error_; }
|
||||
int retval() const { return retval_; }
|
||||
|
||||
long long data_end() const
|
||||
{ if( member_vector.size() ) return member_vector.back().dblock.end();
|
||||
else return 0; }
|
||||
long long udata_size() const
|
||||
{ if( member_vector.empty() ) return 0;
|
||||
return member_vector.back().dblock.end(); }
|
||||
|
||||
long long file_end() const
|
||||
{ if( member_vector.size() ) return member_vector.back().mblock.end();
|
||||
else return 0; }
|
||||
long long cdata_size() const
|
||||
{ if( member_vector.empty() ) return 0;
|
||||
return member_vector.back().mblock.end(); }
|
||||
|
||||
// total size including trailing data (if any)
|
||||
long long file_size() const
|
||||
{ if( isize >= 0 ) return isize; else return 0; }
|
||||
|
||||
const Block & dblock( const long i ) const
|
||||
{ return member_vector[i].dblock; }
|
||||
|
|
121
list.cc
Normal file
121
list.cc
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009-2017 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
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "lzip.h"
|
||||
#include "file_index.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void list_line( const unsigned long long uncomp_size,
|
||||
const unsigned long long comp_size,
|
||||
const char * const input_filename )
|
||||
{
|
||||
if( uncomp_size > 0 )
|
||||
std::printf( "%15llu %15llu %6.2f%% %s\n", uncomp_size, comp_size,
|
||||
100.0 * ( 1.0 - ( (double)comp_size / uncomp_size ) ),
|
||||
input_filename );
|
||||
else
|
||||
std::printf( "%15llu %15llu -INF%% %s\n", uncomp_size, comp_size,
|
||||
input_filename );
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
int list_files( const std::vector< std::string > & filenames,
|
||||
const bool ignore_trailing )
|
||||
{
|
||||
unsigned long long total_comp = 0, total_uncomp = 0;
|
||||
int files = 0, retval = 0;
|
||||
bool first_post = true;
|
||||
bool stdin_used = false;
|
||||
for( unsigned i = 0; i < filenames.size(); ++i )
|
||||
{
|
||||
const bool from_stdin = ( filenames[i] == "-" );
|
||||
if( from_stdin ) { if( stdin_used ) continue; else stdin_used = true; }
|
||||
const char * const input_filename =
|
||||
from_stdin ? "(stdin)" : filenames[i].c_str();
|
||||
struct stat in_stats; // not used
|
||||
const int infd = from_stdin ? STDIN_FILENO :
|
||||
open_instream( input_filename, &in_stats, true, true );
|
||||
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
|
||||
|
||||
const File_index file_index( infd, ignore_trailing );
|
||||
close( infd );
|
||||
if( file_index.retval() != 0 )
|
||||
{
|
||||
show_file_error( input_filename, file_index.error().c_str() );
|
||||
if( retval < file_index.retval() ) retval = file_index.retval();
|
||||
continue;
|
||||
}
|
||||
if( verbosity >= 0 )
|
||||
{
|
||||
const unsigned long long udata_size = file_index.udata_size();
|
||||
const unsigned long long cdata_size = file_index.cdata_size();
|
||||
total_comp += cdata_size; total_uncomp += udata_size; ++files;
|
||||
if( first_post )
|
||||
{
|
||||
first_post = false;
|
||||
if( verbosity >= 1 ) std::fputs( " dict memb trail ", stdout );
|
||||
std::fputs( " uncompressed compressed saved name\n", stdout );
|
||||
}
|
||||
if( verbosity >= 1 )
|
||||
{
|
||||
unsigned dictionary_size = 0;
|
||||
for( long i = 0; i < file_index.members(); ++i )
|
||||
dictionary_size =
|
||||
std::max( dictionary_size, file_index.dictionary_size( i ) );
|
||||
const long long trailing_size = file_index.file_size() - cdata_size;
|
||||
std::printf( "%s %5ld %6lld ", format_ds( dictionary_size ),
|
||||
file_index.members(), trailing_size );
|
||||
}
|
||||
list_line( udata_size, cdata_size, input_filename );
|
||||
|
||||
if( verbosity >= 2 && file_index.members() > 1 )
|
||||
{
|
||||
std::fputs( " member data_pos data_size member_pos member_size\n", stdout );
|
||||
for( long i = 0; i < file_index.members(); ++i )
|
||||
{
|
||||
const Block & db = file_index.dblock( i );
|
||||
const Block & mb = file_index.mblock( i );
|
||||
std::printf( "%5ld %15llu %15llu %15llu %15llu\n",
|
||||
i + 1, db.pos(), db.size(), mb.pos(), mb.size() );
|
||||
}
|
||||
first_post = true; // reprint heading after list of members
|
||||
}
|
||||
std::fflush( stdout );
|
||||
}
|
||||
}
|
||||
if( verbosity >= 0 && files > 1 )
|
||||
{
|
||||
if( verbosity >= 1 ) std::fputs( " ", stdout );
|
||||
list_line( total_uncomp, total_comp, "(totals)" );
|
||||
std::fflush( stdout );
|
||||
}
|
||||
return retval;
|
||||
}
|
33
lzip.h
33
lzip.h
|
@ -1,5 +1,5 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -88,6 +88,12 @@ struct File_header
|
|||
void set_magic() { std::memcpy( data, magic_string, 4 ); data[4] = 1; }
|
||||
bool verify_magic() const
|
||||
{ return ( std::memcmp( data, magic_string, 4 ) == 0 ); }
|
||||
bool verify_prefix( const int size ) const // detect truncated header
|
||||
{
|
||||
for( int i = 0; i < size && i < 4; ++i )
|
||||
if( data[i] != magic_string[i] ) return false;
|
||||
return ( size > 0 );
|
||||
}
|
||||
|
||||
uint8_t version() const { return data[4]; }
|
||||
bool verify_version() const { return ( data[4] == 1 ); }
|
||||
|
@ -108,7 +114,7 @@ struct File_header
|
|||
{
|
||||
const unsigned base_size = 1 << data[5];
|
||||
const unsigned fraction = base_size / 16;
|
||||
for( int i = 7; i >= 1; --i )
|
||||
for( unsigned i = 7; i >= 1; --i )
|
||||
if( base_size - ( i * fraction ) >= sz )
|
||||
{ data[5] |= ( i << 5 ); break; }
|
||||
}
|
||||
|
@ -157,6 +163,10 @@ struct File_trailer
|
|||
};
|
||||
|
||||
|
||||
const char * const bad_magic_msg = "Bad magic number (file not in lzip format).";
|
||||
const char * const bad_dict_msg = "Invalid dictionary size in member header.";
|
||||
const char * const trailing_msg = "Trailing data not allowed.";
|
||||
|
||||
// defined in compress.cc
|
||||
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 );
|
||||
|
@ -185,25 +195,34 @@ int dec_stdout( const int num_workers, const int infd, const int outfd,
|
|||
// defined in dec_stream.cc
|
||||
int dec_stream( const int num_workers, const int infd, const int outfd,
|
||||
const Pretty_print & pp, const int debug_level,
|
||||
const bool ignore_garbage );
|
||||
const bool ignore_trailing );
|
||||
|
||||
// defined in decompress.cc
|
||||
int preadblock( const int fd, uint8_t * const buf, const int size,
|
||||
const long long pos );
|
||||
int pwriteblock( const int fd, const uint8_t * const buf, const int size,
|
||||
const long long pos );
|
||||
int decompress_read_error( struct LZ_Decoder * const decoder,
|
||||
const Pretty_print & pp, const int worker_id );
|
||||
int decompress( int num_workers, const int infd, const int outfd,
|
||||
const Pretty_print & pp, const int debug_level,
|
||||
const bool ignore_garbage, const bool infd_isreg );
|
||||
const bool ignore_trailing, const bool infd_isreg );
|
||||
|
||||
// defined in list.cc
|
||||
int list_files( const std::vector< std::string > & filenames,
|
||||
const bool ignore_trailing );
|
||||
|
||||
// defined in main.cc
|
||||
extern int verbosity;
|
||||
void cleanup_and_fail( const int retval = 1 ); // terminate the program
|
||||
struct stat;
|
||||
const char * bad_version( const unsigned version );
|
||||
const char * format_ds( const unsigned dictionary_size );
|
||||
void show_header( const unsigned dictionary_size );
|
||||
int open_instream( const char * const name, struct stat * const in_statsp,
|
||||
const bool no_ofile, const bool reg_only = false );
|
||||
void cleanup_and_fail( const int retval = 1 ); // terminate the program
|
||||
void show_error( const char * const msg, const int errcode = 0,
|
||||
const bool help = false );
|
||||
void show_file_error( const char * const filename, const char * const msg,
|
||||
const int errcode = 0 );
|
||||
void internal_error( const char * const msg );
|
||||
void show_progress( const int packet_size,
|
||||
const Pretty_print * const p = 0,
|
||||
|
|
178
main.cc
178
main.cc
|
@ -1,6 +1,6 @@
|
|||
/* Plzip - Parallel compressor compatible with lzip
|
||||
Copyright (C) 2009 Laszlo Ersek.
|
||||
Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2017 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
|
||||
|
@ -73,10 +73,10 @@ namespace {
|
|||
|
||||
const char * const Program_name = "Plzip";
|
||||
const char * const program_name = "plzip";
|
||||
const char * const program_year = "2016";
|
||||
const char * const program_year = "2017";
|
||||
const char * invocation_name = 0;
|
||||
|
||||
struct { const char * from; const char * to; } const known_extensions[] = {
|
||||
const struct { const char * from; const char * to; } known_extensions[] = {
|
||||
{ ".lz", "" },
|
||||
{ ".tlz", ".tar" },
|
||||
{ 0, 0 } };
|
||||
|
@ -87,7 +87,7 @@ struct Lzma_options
|
|||
int match_len_limit; // 5 .. 273
|
||||
};
|
||||
|
||||
enum Mode { m_compress, m_decompress, m_test };
|
||||
enum Mode { m_compress, m_decompress, m_list, m_test };
|
||||
|
||||
std::string output_filename;
|
||||
int outfd = -1;
|
||||
|
@ -108,6 +108,7 @@ void show_help( const long num_online )
|
|||
" -f, --force overwrite existing output files\n"
|
||||
" -F, --recompress force re-compression of compressed files\n"
|
||||
" -k, --keep keep (don't delete) input files\n"
|
||||
" -l, --list print (un)compressed file sizes\n"
|
||||
" -m, --match-length=<bytes> set match length limit in bytes [36]\n"
|
||||
" -n, --threads=<n> set number of (de)compression threads [%ld]\n"
|
||||
" -o, --output=<file> if reading standard input, write to <file>\n"
|
||||
|
@ -120,7 +121,7 @@ void show_help( const long num_online )
|
|||
" --best alias for -9\n", num_online );
|
||||
if( verbosity >= 1 )
|
||||
{
|
||||
std::printf( " -D, --debug=<level> (0-1) print debug statistics to stderr\n" );
|
||||
std::printf( " --debug=<level> (0-1) print debug statistics to stderr\n" );
|
||||
}
|
||||
std::printf( "If no file names are given, or if a file is '-', plzip compresses or\n"
|
||||
"decompresses from standard input to standard output.\n"
|
||||
|
@ -154,13 +155,21 @@ void show_version()
|
|||
|
||||
} // end namespace
|
||||
|
||||
void show_header( const unsigned dictionary_size )
|
||||
const char * bad_version( const unsigned version )
|
||||
{
|
||||
if( verbosity >= 3 )
|
||||
static char buf[80];
|
||||
snprintf( buf, sizeof buf, "Version %u member format not supported.",
|
||||
version );
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
const char * format_ds( const unsigned dictionary_size )
|
||||
{
|
||||
enum { bufsize = 16, factor = 1024 };
|
||||
static char buf[bufsize];
|
||||
const char * const prefix[8] =
|
||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
|
||||
enum { factor = 1024 };
|
||||
const char * p = "";
|
||||
const char * np = " ";
|
||||
unsigned num = dictionary_size;
|
||||
|
@ -169,8 +178,15 @@ void show_header( const unsigned dictionary_size )
|
|||
for( int i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
|
||||
{ num /= factor; if( num % factor != 0 ) exact = false;
|
||||
p = prefix[i]; np = ""; }
|
||||
std::fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p );
|
||||
snprintf( buf, bufsize, "%s%4u %sB", np, num, p );
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void show_header( const unsigned dictionary_size )
|
||||
{
|
||||
if( verbosity >= 3 )
|
||||
std::fprintf( stderr, "dictionary %s. ", format_ds( dictionary_size ) );
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -190,7 +206,7 @@ unsigned long long getnum( const char * const ptr,
|
|||
|
||||
if( !errno && tail[0] )
|
||||
{
|
||||
const int factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
||||
const unsigned factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
||||
int exponent = 0; // 0 = bad multiplier
|
||||
switch( tail[0] )
|
||||
{
|
||||
|
@ -228,7 +244,7 @@ unsigned long long getnum( const char * const ptr,
|
|||
int get_dict_size( const char * const arg )
|
||||
{
|
||||
char * tail;
|
||||
const int bits = std::strtol( arg, &tail, 0 );
|
||||
const long bits = std::strtol( arg, &tail, 0 );
|
||||
if( bits >= LZ_min_dictionary_bits() &&
|
||||
bits <= LZ_max_dictionary_bits() && *tail == 0 )
|
||||
return ( 1 << bits );
|
||||
|
@ -239,47 +255,44 @@ int get_dict_size( const char * const arg )
|
|||
}
|
||||
|
||||
|
||||
void set_mode( Mode & program_mode, const Mode new_mode )
|
||||
{
|
||||
if( program_mode != m_compress && program_mode != new_mode )
|
||||
{
|
||||
show_error( "Only one operation can be specified.", 0, true );
|
||||
std::exit( 1 );
|
||||
}
|
||||
program_mode = new_mode;
|
||||
}
|
||||
|
||||
|
||||
int extension_index( const std::string & name )
|
||||
{
|
||||
for( int i = 0; known_extensions[i].from; ++i )
|
||||
for( int eindex = 0; known_extensions[eindex].from; ++eindex )
|
||||
{
|
||||
const std::string ext( known_extensions[i].from );
|
||||
const std::string ext( known_extensions[eindex].from );
|
||||
if( name.size() > ext.size() &&
|
||||
name.compare( name.size() - ext.size(), ext.size(), ext ) == 0 )
|
||||
return i;
|
||||
return eindex;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
int open_instream( const char * const name, struct stat * const in_statsp,
|
||||
const Mode program_mode, const int eindex,
|
||||
const bool recompress, const bool to_stdout )
|
||||
const bool no_ofile, const bool reg_only )
|
||||
{
|
||||
int infd = -1;
|
||||
if( program_mode == m_compress && !recompress && eindex >= 0 )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n",
|
||||
program_name, name, known_extensions[eindex].from );
|
||||
}
|
||||
else
|
||||
{
|
||||
infd = open( name, O_RDONLY | O_BINARY );
|
||||
int infd = open( name, O_RDONLY | O_BINARY );
|
||||
if( infd < 0 )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Can't open input file '%s': %s\n",
|
||||
program_name, name, std::strerror( errno ) );
|
||||
}
|
||||
show_file_error( name, "Can't open input file", errno );
|
||||
else
|
||||
{
|
||||
const int i = fstat( infd, in_statsp );
|
||||
const mode_t mode = in_statsp->st_mode;
|
||||
const bool can_read = ( i == 0 &&
|
||||
const bool can_read = ( i == 0 && !reg_only &&
|
||||
( S_ISBLK( mode ) || S_ISCHR( mode ) ||
|
||||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
|
||||
const bool no_ofile = ( to_stdout || program_mode == m_test );
|
||||
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
|
@ -291,10 +304,26 @@ int open_instream( const char * const name, struct stat * const in_statsp,
|
|||
infd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return infd;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
int open_instream2( const char * const name, struct stat * const in_statsp,
|
||||
const Mode program_mode, const int eindex,
|
||||
const bool recompress, const bool to_stdout )
|
||||
{
|
||||
if( program_mode == m_compress && !recompress && eindex >= 0 )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n",
|
||||
program_name, name, known_extensions[eindex].from );
|
||||
return -1;
|
||||
}
|
||||
const bool no_ofile = ( to_stdout || program_mode == m_test );
|
||||
return open_instream( name, in_statsp, no_ofile, false );
|
||||
}
|
||||
|
||||
|
||||
void set_c_outname( const std::string & name )
|
||||
{
|
||||
|
@ -303,15 +332,15 @@ void set_c_outname( const std::string & name )
|
|||
}
|
||||
|
||||
|
||||
void set_d_outname( const std::string & name, const int i )
|
||||
void set_d_outname( const std::string & name, const int eindex )
|
||||
{
|
||||
if( i >= 0 )
|
||||
if( eindex >= 0 )
|
||||
{
|
||||
const std::string from( known_extensions[i].from );
|
||||
const std::string from( known_extensions[eindex].from );
|
||||
if( name.size() > from.size() )
|
||||
{
|
||||
output_filename.assign( name, 0, name.size() - from.size() );
|
||||
output_filename += known_extensions[i].to;
|
||||
output_filename += known_extensions[eindex].to;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +374,8 @@ bool open_outstream( const bool force, const bool from_stdin )
|
|||
}
|
||||
|
||||
|
||||
bool check_tty( const int infd, const Mode program_mode )
|
||||
bool check_tty( const char * const input_filename, const int infd,
|
||||
const Mode program_mode )
|
||||
{
|
||||
if( program_mode == m_compress && isatty( outfd ) )
|
||||
{
|
||||
|
@ -355,7 +385,8 @@ bool check_tty( const int infd, const Mode program_mode )
|
|||
if( ( program_mode == m_decompress || program_mode == m_test ) &&
|
||||
isatty( infd ) )
|
||||
{
|
||||
show_error( "I won't read compressed data from a terminal.", 0, true );
|
||||
show_file_error( input_filename,
|
||||
"I won't read compressed data from a terminal." );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -454,6 +485,16 @@ void show_error( const char * const msg, const int errcode, const bool help )
|
|||
}
|
||||
|
||||
|
||||
void show_file_error( const char * const filename, const char * const msg,
|
||||
const int errcode )
|
||||
{
|
||||
if( verbosity < 0 ) return;
|
||||
std::fprintf( stderr, "%s: %s: %s", program_name, filename, msg );
|
||||
if( errcode > 0 ) std::fprintf( stderr, ": %s", std::strerror( errcode ) );
|
||||
std::fputc( '\n', stderr );
|
||||
}
|
||||
|
||||
|
||||
void internal_error( const char * const msg )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
|
@ -504,7 +545,6 @@ int main( const int argc, const char * const argv[] )
|
|||
{ 3 << 23, 132 }, // -8
|
||||
{ 1 << 25, 273 } }; // -9
|
||||
Lzma_options encoder_options = option_mapping[6]; // default = "-6"
|
||||
std::string input_filename;
|
||||
std::string default_output_filename;
|
||||
std::vector< std::string > filenames;
|
||||
int data_size = 0;
|
||||
|
@ -528,6 +568,7 @@ int main( const int argc, const char * const argv[] )
|
|||
if( max_workers < 1 || max_workers > INT_MAX / (int)sizeof (pthread_t) )
|
||||
max_workers = INT_MAX / sizeof (pthread_t);
|
||||
|
||||
enum Optcode { opt_dbg = 256 };
|
||||
const Arg_parser::Option options[] =
|
||||
{
|
||||
{ '0', "fast", Arg_parser::no },
|
||||
|
@ -545,11 +586,11 @@ int main( const int argc, const char * const argv[] )
|
|||
{ 'B', "data-size", Arg_parser::yes },
|
||||
{ 'c', "stdout", Arg_parser::no },
|
||||
{ 'd', "decompress", Arg_parser::no },
|
||||
{ 'D', "debug", Arg_parser::yes },
|
||||
{ 'f', "force", Arg_parser::no },
|
||||
{ 'F', "recompress", Arg_parser::no },
|
||||
{ 'h', "help", Arg_parser::no },
|
||||
{ 'k', "keep", Arg_parser::no },
|
||||
{ 'l', "list", Arg_parser::no },
|
||||
{ 'm', "match-length", Arg_parser::yes },
|
||||
{ 'n', "threads", Arg_parser::yes },
|
||||
{ 'o', "output", Arg_parser::yes },
|
||||
|
@ -559,6 +600,7 @@ int main( const int argc, const char * const argv[] )
|
|||
{ 't', "test", Arg_parser::no },
|
||||
{ 'v', "verbose", Arg_parser::no },
|
||||
{ 'V', "version", Arg_parser::no },
|
||||
{ opt_dbg, "debug", Arg_parser::yes },
|
||||
{ 0 , 0, Arg_parser::no } };
|
||||
|
||||
const Arg_parser parser( argc, argv, options );
|
||||
|
@ -570,8 +612,8 @@ int main( const int argc, const char * const argv[] )
|
|||
{
|
||||
const int code = parser.code( argind );
|
||||
if( !code ) break; // no more options
|
||||
const std::string & arg = parser.argument( argind );
|
||||
const char * const ptr = arg.c_str();
|
||||
const std::string & sarg = parser.argument( argind );
|
||||
const char * const arg = sarg.c_str();
|
||||
switch( code )
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
|
@ -579,27 +621,28 @@ int main( const int argc, const char * const argv[] )
|
|||
encoder_options = option_mapping[code-'0']; break;
|
||||
case 'a': ignore_trailing = false; break;
|
||||
case 'b': break;
|
||||
case 'B': data_size = getnum( ptr, 2 * LZ_min_dictionary_size(),
|
||||
case 'B': data_size = getnum( arg, 2 * LZ_min_dictionary_size(),
|
||||
2 * LZ_max_dictionary_size() ); break;
|
||||
case 'c': to_stdout = true; break;
|
||||
case 'd': program_mode = m_decompress; break;
|
||||
case 'D': debug_level = getnum( ptr, 0, 3 ); break;
|
||||
case 'd': set_mode( program_mode, m_decompress ); break;
|
||||
case 'f': force = true; break;
|
||||
case 'F': recompress = true; break;
|
||||
case 'h': show_help( num_online ); return 0;
|
||||
case 'k': keep_input_files = true; break;
|
||||
case 'l': set_mode( program_mode, m_list ); break;
|
||||
case 'm': encoder_options.match_len_limit =
|
||||
getnum( ptr, LZ_min_match_len_limit(),
|
||||
getnum( arg, LZ_min_match_len_limit(),
|
||||
LZ_max_match_len_limit() ); break;
|
||||
case 'n': num_workers = getnum( ptr, 1, max_workers ); break;
|
||||
case 'o': default_output_filename = arg; break;
|
||||
case 'n': num_workers = getnum( arg, 1, max_workers ); break;
|
||||
case 'o': default_output_filename = sarg; break;
|
||||
case 'q': verbosity = -1; break;
|
||||
case 's': encoder_options.dictionary_size = get_dict_size( ptr );
|
||||
case 's': encoder_options.dictionary_size = get_dict_size( arg );
|
||||
break;
|
||||
case 'S': break;
|
||||
case 't': program_mode = m_test; break;
|
||||
case 't': set_mode( program_mode, m_test ); break;
|
||||
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
||||
case 'V': show_version(); return 0;
|
||||
case opt_dbg: debug_level = getnum( arg, 0, 3 ); break;
|
||||
default : internal_error( "uncaught option." );
|
||||
}
|
||||
} // end process options
|
||||
|
@ -609,6 +652,17 @@ int main( const int argc, const char * const argv[] )
|
|||
setmode( STDOUT_FILENO, O_BINARY );
|
||||
#endif
|
||||
|
||||
bool filenames_given = false;
|
||||
for( ; argind < parser.arguments(); ++argind )
|
||||
{
|
||||
filenames.push_back( parser.argument( argind ) );
|
||||
if( filenames.back() != "-" ) filenames_given = true;
|
||||
}
|
||||
if( filenames.empty() ) filenames.push_back("-");
|
||||
|
||||
if( program_mode == m_list )
|
||||
return list_files( filenames, ignore_trailing );
|
||||
|
||||
if( program_mode == m_test )
|
||||
outfd = -1;
|
||||
|
||||
|
@ -626,14 +680,6 @@ int main( const int argc, const char * const argv[] )
|
|||
if( num_workers <= 0 )
|
||||
num_workers = std::min( num_online, max_workers );
|
||||
|
||||
bool filenames_given = false;
|
||||
for( ; argind < parser.arguments(); ++argind )
|
||||
{
|
||||
filenames.push_back( parser.argument( argind ) );
|
||||
if( filenames.back() != "-" ) filenames_given = true;
|
||||
}
|
||||
|
||||
if( filenames.empty() ) filenames.push_back("-");
|
||||
if( !to_stdout && program_mode != m_test &&
|
||||
( filenames_given || default_output_filename.size() ) )
|
||||
set_signals();
|
||||
|
@ -644,13 +690,13 @@ int main( const int argc, const char * const argv[] )
|
|||
bool stdin_used = false;
|
||||
for( unsigned i = 0; i < filenames.size(); ++i )
|
||||
{
|
||||
std::string input_filename;
|
||||
struct stat in_stats;
|
||||
output_filename.clear();
|
||||
|
||||
if( filenames[i].empty() || filenames[i] == "-" )
|
||||
{
|
||||
if( stdin_used ) continue; else stdin_used = true;
|
||||
input_filename.clear();
|
||||
infd = STDIN_FILENO;
|
||||
if( program_mode != m_test )
|
||||
{
|
||||
|
@ -672,9 +718,8 @@ int main( const int argc, const char * const argv[] )
|
|||
}
|
||||
else
|
||||
{
|
||||
input_filename = filenames[i];
|
||||
const int eindex = extension_index( input_filename );
|
||||
infd = open_instream( input_filename.c_str(), &in_stats, program_mode,
|
||||
const int eindex = extension_index( input_filename = filenames[i] );
|
||||
infd = open_instream2( input_filename.c_str(), &in_stats, program_mode,
|
||||
eindex, recompress, to_stdout );
|
||||
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
|
||||
if( program_mode != m_test )
|
||||
|
@ -695,15 +740,16 @@ int main( const int argc, const char * const argv[] )
|
|||
}
|
||||
}
|
||||
|
||||
if( !check_tty( infd, program_mode ) )
|
||||
pp.set_name( input_filename );
|
||||
if( !check_tty( pp.name(), infd, program_mode ) )
|
||||
{
|
||||
if( retval < 1 ) retval = 1;
|
||||
if( program_mode == m_test ) { close( infd ); infd = -1; continue; }
|
||||
cleanup_and_fail( retval );
|
||||
}
|
||||
|
||||
const struct stat * const in_statsp = input_filename.size() ? &in_stats : 0;
|
||||
const bool infd_isreg = in_statsp && S_ISREG( in_statsp->st_mode );
|
||||
pp.set_name( input_filename );
|
||||
if( verbosity >= 1 ) pp();
|
||||
int tmp;
|
||||
if( program_mode == m_compress )
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# check script for Plzip - Parallel compressor compatible with lzip
|
||||
# Copyright (C) 2009-2016 Antonio Diaz Diaz.
|
||||
# Copyright (C) 2009-2017 Antonio Diaz Diaz.
|
||||
#
|
||||
# This script is free software: you have unlimited permission
|
||||
# to copy, distribute and modify it.
|
||||
|
@ -17,12 +17,12 @@ if [ ! -f "${LZIP}" ] || [ ! -x "${LZIP}" ] ; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "${LZIP}" ] 2> /dev/null ; then true
|
||||
else
|
||||
[ -e "${LZIP}" ] 2> /dev/null ||
|
||||
{
|
||||
echo "$0: a POSIX shell is required to run the tests"
|
||||
echo "Try bash -c \"$0 $1 $2\""
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -d tmp ] ; then rm -rf tmp ; fi
|
||||
mkdir tmp
|
||||
|
@ -31,185 +31,233 @@ cd "${objdir}"/tmp || framework_failure
|
|||
cat "${testdir}"/test.txt > in || framework_failure
|
||||
in_lz="${testdir}"/test.txt.lz
|
||||
fail=0
|
||||
test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; }
|
||||
|
||||
printf "testing plzip-%s..." "$2"
|
||||
|
||||
"${LZIP}" -fkqm4 in
|
||||
if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO
|
||||
"${LZIP}" -fkqm274 in
|
||||
if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -fkqs-1 in
|
||||
if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -fkqs0 in
|
||||
if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -fkqs4095 in
|
||||
if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -fkqs513MiB in
|
||||
if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO
|
||||
for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do
|
||||
"${LZIP}" -fkqs $i in
|
||||
{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO $i
|
||||
done
|
||||
"${LZIP}" -lq in
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq in
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq < in
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq in
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq < in
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
dd if="${in_lz}" bs=1 count=6 2> /dev/null | "${LZIP}" -tq
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
dd if="${in_lz}" bs=1 count=20 2> /dev/null | "${LZIP}" -tq
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
# these are for code coverage
|
||||
"${LZIP}" -lt "${in_lz}" 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdl "${in_lz}" > out 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -t -- nx_file 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --help > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -n1 -V > /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -m 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -z 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --bad_option 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --t 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --test=2 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --output= 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" --output 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
printf "LZIP\001-.............................." | "${LZIP}" -t 2> /dev/null
|
||||
printf "LZIP\002-.............................." | "${LZIP}" -t 2> /dev/null
|
||||
printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null
|
||||
|
||||
printf "\ntesting decompression..."
|
||||
|
||||
"${LZIP}" -t "${in_lz}"
|
||||
if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -cd "${in_lz}" > copy || fail=1
|
||||
cmp in copy || fail=1
|
||||
printf .
|
||||
"${LZIP}" -lq "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -t "${in_lz}" || test_failed $LINENO
|
||||
"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
rm -f copy
|
||||
cat "${in_lz}" > copy.lz || framework_failure
|
||||
"${LZIP}" -dk copy.lz || fail=1
|
||||
cmp in copy || fail=1
|
||||
"${LZIP}" -dk copy.lz || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
printf "to be overwritten" > copy || framework_failure
|
||||
"${LZIP}" -dq copy.lz
|
||||
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -d copy.lz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -df copy.lz
|
||||
if [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; then
|
||||
printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; } || test_failed $LINENO
|
||||
|
||||
printf "to be overwritten" > copy || framework_failure
|
||||
"${LZIP}" -df -o copy < "${in_lz}" || fail=1
|
||||
cmp in copy || fail=1
|
||||
printf .
|
||||
"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
rm -f copy
|
||||
"${LZIP}" < in > anyothername || fail=1
|
||||
"${LZIP}" -d -o copy - anyothername - < "${in_lz}"
|
||||
if [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; then
|
||||
printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" < in > anyothername || test_failed $LINENO
|
||||
"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null
|
||||
{ [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; } ||
|
||||
test_failed $LINENO
|
||||
rm -f copy anyothername.out
|
||||
|
||||
"${LZIP}" -lq in "${in_lz}"
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -lq nx_file.lz "${in_lz}"
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq in "${in_lz}"
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -tq foo.lz "${in_lz}"
|
||||
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq nx_file.lz "${in_lz}"
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq in "${in_lz}" > copy
|
||||
if [ $? = 2 ] && cat copy in | cmp in - ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -cdq foo.lz "${in_lz}" > copy
|
||||
if [ $? = 1 ] && cmp in copy ; then printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 2 ] && cat copy in | cmp in - ; } || test_failed $LINENO
|
||||
"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy
|
||||
{ [ $? = 1 ] && cmp in copy ; } || test_failed $LINENO
|
||||
rm -f copy
|
||||
cat "${in_lz}" > copy.lz || framework_failure
|
||||
for i in 1 2 3 4 5 6 7 ; do
|
||||
printf "g" >> copy.lz || framework_failure
|
||||
"${LZIP}" -alvv copy.lz "${in_lz}" > /dev/null 2>&1
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -atvvvv copy.lz "${in_lz}" 2> /dev/null
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
done
|
||||
"${LZIP}" -dq in copy.lz
|
||||
if [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; then
|
||||
printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -dq foo.lz copy.lz
|
||||
if [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e foo ] && cmp in copy ; then
|
||||
printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; } ||
|
||||
test_failed $LINENO
|
||||
"${LZIP}" -dq nx_file.lz copy.lz
|
||||
{ [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e nx_file ] && cmp in copy ; } ||
|
||||
test_failed $LINENO
|
||||
|
||||
cat in in > in2 || framework_failure
|
||||
"${LZIP}" -o copy2 < in2 || fail=1
|
||||
"${LZIP}" -t copy2.lz || fail=1
|
||||
"${LZIP}" -cd copy2.lz > copy2 || fail=1
|
||||
cmp in2 copy2 || fail=1
|
||||
printf .
|
||||
cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure
|
||||
"${LZIP}" -lq in2.lz || test_failed $LINENO
|
||||
"${LZIP}" -t in2.lz || test_failed $LINENO
|
||||
"${LZIP}" -cd in2.lz > copy2 || test_failed $LINENO
|
||||
cmp in2 copy2 || test_failed $LINENO
|
||||
|
||||
printf "garbage" >> copy2.lz || framework_failure
|
||||
"${LZIP}" --output=copy2 < in2 || test_failed $LINENO
|
||||
"${LZIP}" -lq copy2.lz || test_failed $LINENO
|
||||
"${LZIP}" -t copy2.lz || test_failed $LINENO
|
||||
"${LZIP}" -cd copy2.lz > copy2 || test_failed $LINENO
|
||||
cmp in2 copy2 || test_failed $LINENO
|
||||
|
||||
printf "\ngarbage" >> copy2.lz || framework_failure
|
||||
"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO
|
||||
rm -f copy2
|
||||
"${LZIP}" -alq copy2.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -atq copy2.lz
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -atq < copy2.lz
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -adkq copy2.lz
|
||||
if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO
|
||||
"${LZIP}" -adkq -o copy2 < copy2.lz
|
||||
if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO
|
||||
printf "to be overwritten" > copy2 || framework_failure
|
||||
"${LZIP}" -df copy2.lz || fail=1
|
||||
cmp in2 copy2 || fail=1
|
||||
printf .
|
||||
"${LZIP}" -df copy2.lz || test_failed $LINENO
|
||||
cmp in2 copy2 || test_failed $LINENO
|
||||
|
||||
printf "\ntesting compression..."
|
||||
|
||||
"${LZIP}" -cfq "${in_lz}" > out # /dev/null is a tty on OS/2
|
||||
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -cF "${in_lz}" > out || fail=1
|
||||
"${LZIP}" -cd out | "${LZIP}" -d > copy || fail=1
|
||||
cmp in copy || fail=1
|
||||
printf .
|
||||
"${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${LZIP}" -cFvvm36 "${in_lz}" > out 2> /dev/null || test_failed $LINENO
|
||||
"${LZIP}" -cd out | "${LZIP}" -d > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
|
||||
"${LZIP}" -k -$i in || fail=1
|
||||
mv -f in.lz copy.lz || fail=1
|
||||
printf "garbage" >> copy.lz || fail=1
|
||||
"${LZIP}" -df copy.lz || fail=1
|
||||
cmp in copy || fail=1
|
||||
"${LZIP}" -k -$i in || test_failed $LINENO $i
|
||||
mv -f in.lz copy.lz || test_failed $LINENO $i
|
||||
printf "garbage" >> copy.lz || framework_failure
|
||||
"${LZIP}" -df copy.lz || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
printf .
|
||||
|
||||
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
|
||||
"${LZIP}" -c -$i in > out || fail=1
|
||||
printf "g" >> out || fail=1
|
||||
"${LZIP}" -cd out > copy || fail=1
|
||||
cmp in copy || fail=1
|
||||
"${LZIP}" -c -$i in > out || test_failed $LINENO $i
|
||||
printf "g" >> out || framework_failure
|
||||
"${LZIP}" -cd out > copy || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
printf .
|
||||
|
||||
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
|
||||
"${LZIP}" -$i < in > out || fail=1
|
||||
"${LZIP}" -d < out > copy || fail=1
|
||||
cmp in copy || fail=1
|
||||
"${LZIP}" -$i < in > out || test_failed $LINENO $i
|
||||
"${LZIP}" -d < out > copy || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
printf .
|
||||
|
||||
for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do
|
||||
"${LZIP}" -f -$i -o out < in || fail=1
|
||||
"${LZIP}" -df -o copy < out.lz || fail=1
|
||||
cmp in copy || fail=1
|
||||
"${LZIP}" -f -$i -o out < in || test_failed $LINENO $i
|
||||
"${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i
|
||||
cmp in copy || test_failed $LINENO $i
|
||||
done
|
||||
printf .
|
||||
|
||||
cat in in in in > in4 || framework_failure
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
|
||||
"${LZIP}" -c -s4Ki -B8Ki -n$i in4 > out4.lz || fail=1
|
||||
printf "g" >> out4.lz || fail=1
|
||||
"${LZIP}" -cd -n$i out4.lz > copy4 || fail=1
|
||||
cmp in4 copy4 || fail=1
|
||||
"${LZIP}" -d -n$i out4.lz || fail=1
|
||||
cmp in4 out4 || fail=1
|
||||
"${LZIP}" -c -s4Ki -B8Ki -n$i in4 > out4.lz || test_failed $LINENO $i
|
||||
printf "g" >> out4.lz || framework_failure
|
||||
"${LZIP}" -cd -n$i out4.lz > copy4 || test_failed $LINENO $i
|
||||
cmp in4 copy4 || test_failed $LINENO $i
|
||||
"${LZIP}" -d -n$i out4.lz || test_failed $LINENO $i
|
||||
cmp in4 out4 || test_failed $LINENO $i
|
||||
rm -f out4
|
||||
done
|
||||
printf .
|
||||
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
|
||||
"${LZIP}" -s4Ki -B8Ki -n$i < in4 > out4 || fail=1
|
||||
printf "g" >> out4 || fail=1
|
||||
"${LZIP}" -d -n$i < out4 > copy4 || fail=1
|
||||
cmp in4 copy4 || fail=1
|
||||
"${LZIP}" -s4Ki -B8Ki -n$i < in4 > out4 || test_failed $LINENO $i
|
||||
printf "g" >> out4 || framework_failure
|
||||
"${LZIP}" -d -n$i < out4 > copy4 || test_failed $LINENO $i
|
||||
cmp in4 copy4 || test_failed $LINENO $i
|
||||
done
|
||||
printf .
|
||||
|
||||
cat in in in in in in in in | "${LZIP}" -1s4Ki | "${LZIP}" -t ||
|
||||
test_failed $LINENO
|
||||
|
||||
printf "\ntesting bad input..."
|
||||
|
||||
cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure
|
||||
if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null &&
|
||||
[ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then
|
||||
for i in 6 20 14734 14753 14754 14755 14756 14757 14758 ; do
|
||||
dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null
|
||||
"${LZIP}" -lq trunc.lz
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -t trunc.lz 2> /dev/null
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -tq < trunc.lz
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -cdq trunc.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
"${LZIP}" -dq < trunc.lz > out
|
||||
[ $? = 2 ] || test_failed $LINENO $i
|
||||
done
|
||||
else
|
||||
printf "\nwarning: skipping truncation test: 'dd' does not work on your system."
|
||||
fi
|
||||
|
||||
cat "${in_lz}" > ingin.lz || framework_failure
|
||||
printf "g" >> ingin.lz || framework_failure
|
||||
cat "${in_lz}" >> ingin.lz || framework_failure
|
||||
"${LZIP}" -lq ingin.lz
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -tq ingin.lz
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -cdq ingin.lz > out
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -t < ingin.lz || fail=1
|
||||
"${LZIP}" -d < ingin.lz > copy || fail=1
|
||||
cmp in copy || fail=1
|
||||
printf .
|
||||
|
||||
dd if="${in_lz}" bs=1024 count=6 > trunc.lz 2> /dev/null || framework_failure
|
||||
"${LZIP}" -tq trunc.lz
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -tq < trunc.lz
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -cdq trunc.lz > out
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
"${LZIP}" -dq < trunc.lz > out
|
||||
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${LZIP}" -t < ingin.lz || test_failed $LINENO
|
||||
"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO
|
||||
cmp in copy || test_failed $LINENO
|
||||
|
||||
echo
|
||||
if [ ${fail} = 0 ] ; then
|
||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue