Merging upstream version 1.8.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
482a36ad54
commit
0b238fdfef
34 changed files with 858 additions and 455 deletions
147
zcat.cc
147
zcat.cc
|
@ -1,5 +1,5 @@
|
|||
/* Zcat - decompress and concatenate files to standard output
|
||||
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
|
||||
|
@ -93,36 +93,39 @@ void show_help()
|
|||
std::printf( "Zcat copies each given file to standard output. If any given file is\n"
|
||||
"compressed, its decompressed content is used. If a given file does not\n"
|
||||
"exist, and its name does not end with one of the known extensions, zcat\n"
|
||||
"tries the compressed file names corresponding to the 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 sent to standard\n"
|
||||
"output. Data read from standard input must be of the same type; all\n"
|
||||
"uncompressed or all in the same compression format.\n"
|
||||
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||
"tries the compressed file names corresponding to the formats supported.\n"
|
||||
"\nIf a file is specified as '-', data are read from standard input,\n"
|
||||
"decompressed if needed, and sent to standard output. Data read from\n"
|
||||
"standard input must be of the same type; all uncompressed or all in the\n"
|
||||
"same 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: zcat [options] [files]\n"
|
||||
"\nExit status is 0 if no errors occurred, non-zero otherwise.\n"
|
||||
"\nOptions:\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
" -V, --version output version information and exit\n"
|
||||
" -A, --show-all equivalent to '-vET'\n"
|
||||
" -b, --number-nonblank number nonblank output lines\n"
|
||||
" -e equivalent to '-vE'\n"
|
||||
" -E, --show-ends display '$' at end of each line\n"
|
||||
" -M, --format=<list> process only the formats in <list>\n"
|
||||
" -n, --number number all output lines\n"
|
||||
" -N, --no-rcfile don't read runtime configuration file\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, --squeeze-blank never more than one single blank line\n"
|
||||
" -t equivalent to '-vT'\n"
|
||||
" -T, --show-tabs display TAB characters as '^I'\n"
|
||||
" -v, --show-nonprinting use '^' and 'M-' notation, except for LF and TAB\n"
|
||||
" --verbose verbose mode (show error messages)\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" );
|
||||
" -h, --help display this help and exit\n"
|
||||
" -V, --version output version information and exit\n"
|
||||
" -A, --show-all equivalent to '-vET'\n"
|
||||
" -b, --number-nonblank number nonblank output lines\n"
|
||||
" -e equivalent to '-vE'\n"
|
||||
" -E, --show-ends display '$' at end of each line\n"
|
||||
" -M, --format=<list> process only the formats in <list>\n"
|
||||
" -n, --number number all output lines\n"
|
||||
" -N, --no-rcfile don't read runtime configuration file\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, --squeeze-blank never more than one single blank line\n"
|
||||
" -t equivalent to '-vT'\n"
|
||||
" -T, --show-tabs display TAB characters as '^I'\n"
|
||||
" -v, --show-nonprinting use '^' and 'M-' notation, except for LF and TAB\n"
|
||||
" --verbose verbose mode (show error messages)\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" );
|
||||
show_help_addr();
|
||||
}
|
||||
|
||||
|
@ -153,7 +156,7 @@ int do_cat( const int infd, const int buffer_size,
|
|||
rd = readblock( infd, inbuf, buffer_size );
|
||||
if( rd != buffer_size && errno )
|
||||
{
|
||||
show_error2( "Error reading file", input_filename.c_str() );
|
||||
show_file_error( input_filename.c_str(), "Read error", errno );
|
||||
return 1;
|
||||
}
|
||||
if( rd == 0 )
|
||||
|
@ -226,11 +229,13 @@ int do_cat( const int infd, const int buffer_size,
|
|||
int cat( int infd, const int format_index, const std::string & input_filename,
|
||||
const Cat_options & cat_options )
|
||||
{
|
||||
enum { buffer_size = 4096 };
|
||||
// buffer with space for sentinel newline at the end
|
||||
enum { buffer_size = 4096, outbuf_size = (5 * buffer_size) + 256 + 1 };
|
||||
// buffer with space for sentinel newline at the end
|
||||
uint8_t * const inbuf = new uint8_t[buffer_size+1];
|
||||
// buffer with space for character quoting and 255-digit line number
|
||||
uint8_t * const outbuf = new uint8_t[(4*buffer_size)+256];
|
||||
// buffer with space for character quoting, 255-digit line number,
|
||||
// worst case flushing respect to inbuf, and a canary byte.
|
||||
uint8_t * const outbuf = new uint8_t[outbuf_size];
|
||||
outbuf[outbuf_size-1] = 0;
|
||||
int retval = 0;
|
||||
Children children;
|
||||
if( !set_data_feeder( input_filename, &infd, children, format_index ) )
|
||||
|
@ -243,6 +248,8 @@ int cat( int infd, const int format_index, const std::string & input_filename,
|
|||
|
||||
if( retval == 0 && close( infd ) != 0 )
|
||||
{ show_close_error(); retval = 1; }
|
||||
if( outbuf[outbuf_size-1] != 0 )
|
||||
internal_error( "buffer overflow." );
|
||||
delete[] outbuf; delete[] inbuf;
|
||||
return retval;
|
||||
}
|
||||
|
@ -253,10 +260,8 @@ int cat( int infd, const int format_index, const std::string & input_filename,
|
|||
int main( const int argc, const char * const argv[] )
|
||||
{
|
||||
enum { verbose_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt };
|
||||
int infd = -1;
|
||||
int format_index = -1;
|
||||
bool recursive = false;
|
||||
std::string input_filename;
|
||||
int recursive = 0; // 1 = '-r', 2 = '-R'
|
||||
std::list< std::string > filenames;
|
||||
Cat_options cat_options;
|
||||
invocation_name = argv[0];
|
||||
|
@ -264,33 +269,34 @@ int main( const int argc, const char * const argv[] )
|
|||
|
||||
const Arg_parser::Option options[] =
|
||||
{
|
||||
{ 'A', "show-all", Arg_parser::no }, // cat
|
||||
{ 'b', "number-nonblank", Arg_parser::no }, // cat
|
||||
{ 'c', "stdout", Arg_parser::no }, // gzip
|
||||
{ 'd', "decompress", Arg_parser::no }, // gzip
|
||||
{ 'e', 0, Arg_parser::no }, // cat
|
||||
{ 'E', "show-ends", Arg_parser::no }, // cat
|
||||
{ 'f', "force", Arg_parser::no }, // gzip
|
||||
{ 'h', "help", Arg_parser::no },
|
||||
{ 'l', "list", Arg_parser::no }, // gzip
|
||||
{ 'L', "license", Arg_parser::no }, // gzip
|
||||
{ 'M', "format", Arg_parser::yes },
|
||||
{ 'n', "number", Arg_parser::no }, // cat
|
||||
{ 'N', "no-rcfile", Arg_parser::no },
|
||||
{ 'O', "force-format", Arg_parser::yes },
|
||||
{ 'q', "quiet", Arg_parser::no },
|
||||
{ 'r', "recursive", Arg_parser::no },
|
||||
{ 's', "squeeze-blank", Arg_parser::no }, // cat
|
||||
{ 't', 0, Arg_parser::no }, // cat
|
||||
{ 'T', "show-tabs", Arg_parser::no }, // cat
|
||||
{ 'v', "show-nonprinting", Arg_parser::no }, // cat
|
||||
{ 'V', "version", Arg_parser::no },
|
||||
{ verbose_opt, "verbose", Arg_parser::no },
|
||||
{ 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', "show-all", Arg_parser::no }, // cat
|
||||
{ 'b', "number-nonblank", Arg_parser::no }, // cat
|
||||
{ 'c', "stdout", Arg_parser::no }, // gzip
|
||||
{ 'd', "decompress", Arg_parser::no }, // gzip
|
||||
{ 'e', 0, Arg_parser::no }, // cat
|
||||
{ 'E', "show-ends", Arg_parser::no }, // cat
|
||||
{ 'f', "force", Arg_parser::no }, // gzip
|
||||
{ 'h', "help", Arg_parser::no },
|
||||
{ 'l', "list", Arg_parser::no }, // gzip
|
||||
{ 'L', "license", Arg_parser::no }, // gzip
|
||||
{ 'M', "format", Arg_parser::yes },
|
||||
{ 'n', "number", Arg_parser::no }, // cat
|
||||
{ 'N', "no-rcfile", Arg_parser::no },
|
||||
{ 'O', "force-format", Arg_parser::yes },
|
||||
{ 'q', "quiet", Arg_parser::no },
|
||||
{ 'r', "recursive", Arg_parser::no },
|
||||
{ 'R', "dereference-recursive", Arg_parser::no },
|
||||
{ 's', "squeeze-blank", Arg_parser::no }, // cat
|
||||
{ 't', 0, Arg_parser::no }, // cat
|
||||
{ 'T', "show-tabs", Arg_parser::no }, // cat
|
||||
{ 'v', "show-nonprinting", Arg_parser::no }, // cat
|
||||
{ 'V', "version", Arg_parser::no },
|
||||
{ verbose_opt, "verbose", Arg_parser::no },
|
||||
{ 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
|
||||
|
@ -312,7 +318,7 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'b': cat_options.number_lines = 1; break;
|
||||
case 'c': break;
|
||||
case 'd': break;
|
||||
case 'e': cat_options.show_nonprinting = true; // fall through
|
||||
case 'e': cat_options.show_nonprinting = true; // fall through
|
||||
case 'E': cat_options.show_ends = true; break;
|
||||
case 'f': break;
|
||||
case 'h': show_help(); return 0;
|
||||
|
@ -324,9 +330,10 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'N': break;
|
||||
case 'O': format_index = parse_format_type( arg ); break;
|
||||
case 'q': verbosity = -1; break;
|
||||
case 'r': recursive = true; break;
|
||||
case 'r': recursive = 1; break;
|
||||
case 'R': recursive = 2; break;
|
||||
case 's': cat_options.squeeze_blank = true; break;
|
||||
case 't': cat_options.show_nonprinting = true; // fall through
|
||||
case 't': cat_options.show_nonprinting = true; // fall through
|
||||
case 'T': cat_options.show_tabs = true; break;
|
||||
case 'v': cat_options.show_nonprinting = true; break;
|
||||
case 'V': show_version(); return 0;
|
||||
|
@ -347,13 +354,15 @@ 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 ? "." : "-" );
|
||||
|
||||
std::string input_filename;
|
||||
int retval = 0;
|
||||
bool error = false;
|
||||
bool stdin_used = false;
|
||||
while( next_filename( filenames, input_filename, error, recursive ) )
|
||||
{
|
||||
int infd;
|
||||
if( input_filename.empty() )
|
||||
{
|
||||
if( stdin_used ) continue; else stdin_used = true;
|
||||
|
@ -368,12 +377,12 @@ int main( const int argc, const char * const argv[] )
|
|||
const int tmp = cat( infd, format_index, input_filename, cat_options );
|
||||
if( tmp > retval ) retval = tmp;
|
||||
|
||||
if( input_filename.size() ) { close( infd ); infd = -1; }
|
||||
if( input_filename.size() ) close( infd );
|
||||
}
|
||||
|
||||
if( std::fclose( stdout ) != 0 )
|
||||
{
|
||||
show_error( "Can't close stdout", errno );
|
||||
show_error( "Error closing stdout", errno );
|
||||
error = true;
|
||||
}
|
||||
if( error && retval == 0 ) retval = 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue