summaryrefslogtreecommitdiffstats
path: root/main.cc
diff options
context:
space:
mode:
authorDaniel Baumann <mail@daniel-baumann.ch>2015-11-07 11:53:09 +0000
committerDaniel Baumann <mail@daniel-baumann.ch>2015-11-07 11:53:09 +0000
commit746479a2d915d02f6f02ec508202afb1face7c2b (patch)
tree1d26867f949791b0e2ba99246aa252f02e693cef /main.cc
parentAdding debian version 1.18~pre1-1. (diff)
downloadlziprecover-746479a2d915d02f6f02ec508202afb1face7c2b.tar.xz
lziprecover-746479a2d915d02f6f02ec508202afb1face7c2b.zip
Merging upstream version 1.18~pre2.
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
Diffstat (limited to 'main.cc')
-rw-r--r--main.cc86
1 files changed, 49 insertions, 37 deletions
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 <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 )
+ {
+ 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 );