From 746479a2d915d02f6f02ec508202afb1face7c2b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 7 Nov 2015 12:53:09 +0100 Subject: Merging upstream version 1.18~pre2. Signed-off-by: Daniel Baumann --- main.cc | 86 +++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 37 deletions(-) (limited to 'main.cc') diff --git a/main.cc b/main.cc index 9425858..7845d90 100644 --- a/main.cc +++ b/main.cc @@ -24,6 +24,7 @@ #define _FILE_OFFSET_BITS 64 #include +#include #include #include #include @@ -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= 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 ) + { + msg += '\''; + msg.append( (const char *)data, size ); + msg += '\''; + } + else { - if( i > 0 ) garbage_msg += ' '; - garbage_msg += xdigit( data[i] >> 4 ); - garbage_msg += xdigit( data[i] & 0x0F ); + 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 ); -- cgit v1.2.3