Adding upstream version 1.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
06af02d828
commit
af9e755a7b
16 changed files with 182 additions and 181 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,12 +1,7 @@
|
||||||
2015-05-23 Antonio Diaz Diaz <antonio@gnu.org>
|
2015-07-09 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
* Version 1.4-rc1 released.
|
* Version 1.4 released.
|
||||||
* Show default '--data-size' in '--help' output.
|
* Option '-0' now uses the fast encoder of lzlib 1.7.
|
||||||
|
|
||||||
2015-02-25 Antonio Diaz Diaz <antonio@gnu.org>
|
|
||||||
|
|
||||||
* Version 1.4-pre1 released.
|
|
||||||
* Option '-0' now uses the fast encoder of lzlib 1.7-pre1.
|
|
||||||
|
|
||||||
2015-01-22 Antonio Diaz Diaz <antonio@gnu.org>
|
2015-01-22 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
|
4
INSTALL
4
INSTALL
|
@ -3,8 +3,8 @@ Requirements
|
||||||
You will need a C++ compiler and the lzlib compression library installed.
|
You will need a C++ compiler and the lzlib compression library installed.
|
||||||
I use gcc 4.9.1 and 4.1.2, but the code should compile with any
|
I use gcc 4.9.1 and 4.1.2, but the code should compile with any
|
||||||
standards compliant compiler.
|
standards compliant compiler.
|
||||||
Lzlib must be version 1.0 or newer.
|
Lzlib must be version 1.0 or newer, but the fast encoder is only
|
||||||
The fast encoder is only available in lzlib 1.7-pre1 or newer.
|
available in lzlib 1.7 or newer.
|
||||||
Gcc is available at http://gcc.gnu.org.
|
Gcc is available at http://gcc.gnu.org.
|
||||||
Lzlib is available at http://www.nongnu.org/lzip/lzlib.html.
|
Lzlib is available at http://www.nongnu.org/lzip/lzlib.html.
|
||||||
|
|
||||||
|
|
2
NEWS
2
NEWS
|
@ -1,5 +1,5 @@
|
||||||
Changes in version 1.4:
|
Changes in version 1.4:
|
||||||
|
|
||||||
The option "-0" has been modified to use the new fast encoder of lzlib
|
The option "-0" has been modified to use the new fast encoder of lzlib
|
||||||
1.7, achieving a compression speed and ratio comparable to those of
|
1.7, which achieves a compression speed and ratio comparable to those of
|
||||||
pigz's default compression level.
|
pigz's default compression level.
|
||||||
|
|
13
compress.cc
13
compress.cc
|
@ -375,11 +375,10 @@ extern "C" void * cworker( void * arg )
|
||||||
Packet * const packet = courier.distribute_packet();
|
Packet * const packet = courier.distribute_packet();
|
||||||
if( !packet ) break; // no more packets to process
|
if( !packet ) break; // no more packets to process
|
||||||
|
|
||||||
int dict_size;
|
const bool fast = dictionary_size == 65535 && match_len_limit == 16;
|
||||||
if( dictionary_size == 65535 && match_len_limit == 16 )
|
const int dict_size = fast ? dictionary_size :
|
||||||
dict_size = dictionary_size;
|
std::max( std::min( dictionary_size, packet->size ),
|
||||||
else dict_size = std::max( LZ_min_dictionary_size(),
|
LZ_min_dictionary_size() );
|
||||||
std::min( dictionary_size, packet->size ) );
|
|
||||||
LZ_Encoder * const encoder =
|
LZ_Encoder * const encoder =
|
||||||
LZ_compress_open( dict_size, match_len_limit, LLONG_MAX );
|
LZ_compress_open( dict_size, match_len_limit, LLONG_MAX );
|
||||||
if( !encoder || LZ_compress_errno( encoder ) != LZ_ok )
|
if( !encoder || LZ_compress_errno( encoder ) != LZ_ok )
|
||||||
|
@ -413,7 +412,7 @@ extern "C" void * cworker( void * arg )
|
||||||
{
|
{
|
||||||
pp();
|
pp();
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "LZ_compress_read error: %s.\n",
|
std::fprintf( stderr, "LZ_compress_read error: %s\n",
|
||||||
LZ_strerror( LZ_compress_errno( encoder ) ) );
|
LZ_strerror( LZ_compress_errno( encoder ) ) );
|
||||||
cleanup_and_fail();
|
cleanup_and_fail();
|
||||||
}
|
}
|
||||||
|
@ -521,7 +520,7 @@ int compress( const int data_size, const int dictionary_size,
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
{
|
{
|
||||||
if( in_size == 0 || out_size == 0 )
|
if( in_size == 0 || out_size == 0 )
|
||||||
std::fprintf( stderr, " no data compressed.\n" );
|
std::fputs( " no data compressed.\n", stderr );
|
||||||
else
|
else
|
||||||
std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, "
|
std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, "
|
||||||
"%5.2f%% saved, %llu in, %llu out.\n",
|
"%5.2f%% saved, %llu in, %llu out.\n",
|
||||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -6,7 +6,7 @@
|
||||||
# to copy, distribute and modify it.
|
# to copy, distribute and modify it.
|
||||||
|
|
||||||
pkgname=plzip
|
pkgname=plzip
|
||||||
pkgversion=1.4-rc1
|
pkgversion=1.4
|
||||||
progname=plzip
|
progname=plzip
|
||||||
srctrigger=doc/${pkgname}.texi
|
srctrigger=doc/${pkgname}.texi
|
||||||
|
|
||||||
|
|
|
@ -309,7 +309,7 @@ int dec_stdout( const int num_workers, const int infd, const int outfd,
|
||||||
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
||||||
out_size, in_size );
|
out_size, in_size );
|
||||||
|
|
||||||
if( verbosity >= 1 ) std::fprintf( stderr, "done\n" );
|
if( verbosity >= 1 ) std::fputs( "done\n", stderr );
|
||||||
|
|
||||||
if( debug_level & 1 )
|
if( debug_level & 1 )
|
||||||
std::fprintf( stderr,
|
std::fprintf( stderr,
|
||||||
|
|
|
@ -520,7 +520,7 @@ int dec_stream( const int num_workers, const int infd, const int outfd,
|
||||||
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
||||||
out_size, in_size );
|
out_size, in_size );
|
||||||
|
|
||||||
if( verbosity >= 1 ) std::fprintf( stderr, (outfd < 0) ? "ok\n" : "done\n" );
|
if( verbosity >= 1 ) std::fputs( (outfd < 0) ? "ok\n" : "done\n", stderr );
|
||||||
|
|
||||||
if( debug_level & 1 )
|
if( debug_level & 1 )
|
||||||
std::fprintf( stderr,
|
std::fprintf( stderr,
|
||||||
|
|
|
@ -37,6 +37,23 @@
|
||||||
#include "file_index.h"
|
#include "file_index.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Pretty_print::operator()( const char * const msg ) const
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
{
|
||||||
|
if( first_post )
|
||||||
|
{
|
||||||
|
first_post = false;
|
||||||
|
std::fprintf( stderr, " %s: ", name_.c_str() );
|
||||||
|
for( unsigned i = 0; i < longest_name - name_.size(); ++i )
|
||||||
|
std::fputc( ' ', stderr );
|
||||||
|
if( !msg ) std::fflush( stderr );
|
||||||
|
}
|
||||||
|
if( msg ) std::fprintf( stderr, "%s\n", msg );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns the number of bytes really read.
|
// Returns the number of bytes really read.
|
||||||
// If (returned value < size) and (errno == 0), means EOF was reached.
|
// If (returned value < size) and (errno == 0), means EOF was reached.
|
||||||
//
|
//
|
||||||
|
@ -82,7 +99,7 @@ int decompress_read_error( struct LZ_Decoder * const decoder,
|
||||||
const LZ_Errno errcode = LZ_decompress_errno( decoder );
|
const LZ_Errno errcode = LZ_decompress_errno( decoder );
|
||||||
pp();
|
pp();
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "LZ_decompress_read error in worker %d: %s.\n",
|
std::fprintf( stderr, "LZ_decompress_read error in worker %d: %s\n",
|
||||||
worker_id, LZ_strerror( errcode ) );
|
worker_id, LZ_strerror( errcode ) );
|
||||||
if( errcode == LZ_header_error || errcode == LZ_unexpected_eof ||
|
if( errcode == LZ_header_error || errcode == LZ_unexpected_eof ||
|
||||||
errcode == LZ_data_error )
|
errcode == LZ_data_error )
|
||||||
|
@ -160,7 +177,7 @@ extern "C" void * dworker( void * arg )
|
||||||
{
|
{
|
||||||
pp();
|
pp();
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "Write error in worker %d: %s.\n",
|
std::fprintf( stderr, "Write error in worker %d: %s\n",
|
||||||
worker_id, std::strerror( errno ) );
|
worker_id, std::strerror( errno ) );
|
||||||
cleanup_and_fail();
|
cleanup_and_fail();
|
||||||
}
|
}
|
||||||
|
@ -260,7 +277,7 @@ int decompress( int num_workers, const int infd, const int outfd,
|
||||||
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
std::fprintf( stderr, "decompressed size %9llu, size %9llu. ",
|
||||||
out_size, in_size );
|
out_size, in_size );
|
||||||
|
|
||||||
if( verbosity >= 1 ) std::fprintf( stderr, (outfd < 0) ? "ok\n" : "done\n" );
|
if( verbosity >= 1 ) std::fputs( (outfd < 0) ? "ok\n" : "done\n", stderr );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
|
||||||
.TH PLZIP "1" "May 2015" "plzip 1.4-rc1" "User Commands"
|
.TH PLZIP "1" "July 2015" "plzip 1.4" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
plzip \- reduces the size of files
|
plzip \- reduces the size of files
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -28,7 +28,7 @@ decompress
|
||||||
overwrite existing output files
|
overwrite existing output files
|
||||||
.TP
|
.TP
|
||||||
\fB\-F\fR, \fB\-\-recompress\fR
|
\fB\-F\fR, \fB\-\-recompress\fR
|
||||||
force recompression of compressed files
|
force re\-compression of compressed files
|
||||||
.TP
|
.TP
|
||||||
\fB\-k\fR, \fB\-\-keep\fR
|
\fB\-k\fR, \fB\-\-keep\fR
|
||||||
keep (don't delete) input files
|
keep (don't delete) input files
|
||||||
|
@ -84,7 +84,7 @@ Plzip home page: http://www.nongnu.org/lzip/plzip.html
|
||||||
Copyright \(co 2009 Laszlo Ersek.
|
Copyright \(co 2009 Laszlo Ersek.
|
||||||
.br
|
.br
|
||||||
Copyright \(co 2015 Antonio Diaz Diaz.
|
Copyright \(co 2015 Antonio Diaz Diaz.
|
||||||
Using Lzlib 1.7\-rc1
|
Using lzlib 1.7
|
||||||
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv2+: GNU GPL version 2 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.
|
||||||
|
|
112
doc/plzip.info
112
doc/plzip.info
|
@ -11,13 +11,13 @@ File: plzip.info, Node: Top, Next: Introduction, Up: (dir)
|
||||||
Plzip Manual
|
Plzip Manual
|
||||||
************
|
************
|
||||||
|
|
||||||
This manual is for Plzip (version 1.4-rc1, 23 May 2015).
|
This manual is for Plzip (version 1.4, 9 July 2015).
|
||||||
|
|
||||||
* Menu:
|
* Menu:
|
||||||
|
|
||||||
* Introduction:: Purpose and features of plzip
|
* Introduction:: Purpose and features of plzip
|
||||||
* Program design:: Internal structure of plzip
|
|
||||||
* Invoking plzip:: Command line interface
|
* Invoking plzip:: Command line interface
|
||||||
|
* Program design:: Internal structure of plzip
|
||||||
* File format:: Detailed format of the compressed file
|
* File format:: Detailed format of the compressed file
|
||||||
* Memory requirements:: Memory required to compress and decompress
|
* Memory requirements:: Memory required to compress and decompress
|
||||||
* Minimum file sizes:: Minimum file sizes required for full speed
|
* Minimum file sizes:: Minimum file sizes required for full speed
|
||||||
|
@ -31,7 +31,7 @@ This manual is for Plzip (version 1.4-rc1, 23 May 2015).
|
||||||
copy, distribute and modify it.
|
copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Introduction, Next: Program design, Prev: Top, Up: Top
|
File: plzip.info, Node: Introduction, Next: Invoking plzip, Prev: Top, Up: Top
|
||||||
|
|
||||||
1 Introduction
|
1 Introduction
|
||||||
**************
|
**************
|
||||||
|
@ -59,7 +59,8 @@ availability:
|
||||||
recovery means. The lziprecover program can repair bit-flip errors
|
recovery means. The lziprecover program can repair bit-flip errors
|
||||||
(one of the most common forms of data corruption) in lzip files,
|
(one of the most common forms of data corruption) in lzip files,
|
||||||
and provides data recovery capabilities, including error-checked
|
and provides data recovery capabilities, including error-checked
|
||||||
merging of damaged copies of a file.
|
merging of damaged copies of a file. *note Data safety:
|
||||||
|
(lziprecover)Data safety.
|
||||||
|
|
||||||
* The lzip format is as simple as possible (but not simpler). The
|
* The lzip format is as simple as possible (but not simpler). The
|
||||||
lzip manual provides the code of a simple decompressor along with
|
lzip manual provides the code of a simple decompressor along with
|
||||||
|
@ -122,43 +123,9 @@ until you verify the compressed file with a command like
|
||||||
'plzip -cd file.lz | cmp file -'.
|
'plzip -cd file.lz | cmp file -'.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Program design, Next: Invoking plzip, Prev: Introduction, Up: Top
|
File: plzip.info, Node: Invoking plzip, Next: Program design, Prev: Introduction, Up: Top
|
||||||
|
|
||||||
2 Program design
|
2 Invoking plzip
|
||||||
****************
|
|
||||||
|
|
||||||
When compressing, plzip divides the input file into chunks and
|
|
||||||
compresses as many chunks simultaneously as worker threads are chosen,
|
|
||||||
creating a multi-member compressed file.
|
|
||||||
|
|
||||||
When decompressing, plzip decompresses as many members
|
|
||||||
simultaneously as worker threads are chosen. Files that were compressed
|
|
||||||
with lzip will not be decompressed faster than using lzip (unless the
|
|
||||||
'-b' option was used) because lzip usually produces single-member
|
|
||||||
files, which can't be decompressed in parallel.
|
|
||||||
|
|
||||||
For each input file, a splitter thread and several worker threads are
|
|
||||||
created, acting the main thread as muxer (multiplexer) thread. A "packet
|
|
||||||
courier" takes care of data transfers among threads and limits the
|
|
||||||
maximum number of data blocks (packets) being processed simultaneously.
|
|
||||||
|
|
||||||
The splitter reads data blocks from the input file, and distributes
|
|
||||||
them to the workers. The workers (de)compress the blocks received from
|
|
||||||
the splitter. The muxer collects processed packets from the workers, and
|
|
||||||
writes them to the output file.
|
|
||||||
|
|
||||||
When decompressing from a regular file, the splitter is removed and
|
|
||||||
the workers read directly from the input file. If the output file is
|
|
||||||
also a regular file, the muxer is also removed and the workers write
|
|
||||||
directly to the output file. With these optimizations, the use of RAM
|
|
||||||
is greatly reduced and the decompression speed of large files with many
|
|
||||||
members is only limited by the number of processors available and by
|
|
||||||
I/O speed.
|
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Invoking plzip, Next: File format, Prev: Program design, Up: Top
|
|
||||||
|
|
||||||
3 Invoking plzip
|
|
||||||
****************
|
****************
|
||||||
|
|
||||||
The format for running plzip is:
|
The format for running plzip is:
|
||||||
|
@ -199,7 +166,7 @@ The format for running plzip is:
|
||||||
|
|
||||||
'-F'
|
'-F'
|
||||||
'--recompress'
|
'--recompress'
|
||||||
Force recompression of files whose name already has the '.lz' or
|
Force re-compression of files whose name already has the '.lz' or
|
||||||
'.tlz' suffix.
|
'.tlz' suffix.
|
||||||
|
|
||||||
'-k'
|
'-k'
|
||||||
|
@ -318,7 +285,41 @@ invalid input file, 3 for an internal consistency error (eg, bug) which
|
||||||
caused plzip to panic.
|
caused plzip to panic.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: File format, Next: Memory requirements, Prev: Invoking plzip, Up: Top
|
File: plzip.info, Node: Program design, Next: File format, Prev: Invoking plzip, Up: Top
|
||||||
|
|
||||||
|
3 Program design
|
||||||
|
****************
|
||||||
|
|
||||||
|
When compressing, plzip divides the input file into chunks and
|
||||||
|
compresses as many chunks simultaneously as worker threads are chosen,
|
||||||
|
creating a multi-member compressed file.
|
||||||
|
|
||||||
|
When decompressing, plzip decompresses as many members
|
||||||
|
simultaneously as worker threads are chosen. Files that were compressed
|
||||||
|
with lzip will not be decompressed faster than using lzip (unless the
|
||||||
|
'-b' option was used) because lzip usually produces single-member
|
||||||
|
files, which can't be decompressed in parallel.
|
||||||
|
|
||||||
|
For each input file, a splitter thread and several worker threads are
|
||||||
|
created, acting the main thread as muxer (multiplexer) thread. A "packet
|
||||||
|
courier" takes care of data transfers among threads and limits the
|
||||||
|
maximum number of data blocks (packets) being processed simultaneously.
|
||||||
|
|
||||||
|
The splitter reads data blocks from the input file, and distributes
|
||||||
|
them to the workers. The workers (de)compress the blocks received from
|
||||||
|
the splitter. The muxer collects processed packets from the workers, and
|
||||||
|
writes them to the output file.
|
||||||
|
|
||||||
|
When decompressing from a regular file, the splitter is removed and
|
||||||
|
the workers read directly from the input file. If the output file is
|
||||||
|
also a regular file, the muxer is also removed and the workers write
|
||||||
|
directly to the output file. With these optimizations, the use of RAM
|
||||||
|
is greatly reduced and the decompression speed of large files with many
|
||||||
|
members is only limited by the number of processors available and by
|
||||||
|
I/O speed.
|
||||||
|
|
||||||
|
|
||||||
|
File: plzip.info, Node: File format, Next: Memory requirements, Prev: Program design, Up: Top
|
||||||
|
|
||||||
4 File format
|
4 File format
|
||||||
*************
|
*************
|
||||||
|
@ -398,15 +399,16 @@ The amount of memory required *per thread* is approximately the
|
||||||
following:
|
following:
|
||||||
|
|
||||||
* For compression at level -0; 1.5 MiB plus 3 times the data size
|
* For compression at level -0; 1.5 MiB plus 3 times the data size
|
||||||
(*note --data-size::). About 4.5 MiB.
|
(*note --data-size::). Default is 4.5 MiB.
|
||||||
|
|
||||||
* For compression at other levels; 11 times the dictionary size plus
|
* For compression at other levels; 11 times the dictionary size plus
|
||||||
3 times the data size. Default is 136 MiB.
|
3 times the data size. Default is 136 MiB.
|
||||||
|
|
||||||
* For decompression of a regular (seekable) file to another regular
|
* For decompression of a regular (seekable) file to another regular
|
||||||
file, or for testing of a regular file; the dictionary size. Note
|
file, or for testing of a regular file; the dictionary size.
|
||||||
that regular files with more than 1024 bytes of trailing garbage
|
|
||||||
are treated as non-seekable.
|
(Note that regular files with more than 1024 bytes of trailing
|
||||||
|
garbage are treated as non-seekable).
|
||||||
|
|
||||||
* For testing of a non-seekable file or of standard input; the
|
* For testing of a non-seekable file or of standard input; the
|
||||||
dictionary size plus up to 5 MiB.
|
dictionary size plus up to 5 MiB.
|
||||||
|
@ -493,15 +495,15 @@ Concept index
|
||||||
|
|
||||||
Tag Table:
|
Tag Table:
|
||||||
Node: Top221
|
Node: Top221
|
||||||
Node: Introduction988
|
Node: Introduction984
|
||||||
Node: Program design5285
|
Node: Invoking plzip5332
|
||||||
Node: Invoking plzip6874
|
Ref: --data-size5747
|
||||||
Ref: --data-size7288
|
Node: Program design10972
|
||||||
Node: File format12512
|
Node: File format12560
|
||||||
Node: Memory requirements14925
|
Node: Memory requirements14973
|
||||||
Node: Minimum file sizes16029
|
Node: Minimum file sizes16085
|
||||||
Node: Problems17951
|
Node: Problems18007
|
||||||
Node: Concept index18487
|
Node: Concept index18543
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
@finalout
|
@finalout
|
||||||
@c %**end of header
|
@c %**end of header
|
||||||
|
|
||||||
@set UPDATED 23 May 2015
|
@set UPDATED 9 July 2015
|
||||||
@set VERSION 1.4-rc1
|
@set VERSION 1.4
|
||||||
|
|
||||||
@dircategory Data Compression
|
@dircategory Data Compression
|
||||||
@direntry
|
@direntry
|
||||||
|
@ -36,8 +36,8 @@ This manual is for Plzip (version @value{VERSION}, @value{UPDATED}).
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Introduction:: Purpose and features of plzip
|
* Introduction:: Purpose and features of plzip
|
||||||
* Program design:: Internal structure of plzip
|
|
||||||
* Invoking plzip:: Command line interface
|
* Invoking plzip:: Command line interface
|
||||||
|
* Program design:: Internal structure of plzip
|
||||||
* File format:: Detailed format of the compressed file
|
* File format:: Detailed format of the compressed file
|
||||||
* Memory requirements:: Memory required to compress and decompress
|
* Memory requirements:: Memory required to compress and decompress
|
||||||
* Minimum file sizes:: Minimum file sizes required for full speed
|
* Minimum file sizes:: Minimum file sizes required for full speed
|
||||||
|
@ -77,10 +77,14 @@ availability:
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
The lzip format provides very safe integrity checking and some data
|
The lzip format provides very safe integrity checking and some data
|
||||||
recovery means. The lziprecover program can repair bit-flip errors (one
|
recovery means. The
|
||||||
of the most common forms of data corruption) in lzip files, and provides
|
@uref{http://www.nongnu.org/lzip/manual/lziprecover_manual.html#Data-safety,,lziprecover}
|
||||||
data recovery capabilities, including error-checked merging of damaged
|
program can repair bit-flip errors (one of the most common forms of data
|
||||||
copies of a file.
|
corruption) in lzip files, and provides data recovery capabilities,
|
||||||
|
including error-checked merging of damaged copies of a file.
|
||||||
|
@ifnothtml
|
||||||
|
@ref{Data safety,,,lziprecover}.
|
||||||
|
@end ifnothtml
|
||||||
|
|
||||||
@item
|
@item
|
||||||
The lzip format is as simple as possible (but not simpler). The lzip
|
The lzip format is as simple as possible (but not simpler). The lzip
|
||||||
|
@ -148,38 +152,6 @@ you verify the compressed file with a command like
|
||||||
@w{@samp{plzip -cd file.lz | cmp file -}}.
|
@w{@samp{plzip -cd file.lz | cmp file -}}.
|
||||||
|
|
||||||
|
|
||||||
@node Program design
|
|
||||||
@chapter Program design
|
|
||||||
@cindex program design
|
|
||||||
|
|
||||||
When compressing, plzip divides the input file into chunks and
|
|
||||||
compresses as many chunks simultaneously as worker threads are chosen,
|
|
||||||
creating a multi-member compressed file.
|
|
||||||
|
|
||||||
When decompressing, plzip decompresses as many members simultaneously as
|
|
||||||
worker threads are chosen. Files that were compressed with lzip will not
|
|
||||||
be decompressed faster than using lzip (unless the @samp{-b} option was
|
|
||||||
used) because lzip usually produces single-member files, which can't be
|
|
||||||
decompressed in parallel.
|
|
||||||
|
|
||||||
For each input file, a splitter thread and several worker threads are
|
|
||||||
created, acting the main thread as muxer (multiplexer) thread. A "packet
|
|
||||||
courier" takes care of data transfers among threads and limits the
|
|
||||||
maximum number of data blocks (packets) being processed simultaneously.
|
|
||||||
|
|
||||||
The splitter reads data blocks from the input file, and distributes them
|
|
||||||
to the workers. The workers (de)compress the blocks received from the
|
|
||||||
splitter. The muxer collects processed packets from the workers, and
|
|
||||||
writes them to the output file.
|
|
||||||
|
|
||||||
When decompressing from a regular file, the splitter is removed and the
|
|
||||||
workers read directly from the input file. If the output file is also a
|
|
||||||
regular file, the muxer is also removed and the workers write directly
|
|
||||||
to the output file. With these optimizations, the use of RAM is greatly
|
|
||||||
reduced and the decompression speed of large files with many members is
|
|
||||||
only limited by the number of processors available and by I/O speed.
|
|
||||||
|
|
||||||
|
|
||||||
@node Invoking plzip
|
@node Invoking plzip
|
||||||
@chapter Invoking plzip
|
@chapter Invoking plzip
|
||||||
@cindex invoking
|
@cindex invoking
|
||||||
|
@ -229,7 +201,7 @@ Force overwrite of output files.
|
||||||
|
|
||||||
@item -F
|
@item -F
|
||||||
@itemx --recompress
|
@itemx --recompress
|
||||||
Force recompression of files whose name already has the @samp{.lz} or
|
Force re-compression of files whose name already has the @samp{.lz} or
|
||||||
@samp{.tlz} suffix.
|
@samp{.tlz} suffix.
|
||||||
|
|
||||||
@item -k
|
@item -k
|
||||||
|
@ -346,6 +318,38 @@ invalid input file, 3 for an internal consistency error (eg, bug) which
|
||||||
caused plzip to panic.
|
caused plzip to panic.
|
||||||
|
|
||||||
|
|
||||||
|
@node Program design
|
||||||
|
@chapter Program design
|
||||||
|
@cindex program design
|
||||||
|
|
||||||
|
When compressing, plzip divides the input file into chunks and
|
||||||
|
compresses as many chunks simultaneously as worker threads are chosen,
|
||||||
|
creating a multi-member compressed file.
|
||||||
|
|
||||||
|
When decompressing, plzip decompresses as many members simultaneously as
|
||||||
|
worker threads are chosen. Files that were compressed with lzip will not
|
||||||
|
be decompressed faster than using lzip (unless the @samp{-b} option was
|
||||||
|
used) because lzip usually produces single-member files, which can't be
|
||||||
|
decompressed in parallel.
|
||||||
|
|
||||||
|
For each input file, a splitter thread and several worker threads are
|
||||||
|
created, acting the main thread as muxer (multiplexer) thread. A "packet
|
||||||
|
courier" takes care of data transfers among threads and limits the
|
||||||
|
maximum number of data blocks (packets) being processed simultaneously.
|
||||||
|
|
||||||
|
The splitter reads data blocks from the input file, and distributes them
|
||||||
|
to the workers. The workers (de)compress the blocks received from the
|
||||||
|
splitter. The muxer collects processed packets from the workers, and
|
||||||
|
writes them to the output file.
|
||||||
|
|
||||||
|
When decompressing from a regular file, the splitter is removed and the
|
||||||
|
workers read directly from the input file. If the output file is also a
|
||||||
|
regular file, the muxer is also removed and the workers write directly
|
||||||
|
to the output file. With these optimizations, the use of RAM is greatly
|
||||||
|
reduced and the decompression speed of large files with many members is
|
||||||
|
only limited by the number of processors available and by I/O speed.
|
||||||
|
|
||||||
|
|
||||||
@node File format
|
@node File format
|
||||||
@chapter File format
|
@chapter File format
|
||||||
@cindex file format
|
@cindex file format
|
||||||
|
@ -439,7 +443,7 @@ following:
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
For compression at level -0; 1.5 MiB plus 3 times the data size
|
For compression at level -0; 1.5 MiB plus 3 times the data size
|
||||||
(@pxref{--data-size}). About 4.5 MiB.
|
(@pxref{--data-size}). Default is 4.5 MiB.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
For compression at other levels; 11 times the dictionary size plus 3
|
For compression at other levels; 11 times the dictionary size plus 3
|
||||||
|
@ -447,9 +451,10 @@ times the data size. Default is 136 MiB.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
For decompression of a regular (seekable) file to another regular file,
|
For decompression of a regular (seekable) file to another regular file,
|
||||||
or for testing of a regular file; the dictionary size. Note that regular
|
or for testing of a regular file; the dictionary size.
|
||||||
files with more than 1024 bytes of trailing garbage are treated as
|
|
||||||
non-seekable.
|
(Note that regular files with more than 1024 bytes of trailing garbage
|
||||||
|
are treated as non-seekable).
|
||||||
|
|
||||||
@item
|
@item
|
||||||
For testing of a non-seekable file or of standard input; the dictionary
|
For testing of a non-seekable file or of standard input; the dictionary
|
||||||
|
|
|
@ -40,7 +40,7 @@ int seek_read( const int fd, uint8_t * const buf, const int size,
|
||||||
|
|
||||||
void File_index::set_errno_error( const char * const msg )
|
void File_index::set_errno_error( const char * const msg )
|
||||||
{
|
{
|
||||||
error_ = msg; error_ += std::strerror( errno ); error_ += '.';
|
error_ = msg; error_ += std::strerror( errno );
|
||||||
retval_ = 1;
|
retval_ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ class File_index
|
||||||
|
|
||||||
void set_errno_error( const char * const msg );
|
void set_errno_error( const char * const msg );
|
||||||
void set_num_error( const char * const msg1, unsigned long long num,
|
void set_num_error( const char * const msg1, unsigned long long num,
|
||||||
const char * const msg2 = "." );
|
const char * const msg2 = "" );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit File_index( const int infd );
|
explicit File_index( const int infd );
|
||||||
|
|
12
lzip.h
12
lzip.h
|
@ -69,9 +69,9 @@ const uint8_t magic_string[4] = { 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP"
|
||||||
|
|
||||||
struct File_header
|
struct File_header
|
||||||
{
|
{
|
||||||
uint8_t data[6]; /* 0-3 magic bytes */
|
uint8_t data[6]; // 0-3 magic bytes
|
||||||
/* 4 version */
|
// 4 version
|
||||||
/* 5 coded_dict_size */
|
// 5 coded_dict_size
|
||||||
enum { size = 6 };
|
enum { size = 6 };
|
||||||
|
|
||||||
void set_magic() { std::memcpy( data, magic_string, 4 ); data[4] = 1; }
|
void set_magic() { std::memcpy( data, magic_string, 4 ); data[4] = 1; }
|
||||||
|
@ -111,9 +111,9 @@ struct File_header
|
||||||
|
|
||||||
struct File_trailer
|
struct File_trailer
|
||||||
{
|
{
|
||||||
uint8_t data[20]; /* 0-3 CRC32 of the uncompressed data */
|
uint8_t data[20]; // 0-3 CRC32 of the uncompressed data
|
||||||
/* 4-11 size of the uncompressed data */
|
// 4-11 size of the uncompressed data
|
||||||
/* 12-19 member size including header and trailer */
|
// 12-19 member size including header and trailer
|
||||||
|
|
||||||
enum { size = 20 };
|
enum { size = 20 };
|
||||||
|
|
||||||
|
|
76
main.cc
76
main.cc
|
@ -82,8 +82,8 @@ struct { const char * from; const char * to; } const known_extensions[] = {
|
||||||
|
|
||||||
struct Lzma_options
|
struct Lzma_options
|
||||||
{
|
{
|
||||||
int dictionary_size; /* 4 KiB .. 512 MiB */
|
int dictionary_size; // 4 KiB .. 512 MiB
|
||||||
int match_len_limit; /* 5 .. 273 */
|
int match_len_limit; // 5 .. 273
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Mode { m_compress, m_decompress, m_test };
|
enum Mode { m_compress, m_decompress, m_test };
|
||||||
|
@ -107,7 +107,7 @@ void show_help( const long num_online )
|
||||||
" -c, --stdout send output to standard output\n"
|
" -c, --stdout send output to standard output\n"
|
||||||
" -d, --decompress decompress\n"
|
" -d, --decompress decompress\n"
|
||||||
" -f, --force overwrite existing output files\n"
|
" -f, --force overwrite existing output files\n"
|
||||||
" -F, --recompress force recompression of compressed files\n"
|
" -F, --recompress force re-compression of compressed files\n"
|
||||||
" -k, --keep keep (don't delete) input files\n"
|
" -k, --keep keep (don't delete) input files\n"
|
||||||
" -m, --match-length=<bytes> set match length limit in bytes [36]\n"
|
" -m, --match-length=<bytes> set match length limit in bytes [36]\n"
|
||||||
" -n, --threads=<n> set number of (de)compression threads [%ld]\n"
|
" -n, --threads=<n> set number of (de)compression threads [%ld]\n"
|
||||||
|
@ -145,7 +145,7 @@ void show_version()
|
||||||
std::printf( "%s %s\n", program_name, PROGVERSION );
|
std::printf( "%s %s\n", program_name, PROGVERSION );
|
||||||
std::printf( "Copyright (C) 2009 Laszlo Ersek.\n"
|
std::printf( "Copyright (C) 2009 Laszlo Ersek.\n"
|
||||||
"Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
"Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
||||||
std::printf( "Using Lzlib %s\n", LZ_version() );
|
std::printf( "Using lzlib %s\n", LZ_version() );
|
||||||
std::printf( "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
|
std::printf( "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
|
||||||
"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"
|
||||||
"There is NO WARRANTY, to the extent permitted by law.\n" );
|
"There is NO WARRANTY, to the extent permitted by law.\n" );
|
||||||
|
@ -189,7 +189,7 @@ unsigned long long getnum( const char * const ptr,
|
||||||
|
|
||||||
if( !errno && tail[0] )
|
if( !errno && tail[0] )
|
||||||
{
|
{
|
||||||
int factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
const int factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
||||||
int exponent = 0;
|
int exponent = 0;
|
||||||
bool bad_multiplier = false;
|
bool bad_multiplier = false;
|
||||||
switch( tail[0] )
|
switch( tail[0] )
|
||||||
|
@ -273,7 +273,7 @@ int open_instream( const char * const name, struct stat * const in_statsp,
|
||||||
if( infd < 0 )
|
if( infd < 0 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't open input file '%s': %s.\n",
|
std::fprintf( stderr, "%s: Can't open input file '%s': %s\n",
|
||||||
program_name, name, std::strerror( errno ) );
|
program_name, name, std::strerror( errno ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -290,7 +290,7 @@ int open_instream( const char * const name, struct stat * const in_statsp,
|
||||||
std::fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
|
std::fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
|
||||||
program_name, name,
|
program_name, name,
|
||||||
( can_read && !no_ofile ) ?
|
( can_read && !no_ofile ) ?
|
||||||
" and '--stdout' was not specified" : "" );
|
",\n and '--stdout' was not specified" : "" );
|
||||||
close( infd );
|
close( infd );
|
||||||
infd = -1;
|
infd = -1;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ void set_d_outname( const std::string & name, const int i )
|
||||||
}
|
}
|
||||||
output_filename = name; output_filename += ".out";
|
output_filename = name; output_filename += ".out";
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
std::fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n",
|
std::fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n",
|
||||||
program_name, name.c_str(), output_filename.c_str() );
|
program_name, name.c_str(), output_filename.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ bool open_outstream( const bool force )
|
||||||
std::fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
|
std::fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
|
||||||
program_name, output_filename.c_str() );
|
program_name, output_filename.c_str() );
|
||||||
else
|
else
|
||||||
std::fprintf( stderr, "%s: Can't create output file '%s': %s.\n",
|
std::fprintf( stderr, "%s: Can't create output file '%s': %s\n",
|
||||||
program_name, output_filename.c_str(), std::strerror( errno ) );
|
program_name, output_filename.c_str(), std::strerror( errno ) );
|
||||||
}
|
}
|
||||||
return ( outfd >= 0 );
|
return ( outfd >= 0 );
|
||||||
|
@ -388,14 +388,14 @@ void cleanup_and_fail( const int retval )
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* Set permissions, owner and times. */
|
// Set permissions, owner and times.
|
||||||
void close_and_set_permissions( const struct stat * const in_statsp )
|
void close_and_set_permissions( const struct stat * const in_statsp )
|
||||||
{
|
{
|
||||||
bool warning = false;
|
bool warning = false;
|
||||||
if( in_statsp )
|
if( in_statsp )
|
||||||
{
|
{
|
||||||
const mode_t mode = in_statsp->st_mode;
|
const mode_t mode = in_statsp->st_mode;
|
||||||
/* fchown will in many cases return with EPERM, which can be safely ignored. */
|
// 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 )
|
||||||
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
|
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
|
||||||
else
|
else
|
||||||
|
@ -438,23 +438,6 @@ void set_signals()
|
||||||
int verbosity = 0;
|
int verbosity = 0;
|
||||||
|
|
||||||
|
|
||||||
void Pretty_print::operator()( const char * const msg ) const
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
{
|
|
||||||
if( first_post )
|
|
||||||
{
|
|
||||||
first_post = false;
|
|
||||||
std::fprintf( stderr, " %s: ", name_.c_str() );
|
|
||||||
for( unsigned i = 0; i < longest_name - name_.size(); ++i )
|
|
||||||
std::fprintf( stderr, " " );
|
|
||||||
if( !msg ) std::fflush( stderr );
|
|
||||||
}
|
|
||||||
if( msg ) std::fprintf( stderr, "%s\n", msg );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
|
@ -463,8 +446,8 @@ void show_error( const char * const msg, const int errcode, const bool help )
|
||||||
{
|
{
|
||||||
std::fprintf( stderr, "%s: %s", program_name, msg );
|
std::fprintf( stderr, "%s: %s", program_name, msg );
|
||||||
if( errcode > 0 )
|
if( errcode > 0 )
|
||||||
std::fprintf( stderr, ": %s.", std::strerror( errcode ) );
|
std::fprintf( stderr, ": %s", std::strerror( errcode ) );
|
||||||
std::fprintf( stderr, "\n" );
|
std::fputc( '\n', stderr );
|
||||||
}
|
}
|
||||||
if( help )
|
if( help )
|
||||||
std::fprintf( stderr, "Try '%s --help' for more information.\n",
|
std::fprintf( stderr, "Try '%s --help' for more information.\n",
|
||||||
|
@ -485,7 +468,7 @@ void show_progress( const int packet_size,
|
||||||
const Pretty_print * const p,
|
const Pretty_print * const p,
|
||||||
const unsigned long long cfile_size )
|
const unsigned long long cfile_size )
|
||||||
{
|
{
|
||||||
static unsigned long long csize = 0; /* file_size / 100 */
|
static unsigned long long csize = 0; // file_size / 100
|
||||||
static unsigned long long pos = 0;
|
static unsigned long long pos = 0;
|
||||||
static const Pretty_print * pp = 0;
|
static const Pretty_print * pp = 0;
|
||||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
@ -514,16 +497,16 @@ int main( const int argc, const char * const argv[] )
|
||||||
to the corresponding LZMA compression modes. */
|
to the corresponding LZMA compression modes. */
|
||||||
const Lzma_options option_mapping[] =
|
const Lzma_options option_mapping[] =
|
||||||
{
|
{
|
||||||
{ 65535, 16 }, /* -0 */
|
{ 65535, 16 }, // -0
|
||||||
{ 1 << 20, 5 }, /* -1 */
|
{ 1 << 20, 5 }, // -1
|
||||||
{ 3 << 19, 6 }, /* -2 */
|
{ 3 << 19, 6 }, // -2
|
||||||
{ 1 << 21, 8 }, /* -3 */
|
{ 1 << 21, 8 }, // -3
|
||||||
{ 3 << 20, 12 }, /* -4 */
|
{ 3 << 20, 12 }, // -4
|
||||||
{ 1 << 22, 20 }, /* -5 */
|
{ 1 << 22, 20 }, // -5
|
||||||
{ 1 << 23, 36 }, /* -6 */
|
{ 1 << 23, 36 }, // -6
|
||||||
{ 1 << 24, 68 }, /* -7 */
|
{ 1 << 24, 68 }, // -7
|
||||||
{ 3 << 23, 132 }, /* -8 */
|
{ 3 << 23, 132 }, // -8
|
||||||
{ 1 << 25, 273 } }; /* -9 */
|
{ 1 << 25, 273 } }; // -9
|
||||||
Lzma_options encoder_options = option_mapping[6]; // default = "-6"
|
Lzma_options encoder_options = option_mapping[6]; // default = "-6"
|
||||||
std::string input_filename;
|
std::string input_filename;
|
||||||
std::string default_output_filename;
|
std::string default_output_filename;
|
||||||
|
@ -587,7 +570,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
for( ; argind < parser.arguments(); ++argind )
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
{
|
{
|
||||||
const int code = parser.code( argind );
|
const int code = parser.code( argind );
|
||||||
if( !code ) break; /* no more options */
|
if( !code ) break; // no more options
|
||||||
const std::string & arg = parser.argument( argind );
|
const std::string & arg = parser.argument( argind );
|
||||||
switch( code )
|
switch( code )
|
||||||
{
|
{
|
||||||
|
@ -618,7 +601,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
case 'V': show_version(); return 0;
|
case 'V': show_version(); return 0;
|
||||||
default : internal_error( "uncaught option." );
|
default : internal_error( "uncaught option." );
|
||||||
}
|
}
|
||||||
} /* end process options */
|
} // end process options
|
||||||
|
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
setmode( STDIN_FILENO, O_BINARY );
|
setmode( STDIN_FILENO, O_BINARY );
|
||||||
|
@ -628,13 +611,14 @@ int main( const int argc, const char * const argv[] )
|
||||||
if( program_mode == m_test )
|
if( program_mode == m_test )
|
||||||
outfd = -1;
|
outfd = -1;
|
||||||
|
|
||||||
|
const bool fast = encoder_options.dictionary_size == 65535 &&
|
||||||
|
encoder_options.match_len_limit == 16;
|
||||||
if( data_size <= 0 )
|
if( data_size <= 0 )
|
||||||
{
|
{
|
||||||
if( encoder_options.dictionary_size == 65535 &&
|
if( fast ) data_size = 1 << 20;
|
||||||
encoder_options.match_len_limit == 16 ) data_size = 1 << 20;
|
|
||||||
else data_size = 2 * std::max( 65536, encoder_options.dictionary_size );
|
else data_size = 2 * std::max( 65536, encoder_options.dictionary_size );
|
||||||
}
|
}
|
||||||
else if( data_size < encoder_options.dictionary_size )
|
else if( !fast && data_size < encoder_options.dictionary_size )
|
||||||
encoder_options.dictionary_size =
|
encoder_options.dictionary_size =
|
||||||
std::max( data_size, LZ_min_dictionary_size() );
|
std::max( data_size, LZ_min_dictionary_size() );
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@ printf .
|
||||||
cat in in > in2 || framework_failure
|
cat in in > in2 || framework_failure
|
||||||
"${LZIP}" -o copy2 < in2 || fail=1
|
"${LZIP}" -o copy2 < in2 || fail=1
|
||||||
"${LZIP}" -t copy2.lz || fail=1
|
"${LZIP}" -t copy2.lz || fail=1
|
||||||
printf .
|
|
||||||
"${LZIP}" -cd copy2.lz > copy2 || fail=1
|
"${LZIP}" -cd copy2.lz > copy2 || fail=1
|
||||||
cmp in2 copy2 || fail=1
|
cmp in2 copy2 || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
|
Loading…
Add table
Reference in a new issue