From b95f39dfdb659097af23465ec2a533a254fd4ac5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 23 Jan 2024 06:54:09 +0100 Subject: Adding upstream version 1.13~rc1. Signed-off-by: Daniel Baumann --- zcmp.cc | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'zcmp.cc') diff --git a/zcmp.cc b/zcmp.cc index b118840..e7e1b44 100644 --- a/zcmp.cc +++ b/zcmp.cc @@ -58,13 +58,10 @@ void show_help() "\nThe formats supported are bzip2, gzip, lzip, xz, and zstd.\n" "\nUsage: zcmp [options] file1 [file2]\n" "\nzcmp compares file1 to file2. The standard input is used only if file1 or\n" - "file2 refers to standard input. If file2 is omitted zcmp tries the\n" - "following:\n" - "\n - 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 - If file1 is uncompressed, compares it with the decompressed\n" - " contents of file1.[lz|bz2|gz|zst|xz] (the first one that is found).\n" + "file2 refers to standard input. If file2 is omitted zcmp tries to compare\n" + "file1 with the corresponding uncompressed file (if file1 is compressed), and\n" + "then with the corresponding compressed files of the remaining formats until\n" + "one is found.\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" @@ -98,9 +95,9 @@ void show_help() // separate numbers of 5 or more digits in groups of 3 digits using '_' const char * format_num3( long long num ) { - const char * const si_prefix = "kMGTPEZY"; - const char * const binary_prefix = "KMGTPEZY"; - enum { buffers = 8, bufsize = 4 * sizeof num }; + enum { buffers = 8, bufsize = 4 * sizeof num, n = 10 }; + const char * const si_prefix = "kMGTPEZYRQ"; + const char * const binary_prefix = "KMGTPEZYRQ"; static char buffer[buffers][bufsize]; // circle of static buffers for printf static int current = 0; @@ -108,19 +105,22 @@ const char * format_num3( long long num ) char * p = buf + bufsize - 1; // fill the buffer backwards *p = 0; // terminator const bool negative = num < 0; - char prefix = 0; // try binary first, then si - for( int i = 0; i < 8 && num != 0 && ( num / 1024 ) * 1024 == num; ++i ) - { num /= 1024; prefix = binary_prefix[i]; } - if( prefix ) *(--p) = 'i'; - else - for( int i = 0; i < 8 && num != 0 && ( num / 1000 ) * 1000 == num; ++i ) - { num /= 1000; prefix = si_prefix[i]; } - if( prefix ) *(--p) = prefix; + if( num > 1024 || num < -1024 ) + { + char prefix = 0; // try binary first, then si + for( int i = 0; i < n && num != 0 && num % 1024 == 0; ++i ) + { num /= 1024; prefix = binary_prefix[i]; } + if( prefix ) *(--p) = 'i'; + else + for( int i = 0; i < n && num != 0 && num % 1000 == 0; ++i ) + { num /= 1000; prefix = si_prefix[i]; } + if( prefix ) *(--p) = prefix; + } const bool split = num >= 10000 || num <= -10000; for( int i = 0; ; ) { - long long onum = num; num /= 10; + const long long onum = num; num /= 10; *(--p) = llabs( onum - ( 10 * num ) ) + '0'; if( num == 0 ) break; if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; } } @@ -129,6 +129,7 @@ const char * format_num3( long long num ) } +// Recognized formats: k[B], Ki[B], [MGTPEZYRQ][i][B] long long getnum( const char * const arg, const char * const option_name, const char ** const tailp = 0, const long long llimit = 0, @@ -152,6 +153,8 @@ long long getnum( const char * const arg, const char * const option_name, int exponent = -1; // -1 = bad multiplier switch( ch ) { + case 'Q': exponent = 10; break; + case 'R': exponent = 9; break; case 'Y': exponent = 8; break; case 'Z': exponent = 7; break; case 'E': exponent = 6; break; @@ -210,7 +213,7 @@ bool skip_ignore_initial( const long long ignore_initial, const int infd ) const int size = std::min( rest, (long long)buffer_size ); const int rd = readblock( infd, buffer, size ); if( rd != size && errno ) return false; - if( rd < size ) break; + if( rd < size ) break; // EOF rest -= rd; } } @@ -270,6 +273,7 @@ int cmp( const long long max_size, const int infd[2], uint8_t * buffer[2]; buffer[0] = buffer0; buffer[1] = buffer1; int retval = 0; + bool empty[2] = { true, true }; while( rest > 0 ) { @@ -282,6 +286,7 @@ int cmp( const long long max_size, const int infd[2], if( rd[i] != size && errno ) { show_file_error( filenames[i].c_str(), "Read error", errno ); retval = 2; goto done; } + if( rd[i] > 0 ) empty[i] = false; } for( int i = 0; i < 2; ++i ) if( rd[i] < size ) finished[i] = true; @@ -345,11 +350,13 @@ int cmp( const long long max_size, const int infd[2], if( rd[0] != rd[1] ) { + const int i = rd[1] < rd[0]; if( verbosity >= 0 ) - std::fprintf( stderr, list ? + std::fprintf( stderr, empty[i] ? + "%s: EOF on %s which is empty\n" : list ? "%s: EOF on %s after byte %llu\n" : "%s: EOF on %s after byte %llu, in line %llu\n", - program_name, filenames[rd[1]