1
0
Fork 0

Merging upstream version 1.4~pre2.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-24 05:51:15 +01:00
parent 454cd28d9e
commit 06e5e699b7
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
30 changed files with 802 additions and 552 deletions

View file

@ -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

View file

@ -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.

View file

@ -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)

18
NEWS
View file

@ -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.

14
README
View file

@ -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.

View file

@ -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>

View file

@ -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

6
configure vendored
View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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'
@ -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,11 +514,6 @@ 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 file names on output when multiple files
@ -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

View file

@ -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
@ -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,11 +568,6 @@ 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 file names on output when multiple files are
@ -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

153
rc.cc
View file

@ -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;
}

11
rc.h
View file

@ -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;

View file

@ -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;

View file

@ -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=bz2 in.lz 2> /dev/null
"${ZCAT}" -N --format=, 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 --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 --force-format=bz2 in.lz 2> /dev/null
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
"${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 --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=bz2 in.bz2 2> /dev/null
if [ $? = 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 > /dev/null || fail=1
printf .
"${ZGREP}" -N "GNU" < in.gz > /dev/null || fail=1
printf .
"${ZGREP}" -N "GNU" < in.bz2 > /dev/null || fail=1
printf .
"${ZGREP}" -N "GNU" < in.lz > /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."

55
zcat.cc
View file

@ -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;

57
zcatgrep.cc Normal file
View file

@ -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;
}

19
zcmp.cc
View file

@ -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
@ -71,11 +71,12 @@ void show_help()
" -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"
" -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"
@ -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;

View file

@ -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,18 +31,16 @@ 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;
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 );
@ -64,7 +50,7 @@ int open_other_instream( std::string & name )
}
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 ) );

View file

@ -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
@ -75,9 +75,10 @@ void show_help()
" -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"
" -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"
@ -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;

View file

@ -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; }
}

View file

@ -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;

View file

@ -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 )
{
dname.assign( name, 0, name.size() - from.size() );
dname += known_extensions[i].to;
format_index = known_extensions[i].format_index;
format_index = extension_format( eindex );
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 );
program_name, name.c_str(), extension_from( eindex ) );
return 0; // ignore this file
}
break;
}
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;

View file

@ -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.
//

View file

@ -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,