Merging upstream version 1.18~pre2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
20207bbadd
commit
8e75c72be2
18 changed files with 427 additions and 220 deletions
86
main.cc
86
main.cc
|
@ -24,6 +24,7 @@
|
|||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <csignal>
|
||||
|
@ -104,6 +105,7 @@ void show_help()
|
|||
std::printf( "\nOptions:\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
" -V, --version output version information and exit\n"
|
||||
" -a, --trailing-error exit with error status if trailing data\n"
|
||||
" -c, --stdout send decompressed output to standard output\n"
|
||||
" -d, --decompress decompress\n"
|
||||
" -D, --range-decompress=<range> decompress a range of bytes (N-M) to stdout\n"
|
||||
|
@ -146,9 +148,9 @@ void show_version()
|
|||
|
||||
} // end namespace
|
||||
|
||||
void show_header( const unsigned dictionary_size )
|
||||
void show_header( const unsigned dictionary_size, const int vlevel )
|
||||
{
|
||||
if( verbosity >= 3 )
|
||||
if( verbosity >= vlevel )
|
||||
{
|
||||
const char * const prefix[8] =
|
||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
|
||||
|
@ -309,7 +311,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",
|
||||
program_name, name,
|
||||
( can_read && !no_ofile ) ?
|
||||
" and '--stdout' was not specified" : "" );
|
||||
",\n and '--stdout' was not specified" : "" );
|
||||
close( infd );
|
||||
infd = -1;
|
||||
}
|
||||
|
@ -373,14 +375,14 @@ void cleanup_and_fail( const int retval )
|
|||
}
|
||||
|
||||
|
||||
/* Set permissions, owner and times. */
|
||||
// Set permissions, owner and times.
|
||||
void close_and_set_permissions( const struct stat * const in_statsp )
|
||||
{
|
||||
bool warning = false;
|
||||
if( in_statsp )
|
||||
{
|
||||
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( fchmod( outfd, mode ) != 0 ) warning = true; }
|
||||
else
|
||||
|
@ -424,36 +426,42 @@ unsigned char xdigit( const int value )
|
|||
}
|
||||
|
||||
|
||||
void show_trailing_garbage( const uint8_t * const data, const int size,
|
||||
const Pretty_print & pp, const bool all )
|
||||
bool show_trailing_data( const uint8_t * const data, const int size,
|
||||
const Pretty_print & pp, const bool all,
|
||||
const bool ignore_trailing )
|
||||
{
|
||||
std::string garbage_msg;
|
||||
if( !all ) garbage_msg = "first bytes of ";
|
||||
garbage_msg += "trailing garbage found = ";
|
||||
bool text = true;
|
||||
for( int i = 0; i < size; ++i )
|
||||
if( !std::isprint( data[i] ) ) { text = false; break; }
|
||||
if( text )
|
||||
{
|
||||
garbage_msg += '\'';
|
||||
garbage_msg.append( (const char *)data, size );
|
||||
garbage_msg += '\'';
|
||||
}
|
||||
else
|
||||
if( verbosity >= 4 || !ignore_trailing )
|
||||
{
|
||||
std::string msg;
|
||||
if( !all ) msg = "first bytes of ";
|
||||
msg += "trailing data = ";
|
||||
bool text = true;
|
||||
for( int i = 0; i < size; ++i )
|
||||
if( !std::isprint( data[i] ) ) { text = false; break; }
|
||||
if( text )
|
||||
{
|
||||
if( i > 0 ) garbage_msg += ' ';
|
||||
garbage_msg += xdigit( data[i] >> 4 );
|
||||
garbage_msg += xdigit( data[i] & 0x0F );
|
||||
msg += '\'';
|
||||
msg.append( (const char *)data, size );
|
||||
msg += '\'';
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < size; ++i )
|
||||
{
|
||||
if( i > 0 ) msg += ' ';
|
||||
msg += xdigit( data[i] >> 4 );
|
||||
msg += xdigit( data[i] & 0x0F );
|
||||
}
|
||||
}
|
||||
pp( msg.c_str() );
|
||||
if( !ignore_trailing ) show_error( "Trailing data not allowed." );
|
||||
}
|
||||
garbage_msg += '.';
|
||||
pp( garbage_msg.c_str() );
|
||||
return ignore_trailing;
|
||||
}
|
||||
|
||||
|
||||
int decompress( const int infd, const Pretty_print & pp, const bool testing )
|
||||
int decompress( const int infd, const Pretty_print & pp,
|
||||
const bool ignore_trailing, const bool testing )
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
|
@ -469,16 +477,17 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
|
|||
{
|
||||
if( first_member )
|
||||
{ pp( "File ends unexpectedly at member header." ); retval = 2; }
|
||||
else if( verbosity >= 4 && size > 0 )
|
||||
show_trailing_garbage( header.data, size, pp, true );
|
||||
else if( size > 0 && !show_trailing_data( header.data, size, pp,
|
||||
true, ignore_trailing ) )
|
||||
retval = 2;
|
||||
break;
|
||||
}
|
||||
if( !header.verify_magic() )
|
||||
{
|
||||
if( first_member )
|
||||
{ pp( "Bad magic number (file not in lzip format)." ); retval = 2; }
|
||||
else if( verbosity >= 4 )
|
||||
show_trailing_garbage( header.data, size, pp, false );
|
||||
else if( !show_trailing_data( header.data, size, pp, false, ignore_trailing ) )
|
||||
retval = 2;
|
||||
break;
|
||||
}
|
||||
if( !header.verify_version() )
|
||||
|
@ -620,13 +629,15 @@ int main( const int argc, const char * const argv[] )
|
|||
Mode program_mode = m_none;
|
||||
uint8_t bad_value = 0;
|
||||
bool force = false;
|
||||
bool ignore = false;
|
||||
bool ignore_errors = false;
|
||||
bool ignore_trailing = true;
|
||||
bool keep_input_files = false;
|
||||
bool to_stdout = false;
|
||||
invocation_name = argv[0];
|
||||
|
||||
const Arg_parser::Option options[] =
|
||||
{
|
||||
{ 'a', "trailing-error", Arg_parser::no },
|
||||
{ 'c', "stdout", Arg_parser::no },
|
||||
{ 'd', "decompress", Arg_parser::no },
|
||||
{ 'D', "range-decompress", Arg_parser::yes },
|
||||
|
@ -657,17 +668,18 @@ int main( const int argc, const char * const argv[] )
|
|||
for( ; argind < parser.arguments(); ++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 );
|
||||
switch( code )
|
||||
{
|
||||
case 'a': ignore_trailing = false; break;
|
||||
case 'c': to_stdout = true; break;
|
||||
case 'd': set_mode( program_mode, m_decompress ); break;
|
||||
case 'D': set_mode( program_mode, m_range_dec );
|
||||
parse_range( arg.c_str(), range ); break;
|
||||
case 'f': force = true; break;
|
||||
case 'h': show_help(); return 0;
|
||||
case 'i': ignore = true; break;
|
||||
case 'i': ignore_errors = true; break;
|
||||
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;
|
||||
|
@ -688,7 +700,7 @@ int main( const int argc, const char * const argv[] )
|
|||
parse_pos_value( arg.c_str(), bad_pos, bad_value ); break;
|
||||
default : internal_error( "uncaught option." );
|
||||
}
|
||||
} /* end process options */
|
||||
} // end process options
|
||||
|
||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||
setmode( STDIN_FILENO, O_BINARY );
|
||||
|
@ -731,8 +743,8 @@ int main( const int argc, const char * const argv[] )
|
|||
return merge_files( filenames, default_output_filename, verbosity, force );
|
||||
case m_range_dec:
|
||||
one_file( filenames.size() );
|
||||
return range_decompress( filenames[0], default_output_filename,
|
||||
range, verbosity, force, ignore, to_stdout );
|
||||
return range_decompress( filenames[0], default_output_filename, range,
|
||||
verbosity, force, ignore_errors, to_stdout );
|
||||
case m_repair:
|
||||
one_file( filenames.size() );
|
||||
if( default_output_filename.empty() )
|
||||
|
@ -823,7 +835,7 @@ int main( const int argc, const char * const argv[] )
|
|||
delete_output_on_interrupt = true;
|
||||
const struct stat * const in_statsp = input_filename.size() ? &in_stats : 0;
|
||||
pp.set_name( input_filename );
|
||||
const int tmp = decompress( infd, pp, program_mode == m_test );
|
||||
const int tmp = decompress( infd, pp, ignore_trailing, program_mode == m_test );
|
||||
if( tmp > retval ) retval = tmp;
|
||||
if( tmp && program_mode != m_test ) cleanup_and_fail( retval );
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue