diff options
Diffstat (limited to 'main.cc')
-rw-r--r-- | main.cc | 92 |
1 files changed, 54 insertions, 38 deletions
@@ -1,6 +1,6 @@ /* Plzip - A parallel compressor compatible with lzip Copyright (C) 2009 Laszlo Ersek. - Copyright (C) 2009, 2010, 2011, 2012 Antonio Diaz Diaz. + Copyright (C) 2009, 2010, 2011, 2012, 2013 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 @@ -34,15 +34,30 @@ #include <string> #include <vector> #include <fcntl.h> -#include <inttypes.h> #include <pthread.h> +#include <stdint.h> #include <unistd.h> #include <utime.h> #include <sys/stat.h> #include <lzlib.h> +#if defined(__MSVCRT__) +#include <io.h> +#define fchmod(x,y) 0 +#define fchown(x,y,z) 0 +#define strtoull std::strtoul +#define SIGHUP SIGTERM +#define S_ISSOCK(x) 0 +#define S_IRGRP 0 +#define S_IWGRP 0 +#define S_IROTH 0 +#define S_IWOTH 0 +#endif +#if defined(__OS2__) +#include <io.h> +#endif #include "arg_parser.h" -#include "plzip.h" +#include "lzip.h" #if CHAR_BIT != 8 #error "Environments where CHAR_BIT != 8 are not supported." @@ -53,7 +68,7 @@ namespace { const char * const Program_name = "Plzip"; const char * const program_name = "plzip"; -const char * const program_year = "2012"; +const char * const program_year = "2013"; const char * invocation_name = 0; #ifdef O_BINARY @@ -85,7 +100,7 @@ pthread_t main_thread; pid_t main_thread_pid; -void show_help() +void show_help( const long num_online ) { std::printf( "%s - A parallel compressor compatible with lzip.\n", Program_name ); std::printf( "\nUsage: %s [options] [files]\n", invocation_name ); @@ -99,7 +114,7 @@ void show_help() " -F, --recompress force recompression of compressed files\n" " -k, --keep keep (don't delete) input files\n" " -m, --match-length=<bytes> set match length limit in bytes [36]\n" - " -n, --threads=<n> set the number of (de)compression threads\n" + " -n, --threads=<n> set number of (de)compression threads [%ld]\n" " -o, --output=<file> if reading stdin, place the output into <file>\n" " -q, --quiet suppress all messages\n" " -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8MiB]\n" @@ -107,7 +122,7 @@ void show_help() " -v, --verbose be verbose (a 2nd -v gives more)\n" " -1 .. -9 set compression level [default 6]\n" " --fast alias for -1\n" - " --best alias for -9\n" ); + " --best alias for -9\n", num_online ); if( verbosity > 0 ) { std::printf( " -D, --debug=<level> (0-1) print debug statistics to stderr\n" ); @@ -137,13 +152,13 @@ void show_version() } -long long getnum( const char * const ptr, - const long long llimit = LLONG_MIN + 1, - const long long ulimit = LLONG_MAX ) +unsigned long long getnum( const char * const ptr, + const unsigned long long llimit, + const unsigned long long ulimit ) { errno = 0; - char *tail; - long long result = strtoll( ptr, &tail, 0 ); + char * tail; + unsigned long long result = strtoull( ptr, &tail, 0 ); if( tail == ptr ) { show_error( "Bad or missing numerical argument.", 0, true ); @@ -178,7 +193,7 @@ long long getnum( const char * const ptr, } for( int i = 0; i < exponent; ++i ) { - if( LLONG_MAX / factor >= llabs( result ) ) result *= factor; + if( ulimit / factor >= result ) result *= factor; else { errno = ERANGE; break; } } } @@ -194,7 +209,7 @@ long long getnum( const char * const ptr, int get_dict_size( const char * const arg ) { - char *tail; + char * tail; int bits = std::strtol( arg, &tail, 0 ); if( bits >= LZ_min_dictionary_bits() && bits <= LZ_max_dictionary_bits() && *tail == 0 ) @@ -240,7 +255,7 @@ int open_instream( const std::string & name, struct stat * const in_statsp, else { const int i = fstat( infd, in_statsp ); - const mode_t & mode = in_statsp->st_mode; + const mode_t mode = in_statsp->st_mode; const bool can_read = ( i == 0 && ( S_ISBLK( mode ) || S_ISCHR( mode ) || S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); @@ -368,9 +383,9 @@ extern "C" void signal_handler( int sig ) { if( !pthread_equal( pthread_self(), main_thread ) ) kill( main_thread_pid, sig ); - if( sig != SIGUSR1 ) + if( sig != SIGUSR1 && sig != SIGUSR2 ) show_error( "Control-C or similar caught, quitting." ); - cleanup_and_fail( 1 ); + cleanup_and_fail( ( sig != SIGUSR2 ) ? 1 : 2 ); } @@ -391,7 +406,8 @@ int verbosity = 0; // since they all call common helper functions that call fatal() in case // of an error. // -void fatal() { signal_handler( SIGUSR1 ); } +void fatal( const int retval ) + { signal_handler( ( retval != 2 ) ? SIGUSR1 : SIGUSR2 ); } void Pretty_print::operator()( const char * const msg ) const @@ -402,7 +418,7 @@ void Pretty_print::operator()( const char * const msg ) const { first_post = false; std::fprintf( stderr, " %s: ", name_.c_str() ); - for( unsigned int i = 0; i < longest_name - name_.size(); ++i ) + for( unsigned i = 0; i < longest_name - name_.size(); ++i ) std::fprintf( stderr, " " ); if( !msg ) std::fflush( stderr ); } @@ -422,7 +438,7 @@ void show_error( const char * const msg, const int errcode, const bool help ) std::fprintf( stderr, ": %s", std::strerror( errcode ) ); std::fprintf( stderr, "\n" ); } - if( help && invocation_name && invocation_name[0] ) + if( help ) std::fprintf( stderr, "Try '%s --help' for more information.\n", invocation_name ); } @@ -454,6 +470,9 @@ int main( const int argc, const char * const argv[] ) { 3 << 23, 132 }, // -8 { 1 << 25, 273 } }; // -9 Lzma_options encoder_options = option_mapping[6]; // default = "-6" + std::string input_filename; + std::string default_output_filename; + std::vector< std::string > filenames; int data_size = 0; int debug_level = 0; int infd = -1; @@ -463,9 +482,6 @@ int main( const int argc, const char * const argv[] ) bool keep_input_files = false; bool recompress = false; bool to_stdout = false; - std::string input_filename; - std::string default_output_filename; - std::vector< std::string > filenames; invocation_name = argv[0]; main_thread = pthread_self(); main_thread_pid = getpid(); @@ -473,6 +489,7 @@ int main( const int argc, const char * const argv[] ) if( LZ_version()[0] != LZ_version_string[0] ) internal_error( "bad library version" ); + const long num_online = std::max( 1L, sysconf( _SC_NPROCESSORS_ONLN ) ); long max_workers = sysconf( _SC_THREAD_THREADS_MAX ); if( max_workers < 1 || max_workers > INT_MAX / (int)sizeof (pthread_t) ) max_workers = INT_MAX / sizeof (pthread_t); @@ -521,7 +538,8 @@ int main( const int argc, const char * const argv[] ) const char * const arg = parser.argument( argind ).c_str(); switch( code ) { - case '0': case '1': case '2': case '3': case '4': + case '0': + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': encoder_options = option_mapping[code-'0']; break; case 'b': break; @@ -532,7 +550,7 @@ int main( const int argc, const char * const argv[] ) case 'D': debug_level = getnum( arg, 0, 3 ); break; case 'f': force = true; break; case 'F': recompress = true; break; - case 'h': show_help(); return 0; + case 'h': show_help( num_online ); return 0; case 'k': keep_input_files = true; break; case 'm': encoder_options.match_len_limit = getnum( arg, LZ_min_match_len_limit(), @@ -550,9 +568,9 @@ int main( const int argc, const char * const argv[] ) } } // end process options -#if defined(__OS2__) - _fsetmode( stdin, "b" ); - _fsetmode( stdout, "b" ); +#if defined(__MSVCRT__) || defined(__OS2__) + setmode( STDIN_FILENO, O_BINARY ); + setmode( STDOUT_FILENO, O_BINARY ); #endif if( program_mode == m_test ) @@ -564,17 +582,13 @@ int main( const int argc, const char * const argv[] ) encoder_options.dictionary_size = std::max( data_size, LZ_min_dictionary_size() ); if( num_workers <= 0 ) - { - long num_online = sysconf( _SC_NPROCESSORS_ONLN ); - if( num_online <= 0 ) num_online = 1; num_workers = std::min( num_online, max_workers ); - } bool filenames_given = false; for( ; argind < parser.arguments(); ++argind ) { - if( parser.argument( argind ) != "-" ) filenames_given = true; filenames.push_back( parser.argument( argind ) ); + if( filenames.back() != "-" ) filenames_given = true; } if( filenames.empty() ) filenames.push_back("-"); @@ -582,11 +596,12 @@ int main( const int argc, const char * const argv[] ) ( filenames_given || default_output_filename.size() ) ) set_signals(); std::signal( SIGUSR1, signal_handler ); + std::signal( SIGUSR2, signal_handler ); Pretty_print pp( filenames ); int retval = 0; - for( unsigned int i = 0; i < filenames.size(); ++i ) + for( unsigned i = 0; i < filenames.size(); ++i ) { struct stat in_stats; output_filename.clear(); @@ -607,7 +622,7 @@ int main( const int argc, const char * const argv[] ) outfd_mode = all_rw; if( !open_outstream( force ) ) { - if( outfd == -1 && retval < 1 ) retval = 1; + if( retval < 1 ) retval = 1; close( infd ); infd = -1; continue; } @@ -632,7 +647,7 @@ int main( const int argc, const char * const argv[] ) outfd_mode = usr_rw; if( !open_outstream( force ) ) { - if( outfd == -1 && retval < 1 ) retval = 1; + if( retval < 1 ) retval = 1; close( infd ); infd = -1; continue; } @@ -645,16 +660,17 @@ int main( const int argc, const char * const argv[] ) if( output_filename.size() && !to_stdout && program_mode != m_test ) delete_output_on_interrupt = true; const struct stat * const in_statsp = input_filename.size() ? &in_stats : 0; + const bool infd_isreg = in_statsp && S_ISREG( in_statsp->st_mode ); pp.set_name( input_filename ); if( verbosity >= 1 ) pp(); - int tmp = 0; + int tmp; if( program_mode == m_compress ) tmp = compress( data_size, encoder_options.dictionary_size, encoder_options.match_len_limit, num_workers, infd, outfd, pp, debug_level ); else tmp = decompress( num_workers, infd, outfd, pp, debug_level, - program_mode == m_test ); + program_mode == m_test, infd_isreg ); if( tmp > retval ) retval = tmp; if( tmp && program_mode != m_test ) cleanup_and_fail( retval ); |