Adding upstream version 1.0~rc6.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f6c2e71fd5
commit
7b0aab1b8a
25 changed files with 1114 additions and 772 deletions
52
ChangeLog
52
ChangeLog
|
@ -1,14 +1,54 @@
|
||||||
|
2013-03-15 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0-rc6 released.
|
||||||
|
* zdiff.cc (set_data_feeder): Call decompressor with option "-q"
|
||||||
|
only if verbosity < 0.
|
||||||
|
* zutils.cc (set_data_feeder): Likewise.
|
||||||
|
|
||||||
|
2013-02-21 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0-rc5 released.
|
||||||
|
* main.cc (main): Zgrep now shows file names by default when
|
||||||
|
'--recursive' is selected.
|
||||||
|
* zcmp.cc: Fixed deadlock when '-n' option is used.
|
||||||
|
* main.cc: Use 'setmode' instead of '_setmode' on Windows and OS/2.
|
||||||
|
|
||||||
|
2012-12-04 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0-rc4 released.
|
||||||
|
* main.cc (main): Make 'grep_show_name' tri-state so that file name
|
||||||
|
is no prefixed to output by default when searching one file.
|
||||||
|
* zcat.cc (Line_number): Fixed a portability issue with Solaris 9.
|
||||||
|
|
||||||
|
2012-10-26 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0-rc3 released.
|
||||||
|
* Added new option '--format' to all utilities.
|
||||||
|
* Makefile.in: Added new target 'install-bin'.
|
||||||
|
|
||||||
|
2012-04-30 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0-rc2 released.
|
||||||
|
* Minor fixes.
|
||||||
|
* configure: 'datadir' renamed to 'datarootdir'.
|
||||||
|
|
||||||
|
2012-01-18 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0-rc1 released.
|
||||||
|
* Changed quote characters in messages as advised by GNU Standards.
|
||||||
|
* INSTALL: Document installing zutils along with GNU gzip.
|
||||||
|
|
||||||
2011-01-11 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
2011-01-11 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
* Version 0.9 released.
|
* Version 0.9 released.
|
||||||
* configure: Added new options `DIFF' and `GREP'.
|
* configure: Added new options 'DIFF' and 'GREP'.
|
||||||
* zcmp.cc: Fixed deadlock when files differ.
|
* zcmp.cc: Fixed deadlock when files differ.
|
||||||
* zgrep.cc: Fixed deadlock when binary file matches.
|
* zgrep.cc: Fixed deadlock when binary file matches.
|
||||||
|
|
||||||
2010-11-15 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
2010-11-15 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
* Version 0.8 released.
|
* Version 0.8 released.
|
||||||
* main.cc: Added new options `--zcat', `--zgrep' and `--ztest'.
|
* main.cc: Added new options '--zcat', '--zgrep' and '--ztest'.
|
||||||
* zcat.cc: New file implementing zcat+cat functionality in C++.
|
* zcat.cc: New file implementing zcat+cat functionality in C++.
|
||||||
* zcmp.cc: New file implementing zcmp+cmp functionality in C++.
|
* zcmp.cc: New file implementing zcmp+cmp functionality in C++.
|
||||||
* doc/zcmp.1: New file.
|
* doc/zcmp.1: New file.
|
||||||
|
@ -20,7 +60,7 @@
|
||||||
documentation because egrep and fgrep are deprecated.
|
documentation because egrep and fgrep are deprecated.
|
||||||
* ztest.cc: New file implementing ztest functionality in C++.
|
* ztest.cc: New file implementing ztest functionality in C++.
|
||||||
* Makefile.in: Added quotes to directory names.
|
* Makefile.in: Added quotes to directory names.
|
||||||
* testsuite/check.sh: Use `test.txt' instead of `COPYING' for testing.
|
* testsuite/check.sh: Use 'test.txt' instead of 'COPYING' for testing.
|
||||||
* Removed environment safeguards from configure as requested by
|
* Removed environment safeguards from configure as requested by
|
||||||
Richard Stallman. Now environment variables affect configure.
|
Richard Stallman. Now environment variables affect configure.
|
||||||
|
|
||||||
|
@ -28,14 +68,14 @@
|
||||||
|
|
||||||
* Version 0.7 released.
|
* Version 0.7 released.
|
||||||
* Added new utility; ztest.
|
* Added new utility; ztest.
|
||||||
* zcat.in: Added new option `--recursive'.
|
* zcat.in: Added new option '--recursive'.
|
||||||
|
|
||||||
2009-10-05 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
2009-10-05 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
* Version 0.6 released.
|
* Version 0.6 released.
|
||||||
* zcat.in, zgrep.in: Removed again default compressor. Format of
|
* zcat.in, zgrep.in: Removed again default compressor. Format of
|
||||||
data read from stdin is now automatically detected.
|
data read from stdin is now automatically detected.
|
||||||
* Makefile.in: Added `--name' option to help2man invocation.
|
* Makefile.in: Added '--name' option to help2man invocation.
|
||||||
|
|
||||||
2009-10-01 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
2009-10-01 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
@ -66,7 +106,7 @@
|
||||||
* Version 0.1 released.
|
* Version 0.1 released.
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This file is a collection of facts, and thus it is not copyrightable,
|
This file is a collection of facts, and thus it is not copyrightable,
|
||||||
but just in case, you have unlimited permission to copy, distribute and
|
but just in case, you have unlimited permission to copy, distribute and
|
||||||
|
|
39
INSTALL
39
INSTALL
|
@ -1,10 +1,19 @@
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
You will need a C++ compiler.
|
You will need a C++ compiler.
|
||||||
I use gcc 4.3.5 and 3.3.6, but the code should compile with any
|
I use gcc 4.7.2 and 3.3.6, but the code should compile with any
|
||||||
standards compliant compiler.
|
standards compliant compiler.
|
||||||
Gcc is available at http://gcc.gnu.org.
|
Gcc is available at http://gcc.gnu.org.
|
||||||
|
|
||||||
|
If you are installing zutils along with GNU gzip and want to keep the
|
||||||
|
gzip scripts, the recommended method is to configure gzip as follows:
|
||||||
|
|
||||||
|
./configure --program-transform-name='s/^z/gz/'
|
||||||
|
|
||||||
|
This renames, at installation time, the gzip scripts and man pages to
|
||||||
|
'gzcat', 'gzcat.1', etc, avoiding the name clashing with the programs
|
||||||
|
and man pages from zutils.
|
||||||
|
|
||||||
|
|
||||||
Procedure
|
Procedure
|
||||||
---------
|
---------
|
||||||
|
@ -18,7 +27,7 @@ This creates the directory ./zutils[version] containing the source from
|
||||||
the main archive.
|
the main archive.
|
||||||
|
|
||||||
2. Change to zutils directory and run configure.
|
2. Change to zutils directory and run configure.
|
||||||
(Try `configure --help' for usage instructions).
|
(Try 'configure --help' for usage instructions).
|
||||||
|
|
||||||
cd zutils[version]
|
cd zutils[version]
|
||||||
./configure
|
./configure
|
||||||
|
@ -27,30 +36,34 @@ the main archive.
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
4. Optionally, type `make check' to run the tests that come with zutils.
|
4. Optionally, type 'make check' to run the tests that come with zutils.
|
||||||
|
|
||||||
5. Type `make install' to install the programs and any data files and
|
5. Type 'make install' to install the programs and any data files and
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
|
You can install only the programs, the info manual or the man pages
|
||||||
|
typing 'make install-bin', 'make install-info' or 'make install-man'
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
|
||||||
Another way
|
Another way
|
||||||
-----------
|
-----------
|
||||||
You can also compile zutils into a separate directory. To do this, you
|
You can also compile zutils into a separate directory. To do this, you
|
||||||
must use a version of `make' that supports the `VPATH' variable, such
|
must use a version of 'make' that supports the 'VPATH' variable, such
|
||||||
as GNU `make'. `cd' to the directory where you want the object files
|
as GNU 'make'. 'cd' to the directory where you want the object files
|
||||||
and executables to go and run the `configure' script. `configure'
|
and executables to go and run the 'configure' script. 'configure'
|
||||||
automatically checks for the source code in `.', in `..' and in the
|
automatically checks for the source code in '.', in '..' and in the
|
||||||
directory that `configure' is in.
|
directory that 'configure' is in.
|
||||||
|
|
||||||
`configure' recognizes the option `--srcdir=DIR' to control where to
|
'configure' recognizes the option '--srcdir=DIR' to control where to
|
||||||
look for the sources. Usually `configure' can determine that directory
|
look for the sources. Usually 'configure' can determine that directory
|
||||||
automatically.
|
automatically.
|
||||||
|
|
||||||
After running `configure', you can run `make' and `make install' as
|
After running 'configure', you can run 'make' and 'make install' as
|
||||||
explained above.
|
explained above.
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This file is free documentation: you have unlimited permission to copy,
|
This file is free documentation: you have unlimited permission to copy,
|
||||||
distribute and modify it.
|
distribute and modify it.
|
||||||
|
|
23
Makefile.in
23
Makefile.in
|
@ -13,8 +13,8 @@ zdiff_objs = arg_parser.o zutils.o zdiff.o
|
||||||
scripts = zcat zegrep zfgrep zgrep ztest
|
scripts = zcat zegrep zfgrep zgrep ztest
|
||||||
|
|
||||||
|
|
||||||
.PHONY : all install install-info install-man install-strip \
|
.PHONY : all install install-bin install-info install-man install-strip \
|
||||||
uninstall uninstall-info uninstall-man \
|
uninstall uninstall-bin uninstall-info uninstall-man \
|
||||||
doc info man check dist clean distclean
|
doc info man check dist clean distclean
|
||||||
|
|
||||||
all : $(progname) zcmp zdiff $(scripts)
|
all : $(progname) zcmp zdiff $(scripts)
|
||||||
|
@ -67,10 +67,11 @@ $(objs) : Makefile
|
||||||
$(scripts) : Makefile
|
$(scripts) : Makefile
|
||||||
arg_parser.o : arg_parser.h
|
arg_parser.o : arg_parser.h
|
||||||
main.o : arg_parser.h zutils.h zcat.cc zgrep.cc ztest.cc
|
main.o : arg_parser.h zutils.h zcat.cc zgrep.cc ztest.cc
|
||||||
zcmp.o : arg_parser.h zutils.h Makefile
|
zcmp.o : arg_parser.h zutils.h zcmpdiff.cc Makefile
|
||||||
zdiff.o : arg_parser.h zutils.h Makefile
|
zdiff.o : arg_parser.h zutils.h zcmpdiff.cc Makefile
|
||||||
zutils.o : zutils.h
|
zutils.o : zutils.h
|
||||||
|
|
||||||
|
|
||||||
doc : info man
|
doc : info man
|
||||||
|
|
||||||
info : $(VPATH)/doc/$(pkgname).info
|
info : $(VPATH)/doc/$(pkgname).info
|
||||||
|
@ -107,7 +108,9 @@ Makefile : $(VPATH)/configure $(VPATH)/Makefile.in
|
||||||
check : all
|
check : all
|
||||||
@$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion)
|
@$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion)
|
||||||
|
|
||||||
install : all install-info install-man
|
install : install-bin install-info install-man
|
||||||
|
|
||||||
|
install-bin : all
|
||||||
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
|
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
|
||||||
$(INSTALL_PROGRAM) ./$(progname) "$(DESTDIR)$(bindir)/$(progname)"
|
$(INSTALL_PROGRAM) ./$(progname) "$(DESTDIR)$(bindir)/$(progname)"
|
||||||
$(INSTALL_SCRIPT) ./zcat "$(DESTDIR)$(bindir)/zcat"
|
$(INSTALL_SCRIPT) ./zcat "$(DESTDIR)$(bindir)/zcat"
|
||||||
|
@ -121,7 +124,7 @@ install : all install-info install-man
|
||||||
install-info :
|
install-info :
|
||||||
if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi
|
if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi
|
||||||
$(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info"
|
$(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||||
-install-info --info-dir="$(DESTDIR)$(infodir)" $(DESTDIR)$(infodir)/$(pkgname).info
|
-install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||||
|
|
||||||
install-man :
|
install-man :
|
||||||
if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi
|
if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi
|
||||||
|
@ -129,14 +132,14 @@ install-man :
|
||||||
$(INSTALL_DATA) $(VPATH)/doc/zcmp.1 "$(DESTDIR)$(mandir)/man1/zcmp.1"
|
$(INSTALL_DATA) $(VPATH)/doc/zcmp.1 "$(DESTDIR)$(mandir)/man1/zcmp.1"
|
||||||
$(INSTALL_DATA) $(VPATH)/doc/zdiff.1 "$(DESTDIR)$(mandir)/man1/zdiff.1"
|
$(INSTALL_DATA) $(VPATH)/doc/zdiff.1 "$(DESTDIR)$(mandir)/man1/zdiff.1"
|
||||||
$(INSTALL_DATA) $(VPATH)/doc/zgrep.1 "$(DESTDIR)$(mandir)/man1/zgrep.1"
|
$(INSTALL_DATA) $(VPATH)/doc/zgrep.1 "$(DESTDIR)$(mandir)/man1/zgrep.1"
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zegrep.1"
|
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zfgrep.1"
|
|
||||||
$(INSTALL_DATA) $(VPATH)/doc/ztest.1 "$(DESTDIR)$(mandir)/man1/ztest.1"
|
$(INSTALL_DATA) $(VPATH)/doc/ztest.1 "$(DESTDIR)$(mandir)/man1/ztest.1"
|
||||||
|
|
||||||
install-strip : all
|
install-strip : all
|
||||||
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||||
|
|
||||||
uninstall : uninstall-info uninstall-man
|
uninstall : uninstall-bin uninstall-info uninstall-man
|
||||||
|
|
||||||
|
uninstall-bin :
|
||||||
-rm -f "$(DESTDIR)$(bindir)/$(progname)"
|
-rm -f "$(DESTDIR)$(bindir)/$(progname)"
|
||||||
-rm -f "$(DESTDIR)$(bindir)/zcat"
|
-rm -f "$(DESTDIR)$(bindir)/zcat"
|
||||||
-rm -f "$(DESTDIR)$(bindir)/zcmp"
|
-rm -f "$(DESTDIR)$(bindir)/zcmp"
|
||||||
|
@ -154,8 +157,6 @@ uninstall-man :
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zcat.1"
|
-rm -f "$(DESTDIR)$(mandir)/man1/zcat.1"
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zcmp.1"
|
-rm -f "$(DESTDIR)$(mandir)/man1/zcmp.1"
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zdiff.1"
|
-rm -f "$(DESTDIR)$(mandir)/man1/zdiff.1"
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zegrep.1"
|
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zfgrep.1"
|
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/zgrep.1"
|
-rm -f "$(DESTDIR)$(mandir)/man1/zgrep.1"
|
||||||
-rm -f "$(DESTDIR)$(mandir)/man1/ztest.1"
|
-rm -f "$(DESTDIR)$(mandir)/man1/ztest.1"
|
||||||
|
|
||||||
|
|
28
NEWS
28
NEWS
|
@ -1,8 +1,26 @@
|
||||||
Changes in version 0.9:
|
Changes in version 1.0:
|
||||||
|
|
||||||
Configure now allows the selection of diff and grep programs to use.
|
The new option "--format" has been added to all utilities.
|
||||||
|
|
||||||
A deadlock in zcmp.cc, which happened when files differ, has been fixed.
|
Zgrep no more prefixes the file name to the output by default when
|
||||||
|
searching one file and "--recursive" has not been selected.
|
||||||
|
|
||||||
A deadlock in zgrep.cc, which happened when a binary file matches, has
|
A deadlock in zcmp, which happens when the "-n" option is used, has been
|
||||||
been fixed.
|
fixed.
|
||||||
|
|
||||||
|
Decompressors are now invoked without the "-q" option except if
|
||||||
|
explicitly requested, as some simplified implementations do not accept
|
||||||
|
it.
|
||||||
|
|
||||||
|
Minor fixes.
|
||||||
|
|
||||||
|
Quote characters in messages have been changed as advised by GNU Coding
|
||||||
|
Standards.
|
||||||
|
|
||||||
|
Configure option "--datadir" has been renamed to "--datarootdir" to
|
||||||
|
follow GNU Standards.
|
||||||
|
|
||||||
|
The target "install-bin" has been added to the Makefile.
|
||||||
|
|
||||||
|
Information has been added to the INSTALL file about how to install
|
||||||
|
zutils along with GNU gzip.
|
||||||
|
|
15
README
15
README
|
@ -4,15 +4,20 @@ Zutils is a collection of utilities able to deal with any combination of
|
||||||
compressed and non-compressed files transparently. If any given file,
|
compressed and non-compressed files transparently. If any given file,
|
||||||
including standard input, is compressed, its uncompressed content is
|
including standard input, is compressed, its uncompressed content is
|
||||||
used. Compressed files are decompressed on the fly; no temporary files
|
used. Compressed files are decompressed on the fly; no temporary files
|
||||||
are created. These utilities are not wrapper scripts but safer and more
|
are created.
|
||||||
efficient C++ programs. In particular the "--recursive" option is very
|
|
||||||
efficient in those utilities supporting it.
|
These utilities are not wrapper scripts but safer and more efficient C++
|
||||||
|
programs. In particular the "--recursive" option is very efficient in
|
||||||
|
those utilities supporting it.
|
||||||
|
|
||||||
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.
|
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
|
|
||||||
|
Zcat, zcmp, zdiff, and zgrep are improved replacements for the shell
|
||||||
|
scripts provided with GNU gzip. Ztest is unique to zutils.
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This file is free documentation: you have unlimited permission to copy,
|
This file is free documentation: you have unlimited permission to copy,
|
||||||
distribute and modify it.
|
distribute and modify it.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* Arg_parser - A POSIX/GNU command line argument parser. (C++ version)
|
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
|
||||||
Copyright (C) 2006, 2007, 2008, 2009, 2010 Antonio Diaz Diaz.
|
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
|
||||||
|
Antonio Diaz Diaz.
|
||||||
|
|
||||||
This library is free software: you can redistribute it and/or modify
|
This library is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
bool Arg_parser::parse_long_option( const char * const opt, const char * const arg,
|
bool Arg_parser::parse_long_option( const char * const opt, const char * const arg,
|
||||||
const Option options[], int & argind )
|
const Option options[], int & argind )
|
||||||
{
|
{
|
||||||
unsigned int len;
|
unsigned len;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
bool exact = false, ambig = false;
|
bool exact = false, ambig = false;
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a
|
||||||
|
|
||||||
// Test all long options for either exact match or abbreviated matches.
|
// Test all long options for either exact match or abbreviated matches.
|
||||||
for( int i = 0; options[i].code != 0; ++i )
|
for( int i = 0; options[i].code != 0; ++i )
|
||||||
if( options[i].name && !std::strncmp( options[i].name, &opt[2], len ) )
|
if( options[i].name && std::strncmp( options[i].name, &opt[2], len ) == 0 )
|
||||||
{
|
{
|
||||||
if( std::strlen( options[i].name ) == len ) // Exact match found
|
if( std::strlen( options[i].name ) == len ) // Exact match found
|
||||||
{ index = i; exact = true; break; }
|
{ index = i; exact = true; break; }
|
||||||
|
@ -55,30 +56,30 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a
|
||||||
|
|
||||||
if( ambig && !exact )
|
if( ambig && !exact )
|
||||||
{
|
{
|
||||||
error_ = "option `"; error_ += opt; error_ += "' is ambiguous";
|
error_ = "option '"; error_ += opt; error_ += "' is ambiguous";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( index < 0 ) // nothing found
|
if( index < 0 ) // nothing found
|
||||||
{
|
{
|
||||||
error_ = "unrecognized option `"; error_ += opt; error_ += '\'';
|
error_ = "unrecognized option '"; error_ += opt; error_ += '\'';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
++argind;
|
++argind;
|
||||||
data.push_back( Record( options[index].code ) );
|
data.push_back( Record( options[index].code ) );
|
||||||
|
|
||||||
if( opt[len+2] ) // `--<long_option>=<argument>' syntax
|
if( opt[len+2] ) // '--<long_option>=<argument>' syntax
|
||||||
{
|
{
|
||||||
if( options[index].has_arg == no )
|
if( options[index].has_arg == no )
|
||||||
{
|
{
|
||||||
error_ = "option `--"; error_ += options[index].name;
|
error_ = "option '--"; error_ += options[index].name;
|
||||||
error_ += "' doesn't allow an argument";
|
error_ += "' doesn't allow an argument";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if( options[index].has_arg == yes && !opt[len+3] )
|
if( options[index].has_arg == yes && !opt[len+3] )
|
||||||
{
|
{
|
||||||
error_ = "option `--"; error_ += options[index].name;
|
error_ = "option '--"; error_ += options[index].name;
|
||||||
error_ += "' requires an argument";
|
error_ += "' requires an argument";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,7 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a
|
||||||
{
|
{
|
||||||
if( !arg || !arg[0] )
|
if( !arg || !arg[0] )
|
||||||
{
|
{
|
||||||
error_ = "option `--"; error_ += options[index].name;
|
error_ = "option '--"; error_ += options[index].name;
|
||||||
error_ += "' requires an argument";
|
error_ += "' requires an argument";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +178,7 @@ Arg_parser::Arg_parser( const int argc, const char * const argv[],
|
||||||
if( error_.size() ) data.clear();
|
if( error_.size() ) data.clear();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for( unsigned int i = 0; i < non_options.size(); ++i )
|
for( unsigned i = 0; i < non_options.size(); ++i )
|
||||||
{ data.push_back( Record() ); data.back().argument.swap( non_options[i] ); }
|
{ data.push_back( Record() ); data.back().argument.swap( non_options[i] ); }
|
||||||
while( argind < argc )
|
while( argind < argc )
|
||||||
{ data.push_back( Record() ); data.back().argument = argv[argind++]; }
|
{ data.push_back( Record() ); data.back().argument = argv[argind++]; }
|
||||||
|
|
29
arg_parser.h
29
arg_parser.h
|
@ -1,5 +1,6 @@
|
||||||
/* Arg_parser - A POSIX/GNU command line argument parser. (C++ version)
|
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
|
||||||
Copyright (C) 2006, 2007, 2008, 2009, 2010 Antonio Diaz Diaz.
|
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
|
||||||
|
Antonio Diaz Diaz.
|
||||||
|
|
||||||
This library is free software: you can redistribute it and/or modify
|
This library is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,12 +26,12 @@
|
||||||
Public License.
|
Public License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Arg_parser reads the arguments in `argv' and creates a number of
|
/* Arg_parser reads the arguments in 'argv' and creates a number of
|
||||||
option codes, option arguments and non-option arguments.
|
option codes, option arguments and non-option arguments.
|
||||||
|
|
||||||
In case of error, `error' returns a non-empty error message.
|
In case of error, 'error' returns a non-empty error message.
|
||||||
|
|
||||||
`options' is an array of `struct Option' terminated by an element
|
'options' is an array of 'struct Option' terminated by an element
|
||||||
containing a code which is zero. A null name means a short-only
|
containing a code which is zero. A null name means a short-only
|
||||||
option. A code value outside the unsigned char range means a
|
option. A code value outside the unsigned char range means a
|
||||||
long-only option.
|
long-only option.
|
||||||
|
@ -39,13 +40,13 @@
|
||||||
were specified before all the non-option arguments for the purposes
|
were specified before all the non-option arguments for the purposes
|
||||||
of parsing, even if the user of your program intermixed option and
|
of parsing, even if the user of your program intermixed option and
|
||||||
non-option arguments. If you want the arguments in the exact order
|
non-option arguments. If you want the arguments in the exact order
|
||||||
the user typed them, call `Arg_parser' with `in_order' = true.
|
the user typed them, call 'Arg_parser' with 'in_order' = true.
|
||||||
|
|
||||||
The argument `--' terminates all options; any following arguments are
|
The argument '--' terminates all options; any following arguments are
|
||||||
treated as non-option arguments, even if they begin with a hyphen.
|
treated as non-option arguments, even if they begin with a hyphen.
|
||||||
|
|
||||||
The syntax for optional option arguments is `-<short_option><argument>'
|
The syntax for optional option arguments is '-<short_option><argument>'
|
||||||
(without whitespace), or `--<long_option>=<argument>'.
|
(without whitespace), or '--<long_option>=<argument>'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Arg_parser
|
class Arg_parser
|
||||||
|
@ -65,7 +66,7 @@ private:
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
std::string argument;
|
std::string argument;
|
||||||
Record( const int c = 0 ) : code( c ) {}
|
explicit Record( const int c = 0 ) : code( c ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string error_;
|
std::string error_;
|
||||||
|
@ -84,20 +85,20 @@ public:
|
||||||
Arg_parser( const char * const opt, const char * const arg,
|
Arg_parser( const char * const opt, const char * const arg,
|
||||||
const Option options[] );
|
const Option options[] );
|
||||||
|
|
||||||
const std::string & error() const throw() { return error_; }
|
const std::string & error() const { return error_; }
|
||||||
|
|
||||||
// The number of arguments parsed (may be different from argc)
|
// The number of arguments parsed (may be different from argc)
|
||||||
int arguments() const throw() { return data.size(); }
|
int arguments() const { return data.size(); }
|
||||||
|
|
||||||
// If code( i ) is 0, argument( i ) is a non-option.
|
// If code( i ) is 0, argument( i ) is a non-option.
|
||||||
// Else argument( i ) is the option's argument (or empty).
|
// Else argument( i ) is the option's argument (or empty).
|
||||||
int code( const int i ) const throw()
|
int code( const int i ) const
|
||||||
{
|
{
|
||||||
if( i >= 0 && i < arguments() ) return data[i].code;
|
if( i >= 0 && i < arguments() ) return data[i].code;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & argument( const int i ) const throw()
|
const std::string & argument( const int i ) const
|
||||||
{
|
{
|
||||||
if( i >= 0 && i < arguments() ) return data[i].argument;
|
if( i >= 0 && i < arguments() ) return data[i].argument;
|
||||||
else return error_;
|
else return error_;
|
||||||
|
|
91
configure
vendored
91
configure
vendored
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# configure script for Zutils - Utilities dealing with compressed files
|
# configure script for Zutils - Utilities dealing with compressed files
|
||||||
# Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz.
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
#
|
#
|
||||||
# This configure script is free software: you have unlimited permission
|
# This configure script is free software: you have unlimited permission
|
||||||
# to copy, distribute and modify it.
|
# to copy, distribute and modify it.
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
args=
|
args=
|
||||||
no_create=
|
no_create=
|
||||||
pkgname=zutils
|
pkgname=zutils
|
||||||
pkgversion=0.9
|
pkgversion=1.0-rc6
|
||||||
progname=zutils
|
progname=zutils
|
||||||
srctrigger=zutils.h
|
srctrigger=zutils.h
|
||||||
|
|
||||||
|
@ -19,18 +19,23 @@ srcdir=
|
||||||
prefix=/usr/local
|
prefix=/usr/local
|
||||||
exec_prefix='$(prefix)'
|
exec_prefix='$(prefix)'
|
||||||
bindir='$(exec_prefix)/bin'
|
bindir='$(exec_prefix)/bin'
|
||||||
datadir='$(prefix)/share'
|
datarootdir='$(prefix)/share'
|
||||||
infodir='$(datadir)/info'
|
infodir='$(datarootdir)/info'
|
||||||
mandir='$(datadir)/man'
|
mandir='$(datarootdir)/man'
|
||||||
sysconfdir='$(prefix)/etc'
|
CXX=g++
|
||||||
|
CPPFLAGS=
|
||||||
|
CXXFLAGS='-Wall -W -O2'
|
||||||
|
LDFLAGS=
|
||||||
DIFF=diff
|
DIFF=diff
|
||||||
GREP=grep
|
GREP=grep
|
||||||
|
|
||||||
if [ -n "${CXX}" ] ; then args="${args} CXX=\"${CXX}\"" ; fi
|
# checking whether we are using GNU C++.
|
||||||
if [ -n "${CPPFLAGS}" ] ; then args="${args} CPPFLAGS=\"${CPPFLAGS}\"" ; fi
|
if [ ! -x /bin/g++ ] &&
|
||||||
if [ -n "${CXXFLAGS}" ] ; then args="${args} CXXFLAGS=\"${CXXFLAGS}\""
|
[ ! -x /usr/bin/g++ ] &&
|
||||||
else CXXFLAGS='-Wall -W -O2' ; fi
|
[ ! -x /usr/local/bin/g++ ] ; then
|
||||||
if [ -n "${LDFLAGS}" ] ; then args="${args} LDFLAGS=\"${LDFLAGS}\"" ; fi
|
CXX=c++
|
||||||
|
CXXFLAGS='-W -O2'
|
||||||
|
fi
|
||||||
|
|
||||||
# Loop over all args
|
# Loop over all args
|
||||||
while [ -n "$1" ] ; do
|
while [ -n "$1" ] ; do
|
||||||
|
@ -44,12 +49,12 @@ while [ -n "$1" ] ; do
|
||||||
|
|
||||||
# Split out the argument for options that take them
|
# Split out the argument for options that take them
|
||||||
case ${option} in
|
case ${option} in
|
||||||
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,'` ;;
|
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Process the options
|
# Process the options
|
||||||
case ${option} in
|
case ${option} in
|
||||||
--help | --he* | -h)
|
--help | -h)
|
||||||
echo "Usage: configure [options]"
|
echo "Usage: configure [options]"
|
||||||
echo
|
echo
|
||||||
echo "Options: [defaults in brackets]"
|
echo "Options: [defaults in brackets]"
|
||||||
|
@ -59,10 +64,9 @@ while [ -n "$1" ] ; do
|
||||||
echo " --prefix=DIR install into DIR [${prefix}]"
|
echo " --prefix=DIR install into DIR [${prefix}]"
|
||||||
echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]"
|
echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]"
|
||||||
echo " --bindir=DIR user executables directory [${bindir}]"
|
echo " --bindir=DIR user executables directory [${bindir}]"
|
||||||
echo " --datadir=DIR base directory for doc and data [${datadir}]"
|
echo " --datarootdir=DIR base directory for doc and data [${datarootdir}]"
|
||||||
echo " --infodir=DIR info files directory [${infodir}]"
|
echo " --infodir=DIR info files directory [${infodir}]"
|
||||||
echo " --mandir=DIR man pages directory [${mandir}]"
|
echo " --mandir=DIR man pages directory [${mandir}]"
|
||||||
echo " --sysconfdir=DIR read-only single-machine data directory [${sysconfdir}]"
|
|
||||||
echo " CXX=COMPILER C++ compiler to use [g++]"
|
echo " CXX=COMPILER C++ compiler to use [g++]"
|
||||||
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
|
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
|
||||||
echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]"
|
echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]"
|
||||||
|
@ -71,27 +75,17 @@ while [ -n "$1" ] ; do
|
||||||
echo " GREP=NAME grep program to use with zgrep [grep]"
|
echo " GREP=NAME grep program to use with zgrep [grep]"
|
||||||
echo
|
echo
|
||||||
exit 0 ;;
|
exit 0 ;;
|
||||||
--version | --ve* | -V)
|
--version | -V)
|
||||||
echo "Configure script for ${pkgname} version ${pkgversion}"
|
echo "Configure script for ${pkgname} version ${pkgversion}"
|
||||||
exit 0 ;;
|
exit 0 ;;
|
||||||
--srcdir* | --sr*)
|
--srcdir=*) srcdir=${optarg} ;;
|
||||||
srcdir=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
--prefix=*) prefix=${optarg} ;;
|
||||||
--prefix* | --pr*)
|
--exec-prefix=*) exec_prefix=${optarg} ;;
|
||||||
prefix=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
--bindir=*) bindir=${optarg} ;;
|
||||||
--exec-prefix* | --ex*)
|
--datarootdir=*) datarootdir=${optarg} ;;
|
||||||
exec_prefix=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
--infodir=*) infodir=${optarg} ;;
|
||||||
--bindir* | --bi*)
|
--mandir=*) mandir=${optarg} ;;
|
||||||
bindir=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
--no-create) no_create=yes ;;
|
||||||
--datadir* | --da*)
|
|
||||||
datadir=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
|
||||||
--infodir* | --inf*)
|
|
||||||
infodir=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
|
||||||
--mandir* | --ma*)
|
|
||||||
mandir=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
|
||||||
--sysconfdir* | --sy*)
|
|
||||||
sysconfdir=`echo ${optarg} | sed -e 's,/$,,'` ;;
|
|
||||||
--no-create | --no-c*)
|
|
||||||
no_create=yes ;;
|
|
||||||
|
|
||||||
CXX=*) CXX=${optarg} ;;
|
CXX=*) CXX=${optarg} ;;
|
||||||
CPPFLAGS=*) CPPFLAGS=${optarg} ;;
|
CPPFLAGS=*) CPPFLAGS=${optarg} ;;
|
||||||
|
@ -111,14 +105,14 @@ done
|
||||||
srcdirtext=
|
srcdirtext=
|
||||||
if [ -z "${srcdir}" ] ; then
|
if [ -z "${srcdir}" ] ; then
|
||||||
srcdirtext="or . or .." ; srcdir=.
|
srcdirtext="or . or .." ; srcdir=.
|
||||||
if [ ! -r ${srcdir}/${srctrigger} ] ; then srcdir=.. ; fi
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi
|
||||||
if [ ! -r ${srcdir}/${srctrigger} ] ; then
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||||
## the sed command below emulates the dirname command
|
## the sed command below emulates the dirname command
|
||||||
srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -r ${srcdir}/${srctrigger} ] ; then
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||||
exec 1>&2
|
exec 1>&2
|
||||||
echo
|
echo
|
||||||
echo "configure: Can't find sources in ${srcdir} ${srcdirtext}"
|
echo "configure: Can't find sources in ${srcdir} ${srcdirtext}"
|
||||||
|
@ -127,18 +121,7 @@ if [ ! -r ${srcdir}/${srctrigger} ] ; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set srcdir to . if that's what it is.
|
# Set srcdir to . if that's what it is.
|
||||||
if [ "`pwd`" = "`cd ${srcdir} ; pwd`" ] ; then srcdir=. ; fi
|
if [ "`pwd`" = "`cd "${srcdir}" ; pwd`" ] ; then srcdir=. ; fi
|
||||||
|
|
||||||
# checking whether we are using GNU C++.
|
|
||||||
if [ -z "${CXX}" ] ; then # Let the user override the test.
|
|
||||||
if [ -x /bin/g++ ] ||
|
|
||||||
[ -x /usr/bin/g++ ] ||
|
|
||||||
[ -x /usr/local/bin/g++ ] ; then
|
|
||||||
CXX="g++"
|
|
||||||
else
|
|
||||||
CXX="c++"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
if [ -z "${no_create}" ] ; then
|
if [ -z "${no_create}" ] ; then
|
||||||
|
@ -162,10 +145,9 @@ echo "VPATH = ${srcdir}"
|
||||||
echo "prefix = ${prefix}"
|
echo "prefix = ${prefix}"
|
||||||
echo "exec_prefix = ${exec_prefix}"
|
echo "exec_prefix = ${exec_prefix}"
|
||||||
echo "bindir = ${bindir}"
|
echo "bindir = ${bindir}"
|
||||||
echo "datadir = ${datadir}"
|
echo "datarootdir = ${datarootdir}"
|
||||||
echo "infodir = ${infodir}"
|
echo "infodir = ${infodir}"
|
||||||
echo "mandir = ${mandir}"
|
echo "mandir = ${mandir}"
|
||||||
echo "sysconfdir = ${sysconfdir}"
|
|
||||||
echo "CXX = ${CXX}"
|
echo "CXX = ${CXX}"
|
||||||
echo "CPPFLAGS = ${CPPFLAGS}"
|
echo "CPPFLAGS = ${CPPFLAGS}"
|
||||||
echo "CXXFLAGS = ${CXXFLAGS}"
|
echo "CXXFLAGS = ${CXXFLAGS}"
|
||||||
|
@ -175,7 +157,7 @@ echo "GREP = ${GREP}"
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
cat > Makefile << EOF
|
cat > Makefile << EOF
|
||||||
# Makefile for Zutils - Utilities dealing with compressed files
|
# Makefile for Zutils - Utilities dealing with compressed files
|
||||||
# Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz.
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
# This file was generated automatically by configure. Do not edit.
|
# This file was generated automatically by configure. Do not edit.
|
||||||
#
|
#
|
||||||
# This Makefile is free software: you have unlimited permission
|
# This Makefile is free software: you have unlimited permission
|
||||||
|
@ -188,10 +170,9 @@ VPATH = ${srcdir}
|
||||||
prefix = ${prefix}
|
prefix = ${prefix}
|
||||||
exec_prefix = ${exec_prefix}
|
exec_prefix = ${exec_prefix}
|
||||||
bindir = ${bindir}
|
bindir = ${bindir}
|
||||||
datadir = ${datadir}
|
datarootdir = ${datarootdir}
|
||||||
infodir = ${infodir}
|
infodir = ${infodir}
|
||||||
mandir = ${mandir}
|
mandir = ${mandir}
|
||||||
sysconfdir = ${sysconfdir}
|
|
||||||
CXX = ${CXX}
|
CXX = ${CXX}
|
||||||
CPPFLAGS = ${CPPFLAGS}
|
CPPFLAGS = ${CPPFLAGS}
|
||||||
CXXFLAGS = ${CXXFLAGS}
|
CXXFLAGS = ${CXXFLAGS}
|
||||||
|
@ -199,6 +180,6 @@ LDFLAGS = ${LDFLAGS}
|
||||||
DIFF = ${DIFF}
|
DIFF = ${DIFF}
|
||||||
GREP = ${GREP}
|
GREP = ${GREP}
|
||||||
EOF
|
EOF
|
||||||
cat ${srcdir}/Makefile.in >> Makefile
|
cat "${srcdir}/Makefile.in" >> Makefile
|
||||||
|
|
||||||
echo "OK. Now you can run make."
|
echo "OK. Now you can run make."
|
||||||
|
|
26
doc/zcat.1
26
doc/zcat.1
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZCAT "1" "January 2011" "Zcat (zutils) 0.9" "User Commands"
|
.TH ZCAT "1" "March 2013" "Zcat (zutils) 1.0-rc6" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zcat \- decompress and concatenate files to standard output
|
Zcat \- decompress and concatenate files to standard output
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -10,11 +10,12 @@ Zcat copies each given file ("\-" means standard input), to standard
|
||||||
output. If any given file is compressed, its uncompressed content is
|
output. If any given file is compressed, its uncompressed content is
|
||||||
used. If a given file does not exist, and its name does not end with one
|
used. If a given file does not exist, and its name does not end with one
|
||||||
of the known extensions, zcat tries the compressed file names
|
of the known extensions, zcat tries the compressed file names
|
||||||
corresponding to the supported compressors. If no files are specified,
|
corresponding to the supported formats. If no files are specified,
|
||||||
data is read from standard input, decompressed if needed, and sent to
|
data is read from standard input, decompressed if needed, and sent to
|
||||||
standard output. Data read from standard input must be of the same type;
|
standard output. Data read from standard input must be of the same type;
|
||||||
all uncompressed or all compressed with the same compressor.
|
all uncompressed or all in the same compression format.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
.PP
|
||||||
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
.PP
|
.PP
|
||||||
Exit status is 0 if no errors occurred, 1 otherwise.
|
Exit status is 0 if no errors occurred, 1 otherwise.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
@ -26,16 +27,19 @@ display this help and exit
|
||||||
output version information and exit
|
output version information and exit
|
||||||
.TP
|
.TP
|
||||||
\fB\-A\fR, \fB\-\-show\-all\fR
|
\fB\-A\fR, \fB\-\-show\-all\fR
|
||||||
equivalent to `\-vET'
|
equivalent to '\-vET'
|
||||||
.TP
|
.TP
|
||||||
\fB\-b\fR, \fB\-\-number\-nonblank\fR
|
\fB\-b\fR, \fB\-\-number\-nonblank\fR
|
||||||
number nonblank output lines
|
number nonblank output lines
|
||||||
.TP
|
.TP
|
||||||
\fB\-e\fR
|
\fB\-e\fR
|
||||||
equivalent to `\-vE'
|
equivalent to '\-vE'
|
||||||
.TP
|
.TP
|
||||||
\fB\-E\fR, \fB\-\-show\-ends\fR
|
\fB\-E\fR, \fB\-\-show\-ends\fR
|
||||||
display `$' at end of each line
|
display '$' at end of each line
|
||||||
|
.TP
|
||||||
|
\fB\-\-format=\fR<fmt>
|
||||||
|
force given format (bz2, gz, lz, xz)
|
||||||
.TP
|
.TP
|
||||||
\fB\-n\fR, \fB\-\-number\fR
|
\fB\-n\fR, \fB\-\-number\fR
|
||||||
number all output lines
|
number all output lines
|
||||||
|
@ -50,13 +54,13 @@ operate recursively on directories
|
||||||
never more than one single blank line
|
never more than one single blank line
|
||||||
.TP
|
.TP
|
||||||
\fB\-t\fR
|
\fB\-t\fR
|
||||||
equivalent to `\-vT'
|
equivalent to '\-vT'
|
||||||
.TP
|
.TP
|
||||||
\fB\-T\fR, \fB\-\-show\-tabs\fR
|
\fB\-T\fR, \fB\-\-show\-tabs\fR
|
||||||
display TAB characters as `^I'
|
display TAB characters as '^I'
|
||||||
.TP
|
.TP
|
||||||
\fB\-v\fR, \fB\-\-show\-nonprinting\fR
|
\fB\-v\fR, \fB\-\-show\-nonprinting\fR
|
||||||
use `^' and `M\-' notation, except for LF and TAB
|
use '^' and 'M\-' notation, except for LF and TAB
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-verbose\fR
|
\fB\-\-verbose\fR
|
||||||
verbose mode (show error messages)
|
verbose mode (show error messages)
|
||||||
|
@ -65,7 +69,7 @@ Report bugs to zutils\-bug@nongnu.org
|
||||||
.br
|
.br
|
||||||
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
Copyright \(co 2011 Antonio Diaz Diaz.
|
Copyright \(co 2013 Antonio Diaz Diaz.
|
||||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||||
.br
|
.br
|
||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
|
|
10
doc/zcmp.1
10
doc/zcmp.1
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZCMP "1" "January 2011" "Zcmp (zutils) 0.9" "User Commands"
|
.TH ZCMP "1" "March 2013" "Zcmp (zutils) 1.0-rc6" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zcmp \- decompress and compare two files byte by byte
|
Zcmp \- decompress and compare two files byte by byte
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -11,7 +11,8 @@ differ, tells the first byte and line number where they differ. Bytes
|
||||||
and lines are numbered starting with 1. If any given file is compressed,
|
and lines are numbered starting with 1. If any given file is compressed,
|
||||||
its uncompressed content is used. Compressed files are uncompressed on
|
its uncompressed content is used. Compressed files are uncompressed on
|
||||||
the fly; no temporary files are created.
|
the fly; no temporary files are created.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
.PP
|
||||||
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
.PP
|
.PP
|
||||||
Compares <file1> to <file2>. If <file2> is omitted zcmp tries the
|
Compares <file1> to <file2>. If <file2> is omitted zcmp tries the
|
||||||
following:
|
following:
|
||||||
|
@ -35,6 +36,9 @@ output version information and exit
|
||||||
\fB\-b\fR, \fB\-\-print\-bytes\fR
|
\fB\-b\fR, \fB\-\-print\-bytes\fR
|
||||||
print differing bytes
|
print differing bytes
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-format\fR=\fI[\fR<fmt1>][,<fmt2>]
|
||||||
|
force given formats (bz2, gz, lz, xz)
|
||||||
|
.TP
|
||||||
\fB\-i\fR, \fB\-\-ignore\-initial=\fR<n>[,<n2>]
|
\fB\-i\fR, \fB\-\-ignore\-initial=\fR<n>[,<n2>]
|
||||||
ignore differences in the first <n> bytes
|
ignore differences in the first <n> bytes
|
||||||
.TP
|
.TP
|
||||||
|
@ -60,7 +64,7 @@ Report bugs to zutils\-bug@nongnu.org
|
||||||
.br
|
.br
|
||||||
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
Copyright \(co 2011 Antonio Diaz Diaz.
|
Copyright \(co 2013 Antonio Diaz Diaz.
|
||||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||||
.br
|
.br
|
||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
|
|
10
doc/zdiff.1
10
doc/zdiff.1
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZDIFF "1" "January 2011" "Zdiff (zutils) 0.9" "User Commands"
|
.TH ZDIFF "1" "March 2013" "Zdiff (zutils) 1.0-rc6" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zdiff \- decompress and compare two files line by line
|
Zdiff \- decompress and compare two files line by line
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -11,7 +11,8 @@ differ, shows the differences line by line. If any given file is
|
||||||
compressed, its uncompressed content is used. Zdiff is a front end to
|
compressed, its uncompressed content is used. Zdiff is a front end to
|
||||||
the diff program and has the limitation that messages from diff refer to
|
the diff program and has the limitation that messages from diff refer to
|
||||||
temporary filenames instead of those specified.
|
temporary filenames instead of those specified.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
.PP
|
||||||
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
.PP
|
.PP
|
||||||
Compares <file1> to <file2>. If <file2> is omitted zdiff tries the
|
Compares <file1> to <file2>. If <file2> is omitted zdiff tries the
|
||||||
following:
|
following:
|
||||||
|
@ -53,6 +54,9 @@ try hard to find a smaller set of changes
|
||||||
\fB\-E\fR, \fB\-\-ignore\-tab\-expansion\fR
|
\fB\-E\fR, \fB\-\-ignore\-tab\-expansion\fR
|
||||||
ignore changes due to tab expansion
|
ignore changes due to tab expansion
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-format\fR=\fI[\fR<fmt1>][,<fmt2>]
|
||||||
|
force given formats (bz2, gz, lz, xz)
|
||||||
|
.TP
|
||||||
\fB\-i\fR, \fB\-\-ignore\-case\fR
|
\fB\-i\fR, \fB\-\-ignore\-case\fR
|
||||||
ignore case differences in file contents
|
ignore case differences in file contents
|
||||||
.TP
|
.TP
|
||||||
|
@ -87,7 +91,7 @@ Report bugs to zutils\-bug@nongnu.org
|
||||||
.br
|
.br
|
||||||
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
Copyright \(co 2011 Antonio Diaz Diaz.
|
Copyright \(co 2013 Antonio Diaz Diaz.
|
||||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||||
.br
|
.br
|
||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
|
|
14
doc/zgrep.1
14
doc/zgrep.1
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZGREP "1" "January 2011" "Zgrep (zutils) 0.9" "User Commands"
|
.TH ZGREP "1" "March 2013" "Zgrep (zutils) 1.0-rc6" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zgrep \- search compressed files for a regular expression
|
Zgrep \- search compressed files for a regular expression
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -11,11 +11,12 @@ on any combination of compressed and non\-compressed files. If any given
|
||||||
file is compressed, its uncompressed content is used. If a given file
|
file is compressed, its uncompressed content is used. If a given file
|
||||||
does not exist, and its name does not end with one of the known
|
does not exist, and its name does not end with one of the known
|
||||||
extensions, zgrep tries the compressed file names corresponding to the
|
extensions, zgrep tries the compressed file names corresponding to the
|
||||||
supported compressors. If no files are specified, data is read from
|
supported formats. If no files are specified, data is read from
|
||||||
standard input, decompressed if needed, and fed to grep. Data read from
|
standard input, decompressed if needed, and fed to grep. Data read from
|
||||||
standard input must be of the same type; all uncompressed or all
|
standard input must be of the same type; all uncompressed or all
|
||||||
compressed with the same compressor.
|
in the same compression format.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
.PP
|
||||||
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
.PP
|
.PP
|
||||||
Exit status is 0 if match, 1 if no match, 2 if trouble.
|
Exit status is 0 if match, 1 if no match, 2 if trouble.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
@ -56,6 +57,9 @@ obtain patterns from <file>
|
||||||
\fB\-F\fR, \fB\-\-fixed\-strings\fR
|
\fB\-F\fR, \fB\-\-fixed\-strings\fR
|
||||||
<pattern> is a set of newline\-separated strings
|
<pattern> is a set of newline\-separated strings
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-format=\fR<fmt>
|
||||||
|
force given format (bz2, gz, lz, xz)
|
||||||
|
.TP
|
||||||
\fB\-h\fR, \fB\-\-no\-filename\fR
|
\fB\-h\fR, \fB\-\-no\-filename\fR
|
||||||
suppress the prefixing filename on output
|
suppress the prefixing filename on output
|
||||||
.TP
|
.TP
|
||||||
|
@ -108,7 +112,7 @@ Report bugs to zutils\-bug@nongnu.org
|
||||||
.br
|
.br
|
||||||
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
Copyright \(co 2011 Antonio Diaz Diaz.
|
Copyright \(co 2013 Antonio Diaz Diaz.
|
||||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||||
.br
|
.br
|
||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
|
|
19
doc/ztest.1
19
doc/ztest.1
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZTEST "1" "January 2011" "Ztest (zutils) 0.9" "User Commands"
|
.TH ZTEST "1" "March 2013" "Ztest (zutils) 1.0-rc6" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Ztest \- verify integrity of compressed files
|
Ztest \- verify integrity of compressed files
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -9,10 +9,16 @@ Ztest \- verify integrity of compressed files
|
||||||
Ztest verifies the integrity of the specified compressed files.
|
Ztest verifies the integrity of the specified compressed files.
|
||||||
Non\-compressed files are ignored. If no files are specified, the
|
Non\-compressed files are ignored. If no files are specified, the
|
||||||
integrity of compressed data read from standard input is verified. Data
|
integrity of compressed data read from standard input is verified. Data
|
||||||
read from standard input must be all compressed with the same compressor.
|
read from standard input must be all in the same compression format.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
|
||||||
.PP
|
.PP
|
||||||
Exit status is 2 if any compressed file is corrupt, 0 otherwise.
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
|
.PP
|
||||||
|
Note that some xz files lack integrity information, and therefore can't
|
||||||
|
be verified as reliably as the other formats can.
|
||||||
|
.PP
|
||||||
|
Exit status is 0 if all compressed files verify OK, 1 if environmental
|
||||||
|
problems (file not found, invalid flags, I/O errors, etc), 2 if any
|
||||||
|
compressed file is corrupt or invalid.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
\fB\-h\fR, \fB\-\-help\fR
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
|
@ -21,6 +27,9 @@ display this help and exit
|
||||||
\fB\-V\fR, \fB\-\-version\fR
|
\fB\-V\fR, \fB\-\-version\fR
|
||||||
output version information and exit
|
output version information and exit
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-format=\fR<fmt>
|
||||||
|
force given format (bz2, gz, lz, xz)
|
||||||
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
suppress all messages
|
suppress all messages
|
||||||
.TP
|
.TP
|
||||||
|
@ -34,7 +43,7 @@ Report bugs to zutils\-bug@nongnu.org
|
||||||
.br
|
.br
|
||||||
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
Zutils home page: http://www.nongnu.org/zutils/zutils.html
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
Copyright \(co 2011 Antonio Diaz Diaz.
|
Copyright \(co 2013 Antonio Diaz Diaz.
|
||||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||||
.br
|
.br
|
||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
|
|
142
doc/zutils.info
142
doc/zutils.info
|
@ -12,7 +12,7 @@ File: zutils.info, Node: Top, Next: Introduction, Up: (dir)
|
||||||
Zutils Manual
|
Zutils Manual
|
||||||
*************
|
*************
|
||||||
|
|
||||||
This manual is for Zutils (version 0.9, 11 January 2011).
|
This manual is for Zutils (version 1.0-rc6, 15 March 2013).
|
||||||
|
|
||||||
* Menu:
|
* Menu:
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ This manual is for Zutils (version 0.9, 11 January 2011).
|
||||||
* Concept Index:: Index of concepts
|
* Concept Index:: Index of concepts
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This manual is free documentation: you have unlimited permission to
|
This manual is free documentation: you have unlimited permission to
|
||||||
copy, distribute and modify it.
|
copy, distribute and modify it.
|
||||||
|
@ -41,12 +41,17 @@ Zutils is a collection of utilities able to deal with any combination of
|
||||||
compressed and non-compressed files transparently. If any given file,
|
compressed and non-compressed files transparently. If any given file,
|
||||||
including standard input, is compressed, its uncompressed content is
|
including standard input, is compressed, its uncompressed content is
|
||||||
used. Compressed files are decompressed on the fly; no temporary files
|
used. Compressed files are decompressed on the fly; no temporary files
|
||||||
are created. These utilities are not wrapper scripts but safer and more
|
are created.
|
||||||
efficient C++ programs. In particular the `--recursive' option is very
|
|
||||||
efficient in those utilities supporting it.
|
These utilities are not wrapper scripts but safer and more efficient
|
||||||
|
C++ programs. In particular the `--recursive' option is very efficient
|
||||||
|
in those utilities supporting it.
|
||||||
|
|
||||||
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.
|
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
|
|
||||||
|
Zcat, zcmp, zdiff, and zgrep are improved replacements for the shell
|
||||||
|
scripts provided with GNU gzip. Ztest is unique to zutils.
|
||||||
|
|
||||||
|
|
||||||
Numbers given as arguments to options (positions, sizes) may be
|
Numbers given as arguments to options (positions, sizes) may be
|
||||||
|
@ -74,10 +79,12 @@ Zcat copies each given file (`-' means standard input), to standard
|
||||||
output. If any given file is compressed, its uncompressed content is
|
output. If any given file is compressed, its uncompressed content is
|
||||||
used. If a given file does not exist, and its name does not end with one
|
used. If a given file does not exist, and its name does not end with one
|
||||||
of the known extensions, zcat tries the compressed file names
|
of the known extensions, zcat tries the compressed file names
|
||||||
corresponding to the supported compressors. If no files are specified,
|
corresponding to the supported formats.
|
||||||
data is read from standard input, decompressed if needed, and sent to
|
|
||||||
standard output. Data read from standard input must be of the same type;
|
If no files are specified, data is read from standard input,
|
||||||
all uncompressed or all compressed with the same compressor.
|
decompressed if needed, and sent to standard output. Data read from
|
||||||
|
standard input must be of the same type; all uncompressed or all in the
|
||||||
|
same compression format.
|
||||||
|
|
||||||
The format for running zcat is:
|
The format for running zcat is:
|
||||||
|
|
||||||
|
@ -111,6 +118,11 @@ Exit status is 0 if no errors occurred, 1 otherwise.
|
||||||
`--show-ends'
|
`--show-ends'
|
||||||
Print a `$' after the end of each line.
|
Print a `$' after the end of each line.
|
||||||
|
|
||||||
|
`--format=FMT'
|
||||||
|
Force the given compression format. Valid values for FMT are
|
||||||
|
`bz2', `gz', `lz' and `xz'. If this option is used, the exact file
|
||||||
|
name must be given. Other names won't be tried.
|
||||||
|
|
||||||
`-n'
|
`-n'
|
||||||
`--number'
|
`--number'
|
||||||
Number all output lines, starting with 1. The line count is
|
Number all output lines, starting with 1. The line count is
|
||||||
|
@ -161,13 +173,18 @@ fly; no temporary files are created.
|
||||||
|
|
||||||
zcmp [OPTIONS] FILE1 [FILE2]
|
zcmp [OPTIONS] FILE1 [FILE2]
|
||||||
|
|
||||||
Compares FILE1 to FILE2. If FILE2 is omitted zcmp tries the following:
|
This compares FILE1 to FILE2. If FILE2 is omitted zcmp tries the
|
||||||
If FILE1 is compressed, compares FILE1 to the file with the
|
following:
|
||||||
corresponding decompressed file name (removes the extension from FILE1).
|
|
||||||
If FILE1 is not compressed, compares FILE1 to the uncompressed contents
|
1. If FILE1 is compressed, compares FILE1 to the file with the
|
||||||
of FILE1.[bz2|gz|lz|xz] (the first one that is found).
|
corresponding decompressed file name (removes the extension from
|
||||||
If no suitable file is found, compares FILE1 to data read from standard
|
FILE1).
|
||||||
input.
|
|
||||||
|
2. If FILE1 is not compressed, compares FILE1 to the uncompressed
|
||||||
|
contents of FILE1.[bz2|gz|lz|xz] (the first one that is found).
|
||||||
|
|
||||||
|
3. If no suitable file is found, compares FILE1 to data read from
|
||||||
|
standard input.
|
||||||
|
|
||||||
An exit status of 0 means no differences were found, 1 means some
|
An exit status of 0 means no differences were found, 1 means some
|
||||||
differences were found, and 2 means trouble.
|
differences were found, and 2 means trouble.
|
||||||
|
@ -188,6 +205,14 @@ differences were found, and 2 means trouble.
|
||||||
a letter, and precede bytes larger than 127 with `M-' (which stands
|
a letter, and precede bytes larger than 127 with `M-' (which stands
|
||||||
for "meta").
|
for "meta").
|
||||||
|
|
||||||
|
`--format=[FMT1][,FMT2]'
|
||||||
|
Force the given compression formats. Any of FMT1 or FMT2 may be
|
||||||
|
omitted and the corresponding format will be automatically
|
||||||
|
detected. Valid values for FMT are `bz2', `gz', `lz' and `xz'. If
|
||||||
|
at least one format is specified with this option, the exact file
|
||||||
|
names of both FILE1 and FILE2 must be given. Other names won't be
|
||||||
|
tried.
|
||||||
|
|
||||||
`-i SIZE'
|
`-i SIZE'
|
||||||
`--ignore-initial=SIZE'
|
`--ignore-initial=SIZE'
|
||||||
Ignore any differences in the first SIZE bytes of the input files.
|
Ignore any differences in the first SIZE bytes of the input files.
|
||||||
|
@ -231,13 +256,18 @@ temporary filenames instead of those specified.
|
||||||
|
|
||||||
zdiff [OPTIONS] FILE1 [FILE2]
|
zdiff [OPTIONS] FILE1 [FILE2]
|
||||||
|
|
||||||
Compares FILE1 to FILE2. If FILE2 is omitted zdiff tries the following:
|
This compares FILE1 to FILE2. If FILE2 is omitted zdiff tries the
|
||||||
If FILE1 is compressed, compares FILE1 to the file with the
|
following:
|
||||||
corresponding decompressed file name (removes the extension from FILE1).
|
|
||||||
If FILE1 is not compressed, compares FILE1 to the uncompressed contents
|
1. If FILE1 is compressed, compares FILE1 to the file with the
|
||||||
of FILE1.[bz2|gz|lz|xz] (the first one that is found).
|
corresponding decompressed file name (removes the extension from
|
||||||
If no suitable file is found, compares FILE1 to data read from standard
|
FILE1).
|
||||||
input.
|
|
||||||
|
2. If FILE1 is not compressed, compares FILE1 to the uncompressed
|
||||||
|
contents of FILE1.[bz2|gz|lz|xz] (the first one that is found).
|
||||||
|
|
||||||
|
3. If no suitable file is found, compares FILE1 to data read from
|
||||||
|
standard input.
|
||||||
|
|
||||||
An exit status of 0 means no differences were found, 1 means some
|
An exit status of 0 means no differences were found, 1 means some
|
||||||
differences were found, and 2 means trouble.
|
differences were found, and 2 means trouble.
|
||||||
|
@ -279,6 +309,14 @@ differences were found, and 2 means trouble.
|
||||||
`--ignore-tab-expansion'
|
`--ignore-tab-expansion'
|
||||||
Ignore changes due to tab expansion.
|
Ignore changes due to tab expansion.
|
||||||
|
|
||||||
|
`--format=[FMT1][,FMT2]'
|
||||||
|
Force the given compression formats. Any of FMT1 or FMT2 may be
|
||||||
|
omitted and the corresponding format will be automatically
|
||||||
|
detected. Valid values for FMT are `bz2', `gz', `lz' and `xz'. If
|
||||||
|
at least one format is specified with this option, the exact file
|
||||||
|
names of both FILE1 and FILE2 must be given. Other names won't be
|
||||||
|
tried.
|
||||||
|
|
||||||
`-i'
|
`-i'
|
||||||
`--ignore-case'
|
`--ignore-case'
|
||||||
Ignore case differences in file contents.
|
Ignore case differences in file contents.
|
||||||
|
@ -326,10 +364,12 @@ on any combination of compressed and non-compressed files. If any given
|
||||||
file is compressed, its uncompressed content is used. If a given file
|
file is compressed, its uncompressed content is used. If a given file
|
||||||
does not exist, and its name does not end with one of the known
|
does not exist, and its name does not end with one of the known
|
||||||
extensions, zgrep tries the compressed file names corresponding to the
|
extensions, zgrep tries the compressed file names corresponding to the
|
||||||
supported compressors. If no files are specified, data is read from
|
supported formats.
|
||||||
standard input, decompressed if needed, and fed to grep. Data read from
|
|
||||||
standard input must be of the same type; all uncompressed or all
|
If no files are specified, data is read from standard input,
|
||||||
compressed with the same compressor.
|
decompressed if needed, and fed to grep. Data read from standard input
|
||||||
|
must be of the same type; all uncompressed or all in the same
|
||||||
|
compression format.
|
||||||
|
|
||||||
The format for running zgrep is:
|
The format for running zgrep is:
|
||||||
|
|
||||||
|
@ -387,9 +427,15 @@ matches were found, and 2 means trouble.
|
||||||
`--fixed-strings'
|
`--fixed-strings'
|
||||||
Treat PATTERN as a set of newline-separated strings.
|
Treat PATTERN as a set of newline-separated strings.
|
||||||
|
|
||||||
|
`--format=FMT'
|
||||||
|
Force the given compression format. Valid values for FMT are
|
||||||
|
`bz2', `gz', `lz' and `xz'. If this option is used, the exact file
|
||||||
|
name must be given. Other names won't be tried.
|
||||||
|
|
||||||
`-h'
|
`-h'
|
||||||
`--no-filename'
|
`--no-filename'
|
||||||
Suppress the prefixing filename on output.
|
Suppress the prefixing of filenames on output when multiple files
|
||||||
|
are searched.
|
||||||
|
|
||||||
`-H'
|
`-H'
|
||||||
`--with-filename'
|
`--with-filename'
|
||||||
|
@ -459,16 +505,18 @@ File: zutils.info, Node: Ztest, Next: Problems, Prev: Zgrep, Up: Top
|
||||||
Ztest verifies the integrity of the specified compressed files.
|
Ztest verifies the integrity of the specified compressed files.
|
||||||
Non-compressed files are ignored. If no files are specified, the
|
Non-compressed files are ignored. If no files are specified, the
|
||||||
integrity of compressed data read from standard input is verified. Data
|
integrity of compressed data read from standard input is verified. Data
|
||||||
read from standard input must be all compressed with the same
|
read from standard input must be all in the same compression format.
|
||||||
compressor.
|
|
||||||
|
Note that some xz files lack integrity information, and therefore
|
||||||
|
can't be verified as reliably as the other formats can.
|
||||||
|
|
||||||
The format for running ztest is:
|
The format for running ztest is:
|
||||||
|
|
||||||
ztest [OPTIONS] [FILES]
|
ztest [OPTIONS] [FILES]
|
||||||
|
|
||||||
The exit status is 0 if all files verify OK, 1 for environmental
|
The exit status is 0 if all compressed files verify OK, 1 if
|
||||||
problems (file not found, invalid flags, I/O errors, etc), 2 to indicate
|
environmental problems (file not found, invalid flags, I/O errors, etc),
|
||||||
a corrupt or invalid input file.
|
2 if any compressed file is corrupt or invalid.
|
||||||
|
|
||||||
Ztest supports the following options:
|
Ztest supports the following options:
|
||||||
|
|
||||||
|
@ -480,6 +528,11 @@ a corrupt or invalid input file.
|
||||||
`--version'
|
`--version'
|
||||||
Print the version number of ztest on the standard output and exit.
|
Print the version number of ztest on the standard output and exit.
|
||||||
|
|
||||||
|
`--format=FMT'
|
||||||
|
Force the given compression format. Valid values for FMT are
|
||||||
|
`bz2', `gz', `lz' and `xz'. If this option is used, all files not
|
||||||
|
in the given format will fail.
|
||||||
|
|
||||||
`-q'
|
`-q'
|
||||||
`--quiet'
|
`--quiet'
|
||||||
Quiet operation. Suppress all messages.
|
Quiet operation. Suppress all messages.
|
||||||
|
@ -531,13 +584,18 @@ Concept Index
|
||||||
|
|
||||||
Tag Table:
|
Tag Table:
|
||||||
Node: Top224
|
Node: Top224
|
||||||
Node: Introduction992
|
Node: Introduction1006
|
||||||
Node: Zcat2447
|
Node: Zcat2593
|
||||||
Node: Zcmp4331
|
Node: Zcmp4679
|
||||||
Node: Zdiff6388
|
Node: Zdiff7165
|
||||||
Node: Zgrep8625
|
Node: Zgrep9831
|
||||||
Node: Ztest11392
|
Node: Ztest12842
|
||||||
Node: Problems12475
|
Node: Problems14246
|
||||||
Node: Concept Index13004
|
Node: Concept Index14775
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|
||||||
|
|
||||||
|
Local Variables:
|
||||||
|
coding: iso-8859-15
|
||||||
|
End:
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename zutils.info
|
@setfilename zutils.info
|
||||||
|
@documentencoding ISO-8859-15
|
||||||
@settitle Zutils Manual
|
@settitle Zutils Manual
|
||||||
@finalout
|
@finalout
|
||||||
@c %**end of header
|
@c %**end of header
|
||||||
|
|
||||||
@set UPDATED 11 January 2011
|
@set UPDATED 15 March 2013
|
||||||
@set VERSION 0.9
|
@set VERSION 1.0-rc6
|
||||||
|
|
||||||
@dircategory Data Compression
|
@dircategory Data Compression
|
||||||
@direntry
|
@direntry
|
||||||
|
@ -45,7 +46,8 @@ This manual is for Zutils (version @value{VERSION}, @value{UPDATED}).
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
Copyright @copyright{} 2008, 2009, 2010, 2011 Antonio Diaz Diaz.
|
Copyright @copyright{} 2008, 2009, 2010, 2011, 2012, 2013
|
||||||
|
Antonio Diaz Diaz.
|
||||||
|
|
||||||
This manual is free documentation: you have unlimited permission
|
This manual is free documentation: you have unlimited permission
|
||||||
to copy, distribute and modify it.
|
to copy, distribute and modify it.
|
||||||
|
@ -59,13 +61,18 @@ Zutils is a collection of utilities able to deal with any combination of
|
||||||
compressed and non-compressed files transparently. If any given file,
|
compressed and non-compressed files transparently. If any given file,
|
||||||
including standard input, is compressed, its uncompressed content is
|
including standard input, is compressed, its uncompressed content is
|
||||||
used. Compressed files are decompressed on the fly; no temporary files
|
used. Compressed files are decompressed on the fly; no temporary files
|
||||||
are created. These utilities are not wrapper scripts but safer and more
|
are created.
|
||||||
efficient C++ programs. In particular the @samp{--recursive} option is
|
|
||||||
very efficient in those utilities supporting it.
|
These utilities are not wrapper scripts but safer and more efficient C++
|
||||||
|
programs. In particular the @samp{--recursive} option is very efficient
|
||||||
|
in those utilities supporting it.
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.@*
|
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.@*
|
||||||
The supported compressors are bzip2, gzip, lzip and xz.
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
|
|
||||||
|
Zcat, zcmp, zdiff, and zgrep are improved replacements for the shell
|
||||||
|
scripts provided with GNU gzip. Ztest is unique to zutils.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
Numbers given as arguments to options (positions, sizes) may be followed
|
Numbers given as arguments to options (positions, sizes) may be followed
|
||||||
|
@ -94,10 +101,12 @@ Zcat copies each given file (@samp{-} means standard input), to standard
|
||||||
output. If any given file is compressed, its uncompressed content is
|
output. If any given file is compressed, its uncompressed content is
|
||||||
used. If a given file does not exist, and its name does not end with one
|
used. If a given file does not exist, and its name does not end with one
|
||||||
of the known extensions, zcat tries the compressed file names
|
of the known extensions, zcat tries the compressed file names
|
||||||
corresponding to the supported compressors. If no files are specified,
|
corresponding to the supported formats.
|
||||||
data is read from standard input, decompressed if needed, and sent to
|
|
||||||
standard output. Data read from standard input must be of the same type;
|
If no files are specified, data is read from standard input,
|
||||||
all uncompressed or all compressed with the same compressor.
|
decompressed if needed, and sent to standard output. Data read from
|
||||||
|
standard input must be of the same type; all uncompressed or all in the
|
||||||
|
same compression format.
|
||||||
|
|
||||||
The format for running zcat is:
|
The format for running zcat is:
|
||||||
|
|
||||||
|
@ -135,6 +144,11 @@ Equivalent to @samp{-vE}.
|
||||||
@itemx --show-ends
|
@itemx --show-ends
|
||||||
Print a @samp{$} after the end of each line.
|
Print a @samp{$} after the end of each line.
|
||||||
|
|
||||||
|
@item --format=@var{fmt}
|
||||||
|
Force the given compression format. Valid values for @var{fmt} are
|
||||||
|
@samp{bz2}, @samp{gz}, @samp{lz} and @samp{xz}. If this option is used,
|
||||||
|
the exact file name must be given. Other names won't be tried.
|
||||||
|
|
||||||
@item -n
|
@item -n
|
||||||
@itemx --number
|
@itemx --number
|
||||||
Number all output lines, starting with 1. The line count is unlimited.
|
Number all output lines, starting with 1. The line count is unlimited.
|
||||||
|
@ -187,16 +201,22 @@ zcmp [@var{options}] @var{file1} [@var{file2}]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
Compares @var{file1} to @var{file2}. If @var{file2} is omitted zcmp
|
This compares @var{file1} to @var{file2}. If @var{file2} is omitted zcmp
|
||||||
tries the following:@*
|
tries the following:
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
@item
|
||||||
If @var{file1} is compressed, compares @var{file1} to the file with the
|
If @var{file1} is compressed, compares @var{file1} to the file with the
|
||||||
corresponding decompressed file name (removes the extension from
|
corresponding decompressed file name (removes the extension from
|
||||||
@var{file1}).@*
|
@var{file1}).
|
||||||
|
@item
|
||||||
If @var{file1} is not compressed, compares @var{file1} to the
|
If @var{file1} is not compressed, compares @var{file1} to the
|
||||||
uncompressed contents of @var{file1}.[bz2|gz|lz|xz] (the first one that
|
uncompressed contents of @var{file1}.[bz2|gz|lz|xz] (the first one that
|
||||||
is found).@*
|
is found).
|
||||||
|
@item
|
||||||
If no suitable file is found, compares @var{file1} to data read from
|
If no suitable file is found, compares @var{file1} to data read from
|
||||||
standard input.
|
standard input.
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
An exit status of 0 means no differences were found, 1 means some
|
An exit status of 0 means no differences were found, 1 means some
|
||||||
|
@ -219,6 +239,14 @@ Print the differing bytes. Print control bytes as a @samp{^} followed by
|
||||||
a letter, and precede bytes larger than 127 with @samp{M-} (which stands
|
a letter, and precede bytes larger than 127 with @samp{M-} (which stands
|
||||||
for "meta").
|
for "meta").
|
||||||
|
|
||||||
|
@item --format=[@var{fmt1}][,@var{fmt2}]
|
||||||
|
Force the given compression formats. Any of @var{fmt1} or @var{fmt2} may
|
||||||
|
be omitted and the corresponding format will be automatically detected.
|
||||||
|
Valid values for @var{fmt} are @samp{bz2}, @samp{gz}, @samp{lz} and
|
||||||
|
@samp{xz}. If at least one format is specified with this option, the
|
||||||
|
exact file names of both @var{file1} and @var{file2} must be given.
|
||||||
|
Other names won't be tried.
|
||||||
|
|
||||||
@item -i @var{size}
|
@item -i @var{size}
|
||||||
@itemx --ignore-initial=@var{size}
|
@itemx --ignore-initial=@var{size}
|
||||||
Ignore any differences in the first @var{size} bytes of the input files.
|
Ignore any differences in the first @var{size} bytes of the input files.
|
||||||
|
@ -265,16 +293,22 @@ zdiff [@var{options}] @var{file1} [@var{file2}]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
Compares @var{file1} to @var{file2}. If @var{file2} is omitted zdiff
|
This compares @var{file1} to @var{file2}. If @var{file2} is omitted
|
||||||
tries the following:@*
|
zdiff tries the following:
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
@item
|
||||||
If @var{file1} is compressed, compares @var{file1} to the file with the
|
If @var{file1} is compressed, compares @var{file1} to the file with the
|
||||||
corresponding decompressed file name (removes the extension from
|
corresponding decompressed file name (removes the extension from
|
||||||
@var{file1}).@*
|
@var{file1}).
|
||||||
|
@item
|
||||||
If @var{file1} is not compressed, compares @var{file1} to the
|
If @var{file1} is not compressed, compares @var{file1} to the
|
||||||
uncompressed contents of @var{file1}.[bz2|gz|lz|xz] (the first one that
|
uncompressed contents of @var{file1}.[bz2|gz|lz|xz] (the first one that
|
||||||
is found).@*
|
is found).
|
||||||
|
@item
|
||||||
If no suitable file is found, compares @var{file1} to data read from
|
If no suitable file is found, compares @var{file1} to data read from
|
||||||
standard input.
|
standard input.
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
An exit status of 0 means no differences were found, 1 means some
|
An exit status of 0 means no differences were found, 1 means some
|
||||||
|
@ -318,6 +352,14 @@ Try hard to find a smaller set of changes.
|
||||||
@itemx --ignore-tab-expansion
|
@itemx --ignore-tab-expansion
|
||||||
Ignore changes due to tab expansion.
|
Ignore changes due to tab expansion.
|
||||||
|
|
||||||
|
@item --format=[@var{fmt1}][,@var{fmt2}]
|
||||||
|
Force the given compression formats. Any of @var{fmt1} or @var{fmt2} may
|
||||||
|
be omitted and the corresponding format will be automatically detected.
|
||||||
|
Valid values for @var{fmt} are @samp{bz2}, @samp{gz}, @samp{lz} and
|
||||||
|
@samp{xz}. If at least one format is specified with this option, the
|
||||||
|
exact file names of both @var{file1} and @var{file2} must be given.
|
||||||
|
Other names won't be tried.
|
||||||
|
|
||||||
@item -i
|
@item -i
|
||||||
@itemx --ignore-case
|
@itemx --ignore-case
|
||||||
Ignore case differences in file contents.
|
Ignore case differences in file contents.
|
||||||
|
@ -365,10 +407,12 @@ on any combination of compressed and non-compressed files. If any given
|
||||||
file is compressed, its uncompressed content is used. If a given file
|
file is compressed, its uncompressed content is used. If a given file
|
||||||
does not exist, and its name does not end with one of the known
|
does not exist, and its name does not end with one of the known
|
||||||
extensions, zgrep tries the compressed file names corresponding to the
|
extensions, zgrep tries the compressed file names corresponding to the
|
||||||
supported compressors. If no files are specified, data is read from
|
supported formats.
|
||||||
standard input, decompressed if needed, and fed to grep. Data read from
|
|
||||||
standard input must be of the same type; all uncompressed or all
|
If no files are specified, data is read from standard input,
|
||||||
compressed with the same compressor.
|
decompressed if needed, and fed to grep. Data read from standard input
|
||||||
|
must be of the same type; all uncompressed or all in the same
|
||||||
|
compression format.
|
||||||
|
|
||||||
The format for running zgrep is:
|
The format for running zgrep is:
|
||||||
|
|
||||||
|
@ -430,9 +474,15 @@ Obtain patterns from @var{file}, one per line.
|
||||||
@itemx --fixed-strings
|
@itemx --fixed-strings
|
||||||
Treat @var{pattern} as a set of newline-separated strings.
|
Treat @var{pattern} as a set of newline-separated strings.
|
||||||
|
|
||||||
|
@item --format=@var{fmt}
|
||||||
|
Force the given compression format. Valid values for @var{fmt} are
|
||||||
|
@samp{bz2}, @samp{gz}, @samp{lz} and @samp{xz}. If this option is used,
|
||||||
|
the exact file name must be given. Other names won't be tried.
|
||||||
|
|
||||||
@item -h
|
@item -h
|
||||||
@itemx --no-filename
|
@itemx --no-filename
|
||||||
Suppress the prefixing filename on output.
|
Suppress the prefixing of filenames on output when multiple files are
|
||||||
|
searched.
|
||||||
|
|
||||||
@item -H
|
@item -H
|
||||||
@itemx --with-filename
|
@itemx --with-filename
|
||||||
|
@ -502,7 +552,10 @@ Match only whole lines.
|
||||||
Ztest verifies the integrity of the specified compressed files.
|
Ztest verifies the integrity of the specified compressed files.
|
||||||
Non-compressed files are ignored. If no files are specified, the
|
Non-compressed files are ignored. If no files are specified, the
|
||||||
integrity of compressed data read from standard input is verified. Data
|
integrity of compressed data read from standard input is verified. Data
|
||||||
read from standard input must be all compressed with the same compressor.
|
read from standard input must be all in the same compression format.
|
||||||
|
|
||||||
|
Note that some xz files lack integrity information, and therefore can't
|
||||||
|
be verified as reliably as the other formats can.
|
||||||
|
|
||||||
The format for running ztest is:
|
The format for running ztest is:
|
||||||
|
|
||||||
|
@ -511,9 +564,9 @@ ztest [@var{options}] [@var{files}]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
The exit status is 0 if all files verify OK, 1 for environmental
|
The exit status is 0 if all compressed files verify OK, 1 if
|
||||||
problems (file not found, invalid flags, I/O errors, etc), 2 to indicate
|
environmental problems (file not found, invalid flags, I/O errors, etc),
|
||||||
a corrupt or invalid input file.
|
2 if any compressed file is corrupt or invalid.
|
||||||
|
|
||||||
Ztest supports the following options:
|
Ztest supports the following options:
|
||||||
|
|
||||||
|
@ -526,6 +579,11 @@ Print an informative help message describing the options and exit.
|
||||||
@itemx --version
|
@itemx --version
|
||||||
Print the version number of ztest on the standard output and exit.
|
Print the version number of ztest on the standard output and exit.
|
||||||
|
|
||||||
|
@item --format=@var{fmt}
|
||||||
|
Force the given compression format. Valid values for @var{fmt} are
|
||||||
|
@samp{bz2}, @samp{gz}, @samp{lz} and @samp{xz}. If this option is used,
|
||||||
|
all files not in the given format will fail.
|
||||||
|
|
||||||
@item -q
|
@item -q
|
||||||
@itemx --quiet
|
@itemx --quiet
|
||||||
Quiet operation. Suppress all messages.
|
Quiet operation. Suppress all messages.
|
||||||
|
|
86
main.cc
86
main.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Zutils - Utilities dealing with compressed files
|
/* Zutils - Utilities dealing with compressed files
|
||||||
Copyright (C) 2009, 2010, 2011 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -54,27 +54,27 @@ const int o_binary = 0;
|
||||||
enum Mode { m_none, m_zcat, m_zgrep, m_ztest };
|
enum Mode { m_none, m_zcat, m_zgrep, m_ztest };
|
||||||
|
|
||||||
|
|
||||||
void show_help() throw()
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zutils is a collection of utilities able to deal with any combination of\n" );
|
std::printf( "Zutils is a collection of utilities able to deal with any combination of\n"
|
||||||
std::printf( "compressed and non-compressed files transparently. If any given file,\n" );
|
"compressed and non-compressed files transparently. If any given file,\n"
|
||||||
std::printf( "including standard input, is compressed, its uncompressed content is used.\n" );
|
"including standard input, is compressed, its uncompressed content is used.\n"
|
||||||
std::printf( "The supported compressors are bzip2, gzip, lzip and xz.\n" );
|
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||||
std::printf( "\nUsage: %s <operation> [options] [files]\n", invocation_name );
|
"\nUsage: %s <operation> [options] [files]\n", invocation_name );
|
||||||
std::printf( "\nTry `%s <operation> --help' for more specific help.\n", invocation_name );
|
std::printf( "\nTry '%s <operation> --help' for more specific help.\n", invocation_name );
|
||||||
std::printf( "\nOperations:\n" );
|
std::printf( "\nOperations:\n"
|
||||||
std::printf( " -h, --help display this help and exit\n" );
|
" -h, --help display this help and exit\n"
|
||||||
std::printf( " -V, --version output version information and exit\n" );
|
" -V, --version output version information and exit\n"
|
||||||
std::printf( " --zcat zcat operation\n" );
|
" --zcat zcat operation\n"
|
||||||
std::printf( " --zgrep zgrep operation\n" );
|
" --zgrep zgrep operation\n"
|
||||||
std::printf( " --ztest ztest operation\n" );
|
" --ztest ztest operation\n" );
|
||||||
show_help_addr();
|
show_help_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int simple_extension_index( const std::string & name ) throw()
|
int simple_extension_index( const std::string & name )
|
||||||
{
|
{
|
||||||
for( int i = 0; simple_extensions[i]; ++i )
|
for( int i = 0; i < num_formats; ++i )
|
||||||
{
|
{
|
||||||
const std::string ext( simple_extensions[i] );
|
const std::string ext( simple_extensions[i] );
|
||||||
if( name.size() > ext.size() &&
|
if( name.size() > ext.size() &&
|
||||||
|
@ -85,17 +85,19 @@ int simple_extension_index( const std::string & name ) throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int open_instream( std::string & input_filename, const Mode program_mode ) throw()
|
int open_instream( std::string & input_filename, const Mode program_mode,
|
||||||
|
const bool search )
|
||||||
{
|
{
|
||||||
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
||||||
if( infd < 0 )
|
if( infd < 0 )
|
||||||
{
|
{
|
||||||
if( ( program_mode == m_zcat || program_mode == m_zgrep )
|
if( search && ( program_mode == m_zcat || program_mode == m_zgrep ) &&
|
||||||
&& simple_extension_index( input_filename ) < 0 )
|
simple_extension_index( input_filename ) < 0 )
|
||||||
{
|
{
|
||||||
for( int i = 0; simple_extensions[i]; ++i )
|
for( int i = 0; i < num_formats; ++i )
|
||||||
{
|
{
|
||||||
const std::string name( input_filename + simple_extensions[i] );
|
const std::string name( input_filename +
|
||||||
|
simple_extensions[format_order[i]] );
|
||||||
infd = open( name.c_str(), O_RDONLY | o_binary );
|
infd = open( name.c_str(), O_RDONLY | o_binary );
|
||||||
if( infd >= 0 ) { input_filename = name; break; }
|
if( infd >= 0 ) { input_filename = name; break; }
|
||||||
}
|
}
|
||||||
|
@ -115,9 +117,11 @@ int open_instream( std::string & input_filename, const Mode program_mode ) throw
|
||||||
|
|
||||||
int main( const int argc, const char * const argv[] )
|
int main( const int argc, const char * const argv[] )
|
||||||
{
|
{
|
||||||
enum { help_opt = 256, verbose_opt, zcat_opt, zgrep_opt, ztest_opt };
|
enum { format_opt = 256, help_opt, verbose_opt,
|
||||||
|
zcat_opt, zgrep_opt, ztest_opt };
|
||||||
const Arg_parser::Option * options = 0;
|
const Arg_parser::Option * options = 0;
|
||||||
int infd = -1;
|
int infd = -1;
|
||||||
|
int format_type = -1;
|
||||||
Mode program_mode = m_none;
|
Mode program_mode = m_none;
|
||||||
bool recursive = false;
|
bool recursive = false;
|
||||||
std::string input_filename;
|
std::string input_filename;
|
||||||
|
@ -147,6 +151,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ 'T', "show-tabs", Arg_parser::no }, // cat
|
{ 'T', "show-tabs", Arg_parser::no }, // cat
|
||||||
{ 'v', "show-nonprinting", Arg_parser::no }, // cat
|
{ 'v', "show-nonprinting", Arg_parser::no }, // cat
|
||||||
{ 'V', "version", Arg_parser::no },
|
{ 'V', "version", Arg_parser::no },
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
{ verbose_opt, "verbose", Arg_parser::no },
|
{ verbose_opt, "verbose", Arg_parser::no },
|
||||||
{ zcat_opt, "zcat", Arg_parser::no },
|
{ zcat_opt, "zcat", Arg_parser::no },
|
||||||
{ 0 , 0, Arg_parser::no } };
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
@ -179,6 +184,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ 'V', "version", Arg_parser::no },
|
{ 'V', "version", Arg_parser::no },
|
||||||
{ 'w', "word-regexp", Arg_parser::no }, // grep GNU
|
{ 'w', "word-regexp", Arg_parser::no }, // grep GNU
|
||||||
{ 'x', "line-regexp", Arg_parser::no }, // grep
|
{ 'x', "line-regexp", Arg_parser::no }, // grep
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
{ help_opt, "help", Arg_parser::no },
|
{ help_opt, "help", Arg_parser::no },
|
||||||
{ verbose_opt, "verbose", Arg_parser::no },
|
{ verbose_opt, "verbose", Arg_parser::no },
|
||||||
{ zgrep_opt, "zgrep", Arg_parser::no },
|
{ zgrep_opt, "zgrep", Arg_parser::no },
|
||||||
|
@ -191,6 +197,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ 'r', "recursive", Arg_parser::no },
|
{ 'r', "recursive", Arg_parser::no },
|
||||||
{ 'v', "verbose", Arg_parser::no },
|
{ 'v', "verbose", Arg_parser::no },
|
||||||
{ 'V', "version", Arg_parser::no },
|
{ 'V', "version", Arg_parser::no },
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
{ ztest_opt, "ztest", Arg_parser::no },
|
{ ztest_opt, "ztest", Arg_parser::no },
|
||||||
{ 0 , 0, Arg_parser::no } };
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
|
||||||
|
@ -226,8 +233,8 @@ int main( const int argc, const char * const argv[] )
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
_setmode( STDIN_FILENO, O_BINARY );
|
setmode( STDIN_FILENO, O_BINARY );
|
||||||
_setmode( STDOUT_FILENO, O_BINARY );
|
setmode( STDOUT_FILENO, O_BINARY );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( program_mode == m_none )
|
if( program_mode == m_none )
|
||||||
|
@ -240,11 +247,11 @@ int main( const int argc, const char * const argv[] )
|
||||||
const Arg_parser parser( argc, argv, options );
|
const Arg_parser parser( argc, argv, options );
|
||||||
if( parser.error().size() ) // bad option
|
if( parser.error().size() ) // bad option
|
||||||
{ show_error( parser.error().c_str(), 0, true );
|
{ show_error( parser.error().c_str(), 0, true );
|
||||||
return ( program_mode == m_zcat ) ? 1 : 2; }
|
return ( program_mode == m_zcat || program_mode == m_ztest ) ? 1 : 2; }
|
||||||
|
|
||||||
int argind = 0;
|
int argind = 0;
|
||||||
|
int grep_show_name = -1;
|
||||||
bool grep_list = false;
|
bool grep_list = false;
|
||||||
bool grep_show_name = true;
|
|
||||||
bool grep_pattern_found = false;
|
bool grep_pattern_found = false;
|
||||||
for( ; argind < parser.arguments(); ++argind )
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
{
|
{
|
||||||
|
@ -256,9 +263,13 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ grep_args.push_back( arg ); grep_pattern_found = true; continue; }
|
{ grep_args.push_back( arg ); grep_pattern_found = true; continue; }
|
||||||
else break; // no more options
|
else break; // no more options
|
||||||
}
|
}
|
||||||
|
if( code == format_opt )
|
||||||
|
{
|
||||||
|
format_type = get_format_type( arg ); continue;
|
||||||
|
}
|
||||||
switch( program_mode )
|
switch( program_mode )
|
||||||
{
|
{
|
||||||
case m_none: internal_error( "invalid operation" );
|
case m_none: internal_error( "invalid operation" ); break;
|
||||||
case m_zcat:
|
case m_zcat:
|
||||||
switch( code )
|
switch( code )
|
||||||
{
|
{
|
||||||
|
@ -339,17 +350,16 @@ int main( const int argc, const char * const argv[] )
|
||||||
} // end process options
|
} // end process options
|
||||||
|
|
||||||
if( program_mode == m_zgrep && !grep_pattern_found )
|
if( program_mode == m_zgrep && !grep_pattern_found )
|
||||||
{ show_error( "Pattern not found.", 0, true ); return 2; }
|
{ show_error( "Pattern not found." ); return 2; }
|
||||||
|
|
||||||
bool filenames_given = false;
|
|
||||||
for( ; argind < parser.arguments(); ++argind )
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
{
|
|
||||||
if( parser.argument( argind ) != "-" ) filenames_given = true;
|
|
||||||
filenames.push_back( parser.argument( argind ) );
|
filenames.push_back( parser.argument( argind ) );
|
||||||
}
|
|
||||||
|
|
||||||
if( filenames.empty() ) filenames.push_back("-");
|
if( filenames.empty() ) filenames.push_back("-");
|
||||||
|
|
||||||
|
if( grep_show_name < 0 )
|
||||||
|
grep_show_name = ( filenames.size() != 1 || recursive );
|
||||||
|
|
||||||
int retval = ( ( program_mode == m_zgrep ) ? 1 : 0 );
|
int retval = ( ( program_mode == m_zgrep ) ? 1 : 0 );
|
||||||
while( !filenames.empty() )
|
while( !filenames.empty() )
|
||||||
{
|
{
|
||||||
|
@ -386,7 +396,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
infd = open_instream( input_filename, program_mode );
|
infd = open_instream( input_filename, program_mode, format_type < 0 );
|
||||||
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
|
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,18 +406,18 @@ int main( const int argc, const char * const argv[] )
|
||||||
case m_none:
|
case m_none:
|
||||||
break;
|
break;
|
||||||
case m_zcat:
|
case m_zcat:
|
||||||
tmp = cat( infd, input_filename, cat_options );
|
tmp = cat( infd, format_type, input_filename, cat_options );
|
||||||
break;
|
break;
|
||||||
case m_zgrep:
|
case m_zgrep:
|
||||||
if( infd == STDIN_FILENO )
|
if( infd == STDIN_FILENO )
|
||||||
tmp = zgrep_stdin( infd, grep_args );
|
tmp = zgrep_stdin( infd, format_type, grep_args );
|
||||||
else tmp = zgrep_file( infd, input_filename, grep_args,
|
else tmp = zgrep_file( infd, format_type, input_filename, grep_args,
|
||||||
grep_list, grep_show_name );
|
grep_list, grep_show_name );
|
||||||
break;
|
break;
|
||||||
case m_ztest:
|
case m_ztest:
|
||||||
if( infd == STDIN_FILENO )
|
if( infd == STDIN_FILENO )
|
||||||
tmp = ztest_stdin( infd, ztest_args );
|
tmp = ztest_stdin( infd, format_type, ztest_args );
|
||||||
else tmp = ztest_file( infd, input_filename, ztest_args );
|
else tmp = ztest_file( infd, format_type, input_filename, ztest_args );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( program_mode == m_zgrep )
|
if( program_mode == m_zgrep )
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# check script for Zutils - Utilities dealing with compressed files
|
# check script for Zutils - Utilities dealing with compressed files
|
||||||
# Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz.
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
#
|
#
|
||||||
# This script is free software: you have unlimited permission
|
# This script is free software: you have unlimited permission
|
||||||
# to copy, distribute and modify it.
|
# to copy, distribute and modify it.
|
||||||
|
@ -18,8 +18,8 @@ ZFGREP="${objdir}"/zfgrep
|
||||||
ZTEST="${objdir}"/ztest
|
ZTEST="${objdir}"/ztest
|
||||||
compressors="bzip2 gzip lzip"
|
compressors="bzip2 gzip lzip"
|
||||||
extensions="bz2 gz lz"
|
extensions="bz2 gz lz"
|
||||||
framework_failure() { echo "failure in testing framework" ; exit 1 ; }
|
|
||||||
compressor_needed() { echo "${compressors} are needed to run tests" ; exit 1 ; }
|
compressor_needed() { echo "${compressors} are needed to run tests" ; exit 1 ; }
|
||||||
|
framework_failure() { echo "failure in testing framework" ; exit 1 ; }
|
||||||
|
|
||||||
if [ ! -x "${ZCAT}" ] ; then
|
if [ ! -x "${ZCAT}" ] ; then
|
||||||
echo "${ZCAT}: cannot execute"
|
echo "${ZCAT}: cannot execute"
|
||||||
|
@ -35,7 +35,6 @@ for i in ${compressors}; do
|
||||||
$i in || compressor_needed
|
$i in || compressor_needed
|
||||||
done
|
done
|
||||||
|
|
||||||
printf "testing zutils-%s..." "$2"
|
|
||||||
cat "${testdir}"/test.txt > in || framework_failure
|
cat "${testdir}"/test.txt > in || framework_failure
|
||||||
cat "${testdir}"/test.txt.tar > in.tar || framework_failure
|
cat "${testdir}"/test.txt.tar > in.tar || framework_failure
|
||||||
printf "01234567890" > pin.tar || framework_failure
|
printf "01234567890" > pin.tar || framework_failure
|
||||||
|
@ -46,12 +45,20 @@ cat in.lz > lz_only.lz || framework_failure
|
||||||
cat in in in in in in > in6 || framework_failure
|
cat in in in in in in > in6 || framework_failure
|
||||||
fail=0
|
fail=0
|
||||||
|
|
||||||
|
printf "testing zutils-%s..." "$2"
|
||||||
|
|
||||||
printf "\ntesting zcat-%s..." "$2"
|
printf "\ntesting zcat-%s..." "$2"
|
||||||
|
|
||||||
for i in ${extensions}; do
|
for i in ${extensions}; do
|
||||||
"${ZCAT}" in.$i > copy || fail=1
|
"${ZCAT}" in.$i > copy || fail=1
|
||||||
cmp in copy || fail=1
|
cmp in copy || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZCAT}" --format=$i in.$i > copy || fail=1
|
||||||
|
cmp in copy || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZCAT}" in.$i | dd bs=1000 count=1 > copy 2> /dev/null || fail=1
|
||||||
|
dd if=in bs=1000 count=1 2> /dev/null | cmp - copy || fail=1
|
||||||
|
printf .
|
||||||
done
|
done
|
||||||
|
|
||||||
"${ZCAT}" < in > copy || fail=1
|
"${ZCAT}" < in > copy || fail=1
|
||||||
|
@ -75,20 +82,51 @@ printf .
|
||||||
"${ZCAT}" in in.gz in.bz2 in.lz -- -in- -in-.lz > copy6 || fail=1
|
"${ZCAT}" in in.gz in.bz2 in.lz -- -in- -in-.lz > copy6 || fail=1
|
||||||
cmp in6 copy6 || fail=1
|
cmp in6 copy6 || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZCAT}" --format=gz in.bz2 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCAT}" --format=bz2 in.lz 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCAT}" --format=lz in.gz 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCAT}" --bad-option 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
|
||||||
|
|
||||||
printf "\ntesting zcmp-%s..." "$2"
|
printf "\ntesting zcmp-%s..." "$2"
|
||||||
|
|
||||||
for i in ${extensions}; do
|
for i in ${extensions}; do
|
||||||
"${ZCMP}" in.$i || fail=1
|
"${ZCMP}" in.$i || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZCMP}" in in.$i || fail=1
|
"${ZCMP}" in in.$i || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZCMP}" -i 100 -n 500 in6 in.$i || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZCMP}" in in.$i --format=,$i || fail=1
|
||||||
|
printf .
|
||||||
"${ZCMP}" in.$i in || fail=1
|
"${ZCMP}" in.$i in || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZCMP}" -i 1000:1000 -n 50 in.$i in6 || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZCMP}" in.$i in --format=$i || fail=1
|
||||||
|
printf .
|
||||||
done
|
done
|
||||||
|
|
||||||
|
"${ZCMP}" in in6 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCMP}" -n 0 in in6 || fail=1
|
||||||
|
"${ZCMP}" -n 100 in in6 || fail=1
|
||||||
|
"${ZCMP}" -n 1000 in in6 || fail=1
|
||||||
|
"${ZCMP}" -n 10000 in in6 || fail=1
|
||||||
|
printf .
|
||||||
"${ZCMP}" in.tar pin.tar > /dev/null
|
"${ZCMP}" in.tar pin.tar > /dev/null
|
||||||
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCMP}" -i 0,11 in.tar pin.tar 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCMP}" -i 0,11 -n 0 in.tar pin.tar || fail=1
|
||||||
|
"${ZCMP}" -i 0,11 -n 100 in.tar pin.tar || fail=1
|
||||||
|
"${ZCMP}" -i 0,11 -n 1000 in.tar pin.tar || fail=1
|
||||||
|
"${ZCMP}" -i 0,11 -n 10000 in.tar pin.tar || fail=1
|
||||||
|
printf .
|
||||||
"${ZCMP}" - || fail=1
|
"${ZCMP}" - || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZCMP}" in in || fail=1
|
"${ZCMP}" in in || fail=1
|
||||||
|
@ -123,20 +161,35 @@ printf .
|
||||||
printf .
|
printf .
|
||||||
"${ZCMP}" - in < in.lz || fail=1
|
"${ZCMP}" - in < in.lz || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZCMP}" -q --format=lz in.lz
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCMP}" --format=lz in.gz in.lz 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCMP}" -n -1 in in 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZCMP}" --bad-option in in 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
|
||||||
|
|
||||||
printf "\ntesting zdiff-%s..." "$2"
|
printf "\ntesting zdiff-%s..." "$2"
|
||||||
|
|
||||||
for i in ${extensions}; do
|
for i in ${extensions}; do
|
||||||
"${ZDIFF}" in.$i || fail=1
|
"${ZDIFF}" in.$i || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZDIFF}" in in.$i || fail=1
|
"${ZDIFF}" in in.$i || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZDIFF}" --format=,$i in in.$i || fail=1
|
||||||
|
printf .
|
||||||
"${ZDIFF}" in.$i in || fail=1
|
"${ZDIFF}" in.$i in || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZDIFF}" --format=$i, in.$i in || fail=1
|
||||||
|
printf .
|
||||||
done
|
done
|
||||||
|
|
||||||
#"${ZDIFF}" in.tar pin.tar > /dev/null
|
"${ZDIFF}" in in6 > /dev/null
|
||||||
#if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
if [ $? = 0 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZDIFF}" in.tar pin.tar > /dev/null
|
||||||
|
if [ $? = 0 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
"${ZDIFF}" - || fail=1
|
"${ZDIFF}" - || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZDIFF}" in in || fail=1
|
"${ZDIFF}" in in || fail=1
|
||||||
|
@ -171,13 +224,27 @@ printf .
|
||||||
printf .
|
printf .
|
||||||
"${ZDIFF}" - in < in.lz || fail=1
|
"${ZDIFF}" - in < in.lz || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZDIFF}" -q --format=bz2 in.bz2 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZDIFF}" -q --format=,lz in.lz in.bz2 > /dev/null 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZDIFF}" --bad-option 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
|
||||||
|
|
||||||
printf "\ntesting zgrep-%s..." "$2"
|
printf "\ntesting zgrep-%s..." "$2"
|
||||||
|
|
||||||
for i in ${extensions}; do
|
for i in ${extensions}; do
|
||||||
"${ZGREP}" "GNU" in.$i > /dev/null || fail=1
|
"${ZGREP}" "GNU" in.$i > /dev/null || fail=1
|
||||||
"${ZGREP}" "nx_pattern" in.$i > /dev/null && fail=1
|
|
||||||
printf .
|
printf .
|
||||||
|
"${ZGREP}" --format=$i "GNU" in.$i > /dev/null || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZGREP}" -v "nx_pattern" in.$i > /dev/null || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZGREP}" "nx_pattern" in.$i > /dev/null
|
||||||
|
if [ $? = 0 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZGREP}" --format=$i "GNU" in 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
done
|
done
|
||||||
|
|
||||||
"${ZGREP}" "GNU" < pin.tar > /dev/null || fail=1
|
"${ZGREP}" "GNU" < pin.tar > /dev/null || fail=1
|
||||||
|
@ -186,8 +253,8 @@ printf .
|
||||||
printf .
|
printf .
|
||||||
"${ZGREP}" -r "GNU" . > /dev/null || fail=1
|
"${ZGREP}" -r "GNU" . > /dev/null || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZGREP}" "nx_pattern" -r . in > /dev/null && fail=1
|
"${ZGREP}" "nx_pattern" -r . in > /dev/null
|
||||||
printf .
|
if [ $? = 0 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
"${ZGREP}" "GNU" < in > /dev/null || fail=1
|
"${ZGREP}" "GNU" < in > /dev/null || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZGREP}" "GNU" < in.gz > /dev/null || fail=1
|
"${ZGREP}" "GNU" < in.gz > /dev/null || fail=1
|
||||||
|
@ -204,6 +271,11 @@ printf .
|
||||||
printf .
|
printf .
|
||||||
"${ZGREP}" "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null || fail=1
|
"${ZGREP}" "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
"${ZGREP}" -l "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZGREP}" --bad-option 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
|
||||||
"${ZEGREP}" "GNU" in > /dev/null || fail=1
|
"${ZEGREP}" "GNU" in > /dev/null || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZFGREP}" "GNU" in > /dev/null || fail=1
|
"${ZFGREP}" "GNU" in > /dev/null || fail=1
|
||||||
|
@ -211,6 +283,16 @@ printf .
|
||||||
|
|
||||||
|
|
||||||
printf "\ntesting ztest-%s..." "$2"
|
printf "\ntesting ztest-%s..." "$2"
|
||||||
|
|
||||||
|
for i in ${extensions}; do
|
||||||
|
"${ZTEST}" --format=$i < in.$i || fail=1
|
||||||
|
printf .
|
||||||
|
"${ZTEST}" --format=$i < in 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZTEST}" --format=$i in 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
done
|
||||||
|
|
||||||
"${ZTEST}" in in.gz in.bz2 in.lz -- -in- || fail=1
|
"${ZTEST}" in in.gz in.bz2 in.lz -- -in- || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZTEST}" < in.gz || fail=1
|
"${ZTEST}" < in.gz || fail=1
|
||||||
|
@ -222,9 +304,13 @@ printf .
|
||||||
"${ZTEST}" -r . || fail=1
|
"${ZTEST}" -r . || fail=1
|
||||||
printf .
|
printf .
|
||||||
"${ZTEST}" < in 2> /dev/null
|
"${ZTEST}" < in 2> /dev/null
|
||||||
if [ $? = 0 ] ; then fail=1 ; printf - ; else printf . ; fi
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
printf "LZIPvs0000000000000000000000" | "${ZTEST}" 2>/dev/null
|
dd if=in.lz bs=1000 count=1 2> /dev/null | "${ZTEST}" -q
|
||||||
if [ $? = 0 ] ; then fail=1 ; printf - ; else printf . ; fi
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZTEST}" --format=lz in.bz2 2> /dev/null
|
||||||
|
if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
"${ZTEST}" --bad-option 2> /dev/null
|
||||||
|
if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
if [ ${fail} = 0 ] ; then
|
if [ ${fail} = 0 ] ; then
|
||||||
|
|
71
zcat.cc
71
zcat.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Zcat - decompress and concatenate files to standard output
|
/* Zcat - decompress and concatenate files to standard output
|
||||||
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -23,7 +23,7 @@ struct Cat_options
|
||||||
bool show_tabs;
|
bool show_tabs;
|
||||||
bool squeeze_blank;
|
bool squeeze_blank;
|
||||||
|
|
||||||
Cat_options() throw()
|
Cat_options()
|
||||||
: number_lines( 0 ), show_ends( false ), show_nonprinting( false ),
|
: number_lines( 0 ), show_ends( false ), show_nonprinting( false ),
|
||||||
show_tabs( false ), squeeze_blank( false ) {}
|
show_tabs( false ), squeeze_blank( false ) {}
|
||||||
};
|
};
|
||||||
|
@ -32,20 +32,20 @@ struct Cat_options
|
||||||
class Line_number // unlimited size line counter
|
class Line_number // unlimited size line counter
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
int first_digit_pos;
|
unsigned first_digit_pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Line_number() : str( " 0\t" ), first_digit_pos( 5 ) {}
|
Line_number() : str( " 0\t" ), first_digit_pos( 5 ) {}
|
||||||
|
|
||||||
void next()
|
void next()
|
||||||
{
|
{
|
||||||
for( int i = str.size() - 2; i >= first_digit_pos; --i )
|
for( unsigned i = str.size() - 1; i > first_digit_pos; )
|
||||||
{
|
{
|
||||||
if( str[i] < '9' ) { ++str[i]; return; }
|
if( str[--i] < '9' ) { ++str[i]; return; }
|
||||||
str[i] = '0';
|
str[i] = '0';
|
||||||
}
|
}
|
||||||
if( first_digit_pos > 0 ) str[--first_digit_pos] = '1';
|
if( first_digit_pos > 0 ) str[--first_digit_pos] = '1';
|
||||||
else str.insert( 0U, 1, '1' );
|
else str.insert( first_digit_pos, 1, '1' );
|
||||||
}
|
}
|
||||||
|
|
||||||
int sprint( uint8_t * const buf )
|
int sprint( uint8_t * const buf )
|
||||||
|
@ -58,34 +58,35 @@ public:
|
||||||
Line_number line_number;
|
Line_number line_number;
|
||||||
|
|
||||||
|
|
||||||
void show_zcat_help() throw()
|
void show_zcat_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zcat copies each given file (\"-\" means standard input), to standard\n" );
|
std::printf( "Zcat copies each given file (\"-\" means standard input), to standard\n"
|
||||||
std::printf( "output. If any given file is compressed, its uncompressed content is\n" );
|
"output. If any given file is compressed, its uncompressed content is\n"
|
||||||
std::printf( "used. If a given file does not exist, and its name does not end with one\n" );
|
"used. If a given file does not exist, and its name does not end with one\n"
|
||||||
std::printf( "of the known extensions, zcat tries the compressed file names\n" );
|
"of the known extensions, zcat tries the compressed file names\n"
|
||||||
std::printf( "corresponding to the supported compressors. If no files are specified,\n" );
|
"corresponding to the supported formats. If no files are specified,\n"
|
||||||
std::printf( "data is read from standard input, decompressed if needed, and sent to\n" );
|
"data is read from standard input, decompressed if needed, and sent to\n"
|
||||||
std::printf( "standard output. Data read from standard input must be of the same type;\n" );
|
"standard output. Data read from standard input must be of the same type;\n"
|
||||||
std::printf( "all uncompressed or all compressed with the same compressor.\n" );
|
"all uncompressed or all in the same compression format.\n"
|
||||||
std::printf( "The supported compressors are bzip2, gzip, lzip and xz.\n" );
|
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||||
std::printf( "\nUsage: zcat [options] [files]\n" );
|
"\nUsage: zcat [options] [files]\n"
|
||||||
std::printf( "\nExit status is 0 if no errors occurred, 1 otherwise.\n" );
|
"\nExit status is 0 if no errors occurred, 1 otherwise.\n"
|
||||||
std::printf( "\nOptions:\n" );
|
"\nOptions:\n"
|
||||||
std::printf( " -h, --help display this help and exit\n" );
|
" -h, --help display this help and exit\n"
|
||||||
std::printf( " -V, --version output version information and exit\n" );
|
" -V, --version output version information and exit\n"
|
||||||
std::printf( " -A, --show-all equivalent to `-vET'\n" );
|
" -A, --show-all equivalent to '-vET'\n"
|
||||||
std::printf( " -b, --number-nonblank number nonblank output lines\n" );
|
" -b, --number-nonblank number nonblank output lines\n"
|
||||||
std::printf( " -e equivalent to `-vE'\n" );
|
" -e equivalent to '-vE'\n"
|
||||||
std::printf( " -E, --show-ends display `$' at end of each line\n" );
|
" -E, --show-ends display '$' at end of each line\n"
|
||||||
std::printf( " -n, --number number all output lines\n" );
|
" --format=<fmt> force given format (bz2, gz, lz, xz)\n"
|
||||||
std::printf( " -q, --quiet suppress all messages\n" );
|
" -n, --number number all output lines\n"
|
||||||
std::printf( " -r, --recursive operate recursively on directories\n" );
|
" -q, --quiet suppress all messages\n"
|
||||||
std::printf( " -s, --squeeze-blank never more than one single blank line\n" );
|
" -r, --recursive operate recursively on directories\n"
|
||||||
std::printf( " -t equivalent to `-vT'\n" );
|
" -s, --squeeze-blank never more than one single blank line\n"
|
||||||
std::printf( " -T, --show-tabs display TAB characters as `^I'\n" );
|
" -t equivalent to '-vT'\n"
|
||||||
std::printf( " -v, --show-nonprinting use `^' and `M-' notation, except for LF and TAB\n" );
|
" -T, --show-tabs display TAB characters as '^I'\n"
|
||||||
std::printf( " --verbose verbose mode (show error messages)\n" );
|
" -v, --show-nonprinting use '^' and 'M-' notation, except for LF and TAB\n"
|
||||||
|
" --verbose verbose mode (show error messages)\n" );
|
||||||
show_help_addr();
|
show_help_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +187,7 @@ int do_cat( const int infd, const int buffer_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cat( int infd, const std::string & input_filename,
|
int cat( int infd, const int format_type, const std::string & input_filename,
|
||||||
const Cat_options & cat_options )
|
const Cat_options & cat_options )
|
||||||
{
|
{
|
||||||
enum { buffer_size = 4096 };
|
enum { buffer_size = 4096 };
|
||||||
|
@ -196,7 +197,7 @@ int cat( int infd, const std::string & input_filename,
|
||||||
uint8_t * const outbuf = new uint8_t[(4*buffer_size)+256];
|
uint8_t * const outbuf = new uint8_t[(4*buffer_size)+256];
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
if( !set_data_feeder( &infd, &pid ) ) retval = 1;
|
if( !set_data_feeder( &infd, &pid, format_type ) ) retval = 1;
|
||||||
else
|
else
|
||||||
retval = do_cat( infd, buffer_size, inbuf, outbuf,
|
retval = do_cat( infd, buffer_size, inbuf, outbuf,
|
||||||
input_filename, cat_options );
|
input_filename, cat_options );
|
||||||
|
|
197
zcmp.cc
197
zcmp.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Zcmp - decompress and compare two files byte by byte
|
/* Zcmp - decompress and compare two files byte by byte
|
||||||
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
@ -30,9 +31,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
#include "zutils.h"
|
#include "zutils.h"
|
||||||
|
@ -44,73 +42,52 @@
|
||||||
#ifndef LLONG_MAX
|
#ifndef LLONG_MAX
|
||||||
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
|
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||||
#endif
|
#endif
|
||||||
#ifndef LLONG_MIN
|
|
||||||
#define LLONG_MIN (-LLONG_MAX - 1LL)
|
|
||||||
#endif
|
|
||||||
#ifndef ULLONG_MAX
|
|
||||||
#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#ifdef O_BINARY
|
#include "zcmpdiff.cc"
|
||||||
const int o_binary = O_BINARY;
|
|
||||||
#else
|
|
||||||
const int o_binary = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct { const char * from; const char * to; } const known_extensions[] = {
|
|
||||||
{ ".bz2", "" },
|
|
||||||
{ ".tbz", ".tar" },
|
|
||||||
{ ".tbz2", ".tar" },
|
|
||||||
{ ".gz", "" },
|
|
||||||
{ ".tgz", ".tar" },
|
|
||||||
{ ".lz", "" },
|
|
||||||
{ ".tlz", ".tar" },
|
|
||||||
{ ".xz", "" },
|
|
||||||
{ ".txz", ".tar" },
|
|
||||||
{ 0, 0 } };
|
|
||||||
|
|
||||||
|
|
||||||
void show_help() throw()
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zcmp compares two files (\"-\" means standard input), and if they\n" );
|
std::printf( "Zcmp compares two files (\"-\" means standard input), and if they\n"
|
||||||
std::printf( "differ, tells the first byte and line number where they differ. Bytes\n" );
|
"differ, tells the first byte and line number where they differ. Bytes\n"
|
||||||
std::printf( "and lines are numbered starting with 1. If any given file is compressed,\n" );
|
"and lines are numbered starting with 1. If any given file is compressed,\n"
|
||||||
std::printf( "its uncompressed content is used. Compressed files are uncompressed on\n" );
|
"its uncompressed content is used. Compressed files are uncompressed on\n"
|
||||||
std::printf( "the fly; no temporary files are created.\n" );
|
"the fly; no temporary files are created.\n"
|
||||||
std::printf( "The supported compressors are bzip2, gzip, lzip and xz.\n" );
|
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||||
std::printf( "\nUsage: zcmp [options] file1 [file2]\n" );
|
"\nUsage: zcmp [options] file1 [file2]\n"
|
||||||
std::printf( "\nCompares <file1> to <file2>. If <file2> is omitted zcmp tries the\n" );
|
"\nCompares <file1> to <file2>. If <file2> is omitted zcmp tries the\n"
|
||||||
std::printf( "following:\n" );
|
"following:\n"
|
||||||
std::printf( "If <file1> is compressed, compares <file1> to the file with the\n" );
|
"If <file1> is compressed, compares <file1> to the file with the\n"
|
||||||
std::printf( "corresponding decompressed file name (removes the extension from\n" );
|
"corresponding decompressed file name (removes the extension from\n"
|
||||||
std::printf( "<file1>).\n" );
|
"<file1>).\n"
|
||||||
std::printf( "If <file1> is not compressed, compares <file1> to the uncompressed\n" );
|
"If <file1> is not compressed, compares <file1> to the uncompressed\n"
|
||||||
std::printf( "contents of <file1>.[bz2|gz|lz|xz] (the first one that is found).\n" );
|
"contents of <file1>.[bz2|gz|lz|xz] (the first one that is found).\n"
|
||||||
std::printf( "If no suitable file is found, compares <file1> to data read from\n" );
|
"If no suitable file is found, compares <file1> to data read from\n"
|
||||||
std::printf( "standard input.\n" );
|
"standard input.\n"
|
||||||
std::printf( "\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n" );
|
"\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n"
|
||||||
std::printf( "\nOptions:\n" );
|
"\nOptions:\n"
|
||||||
std::printf( " -h, --help display this help and exit\n" );
|
" -h, --help display this help and exit\n"
|
||||||
std::printf( " -V, --version output version information and exit\n" );
|
" -V, --version output version information and exit\n"
|
||||||
std::printf( " -b, --print-bytes print differing bytes\n" );
|
" -b, --print-bytes print differing bytes\n"
|
||||||
std::printf( " -i, --ignore-initial=<n>[,<n2>] ignore differences in the first <n> bytes\n" );
|
" --format=[<fmt1>][,<fmt2>] force given formats (bz2, gz, lz, xz)\n"
|
||||||
std::printf( " -l, --list list position, value of all differing bytes\n" );
|
" -i, --ignore-initial=<n>[,<n2>] ignore differences in the first <n> bytes\n"
|
||||||
std::printf( " -n, --bytes=<n> compare at most <n> bytes\n" );
|
" -l, --list list position, value of all differing bytes\n"
|
||||||
std::printf( " -q, --quiet suppress all messages\n" );
|
" -n, --bytes=<n> compare at most <n> bytes\n"
|
||||||
std::printf( " -s, --silent (same as --quiet)\n" );
|
" -q, --quiet suppress all messages\n"
|
||||||
std::printf( " -v, --verbose verbose mode (same as --list)\n" );
|
" -s, --silent (same as --quiet)\n"
|
||||||
std::printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" );
|
" -v, --verbose verbose mode (same as --list)\n"
|
||||||
std::printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\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();
|
show_help_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
long long getnum( const char * const ptr, const char ** const tailp = 0,
|
long long getnum( const char * const ptr, const char ** const tailp = 0,
|
||||||
const long long llimit = LLONG_MIN + 1,
|
const long long llimit = 0,
|
||||||
const long long ulimit = LLONG_MAX ) throw()
|
const long long ulimit = LLONG_MAX )
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
char * tail;
|
char * tail;
|
||||||
|
@ -120,6 +97,7 @@ long long getnum( const char * const ptr, const char ** const tailp = 0,
|
||||||
show_error( "Bad or missing numerical argument.", 0, true );
|
show_error( "Bad or missing numerical argument.", 0, true );
|
||||||
std::exit( 2 );
|
std::exit( 2 );
|
||||||
}
|
}
|
||||||
|
if( result < 0 ) errno = ERANGE;
|
||||||
|
|
||||||
if( !errno && tail[0] && std::isalpha( tail[0] ) )
|
if( !errno && tail[0] && std::isalpha( tail[0] ) )
|
||||||
{
|
{
|
||||||
|
@ -148,7 +126,7 @@ long long getnum( const char * const ptr, const char ** const tailp = 0,
|
||||||
}
|
}
|
||||||
for( int i = 0; i < exponent; ++i )
|
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; }
|
else { errno = ERANGE; break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,53 +141,12 @@ long long getnum( const char * const ptr, const char ** const tailp = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int open_instream( const std::string & input_filename ) throw()
|
|
||||||
{
|
|
||||||
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
|
||||||
if( infd < 0 )
|
|
||||||
show_error2( "Can't open input file", input_filename.c_str() );
|
|
||||||
return infd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int open_other_instream( std::string & name ) throw()
|
|
||||||
{
|
|
||||||
for( int i = 0; known_extensions[i].from; ++i )
|
|
||||||
{ // search uncompressed version
|
|
||||||
const std::string from( known_extensions[i].from );
|
|
||||||
if( name.size() > from.size() &&
|
|
||||||
name.compare( name.size() - from.size(), from.size(), from ) == 0 )
|
|
||||||
{
|
|
||||||
name.resize( name.size() - from.size() );
|
|
||||||
name += known_extensions[i].to;
|
|
||||||
return open( name.c_str(), O_RDONLY | o_binary );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for( int i = 0; simple_extensions[i]; ++i )
|
|
||||||
{ // search compressed version
|
|
||||||
const std::string s( name + simple_extensions[i] );
|
|
||||||
const int infd = open( s.c_str(), O_RDONLY | o_binary );
|
|
||||||
if( infd >= 0 ) { name = s; return infd; }
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool check_identical( const char * const name1, const char * const name2 ) throw()
|
|
||||||
{
|
|
||||||
if( !std::strcmp( name1, name2 ) ) return true;
|
|
||||||
struct stat stat1, stat2;
|
|
||||||
if( stat( name1, &stat1 ) || stat( name2, &stat2 ) ) return false;
|
|
||||||
return ( stat1.st_ino == stat2.st_ino && stat1.st_dev == stat2.st_dev );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void parse_ignore_initial( const char * const arg, long long ignore_initial[2] )
|
void parse_ignore_initial( const char * const arg, long long ignore_initial[2] )
|
||||||
{
|
{
|
||||||
const char * tail;
|
const char * tail;
|
||||||
ignore_initial[0] = getnum( arg, &tail, 0 );
|
ignore_initial[0] = getnum( arg, &tail );
|
||||||
if( *tail == ',' || *tail == ':' )
|
if( *tail == ',' || *tail == ':' )
|
||||||
ignore_initial[1] = getnum( ++tail, 0, 0 );
|
ignore_initial[1] = getnum( ++tail );
|
||||||
else ignore_initial[1] = ignore_initial[0];
|
else ignore_initial[1] = ignore_initial[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,10 +190,11 @@ void sprintc( char * const buf, unsigned char c )
|
||||||
|
|
||||||
int block_compare( const uint8_t * const buffer0,
|
int block_compare( const uint8_t * const buffer0,
|
||||||
const uint8_t * const buffer1,
|
const uint8_t * const buffer1,
|
||||||
long long * line_numberp )
|
unsigned long long * const line_numberp )
|
||||||
{
|
{
|
||||||
const uint8_t * p0 = buffer0;
|
const uint8_t * p0 = buffer0;
|
||||||
const uint8_t * p1 = buffer1;
|
const uint8_t * p1 = buffer1;
|
||||||
|
|
||||||
if( verbosity == 0 )
|
if( verbosity == 0 )
|
||||||
{
|
{
|
||||||
int nl_count = 0;
|
int nl_count = 0;
|
||||||
|
@ -272,10 +210,11 @@ int block_compare( const uint8_t * const buffer0,
|
||||||
int cmp( const long long max_size, const int infd[2],
|
int cmp( const long long max_size, const int infd[2],
|
||||||
const std::string filenames[2], const bool print_bytes )
|
const std::string filenames[2], const bool print_bytes )
|
||||||
{
|
{
|
||||||
enum { buffer_size = 4096 };
|
const int buffer_size = 4096;
|
||||||
long long byte_number = 1;
|
unsigned long long byte_number = 1;
|
||||||
long long line_number = 1;
|
unsigned long long line_number = 1;
|
||||||
long long rest = max_size; // remaining number of bytes to compare
|
// remaining number of bytes to compare
|
||||||
|
long long rest = ( ( max_size >= 0 ) ? max_size : buffer_size );
|
||||||
// buffers with space for sentinels at the end
|
// buffers with space for sentinels at the end
|
||||||
uint8_t * const buffer0 = new uint8_t[2*(buffer_size+1)];
|
uint8_t * const buffer0 = new uint8_t[2*(buffer_size+1)];
|
||||||
uint8_t * const buffer1 = buffer0 + buffer_size + 1;
|
uint8_t * const buffer1 = buffer0 + buffer_size + 1;
|
||||||
|
@ -285,7 +224,8 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
|
|
||||||
while( rest > 0 )
|
while( rest > 0 )
|
||||||
{
|
{
|
||||||
const int size = std::min( rest, (long long)buffer_size );
|
const int size = std::min( (long long)buffer_size, rest );
|
||||||
|
if( max_size >= 0 ) rest -= size;
|
||||||
int rd[2]; // number of bytes read from each file
|
int rd[2]; // number of bytes read from each file
|
||||||
for( int i = 0; i < 2; ++i )
|
for( int i = 0; i < 2; ++i )
|
||||||
{
|
{
|
||||||
|
@ -296,7 +236,6 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rest -= size;
|
|
||||||
|
|
||||||
buffer0[rd[0]] = ~buffer1[rd[0]]; // sentinels for the block compare
|
buffer0[rd[0]] = ~buffer1[rd[0]]; // sentinels for the block compare
|
||||||
buffer1[rd[1]] = ~buffer0[rd[1]];
|
buffer1[rd[1]] = ~buffer0[rd[1]];
|
||||||
|
@ -311,7 +250,7 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
if( verbosity == 0 ) // show first difference
|
if( verbosity == 0 ) // show first difference
|
||||||
{
|
{
|
||||||
if( !print_bytes )
|
if( !print_bytes )
|
||||||
std::printf( "%s %s differ: byte %lld, line %lld\n",
|
std::printf( "%s %s differ: byte %llu, line %llu\n",
|
||||||
filenames[0].c_str(), filenames[1].c_str(),
|
filenames[0].c_str(), filenames[1].c_str(),
|
||||||
byte_number, line_number );
|
byte_number, line_number );
|
||||||
else
|
else
|
||||||
|
@ -320,7 +259,7 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
const unsigned char c1 = buffer1[first_diff];
|
const unsigned char c1 = buffer1[first_diff];
|
||||||
char buf0[5], buf1[5];
|
char buf0[5], buf1[5];
|
||||||
sprintc( buf0, c0 ); sprintc( buf1, c1 );
|
sprintc( buf0, c0 ); sprintc( buf1, c1 );
|
||||||
std::printf( "%s %s differ: byte %lld, line %lld is %3o %s %3o %s\n",
|
std::printf( "%s %s differ: byte %llu, line %llu is %3o %s %3o %s\n",
|
||||||
filenames[0].c_str(), filenames[1].c_str(),
|
filenames[0].c_str(), filenames[1].c_str(),
|
||||||
byte_number, line_number, c0, buf0, c1, buf1 );
|
byte_number, line_number, c0, buf0, c1, buf1 );
|
||||||
}
|
}
|
||||||
|
@ -336,12 +275,12 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
if( c0 != c1 )
|
if( c0 != c1 )
|
||||||
{
|
{
|
||||||
if( !print_bytes )
|
if( !print_bytes )
|
||||||
std::printf( "%lld %3o %3o\n", byte_number, c0, c1 );
|
std::printf( "%llu %3o %3o\n", byte_number, c0, c1 );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buf0[5], buf1[5];
|
char buf0[5], buf1[5];
|
||||||
sprintc( buf0, c0 ); sprintc( buf1, c1 );
|
sprintc( buf0, c0 ); sprintc( buf1, c1 );
|
||||||
std::printf( "%lld %3o %-4s %3o %s\n",
|
std::printf( "%llu %3o %-4s %3o %s\n",
|
||||||
byte_number, c0, buf0, c1, buf1 );
|
byte_number, c0, buf0, c1, buf1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,9 +307,11 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
|
|
||||||
int main( const int argc, const char * const argv[] )
|
int main( const int argc, const char * const argv[] )
|
||||||
{
|
{
|
||||||
|
enum { format_opt = 256 };
|
||||||
// number of initial bytes ignored for each file
|
// number of initial bytes ignored for each file
|
||||||
long long ignore_initial[2] = { 0, 0 };
|
long long ignore_initial[2] = { 0, 0 };
|
||||||
long long max_size = LLONG_MAX;
|
long long max_size = -1; // < 0 means unlimited size
|
||||||
|
int format_types[2] = { -1, -1 };
|
||||||
bool print_bytes = false;
|
bool print_bytes = false;
|
||||||
invocation_name = argv[0];
|
invocation_name = argv[0];
|
||||||
util_name = "zcmp";
|
util_name = "zcmp";
|
||||||
|
@ -386,6 +327,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ 's', "silent", Arg_parser::no },
|
{ 's', "silent", Arg_parser::no },
|
||||||
{ 'v', "verbose", Arg_parser::no },
|
{ 'v', "verbose", Arg_parser::no },
|
||||||
{ 'V', "version", Arg_parser::no },
|
{ 'V', "version", Arg_parser::no },
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
{ 0 , 0, Arg_parser::no } };
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
|
||||||
const Arg_parser parser( argc, argv, options );
|
const Arg_parser parser( argc, argv, options );
|
||||||
|
@ -404,18 +346,19 @@ int main( const int argc, const char * const argv[] )
|
||||||
case 'h': show_help(); return 0;
|
case 'h': show_help(); return 0;
|
||||||
case 'i': parse_ignore_initial( arg, ignore_initial ); break;
|
case 'i': parse_ignore_initial( arg, ignore_initial ); break;
|
||||||
case 'l': verbosity = 1; break;
|
case 'l': verbosity = 1; break;
|
||||||
case 'n': max_size = getnum( arg, 0, 0 ); break;
|
case 'n': max_size = getnum( arg ); break;
|
||||||
case 'q':
|
case 'q':
|
||||||
case 's': verbosity = -1; break;
|
case 's': verbosity = -1; break;
|
||||||
case 'v': verbosity = 1; break;
|
case 'v': verbosity = 1; break;
|
||||||
case 'V': show_version( "Zcmp" ); return 0;
|
case 'V': show_version( "Zcmp" ); return 0;
|
||||||
|
case format_opt: get_format_types( arg, format_types ); break;
|
||||||
default : internal_error( "uncaught option" );
|
default : internal_error( "uncaught option" );
|
||||||
}
|
}
|
||||||
} // end process options
|
} // end process options
|
||||||
|
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
_setmode( STDIN_FILENO, O_BINARY );
|
_fsetmode( stdin, "b" );
|
||||||
_setmode( STDOUT_FILENO, O_BINARY );
|
_fsetmode( stdout, "b" );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( argind >= parser.arguments() )
|
if( argind >= parser.arguments() )
|
||||||
|
@ -449,6 +392,9 @@ int main( const int argc, const char * const argv[] )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if( format_types[0] >= 0 || format_types[1] >= 0 )
|
||||||
|
{ show_error( "Two files must be given when format is specified.", 0, true );
|
||||||
|
return 2; }
|
||||||
filenames[1] = filenames[0];
|
filenames[1] = filenames[0];
|
||||||
infd[1] = open_other_instream( filenames[1] );
|
infd[1] = open_other_instream( filenames[1] );
|
||||||
if( infd[1] < 0 ) { infd[1] = STDIN_FILENO; filenames[1] = "-"; }
|
if( infd[1] < 0 ) { infd[1] = STDIN_FILENO; filenames[1] = "-"; }
|
||||||
|
@ -457,8 +403,8 @@ int main( const int argc, const char * const argv[] )
|
||||||
int old_infd[2]; // copy of file descriptors of the two files
|
int old_infd[2]; // copy of file descriptors of the two files
|
||||||
old_infd[0] = infd[0]; old_infd[1] = infd[1];
|
old_infd[0] = infd[0]; old_infd[1] = infd[1];
|
||||||
pid_t pid[2];
|
pid_t pid[2];
|
||||||
if( !set_data_feeder( &infd[0], &pid[0] ) ||
|
if( !set_data_feeder( &infd[0], &pid[0], format_types[0] ) ||
|
||||||
!set_data_feeder( &infd[1], &pid[1] ) )
|
!set_data_feeder( &infd[1], &pid[1], format_types[1] ) )
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
for( int i = 0; i < 2; ++i )
|
for( int i = 0; i < 2; ++i )
|
||||||
|
@ -470,10 +416,15 @@ int main( const int argc, const char * const argv[] )
|
||||||
|
|
||||||
int retval = cmp( max_size, infd, filenames, print_bytes );
|
int retval = cmp( max_size, infd, filenames, print_bytes );
|
||||||
|
|
||||||
if( retval != 0 )
|
if( retval != 0 || max_size >= 0 )
|
||||||
{
|
{
|
||||||
if( pid[0] ) kill( pid[0], SIGTERM );
|
for( int i = 0; i < 2; ++i )
|
||||||
if( pid[1] ) kill( pid[1], SIGTERM );
|
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
|
else
|
||||||
if( ( pid[0] && wait_for_child( pid[0], "data feeder" ) != 0 ) ||
|
if( ( pid[0] && wait_for_child( pid[0], "data feeder" ) != 0 ) ||
|
||||||
|
|
86
zcmpdiff.cc
Normal file
86
zcmpdiff.cc
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* Common code for Zcmp and Zdiff
|
||||||
|
Copyright (C) 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
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef O_BINARY
|
||||||
|
const int o_binary = O_BINARY;
|
||||||
|
#else
|
||||||
|
const int o_binary = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct { const char * from; const char * to; } const known_extensions[] = {
|
||||||
|
{ ".bz2", "" },
|
||||||
|
{ ".tbz", ".tar" },
|
||||||
|
{ ".tbz2", ".tar" },
|
||||||
|
{ ".gz", "" },
|
||||||
|
{ ".tgz", ".tar" },
|
||||||
|
{ ".lz", "" },
|
||||||
|
{ ".tlz", ".tar" },
|
||||||
|
{ ".xz", "" },
|
||||||
|
{ ".txz", ".tar" },
|
||||||
|
{ 0, 0 } };
|
||||||
|
|
||||||
|
|
||||||
|
int open_instream( const std::string & input_filename )
|
||||||
|
{
|
||||||
|
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
||||||
|
if( infd < 0 )
|
||||||
|
show_error2( "Can't open input file", input_filename.c_str() );
|
||||||
|
return infd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int open_other_instream( std::string & name )
|
||||||
|
{
|
||||||
|
for( int i = 0; known_extensions[i].from; ++i )
|
||||||
|
{ // search uncompressed version
|
||||||
|
const std::string from( known_extensions[i].from );
|
||||||
|
if( name.size() > from.size() &&
|
||||||
|
name.compare( name.size() - from.size(), from.size(), from ) == 0 )
|
||||||
|
{
|
||||||
|
name.resize( name.size() - from.size() );
|
||||||
|
name += known_extensions[i].to;
|
||||||
|
return open( name.c_str(), O_RDONLY | o_binary );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( int i = 0; i < num_formats; ++i )
|
||||||
|
{ // search compressed version
|
||||||
|
const std::string s( name + simple_extensions[format_order[i]] );
|
||||||
|
const int infd = open( s.c_str(), O_RDONLY | o_binary );
|
||||||
|
if( infd >= 0 ) { name = s; return infd; }
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void get_format_types( const std::string & arg, int format_types[2] )
|
||||||
|
{
|
||||||
|
const unsigned i = std::min( arg.find( ',' ), arg.size() );
|
||||||
|
if( i > 0 ) format_types[0] = get_format_type( arg.substr( 0, i ) );
|
||||||
|
else format_types[0] = -1;
|
||||||
|
if( i + 1 < arg.size() ) format_types[1] =
|
||||||
|
get_format_type( arg.substr( i + 1 ) );
|
||||||
|
else format_types[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool check_identical( const char * const name1, const char * const name2 )
|
||||||
|
{
|
||||||
|
if( !std::strcmp( name1, name2 ) ) return true;
|
||||||
|
struct stat stat1, stat2;
|
||||||
|
if( stat( name1, &stat1 ) || stat( name2, &stat2 ) ) return false;
|
||||||
|
return ( stat1.st_ino == stat2.st_ino && stat1.st_dev == stat2.st_dev );
|
||||||
|
}
|
217
zdiff.cc
217
zdiff.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Zdiff - decompress and compare two files line by line
|
/* Zdiff - decompress and compare two files line by line
|
||||||
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
@ -30,9 +31,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
#include "zutils.h"
|
#include "zutils.h"
|
||||||
|
@ -41,126 +39,60 @@
|
||||||
#error "Environments where CHAR_BIT != 8 are not supported."
|
#error "Environments where CHAR_BIT != 8 are not supported."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LLONG_MAX
|
|
||||||
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
|
|
||||||
#endif
|
|
||||||
#ifndef LLONG_MIN
|
|
||||||
#define LLONG_MIN (-LLONG_MAX - 1LL)
|
|
||||||
#endif
|
|
||||||
#ifndef ULLONG_MAX
|
|
||||||
#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string fifonames[2]; // names of the two fifos passed to diff
|
std::string fifonames[2]; // names of the two fifos passed to diff
|
||||||
|
|
||||||
#ifdef O_BINARY
|
#include "zcmpdiff.cc"
|
||||||
const int o_binary = O_BINARY;
|
|
||||||
#else
|
|
||||||
const int o_binary = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct { const char * from; const char * to; } const known_extensions[] = {
|
|
||||||
{ ".bz2", "" },
|
|
||||||
{ ".tbz", ".tar" },
|
|
||||||
{ ".tbz2", ".tar" },
|
|
||||||
{ ".gz", "" },
|
|
||||||
{ ".tgz", ".tar" },
|
|
||||||
{ ".lz", "" },
|
|
||||||
{ ".tlz", ".tar" },
|
|
||||||
{ ".xz", "" },
|
|
||||||
{ ".txz", ".tar" },
|
|
||||||
{ 0, 0 } };
|
|
||||||
|
|
||||||
|
|
||||||
void show_help() throw()
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zdiff compares two files (\"-\" means standard input), and if they\n" );
|
std::printf( "Zdiff compares two files (\"-\" means standard input), and if they\n"
|
||||||
std::printf( "differ, shows the differences line by line. If any given file is\n" );
|
"differ, shows the differences line by line. If any given file is\n"
|
||||||
std::printf( "compressed, its uncompressed content is used. Zdiff is a front end to\n" );
|
"compressed, its uncompressed content is used. Zdiff is a front end to\n"
|
||||||
std::printf( "the diff program and has the limitation that messages from diff refer to\n" );
|
"the diff program and has the limitation that messages from diff refer to\n"
|
||||||
std::printf( "temporary filenames instead of those specified.\n" );
|
"temporary filenames instead of those specified.\n"
|
||||||
std::printf( "The supported compressors are bzip2, gzip, lzip and xz.\n" );
|
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||||
std::printf( "\nUsage: zdiff [options] file1 [file2]\n" );
|
"\nUsage: zdiff [options] file1 [file2]\n"
|
||||||
std::printf( "\nCompares <file1> to <file2>. If <file2> is omitted zdiff tries the\n" );
|
"\nCompares <file1> to <file2>. If <file2> is omitted zdiff tries the\n"
|
||||||
std::printf( "following:\n" );
|
"following:\n"
|
||||||
std::printf( "If <file1> is compressed, compares <file1> to the file with the\n" );
|
"If <file1> is compressed, compares <file1> to the file with the\n"
|
||||||
std::printf( "corresponding decompressed file name (removes the extension from\n" );
|
"corresponding decompressed file name (removes the extension from\n"
|
||||||
std::printf( "<file1>).\n" );
|
"<file1>).\n"
|
||||||
std::printf( "If <file1> is not compressed, compares <file1> to the uncompressed\n" );
|
"If <file1> is not compressed, compares <file1> to the uncompressed\n"
|
||||||
std::printf( "contents of <file1>.[bz2|gz|lz|xz] (the first one that is found).\n" );
|
"contents of <file1>.[bz2|gz|lz|xz] (the first one that is found).\n"
|
||||||
std::printf( "If no suitable file is found, compares <file1> to data read from\n" );
|
"If no suitable file is found, compares <file1> to data read from\n"
|
||||||
std::printf( "standard input.\n" );
|
"standard input.\n"
|
||||||
std::printf( "\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n" );
|
"\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n"
|
||||||
std::printf( "\nOptions:\n" );
|
"\nOptions:\n"
|
||||||
std::printf( " -h, --help display this help and exit\n" );
|
" -h, --help display this help and exit\n"
|
||||||
std::printf( " -V, --version output version information and exit\n" );
|
" -V, --version output version information and exit\n"
|
||||||
std::printf( " -a, --text treat all files as text\n" );
|
" -a, --text treat all files as text\n"
|
||||||
std::printf( " -b, --ignore-space-change ignore changes in the amount of white space\n" );
|
" -b, --ignore-space-change ignore changes in the amount of white space\n"
|
||||||
std::printf( " -B, --ignore-blank-lines ignore changes whose lines are all blank\n" );
|
" -B, --ignore-blank-lines ignore changes whose lines are all blank\n"
|
||||||
std::printf( " -c use the context output format\n" );
|
" -c use the context output format\n"
|
||||||
std::printf( " -C, --context=<n> same as -c but use <n> lines of context\n" );
|
" -C, --context=<n> same as -c but use <n> lines of context\n"
|
||||||
std::printf( " -d, --minimal try hard to find a smaller set of changes\n" );
|
" -d, --minimal try hard to find a smaller set of changes\n"
|
||||||
std::printf( " -E, --ignore-tab-expansion ignore changes due to tab expansion\n" );
|
" -E, --ignore-tab-expansion ignore changes due to tab expansion\n"
|
||||||
std::printf( " -i, --ignore-case ignore case differences in file contents\n" );
|
" --format=[<fmt1>][,<fmt2>] force given formats (bz2, gz, lz, xz)\n"
|
||||||
std::printf( " -p, --show-c-function show which C function each change is in\n" );
|
" -i, --ignore-case ignore case differences in file contents\n"
|
||||||
std::printf( " -q, --brief output only whether files differ\n" );
|
" -p, --show-c-function show which C function each change is in\n"
|
||||||
std::printf( " -s, --report-identical-files report when two files are identical\n" );
|
" -q, --brief output only whether files differ\n"
|
||||||
std::printf( " -t, --expand-tabs expand tabs to spaces in output\n" );
|
" -s, --report-identical-files report when two files are identical\n"
|
||||||
std::printf( " -T, --initial-tab make tabs line up by prepending a tab\n" );
|
" -t, --expand-tabs expand tabs to spaces in output\n"
|
||||||
std::printf( " -u use the unified output format\n" );
|
" -T, --initial-tab make tabs line up by prepending a tab\n"
|
||||||
std::printf( " -U, --unified=<n> same as -u but use <n> lines of context\n" );
|
" -u use the unified output format\n"
|
||||||
std::printf( " -w, --ignore-all-space ignore all white space\n" );
|
" -U, --unified=<n> same as -u but use <n> lines of context\n"
|
||||||
std::printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" );
|
" -w, --ignore-all-space ignore all white space\n"
|
||||||
std::printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\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();
|
show_help_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int open_instream( const std::string & input_filename ) throw()
|
const char * my_basename( const char * filename )
|
||||||
{
|
|
||||||
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
|
||||||
if( infd < 0 )
|
|
||||||
show_error2( "Can't open input file", input_filename.c_str() );
|
|
||||||
return infd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int open_other_instream( std::string & name ) throw()
|
|
||||||
{
|
|
||||||
for( int i = 0; known_extensions[i].from; ++i )
|
|
||||||
{ // search uncompressed version
|
|
||||||
const std::string from( known_extensions[i].from );
|
|
||||||
if( name.size() > from.size() &&
|
|
||||||
name.compare( name.size() - from.size(), from.size(), from ) == 0 )
|
|
||||||
{
|
|
||||||
name.resize( name.size() - from.size() );
|
|
||||||
name += known_extensions[i].to;
|
|
||||||
return open( name.c_str(), O_RDONLY | o_binary );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for( int i = 0; simple_extensions[i]; ++i )
|
|
||||||
{ // search compressed version
|
|
||||||
const std::string s( name + simple_extensions[i] );
|
|
||||||
const int infd = open( s.c_str(), O_RDONLY | o_binary );
|
|
||||||
if( infd >= 0 ) { name = s; return infd; }
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool check_identical( const char * const name1, const char * const name2 ) throw()
|
|
||||||
{
|
|
||||||
if( !std::strcmp( name1, name2 ) ) return true;
|
|
||||||
struct stat stat1, stat2;
|
|
||||||
if( stat( name1, &stat1 ) || stat( name2, &stat2 ) ) return false;
|
|
||||||
return ( stat1.st_ino == stat2.st_ino && stat1.st_dev == stat2.st_dev );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char * my_basename( const char * filename ) throw()
|
|
||||||
{
|
{
|
||||||
const char * c = filename;
|
const char * c = filename;
|
||||||
while( *c ) { if( *c == '/' ) { filename = c + 1; } ++c; }
|
while( *c ) { if( *c == '/' ) { filename = c + 1; } ++c; }
|
||||||
|
@ -168,7 +100,7 @@ const char * my_basename( const char * filename ) throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" void remove_fifos() throw()
|
extern "C" void remove_fifos()
|
||||||
{
|
{
|
||||||
if( fifonames[0].size() )
|
if( fifonames[0].size() )
|
||||||
{ std::remove( fifonames[0].c_str() ); fifonames[0].clear(); }
|
{ std::remove( fifonames[0].c_str() ); fifonames[0].clear(); }
|
||||||
|
@ -191,7 +123,7 @@ bool set_fifonames( const std::string filenames[2] )
|
||||||
if( p ) fifonames[i] = p; else fifonames[i] = "/tmp";
|
if( p ) fifonames[i] = p; else fifonames[i] = "/tmp";
|
||||||
fifonames[i] += '/';
|
fifonames[i] += '/';
|
||||||
int n = ( 2 * pid ) + i;
|
int n = ( 2 * pid ) + i;
|
||||||
const unsigned int pos = fifonames[i].size();
|
const unsigned pos = fifonames[i].size();
|
||||||
do { fifonames[i].insert( pos, 1, codes[n % num_codes] );
|
do { fifonames[i].insert( pos, 1, codes[n % num_codes] );
|
||||||
n /= num_codes; }
|
n /= num_codes; }
|
||||||
while( n );
|
while( n );
|
||||||
|
@ -216,15 +148,15 @@ bool set_fifonames( const std::string filenames[2] )
|
||||||
|
|
||||||
|
|
||||||
bool set_data_feeder( const std::string & fifoname, const int infd,
|
bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
pid_t * const pidp )
|
pid_t * const pidp, const int format_type )
|
||||||
{
|
{
|
||||||
std::string file_type;
|
const uint8_t * magic_data = 0;
|
||||||
const uint8_t * magic_data;
|
int magic_size = 0;
|
||||||
int magic_size;
|
const char * const decompressor_name = ( format_type >= 0 ) ?
|
||||||
const bool compressed =
|
decompressor_names[format_type] :
|
||||||
test_format( infd, file_type, &magic_data, &magic_size );
|
test_format( infd, &magic_data, &magic_size );
|
||||||
|
|
||||||
if( compressed ) // compressed with `file_type'
|
if( decompressor_name ) // compressed
|
||||||
{
|
{
|
||||||
int fda[2]; // pipe from feeder to decompressor
|
int fda[2]; // pipe from feeder to decompressor
|
||||||
if( pipe( fda ) < 0 )
|
if( pipe( fda ) < 0 )
|
||||||
|
@ -239,7 +171,7 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
if( outfd < 0 )
|
if( outfd < 0 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't open FIFO `%s' for writing: %s.\n",
|
std::fprintf( stderr, "%s: Can't open FIFO '%s' for writing: %s.\n",
|
||||||
util_name, fifoname.c_str(), std::strerror( errno ) );
|
util_name, fifoname.c_str(), std::strerror( errno ) );
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
}
|
}
|
||||||
|
@ -247,19 +179,20 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
dup2( outfd, STDOUT_FILENO ) >= 0 &&
|
dup2( outfd, STDOUT_FILENO ) >= 0 &&
|
||||||
close( fda[0] ) == 0 && close( fda[1] ) == 0 &&
|
close( fda[0] ) == 0 && close( fda[1] ) == 0 &&
|
||||||
close( outfd ) == 0 )
|
close( outfd ) == 0 )
|
||||||
execlp( file_type.c_str(), file_type.c_str(), "-cdfq", (char *)0 );
|
execlp( decompressor_name, decompressor_name,
|
||||||
show_exec_error( file_type.c_str() );
|
(verbosity >= 0) ? "-d" : "-dq", (char *)0 );
|
||||||
|
show_exec_error( decompressor_name );
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
}
|
}
|
||||||
if( pid2 < 0 )
|
if( pid2 < 0 )
|
||||||
{ show_fork_error( file_type.c_str() ); _exit( 2 ); }
|
{ show_fork_error( decompressor_name ); _exit( 2 ); }
|
||||||
|
|
||||||
if( close( fda[0] ) != 0 ||
|
if( close( fda[0] ) != 0 ||
|
||||||
!feed_data( infd, fda[1], magic_data, magic_size ) )
|
!feed_data( infd, fda[1], magic_data, magic_size ) )
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
if( close( fda[1] ) != 0 )
|
if( close( fda[1] ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); _exit( 2 ); }
|
{ show_close_error( "data feeder" ); _exit( 2 ); }
|
||||||
_exit( wait_for_child( pid2, file_type.c_str() ) );
|
_exit( wait_for_child( pid2, decompressor_name ) );
|
||||||
}
|
}
|
||||||
// parent
|
// parent
|
||||||
close( fda[0] ); close( fda[1] );
|
close( fda[0] ); close( fda[1] );
|
||||||
|
@ -276,7 +209,7 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
if( outfd < 0 )
|
if( outfd < 0 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't open FIFO `%s' for writing: %s.\n",
|
std::fprintf( stderr, "%s: Can't open FIFO '%s' for writing: %s.\n",
|
||||||
util_name, fifoname.c_str(), std::strerror( errno ) );
|
util_name, fifoname.c_str(), std::strerror( errno ) );
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
}
|
}
|
||||||
|
@ -295,7 +228,7 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" void signal_handler( int sig ) throw()
|
extern "C" void signal_handler( int sig )
|
||||||
{
|
{
|
||||||
remove_fifos();
|
remove_fifos();
|
||||||
std::signal( sig, SIG_DFL );
|
std::signal( sig, SIG_DFL );
|
||||||
|
@ -303,7 +236,7 @@ extern "C" void signal_handler( int sig ) throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_signals() throw()
|
void set_signals()
|
||||||
{
|
{
|
||||||
std::signal( SIGHUP, signal_handler );
|
std::signal( SIGHUP, signal_handler );
|
||||||
std::signal( SIGINT, signal_handler );
|
std::signal( SIGINT, signal_handler );
|
||||||
|
@ -315,7 +248,9 @@ void set_signals() throw()
|
||||||
|
|
||||||
int main( const int argc, const char * const argv[] )
|
int main( const int argc, const char * const argv[] )
|
||||||
{
|
{
|
||||||
|
enum { format_opt = 256 };
|
||||||
std::vector< const char * > diff_args; // args to diff, maybe empty
|
std::vector< const char * > diff_args; // args to diff, maybe empty
|
||||||
|
int format_types[2] = { -1, -1 };
|
||||||
invocation_name = argv[0];
|
invocation_name = argv[0];
|
||||||
util_name = "zdiff";
|
util_name = "zdiff";
|
||||||
|
|
||||||
|
@ -339,6 +274,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ 'U', "unified", Arg_parser::yes },
|
{ 'U', "unified", Arg_parser::yes },
|
||||||
{ 'V', "version", Arg_parser::no },
|
{ 'V', "version", Arg_parser::no },
|
||||||
{ 'w', "ignore-all-space", Arg_parser::no },
|
{ 'w', "ignore-all-space", Arg_parser::no },
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
{ 0 , 0, Arg_parser::no } };
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
|
||||||
const Arg_parser parser( argc, argv, options );
|
const Arg_parser parser( argc, argv, options );
|
||||||
|
@ -371,13 +307,14 @@ int main( const int argc, const char * const argv[] )
|
||||||
case 'U': diff_args.push_back( "-U" ); diff_args.push_back( arg ); break;
|
case 'U': diff_args.push_back( "-U" ); diff_args.push_back( arg ); break;
|
||||||
case 'V': show_version( "Zdiff" ); return 0;
|
case 'V': show_version( "Zdiff" ); return 0;
|
||||||
case 'w': diff_args.push_back( "-w" ); break;
|
case 'w': diff_args.push_back( "-w" ); break;
|
||||||
|
case format_opt: get_format_types( arg, format_types ); break;
|
||||||
default : internal_error( "uncaught option" );
|
default : internal_error( "uncaught option" );
|
||||||
}
|
}
|
||||||
} // end process options
|
} // end process options
|
||||||
|
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
_setmode( STDIN_FILENO, O_BINARY );
|
_fsetmode( stdin, "b" );
|
||||||
_setmode( STDOUT_FILENO, O_BINARY );
|
_fsetmode( stdout, "b" );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( argind >= parser.arguments() )
|
if( argind >= parser.arguments() )
|
||||||
|
@ -408,6 +345,9 @@ int main( const int argc, const char * const argv[] )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if( format_types[0] >= 0 || format_types[1] >= 0 )
|
||||||
|
{ show_error( "Two files must be given when format is specified.", 0, true );
|
||||||
|
return 2; }
|
||||||
filenames[1] = filenames[0];
|
filenames[1] = filenames[0];
|
||||||
infd[1] = open_other_instream( filenames[1] );
|
infd[1] = open_other_instream( filenames[1] );
|
||||||
if( infd[1] < 0 ) { infd[1] = STDIN_FILENO; filenames[1] = "-"; }
|
if( infd[1] < 0 ) { infd[1] = STDIN_FILENO; filenames[1] = "-"; }
|
||||||
|
@ -422,7 +362,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{
|
{
|
||||||
const char ** const argv = new const char *[diff_args.size()+5];
|
const char ** const argv = new const char *[diff_args.size()+5];
|
||||||
argv[0] = DIFF;
|
argv[0] = DIFF;
|
||||||
for( unsigned int i = 0; i < diff_args.size(); ++i )
|
for( unsigned i = 0; i < diff_args.size(); ++i )
|
||||||
argv[i+1] = diff_args[i];
|
argv[i+1] = diff_args[i];
|
||||||
argv[diff_args.size()+1] = "--";
|
argv[diff_args.size()+1] = "--";
|
||||||
argv[diff_args.size()+2] = fifonames[0].c_str();
|
argv[diff_args.size()+2] = fifonames[0].c_str();
|
||||||
|
@ -437,16 +377,21 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ show_fork_error( DIFF ); return 2; }
|
{ show_fork_error( DIFF ); return 2; }
|
||||||
|
|
||||||
pid_t pid[2];
|
pid_t pid[2];
|
||||||
if( !set_data_feeder( fifonames[0], infd[0], &pid[0] ) ||
|
if( !set_data_feeder( fifonames[0], infd[0], &pid[0], format_types[0] ) ||
|
||||||
!set_data_feeder( fifonames[1], infd[1], &pid[1] ) )
|
!set_data_feeder( fifonames[1], infd[1], &pid[1], format_types[1] ) )
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
int retval = wait_for_child( diff_pid, DIFF );
|
int retval = wait_for_child( diff_pid, DIFF );
|
||||||
|
|
||||||
if( retval != 0 )
|
if( retval != 0 )
|
||||||
{
|
{
|
||||||
if( pid[0] ) kill( pid[0], SIGTERM );
|
for( int i = 0; i < 2; ++i )
|
||||||
if( pid[1] ) kill( pid[1], SIGTERM );
|
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
|
else
|
||||||
if( ( pid[0] && wait_for_child( pid[0], "data feeder" ) != 0 ) ||
|
if( ( pid[0] && wait_for_child( pid[0], "data feeder" ) != 0 ) ||
|
||||||
|
|
103
zgrep.cc
103
zgrep.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Zgrep - search compressed files for a regular expression
|
/* Zgrep - search compressed files for a regular expression
|
||||||
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,57 +15,59 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void show_zgrep_help() throw()
|
void show_zgrep_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zgrep is a front end to the grep program that allows transparent search\n" );
|
std::printf( "Zgrep is a front end to the grep program that allows transparent search\n"
|
||||||
std::printf( "on any combination of compressed and non-compressed files. If any given\n" );
|
"on any combination of compressed and non-compressed files. If any given\n"
|
||||||
std::printf( "file is compressed, its uncompressed content is used. If a given file\n" );
|
"file is compressed, its uncompressed content is used. If a given file\n"
|
||||||
std::printf( "does not exist, and its name does not end with one of the known\n" );
|
"does not exist, and its name does not end with one of the known\n"
|
||||||
std::printf( "extensions, zgrep tries the compressed file names corresponding to the\n" );
|
"extensions, zgrep tries the compressed file names corresponding to the\n"
|
||||||
std::printf( "supported compressors. If no files are specified, data is read from\n" );
|
"supported formats. If no files are specified, data is read from\n"
|
||||||
std::printf( "standard input, decompressed if needed, and fed to grep. Data read from\n" );
|
"standard input, decompressed if needed, and fed to grep. Data read from\n"
|
||||||
std::printf( "standard input must be of the same type; all uncompressed or all\n" );
|
"standard input must be of the same type; all uncompressed or all\n"
|
||||||
std::printf( "compressed with the same compressor.\n" );
|
"in the same compression format.\n"
|
||||||
std::printf( "The supported compressors are bzip2, gzip, lzip and xz.\n" );
|
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||||
std::printf( "\nUsage: zgrep [options] <pattern> [files]\n" );
|
"\nUsage: zgrep [options] <pattern> [files]\n"
|
||||||
std::printf( "\nExit status is 0 if match, 1 if no match, 2 if trouble.\n" );
|
"\nExit status is 0 if match, 1 if no match, 2 if trouble.\n"
|
||||||
std::printf( "\nOptions:\n" );
|
"\nOptions:\n"
|
||||||
std::printf( " --help display this help and exit\n" );
|
" --help display this help and exit\n"
|
||||||
std::printf( " -V, --version output version information and exit\n" );
|
" -V, --version output version information and exit\n"
|
||||||
std::printf( " -a, --text treat all files as text\n" );
|
" -a, --text treat all files as text\n"
|
||||||
std::printf( " -A, --after-context=<n> print <n> lines of trailing context\n" );
|
" -A, --after-context=<n> print <n> lines of trailing context\n"
|
||||||
std::printf( " -b, --byte-offset print the byte offset of each line\n" );
|
" -b, --byte-offset print the byte offset of each line\n"
|
||||||
std::printf( " -B, --before-context=<n> print <n> lines of leading context\n" );
|
" -B, --before-context=<n> print <n> lines of leading context\n"
|
||||||
std::printf( " -c, --count only print a count of matching lines per file\n" );
|
" -c, --count only print a count of matching lines per file\n"
|
||||||
std::printf( " -C, --context=<n> print <n> lines of output context\n" );
|
" -C, --context=<n> print <n> lines of output context\n"
|
||||||
std::printf( " -e, --regexp=<pattern> use <pattern> as the pattern to match\n" );
|
" -e, --regexp=<pattern> use <pattern> as the pattern to match\n"
|
||||||
std::printf( " -E, --extended-regexp <pattern> is an extended regular expression\n" );
|
" -E, --extended-regexp <pattern> is an extended regular expression\n"
|
||||||
std::printf( " -f, --file=<file> obtain patterns from <file>\n" );
|
" -f, --file=<file> obtain patterns from <file>\n"
|
||||||
std::printf( " -F, --fixed-strings <pattern> is a set of newline-separated strings\n" );
|
" -F, --fixed-strings <pattern> is a set of newline-separated strings\n"
|
||||||
std::printf( " -h, --no-filename suppress the prefixing filename on output\n" );
|
" --format=<fmt> force given format (bz2, gz, lz, xz)\n"
|
||||||
std::printf( " -H, --with-filename print the filename for each match\n" );
|
" -h, --no-filename suppress the prefixing filename on output\n"
|
||||||
std::printf( " -i, --ignore-case ignore case distinctions\n" );
|
" -H, --with-filename print the filename for each match\n"
|
||||||
std::printf( " -I ignore binary files\n" );
|
" -i, --ignore-case ignore case distinctions\n"
|
||||||
std::printf( " -l, --files-with-matches only print names of files containing matches\n" );
|
" -I ignore binary files\n"
|
||||||
std::printf( " -L, --files-without-match only print names of files containing no matches\n" );
|
" -l, --files-with-matches only print names of files containing matches\n"
|
||||||
std::printf( " -m, --max-count=<n> stop after <n> matches\n" );
|
" -L, --files-without-match only print names of files containing no matches\n"
|
||||||
std::printf( " -n, --line-number print the line number of each line\n" );
|
" -m, --max-count=<n> stop after <n> matches\n"
|
||||||
std::printf( " -o, --only-matching show only the part of a line matching <pattern>\n" );
|
" -n, --line-number print the line number of each line\n"
|
||||||
std::printf( " -q, --quiet suppress all messages\n" );
|
" -o, --only-matching show only the part of a line matching <pattern>\n"
|
||||||
std::printf( " -r, --recursive operate recursively on directories\n" );
|
" -q, --quiet suppress all messages\n"
|
||||||
std::printf( " -s, --no-messages suppress error messages\n" );
|
" -r, --recursive operate recursively on directories\n"
|
||||||
std::printf( " -v, --invert-match select non-matching lines\n" );
|
" -s, --no-messages suppress error messages\n"
|
||||||
std::printf( " --verbose verbose mode (show error messages)\n" );
|
" -v, --invert-match select non-matching lines\n"
|
||||||
std::printf( " -w, --word-regexp match only whole words\n" );
|
" --verbose verbose mode (show error messages)\n"
|
||||||
std::printf( " -x, --line-regexp match only whole lines\n" );
|
" -w, --word-regexp match only whole words\n"
|
||||||
|
" -x, --line-regexp match only whole lines\n" );
|
||||||
show_help_addr();
|
show_help_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int zgrep_stdin( int infd, const std::vector< const char * > & grep_args )
|
int zgrep_stdin( int infd, const int format_type,
|
||||||
|
const std::vector< const char * > & grep_args )
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
if( !set_data_feeder( &infd, &pid ) ) return 2;
|
if( !set_data_feeder( &infd, &pid, format_type ) ) return 2;
|
||||||
const pid_t grep_pid = fork();
|
const pid_t grep_pid = fork();
|
||||||
if( grep_pid == 0 ) // child (grep)
|
if( grep_pid == 0 ) // child (grep)
|
||||||
{
|
{
|
||||||
|
@ -73,7 +75,7 @@ int zgrep_stdin( int infd, const std::vector< const char * > & grep_args )
|
||||||
{
|
{
|
||||||
const char ** const argv = new const char *[grep_args.size()+2];
|
const char ** const argv = new const char *[grep_args.size()+2];
|
||||||
argv[0] = GREP;
|
argv[0] = GREP;
|
||||||
for( unsigned int i = 0; i < grep_args.size(); ++i )
|
for( unsigned i = 0; i < grep_args.size(); ++i )
|
||||||
argv[i+1] = grep_args[i];
|
argv[i+1] = grep_args[i];
|
||||||
argv[grep_args.size()+1] = 0;
|
argv[grep_args.size()+1] = 0;
|
||||||
execvp( argv[0], (char **)argv );
|
execvp( argv[0], (char **)argv );
|
||||||
|
@ -96,12 +98,13 @@ int zgrep_stdin( int infd, const std::vector< const char * > & grep_args )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int zgrep_file( int infd, const std::string & input_filename,
|
int zgrep_file( int infd, const int format_type,
|
||||||
|
const std::string & input_filename,
|
||||||
const std::vector< const char * > & grep_args,
|
const std::vector< const char * > & grep_args,
|
||||||
const bool grep_list, const bool grep_show_name )
|
const bool grep_list, const bool grep_show_name )
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
if( !set_data_feeder( &infd, &pid ) ) return 2;
|
if( !set_data_feeder( &infd, &pid, format_type ) ) return 2;
|
||||||
int fda[2]; // pipe from grep
|
int fda[2]; // pipe from grep
|
||||||
if( pipe( fda ) < 0 )
|
if( pipe( fda ) < 0 )
|
||||||
{ show_error( "Can't create pipe", errno ); return 2; }
|
{ show_error( "Can't create pipe", errno ); return 2; }
|
||||||
|
@ -114,7 +117,7 @@ int zgrep_file( int infd, const std::string & input_filename,
|
||||||
{
|
{
|
||||||
const char ** const argv = new const char *[grep_args.size()+2];
|
const char ** const argv = new const char *[grep_args.size()+2];
|
||||||
argv[0] = GREP;
|
argv[0] = GREP;
|
||||||
for( unsigned int i = 0; i < grep_args.size(); ++i )
|
for( unsigned i = 0; i < grep_args.size(); ++i )
|
||||||
argv[i+1] = grep_args[i];
|
argv[i+1] = grep_args[i];
|
||||||
argv[grep_args.size()+1] = 0;
|
argv[grep_args.size()+1] = 0;
|
||||||
execvp( argv[0], (char **)argv );
|
execvp( argv[0], (char **)argv );
|
||||||
|
@ -144,7 +147,7 @@ int zgrep_file( int infd, const std::string & input_filename,
|
||||||
if( buffer[i] == '\n' ) line_begin = true;
|
if( buffer[i] == '\n' ) line_begin = true;
|
||||||
putchar( buffer[i] );
|
putchar( buffer[i] );
|
||||||
}
|
}
|
||||||
else if( std::fwrite( buffer, 1, size, stdout ) != (unsigned int)size )
|
else if( std::fwrite( buffer, 1, size, stdout ) != (unsigned)size )
|
||||||
{ show_error( "Write error", errno ); return 2; }
|
{ show_error( "Write error", errno ); return 2; }
|
||||||
}
|
}
|
||||||
if( size < buffer_size ) break;
|
if( size < buffer_size ) break;
|
||||||
|
|
78
ztest.cc
78
ztest.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Ztest - verify integrity of compressed files
|
/* Ztest - verify integrity of compressed files
|
||||||
Copyright (C) 2010, 2011 Antonio Diaz Diaz.
|
Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,32 +15,39 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void show_ztest_help() throw()
|
void show_ztest_help()
|
||||||
{
|
{
|
||||||
std::printf( "Ztest verifies the integrity of the specified compressed files.\n" );
|
std::printf( "Ztest verifies the integrity of the specified compressed files.\n"
|
||||||
std::printf( "Non-compressed files are ignored. If no files are specified, the\n" );
|
"Non-compressed files are ignored. If no files are specified, the\n"
|
||||||
std::printf( "integrity of compressed data read from standard input is verified. Data\n" );
|
"integrity of compressed data read from standard input is verified. Data\n"
|
||||||
std::printf( "read from standard input must be all compressed with the same compressor.\n" );
|
"read from standard input must be all in the same compression format.\n"
|
||||||
std::printf( "The supported compressors are bzip2, gzip, lzip and xz.\n" );
|
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
||||||
std::printf( "\nUsage: ztest [options] [files]\n" );
|
"\nNote that some xz files lack integrity information, and therefore can't\n"
|
||||||
std::printf( "\nExit status is 2 if any compressed file is corrupt, 0 otherwise.\n" );
|
"be verified as reliably as the other formats can.\n"
|
||||||
std::printf( "\nOptions:\n" );
|
"\nUsage: ztest [options] [files]\n"
|
||||||
std::printf( " -h, --help display this help and exit\n" );
|
"\nExit status is 0 if all compressed files verify OK, 1 if environmental\n"
|
||||||
std::printf( " -V, --version output version information and exit\n" );
|
"problems (file not found, invalid flags, I/O errors, etc), 2 if any\n"
|
||||||
std::printf( " -q, --quiet suppress all messages\n" );
|
"compressed file is corrupt or invalid.\n"
|
||||||
std::printf( " -r, --recursive operate recursively on directories\n" );
|
"\nOptions:\n"
|
||||||
std::printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" );
|
" -h, --help display this help and exit\n"
|
||||||
|
" -V, --version output version information and exit\n"
|
||||||
|
" --format=<fmt> force given format (bz2, gz, lz, xz)\n"
|
||||||
|
" -q, --quiet suppress all messages\n"
|
||||||
|
" -r, --recursive operate recursively on directories\n"
|
||||||
|
" -v, --verbose be verbose (a 2nd -v gives more)\n" );
|
||||||
show_help_addr();
|
show_help_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ztest_stdin( const int infd,
|
int ztest_stdin( const int infd, const int format_type,
|
||||||
const std::vector< const char * > & ztest_args )
|
const std::vector< const char * > & ztest_args )
|
||||||
{
|
{
|
||||||
std::string file_type;
|
const uint8_t * magic_data = 0;
|
||||||
const uint8_t * magic_data;
|
|
||||||
int magic_size = 0;
|
int magic_size = 0;
|
||||||
if( !test_format( infd, file_type, &magic_data, &magic_size ) )
|
const char * const decompressor_name = ( format_type >= 0 ) ?
|
||||||
|
decompressor_names[format_type] :
|
||||||
|
test_format( infd, &magic_data, &magic_size );
|
||||||
|
if( !decompressor_name )
|
||||||
{ show_error( "Unknown data format read from stdin." ); return 2; }
|
{ show_error( "Unknown data format read from stdin." ); return 2; }
|
||||||
int fda[2]; // pipe from feeder
|
int fda[2]; // pipe from feeder
|
||||||
if( pipe( fda ) < 0 )
|
if( pipe( fda ) < 0 )
|
||||||
|
@ -53,19 +60,19 @@ int ztest_stdin( const int infd,
|
||||||
close( fda[0] ) == 0 && close( fda[1] ) == 0 )
|
close( fda[0] ) == 0 && close( fda[1] ) == 0 )
|
||||||
{
|
{
|
||||||
const char ** const argv = new const char *[ztest_args.size()+3];
|
const char ** const argv = new const char *[ztest_args.size()+3];
|
||||||
argv[0] = file_type.c_str();
|
argv[0] = decompressor_name;
|
||||||
for( unsigned int i = 0; i < ztest_args.size(); ++i )
|
for( unsigned i = 0; i < ztest_args.size(); ++i )
|
||||||
argv[i+1] = ztest_args[i];
|
argv[i+1] = ztest_args[i];
|
||||||
argv[ztest_args.size()+1] = "-t";
|
argv[ztest_args.size()+1] = "-t";
|
||||||
argv[ztest_args.size()+2] = 0;
|
argv[ztest_args.size()+2] = 0;
|
||||||
execvp( argv[0], (char **)argv );
|
execvp( argv[0], (char **)argv );
|
||||||
}
|
}
|
||||||
show_exec_error( file_type.c_str() );
|
show_exec_error( decompressor_name );
|
||||||
_exit( 1 );
|
_exit( 1 );
|
||||||
}
|
}
|
||||||
// parent
|
// parent
|
||||||
if( pid < 0 )
|
if( pid < 0 )
|
||||||
{ show_fork_error( file_type.c_str() ); return 1; }
|
{ show_fork_error( decompressor_name ); return 1; }
|
||||||
|
|
||||||
const pid_t pid2 = fork();
|
const pid_t pid2 = fork();
|
||||||
if( pid2 == 0 ) // child2 (decompressor feeder)
|
if( pid2 == 0 ) // child2 (decompressor feeder)
|
||||||
|
@ -82,40 +89,43 @@ int ztest_stdin( const int infd,
|
||||||
{ show_fork_error( "decompressor feeder" ); return 1; }
|
{ show_fork_error( "decompressor feeder" ); return 1; }
|
||||||
|
|
||||||
close( fda[0] ); close( fda[1] );
|
close( fda[0] ); close( fda[1] );
|
||||||
int retval = wait_for_child( pid, file_type.c_str(), 1 );
|
int retval = wait_for_child( pid, decompressor_name, 1 );
|
||||||
if( retval == 0 && wait_for_child( pid2, "decompressor feeder" ) != 0 )
|
if( retval == 0 && wait_for_child( pid2, "decompressor feeder" ) != 0 )
|
||||||
retval = 1;
|
retval = 1;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ztest_file( const int infd, const std::string & input_filename,
|
int ztest_file( const int infd, const int format_type,
|
||||||
|
const std::string & input_filename,
|
||||||
const std::vector< const char * > & ztest_args )
|
const std::vector< const char * > & ztest_args )
|
||||||
{
|
{
|
||||||
std::string file_type;
|
const uint8_t * magic_data = 0;
|
||||||
const uint8_t * magic_data;
|
|
||||||
int magic_size = 0;
|
int magic_size = 0;
|
||||||
if( !test_format( infd, file_type, &magic_data, &magic_size ) )
|
const char * const decompressor_name = ( format_type >= 0 ) ?
|
||||||
return 0; // ignored
|
decompressor_names[format_type] :
|
||||||
|
test_format( infd, &magic_data, &magic_size );
|
||||||
|
if( !decompressor_name )
|
||||||
|
return 0; // skip this file
|
||||||
const pid_t pid = fork();
|
const pid_t pid = fork();
|
||||||
|
|
||||||
if( pid == 0 ) // child (decompressor)
|
if( pid == 0 ) // child (decompressor)
|
||||||
{
|
{
|
||||||
const char ** const argv = new const char *[ztest_args.size()+5];
|
const char ** const argv = new const char *[ztest_args.size()+5];
|
||||||
argv[0] = file_type.c_str();
|
argv[0] = decompressor_name;
|
||||||
for( unsigned int i = 0; i < ztest_args.size(); ++i )
|
for( unsigned i = 0; i < ztest_args.size(); ++i )
|
||||||
argv[i+1] = ztest_args[i];
|
argv[i+1] = ztest_args[i];
|
||||||
argv[ztest_args.size()+1] = "-t";
|
argv[ztest_args.size()+1] = "-t";
|
||||||
argv[ztest_args.size()+2] = "--";
|
argv[ztest_args.size()+2] = "--";
|
||||||
argv[ztest_args.size()+3] = input_filename.c_str();
|
argv[ztest_args.size()+3] = input_filename.c_str();
|
||||||
argv[ztest_args.size()+4] = 0;
|
argv[ztest_args.size()+4] = 0;
|
||||||
execvp( argv[0], (char **)argv );
|
execvp( argv[0], (char **)argv );
|
||||||
show_exec_error( file_type.c_str() );
|
show_exec_error( decompressor_name );
|
||||||
_exit( 1 );
|
_exit( 1 );
|
||||||
}
|
}
|
||||||
// parent
|
// parent
|
||||||
if( pid < 0 )
|
if( pid < 0 )
|
||||||
{ show_fork_error( file_type.c_str() ); return 1; }
|
{ show_fork_error( decompressor_name ); return 1; }
|
||||||
|
|
||||||
return wait_for_child( pid, file_type.c_str(), 1 );
|
return wait_for_child( pid, decompressor_name, 1 );
|
||||||
}
|
}
|
||||||
|
|
149
zutils.cc
149
zutils.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Zutils - Utilities dealing with compressed files
|
/* Zutils - Utilities dealing with compressed files
|
||||||
Copyright (C) 2009, 2010, 2011 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,10 +35,20 @@ const char * util_name = program_name;
|
||||||
int verbosity = 0;
|
int verbosity = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int get_format_type( const std::string & arg )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < num_formats; ++i )
|
||||||
|
if( arg == format_names[i] )
|
||||||
|
return i;
|
||||||
|
show_error( "Bad argument for '--format' option." );
|
||||||
|
std::exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns the number of bytes really read.
|
// Returns the number of bytes really read.
|
||||||
// If (returned value < size) and (errno == 0), means EOF was reached.
|
// If (returned value < size) and (errno == 0), means EOF was reached.
|
||||||
//
|
//
|
||||||
int readblock( const int fd, uint8_t * const buf, const int size ) throw()
|
int readblock( const int fd, uint8_t * const buf, const int size )
|
||||||
{
|
{
|
||||||
int rest = size;
|
int rest = size;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -47,7 +57,7 @@ int readblock( const int fd, uint8_t * const buf, const int size ) throw()
|
||||||
errno = 0;
|
errno = 0;
|
||||||
const int n = read( fd, buf + size - rest, rest );
|
const int n = read( fd, buf + size - rest, rest );
|
||||||
if( n > 0 ) rest -= n;
|
if( n > 0 ) rest -= n;
|
||||||
else if( n == 0 ) break;
|
else if( n == 0 ) break; // EOF
|
||||||
else if( errno != EINTR && errno != EAGAIN ) break;
|
else if( errno != EINTR && errno != EAGAIN ) break;
|
||||||
}
|
}
|
||||||
return ( rest > 0 ) ? size - rest : size;
|
return ( rest > 0 ) ? size - rest : size;
|
||||||
|
@ -57,7 +67,7 @@ int readblock( const int fd, uint8_t * const buf, const int size ) throw()
|
||||||
// Returns the number of bytes really written.
|
// Returns the number of bytes really written.
|
||||||
// If (returned value < size), it is always an error.
|
// If (returned value < size), it is always an error.
|
||||||
//
|
//
|
||||||
int writeblock( const int fd, const uint8_t * const buf, const int size ) throw()
|
int writeblock( const int fd, const uint8_t * const buf, const int size )
|
||||||
{
|
{
|
||||||
int rest = size;
|
int rest = size;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -66,7 +76,7 @@ int writeblock( const int fd, const uint8_t * const buf, const int size ) throw(
|
||||||
errno = 0;
|
errno = 0;
|
||||||
const int n = write( fd, buf + size - rest, rest );
|
const int n = write( fd, buf + size - rest, rest );
|
||||||
if( n > 0 ) rest -= n;
|
if( n > 0 ) rest -= n;
|
||||||
else if( errno && errno != EINTR && errno != EAGAIN ) break;
|
else if( n < 0 && errno != EINTR && errno != EAGAIN ) break;
|
||||||
}
|
}
|
||||||
return ( rest > 0 ) ? size - rest : size;
|
return ( rest > 0 ) ? size - rest : size;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +85,7 @@ int writeblock( const int fd, const uint8_t * const buf, const int size ) throw(
|
||||||
bool feed_data( const int infd, const int outfd,
|
bool feed_data( const int infd, const int outfd,
|
||||||
const uint8_t * magic_data, const int magic_size )
|
const uint8_t * magic_data, const int magic_size )
|
||||||
{
|
{
|
||||||
if( writeblock( outfd, magic_data, magic_size ) != magic_size )
|
if( magic_size && writeblock( outfd, magic_data, magic_size ) != magic_size )
|
||||||
{ show_error( "Write error", errno ); return false; }
|
{ show_error( "Write error", errno ); return false; }
|
||||||
enum { buffer_size = 4096 };
|
enum { buffer_size = 4096 };
|
||||||
uint8_t buffer[buffer_size];
|
uint8_t buffer[buffer_size];
|
||||||
|
@ -92,15 +102,16 @@ bool feed_data( const int infd, const int outfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool set_data_feeder( int * const infdp, pid_t * const pidp )
|
bool set_data_feeder( int * const infdp, pid_t * const pidp,
|
||||||
|
const int format_type )
|
||||||
{
|
{
|
||||||
std::string file_type;
|
const uint8_t * magic_data = 0;
|
||||||
const uint8_t * magic_data;
|
int magic_size = 0;
|
||||||
int magic_size;
|
const char * const decompressor_name = ( format_type >= 0 ) ?
|
||||||
const bool compressed =
|
decompressor_names[format_type] :
|
||||||
test_format( *infdp, file_type, &magic_data, &magic_size );
|
test_format( *infdp, &magic_data, &magic_size );
|
||||||
|
|
||||||
if( compressed ) // compressed with `file_type'
|
if( decompressor_name ) // compressed
|
||||||
{
|
{
|
||||||
int fda[2]; // pipe from feeder
|
int fda[2]; // pipe from feeder
|
||||||
int fda2[2]; // pipe from decompressor
|
int fda2[2]; // pipe from decompressor
|
||||||
|
@ -118,12 +129,13 @@ bool set_data_feeder( int * const infdp, pid_t * const pidp )
|
||||||
dup2( fda2[1], STDOUT_FILENO ) >= 0 &&
|
dup2( fda2[1], STDOUT_FILENO ) >= 0 &&
|
||||||
close( fda[0] ) == 0 && close( fda[1] ) == 0 &&
|
close( fda[0] ) == 0 && close( fda[1] ) == 0 &&
|
||||||
close( fda2[0] ) == 0 && close( fda2[1] ) == 0 )
|
close( fda2[0] ) == 0 && close( fda2[1] ) == 0 )
|
||||||
execlp( file_type.c_str(), file_type.c_str(), "-cdfq", (char *)0 );
|
execlp( decompressor_name, decompressor_name,
|
||||||
show_exec_error( file_type.c_str() );
|
(verbosity >= 0) ? "-d" : "-dq", (char *)0 );
|
||||||
|
show_exec_error( decompressor_name );
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
}
|
}
|
||||||
if( pid2 < 0 )
|
if( pid2 < 0 )
|
||||||
{ show_fork_error( file_type.c_str() ); _exit( 2 ); }
|
{ show_fork_error( decompressor_name ); _exit( 2 ); }
|
||||||
|
|
||||||
if( close( fda[0] ) != 0 ||
|
if( close( fda[0] ) != 0 ||
|
||||||
close( fda2[0] ) != 0 || close( fda2[1] ) != 0 ||
|
close( fda2[0] ) != 0 || close( fda2[1] ) != 0 ||
|
||||||
|
@ -131,7 +143,7 @@ bool set_data_feeder( int * const infdp, pid_t * const pidp )
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
if( close( fda[1] ) != 0 )
|
if( close( fda[1] ) != 0 )
|
||||||
{ show_close_error( "decompressor feeder" ); _exit( 2 ); }
|
{ show_close_error( "decompressor feeder" ); _exit( 2 ); }
|
||||||
_exit( wait_for_child( pid2, file_type.c_str() ) );
|
_exit( wait_for_child( pid2, decompressor_name ) );
|
||||||
}
|
}
|
||||||
// parent
|
// parent
|
||||||
close( fda[0] ); close( fda[1] ); close( fda2[1] );
|
close( fda[0] ); close( fda[1] ); close( fda2[1] );
|
||||||
|
@ -166,28 +178,27 @@ bool set_data_feeder( int * const infdp, pid_t * const pidp )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_help_addr() throw()
|
void show_help_addr()
|
||||||
{
|
{
|
||||||
std::printf( "\nReport bugs to zutils-bug@nongnu.org\n" );
|
std::printf( "\nReport bugs to zutils-bug@nongnu.org\n"
|
||||||
std::printf( "Zutils home page: http://www.nongnu.org/zutils/zutils.html\n" );
|
"Zutils home page: http://www.nongnu.org/zutils/zutils.html\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_version( const char * const Util_name ) throw()
|
void show_version( const char * const Util_name )
|
||||||
{
|
{
|
||||||
if( !Util_name || !*Util_name )
|
if( !Util_name || !*Util_name )
|
||||||
std::printf( "%s %s\n", Program_name, PROGVERSION );
|
std::printf( "%s %s\n", Program_name, PROGVERSION );
|
||||||
else
|
else
|
||||||
std::printf( "%s (%s) %s\n", Util_name, program_name, PROGVERSION );
|
std::printf( "%s (%s) %s\n", Util_name, program_name, PROGVERSION );
|
||||||
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
||||||
std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n" );
|
std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
|
||||||
std::printf( "This is free software: you are free to change and redistribute it.\n" );
|
"This is free software: you are free to change and redistribute it.\n"
|
||||||
std::printf( "There is NO WARRANTY, to the extent permitted by law.\n" );
|
"There is NO WARRANTY, to the extent permitted by law.\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_error( const char * const msg, const int errcode,
|
void show_error( const char * const msg, const int errcode, const bool help )
|
||||||
const bool help ) throw()
|
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
{
|
{
|
||||||
|
@ -198,22 +209,22 @@ void show_error( const char * const msg, const int errcode,
|
||||||
std::fprintf( stderr, ": %s", std::strerror( errcode ) );
|
std::fprintf( stderr, ": %s", std::strerror( errcode ) );
|
||||||
std::fprintf( stderr, "\n" );
|
std::fprintf( stderr, "\n" );
|
||||||
}
|
}
|
||||||
if( help && invocation_name && invocation_name[0] )
|
if( help )
|
||||||
std::fprintf( stderr, "Try `%s --help' for more information.\n",
|
std::fprintf( stderr, "Try '%s --help' for more information.\n",
|
||||||
invocation_name );
|
invocation_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_error2( const char * const msg, const char * const name ) throw()
|
void show_error2( const char * const msg, const char * const name )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: %s `%s': %s.\n",
|
std::fprintf( stderr, "%s: %s '%s': %s.\n",
|
||||||
util_name, msg, name, std::strerror( errno ) );
|
util_name, msg, name, std::strerror( errno ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_close_error( const char * const prog_name ) throw()
|
void show_close_error( const char * const prog_name )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't close output of %s: %s.\n",
|
std::fprintf( stderr, "%s: Can't close output of %s: %s.\n",
|
||||||
|
@ -221,18 +232,18 @@ void show_close_error( const char * const prog_name ) throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_exec_error( const char * const prog_name ) throw()
|
void show_exec_error( const char * const prog_name )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't exec `%s': %s.\n",
|
std::fprintf( stderr, "%s: Can't exec '%s': %s.\n",
|
||||||
util_name, prog_name, std::strerror( errno ) );
|
util_name, prog_name, std::strerror( errno ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_fork_error( const char * const prog_name ) throw()
|
void show_fork_error( const char * const prog_name )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't fork `%s': %s.\n",
|
std::fprintf( stderr, "%s: Can't fork '%s': %s.\n",
|
||||||
util_name, prog_name, std::strerror( errno ) );
|
util_name, prog_name, std::strerror( errno ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,21 +256,13 @@ void internal_error( const char * const msg )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned char xdigit( const int value ) throw()
|
const char * test_format( const int infd,
|
||||||
{
|
const uint8_t ** const magic_datap,
|
||||||
if( value >= 0 && value <= 9 ) return '0' + value;
|
int * const magic_sizep )
|
||||||
if( value >= 10 && value <= 15 ) return 'A' + ( value - 10 );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool test_format( const int infd, std::string & file_type,
|
|
||||||
const uint8_t ** const magic_datap, int * const magic_sizep )
|
|
||||||
{
|
{
|
||||||
enum { buf_size = 5 };
|
enum { buf_size = 5 };
|
||||||
static uint8_t buf[buf_size];
|
static uint8_t buf[buf_size];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
file_type.clear();
|
|
||||||
if( readblock( infd, buf, 1 ) == 1 )
|
if( readblock( infd, buf, 1 ) == 1 )
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
@ -267,22 +270,22 @@ bool test_format( const int infd, std::string & file_type,
|
||||||
{
|
{
|
||||||
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == bzip2_magic[1] &&
|
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == bzip2_magic[1] &&
|
||||||
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == bzip2_magic[2] )
|
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == bzip2_magic[2] )
|
||||||
{ file_type = "bzip2";
|
{ *magic_datap = bzip2_magic; *magic_sizep = bzip2_magic_size;
|
||||||
*magic_datap = bzip2_magic; *magic_sizep = bzip2_magic_size; }
|
return decompressor_names[fmt_bz2]; }
|
||||||
}
|
}
|
||||||
else if( buf[0] == gzip_magic[0] )
|
else if( buf[0] == gzip_magic[0] )
|
||||||
{
|
{
|
||||||
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == gzip_magic[1] )
|
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == gzip_magic[1] )
|
||||||
{ file_type = "gzip";
|
{ *magic_datap = gzip_magic; *magic_sizep = gzip_magic_size;
|
||||||
*magic_datap = gzip_magic; *magic_sizep = gzip_magic_size; }
|
return decompressor_names[fmt_gz]; }
|
||||||
}
|
}
|
||||||
else if( buf[0] == lzip_magic[0] )
|
else if( buf[0] == lzip_magic[0] )
|
||||||
{
|
{
|
||||||
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[1] &&
|
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[1] &&
|
||||||
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[2] &&
|
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[2] &&
|
||||||
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[3] )
|
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[3] )
|
||||||
{ file_type = "lzip";
|
{ *magic_datap = lzip_magic; *magic_sizep = lzip_magic_size;
|
||||||
*magic_datap = lzip_magic; *magic_sizep = lzip_magic_size; }
|
return decompressor_names[fmt_lz]; }
|
||||||
}
|
}
|
||||||
else if( buf[0] == xz_magic[0] )
|
else if( buf[0] == xz_magic[0] )
|
||||||
{
|
{
|
||||||
|
@ -290,18 +293,12 @@ bool test_format( const int infd, std::string & file_type,
|
||||||
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[2] &&
|
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[2] &&
|
||||||
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[3] &&
|
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[3] &&
|
||||||
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[4] )
|
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[4] )
|
||||||
{ file_type = "xz";
|
{ *magic_datap = xz_magic; *magic_sizep = xz_magic_size;
|
||||||
*magic_datap = xz_magic; *magic_sizep = xz_magic_size; }
|
return decompressor_names[fmt_xz]; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( file_type.size() ) return true;
|
|
||||||
for( int j = 0; j < i; ++j )
|
|
||||||
{
|
|
||||||
file_type += xdigit( buf[j] >> 4 );
|
|
||||||
file_type += xdigit( buf[j] & 0x0F );
|
|
||||||
}
|
|
||||||
*magic_datap = buf; *magic_sizep = i;
|
*magic_datap = buf; *magic_sizep = i;
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -314,12 +311,40 @@ int wait_for_child( const pid_t pid, const char * const name,
|
||||||
if( errno != EINTR )
|
if( errno != EINTR )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Error waiting termination of `%s': %s.\n",
|
std::fprintf( stderr, "%s: Error waiting termination of '%s': %s.\n",
|
||||||
util_name, name, std::strerror( errno ) );
|
util_name, name, std::strerror( errno ) );
|
||||||
_exit( eretval );
|
_exit( eretval );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( WIFEXITED( status ) )
|
||||||
|
{
|
||||||
|
const int tmp = WEXITSTATUS( status );
|
||||||
|
if( eretval == 1 && tmp == 1 ) return 2; // for ztest
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
return eretval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int child_status( const pid_t pid, const char * const name,
|
||||||
|
const int eretval )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
const int tmp = waitpid( pid, &status, WNOHANG );
|
||||||
|
if( tmp == -1 && errno != EINTR )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: Error checking status of '%s': %s.\n",
|
||||||
|
util_name, name, std::strerror( errno ) );
|
||||||
|
_exit( eretval );
|
||||||
|
}
|
||||||
|
if( tmp == 0 ) return -1; // child not terminated
|
||||||
|
if( tmp == pid ) break; // child terminated
|
||||||
|
}
|
||||||
|
|
||||||
if( WIFEXITED( status ) ) return WEXITSTATUS( status );
|
if( WIFEXITED( status ) ) return WEXITSTATUS( status );
|
||||||
return eretval;
|
return eretval;
|
||||||
}
|
}
|
||||||
|
|
70
zutils.h
70
zutils.h
|
@ -1,5 +1,5 @@
|
||||||
/* Zutils - Utilities dealing with compressed files
|
/* Zutils - Utilities dealing with compressed files
|
||||||
Copyright (C) 2009, 2010, 2011 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,42 +17,66 @@
|
||||||
|
|
||||||
const char * const Program_name = "Zutils";
|
const char * const Program_name = "Zutils";
|
||||||
const char * const program_name = "zutils";
|
const char * const program_name = "zutils";
|
||||||
const char * const program_year = "2011";
|
const char * const program_year = "2013";
|
||||||
extern const char * invocation_name;
|
extern const char * invocation_name;
|
||||||
extern const char * util_name;
|
extern const char * util_name;
|
||||||
|
|
||||||
extern int verbosity;
|
extern int verbosity;
|
||||||
|
|
||||||
const char * const simple_extensions[] = { ".gz", ".lz", ".bz2", ".xz", 0 };
|
enum { fmt_bz2, fmt_gz, fmt_lz, fmt_xz, num_formats };
|
||||||
|
const char * const format_names[num_formats] = { "bz2", "gz", "lz", "xz" };
|
||||||
|
const char * const simple_extensions[num_formats] =
|
||||||
|
{ ".bz2", ".gz", ".lz", ".xz" };
|
||||||
|
const char * const decompressor_names[num_formats] =
|
||||||
|
{ "bzip2", "gzip", "lzip", "xz" };
|
||||||
|
const int8_t format_order[num_formats] =
|
||||||
|
{ fmt_gz, fmt_lz, fmt_bz2, fmt_xz }; // search order
|
||||||
|
|
||||||
enum { bzip2_magic_size = 3 };
|
// first magic byte must be different among formats
|
||||||
enum { gzip_magic_size = 2 };
|
enum { bzip2_magic_size = 3,
|
||||||
enum { lzip_magic_size = 4 };
|
gzip_magic_size = 2,
|
||||||
enum { xz_magic_size = 5 };
|
lzip_magic_size = 4,
|
||||||
const uint8_t bzip2_magic[bzip2_magic_size] = { 'B', 'Z', 'h' };
|
xz_magic_size = 5 };
|
||||||
const uint8_t gzip_magic[ gzip_magic_size] = { '\x1F', '\x8B' };
|
const uint8_t bzip2_magic[bzip2_magic_size] =
|
||||||
const uint8_t lzip_magic[ lzip_magic_size] = { 'L', 'Z', 'I', 'P' };
|
{ 0x42, 0x5A, 0x68 }; // "BZh"
|
||||||
const uint8_t xz_magic[ xz_magic_size] = { '\xFD', '7', 'z', 'X', 'Z' };
|
const uint8_t gzip_magic[gzip_magic_size] =
|
||||||
|
{ 0x1F, 0x8B };
|
||||||
|
const uint8_t lzip_magic[lzip_magic_size] =
|
||||||
|
{ 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP"
|
||||||
|
const uint8_t xz_magic[xz_magic_size] =
|
||||||
|
{ 0xFD, 0x37, 0x7A, 0x58, 0x5A }; // 0xFD, "7zXZ"
|
||||||
|
|
||||||
|
|
||||||
int readblock( const int fd, uint8_t * const buf, const int size ) throw();
|
int get_format_type( const std::string & arg );
|
||||||
int writeblock( const int fd, const uint8_t * const buf, const int size ) throw();
|
|
||||||
|
int readblock( const int fd, uint8_t * const buf, const int size );
|
||||||
|
int writeblock( const int fd, const uint8_t * const buf, const int size );
|
||||||
bool feed_data( const int infd, const int outfd,
|
bool feed_data( const int infd, const int outfd,
|
||||||
const uint8_t * magic_data, const int magic_size );
|
const uint8_t * magic_data, const int magic_size );
|
||||||
bool set_data_feeder( int * const infdp, pid_t * const pidp );
|
bool set_data_feeder( int * const infdp, pid_t * const pidp,
|
||||||
|
const int format_type );
|
||||||
|
|
||||||
void show_help_addr() throw();
|
void show_help_addr();
|
||||||
void show_version( const char * const Util_name = 0 ) throw();
|
void show_version( const char * const Util_name = 0 );
|
||||||
void show_error( const char * const msg, const int errcode = 0,
|
void show_error( const char * const msg, const int errcode = 0,
|
||||||
const bool help = false ) throw();
|
const bool help = false );
|
||||||
void show_error2( const char * const msg, const char * const name ) throw();
|
void show_error2( const char * const msg, const char * const name );
|
||||||
void show_close_error( const char * const prog_name ) throw();
|
void show_close_error( const char * const prog_name );
|
||||||
void show_exec_error( const char * const prog_name ) throw();
|
void show_exec_error( const char * const prog_name );
|
||||||
void show_fork_error( const char * const prog_name ) throw();
|
void show_fork_error( const char * const prog_name );
|
||||||
void internal_error( const char * const msg );
|
void internal_error( const char * const msg );
|
||||||
|
|
||||||
bool test_format( const int infd, std::string & file_type,
|
const char * test_format( const int infd,
|
||||||
const uint8_t ** magic_data, int * magic_sizep );
|
const uint8_t ** const magic_datap,
|
||||||
|
int * const magic_sizep );
|
||||||
|
|
||||||
|
// Returns exit status of child process 'pid', or 'eretval' in case of error.
|
||||||
|
//
|
||||||
int wait_for_child( const pid_t pid, const char * const name,
|
int wait_for_child( const pid_t pid, const char * const name,
|
||||||
const int eretval = 2 );
|
const int eretval = 2 );
|
||||||
|
|
||||||
|
// Returns -1 if child not terminated, 'eretval' in case of error, or
|
||||||
|
// exit status of child process 'pid'.
|
||||||
|
//
|
||||||
|
int child_status( const pid_t pid, const char * const name,
|
||||||
|
const int eretval = 2 );
|
||||||
|
|
Loading…
Add table
Reference in a new issue