1
0
Fork 0

Adding upstream version 1.13~rc2.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-21 10:12:24 +01:00
parent 89ca1f7591
commit 7fe0f13dd3
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
17 changed files with 679 additions and 132 deletions

143
main.cc
View file

@ -71,8 +71,8 @@ struct { const char * from; const char * to; } const known_extensions[] = {
{ ".tlz", ".tar" },
{ 0, 0 } };
enum Mode { m_none, m_decompress, m_generate, m_merge, m_recover, m_repair,
m_split, m_test, m_update };
enum Mode { m_none, m_decompress, m_generate, m_list, m_merge, m_range,
m_recover, m_repair, m_split, m_test, m_update };
std::string output_filename;
int outfd = -1;
@ -87,22 +87,26 @@ void show_help() throw()
std::printf( "%s - Data recovery tool and decompressor for lzipped files.\n", Program_name );
std::printf( "\nUsage: %s [options] [files]\n", invocation_name );
std::printf( "\nOptions:\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" -c, --stdout send decompressed output to standard output\n"
" -d, --decompress decompress\n"
" -f, --force overwrite existing output files\n"
// " -g, --generate-recover-file generate a recover file\n"
" -k, --keep keep (don't delete) input files\n"
" -m, --merge correct errors in file using several copies\n"
" -o, --output=<file> place the output into <file>\n"
" -q, --quiet suppress all messages\n"
// " -r, --recover correct errors in file using a recover file\n"
" -R, --repair try to repair a small error in file\n"
" -s, --split split a multimember file in single-member files\n"
" -t, --test test compressed file integrity\n"
// " -u, --update convert file from version 0 to version 1\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" -c, --stdout send decompressed output to standard output\n"
" -d, --decompress decompress\n"
" -D, --range-decompress=<range> decompress only a range of bytes (N-M)\n"
" -f, --force overwrite existing output files\n"
// " -g, --generate-recover-file generate a recover file\n"
" -k, --keep keep (don't delete) input files\n"
" -l, --list print total file sizes and ratios\n"
" -m, --merge correct errors in file using several copies\n"
" -o, --output=<file> place the output into <file>\n"
" -q, --quiet suppress all messages\n"
// " -r, --recover correct errors in file using a recover file\n"
" -R, --repair try to repair a small error in file\n"
" -s, --split split multimember file in single-member files\n"
" -t, --test test compressed file integrity\n"
// " -u, --update convert file from version 0 to version 1\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n"
"Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n"
"Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n"
"\nReport bugs to lzip-bug@nongnu.org\n"
"Lziprecover home page: http://www.nongnu.org/lzip/lziprecover.html\n" );
}
@ -118,20 +122,13 @@ void show_version() throw()
}
const char * format_num( long long num ) throw()
void one_file( const int argind, const int arguments ) throw()
{
const char * const prefix[8] =
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
enum { buf_size = 16, factor = 1024 };
static char buf[buf_size];
const char *p = "";
bool exact = ( num % factor == 0 );
for( int i = 0; i < 8 && ( llabs( num ) > 9999 ||
( exact && llabs( num ) >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; }
snprintf( buf, buf_size, "%lld %s", num, p );
return buf;
if( argind + 1 != arguments )
{
show_error( "You must specify exactly 1 file.", 0, true );
std::exit( 1 );
}
}
@ -345,7 +342,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
if( verbosity >= 2 )
std::fprintf( stderr, "version %d, dictionary size %7sB. ",
header.version(),
format_num( header.dictionary_size() ) );
format_num( header.dictionary_size(), 9999, -1 ) );
}
LZ_decoder decoder( header, rdec, outfd );
@ -403,6 +400,30 @@ void set_signals() throw()
int verbosity = 0;
const char * format_num( long long num, long long limit,
const int set_prefix ) throw()
{
const char * const si_prefix[8] =
{ "k", "M", "G", "T", "P", "E", "Z", "Y" };
const char * const binary_prefix[8] =
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
static bool si = true;
static char buf[32];
if( set_prefix ) si = ( set_prefix > 0 );
const int factor = ( si ? 1000 : 1024 );
const char * const * prefix = ( si ? si_prefix : binary_prefix );
const char * p = "";
bool exact = ( num % factor == 0 );
for( int i = 0; i < 8 && ( llabs( num ) > limit ||
( exact && llabs( num ) >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; }
snprintf( buf, sizeof buf, "%lld %s", num, p );
return buf;
}
int open_instream( const std::string & name, struct stat * const in_statsp,
const bool to_stdout, const bool reg_only ) throw()
{
@ -491,25 +512,28 @@ int main( const int argc, const char * const argv[] )
bool to_stdout = false;
std::string input_filename;
std::string default_output_filename;
std::string range_string;
std::vector< std::string > filenames;
invocation_name = argv[0];
const Arg_parser::Option options[] =
{
{ 'c', "stdout", Arg_parser::no },
{ 'd', "decompress", Arg_parser::no },
{ 'f', "force", Arg_parser::no },
{ 'h', "help", Arg_parser::no },
{ 'k', "keep", Arg_parser::no },
{ 'm', "merge", Arg_parser::no },
{ 'o', "output", Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 'R', "repair", Arg_parser::no },
{ 's', "split", Arg_parser::no },
{ 't', "test", Arg_parser::no },
{ 'v', "verbose", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ 0 , 0, Arg_parser::no } };
{ 'c', "stdout", Arg_parser::no },
{ 'd', "decompress", Arg_parser::no },
{ 'D', "range-decompress", Arg_parser::yes },
{ 'f', "force", Arg_parser::no },
{ 'h', "help", Arg_parser::no },
{ 'k', "keep", Arg_parser::no },
{ 'l', "list", Arg_parser::no },
{ 'm', "merge", Arg_parser::no },
{ 'o', "output", Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 'R', "repair", Arg_parser::no },
{ 's', "split", Arg_parser::no },
{ 't', "test", Arg_parser::no },
{ 'v', "verbose", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ 0 , 0, Arg_parser::no } };
const Arg_parser parser( argc, argv, options );
if( parser.error().size() ) // bad option
@ -520,15 +544,19 @@ 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 ).c_str();
switch( code )
{
case 'c': to_stdout = true; break;
case 'd': set_mode( program_mode, m_decompress ); break;
case 'D': set_mode( program_mode, m_range );
range_string = arg; break;
case 'f': force = true; break;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
case 'l': set_mode( program_mode, m_list ); break;
case 'm': set_mode( program_mode, m_merge ); break;
case 'o': default_output_filename = parser.argument( argind ); break;
case 'o': default_output_filename = arg; break;
case 'q': verbosity = -1; break;
case 'R': set_mode( program_mode, m_repair ); break;
case 's': set_mode( program_mode, m_split ); break;
@ -552,9 +580,10 @@ int main( const int argc, const char * const argv[] )
case m_update:
case m_none: internal_error( "invalid operation" ); break;
case m_decompress: break;
case m_list:
one_file( argind, parser.arguments() );
return list_file( parser.argument( argind ) );
case m_merge:
{
std::vector< std::string > filenames;
for( ; argind < parser.arguments(); ++argind )
filenames.push_back( parser.argument( argind ) );
if( filenames.size() < 2 )
@ -562,21 +591,19 @@ int main( const int argc, const char * const argv[] )
if( !default_output_filename.size() )
default_output_filename = insert_fixed( filenames[0] );
return merge_files( filenames, default_output_filename, force );
} break;
case m_range:
one_file( argind, parser.arguments() );
return range_decompress( parser.argument( argind ),
default_output_filename, range_string,
to_stdout, force );
case m_repair:
{
if( argind + 1 != parser.arguments() )
{ show_error( "You must specify exactly 1 file.", 0, true ); return 1; }
one_file( argind, parser.arguments() );
if( !default_output_filename.size() )
default_output_filename = insert_fixed( parser.argument( argind ) );
return repair_file( parser.argument( argind ), default_output_filename, force );
} break;
case m_split:
{
if( argind + 1 != parser.arguments() )
{ show_error( "You must specify exactly 1 file.", 0, true ); return 1; }
one_file( argind, parser.arguments() );
return split_file( parser.argument( argind ), default_output_filename, force );
} break;
case m_test: break;
}