diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2019-01-04 11:13:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2019-01-04 11:13:03 +0000 |
commit | 74f3e49ba198016d7d078fbaf4954323f2cb3a15 (patch) | |
tree | 3be3ee4bf92eb1d9c3576e6019aa0010015c0161 /zgrep.cc | |
parent | Releasing debian version 1.7-8. (diff) | |
download | zutils-74f3e49ba198016d7d078fbaf4954323f2cb3a15.tar.xz zutils-74f3e49ba198016d7d078fbaf4954323f2cb3a15.zip |
Merging upstream version 1.8.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | zgrep.cc | 184 |
1 files changed, 95 insertions, 89 deletions
@@ -1,5 +1,5 @@ /* Zgrep - search compressed files for a regular expression - Copyright (C) 2010-2018 Antonio Diaz Diaz. + Copyright (C) 2010-2019 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 @@ -52,51 +52,54 @@ void show_help() "file is compressed, its decompressed content is used. If a given file\n" "does not exist, and its name does not end with one of the known\n" "extensions, zgrep tries the compressed file names corresponding to the\n" - "supported formats.\n" - "\nIf no files are specified, or if a file is specified as '-', data are\n" - "read from standard input, decompressed if needed, and fed to grep. Data\n" - "read from standard input must be of the same type; all uncompressed or\n" - "all in the same compression format.\n" - "\nThe supported formats are bzip2, gzip, lzip and xz.\n" + "formats supported.\n" + "\nIf a file is specified as '-', data are read from standard input,\n" + "decompressed if needed, and fed to grep. Data read from standard input\n" + "must be of the same type; all uncompressed or all in the same\n" + "compression format.\n" + "\nIf no files are specified, recursive searches examine the current\n" + "working directory, and nonrecursive searches read standard input.\n" + "\nThe formats supported are bzip2, gzip, lzip and xz.\n" "\nUsage: zgrep [options] <pattern> [files]\n" "\nExit status is 0 if match, 1 if no match, 2 if trouble.\n" "\nOptions:\n" - " --help display this help and exit\n" - " -V, --version output version information and exit\n" - " -a, --text treat all files as text\n" - " -A, --after-context=<n> print <n> lines of trailing context\n" - " -b, --byte-offset print the byte offset of each line\n" - " -B, --before-context=<n> print <n> lines of leading context\n" - " -c, --count only print a count of matching lines per file\n" - " -C, --context=<n> print <n> lines of output context\n" - " --color[=<when>] show matched strings in color\n" - " -e, --regexp=<pattern> use <pattern> as the pattern to match\n" - " -E, --extended-regexp <pattern> is an extended regular expression\n" - " -f, --file=<file> obtain patterns from <file>\n" - " -F, --fixed-strings <pattern> is a set of newline-separated strings\n" - " -h, --no-filename suppress the prefixing filename on output\n" - " -H, --with-filename print the filename for each match\n" - " -i, --ignore-case ignore case distinctions\n" - " -I ignore binary files\n" - " -l, --files-with-matches only print names of files containing matches\n" - " -L, --files-without-match only print names of files containing no matches\n" - " -m, --max-count=<n> stop after <n> matches\n" - " -M, --format=<list> process only the formats in <list>\n" - " -n, --line-number print the line number of each line\n" - " -N, --no-rcfile don't read runtime configuration file\n" - " -o, --only-matching show only the part of a line matching <pattern>\n" - " -O, --force-format=<fmt> force given format (bz2, gz, lz, xz)\n" - " -q, --quiet suppress all messages\n" - " -r, --recursive operate recursively on directories\n" - " -s, --no-messages suppress error messages\n" - " -v, --invert-match select non-matching lines\n" - " --verbose verbose mode (show error messages)\n" - " -w, --word-regexp match only whole words\n" - " -x, --line-regexp match only whole lines\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" + " --help display this help and exit\n" + " -V, --version output version information and exit\n" + " -a, --text treat all files as text\n" + " -A, --after-context=<n> print <n> lines of trailing context\n" + " -b, --byte-offset print the byte offset of each line\n" + " -B, --before-context=<n> print <n> lines of leading context\n" + " -c, --count only print a count of matching lines per file\n" + " -C, --context=<n> print <n> lines of output context\n" + " --color[=<when>] show matched strings in color\n" + " -e, --regexp=<pattern> use <pattern> as the pattern to match\n" + " -E, --extended-regexp <pattern> is an extended regular expression\n" + " -f, --file=<file> obtain patterns from <file>\n" + " -F, --fixed-strings <pattern> is a set of newline-separated strings\n" + " -h, --no-filename suppress the prefixing filename on output\n" + " -H, --with-filename print the filename for each match\n" + " -i, --ignore-case ignore case distinctions\n" + " -I ignore binary files\n" + " -l, --files-with-matches only print names of files containing matches\n" + " -L, --files-without-match only print names of files containing no matches\n" + " -m, --max-count=<n> stop after <n> matches\n" + " -M, --format=<list> process only the formats in <list>\n" + " -n, --line-number print the line number of each line\n" + " -N, --no-rcfile don't read runtime configuration file\n" + " -o, --only-matching show only the part of a line matching <pattern>\n" + " -O, --force-format=<fmt> force given format (bz2, gz, lz, xz)\n" + " -q, --quiet suppress all messages\n" + " -r, --recursive operate recursively on directories\n" + " -R, --dereference-recursive recursively follow symbolic links\n" + " -s, --no-messages suppress error messages\n" + " -v, --invert-match select non-matching lines\n" + " --verbose verbose mode (show error messages)\n" + " -w, --word-regexp match only whole words\n" + " -x, --line-regexp match only whole lines\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(); @@ -187,7 +190,8 @@ int zgrep_file( int infd, const int format_index, putchar( buffer[i] ); } else if( std::fwrite( buffer, 1, size, stdout ) != (unsigned)size ) - { show_error( "Write error", errno ); return 2; } + { std::fflush( stdout ); show_error( "Write error", errno ); return 2; } + std::fflush( stdout ); } if( size < buffer_size ) break; } @@ -197,7 +201,7 @@ int zgrep_file( int infd, const int format_index, if( !good_status( children, retval == 1 ) ) retval = 2; if( list_mode && (retval == 0) == (list_mode == 1) ) - std::printf( "%s\n", input_filename.c_str() ); + { std::printf( "%s\n", input_filename.c_str() ); std::fflush( stdout ); } if( close( infd ) != 0 ) { show_close_error(); return 2; } if( close( fda[0] ) != 0 ) @@ -213,12 +217,10 @@ int main( const int argc, const char * const argv[] ) enum { help_opt = 256, verbose_opt, color_opt, bz2_opt, gz_opt, lz_opt, xz_opt }; int format_index = -1; - int infd = -1; int list_mode = 0; // 1 = list matches, -1 = list non matches + int recursive = 0; // 1 = '-r', 2 = '-R' int show_name = -1; // tri-state bool bool no_messages = false; - bool recursive = false; - std::string input_filename; std::list< std::string > filenames; std::vector< const char * > grep_args; // args to grep, maybe empty std::string color_option; // needed because of optional arg @@ -227,43 +229,44 @@ int main( const int argc, const char * const argv[] ) const Arg_parser::Option options[] = { - { 'a', "text", Arg_parser::no }, // grep GNU - { 'A', "after-context", Arg_parser::yes }, // grep GNU - { 'b', "byte-offset", Arg_parser::no }, // grep GNU - { 'B', "before-context", Arg_parser::yes }, // grep GNU - { 'c', "count", Arg_parser::no }, // grep - { 'C', "context", Arg_parser::yes }, // grep GNU - { 'e', "regexp", Arg_parser::yes }, // grep - { 'E', "extended-regexp", Arg_parser::no }, // grep - { 'f', "file ", Arg_parser::yes }, // grep - { 'F', "fixed-strings", Arg_parser::no }, // grep - { 'h', "no-filename", Arg_parser::no }, // grep GNU - { 'H', "with-filename", Arg_parser::no }, // grep GNU - { 'i', "ignore-case", Arg_parser::no }, // grep - { 'I', 0, Arg_parser::no }, // grep GNU - { 'l', "files-with-matches", Arg_parser::no }, // grep - { 'L', "files-without-match", Arg_parser::no }, // grep GNU - { 'm', "max-count", Arg_parser::yes }, // grep GNU - { 'M', "format", Arg_parser::yes }, - { 'n', "line-number", Arg_parser::no }, // grep - { 'N', "no-rcfile", Arg_parser::no }, - { 'o', "only-matching", Arg_parser::no }, // grep - { 'O', "force-format", Arg_parser::yes }, - { 'q', "quiet", Arg_parser::no }, - { 'r', "recursive", Arg_parser::no }, - { 's', "no-messages", Arg_parser::no }, // grep - { 'v', "invert-match", Arg_parser::no }, // grep - { 'V', "version", Arg_parser::no }, - { 'w', "word-regexp", Arg_parser::no }, // grep GNU - { 'x', "line-regexp", Arg_parser::no }, // grep - { help_opt, "help", Arg_parser::no }, - { verbose_opt, "verbose", Arg_parser::no }, - { color_opt, "color", Arg_parser::maybe }, - { 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 } }; + { 'a', "text", Arg_parser::no }, // grep GNU + { 'A', "after-context", Arg_parser::yes }, // grep GNU + { 'b', "byte-offset", Arg_parser::no }, // grep GNU + { 'B', "before-context", Arg_parser::yes }, // grep GNU + { 'c', "count", Arg_parser::no }, // grep + { 'C', "context", Arg_parser::yes }, // grep GNU + { 'e', "regexp", Arg_parser::yes }, // grep + { 'E', "extended-regexp", Arg_parser::no }, // grep + { 'f', "file ", Arg_parser::yes }, // grep + { 'F', "fixed-strings", Arg_parser::no }, // grep + { 'h', "no-filename", Arg_parser::no }, // grep GNU + { 'H', "with-filename", Arg_parser::no }, // grep GNU + { 'i', "ignore-case", Arg_parser::no }, // grep + { 'I', 0, Arg_parser::no }, // grep GNU + { 'l', "files-with-matches", Arg_parser::no }, // grep + { 'L', "files-without-match", Arg_parser::no }, // grep GNU + { 'm', "max-count", Arg_parser::yes }, // grep GNU + { 'M', "format", Arg_parser::yes }, + { 'n', "line-number", Arg_parser::no }, // grep + { 'N', "no-rcfile", Arg_parser::no }, + { 'o', "only-matching", Arg_parser::no }, // grep + { 'O', "force-format", Arg_parser::yes }, + { 'q', "quiet", Arg_parser::no }, + { 'r', "recursive", Arg_parser::no }, + { 'R', "dereference-recursive", Arg_parser::no }, + { 's', "no-messages", Arg_parser::no }, // grep + { 'v', "invert-match", Arg_parser::no }, // grep + { 'V', "version", Arg_parser::no }, + { 'w', "word-regexp", Arg_parser::no }, // grep GNU + { 'x', "line-regexp", Arg_parser::no }, // grep + { help_opt, "help", Arg_parser::no }, + { verbose_opt, "verbose", Arg_parser::no }, + { color_opt, "color", Arg_parser::maybe }, + { 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 @@ -309,7 +312,8 @@ int main( const int argc, const char * const argv[] ) case 'o': grep_args.push_back( "-o" ); break; case 'O': format_index = parse_format_type( arg ); break; case 'q': grep_args.push_back( "-q" ); verbosity = -1; break; - case 'r': recursive = true; break; + case 'r': recursive = 1; break; + case 'R': recursive = 2; break; case 's': grep_args.push_back( "-s" ); no_messages = true; break; case 'v': grep_args.push_back( "-v" ); break; case 'V': show_version(); return 0; @@ -349,16 +353,18 @@ int main( const int argc, const char * const argv[] ) for( ; argind < parser.arguments(); ++argind ) filenames.push_back( parser.argument( argind ) ); - if( filenames.empty() ) filenames.push_back( "-" ); + if( filenames.empty() ) filenames.push_back( recursive ? "." : "-" ); if( show_name < 0 ) show_name = ( filenames.size() != 1 || recursive ); + std::string input_filename; int retval = 1; bool error = false; bool stdin_used = false; while( next_filename( filenames, input_filename, error, recursive, false, no_messages ) ) { + int infd; if( input_filename.empty() ) { if( stdin_used ) continue; else stdin_used = true; @@ -377,13 +383,13 @@ int main( const int argc, const char * const argv[] ) list_mode, show_name ); if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp; - if( input_filename.size() ) { close( infd ); infd = -1; } + if( input_filename.size() ) close( infd ); if( retval == 0 && verbosity < 0 ) break; } if( std::fclose( stdout ) != 0 ) { - show_error( "Can't close stdout", errno ); + show_error( "Error closing stdout", errno ); error = true; } if( error && ( retval != 0 || verbosity >= 0 ) ) retval = 2; |