diff options
author | Daniel Baumann <mail@daniel-baumann.ch> | 2015-11-08 04:40:35 +0000 |
---|---|---|
committer | Daniel Baumann <mail@daniel-baumann.ch> | 2015-11-08 04:40:35 +0000 |
commit | f7deb94049481143ef12eab590840d39aecedc14 (patch) | |
tree | 9ff4090b78d8343fd073ba1ea32068bb0d07caa6 | |
parent | Adding debian version 1.3-4. (diff) | |
download | zutils-f7deb94049481143ef12eab590840d39aecedc14.tar.xz zutils-f7deb94049481143ef12eab590840d39aecedc14.zip |
Merging upstream version 1.4~pre2.
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
Diffstat (limited to '')
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | INSTALL | 8 | ||||
-rw-r--r-- | Makefile.in | 69 | ||||
-rw-r--r-- | NEWS | 18 | ||||
-rw-r--r-- | README | 14 | ||||
-rw-r--r-- | arg_parser.cc | 32 | ||||
-rw-r--r-- | arg_parser.h | 32 | ||||
-rwxr-xr-x | configure | 6 | ||||
-rw-r--r-- | doc/zcat.1 | 11 | ||||
-rw-r--r-- | doc/zcmp.1 | 13 | ||||
-rw-r--r-- | doc/zdiff.1 | 13 | ||||
-rw-r--r-- | doc/zgrep.1 | 13 | ||||
-rw-r--r-- | doc/ztest.1 | 11 | ||||
-rw-r--r-- | doc/zupdate.1 | 7 | ||||
-rw-r--r-- | doc/zutils.info | 158 | ||||
-rw-r--r-- | doc/zutils.texi | 138 | ||||
-rw-r--r-- | rc.cc | 153 | ||||
-rw-r--r-- | rc.h | 11 | ||||
-rw-r--r-- | recursive.cc | 11 | ||||
-rwxr-xr-x | testsuite/check.sh | 141 | ||||
-rw-r--r-- | zcat.cc | 55 | ||||
-rw-r--r-- | zcatgrep.cc | 57 | ||||
-rw-r--r-- | zcmp.cc | 47 | ||||
-rw-r--r-- | zcmpdiff.cc | 46 | ||||
-rw-r--r-- | zdiff.cc | 91 | ||||
-rw-r--r-- | zgrep.cc | 97 | ||||
-rw-r--r-- | ztest.cc | 17 | ||||
-rw-r--r-- | zupdate.cc | 55 | ||||
-rw-r--r-- | zutils.cc | 12 | ||||
-rw-r--r-- | zutils.h | 4 |
30 files changed, 802 insertions, 552 deletions
@@ -1,3 +1,15 @@ +2015-04-30 Antonio Diaz Diaz <antonio@gnu.org> + + * Version 1.4-pre2 released. + * zgrep.cc (main): Pass '-e' to grep if pattern begins with '-'. + +2015-04-27 Antonio Diaz Diaz <antonio@gnu.org> + + * Version 1.4-pre1 released. + * Option '--format' has been renamed to '-O, --force-format'. + * Added new option '-M, --format=<list>' to all utilities. + * Makefile.in: Added new targets 'install*-compress'. + 2014-08-30 Antonio Diaz Diaz <antonio@gnu.org> * Version 1.3 released. @@ -110,7 +122,7 @@ * Version 0.1 released. -Copyright (C) 2009-2014 Antonio Diaz Diaz. +Copyright (C) 2009-2015 Antonio Diaz Diaz. 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 @@ -1,7 +1,7 @@ Requirements ------------ You will need a C++ compiler. -I use gcc 4.9.1 and 3.3.6, but the code should compile with any +I use gcc 4.9.1 and 4.1.2, but the code should compile with any standards compliant compiler. Gcc is available at http://gcc.gnu.org. @@ -44,6 +44,10 @@ the main archive. 5. Type 'make install' to install the programs and any data files and documentation. + Or type 'make install-compress', which additionally compresses the + info manual and the man pages after installation. (Installing + compressed docs may become the default in the future). + You can install only the programs, the info manual or the man pages by typing 'make install-bin', 'make install-info' or 'make install-man' respectively. @@ -66,7 +70,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2009-2014 Antonio Diaz Diaz. +Copyright (C) 2009-2015 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/Makefile.in b/Makefile.in index f445454..0b7a4d0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,20 +19,22 @@ programs = zcat zcmp zdiff zgrep ztest zupdate scripts = zegrep zfgrep -.PHONY : all install install-bin install-info install-man install-strip \ +.PHONY : all install install-bin install-info install-man \ + install-strip install-compress install-strip-compress \ + install-bin-strip install-info-compress install-man-compress \ uninstall uninstall-bin uninstall-info uninstall-man \ doc info man check dist clean distclean all : $(programs) $(scripts) zcat : $(zcat_objs) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(zcat_objs) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(zcat_objs) zcmp : $(zcmp_objs) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(zcmp_objs) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(zcmp_objs) zdiff : $(zdiff_objs) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(zdiff_objs) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(zdiff_objs) zegrep : zegrep.in cat $(VPATH)/zegrep.in > $@ @@ -43,34 +45,34 @@ zfgrep : zfgrep.in chmod a+x zfgrep zgrep : $(zgrep_objs) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(zgrep_objs) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(zgrep_objs) ztest : $(ztest_objs) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(ztest_objs) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(ztest_objs) zupdate : $(zupdate_objs) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(zupdate_objs) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(zupdate_objs) rc.o : rc.cc - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -DPROGVERSION=\"$(pkgversion)\" -DSYSCONFDIR=\"$(sysconfdir)\" -c -o $@ $< + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -DSYSCONFDIR=\"$(sysconfdir)\" -c -o $@ $< zdiff.o : zdiff.cc - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -DDIFF=\"$(DIFF)\" -c -o $@ $< + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DDIFF=\"$(DIFF)\" -c -o $@ $< zgrep.o : zgrep.cc - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -DGREP=\"$(GREP)\" -c -o $@ $< + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DGREP=\"$(GREP)\" -c -o $@ $< %.o : %.cc - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< $(objs) : Makefile $(scripts) : Makefile arg_parser.o : arg_parser.h rc.o : arg_parser.h rc.h -zcat.o : arg_parser.h rc.h zutils.h recursive.cc +zcat.o : arg_parser.h rc.h zutils.h recursive.cc zcatgrep.cc zcmp.o : arg_parser.h rc.h zutils.h zcmpdiff.cc zdiff.o : arg_parser.h rc.h zutils.h zcmpdiff.cc -zgrep.o : arg_parser.h rc.h zutils.h recursive.cc +zgrep.o : arg_parser.h rc.h zutils.h recursive.cc zcatgrep.cc ztest.o : arg_parser.h rc.h zutils.h recursive.cc zupdate.o : arg_parser.h rc.h recursive.cc zutils.o : rc.h zutils.h @@ -117,6 +119,9 @@ check : all @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion) install : install-bin install-info install-man +install-strip : install-bin-strip install-info install-man +install-compress : install-bin install-info-compress install-man-compress +install-strip-compress : install-bin-strip install-info-compress install-man-compress install-bin : all if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi @@ -133,13 +138,26 @@ install-bin : all $(INSTALL_DATA) $(VPATH)/$(pkgname)rc "$(DESTDIR)$(sysconfdir)/$(pkgname)rc" ; \ fi +install-bin-strip : all + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install-bin + install-info : if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi + -rm -f "$(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-compress : install-info + lzip -v -9 "$(DESTDIR)$(infodir)/$(pkgname).info" + install-man : if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi + -rm -f "$(DESTDIR)$(mandir)/man1/zcat.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zcmp.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zdiff.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zgrep.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/ztest.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zupdate.1"* $(INSTALL_DATA) $(VPATH)/doc/zcat.1 "$(DESTDIR)$(mandir)/man1/zcat.1" $(INSTALL_DATA) $(VPATH)/doc/zcmp.1 "$(DESTDIR)$(mandir)/man1/zcmp.1" $(INSTALL_DATA) $(VPATH)/doc/zdiff.1 "$(DESTDIR)$(mandir)/man1/zdiff.1" @@ -147,10 +165,15 @@ install-man : $(INSTALL_DATA) $(VPATH)/doc/ztest.1 "$(DESTDIR)$(mandir)/man1/ztest.1" $(INSTALL_DATA) $(VPATH)/doc/zupdate.1 "$(DESTDIR)$(mandir)/man1/zupdate.1" -install-strip : all - $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install +install-man-compress : install-man + lzip -v -9 "$(DESTDIR)$(mandir)/man1/zcat.1" + lzip -v -9 "$(DESTDIR)$(mandir)/man1/zcmp.1" + lzip -v -9 "$(DESTDIR)$(mandir)/man1/zdiff.1" + lzip -v -9 "$(DESTDIR)$(mandir)/man1/zgrep.1" + lzip -v -9 "$(DESTDIR)$(mandir)/man1/ztest.1" + lzip -v -9 "$(DESTDIR)$(mandir)/man1/zupdate.1" -uninstall : uninstall-bin uninstall-info uninstall-man +uninstall : uninstall-man uninstall-info uninstall-bin uninstall-bin : -rm -f "$(DESTDIR)$(bindir)/zcat" @@ -165,15 +188,15 @@ uninstall-bin : uninstall-info : -install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" - -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info" + -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* uninstall-man : - -rm -f "$(DESTDIR)$(mandir)/man1/zcat.1" - -rm -f "$(DESTDIR)$(mandir)/man1/zcmp.1" - -rm -f "$(DESTDIR)$(mandir)/man1/zdiff.1" - -rm -f "$(DESTDIR)$(mandir)/man1/zgrep.1" - -rm -f "$(DESTDIR)$(mandir)/man1/ztest.1" - -rm -f "$(DESTDIR)$(mandir)/man1/zupdate.1" + -rm -f "$(DESTDIR)$(mandir)/man1/zcat.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zcmp.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zdiff.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zgrep.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/ztest.1"* + -rm -f "$(DESTDIR)$(mandir)/man1/zupdate.1"* dist : doc ln -sf $(VPATH) $(DISTNAME) @@ -1,12 +1,14 @@ -Changes in version 1.3: +Changes in version 1.4: -Two incomplete values of expected exit status producing sporadic -failures of the tests have been fixed. +The option "--format" has been renamed to "-O, --force-format". -It has been documented that the "--format" option does not verify the -format, allowing for example the processing of compress'd (.Z) files -with gzip. +Option "-M, --format=<list>" now excludes from automatic search the +formats not listed in the comma-separated <list>. This change introduces +a backward incompatibility with previous versions of zutils. -Minor fixes. +If the pattern begins with "-", zgrep now prepends "-e" before passing +it to grep. ('zgrep -- -pattern file' now works as expected). -The license has been changed to GPL version 2 or later. +The targets "install-compress", "install-strip-compress", +"install-info-compress" and "install-man-compress" have been added to +the Makefile. @@ -22,17 +22,21 @@ NOTE: Bzip2 and lzip provide well-defined values of exit status, which makes them safe to use with zutils. Gzip and xz may return ambiguous warning values, making them less reliable back ends for zutils. -FORMAT NOTE: If the "--format" option is given, the corresponding files -are passed to the decompressor without verifying their format, allowing -for example the processing of compress'd (.Z) files with gzip: -"zcmp --format=gz file.Z file.lz". +FORMAT NOTE: The "--format" option allows the processing of a subset of +formats in search and recursive modes: +"zgrep foo -r --format=bz2,lz somedir". + +FORMAT NOTE 2: If the "--force-format" option is given, the files are +passed to the corresponding decompressor without verifying their format, +allowing for example the processing of compress'd (.Z) files with gzip: +"zcmp --force-format=gz file.Z file.lz". LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never have been compressed. Decompressed is used to refer to data which has undergone the process of decompression. -Copyright (C) 2009-2014 Antonio Diaz Diaz. +Copyright (C) 2009-2015 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/arg_parser.cc b/arg_parser.cc index 74f9298..551264a 100644 --- a/arg_parser.cc +++ b/arg_parser.cc @@ -1,28 +1,20 @@ /* Arg_parser - POSIX/GNU command line argument parser. (C++ version) - Copyright (C) 2006-2014 Antonio Diaz Diaz. + Copyright (C) 2006-2015 Antonio Diaz Diaz. - 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 - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. + This library is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. This library 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 library. If not, see <http://www.gnu.org/licenses/>. - - As a special exception, you may use this file as part of a free - software library without restriction. Specifically, if other files - instantiate templates or use macros or inline functions from this - file, or you compile this file and link it with other files to - produce an executable, this file does not by itself cause the - resulting executable to be covered by the GNU General Public - License. This exception does not however invalidate any other - reasons why the executable file might be covered by the GNU General - Public License. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include <cstring> diff --git a/arg_parser.h b/arg_parser.h index d80c353..3dc85d0 100644 --- a/arg_parser.h +++ b/arg_parser.h @@ -1,28 +1,20 @@ /* Arg_parser - POSIX/GNU command line argument parser. (C++ version) - Copyright (C) 2006-2014 Antonio Diaz Diaz. + Copyright (C) 2006-2015 Antonio Diaz Diaz. - 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 - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. + This library is free software. Redistribution and use in source and + binary forms, with or without modification, are permitted provided + that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. This library 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 library. If not, see <http://www.gnu.org/licenses/>. - - As a special exception, you may use this file as part of a free - software library without restriction. Specifically, if other files - instantiate templates or use macros or inline functions from this - file, or you compile this file and link it with other files to - produce an executable, this file does not by itself cause the - resulting executable to be covered by the GNU General Public - License. This exception does not however invalidate any other - reasons why the executable file might be covered by the GNU General - Public License. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* Arg_parser reads the arguments in 'argv' and creates a number of @@ -1,12 +1,12 @@ #! /bin/sh # configure script for Zutils - Utilities dealing with compressed files -# Copyright (C) 2009-2014 Antonio Diaz Diaz. +# Copyright (C) 2009-2015 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. pkgname=zutils -pkgversion=1.3 +pkgversion=1.4-pre2 srctrigger=doc/${pkgname}.texi # clear some things potentially inherited from environment. @@ -177,7 +177,7 @@ echo "GREP = ${GREP}" rm -f Makefile cat > Makefile << EOF # Makefile for Zutils - Utilities dealing with compressed files -# Copyright (C) 2009-2014 Antonio Diaz Diaz. +# Copyright (C) 2009-2015 Antonio Diaz Diaz. # This file was generated automatically by configure. Do not edit. # # This Makefile is free software: you have unlimited permission @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH ZCAT "1" "August 2014" "zcat (zutils) 1.3" "User Commands" +.TH ZCAT "1" "April 2015" "zcat (zutils) 1.4-pre2" "User Commands" .SH NAME zcat \- decompress and concatenate files to standard output .SH SYNOPSIS @@ -38,8 +38,8 @@ equivalent to '\-vE' \fB\-E\fR, \fB\-\-show\-ends\fR display '$' at end of each line .TP -\fB\-\-format=\fR<fmt> -force given format (bz2, gz, lz, xz) +\fB\-M\fR, \fB\-\-format=\fR<list> +exclude formats not in <list> .TP \fB\-n\fR, \fB\-\-number\fR number all output lines @@ -47,6 +47,9 @@ number all output lines \fB\-N\fR, \fB\-\-no\-rcfile\fR don't read runtime configuration file .TP +\fB\-O\fR, \fB\-\-force\-format=\fR<fmt> +force given format (bz2, gz, lz, xz) +.TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages .TP @@ -84,7 +87,7 @@ Report bugs to zutils\-bug@nongnu.org .br Zutils home page: http://www.nongnu.org/zutils/zutils.html .SH COPYRIGHT -Copyright \(co 2014 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH ZCMP "1" "August 2014" "zcmp (zutils) 1.3" "User Commands" +.TH ZCMP "1" "April 2015" "zcmp (zutils) 1.4-pre2" "User Commands" .SH NAME zcmp \- decompress and compare two files byte by byte .SH SYNOPSIS @@ -39,21 +39,24 @@ output version information and exit \fB\-b\fR, \fB\-\-print\-bytes\fR print differing bytes .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>] ignore differences in the first <n> bytes .TP \fB\-l\fR, \fB\-\-list\fR list position, value of all differing bytes .TP +\fB\-M\fR, \fB\-\-format=\fR<list> +exclude formats not in <list> +.TP \fB\-n\fR, \fB\-\-bytes=\fR<n> compare at most <n> bytes .TP \fB\-N\fR, \fB\-\-no\-rcfile\fR don't read runtime configuration file .TP +\fB\-O\fR, \fB\-\-force\-format\fR=\fI\,[\/\fR<f1>][,<f2>] +force given formats (bz2, gz, lz, xz) +.TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages .TP @@ -82,7 +85,7 @@ Report bugs to zutils\-bug@nongnu.org .br Zutils home page: http://www.nongnu.org/zutils/zutils.html .SH COPYRIGHT -Copyright \(co 2014 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. diff --git a/doc/zdiff.1 b/doc/zdiff.1 index 5675471..f9dd2ca 100644 --- a/doc/zdiff.1 +++ b/doc/zdiff.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH ZDIFF "1" "August 2014" "zdiff (zutils) 1.3" "User Commands" +.TH ZDIFF "1" "April 2015" "zdiff (zutils) 1.4-pre2" "User Commands" .SH NAME zdiff \- decompress and compare two files line by line .SH SYNOPSIS @@ -57,15 +57,18 @@ try hard to find a smaller set of changes \fB\-E\fR, \fB\-\-ignore\-tab\-expansion\fR ignore changes due to tab expansion .TP -\fB\-\-format\fR=\fI\,[\/\fR<fmt1>][,<fmt2>] -force given formats (bz2, gz, lz, xz) -.TP \fB\-i\fR, \fB\-\-ignore\-case\fR ignore case differences in file contents .TP +\fB\-M\fR, \fB\-\-format=\fR<list> +exclude formats not in <list> +.TP \fB\-N\fR, \fB\-\-no\-rcfile\fR don't read runtime configuration file .TP +\fB\-O\fR, \fB\-\-force\-format\fR=\fI\,[\/\fR<f1>][,<f2>] +force given formats (bz2, gz, lz, xz) +.TP \fB\-p\fR, \fB\-\-show\-c\-function\fR show which C function each change is in .TP @@ -109,7 +112,7 @@ Report bugs to zutils\-bug@nongnu.org .br Zutils home page: http://www.nongnu.org/zutils/zutils.html .SH COPYRIGHT -Copyright \(co 2014 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. diff --git a/doc/zgrep.1 b/doc/zgrep.1 index 20574aa..e032217 100644 --- a/doc/zgrep.1 +++ b/doc/zgrep.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH ZGREP "1" "August 2014" "zgrep (zutils) 1.3" "User Commands" +.TH ZGREP "1" "April 2015" "zgrep (zutils) 1.4-pre2" "User Commands" .SH NAME zgrep \- search compressed files for a regular expression .SH SYNOPSIS @@ -57,9 +57,6 @@ obtain patterns from <file> \fB\-F\fR, \fB\-\-fixed\-strings\fR <pattern> is a set of newline\-separated strings .TP -\fB\-\-format=\fR<fmt> -force given format (bz2, gz, lz, xz) -.TP \fB\-h\fR, \fB\-\-no\-filename\fR suppress the prefixing filename on output .TP @@ -81,6 +78,9 @@ only print names of files containing no matches \fB\-m\fR, \fB\-\-max\-count=\fR<n> stop after <n> matches .TP +\fB\-M\fR, \fB\-\-format=\fR<list> +exclude formats not in <list> +.TP \fB\-n\fR, \fB\-\-line\-number\fR print the line number of each line .TP @@ -90,6 +90,9 @@ don't read runtime configuration file \fB\-o\fR, \fB\-\-only\-matching\fR show only the part of a line matching <pattern> .TP +\fB\-O\fR, \fB\-\-force\-format=\fR<fmt> +force given format (bz2, gz, lz, xz) +.TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages .TP @@ -127,7 +130,7 @@ Report bugs to zutils\-bug@nongnu.org .br Zutils home page: http://www.nongnu.org/zutils/zutils.html .SH COPYRIGHT -Copyright \(co 2014 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. diff --git a/doc/ztest.1 b/doc/ztest.1 index 66ddc70..8eeaf4d 100644 --- a/doc/ztest.1 +++ b/doc/ztest.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH ZTEST "1" "August 2014" "ztest (zutils) 1.3" "User Commands" +.TH ZTEST "1" "April 2015" "ztest (zutils) 1.4-pre2" "User Commands" .SH NAME ztest \- verify integrity of compressed files .SH SYNOPSIS @@ -27,12 +27,15 @@ display this help and exit \fB\-V\fR, \fB\-\-version\fR output version information and exit .TP -\fB\-\-format=\fR<fmt> -force given format (bz2, gz, lz, xz) +\fB\-M\fR, \fB\-\-format=\fR<list> +exclude formats not in <list> .TP \fB\-N\fR, \fB\-\-no\-rcfile\fR don't read runtime configuration file .TP +\fB\-O\fR, \fB\-\-force\-format=\fR<fmt> +force given format (bz2, gz, lz, xz) +.TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages .TP @@ -58,7 +61,7 @@ Report bugs to zutils\-bug@nongnu.org .br Zutils home page: http://www.nongnu.org/zutils/zutils.html .SH COPYRIGHT -Copyright \(co 2014 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. diff --git a/doc/zupdate.1 b/doc/zupdate.1 index 4f862f2..29ac253 100644 --- a/doc/zupdate.1 +++ b/doc/zupdate.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH ZUPDATE "1" "August 2014" "zupdate (zutils) 1.3" "User Commands" +.TH ZUPDATE "1" "April 2015" "zupdate (zutils) 1.4-pre2" "User Commands" .SH NAME zupdate \- recompress bzip2, gzip, xz files to lzip files .SH SYNOPSIS @@ -42,6 +42,9 @@ keep (don't delete) input files \fB\-l\fR, \fB\-\-lzip\-verbose\fR pass a \fB\-v\fR option to the lzip compressor .TP +\fB\-M\fR, \fB\-\-format=\fR<list> +exclude formats not in <list> +.TP \fB\-N\fR, \fB\-\-no\-rcfile\fR don't read runtime configuration file .TP @@ -73,7 +76,7 @@ Report bugs to zutils\-bug@nongnu.org .br Zutils home page: http://www.nongnu.org/zutils/zutils.html .SH COPYRIGHT -Copyright \(co 2014 Antonio Diaz Diaz. +Copyright \(co 2015 Antonio Diaz Diaz. License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. diff --git a/doc/zutils.info b/doc/zutils.info index ac3c7a5..83f07b7 100644 --- a/doc/zutils.info +++ b/doc/zutils.info @@ -12,12 +12,12 @@ File: zutils.info, Node: Top, Next: Introduction, Up: (dir) Zutils Manual ************* -This manual is for Zutils (version 1.3, 30 August 2014). +This manual is for Zutils (version 1.4-pre2, 30 April 2015). * Menu: * Introduction:: Purpose and features of zutils -* Common options:: Common options +* Common options:: Options common to all utilities * The zutilsrc file:: The zutils configuration file * Zcat:: Concatenating compressed files * Zcmp:: Comparing compressed files byte by byte @@ -29,7 +29,7 @@ This manual is for Zutils (version 1.3, 30 August 2014). * Concept index:: Index of concepts - Copyright (C) 2009-2014 Antonio Diaz Diaz. + Copyright (C) 2009-2015 Antonio Diaz Diaz. This manual is free documentation: you have unlimited permission to copy, distribute and modify it. @@ -61,12 +61,16 @@ similar to gzip's znew. NOTE: Bzip2 and lzip provide well-defined values of exit status, which makes them safe to use with zutils. Gzip and xz may return ambiguous warning values, making them less reliable back ends for -zutils. +zutils. *Note compressor-requirements::. - FORMAT NOTE: If the '--format' option is given, the corresponding -files are passed to the decompressor without verifying their format, + FORMAT NOTE: The "-format" option allows the processing of a subset +of formats in search and recursive modes: +'zgrep foo -r --format=bz2,lz somedir'. + + FORMAT NOTE 2: If the '--force-format' option is given, the files are +passed to the corresponding decompressor without verifying their format, allowing for example the processing of compress'd (.Z) files with gzip: -'zcmp --format=gz file.Z file.lz'. +'zcmp --force-format=gz file.Z file.lz'. LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never have been compressed. Decompressed is used to refer to data which @@ -107,6 +111,26 @@ described here. '--version' Print the version number on the standard output and exit. +'-M FORMAT_LIST' +'--format=FORMAT_LIST' + Exclude formats not listed in the comma-separated FORMAT_LIST. + Valid formats are 'bz2', 'gz', 'lz', 'xz' and 'un' for + 'uncompressed', meaning "any file name without a known extension". + This option excludes files based on extension, instead of format, + because it is more efficient. The exclusion only applies to names + generated automatically (for example when adding extensions to a + file name or when operating recursively on directories). Files + given in the command line are always processed. + + Each format in FORMAT_LIST enables file names with the following + extensions: + + bz2 enables .bz2 .tbz .tbz2 + gz enables .gz .tgz + lz enables .lz .tlz + xz enables .xz .txz + un enables any other file name + '-N' '--no-rcfile' Don't read the runtime configuration file 'zutilsrc'. @@ -116,9 +140,9 @@ described here. '--lz=COMMAND' '--xz=COMMAND' Set program (may include arguments) to be used as (de)compressor - for the given format. These options override the values set in - 'zutilsrc'. The compression program used must meet three - requirements: + for the given format. The mane of the program can't begin with + '-'. These options override the values set in 'zutilsrc'. The + compression program used must meet three requirements: 1. When called with the '-d' option, it must read compressed data from the standard input and produce decompressed data on @@ -197,16 +221,19 @@ Exit status is 0 if no errors occurred, non-zero otherwise. '--show-ends' 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' '--number' Number all output lines, starting with 1. The line count is unlimited. +'-O FORMAT' +'--force-format=FORMAT' + Force the given compression format. Valid values for FORMAT are + 'bz2', 'gz', 'lz' and 'xz'. If this option is used, the files are + passed to the corresponding decompressor without verifying their + format, and the exact file name must be given. Other names won't + be tried. + '-q' '--quiet' Quiet operation. Suppress all messages. @@ -276,14 +303,6 @@ differences were found, and 2 means trouble. a letter, and precede bytes larger than 127 with 'M-' (which stands 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' '--ignore-initial=SIZE' Ignore any differences in the first SIZE bytes of the input files. @@ -303,6 +322,16 @@ differences were found, and 2 means trouble. '--bytes=COUNT' Compare at most COUNT input bytes. +'-O [FORMAT1][,FORMAT2]' +'--force-format=[FORMAT1][,FORMAT2]' + Force the given compression formats. Any of FORMAT1 or FORMAT2 may + be omitted and the corresponding format will be automatically + detected. Valid values for FORMAT are 'bz2', 'gz', 'lz' and 'xz'. + If at least one format is specified with this option, the file is + passed to the corresponding decompressor without verifying its + format, and the exact file names of both FILE1 and FILE2 must be + given. Other names won't be tried. + '-q' '-s' '--quiet' @@ -321,7 +350,7 @@ Zdiff compares two files ('-' means standard input), and if they differ, shows the differences line by line. If any given file is compressed, its decompressed content is used. Zdiff is a front end to the diff program and has the limitation that messages from diff refer to -temporary filenames instead of those specified. +temporary file names instead of those specified. The format for running zdiff is: @@ -372,18 +401,20 @@ differences were found, and 2 means trouble. '--ignore-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' '--ignore-case' Ignore case differences in file contents. +'-O [FORMAT1][,FORMAT2]' +'--force-format=[FORMAT1][,FORMAT2]' + Force the given compression formats. Any of FORMAT1 or FORMAT2 may + be omitted and the corresponding format will be automatically + detected. Valid values for FORMAT are 'bz2', 'gz', 'lz' and 'xz'. + If at least one format is specified with this option, the file is + passed to the corresponding decompressor without verifying its + format, and the exact file names of both FILE1 and FILE2 must be + given. Other names won't be tried. + '-p' '--show-c-function' Show which C function each change is in. @@ -483,19 +514,14 @@ matches were found, and 2 means trouble. '--fixed-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' '--no-filename' - Suppress the prefixing of filenames on output when multiple files + Suppress the prefixing of file names on output when multiple files are searched. '-H' '--with-filename' - Print the filename for each match. + Print the file name for each match. '-i' '--ignore-case' @@ -524,6 +550,14 @@ matches were found, and 2 means trouble. '--only-matching' Show only the part of matching lines that actually matches PATTERN. +'-O FORMAT' +'--force-format=FORMAT' + Force the given compression format. Valid values for FORMAT are + 'bz2', 'gz', 'lz' and 'xz'. If this option is used, the files are + passed to the corresponding decompressor without verifying their + format, and the exact file name must be given. Other names won't + be tried. + '-q' '--quiet' Suppress all messages. Exit immediately with zero status if any @@ -577,10 +611,15 @@ environmental problems (file not found, invalid flags, I/O errors, etc), Ztest supports the following options: -'--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. +'-O FORMAT' +'--force-format=FORMAT' + Force the given compression format. Valid values for FORMAT are + 'bz2', 'gz', 'lz' and 'xz'. If this option is used, the files are + passed to the corresponding decompressor without verifying their + format, and any files in a format that the decompressor can't + understand will fail. For example, '--force-format=gz' can test + gzipped (.gz) and compress'd (.Z) files if the compressor used is + GNU gzip. '-q' '--quiet' @@ -617,10 +656,20 @@ and the original file is not deleted. The operation of zupdate is meant to be safe and not produce any data loss. Therefore, existing lzip compressed files are never overwritten nor deleted. + Combining the '--force' and '--keep' options, as in +'zupdate -f -k *.gz', verifies that there are no differences between +each pair of files in a multiformat set of files. + The names of the original files must have one of the following extensions: '.bz2', '.tbz', '.tbz2', '.gz', '.tgz', '.xz', '.txz'. The files produced have the extensions '.lz' or '.tar.lz'. + Recompressing a file is much like copying or moving it; therefore +zupdate preserves the access and modification dates, permissions, and, +when possible, ownership of the file just as "cp -p" does. (If the user +ID or the group ID can't be duplicated, the file permission bits S_ISUID +and S_ISGID are cleared). + The format for running zupdate is: zupdate [OPTIONS] [FILES] @@ -708,17 +757,18 @@ Concept index Tag Table: Node: Top222 -Node: Introduction1128 -Node: Common options3475 -Node: The zutilsrc file4724 -Node: Zcat5650 -Node: Zcmp7572 -Node: Zdiff9896 -Node: Zgrep12399 -Node: Ztest15367 -Node: Zupdate16591 -Node: Problems18979 -Node: Concept index19513 +Node: Introduction1149 +Node: Common options3698 +Ref: compressor-requirements5451 +Node: The zutilsrc file5823 +Node: Zcat6749 +Node: Zcmp8796 +Node: Zdiff11256 +Node: Zgrep13896 +Node: Ztest16991 +Node: Zupdate18495 +Node: Problems21370 +Node: Concept index21904 End Tag Table diff --git a/doc/zutils.texi b/doc/zutils.texi index 6737c72..4624d8c 100644 --- a/doc/zutils.texi +++ b/doc/zutils.texi @@ -6,8 +6,8 @@ @finalout @c %**end of header -@set UPDATED 30 August 2014 -@set VERSION 1.3 +@set UPDATED 30 April 2015 +@set VERSION 1.4-pre2 @dircategory Data Compression @direntry @@ -36,7 +36,7 @@ This manual is for Zutils (version @value{VERSION}, @value{UPDATED}). @menu * Introduction:: Purpose and features of zutils -* Common options:: Common options +* Common options:: Options common to all utilities * The zutilsrc file:: The zutils configuration file * Zcat:: Concatenating compressed files * Zcmp:: Comparing compressed files byte by byte @@ -49,7 +49,7 @@ This manual is for Zutils (version @value{VERSION}, @value{UPDATED}). @end menu @sp 1 -Copyright @copyright{} 2009-2014 Antonio Diaz Diaz. +Copyright @copyright{} 2009-2015 Antonio Diaz Diaz. This manual is free documentation: you have unlimited permission to copy, distribute and modify it. @@ -81,11 +81,16 @@ similar to gzip's znew. NOTE: Bzip2 and lzip provide well-defined values of exit status, which makes them safe to use with zutils. Gzip and xz may return ambiguous warning values, making them less reliable back ends for zutils. +@xref{compressor-requirements}. -FORMAT NOTE: If the @samp{--format} option is given, the corresponding -files are passed to the decompressor without verifying their format, +FORMAT NOTE: The "--format" option allows the processing of a subset of +formats in search and recursive modes: +@w{@samp{zgrep foo -r --format=bz2,lz somedir}}. + +FORMAT NOTE 2: If the @samp{--force-format} option is given, the files are +passed to the corresponding decompressor without verifying their format, allowing for example the processing of compress'd (.Z) files with gzip: -@samp{zcmp --format=gz file.Z file.lz}. +@w{@samp{zcmp --force-format=gz file.Z file.lz}}. LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never have been compressed. Decompressed is used to refer to data which has @@ -128,6 +133,28 @@ only supports the @samp{--help} form of this option. @itemx --version Print the version number on the standard output and exit. +@item -M @var{format_list} +@itemx --format=@var{format_list} +Exclude formats not listed in the comma-separated @var{format_list}. +Valid formats are @samp{bz2}, @samp{gz}, @samp{lz}, @samp{xz} and +@samp{un} for @samp{uncompressed}, meaning "any file name without a +known extension". This option excludes files based on extension, instead +of format, because it is more efficient. The exclusion only applies to +names generated automatically (for example when adding extensions to a +file name or when operating recursively on directories). Files given in +the command line are always processed. + +Each format in @var{format_list} enables file names with the following +extensions: + +@multitable {bz2} {enables} {any other file name} +@item bz2 @tab enables @tab .bz2 .tbz .tbz2 +@item gz @tab enables @tab .gz .tgz +@item lz @tab enables @tab .lz .tlz +@item xz @tab enables @tab .xz .txz +@item un @tab enables @tab any other file name +@end multitable + @item -N @itemx --no-rcfile Don't read the runtime configuration file @samp{zutilsrc}. @@ -137,9 +164,11 @@ Don't read the runtime configuration file @samp{zutilsrc}. @itemx --lz=@var{command} @itemx --xz=@var{command} Set program (may include arguments) to be used as (de)compressor for the -given format. These options override the values set in @file{zutilsrc}. -The compression program used must meet three requirements: +given format. The mane of the program can't begin with @samp{-}. These +options override the values set in @file{zutilsrc}. The compression +program used must meet three requirements: +@anchor{compressor-requirements} @enumerate @item When called with the @samp{-d} option, it must read compressed data from @@ -227,15 +256,18 @@ Equivalent to @samp{-vE}. @itemx --show-ends 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 @itemx --number Number all output lines, starting with 1. The line count is unlimited. +@item -O @var{format} +@itemx --force-format=@var{format} +Force the given compression format. Valid values for @var{format} are +@samp{bz2}, @samp{gz}, @samp{lz} and @samp{xz}. If this option is used, +the files are passed to the corresponding decompressor without verifying +their format, and the exact file name must be given. Other names won't +be tried. + @item -q @itemx --quiet Quiet operation. Suppress all messages. @@ -313,14 +345,6 @@ 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 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} @itemx --ignore-initial=@var{size} Ignore any differences in the first @var{size} bytes of the input files. @@ -340,6 +364,16 @@ differing bytes. @itemx --bytes=@var{count} Compare at most @var{count} input bytes. +@item -O [@var{format1}][,@var{format2}] +@itemx --force-format=[@var{format1}][,@var{format2}] +Force the given compression formats. Any of @var{format1} or +@var{format2} may be omitted and the corresponding format will be +automatically detected. Valid values for @var{format} are @samp{bz2}, +@samp{gz}, @samp{lz} and @samp{xz}. If at least one format is specified +with this option, the file is passed to the corresponding decompressor +without verifying its format, and the exact file names of both +@var{file1} and @var{file2} must be given. Other names won't be tried. + @item -q @itemx -s @itemx --quiet @@ -358,7 +392,7 @@ Zdiff compares two files (@samp{-} means standard input), and if they differ, shows the differences line by line. If any given file is compressed, its decompressed content is used. Zdiff is a front end to the diff program and has the limitation that messages from diff refer to -temporary filenames instead of those specified. +temporary file names instead of those specified. The format for running zdiff is: @@ -417,18 +451,20 @@ Try hard to find a smaller set of changes. @itemx --ignore-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 @itemx --ignore-case Ignore case differences in file contents. +@item -O [@var{format1}][,@var{format2}] +@itemx --force-format=[@var{format1}][,@var{format2}] +Force the given compression formats. Any of @var{format1} or +@var{format2} may be omitted and the corresponding format will be +automatically detected. Valid values for @var{format} are @samp{bz2}, +@samp{gz}, @samp{lz} and @samp{xz}. If at least one format is specified +with this option, the file is passed to the corresponding decompressor +without verifying its format, and the exact file names of both +@var{file1} and @var{file2} must be given. Other names won't be tried. + @item -p @itemx --show-c-function Show which C function each change is in. @@ -532,19 +568,14 @@ Obtain patterns from @var{file}, one per line. @itemx --fixed-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 @itemx --no-filename -Suppress the prefixing of filenames on output when multiple files are +Suppress the prefixing of file names on output when multiple files are searched. @item -H @itemx --with-filename -Print the filename for each match. +Print the file name for each match. @item -i @itemx --ignore-case @@ -573,6 +604,14 @@ Prefix each matched line with its line number in the input file. @itemx --only-matching Show only the part of matching lines that actually matches @var{pattern}. +@item -O @var{format} +@itemx --force-format=@var{format} +Force the given compression format. Valid values for @var{format} are +@samp{bz2}, @samp{gz}, @samp{lz} and @samp{xz}. If this option is used, +the files are passed to the corresponding decompressor without verifying +their format, and the exact file name must be given. Other names won't +be tried. + @item -q @itemx --quiet Suppress all messages. Exit immediately with zero status if any match is @@ -630,10 +669,15 @@ environmental problems (file not found, invalid flags, I/O errors, etc), Ztest supports the following options: @table @samp -@item --format=@var{fmt} -Force the given compression format. Valid values for @var{fmt} are +@item -O @var{format} +@itemx --force-format=@var{format} +Force the given compression format. Valid values for @var{format} are @samp{bz2}, @samp{gz}, @samp{lz} and @samp{xz}. If this option is used, -all files not in the given format will fail. +the files are passed to the corresponding decompressor without verifying +their format, and any files in a format that the decompressor can't +understand will fail. For example, @samp{--force-format=gz} can test +gzipped (.gz) and compress'd (.Z) files if the compressor used is GNU +gzip. @item -q @itemx --quiet @@ -670,11 +714,21 @@ and the original file is not deleted. The operation of zupdate is meant to be safe and not produce any data loss. Therefore, existing lzip compressed files are never overwritten nor deleted. +Combining the @samp{--force} and @samp{--keep} options, as in +@w{@code{zupdate -f -k *.gz}}, verifies that there are no differences +between each pair of files in a multiformat set of files. + The names of the original files must have one of the following extensions: @samp{.bz2}, @samp{.tbz}, @samp{.tbz2}, @samp{.gz}, @samp{.tgz}, @samp{.xz}, @samp{.txz}. The files produced have the extensions @samp{.lz} or @samp{.tar.lz}. +Recompressing a file is much like copying or moving it; therefore +zupdate preserves the access and modification dates, permissions, and, +when possible, ownership of the file just as "cp -p" does. (If the user +ID or the group ID can't be duplicated, the file permission bits S_ISUID +and S_ISGID are cleared). + The format for running zupdate is: @example @@ -739,7 +793,7 @@ for all eternity, if not longer. If you find a bug in zutils, please send electronic mail to @email{zutils-bug@@nongnu.org}. Include the version number, which you can -find by running @w{@samp{zupdate --version}}. +find by running @w{@code{zupdate --version}}. @node Concept index @@ -1,5 +1,5 @@ /* Zutils - Utilities dealing with compressed files - Copyright (C) 2009-2014 Antonio Diaz Diaz. + Copyright (C) 2009-2015 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 @@ -37,7 +37,7 @@ int verbosity = 0; namespace { const char * const config_file_name = "zutilsrc"; -const char * const program_year = "2014"; +const char * const program_year = "2015"; std::string compressor_names[num_formats] = { "bzip2", "gzip", "lzip", "xz" }; // default compressor names @@ -45,6 +45,23 @@ std::string compressor_names[num_formats] = // args to compressors, maybe empty std::vector< std::string > compressor_args[num_formats]; +// vector of enabled formats plus [num_formats] for uncompressed. +// empty means all enabled. +std::vector< bool > enabled_formats; + +struct { const char * from; const char * to; int format_index; } const + known_extensions[] = { + { ".bz2", "", fmt_bz2 }, + { ".tbz", ".tar", fmt_bz2 }, + { ".tbz2", ".tar", fmt_bz2 }, + { ".gz", "", fmt_gz }, + { ".tgz", ".tar", fmt_gz }, + { ".lz", "", fmt_lz }, + { ".tlz", ".tar", fmt_lz }, + { ".xz", "", fmt_xz }, + { ".txz", ".tar", fmt_xz }, + { 0, 0, -1 } }; + int my_fgetc( FILE * const f ) { @@ -95,12 +112,12 @@ const std::string & my_fgets( FILE * const f, int & linenum ) while( std::isspace( ch ) ) { if( ch == '\n' ) { ++linenum; } ch = my_fgetc( f ); } } - if( ch == EOF ) { if( s.size() > 0 ) { ++linenum; } break; } + if( ch == EOF ) { if( s.size() ) { ++linenum; } break; } else if( ch == '\n' ) { ++linenum; strip = true; if( trailing_escape( s ) ) s.erase( s.size() - 1 ); - else if( s.size() > 0 ) break; + else if( s.size() ) break; } else s += ch; } @@ -108,6 +125,29 @@ const std::string & my_fgets( FILE * const f, int & linenum ) } +bool parse_compressor_command( const std::string & s, int i, + const int format_index ) + { + const int len = s.size(); + while( i < len && std::isspace( s[i] ) ) ++i; // strip spaces + int l = i; + while( i < len && !std::isspace( s[i] ) ) ++i; + if( l >= i || s[l] == '-' ) return false; + compressor_names[format_index].assign( s, l, i - l ); + + compressor_args[format_index].clear(); + while( i < len ) + { + while( i < len && std::isspace( s[i] ) ) ++i; // strip spaces + l = i; + while( i < len && !std::isspace( s[i] ) ) ++i; + if( l < i ) + compressor_args[format_index].push_back( std::string( s, l, i - l ) ); + } + return true; + } + + bool parse_rc_line( const std::string & line, const char * const filename, const int linenum ) { @@ -136,23 +176,11 @@ bool parse_rc_line( const std::string & line, std::fprintf( stderr, "%s %d: missing '='.\n", filename, linenum ); return false; } ++i; // skip the '=' - while( i < len && std::isspace( line[i] ) ) ++i; // strip spaces - l = i; - while( i < len && !std::isspace( line[i] ) ) ++i; - if( l >= i ) - { if( verbosity >= 0 ) - std::fprintf( stderr, "%s %d: missing compressor name.\n", filename, linenum ); - return false; } - compressor_names[format_index].assign( line, l, i - l ); - - compressor_args[format_index].clear(); - while( i < len ) + if( !parse_compressor_command( line, i, format_index ) ) { - while( i < len && std::isspace( line[i] ) ) ++i; // strip spaces - l = i; - while( i < len && !std::isspace( line[i] ) ) ++i; - if( l < i ) - compressor_args[format_index].push_back( std::string( line, l, i - l ) ); + if( verbosity >= 0 ) + std::fprintf( stderr, "%s %d: missing compressor name.\n", filename, linenum ); + return false; } return true; } @@ -181,6 +209,70 @@ int process_rcfile( const std::string & name ) } // end namespace +bool enabled_format( const int format_index ) + { + if( enabled_formats.size() <= num_formats ) return true; + if( format_index < 0 ) return enabled_formats[num_formats]; + return enabled_formats[format_index]; + } + + +void parse_format_list( const std::string & arg ) + { + const std::string un( "uncompressed" ); + bool error = arg.empty(); + enabled_formats.assign( num_formats + 1, false ); + + for( unsigned l = 0, r; l < arg.size(); l = r + 1 ) + { + r = std::min( arg.find( ',', l ), arg.size() ); + if( l >= r ) { error = true; break; } // empty format + int format_index = num_formats; + const std::string s( arg, l, r - l ); + for( int i = 0; i < num_formats; ++i ) + if( s == format_names[i] ) + { format_index = i; break; } + if( format_index == num_formats && un.find( s ) != 0 ) + { error = true; break; } + enabled_formats[format_index] = true; + } + if( error ) + { show_error( "Bad argument for '--format' option." ); std::exit( 1 ); } + } + + +int parse_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 '--force-format' option." ); + std::exit( 1 ); + } + + +int extension_index( const std::string & name ) + { + for( int i = 0; known_extensions[i].from; ++i ) + { + const std::string ext( known_extensions[i].from ); + if( name.size() > ext.size() && + name.compare( name.size() - ext.size(), ext.size(), ext ) == 0 ) + return i; + } + return -1; + } + +int extension_format( const int eindex ) + { return ( eindex >= 0 ) ? known_extensions[eindex].format_index : -1; } + +const char * extension_from( const int eindex ) + { return known_extensions[eindex].from; } + +const char * extension_to( const int eindex ) + { return known_extensions[eindex].to; } + + void maybe_process_config_file( const Arg_parser & parser ) { for( int i = 0; i < parser.arguments(); ++i ) @@ -203,32 +295,15 @@ void maybe_process_config_file( const Arg_parser & parser ) void parse_compressor( const std::string & arg, const int format_index, const int eretval ) { - const int len = arg.size(); - int i = 0; - while( i < len && std::isspace( arg[i] ) ) ++i; // strip spaces - int l = i; - while( i < len && !std::isspace( arg[i] ) ) ++i; - if( l >= i ) + if( !parse_compressor_command( arg, 0, format_index ) ) { show_error( "Missing compressor name." ); std::exit( eretval ); } - compressor_names[format_index].assign( arg, l, i - l ); - - compressor_args[format_index].clear(); - while( i < len ) - { - while( i < len && std::isspace( arg[i] ) ) ++i; // strip spaces - l = i; - while( i < len && !std::isspace( arg[i] ) ) ++i; - if( l < i ) - compressor_args[format_index].push_back( std::string( arg, l, i - l ) ); - } } const char * get_compressor_name( const int format_index ) { if( format_index >= 0 && format_index < num_formats && - compressor_names[format_index].size() && - compressor_names[format_index][0] != '-' ) + compressor_names[format_index].size() ) return compressor_names[format_index].c_str(); return 0; } @@ -1,5 +1,5 @@ /* Zutils - Utilities dealing with compressed files - Copyright (C) 2009-2014 Antonio Diaz Diaz. + Copyright (C) 2009-2015 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 @@ -22,6 +22,15 @@ const char * const simple_extensions[num_formats] = const int format_order[num_formats] = { fmt_lz, fmt_bz2, fmt_gz, fmt_xz }; // search order +bool enabled_format( const int format_index ); +void parse_format_list( const std::string & arg ); +int parse_format_type( const std::string & arg ); + +int extension_index( const std::string & name ); // -1 if unknown +int extension_format( const int eindex ); // -1 if uncompressed +const char * extension_from( const int eindex ); +const char * extension_to( const int eindex ); + extern const char * invocation_name; extern const char * program_name; extern int verbosity; diff --git a/recursive.cc b/recursive.cc index 8c39121..9c98362 100644 --- a/recursive.cc +++ b/recursive.cc @@ -1,5 +1,5 @@ /* Zutils - Utilities dealing with compressed files - Copyright (C) 2009-2014 Antonio Diaz Diaz. + Copyright (C) 2009-2015 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 @@ -46,9 +46,12 @@ bool next_filename( std::list< std::string > & filenames, { const struct dirent * const entryp = readdir( dirp ); if( !entryp ) { closedir( dirp ); break; } - std::string tmp_name( entryp->d_name ); - if( tmp_name != "." && tmp_name != ".." ) - tmp_list.push_back( input_filename + "/" + tmp_name ); + const std::string tmp_name( entryp->d_name ); + if( tmp_name == "." || tmp_name == ".." ) continue; + const std::string full_name( input_filename + "/" + tmp_name ); + if( enabled_format( extension_format( extension_index( tmp_name ) ) ) || + ( stat( full_name.c_str(), &st ) == 0 && S_ISDIR( st.st_mode ) ) ) + tmp_list.push_back( full_name ); } filenames.splice( filenames.begin(), tmp_list ); continue; diff --git a/testsuite/check.sh b/testsuite/check.sh index c2d67f4..cbd53b3 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh # check script for Zutils - Utilities dealing with compressed files -# Copyright (C) 2009-2014 Antonio Diaz Diaz. +# Copyright (C) 2009-2015 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -52,7 +52,10 @@ for i in ${extensions}; do "${ZCAT}" -N in.$i > copy || fail=1 cmp in copy || fail=1 printf . - "${ZCAT}" -N --format=$i in.$i > copy || fail=1 + "${ZCAT}" -N --format=un in.$i > copy || fail=1 + cmp in copy || fail=1 + printf . + "${ZCAT}" -N --force-format=$i in.$i > copy || fail=1 cmp in copy || fail=1 printf . "${ZCAT}" -N in.$i | dd bs=1000 count=1 > copy 2> /dev/null || fail=1 @@ -81,14 +84,28 @@ printf . "${ZCAT}" -N lz_only > copy || fail=1 cmp in copy || fail=1 printf . -"${ZCAT}" -N in in.gz in.bz2 in.lz -- -in- -in-.lz > copy6 || fail=1 -cmp in6 copy6 || fail=1 +"${ZCAT}" -N in in.gz in.bz2 in.lz -- -in- -in-.lz > copy || fail=1 +cmp in6 copy || fail=1 printf . -"${ZCAT}" -N --format=gz in.bz2 2> /dev/null +"${ZCAT}" -N --format= in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --format=, in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --format=,lz in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --format=gz,,lz in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --format=lz,, in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --format=nc in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --lz='-lzip -q' in.lz 2> /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCAT}" -N --force-format=gz in.bz2 2> /dev/null if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${ZCAT}" -N --format=bz2 in.lz 2> /dev/null +"${ZCAT}" -N --force-format=bz2 in.lz 2> /dev/null if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi -"${ZCAT}" -N --format=lz in.gz 2> /dev/null +"${ZCAT}" -N --force-format=lz in.gz 2> /dev/null if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZCAT}" -N --bad-option 2> /dev/null if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi @@ -103,13 +120,13 @@ for i in ${extensions}; do printf . "${ZCMP}" -N -i 100 -n 500 in6 in.$i || fail=1 printf . - "${ZCMP}" -N in in.$i --format=,$i || fail=1 + "${ZCMP}" -N in in.$i --force-format=,$i || fail=1 printf . "${ZCMP}" -N in.$i in || fail=1 printf . "${ZCMP}" -N -i 1000:1000 -n 50 in.$i in6 || fail=1 printf . - "${ZCMP}" -N in.$i in --format=$i || fail=1 + "${ZCMP}" -N in.$i in --force-format=$i || fail=1 printf . done @@ -165,11 +182,11 @@ printf . printf . "${ZCMP}" -N - in < in.lz || fail=1 printf . -"${ZCMP}" -N -q --format=lz in.lz +"${ZCMP}" -N -q --force-format=lz in.lz if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -"${ZCMP}" -N --format=lz in.gz in.lz 2> /dev/null -res=$? -if [ ${res} = 1 ] || [ ${res} = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZCMP}" -N --force-format=lz in.gz in.lz 2> /dev/null +r=$? +if [ $r = 1 ] || [ $r = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZCMP}" -N -n -1 in in 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZCMP}" -N --bad-option in in 2> /dev/null @@ -183,11 +200,11 @@ for i in ${extensions}; do printf . "${ZDIFF}" -N in in.$i > /dev/null || fail=1 printf . - "${ZDIFF}" -N --format=,$i in in.$i > /dev/null || fail=1 + "${ZDIFF}" -N --force-format=,$i in in.$i > /dev/null || fail=1 printf . "${ZDIFF}" -N in.$i in > /dev/null || fail=1 printf . - "${ZDIFF}" -N --format=$i, in.$i in > /dev/null || fail=1 + "${ZDIFF}" -N --force-format=$i, in.$i in > /dev/null || fail=1 printf . done @@ -199,7 +216,11 @@ if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi printf . "${ZDIFF}" -N in in || fail=1 printf . -"${ZDIFF}" -N in > /dev/null || fail=1 +"${ZDIFF}" -N in || fail=1 +printf . +"${ZDIFF}" -N --format=gz,bz2 in || fail=1 +printf . +"${ZDIFF}" -N --format=gz in || fail=1 printf . "${ZDIFF}" -N in.lz in.gz > /dev/null || fail=1 printf . @@ -231,25 +252,44 @@ printf . printf . "${ZDIFF}" -N - in < in.lz > /dev/null || fail=1 printf . -"${ZDIFF}" -N -q --format=bz2 in.bz2 2> /dev/null +"${ZDIFF}" -N --bz2='-bzip2' in.bz2 2> /dev/null +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZDIFF}" -N -q --force-format=bz2 in.bz2 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -"${ZDIFF}" -N -q --format=,lz in.lz in.bz2 > /dev/null 2>&1 -res=$? -if [ ${res} = 1 ] || [ ${res} = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZDIFF}" -N -q --force-format=,lz in.lz in.bz2 > /dev/null 2>&1 +r=$? +if [ $r = 1 ] || [ $r = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZDIFF}" -N --bad-option 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +mkdir tmp2 +cat in > tmp2/x || framework_failure +cat in.lz > tmp2/x.lz || framework_failure +"${ZDIFF}" -N --format=bz2 tmp2/x < /dev/null > /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZDIFF}" -N --format=gz tmp2/x < /dev/null > /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZDIFF}" -N --format=lz tmp2/x.lz < /dev/null > /dev/null +if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZDIFF}" -N --format=lz tmp2/x < /dev/null +if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZDIFF}" -N --format=un tmp2/x.lz < /dev/null +if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi +rm -r tmp2 || framework_failure + printf "\ntesting zgrep-%s..." "$2" for i in ${extensions}; do "${ZGREP}" -N "GNU" in.$i > /dev/null || fail=1 printf . + "${ZGREP}" -N "GNU" < in.$i > /dev/null || fail=1 + printf . "${ZGREP}" -N -l "GNU" in.$i > /dev/null || fail=1 printf . "${ZGREP}" -N -L "GNU" in.$i || fail=1 printf . - "${ZGREP}" -N --format=$i "GNU" in.$i > /dev/null || fail=1 + "${ZGREP}" -N --force-format=$i "GNU" in.$i > /dev/null || fail=1 printf . "${ZGREP}" -N -v "nx_pattern" in.$i > /dev/null || fail=1 printf . @@ -259,34 +299,28 @@ for i in ${extensions}; do if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZGREP}" -N -L "nx_pattern" in.$i > /dev/null if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi - "${ZGREP}" -N --format=$i "GNU" in 2> /dev/null + "${ZGREP}" -N --force-format=$i "GNU" in 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi done -"${ZGREP}" -N "GNU" < pin.tar > /dev/null || fail=1 -printf . "${ZGREP}" -N "GNU" pin.tar > /dev/null || fail=1 printf . +"${ZGREP}" -N "GNU" < pin.tar > /dev/null || fail=1 +printf . "${ZGREP}" -N -r "GNU" . > /dev/null || fail=1 printf . "${ZGREP}" -N "nx_pattern" -r . in > /dev/null if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi -"${ZGREP}" -N "GNU" < in > /dev/null || fail=1 -printf . -"${ZGREP}" -N "GNU" < in.gz > /dev/null || fail=1 -printf . -"${ZGREP}" -N "GNU" < in.bz2 > /dev/null || fail=1 +"${ZGREP}" -N "GNU" in > /dev/null || fail=1 printf . -"${ZGREP}" -N "GNU" < in.lz > /dev/null || fail=1 +"${ZGREP}" -N "GNU" < in > /dev/null || fail=1 printf . "${ZGREP}" -N "GNU" --lz='lzip -q' < in.lz > /dev/null || fail=1 printf . -"${ZGREP}" -N "GNU" in > /dev/null || fail=1 -printf . -"${ZGREP}" -N "GNU" -- -in- > /dev/null || fail=1 -printf . -"${ZGREP}" -N "GNU" -- -in-.lz > /dev/null || fail=1 +"${ZGREP}" -N -- "-free" -in- > /dev/null || fail=1 printf . +"${ZGREP}" -N -q -- "-free" nx_file -in-.lz +if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZGREP}" -N "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null || fail=1 printf . "${ZGREP}" -N -l "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null || fail=1 @@ -301,6 +335,8 @@ if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZGREP}" -N "GNU" -s nx_file if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi +"${ZGREP}" -N -q +if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZEGREP}" -N "GNU" in > /dev/null || fail=1 printf . @@ -311,11 +347,11 @@ printf . printf "\ntesting ztest-%s..." "$2" for i in ${extensions}; do - "${ZTEST}" -N --format=$i < in.$i || fail=1 + "${ZTEST}" -N --force-format=$i < in.$i || fail=1 printf . - "${ZTEST}" -N --format=$i < in 2> /dev/null + "${ZTEST}" -N --force-format=$i < in 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi - "${ZTEST}" -N --format=$i in 2> /dev/null + "${ZTEST}" -N --force-format=$i in 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi done @@ -335,7 +371,7 @@ printf . if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi dd if=in.lz bs=1000 count=1 2> /dev/null | "${ZTEST}" -N -q if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi -"${ZTEST}" -N --format=lz in.bz2 2> /dev/null +"${ZTEST}" -N --force-format=lz in.bz2 2> /dev/null if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi "${ZTEST}" -N --lz='lzip --bad-option' in.lz 2> /dev/null if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi @@ -369,12 +405,12 @@ else printf - ; fail=1 fi rm -f x.lz || framework_failure -"${ZUPDATE}" -N x.bz2 2> /dev/null +"${ZUPDATE}" -N x.bz2 if [ $? = 0 ] && [ ! -e x.bz2 ] && [ -e x.gz ] && [ -e x.lz ] ; then printf . else printf - ; fail=1 fi rm -f x.lz || framework_failure -"${ZUPDATE}" -N x.gz 2> /dev/null +"${ZUPDATE}" -N x.gz if [ $? = 0 ] && [ ! -e x.bz2 ] && [ ! -e x.gz ] && [ -e x.lz ] ; then printf . else printf - ; fail=1 fi @@ -390,7 +426,7 @@ rm -f x.lz || framework_failure cat in.bz2 > x.bz2 || framework_failure cat in.gz > x.gz || framework_failure -"${ZUPDATE}" -N -f -k x.bz2 x.gz 2> /dev/null +"${ZUPDATE}" -N -f -k x.bz2 x.gz if [ $? = 0 ] && [ -e x.bz2 ] && [ -e x.gz ] && [ -e x.lz ] ; then printf . else printf - ; fail=1 fi @@ -398,7 +434,7 @@ rm -f x.lz || framework_failure cat in.bz2 > x.bz2 || framework_failure cat in.gz > x.gz || framework_failure -"${ZUPDATE}" -N -f x.bz2 x.gz 2> /dev/null +"${ZUPDATE}" -N -f x.bz2 x.gz if [ $? = 0 ] && [ ! -e x.bz2 ] && [ ! -e x.gz ] && [ ! -e x ] && [ -e x.lz ] ; then printf . else printf - ; fail=1 @@ -406,12 +442,29 @@ fi rm -f x.lz || framework_failure cat in.bz2 > x.bz2 || framework_failure -"${ZUPDATE}" -N -6 -q x.bz2 +"${ZUPDATE}" -N -1 -q x.bz2 if [ $? = 0 ] && [ ! -e x.bz2 ] && [ -e x.lz ] ; then printf . else printf - ; fail=1 fi rm -f x.lz || framework_failure +mkdir tmp2 +mkdir tmp2/tmp3 +cat in.bz2 > tmp2/tmp3/x.bz2 || framework_failure +cat in.gz > tmp2/tmp3/x.gz || framework_failure +"${ZUPDATE}" -N -r --format=gz tmp2 +if [ $? = 0 ] && [ -e tmp2/tmp3/x.bz2 ] && [ ! -e tmp2/tmp3/x.gz ] && + [ -e tmp2/tmp3/x.lz ] ; then printf . +else printf - ; fail=1 +fi +rm -f tmp2/tmp3/x.lz || framework_failure +"${ZUPDATE}" -N -r --format=bz2 tmp2 +if [ $? = 0 ] && [ ! -e tmp2/tmp3/x.bz2 ] && [ ! -e tmp2/tmp3/x.gz ] && + [ -e tmp2/tmp3/x.lz ] ; then printf . +else printf - ; fail=1 +fi +rm -r tmp2 || framework_failure + echo if [ ${fail} = 0 ] ; then echo "tests completed successfully." @@ -1,5 +1,5 @@ /* Zcat - decompress and concatenate files to standard output - Copyright (C) 2010-2014 Antonio Diaz Diaz. + Copyright (C) 2010-2015 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 @@ -39,14 +39,11 @@ #include "rc.h" #include "zutils.h" -#ifndef O_BINARY -#define O_BINARY 0 -#endif - namespace { #include "recursive.cc" +#include "zcatgrep.cc" struct Cat_options { @@ -111,9 +108,10 @@ void show_help() " -b, --number-nonblank number nonblank output lines\n" " -e equivalent to '-vE'\n" " -E, --show-ends display '$' at end of each line\n" - " --format=<fmt> force given format (bz2, gz, lz, xz)\n" + " -M, --format=<list> exclude formats not in <list>\n" " -n, --number number all output lines\n" " -N, --no-rcfile don't read runtime configuration file\n" + " -O, --force-format=<fmt> force given format (bz2, gz, lz, xz)\n" " -q, --quiet suppress all messages\n" " -r, --recursive operate recursively on directories\n" " -s, --squeeze-blank never more than one single blank line\n" @@ -129,41 +127,6 @@ void show_help() } -int simple_extension_index( const std::string & name ) - { - for( int i = 0; i < num_formats; ++i ) - { - const std::string ext( simple_extensions[i] ); - if( name.size() > ext.size() && - name.compare( name.size() - ext.size(), ext.size(), ext ) == 0 ) - return i; - } - return -1; - } - - -int open_instream( std::string & input_filename, const bool search ) - { - int infd = open( input_filename.c_str(), O_RDONLY | O_BINARY ); - if( infd < 0 ) - { - if( search && simple_extension_index( input_filename ) < 0 ) - { - for( int i = 0; i < num_formats; ++i ) - { - const std::string name( input_filename + - simple_extensions[format_order[i]] ); - infd = open( name.c_str(), O_RDONLY | O_BINARY ); - if( infd >= 0 ) { input_filename = name; break; } - } - } - if( infd < 0 ) - show_error2( "Can't open input file", input_filename.c_str() ); - } - return infd; - } - - int do_cat( const int infd, const int buffer_size, uint8_t * const inbuf, uint8_t * const outbuf, const std::string & input_filename, @@ -288,7 +251,7 @@ int cat( int infd, const int format_index, const std::string & input_filename, int main( const int argc, const char * const argv[] ) { - enum { format_opt = 256, verbose_opt, bz2_opt, gz_opt, lz_opt, xz_opt }; + enum { verbose_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt }; int infd = -1; int format_index = -1; bool recursive = false; @@ -310,8 +273,10 @@ int main( const int argc, const char * const argv[] ) { 'h', "help", Arg_parser::no }, { 'l', "list", Arg_parser::no }, // gzip { 'L', "license", Arg_parser::no }, // gzip + { 'M', "format", Arg_parser::yes }, { 'n', "number", Arg_parser::no }, // cat { 'N', "no-rcfile", Arg_parser::no }, + { 'O', "force-format", Arg_parser::yes }, { 'q', "quiet", Arg_parser::no }, { 'r', "recursive", Arg_parser::no }, { 's', "squeeze-blank", Arg_parser::no }, // cat @@ -319,7 +284,6 @@ int main( const int argc, const char * const argv[] ) { 'T', "show-tabs", Arg_parser::no }, // cat { 'v', "show-nonprinting", Arg_parser::no }, // cat { 'V', "version", Arg_parser::no }, - { format_opt, "format", Arg_parser::yes }, { verbose_opt, "verbose", Arg_parser::no }, { bz2_opt, "bz2", Arg_parser::yes }, { gz_opt, "gz", Arg_parser::yes }, @@ -338,7 +302,7 @@ int main( const int argc, const char * const argv[] ) { const int code = parser.code( argind ); if( !code ) break; // no more options - const char * const arg = parser.argument( argind ).c_str(); + const std::string & arg = parser.argument( argind ); switch( code ) { case 'A': cat_options.show_ends = true; @@ -353,9 +317,11 @@ int main( const int argc, const char * const argv[] ) case 'h': show_help(); return 0; case 'l': break; case 'L': break; + case 'M': parse_format_list( arg ); break; case 'n': if( cat_options.number_lines == 0 ) { cat_options.number_lines = 2; } break; case 'N': break; + case 'O': format_index = parse_format_type( arg ); break; case 'q': verbosity = -1; break; case 'r': recursive = true; break; case 's': cat_options.squeeze_blank = true; break; @@ -363,7 +329,6 @@ int main( const int argc, const char * const argv[] ) case 'T': cat_options.show_tabs = true; break; case 'v': cat_options.show_nonprinting = true; break; case 'V': show_version(); return 0; - case format_opt: format_index = parse_format_type( arg ); break; case verbose_opt: if( verbosity < 4 ) ++verbosity; break; case bz2_opt: parse_compressor( arg, fmt_bz2, 1 ); break; case gz_opt: parse_compressor( arg, fmt_gz, 1 ); break; diff --git a/zcatgrep.cc b/zcatgrep.cc new file mode 100644 index 0000000..08cd181 --- /dev/null +++ b/zcatgrep.cc @@ -0,0 +1,57 @@ +/* Common code for zcat and zgrep + Copyright (C) 2010-2015 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 2 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/>. +*/ + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + + +int simple_extension_index( const std::string & name ) + { + for( int i = 0; i < num_formats; ++i ) + { + const std::string ext( simple_extensions[i] ); + if( name.size() > ext.size() && + name.compare( name.size() - ext.size(), ext.size(), ext ) == 0 ) + return i; + } + return -1; + } + + +int open_instream( std::string & input_filename, const bool search, + const bool no_messages = false ) + { + int infd = open( input_filename.c_str(), O_RDONLY | O_BINARY ); + if( infd < 0 ) + { + if( search && simple_extension_index( input_filename ) < 0 ) + { + for( int i = 0; i < num_formats; ++i ) + if( enabled_format( format_order[i] ) ) + { + const std::string name( input_filename + + simple_extensions[format_order[i]] ); + infd = open( name.c_str(), O_RDONLY | O_BINARY ); + if( infd >= 0 ) { input_filename = name; break; } + } + } + if( infd < 0 && !no_messages ) + show_error2( "Can't open input file", input_filename.c_str() ); + } + return infd; + } @@ -1,5 +1,5 @@ /* Zcmp - decompress and compare two files byte by byte - Copyright (C) 2010-2014 Antonio Diaz Diaz. + Copyright (C) 2010-2015 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 @@ -68,21 +68,22 @@ void show_help() " standard input.\n" "\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n" "\nOptions:\n" - " -h, --help display this help and exit\n" - " -V, --version output version information and exit\n" - " -b, --print-bytes print differing bytes\n" - " --format=[<fmt1>][,<fmt2>] force given formats (bz2, gz, lz, xz)\n" - " -i, --ignore-initial=<n>[,<n2>] ignore differences in the first <n> bytes\n" - " -l, --list list position, value of all differing bytes\n" - " -n, --bytes=<n> compare at most <n> bytes\n" - " -N, --no-rcfile don't read runtime configuration file\n" - " -q, --quiet suppress all messages\n" - " -s, --silent (same as --quiet)\n" - " -v, --verbose verbose mode (same as --list)\n" - " --bz2=<command> set compressor and options for bzip2 format\n" - " --gz=<command> set compressor and options for gzip format\n" - " --lz=<command> set compressor and options for lzip format\n" - " --xz=<command> set compressor and options for xz format\n" + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n" + " -b, --print-bytes print differing bytes\n" + " -i, --ignore-initial=<n>[,<n2>] ignore differences in the first <n> bytes\n" + " -l, --list list position, value of all differing bytes\n" + " -M, --format=<list> exclude formats not in <list>\n" + " -n, --bytes=<n> compare at most <n> bytes\n" + " -N, --no-rcfile don't read runtime configuration file\n" + " -O, --force-format=[<f1>][,<f2>] force given formats (bz2, gz, lz, xz)\n" + " -q, --quiet suppress all messages\n" + " -s, --silent (same as --quiet)\n" + " -v, --verbose verbose mode (same as --list)\n" + " --bz2=<command> set compressor and options for bzip2 format\n" + " --gz=<command> set compressor and options for gzip format\n" + " --lz=<command> set compressor and options for lzip format\n" + " --xz=<command> set compressor and options for xz format\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" ); show_help_addr(); @@ -311,7 +312,7 @@ int cmp( const long long max_size, const int infd[2], int main( const int argc, const char * const argv[] ) { - enum { format_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt }; + enum { bz2_opt = 256, gz_opt, lz_opt, xz_opt }; // number of initial bytes ignored for each file long long ignore_initial[2] = { 0, 0 }; long long max_size = -1; // < 0 means unlimited size @@ -326,13 +327,14 @@ int main( const int argc, const char * const argv[] ) { 'h', "help", Arg_parser::no }, { 'i', "ignore-initial", Arg_parser::yes }, { 'l', "list", Arg_parser::no }, + { 'M', "format", Arg_parser::yes }, { 'n', "bytes", Arg_parser::yes }, { 'N', "no-rcfile", Arg_parser::no }, + { 'O', "force-format", Arg_parser::yes }, { 'q', "quiet", Arg_parser::no }, { 's', "silent", Arg_parser::no }, { 'v', "verbose", Arg_parser::no }, { 'V', "version", Arg_parser::no }, - { format_opt, "format", Arg_parser::yes }, { bz2_opt, "bz2", Arg_parser::yes }, { gz_opt, "gz", Arg_parser::yes }, { lz_opt, "lz", Arg_parser::yes }, @@ -350,20 +352,21 @@ int main( const int argc, const char * const argv[] ) { const int code = parser.code( argind ); if( !code ) break; // no more options - const char * const arg = parser.argument( argind ).c_str(); + const std::string & arg = parser.argument( argind ); switch( code ) { case 'b': print_bytes = true; break; case 'h': show_help(); return 0; - case 'i': parse_ignore_initial( arg, ignore_initial ); break; + case 'i': parse_ignore_initial( arg.c_str(), ignore_initial ); break; case 'l': verbosity = 1; break; - case 'n': max_size = getnum( arg ); break; + case 'M': parse_format_list( arg ); break; + case 'n': max_size = getnum( arg.c_str() ); break; case 'N': break; + case 'O': parse_format_types2( arg, format_types ); break; case 'q': case 's': verbosity = -1; break; case 'v': verbosity = 1; break; case 'V': show_version(); return 0; - case format_opt: parse_format_types( arg, format_types ); break; case bz2_opt: parse_compressor( arg, fmt_bz2 ); break; case gz_opt: parse_compressor( arg, fmt_gz ); break; case lz_opt: parse_compressor( arg, fmt_lz ); break; diff --git a/zcmpdiff.cc b/zcmpdiff.cc index 70fa986..524b863 100644 --- a/zcmpdiff.cc +++ b/zcmpdiff.cc @@ -1,5 +1,5 @@ /* Common code for zcmp and zdiff - Copyright (C) 2010-2014 Antonio Diaz Diaz. + Copyright (C) 2010-2015 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 @@ -19,18 +19,6 @@ #define 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 ) { @@ -43,28 +31,26 @@ int open_instream( const std::string & input_filename ) 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; } + const int eindex = extension_index( name ); + if( eindex >= 0 && enabled_format( -1 ) ) + { // open uncompressed version + name.resize( name.size() - std::strlen( extension_from( eindex ) ) ); + name += extension_to( eindex ); + return open( name.c_str(), O_RDONLY | O_BINARY ); } + if( eindex < 0 ) + for( int i = 0; i < num_formats; ++i ) + if( enabled_format( format_order[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 parse_format_types( const std::string & arg, int format_types[2] ) +void parse_format_types2( const std::string & arg, int format_types[2] ) { const unsigned i = std::min( arg.find( ',' ), arg.size() ); if( i > 0 ) format_types[0] = parse_format_type( arg.substr( 0, i ) ); @@ -1,5 +1,5 @@ /* Zdiff - decompress and compare two files line by line - Copyright (C) 2010-2014 Antonio Diaz Diaz. + Copyright (C) 2010-2015 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 @@ -66,30 +66,31 @@ void show_help() " standard input.\n" "\nExit status is 0 if inputs are identical, 1 if different, 2 if trouble.\n" "\nOptions:\n" - " -h, --help display this help and exit\n" - " -V, --version output version information and exit\n" - " -a, --text treat all files as text\n" - " -b, --ignore-space-change ignore changes in the amount of white space\n" - " -B, --ignore-blank-lines ignore changes whose lines are all blank\n" - " -c use the context output format\n" - " -C, --context=<n> same as -c but use <n> lines of context\n" - " -d, --minimal try hard to find a smaller set of changes\n" - " -E, --ignore-tab-expansion ignore changes due to tab expansion\n" - " --format=[<fmt1>][,<fmt2>] force given formats (bz2, gz, lz, xz)\n" - " -i, --ignore-case ignore case differences in file contents\n" - " -N, --no-rcfile don't read runtime configuration file\n" - " -p, --show-c-function show which C function each change is in\n" - " -q, --brief output only whether files differ\n" - " -s, --report-identical-files report when two files are identical\n" - " -t, --expand-tabs expand tabs to spaces in output\n" - " -T, --initial-tab make tabs line up by prepending a tab\n" - " -u use the unified output format\n" - " -U, --unified=<n> same as -u but use <n> lines of context\n" - " -w, --ignore-all-space ignore all white space\n" - " --bz2=<command> set compressor and options for bzip2 format\n" - " --gz=<command> set compressor and options for gzip format\n" - " --lz=<command> set compressor and options for lzip format\n" - " --xz=<command> set compressor and options for xz format\n" + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n" + " -a, --text treat all files as text\n" + " -b, --ignore-space-change ignore changes in the amount of white space\n" + " -B, --ignore-blank-lines ignore changes whose lines are all blank\n" + " -c use the context output format\n" + " -C, --context=<n> same as -c but use <n> lines of context\n" + " -d, --minimal try hard to find a smaller set of changes\n" + " -E, --ignore-tab-expansion ignore changes due to tab expansion\n" + " -i, --ignore-case ignore case differences in file contents\n" + " -M, --format=<list> exclude formats not in <list>\n" + " -N, --no-rcfile don't read runtime configuration file\n" + " -O, --force-format=[<f1>][,<f2>] force given formats (bz2, gz, lz, xz)\n" + " -p, --show-c-function show which C function each change is in\n" + " -q, --brief output only whether files differ\n" + " -s, --report-identical-files report when two files are identical\n" + " -t, --expand-tabs expand tabs to spaces in output\n" + " -T, --initial-tab make tabs line up by prepending a tab\n" + " -u use the unified output format\n" + " -U, --unified=<n> same as -u but use <n> lines of context\n" + " -w, --ignore-all-space ignore all white space\n" + " --bz2=<command> set compressor and options for bzip2 format\n" + " --gz=<command> set compressor and options for gzip format\n" + " --lz=<command> set compressor and options for lzip format\n" + " --xz=<command> set compressor and options for xz format\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" ); show_help_addr(); @@ -113,27 +114,23 @@ extern "C" void remove_fifos() } -// Set fifonames[i] to "${TMPDIR}/<coded_pid><i>_<basename(filenames[i])>" +// Set fifonames[i] to "${TMPDIR}/<coded_pid>[_-]<basename(filenames[i])>" // and create FIFOs. bool set_fifonames( const std::string filenames[2] ) { enum { num_codes = 36 }; const char * const codes = "0123456789abcdefghijklmnopqrstuvwxyz"; const char * p = std::getenv( "TMPDIR" ); - const int pid = getpid(); - for( int i = 0; i < 2; ++i ) - { - if( p ) fifonames[i] = p; else fifonames[i] = "/tmp"; - fifonames[i] += '/'; - int n = ( 2 * pid ) + i; - const unsigned pos = fifonames[i].size(); - do { fifonames[i].insert( pos, 1, codes[n % num_codes] ); - n /= num_codes; } - while( n ); - fifonames[i] += '_'; - fifonames[i] += my_basename( filenames[i].c_str() ); - } + if( p ) { fifonames[0] = p; fifonames[0] += '/'; } + else fifonames[0] = "/tmp/"; + int n = getpid(); + const unsigned pos = fifonames[0].size(); + do fifonames[0].insert( pos, 1, codes[n % num_codes] ); + while( n /= num_codes ); + fifonames[1] = fifonames[0]; + fifonames[0] += '_'; fifonames[0] += my_basename( filenames[0].c_str() ); + fifonames[1] += '-'; fifonames[1] += my_basename( filenames[1].c_str() ); for( int i = 0; i < 2; ++i ) if( mkfifo( fifonames[i].c_str(), S_IRUSR | S_IWUSR ) != 0 ) @@ -263,7 +260,7 @@ void set_signals() int main( const int argc, const char * const argv[] ) { - enum { format_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt }; + enum { bz2_opt = 256, gz_opt, lz_opt, xz_opt }; std::vector< const char * > diff_args; // args to diff, maybe empty int format_types[2] = { -1, -1 }; invocation_name = argv[0]; @@ -280,7 +277,9 @@ int main( const int argc, const char * const argv[] ) { 'E', "ignore-tab-expansion", Arg_parser::no }, { 'h', "help", Arg_parser::no }, { 'i', "ignore-case", Arg_parser::no }, + { 'M', "format", Arg_parser::yes }, { 'N', "no-rcfile", Arg_parser::no }, + { 'O', "force-format", Arg_parser::yes }, { 'p', "show-c-function", Arg_parser::no }, { 'q', "brief", Arg_parser::no }, { 's', "report-identical-files", Arg_parser::no }, @@ -290,7 +289,6 @@ int main( const int argc, const char * const argv[] ) { 'U', "unified", Arg_parser::yes }, { 'V', "version", Arg_parser::no }, { 'w', "ignore-all-space", Arg_parser::no }, - { format_opt, "format", Arg_parser::yes }, { bz2_opt, "bz2", Arg_parser::yes }, { gz_opt, "gz", Arg_parser::yes }, { lz_opt, "lz", Arg_parser::yes }, @@ -308,29 +306,32 @@ int main( const int argc, const char * const argv[] ) { const int code = parser.code( argind ); if( !code ) break; // no more options - const char * const arg = parser.argument( argind ).c_str(); + const std::string & arg = parser.argument( argind ); switch( code ) { case 'a': diff_args.push_back( "-a" ); break; case 'b': diff_args.push_back( "-b" ); break; case 'B': diff_args.push_back( "-B" ); break; case 'c': diff_args.push_back( "-c" ); break; - case 'C': diff_args.push_back( "-C" ); diff_args.push_back( arg ); break; + case 'C': diff_args.push_back( "-C" ); + diff_args.push_back( arg.c_str() ); break; case 'd': diff_args.push_back( "-d" ); break; case 'E': diff_args.push_back( "-E" ); break; case 'h': show_help(); return 0; case 'i': diff_args.push_back( "-i" ); break; + case 'M': parse_format_list( arg ); break; case 'N': break; + case 'O': parse_format_types2( arg, format_types ); break; case 'p': diff_args.push_back( "-p" ); break; case 'q': diff_args.push_back( "-q" ); break; case 's': diff_args.push_back( "-s" ); break; case 't': diff_args.push_back( "-t" ); break; case 'T': diff_args.push_back( "-T" ); break; case 'u': diff_args.push_back( "-u" ); break; - 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.c_str() ); break; case 'V': show_version(); return 0; case 'w': diff_args.push_back( "-w" ); break; - case format_opt: parse_format_types( arg, format_types ); break; case bz2_opt: parse_compressor( arg, fmt_bz2 ); break; case gz_opt: parse_compressor( arg, fmt_gz ); break; case lz_opt: parse_compressor( arg, fmt_lz ); break; @@ -1,5 +1,5 @@ /* Zgrep - search compressed files for a regular expression - Copyright (C) 2010-2014 Antonio Diaz Diaz. + Copyright (C) 2010-2015 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 @@ -39,14 +39,11 @@ #include "rc.h" #include "zutils.h" -#ifndef O_BINARY -#define O_BINARY 0 -#endif - namespace { #include "recursive.cc" +#include "zcatgrep.cc" void show_help() { @@ -75,7 +72,6 @@ void show_help() " -E, --extended-regexp <pattern> is an extended regular expression\n" " -f, --file=<file> obtain patterns from <file>\n" " -F, --fixed-strings <pattern> is a set of newline-separated strings\n" - " --format=<fmt> force given format (bz2, gz, lz, xz)\n" " -h, --no-filename suppress the prefixing filename on output\n" " -H, --with-filename print the filename for each match\n" " -i, --ignore-case ignore case distinctions\n" @@ -83,9 +79,11 @@ void show_help() " -l, --files-with-matches only print names of files containing matches\n" " -L, --files-without-match only print names of files containing no matches\n" " -m, --max-count=<n> stop after <n> matches\n" + " -M, --format=<list> exclude formats not in <list>\n" " -n, --line-number print the line number of each line\n" " -N, --no-rcfile don't read runtime configuration file\n" " -o, --only-matching show only the part of a line matching <pattern>\n" + " -O, --force-format=<fmt> force given format (bz2, gz, lz, xz)\n" " -q, --quiet suppress all messages\n" " -r, --recursive operate recursively on directories\n" " -s, --no-messages suppress error messages\n" @@ -101,42 +99,6 @@ void show_help() } -int simple_extension_index( const std::string & name ) - { - for( int i = 0; i < num_formats; ++i ) - { - const std::string ext( simple_extensions[i] ); - if( name.size() > ext.size() && - name.compare( name.size() - ext.size(), ext.size(), ext ) == 0 ) - return i; - } - return -1; - } - - -int open_instream( std::string & input_filename, - const bool no_messages, const bool search ) - { - int infd = open( input_filename.c_str(), O_RDONLY | O_BINARY ); - if( infd < 0 ) - { - if( search && simple_extension_index( input_filename ) < 0 ) - { - for( int i = 0; i < num_formats; ++i ) - { - const std::string name( input_filename + - simple_extensions[format_order[i]] ); - infd = open( name.c_str(), O_RDONLY | O_BINARY ); - if( infd >= 0 ) { input_filename = name; break; } - } - } - if( infd < 0 && !no_messages ) - show_error2( "Can't open input file", input_filename.c_str() ); - } - return infd; - } - - int zgrep_stdin( int infd, const int format_index, const std::vector< const char * > & grep_args ) { @@ -243,13 +205,11 @@ int zgrep_file( int infd, const int format_index, int main( const int argc, const char * const argv[] ) { - enum { format_opt = 256, help_opt, verbose_opt, - bz2_opt, gz_opt, lz_opt, xz_opt }; + enum { help_opt = 256, verbose_opt, bz2_opt, gz_opt, lz_opt, xz_opt }; int format_index = -1; int infd = -1; int list_mode = 0; // 1 = list matches, -1 = list non matches int show_name = -1; // tri-state bool - bool error = false; bool no_messages = false; bool recursive = false; std::string input_filename; @@ -277,9 +237,11 @@ int main( const int argc, const char * const argv[] ) { 'l', "files-with-matches", Arg_parser::no }, // grep { 'L', "files-without-match", Arg_parser::no }, // grep GNU { 'm', "max-count", Arg_parser::yes }, // grep GNU + { 'M', "format", Arg_parser::yes }, { 'n', "line-number", Arg_parser::no }, // grep { 'N', "no-rcfile", Arg_parser::no }, { 'o', "only-matching", Arg_parser::no }, // grep + { 'O', "force-format", Arg_parser::yes }, { 'q', "quiet", Arg_parser::no }, { 'r', "recursive", Arg_parser::no }, { 's', "no-messages", Arg_parser::no }, // grep @@ -287,7 +249,6 @@ int main( const int argc, const char * const argv[] ) { 'V', "version", Arg_parser::no }, { 'w', "word-regexp", Arg_parser::no }, // grep GNU { 'x', "line-regexp", Arg_parser::no }, // grep - { format_opt, "format", Arg_parser::yes }, { help_opt, "help", Arg_parser::no }, { verbose_opt, "verbose", Arg_parser::no }, { bz2_opt, "bz2", Arg_parser::yes }, @@ -307,26 +268,24 @@ int main( const int argc, const char * const argv[] ) for( ; argind < parser.arguments(); ++argind ) { const int code = parser.code( argind ); - const char * const arg = parser.argument( argind ).c_str(); - if( !code ) - { - if( !pattern_found ) - { grep_args.push_back( arg ); pattern_found = true; continue; } - else break; // no more options - } + if( !code ) break; // no more options + const std::string & arg = parser.argument( argind ); switch( code ) { case 'a': grep_args.push_back( "-a" ); break; - case 'A': grep_args.push_back( "-A" ); grep_args.push_back( arg ); break; + case 'A': grep_args.push_back( "-A" ); + grep_args.push_back( arg.c_str() ); break; case 'b': grep_args.push_back( "-b" ); break; - case 'B': grep_args.push_back( "-B" ); grep_args.push_back( arg ); break; + case 'B': grep_args.push_back( "-B" ); + grep_args.push_back( arg.c_str() ); break; case 'c': grep_args.push_back( "-c" ); break; - case 'C': grep_args.push_back( "-C" ); grep_args.push_back( arg ); break; - case 'e': grep_args.push_back( "-e" ); grep_args.push_back( arg ); - pattern_found = true; break; + case 'C': grep_args.push_back( "-C" ); + grep_args.push_back( arg.c_str() ); break; + case 'e': grep_args.push_back( "-e" ); + grep_args.push_back( arg.c_str() ); pattern_found = true; break; case 'E': grep_args.push_back( "-E" ); break; - case 'f': grep_args.push_back( "-f" ); grep_args.push_back( arg ); - pattern_found = true; break; + case 'f': grep_args.push_back( "-f" ); + grep_args.push_back( arg.c_str() ); pattern_found = true; break; case 'F': grep_args.push_back( "-F" ); break; case 'h': show_name = false; break; case 'H': show_name = true; break; @@ -334,10 +293,13 @@ int main( const int argc, const char * const argv[] ) case 'I': grep_args.push_back( "-I" ); break; case 'l': grep_args.push_back( "-l" ); list_mode = 1; break; case 'L': grep_args.push_back( "-L" ); list_mode = -1; break; - case 'm': grep_args.push_back( "-m" ); grep_args.push_back( arg ); break; + case 'm': grep_args.push_back( "-m" ); + grep_args.push_back( arg.c_str() ); break; + case 'M': parse_format_list( arg ); break; case 'n': grep_args.push_back( "-n" ); break; case 'N': break; case 'o': grep_args.push_back( "-o" ); break; + case 'O': format_index = parse_format_type( arg ); break; case 'q': grep_args.push_back( "-q" ); verbosity = -1; break; case 'r': recursive = true; break; case 's': grep_args.push_back( "-s" ); no_messages = true; break; @@ -345,7 +307,6 @@ int main( const int argc, const char * const argv[] ) case 'V': show_version(); return 0; case 'w': grep_args.push_back( "-w" ); break; case 'x': grep_args.push_back( "-x" ); break; - case format_opt : format_index = parse_format_type( arg ); break; case help_opt : show_help(); return 0; case verbose_opt: if( verbosity < 4 ) ++verbosity; no_messages = false; break; @@ -362,7 +323,14 @@ int main( const int argc, const char * const argv[] ) setmode( STDOUT_FILENO, O_BINARY ); #endif - if( !pattern_found ) { show_error( "Pattern not found." ); return 2; } + if( !pattern_found ) + { + if( argind >= parser.arguments() ) + { show_error( "Pattern not found." ); return 2; } + const std::string & arg = parser.argument( argind++ ); + if( arg.size() && arg[0] == '-' ) grep_args.push_back( "-e" ); + grep_args.push_back( arg.c_str() ); + } for( ; argind < parser.arguments(); ++argind ) filenames.push_back( parser.argument( argind ) ); @@ -372,13 +340,14 @@ int main( const int argc, const char * const argv[] ) if( show_name < 0 ) show_name = ( filenames.size() != 1 || recursive ); int retval = 1; + bool error = false; while( next_filename( filenames, input_filename, error, recursive, false, no_messages ) ) { if( input_filename.empty() ) infd = STDIN_FILENO; else { - infd = open_instream( input_filename, no_messages, format_index < 0 ); + infd = open_instream( input_filename, format_index < 0, no_messages ); if( infd < 0 ) { error = true; continue; } } @@ -1,5 +1,5 @@ /* Ztest - verify integrity of compressed files - Copyright (C) 2010-2014 Antonio Diaz Diaz. + Copyright (C) 2010-2015 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 @@ -64,8 +64,9 @@ void show_help() "\nOptions:\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" + " -M, --format=<list> exclude formats not in <list>\n" " -N, --no-rcfile don't read runtime configuration file\n" + " -O, --force-format=<fmt> force given format (bz2, gz, lz, xz)\n" " -q, --quiet suppress all messages\n" " -r, --recursive operate recursively on directories\n" " -v, --verbose be verbose (a 2nd -v gives more)\n" @@ -77,7 +78,7 @@ void show_help() } -int open_instream( std::string & input_filename ) +int open_instream( const std::string & input_filename ) { const int infd = open( input_filename.c_str(), O_RDONLY | O_BINARY ); if( infd < 0 ) @@ -204,7 +205,7 @@ int ztest_file( const int infd, int format_index, int main( const int argc, const char * const argv[] ) { - enum { format_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt }; + enum { bz2_opt = 256, gz_opt, lz_opt, xz_opt }; int infd = -1; int format_index = -1; bool recursive = false; @@ -217,12 +218,13 @@ int main( const int argc, const char * const argv[] ) const Arg_parser::Option options[] = { { 'h', "help", Arg_parser::no }, + { 'M', "format", Arg_parser::yes }, { 'N', "no-rcfile", Arg_parser::no }, + { 'O', "force-format", Arg_parser::yes }, { 'q', "quiet", Arg_parser::no }, { 'r', "recursive", Arg_parser::no }, { 'v', "verbose", Arg_parser::no }, { 'V', "version", Arg_parser::no }, - { format_opt, "format", Arg_parser::yes }, { bz2_opt, "bz2", Arg_parser::yes }, { gz_opt, "gz", Arg_parser::yes }, { lz_opt, "lz", Arg_parser::yes }, @@ -240,17 +242,18 @@ int main( const int argc, const char * const argv[] ) { const int code = parser.code( argind ); if( !code ) break; // no more options - const char * const arg = parser.argument( argind ).c_str(); + const std::string & arg = parser.argument( argind ); switch( code ) { case 'h': show_help(); return 0; + case 'M': parse_format_list( arg ); break; case 'N': break; + case 'O': format_index = parse_format_type( arg ); break; case 'q': verbosity = -1; ztest_args.push_back( "-q" ); break; case 'r': recursive = true; break; case 'v': if( verbosity < 4 ) ++verbosity; ztest_args.push_back( "-v" ); break; case 'V': show_version(); return 0; - case format_opt: format_index = parse_format_type( arg ); break; case bz2_opt: parse_compressor( arg, fmt_bz2, 1 ); break; case gz_opt: parse_compressor( arg, fmt_gz, 1 ); break; case lz_opt: parse_compressor( arg, fmt_lz, 1 ); break; @@ -1,5 +1,5 @@ /* Zupdate - recompress bzip2, gzip, xz files to lzip files - Copyright (C) 2013, 2014 Antonio Diaz Diaz. + Copyright (C) 2013-2015 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 @@ -75,6 +75,7 @@ void show_help() " -f, --force do not skip a file even if the .lz exists\n" " -k, --keep keep (don't delete) input files\n" " -l, --lzip-verbose pass a -v option to the lzip compressor\n" + " -M, --format=<list> exclude formats not in <list>\n" " -N, --no-rcfile don't read runtime configuration file\n" " -q, --quiet suppress all messages\n" " -r, --recursive operate recursively on directories\n" @@ -124,47 +125,29 @@ void set_permissions( const char * const rname, const struct stat & in_stats ) } -struct { const char * from; const char * to; int format_index; } const - known_extensions[] = { - { ".bz2", "", fmt_bz2 }, - { ".tbz", ".tar", fmt_bz2 }, - { ".tbz2", ".tar", fmt_bz2 }, - { ".gz", "", fmt_gz }, - { ".tgz", ".tar", fmt_gz }, - { ".lz", "", fmt_lz }, - { ".tlz", ".tar", fmt_lz }, - { ".xz", "", fmt_xz }, - { ".txz", ".tar", fmt_xz }, - { 0, 0, -1 } }; - - // Returns 0 for success, -1 for file skipped, 1 for error. int zupdate_file( const std::string & name, const char * const lzip_name, const std::vector< std::string > & lzip_args2, - const bool force, const bool keep_input_files ) + const bool force, const bool keep_input_files, + const bool no_rcfile ) { static int disable_xz = -1; // tri-state bool int format_index = -1; std::string dname; // decompressed_name - for( int i = 0; known_extensions[i].from; ++i ) // search extension + const int eindex = extension_index( name ); // search extension + if( eindex >= 0 ) { - const std::string from( known_extensions[i].from ); - if( name.size() > from.size() && - name.compare( name.size() - from.size(), from.size(), from ) == 0 ) + format_index = extension_format( eindex ); + if( format_index == fmt_lz ) { - dname.assign( name, 0, name.size() - from.size() ); - dname += known_extensions[i].to; - format_index = known_extensions[i].format_index; - if( format_index == fmt_lz ) - { - if( verbosity >= 2 ) - std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", - program_name, name.c_str(), known_extensions[i].from ); - return 0; // ignore this file - } - break; + if( verbosity >= 2 ) + std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", + program_name, name.c_str(), extension_from( eindex ) ); + return 0; // ignore this file } + dname.assign( name, 0, name.size() - std::strlen( extension_from( eindex ) ) ); + dname += extension_to( eindex ); } const char * const compressor_name = get_compressor_name( format_index ); if( !compressor_name ) @@ -285,6 +268,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name, while( i > 0 && zcmp_command[i-1] != '/' ) --i; zcmp_command.resize( i ); zcmp_command += "zcmp "; // ${bindir}zcmp + if( no_rcfile ) zcmp_command += "-N "; zcmp_command += name; zcmp_command += ' '; zcmp_command += rname; int status = std::system( zcmp_command.c_str() ); if( status != 0 ) @@ -313,6 +297,7 @@ int main( const int argc, const char * const argv[] ) std::vector< std::string > lzip_args2; // args to lzip, maybe empty bool force = false; bool keep_input_files = false; + bool no_rcfile = false; bool recursive = false; invocation_name = argv[0]; program_name = "zupdate"; @@ -333,6 +318,7 @@ int main( const int argc, const char * const argv[] ) { 'h', "help", Arg_parser::no }, { 'k', "keep", Arg_parser::no }, { 'l', "lzip-verbose", Arg_parser::no }, + { 'M', "format", Arg_parser::yes }, { 'N', "no-rcfile", Arg_parser::no }, { 'q', "quiet", Arg_parser::no }, { 'r', "recursive", Arg_parser::no }, @@ -355,7 +341,7 @@ int main( const int argc, const char * const argv[] ) { const int code = parser.code( argind ); if( !code ) break; // no more options - const char * const arg = parser.argument( argind ).c_str(); + const std::string & arg = parser.argument( argind ); switch( code ) { case '0': case '1': case '2': case '3': case '4': @@ -365,7 +351,8 @@ int main( const int argc, const char * const argv[] ) case 'h': show_help(); return 0; case 'k': keep_input_files = true; break; case 'l': lzip_args2.push_back( "-v" ); break; - case 'N': break; + case 'M': parse_format_list( arg ); break; + case 'N': no_rcfile = true; break; case 'q': verbosity = -1; lzip_args2.push_back( "-q" ); break; case 'r': recursive = true; break; case 'v': if( verbosity < 4 ) ++verbosity; break; @@ -395,7 +382,7 @@ int main( const int argc, const char * const argv[] ) while( next_filename( filenames, input_filename, error, recursive, true ) ) { int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, force, - keep_input_files ); + keep_input_files, no_rcfile ); if( tmp < 0 ) error = true; if( tmp > retval ) retval = tmp; if( tmp > 0 ) break; @@ -1,5 +1,5 @@ /* Zutils - Utilities dealing with compressed files - Copyright (C) 2009-2014 Antonio Diaz Diaz. + Copyright (C) 2009-2015 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 @@ -75,16 +75,6 @@ int child_status( const pid_t pid, const char * const name ) } // end namespace -int parse_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. // If (returned value < size) and (errno == 0), means EOF was reached. // @@ -1,5 +1,5 @@ /* Zutils - Utilities dealing with compressed files - Copyright (C) 2009-2014 Antonio Diaz Diaz. + Copyright (C) 2009-2015 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 @@ -15,8 +15,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -int parse_format_type( const std::string & arg ); - 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, |