diff options
Diffstat (limited to 'zcmp.cc')
-rw-r--r-- | zcmp.cc | 60 |
1 files changed, 33 insertions, 27 deletions
@@ -37,6 +37,7 @@ #include "arg_parser.h" #include "zutils.h" +#include "rc.h" #if CHAR_BIT != 8 #error "Environments where CHAR_BIT != 8 are not supported." @@ -57,19 +58,19 @@ void show_help() std::printf( "Zcmp compares two files (\"-\" means standard input), and if they\n" "differ, tells the first byte and line number where they differ. Bytes\n" "and lines are numbered starting with 1. If any given file is compressed,\n" - "its uncompressed content is used. Compressed files are uncompressed on\n" + "its decompressed content is used. Compressed files are decompressed on\n" "the fly; no temporary files are created.\n" "\nThe supported formats are bzip2, gzip, lzip and xz.\n" "\nUsage: zcmp [options] file1 [file2]\n" "\nCompares <file1> to <file2>. If <file2> is omitted zcmp tries the\n" "following:\n" - "If <file1> is compressed, compares <file1> to the file with the\n" - "corresponding decompressed file name (removes the extension from\n" - "<file1>).\n" - "If <file1> is not compressed, compares <file1> to the uncompressed\n" - "contents of <file1>.[lz|bz2|gz|xz] (the first one that is found).\n" - "If no suitable file is found, compares <file1> to data read from\n" - "standard input.\n" + "\n 1. If <file1> is compressed, compares its decompressed contents with\n" + " the corresponding uncompressed file (the name of <file1> with the\n" + " extension removed).\n" + "\n 2. If <file1> is uncompressed, compares it with the decompressed\n" + " contents of <file1>.[lz|bz2|gz|xz] (the first one that is found).\n" + "\n 3. If no suitable file is found, compares <file1> with data read from\n" + " standard input.\n" "\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n" "\nOptions:\n" " -h, --help display this help and exit\n" @@ -79,9 +80,14 @@ void show_help() " -i, --ignore-initial=<n>[,<n2>] ignore differences in the first <n> bytes\n" " -l, --list list position, value of all differing bytes\n" " -n, --bytes=<n> compare at most <n> bytes\n" + " -N, --no-rcfile don't read runtime configuration file\n" " -q, --quiet suppress all messages\n" " -s, --silent (same as --quiet)\n" " -v, --verbose verbose mode (same as --list)\n" + " --bz2=<command> set compressor and options for bzip2 format\n" + " --gz=<command> set compressor and options for gzip format\n" + " --lz=<command> set compressor and options for lzip format\n" + " --xz=<command> set compressor and options for xz format\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" ); show_help_addr(); @@ -310,7 +316,7 @@ int cmp( const long long max_size, const int infd[2], int main( const int argc, const char * const argv[] ) { - enum { format_opt = 256 }; + enum { format_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt }; // number of initial bytes ignored for each file long long ignore_initial[2] = { 0, 0 }; long long max_size = -1; // < 0 means unlimited size @@ -326,17 +332,24 @@ int main( const int argc, const char * const argv[] ) { 'i', "ignore-initial", Arg_parser::yes }, { 'l', "list", Arg_parser::no }, { 'n', "bytes", Arg_parser::yes }, + { 'N', "no-rcfile", Arg_parser::no }, { 'q', "quiet", Arg_parser::no }, { 's', "silent", Arg_parser::no }, { 'v', "verbose", Arg_parser::no }, { 'V', "version", Arg_parser::no }, { format_opt, "format", Arg_parser::yes }, + { bz2_opt, "bz2", Arg_parser::yes }, + { gz_opt, "gz", Arg_parser::yes }, + { lz_opt, "lz", Arg_parser::yes }, + { xz_opt, "xz", Arg_parser::yes }, { 0 , 0, Arg_parser::no } }; const Arg_parser parser( argc, argv, options ); if( parser.error().size() ) // bad option { show_error( parser.error().c_str(), 0, true ); return 2; } + maybe_process_config_file( parser ); + int argind = 0; for( ; argind < parser.arguments(); ++argind ) { @@ -350,11 +363,16 @@ int main( const int argc, const char * const argv[] ) case 'i': parse_ignore_initial( arg, ignore_initial ); break; case 'l': verbosity = 1; break; case 'n': max_size = getnum( arg ); break; + case 'N': break; case 'q': case 's': verbosity = -1; break; case 'v': verbosity = 1; break; case 'V': show_version( "Zcmp" ); return 0; - case format_opt: get_format_types( arg, format_types ); break; + case format_opt: parse_format_types( arg, format_types ); break; + case bz2_opt: parse_compressor( arg, fmt_bz2 ); break; + case gz_opt: parse_compressor( arg, fmt_gz ); break; + case lz_opt: parse_compressor( arg, fmt_lz ); break; + case xz_opt: parse_compressor( arg, fmt_xz ); break; default : internal_error( "uncaught option" ); } } // end process options @@ -405,9 +423,9 @@ int main( const int argc, const char * const argv[] ) int old_infd[2]; // copy of file descriptors of the two files old_infd[0] = infd[0]; old_infd[1] = infd[1]; - pid_t pid[2]; - if( !set_data_feeder( &infd[0], &pid[0], format_types[0] ) || - !set_data_feeder( &infd[1], &pid[1], format_types[1] ) ) + Children children[2]; + if( !set_data_feeder( &infd[0], children[0], format_types[0] ) || + !set_data_feeder( &infd[1], children[1], format_types[1] ) ) return 2; for( int i = 0; i < 2; ++i ) @@ -419,20 +437,8 @@ int main( const int argc, const char * const argv[] ) int retval = cmp( max_size, infd, filenames, print_bytes ); - if( retval != 0 || max_size >= 0 ) - { - for( int i = 0; i < 2; ++i ) - if( pid[i] ) - { - const int tmp = child_status( pid[i], "data feeder" ); - if( tmp < 0 ) kill( pid[i], SIGTERM ); // child not terminated - else if( tmp != 0 ) retval = 2; // child status != 0 - } - } - else - if( ( pid[0] && wait_for_child( pid[0], "data feeder" ) != 0 ) || - ( pid[1] && wait_for_child( pid[1], "data feeder" ) != 0 ) ) - retval = 2; + for( int i = 0; i < 2; ++i ) + if( !good_status( children[i], retval == 0 && max_size < 0 ) ) retval = 2; for( int i = 0; i < 2; ++i ) { |