diff options
Diffstat (limited to '')
-rw-r--r-- | main.cc | 94 |
1 files changed, 49 insertions, 45 deletions
@@ -1,5 +1,5 @@ /* Lziprecover - Data recovery tool for lzip files - Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz. + Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,6 +56,10 @@ #include "lzip.h" #include "decoder.h" +#ifndef O_BINARY +#define O_BINARY 0 +#endif + #if CHAR_BIT != 8 #error "Environments where CHAR_BIT != 8 are not supported." #endif @@ -65,22 +69,16 @@ namespace { const char * const Program_name = "Lziprecover"; const char * const program_name = "lziprecover"; -const char * const program_year = "2013"; +const char * const program_year = "2014"; const char * invocation_name = 0; -#ifdef O_BINARY -const int o_binary = O_BINARY; -#else -const int o_binary = 0; -#endif - struct { const char * from; const char * to; } const known_extensions[] = { { ".lz", "" }, { ".tlz", ".tar" }, { 0, 0 } }; -enum Mode { m_none, m_decompress, m_generate, m_list, m_merge, m_range, - m_recover, m_repair, m_split, m_test }; +enum Mode { m_none, m_decompress, m_list, m_merge, m_range, m_repair, + m_split, m_test }; std::string output_filename; int outfd = -1; @@ -102,14 +100,12 @@ void show_help() " -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" " -i, --ignore-errors make '--range-decompress' ignore data errors\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 multi-member file in single-member files\n" " -t, --test test compressed file integrity\n" @@ -127,7 +123,7 @@ void show_help() void show_version() { - std::printf( "%s %s\n", Program_name, PROGVERSION ); + std::printf( "%s %s\n", program_name, PROGVERSION ); std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n" "This is free software: you are free to change and redistribute it.\n" @@ -189,15 +185,15 @@ int extension_index( const std::string & name ) } // end namespace -int open_instream( const std::string & name, struct stat * const in_statsp, +int open_instream( const char * const name, struct stat * const in_statsp, const bool no_ofile, const bool reg_only ) { - int infd = open( name.c_str(), O_RDONLY | o_binary ); + int infd = open( name, O_RDONLY | O_BINARY ); if( infd < 0 ) { if( verbosity >= 0 ) std::fprintf( stderr, "%s: Can't open input file '%s': %s.\n", - program_name, name.c_str(), std::strerror( errno ) ); + program_name, name, std::strerror( errno ) ); } else { @@ -210,7 +206,7 @@ int open_instream( const std::string & name, struct stat * const in_statsp, { if( verbosity >= 0 ) std::fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", - program_name, name.c_str(), + program_name, name, ( can_read && !no_ofile ) ? " and '--stdout' was not specified" : "" ); close( infd ); @@ -243,7 +239,7 @@ void set_d_outname( const std::string & name, const int i ) bool open_outstream( const bool force ) { - int flags = O_CREAT | O_WRONLY | o_binary; + int flags = O_CREAT | O_WRONLY | O_BINARY; if( force ) flags |= O_TRUNC; else flags |= O_EXCL; outfd = open( output_filename.c_str(), flags, outfd_mode ); @@ -293,10 +289,14 @@ 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. - if( ( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) != 0 && - errno != EPERM ) || - fchmod( outfd, in_statsp->st_mode ) != 0 ) warning = true; + if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 ) + { if( fchmod( outfd, mode ) != 0 ) warning = true; } + else + if( errno != EPERM || + fchmod( outfd, mode & ~( S_ISUID | S_ISGID | S_ISVTX ) ) != 0 ) + warning = true; } if( close( outfd ) != 0 ) cleanup_and_fail( 1 ); outfd = -1; @@ -356,6 +356,7 @@ void show_trailing_garbage( const uint8_t * const data, const int size, garbage_msg += xdigit( data[i] & 0x0F ); } } + garbage_msg += '.'; pp( garbage_msg.c_str() ); } @@ -375,7 +376,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) if( rdec.finished() ) // End Of File { if( first_member ) - { pp( "File ends unexpectedly at member header" ); retval = 2; } + { pp( "File ends unexpectedly at member header." ); retval = 2; } else if( verbosity >= 4 && size > 0 ) show_trailing_garbage( header.data, size, pp, true ); break; @@ -383,7 +384,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) if( !header.verify_magic() ) { if( first_member ) - { pp( "Bad magic number (file not in lzip format)" ); retval = 2; } + { pp( "Bad magic number (file not in lzip format)." ); retval = 2; } else if( verbosity >= 4 ) show_trailing_garbage( header.data, size, pp, false ); break; @@ -398,7 +399,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) } if( header.dictionary_size() < min_dictionary_size || header.dictionary_size() > max_dictionary_size ) - { pp( "Invalid dictionary size in member header" ); retval = 2; break; } + { pp( "Invalid dictionary size in member header." ); retval = 2; break; } if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) { pp(); if( verbosity >= 3 ) show_header( header ); } @@ -412,10 +413,10 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) { pp(); if( result == 2 ) - std::fprintf( stderr, "File ends unexpectedly at pos %llu\n", + std::fprintf( stderr, "File ends unexpectedly at pos %llu.\n", partial_file_pos ); else - std::fprintf( stderr, "Decoder error at pos %llu\n", + std::fprintf( stderr, "Decoder error at pos %llu.\n", partial_file_pos ); } retval = 2; break; @@ -424,11 +425,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) { std::fprintf( stderr, testing ? "ok\n" : "done\n" ); pp.reset(); } } } - catch( std::bad_alloc ) - { - pp( "Not enough memory. Find a machine with more memory" ); - retval = 1; - } + catch( std::bad_alloc ) { pp( "Not enough memory." ); retval = 1; } catch( Error e ) { pp(); show_error( e.msg, errno ); retval = 1; } if( verbosity == 1 && retval == 0 ) std::fprintf( stderr, testing ? "ok\n" : "done\n" ); @@ -455,7 +452,7 @@ void set_signals() int open_outstream_rw( const std::string & output_filename, const bool force ) { - int flags = O_CREAT | O_RDWR | o_binary; + int flags = O_CREAT | O_RDWR | O_BINARY; if( force ) flags |= O_TRUNC; else flags |= O_EXCL; int outfd = open( output_filename.c_str(), flags, all_rw ); @@ -481,7 +478,7 @@ void show_error( const char * const msg, const int errcode, const bool help ) { std::fprintf( stderr, "%s: %s", program_name, msg ); if( errcode > 0 ) - std::fprintf( stderr, ": %s", std::strerror( errcode ) ); + std::fprintf( stderr, ": %s.", std::strerror( errcode ) ); std::fprintf( stderr, "\n" ); } if( help ) @@ -491,10 +488,18 @@ void show_error( const char * const msg, const int errcode, const bool help ) } +void show_error2( const char * const msg1, const char * const name, + const char * const msg2 ) + { + if( verbosity >= 0 ) + std::fprintf( stderr, "%s: %s '%s' %s\n", program_name, msg1, name, msg2 ); + } + + void internal_error( const char * const msg ) { if( verbosity >= 0 ) - std::fprintf( stderr, "%s: internal error: %s.\n", program_name, msg ); + std::fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); std::exit( 3 ); } @@ -564,7 +569,7 @@ int main( const int argc, const char * const argv[] ) case 't': set_mode( program_mode, m_test ); break; case 'v': if( verbosity < 4 ) ++verbosity; break; case 'V': show_version(); return 0; - default : internal_error( "uncaught option" ); + default : internal_error( "uncaught option." ); } } // end process options @@ -588,9 +593,7 @@ int main( const int argc, const char * const argv[] ) switch( program_mode ) { - case m_generate: - case m_recover: - case m_none: internal_error( "invalid operation" ); break; + case m_none: internal_error( "invalid operation." ); break; case m_decompress: break; case m_list: if( filenames.size() < 1 ) @@ -599,7 +602,7 @@ int main( const int argc, const char * const argv[] ) case m_merge: if( filenames.size() < 2 ) { show_error( "You must specify at least 2 files.", 0, true ); return 1; } - if( !default_output_filename.size() ) + if( default_output_filename.empty() ) default_output_filename = insert_fixed( filenames[0] ); return merge_files( filenames, default_output_filename, verbosity, force ); case m_range: @@ -608,9 +611,10 @@ int main( const int argc, const char * const argv[] ) range_string, verbosity, force, ignore, to_stdout ); case m_repair: one_file( filenames.size() ); - if( !default_output_filename.size() ) + if( default_output_filename.empty() ) default_output_filename = insert_fixed( filenames[0] ); - return repair_file( filenames[0], default_output_filename, verbosity, force ); + return repair_file( filenames[0], default_output_filename, + verbosity, force ); case m_split: one_file( filenames.size() ); return split_file( filenames[0], default_output_filename, verbosity, force ); @@ -620,7 +624,7 @@ int main( const int argc, const char * const argv[] ) if( program_mode == m_test ) outfd = -1; else if( program_mode != m_decompress ) - internal_error( "invalid decompressor operation" ); + internal_error( "invalid decompressor operation." ); if( filenames.empty() ) filenames.push_back("-"); if( !to_stdout && program_mode != m_test && @@ -635,13 +639,13 @@ int main( const int argc, const char * const argv[] ) struct stat in_stats; output_filename.clear(); - if( !filenames[i].size() || filenames[i] == "-" ) + if( filenames[i].empty() || filenames[i] == "-" ) { input_filename.clear(); infd = STDIN_FILENO; if( program_mode != m_test ) { - if( to_stdout || !default_output_filename.size() ) + if( to_stdout || default_output_filename.empty() ) outfd = STDOUT_FILENO; else { @@ -659,7 +663,7 @@ int main( const int argc, const char * const argv[] ) else { input_filename = filenames[i]; - infd = open_instream( input_filename, &in_stats, + infd = open_instream( input_filename.c_str(), &in_stats, to_stdout || program_mode == m_test ); if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } if( program_mode != m_test ) |