Adding upstream version 1.2~pre3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
c9a98be648
commit
cac35a934f
32 changed files with 1172 additions and 1035 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2013-10-11 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.2-pre3 released.
|
||||||
|
* Removed zutils executable. Utils are now independent executables.
|
||||||
|
* zupdate.cc: Added new option '-k, --keep'.
|
||||||
|
* zupdate.cc: Ignore xz files if xz compressor is not installed.
|
||||||
|
* zgrep.cc: Fixed the exit status returned on error.
|
||||||
|
|
||||||
2013-09-04 Antonio Diaz Diaz <antonio@gnu.org>
|
2013-09-04 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
* Version 1.2-pre2 released.
|
* Version 1.2-pre2 released.
|
||||||
|
|
76
Makefile.in
76
Makefile.in
|
@ -7,28 +7,26 @@ INSTALL_DATA = $(INSTALL) -p -m 644
|
||||||
INSTALL_DIR = $(INSTALL) -d -m 755
|
INSTALL_DIR = $(INSTALL) -d -m 755
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
|
|
||||||
objs = arg_parser.o rc.o zutils.o main.o
|
objs = arg_parser.o rc.o zutils.o \
|
||||||
|
zcat.o zcmp.o zdiff.o zgrep.o ztest.o zupdate.o
|
||||||
|
zcat_objs = arg_parser.o rc.o zutils.o zcat.o
|
||||||
zcmp_objs = arg_parser.o rc.o zutils.o zcmp.o
|
zcmp_objs = arg_parser.o rc.o zutils.o zcmp.o
|
||||||
zdiff_objs = arg_parser.o rc.o zutils.o zdiff.o
|
zdiff_objs = arg_parser.o rc.o zutils.o zdiff.o
|
||||||
zupdate_objs = arg_parser.o rc.o zutils.o zupdate.o
|
zgrep_objs = arg_parser.o rc.o zutils.o zgrep.o
|
||||||
scripts = zcat zegrep zfgrep zgrep ztest
|
ztest_objs = arg_parser.o rc.o zutils.o ztest.o
|
||||||
|
zupdate_objs = arg_parser.o rc.o zupdate.o
|
||||||
|
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 \
|
||||||
uninstall uninstall-bin uninstall-info uninstall-man \
|
uninstall uninstall-bin uninstall-info uninstall-man \
|
||||||
doc info man check dist clean distclean
|
doc info man check dist clean distclean
|
||||||
|
|
||||||
all : $(progname) zcmp zdiff zupdate $(scripts)
|
all : $(programs) $(scripts)
|
||||||
|
|
||||||
$(progname) : $(objs)
|
zcat : $(zcat_objs)
|
||||||
$(CXX) $(LDFLAGS) -o $@ $(objs)
|
$(CXX) $(LDFLAGS) -o $@ $(zcat_objs)
|
||||||
|
|
||||||
$(progname)_profiled : $(objs)
|
|
||||||
$(CXX) $(LDFLAGS) -pg -o $@ $(objs)
|
|
||||||
|
|
||||||
zcat : zcat.in
|
|
||||||
cat $(VPATH)/zcat.in > $@
|
|
||||||
chmod a+x zcat
|
|
||||||
|
|
||||||
zcmp : $(zcmp_objs)
|
zcmp : $(zcmp_objs)
|
||||||
$(CXX) $(LDFLAGS) -o $@ $(zcmp_objs)
|
$(CXX) $(LDFLAGS) -o $@ $(zcmp_objs)
|
||||||
|
@ -44,28 +42,23 @@ zfgrep : zfgrep.in
|
||||||
cat $(VPATH)/zfgrep.in > $@
|
cat $(VPATH)/zfgrep.in > $@
|
||||||
chmod a+x zfgrep
|
chmod a+x zfgrep
|
||||||
|
|
||||||
zgrep : zgrep.in
|
zgrep : $(zgrep_objs)
|
||||||
cat $(VPATH)/zgrep.in > $@
|
$(CXX) $(LDFLAGS) -o $@ $(zgrep_objs)
|
||||||
chmod a+x zgrep
|
|
||||||
|
|
||||||
ztest : ztest.in
|
ztest : $(ztest_objs)
|
||||||
cat $(VPATH)/ztest.in > $@
|
$(CXX) $(LDFLAGS) -o $@ $(ztest_objs)
|
||||||
chmod a+x ztest
|
|
||||||
|
|
||||||
zupdate : $(zupdate_objs)
|
zupdate : $(zupdate_objs)
|
||||||
$(CXX) $(LDFLAGS) -o $@ $(zupdate_objs)
|
$(CXX) $(LDFLAGS) -o $@ $(zupdate_objs)
|
||||||
|
|
||||||
main.o : main.cc
|
rc.o : rc.cc
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DGREP=\"$(GREP)\" -c -o $@ $<
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -DSYSCONFDIR=\"$(sysconfdir)\" -c -o $@ $<
|
||||||
|
|
||||||
zdiff.o : zdiff.cc
|
zdiff.o : zdiff.cc
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DDIFF=\"$(DIFF)\" -c -o $@ $<
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DDIFF=\"$(DIFF)\" -c -o $@ $<
|
||||||
|
|
||||||
rc.o : rc.cc
|
zgrep.o : zgrep.cc
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DSYSCONFDIR=\"$(sysconfdir)\" -c -o $@ $<
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DGREP=\"$(GREP)\" -c -o $@ $<
|
||||||
|
|
||||||
zutils.o : zutils.cc
|
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $<
|
|
||||||
|
|
||||||
%.o : %.cc
|
%.o : %.cc
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
@ -73,12 +66,14 @@ zutils.o : zutils.cc
|
||||||
$(objs) : Makefile
|
$(objs) : Makefile
|
||||||
$(scripts) : Makefile
|
$(scripts) : Makefile
|
||||||
arg_parser.o : arg_parser.h
|
arg_parser.o : arg_parser.h
|
||||||
main.o : arg_parser.h zutils.h rc.h zcat.cc zgrep.cc ztest.cc
|
rc.o : arg_parser.h rc.h
|
||||||
rc.o : arg_parser.h zutils.h rc.h
|
zcat.o : arg_parser.h rc.h zutils.h recursive.cc
|
||||||
zcmp.o : arg_parser.h zutils.h rc.h zcmpdiff.cc Makefile
|
zcmp.o : arg_parser.h rc.h zutils.h zcmpdiff.cc
|
||||||
zdiff.o : arg_parser.h zutils.h rc.h zcmpdiff.cc Makefile
|
zdiff.o : arg_parser.h rc.h zutils.h zcmpdiff.cc
|
||||||
zupdate.o : arg_parser.h zutils.h rc.h Makefile
|
zgrep.o : arg_parser.h rc.h zutils.h recursive.cc
|
||||||
zutils.o : zutils.h rc.h
|
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
|
||||||
|
|
||||||
|
|
||||||
doc : info man
|
doc : info man
|
||||||
|
@ -91,7 +86,7 @@ $(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texinfo
|
||||||
man : $(VPATH)/doc/zcat.1 $(VPATH)/doc/zcmp.1 $(VPATH)/doc/zdiff.1 \
|
man : $(VPATH)/doc/zcat.1 $(VPATH)/doc/zcmp.1 $(VPATH)/doc/zdiff.1 \
|
||||||
$(VPATH)/doc/zgrep.1 $(VPATH)/doc/ztest.1 $(VPATH)/doc/zupdate.1
|
$(VPATH)/doc/zgrep.1 $(VPATH)/doc/ztest.1 $(VPATH)/doc/zupdate.1
|
||||||
|
|
||||||
$(VPATH)/doc/zcat.1 : $(progname) zcat
|
$(VPATH)/doc/zcat.1 : zcat
|
||||||
help2man -n 'decompress and concatenate files to standard output' \
|
help2man -n 'decompress and concatenate files to standard output' \
|
||||||
-o $@ --no-info ./zcat
|
-o $@ --no-info ./zcat
|
||||||
|
|
||||||
|
@ -103,11 +98,11 @@ $(VPATH)/doc/zdiff.1 : zdiff
|
||||||
help2man -n 'decompress and compare two files line by line' \
|
help2man -n 'decompress and compare two files line by line' \
|
||||||
-o $@ --no-info ./zdiff
|
-o $@ --no-info ./zdiff
|
||||||
|
|
||||||
$(VPATH)/doc/zgrep.1 : $(progname) zgrep
|
$(VPATH)/doc/zgrep.1 : zgrep
|
||||||
help2man -n 'search compressed files for a regular expression' \
|
help2man -n 'search compressed files for a regular expression' \
|
||||||
-o $@ --no-info ./zgrep
|
-o $@ --no-info ./zgrep
|
||||||
|
|
||||||
$(VPATH)/doc/ztest.1 : $(progname) ztest
|
$(VPATH)/doc/ztest.1 : ztest
|
||||||
help2man -n 'verify integrity of compressed files' \
|
help2man -n 'verify integrity of compressed files' \
|
||||||
-o $@ --no-info ./ztest
|
-o $@ --no-info ./ztest
|
||||||
|
|
||||||
|
@ -125,14 +120,13 @@ install : install-bin install-info install-man
|
||||||
|
|
||||||
install-bin : all
|
install-bin : all
|
||||||
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
|
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
|
||||||
$(INSTALL_PROGRAM) ./$(progname) "$(DESTDIR)$(bindir)/$(progname)"
|
$(INSTALL_PROGRAM) ./zcat "$(DESTDIR)$(bindir)/zcat"
|
||||||
$(INSTALL_SCRIPT) ./zcat "$(DESTDIR)$(bindir)/zcat"
|
|
||||||
$(INSTALL_PROGRAM) ./zcmp "$(DESTDIR)$(bindir)/zcmp"
|
$(INSTALL_PROGRAM) ./zcmp "$(DESTDIR)$(bindir)/zcmp"
|
||||||
$(INSTALL_PROGRAM) ./zdiff "$(DESTDIR)$(bindir)/zdiff"
|
$(INSTALL_PROGRAM) ./zdiff "$(DESTDIR)$(bindir)/zdiff"
|
||||||
$(INSTALL_SCRIPT) ./zegrep "$(DESTDIR)$(bindir)/zegrep"
|
$(INSTALL_SCRIPT) ./zegrep "$(DESTDIR)$(bindir)/zegrep"
|
||||||
$(INSTALL_SCRIPT) ./zfgrep "$(DESTDIR)$(bindir)/zfgrep"
|
$(INSTALL_SCRIPT) ./zfgrep "$(DESTDIR)$(bindir)/zfgrep"
|
||||||
$(INSTALL_SCRIPT) ./zgrep "$(DESTDIR)$(bindir)/zgrep"
|
$(INSTALL_PROGRAM) ./zgrep "$(DESTDIR)$(bindir)/zgrep"
|
||||||
$(INSTALL_SCRIPT) ./ztest "$(DESTDIR)$(bindir)/ztest"
|
$(INSTALL_PROGRAM) ./ztest "$(DESTDIR)$(bindir)/ztest"
|
||||||
$(INSTALL_PROGRAM) ./zupdate "$(DESTDIR)$(bindir)/zupdate"
|
$(INSTALL_PROGRAM) ./zupdate "$(DESTDIR)$(bindir)/zupdate"
|
||||||
if [ ! -e "$(DESTDIR)$(sysconfdir)/$(pkgname)rc" ] ; then \
|
if [ ! -e "$(DESTDIR)$(sysconfdir)/$(pkgname)rc" ] ; then \
|
||||||
if [ ! -d "$(DESTDIR)$(sysconfdir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(sysconfdir)" ; fi ; \
|
if [ ! -d "$(DESTDIR)$(sysconfdir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(sysconfdir)" ; fi ; \
|
||||||
|
@ -159,7 +153,6 @@ install-strip : all
|
||||||
uninstall : uninstall-bin uninstall-info uninstall-man
|
uninstall : uninstall-bin uninstall-info uninstall-man
|
||||||
|
|
||||||
uninstall-bin :
|
uninstall-bin :
|
||||||
-rm -f "$(DESTDIR)$(bindir)/$(progname)"
|
|
||||||
-rm -f "$(DESTDIR)$(bindir)/zcat"
|
-rm -f "$(DESTDIR)$(bindir)/zcat"
|
||||||
-rm -f "$(DESTDIR)$(bindir)/zcmp"
|
-rm -f "$(DESTDIR)$(bindir)/zcmp"
|
||||||
-rm -f "$(DESTDIR)$(bindir)/zdiff"
|
-rm -f "$(DESTDIR)$(bindir)/zdiff"
|
||||||
|
@ -207,8 +200,7 @@ dist : doc
|
||||||
lzip -v -9 $(DISTNAME).tar
|
lzip -v -9 $(DISTNAME).tar
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
-rm -f $(progname) $(progname)_profiled $(objs)
|
-rm -f $(programs) $(scripts) $(objs)
|
||||||
-rm -f zcmp zcmp.o zdiff zdiff.o zupdate zupdate.o $(scripts)
|
|
||||||
|
|
||||||
distclean : clean
|
distclean : clean
|
||||||
-rm -f Makefile config.status *.tar *.tar.lz
|
-rm -f Makefile config.status *.tar *.tar.lz
|
||||||
|
|
5
NEWS
5
NEWS
|
@ -1,4 +1,9 @@
|
||||||
Changes in version 1.2:
|
Changes in version 1.2:
|
||||||
|
|
||||||
|
The zutils executable has been removed. All utilities are now
|
||||||
|
independent executables.
|
||||||
|
|
||||||
The new utility zupdate, which recompresses bzip2, gzip and xz files to
|
The new utility zupdate, which recompresses bzip2, gzip and xz files to
|
||||||
lzip format, has been added.
|
lzip format, has been added.
|
||||||
|
|
||||||
|
The exit status of zgrep should now be identical to that of grep.
|
||||||
|
|
7
README
7
README
|
@ -10,16 +10,17 @@ These utilities are not wrapper scripts but safer and more efficient C++
|
||||||
programs. In particular the "--recursive" option is very efficient in
|
programs. In particular the "--recursive" option is very efficient in
|
||||||
those utilities supporting it.
|
those utilities supporting it.
|
||||||
|
|
||||||
The provided utilities are zcat, zcmp, zdiff, zgrep and ztest.
|
The provided utilities are zcat, zcmp, zdiff, zgrep, ztest and zupdate.
|
||||||
The supported formats are bzip2, gzip, lzip and xz.
|
The supported formats are bzip2, gzip, lzip and xz.
|
||||||
The compressor to be used for each format is configurable at runtime.
|
The compressor to be used for each format is configurable at runtime.
|
||||||
|
|
||||||
Zcat, zcmp, zdiff, and zgrep are improved replacements for the shell
|
Zcat, zcmp, zdiff, and zgrep are improved replacements for the shell
|
||||||
scripts provided with GNU gzip. Ztest is unique to zutils.
|
scripts provided with GNU gzip. Ztest is unique to zutils. Zupdate is
|
||||||
|
similar to gzip's znew.
|
||||||
|
|
||||||
NOTE: Bzip2 and lzip provide well-defined values of exit status, which
|
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
|
makes them safe to use with zutils. Gzip and xz may return ambiguous
|
||||||
warning values, making them less reliable backends for zutils.
|
warning values, making them less reliable back ends for zutils.
|
||||||
|
|
||||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
|
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
|
||||||
have been compressed. Decompressed is used to refer to data which has
|
have been compressed. Decompressed is used to refer to data which has
|
||||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -6,8 +6,7 @@
|
||||||
# to copy, distribute and modify it.
|
# to copy, distribute and modify it.
|
||||||
|
|
||||||
pkgname=zutils
|
pkgname=zutils
|
||||||
pkgversion=1.2-pre2
|
pkgversion=1.2-pre3
|
||||||
progname=zutils
|
|
||||||
srctrigger=doc/${pkgname}.texinfo
|
srctrigger=doc/${pkgname}.texinfo
|
||||||
|
|
||||||
# clear some things potentially inherited from environment.
|
# clear some things potentially inherited from environment.
|
||||||
|
@ -186,7 +185,6 @@ cat > Makefile << EOF
|
||||||
|
|
||||||
pkgname = ${pkgname}
|
pkgname = ${pkgname}
|
||||||
pkgversion = ${pkgversion}
|
pkgversion = ${pkgversion}
|
||||||
progname = ${progname}
|
|
||||||
VPATH = ${srcdir}
|
VPATH = ${srcdir}
|
||||||
prefix = ${prefix}
|
prefix = ${prefix}
|
||||||
exec_prefix = ${exec_prefix}
|
exec_prefix = ${exec_prefix}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZCAT "1" "September 2013" "Zcat (zutils) 1.2-pre2" "User Commands"
|
.TH ZCAT "1" "October 2013" "Zcat (zutils) 1.2-pre3" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zcat \- decompress and concatenate files to standard output
|
Zcat \- decompress and concatenate files to standard output
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZCMP "1" "September 2013" "Zcmp (zutils) 1.2-pre2" "User Commands"
|
.TH ZCMP "1" "October 2013" "Zcmp (zutils) 1.2-pre3" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zcmp \- decompress and compare two files byte by byte
|
Zcmp \- decompress and compare two files byte by byte
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZDIFF "1" "September 2013" "Zdiff (zutils) 1.2-pre2" "User Commands"
|
.TH ZDIFF "1" "October 2013" "Zdiff (zutils) 1.2-pre3" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zdiff \- decompress and compare two files line by line
|
Zdiff \- decompress and compare two files line by line
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZGREP "1" "September 2013" "Zgrep (zutils) 1.2-pre2" "User Commands"
|
.TH ZGREP "1" "October 2013" "Zgrep (zutils) 1.2-pre3" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zgrep \- search compressed files for a regular expression
|
Zgrep \- search compressed files for a regular expression
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZTEST "1" "September 2013" "Ztest (zutils) 1.2-pre2" "User Commands"
|
.TH ZTEST "1" "October 2013" "Ztest (zutils) 1.2-pre3" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Ztest \- verify integrity of compressed files
|
Ztest \- verify integrity of compressed files
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH ZUPDATE "1" "September 2013" "Zupdate (zutils) 1.2-pre2" "User Commands"
|
.TH ZUPDATE "1" "October 2013" "Zupdate (zutils) 1.2-pre3" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Zupdate \- recompress bzip2, gzip, xz files to lzip files
|
Zupdate \- recompress bzip2, gzip, xz files to lzip files
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -35,6 +35,9 @@ output version information and exit
|
||||||
\fB\-f\fR, \fB\-\-force\fR
|
\fB\-f\fR, \fB\-\-force\fR
|
||||||
do not skip a file even if the .lz exists
|
do not skip a file even if the .lz exists
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-k\fR, \fB\-\-keep\fR
|
||||||
|
keep (don't delete) input files
|
||||||
|
.TP
|
||||||
\fB\-l\fR, \fB\-\-lzip\-verbose\fR
|
\fB\-l\fR, \fB\-\-lzip\-verbose\fR
|
||||||
pass a \fB\-v\fR option to the lzip compressor
|
pass a \fB\-v\fR option to the lzip compressor
|
||||||
.TP
|
.TP
|
||||||
|
|
419
doc/zutils.info
419
doc/zutils.info
|
@ -1,4 +1,4 @@
|
||||||
This is zutils.info, produced by makeinfo version 4.13 from
|
This is zutils.info, produced by makeinfo version 4.13+ from
|
||||||
zutils.texinfo.
|
zutils.texinfo.
|
||||||
|
|
||||||
INFO-DIR-SECTION Data Compression
|
INFO-DIR-SECTION Data Compression
|
||||||
|
@ -12,7 +12,7 @@ File: zutils.info, Node: Top, Next: Introduction, Up: (dir)
|
||||||
Zutils Manual
|
Zutils Manual
|
||||||
*************
|
*************
|
||||||
|
|
||||||
This manual is for Zutils (version 1.2-pre2, 4 September 2013).
|
This manual is for Zutils (version 1.2-pre3, 11 October 2013).
|
||||||
|
|
||||||
* Menu:
|
* Menu:
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ used. Compressed files are decompressed on the fly; no temporary files
|
||||||
are created.
|
are created.
|
||||||
|
|
||||||
These utilities are not wrapper scripts but safer and more efficient
|
These utilities are not wrapper scripts but safer and more efficient
|
||||||
C++ programs. In particular the `--recursive' option is very efficient
|
C++ programs. In particular the '--recursive' option is very efficient
|
||||||
in those utilities supporting it.
|
in those utilities supporting it.
|
||||||
|
|
||||||
The provided utilities are zcat, zcmp, zdiff, zgrep, ztest and zupdate.
|
The provided utilities are zcat, zcmp, zdiff, zgrep, ztest and zupdate.
|
||||||
|
@ -60,7 +60,8 @@ similar to gzip's znew.
|
||||||
|
|
||||||
NOTE: Bzip2 and lzip provide well-defined values of exit status,
|
NOTE: Bzip2 and lzip provide well-defined values of exit status,
|
||||||
which makes them safe to use with zutils. Gzip and xz may return
|
which makes them safe to use with zutils. Gzip and xz may return
|
||||||
ambiguous warning values, making them less reliable backends for zutils.
|
ambiguous warning values, making them less reliable back ends for
|
||||||
|
zutils.
|
||||||
|
|
||||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may
|
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may
|
||||||
never have been compressed. Decompressed is used to refer to data which
|
never have been compressed. Decompressed is used to refer to data which
|
||||||
|
@ -68,7 +69,7 @@ has undergone the process of decompression.
|
||||||
|
|
||||||
|
|
||||||
Numbers given as arguments to options (positions, sizes) may be
|
Numbers given as arguments to options (positions, sizes) may be
|
||||||
followed by a multiplier and an optional `B' for "byte".
|
followed by a multiplier and an optional 'B' for "byte".
|
||||||
|
|
||||||
Table of SI and binary prefixes (unit multipliers):
|
Table of SI and binary prefixes (unit multipliers):
|
||||||
|
|
||||||
|
@ -92,33 +93,33 @@ The following options are available in all the utilities. Rather than
|
||||||
writing identical descriptions for each of the programs, they are
|
writing identical descriptions for each of the programs, they are
|
||||||
described here.
|
described here.
|
||||||
|
|
||||||
`-h'
|
'-h'
|
||||||
`--help'
|
'--help'
|
||||||
Print an informative help message describing the options and exit.
|
Print an informative help message describing the options and exit.
|
||||||
Zgrep only supports the `--help' form of this option.
|
Zgrep only supports the '--help' form of this option.
|
||||||
|
|
||||||
`-V'
|
'-V'
|
||||||
`--version'
|
'--version'
|
||||||
Print the version number on the standard output and exit.
|
Print the version number on the standard output and exit.
|
||||||
|
|
||||||
`-N'
|
'-N'
|
||||||
`--no-rcfile'
|
'--no-rcfile'
|
||||||
Don't read the runtime configuration file `zutilsrc'.
|
Don't read the runtime configuration file 'zutilsrc'.
|
||||||
|
|
||||||
`--bz2=COMMAND'
|
'--bz2=COMMAND'
|
||||||
`--gz=COMMAND'
|
'--gz=COMMAND'
|
||||||
`--lz=COMMAND'
|
'--lz=COMMAND'
|
||||||
`--xz=COMMAND'
|
'--xz=COMMAND'
|
||||||
Set program (may include arguments) to be used as (de)compressor
|
Set program (may include arguments) to be used as (de)compressor
|
||||||
for the given format. These options override the values set in
|
for the given format. These options override the values set in
|
||||||
`zutilsrc'. The compression program used must meet three
|
'zutilsrc'. The compression program used must meet three
|
||||||
requirements:
|
requirements:
|
||||||
|
|
||||||
1. When called with the `-d' option, it must read compressed
|
1. When called with the '-d' option, it must read compressed
|
||||||
data from the standard input and produce decompressed data on
|
data from the standard input and produce decompressed data on
|
||||||
the standard output.
|
the standard output.
|
||||||
|
|
||||||
2. If the `-q' option is passed to zutils, the compression
|
2. If the '-q' option is passed to zutils, the compression
|
||||||
program must also accept it.
|
program must also accept it.
|
||||||
|
|
||||||
3. It must return 0 if no errors occurred, and a non-zero value
|
3. It must return 0 if no errors occurred, and a non-zero value
|
||||||
|
@ -131,24 +132,24 @@ File: zutils.info, Node: The zutilsrc file, Next: Zcat, Prev: Common options,
|
||||||
3 The zutilsrc file
|
3 The zutilsrc file
|
||||||
*******************
|
*******************
|
||||||
|
|
||||||
`zutilsrc' is the runtime configuration file for zutils. In it you may
|
'zutilsrc' is the runtime configuration file for zutils. In it you may
|
||||||
define the compressor name and options to be used for each format. The
|
define the compressor name and options to be used for each format. The
|
||||||
`zutilsrc' file is optional; you do not need to install it in order to
|
'zutilsrc' file is optional; you do not need to install it in order to
|
||||||
run zutils.
|
run zutils.
|
||||||
|
|
||||||
The compressors specified in the command line override those
|
The compressors specified in the command line override those
|
||||||
specified in the `zutilsrc' file.
|
specified in the 'zutilsrc' file.
|
||||||
|
|
||||||
You may copy the system `zutilsrc' file `${sysconfdir}/zutilsrc' to
|
You may copy the system 'zutilsrc' file '${sysconfdir}/zutilsrc' to
|
||||||
`$HOME/.zutilsrc' and customize these options as you like. The file
|
'$HOME/.zutilsrc' and customize these options as you like. The file
|
||||||
syntax is fairly obvious (and there are further instructions in it):
|
syntax is fairly obvious (and there are further instructions in it):
|
||||||
|
|
||||||
1. Any line beginning with `#' is a comment line.
|
1. Any line beginning with '#' is a comment line.
|
||||||
|
|
||||||
2. Each non-comment line defines the command to be used for the given
|
2. Each non-comment line defines the command to be used for the given
|
||||||
format, with the syntax:
|
format, with the syntax:
|
||||||
<format> = <compressor> [options]
|
<format> = <compressor> [options]
|
||||||
where <format> is one of `bz2', `gz', `lz' or `xz'.
|
where <format> is one of 'bz2', 'gz', 'lz' or 'xz'.
|
||||||
|
|
||||||
|
|
||||||
File: zutils.info, Node: Zcat, Next: Zcmp, Prev: The zutilsrc file, Up: Top
|
File: zutils.info, Node: Zcat, Next: Zcmp, Prev: The zutilsrc file, Up: Top
|
||||||
|
@ -156,7 +157,7 @@ File: zutils.info, Node: Zcat, Next: Zcmp, Prev: The zutilsrc file, Up: Top
|
||||||
4 Zcat
|
4 Zcat
|
||||||
******
|
******
|
||||||
|
|
||||||
Zcat copies each given file (`-' means standard input), to standard
|
Zcat copies each given file ('-' means standard input), to standard
|
||||||
output. If any given file is compressed, its decompressed content is
|
output. If any given file is compressed, its decompressed content is
|
||||||
used. If a given file does not exist, and its name does not end with one
|
used. If a given file does not exist, and its name does not end with one
|
||||||
of the known extensions, zcat tries the compressed file names
|
of the known extensions, zcat tries the compressed file names
|
||||||
|
@ -175,58 +176,58 @@ Exit status is 0 if no errors occurred, non-zero otherwise.
|
||||||
|
|
||||||
Zcat supports the following options:
|
Zcat supports the following options:
|
||||||
|
|
||||||
`-A'
|
'-A'
|
||||||
`--show-all'
|
'--show-all'
|
||||||
Equivalent to `-vET'.
|
Equivalent to '-vET'.
|
||||||
|
|
||||||
`-b'
|
'-b'
|
||||||
`--number-nonblank'
|
'--number-nonblank'
|
||||||
Number all nonblank output lines, starting with 1. The line count
|
Number all nonblank output lines, starting with 1. The line count
|
||||||
is unlimited.
|
is unlimited.
|
||||||
|
|
||||||
`-e'
|
'-e'
|
||||||
Equivalent to `-vE'.
|
Equivalent to '-vE'.
|
||||||
|
|
||||||
`-E'
|
'-E'
|
||||||
`--show-ends'
|
'--show-ends'
|
||||||
Print a `$' after the end of each line.
|
Print a '$' after the end of each line.
|
||||||
|
|
||||||
`--format=FMT'
|
'--format=FMT'
|
||||||
Force the given compression format. Valid values for FMT are
|
Force the given compression format. Valid values for FMT are
|
||||||
`bz2', `gz', `lz' and `xz'. If this option is used, the exact file
|
'bz2', 'gz', 'lz' and 'xz'. If this option is used, the exact file
|
||||||
name must be given. Other names won't be tried.
|
name must be given. Other names won't be tried.
|
||||||
|
|
||||||
`-n'
|
'-n'
|
||||||
`--number'
|
'--number'
|
||||||
Number all output lines, starting with 1. The line count is
|
Number all output lines, starting with 1. The line count is
|
||||||
unlimited.
|
unlimited.
|
||||||
|
|
||||||
`-q'
|
'-q'
|
||||||
`--quiet'
|
'--quiet'
|
||||||
Quiet operation. Suppress all messages.
|
Quiet operation. Suppress all messages.
|
||||||
|
|
||||||
`-r'
|
'-r'
|
||||||
`--recursive'
|
'--recursive'
|
||||||
Operate recursively on directories.
|
Operate recursively on directories.
|
||||||
|
|
||||||
`-s'
|
'-s'
|
||||||
`--squeeze-blank'
|
'--squeeze-blank'
|
||||||
Replace multiple adjacent blank lines with a single blank line.
|
Replace multiple adjacent blank lines with a single blank line.
|
||||||
|
|
||||||
`-t'
|
'-t'
|
||||||
Equivalent to `-vT'.
|
Equivalent to '-vT'.
|
||||||
|
|
||||||
`-T'
|
'-T'
|
||||||
`--show-tabs'
|
'--show-tabs'
|
||||||
Print TAB characters as `^I'.
|
Print TAB characters as '^I'.
|
||||||
|
|
||||||
`-v'
|
'-v'
|
||||||
`--show-nonprinting'
|
'--show-nonprinting'
|
||||||
Print control characters except for LF (newline) and TAB using `^'
|
Print control characters except for LF (newline) and TAB using '^'
|
||||||
notation and precede characters larger than 127 with `M-' (which
|
notation and precede characters larger than 127 with 'M-' (which
|
||||||
stands for "meta").
|
stands for "meta").
|
||||||
|
|
||||||
`--verbose'
|
'--verbose'
|
||||||
Verbose mode. Show error messages.
|
Verbose mode. Show error messages.
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,7 +237,7 @@ File: zutils.info, Node: Zcmp, Next: Zdiff, Prev: Zcat, Up: Top
|
||||||
5 Zcmp
|
5 Zcmp
|
||||||
******
|
******
|
||||||
|
|
||||||
Zcmp compares two files (`-' means standard input), and if they differ,
|
Zcmp compares two files ('-' means standard input), and if they differ,
|
||||||
tells the first byte and line number where they differ. Bytes and lines
|
tells the first byte and line number where they differ. Bytes and lines
|
||||||
are numbered starting with 1. If any given file is compressed, its
|
are numbered starting with 1. If any given file is compressed, its
|
||||||
decompressed content is used. Compressed files are decompressed on the
|
decompressed content is used. Compressed files are decompressed on the
|
||||||
|
@ -264,43 +265,43 @@ differences were found, and 2 means trouble.
|
||||||
|
|
||||||
Zcmp supports the following options:
|
Zcmp supports the following options:
|
||||||
|
|
||||||
`-b'
|
'-b'
|
||||||
`--print-bytes'
|
'--print-bytes'
|
||||||
Print the differing bytes. Print control bytes as a `^' followed by
|
Print the differing bytes. Print control bytes as a '^' followed by
|
||||||
a letter, and precede bytes larger than 127 with `M-' (which stands
|
a letter, and precede bytes larger than 127 with 'M-' (which stands
|
||||||
for "meta").
|
for "meta").
|
||||||
|
|
||||||
`--format=[FMT1][,FMT2]'
|
'--format=[FMT1][,FMT2]'
|
||||||
Force the given compression formats. Any of FMT1 or FMT2 may be
|
Force the given compression formats. Any of FMT1 or FMT2 may be
|
||||||
omitted and the corresponding format will be automatically
|
omitted and the corresponding format will be automatically
|
||||||
detected. Valid values for FMT are `bz2', `gz', `lz' and `xz'. If
|
detected. Valid values for FMT are 'bz2', 'gz', 'lz' and 'xz'. If
|
||||||
at least one format is specified with this option, the exact file
|
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
|
names of both FILE1 and FILE2 must be given. Other names won't be
|
||||||
tried.
|
tried.
|
||||||
|
|
||||||
`-i SIZE'
|
'-i SIZE'
|
||||||
`--ignore-initial=SIZE'
|
'--ignore-initial=SIZE'
|
||||||
Ignore any differences in the first SIZE bytes of the input files.
|
Ignore any differences in the first SIZE bytes of the input files.
|
||||||
Treat files with fewer than SIZE bytes as if they were empty. If
|
Treat files with fewer than SIZE bytes as if they were empty. If
|
||||||
SIZE is in the form `SIZE1,SIZE2', ignore the first SIZE1 bytes of
|
SIZE is in the form 'SIZE1,SIZE2', ignore the first SIZE1 bytes of
|
||||||
the first input file and the first SIZE2 bytes of the second input
|
the first input file and the first SIZE2 bytes of the second input
|
||||||
file.
|
file.
|
||||||
|
|
||||||
`-l'
|
'-l'
|
||||||
`-v'
|
'-v'
|
||||||
`--list'
|
'--list'
|
||||||
`--verbose'
|
'--verbose'
|
||||||
Print the byte numbers (in decimal) and values (in octal) of all
|
Print the byte numbers (in decimal) and values (in octal) of all
|
||||||
differing bytes.
|
differing bytes.
|
||||||
|
|
||||||
`-n COUNT'
|
'-n COUNT'
|
||||||
`--bytes=COUNT'
|
'--bytes=COUNT'
|
||||||
Compare at most COUNT input bytes.
|
Compare at most COUNT input bytes.
|
||||||
|
|
||||||
`-q'
|
'-q'
|
||||||
`-s'
|
'-s'
|
||||||
`--quiet'
|
'--quiet'
|
||||||
`--silent'
|
'--silent'
|
||||||
Do not print anything; only return an exit status indicating
|
Do not print anything; only return an exit status indicating
|
||||||
whether the files differ.
|
whether the files differ.
|
||||||
|
|
||||||
|
@ -311,7 +312,7 @@ File: zutils.info, Node: Zdiff, Next: Zgrep, Prev: Zcmp, Up: Top
|
||||||
6 Zdiff
|
6 Zdiff
|
||||||
*******
|
*******
|
||||||
|
|
||||||
Zdiff compares two files (`-' means standard input), and if they
|
Zdiff compares two files ('-' means standard input), and if they
|
||||||
differ, shows the differences line by line. If any given file is
|
differ, shows the differences line by line. If any given file is
|
||||||
compressed, its decompressed content is used. Zdiff is a front end to
|
compressed, its decompressed content is used. Zdiff is a front end to
|
||||||
the diff program and has the limitation that messages from diff refer to
|
the diff program and has the limitation that messages from diff refer to
|
||||||
|
@ -339,74 +340,74 @@ differences were found, and 2 means trouble.
|
||||||
|
|
||||||
Zdiff supports the following options:
|
Zdiff supports the following options:
|
||||||
|
|
||||||
`-a'
|
'-a'
|
||||||
`--text'
|
'--text'
|
||||||
Treat all files as text.
|
Treat all files as text.
|
||||||
|
|
||||||
`-b'
|
'-b'
|
||||||
`--ignore-space-change'
|
'--ignore-space-change'
|
||||||
Ignore changes in the amount of white space.
|
Ignore changes in the amount of white space.
|
||||||
|
|
||||||
`-B'
|
'-B'
|
||||||
`--ignore-blank-lines'
|
'--ignore-blank-lines'
|
||||||
Ignore changes whose lines are all blank.
|
Ignore changes whose lines are all blank.
|
||||||
|
|
||||||
`-c'
|
'-c'
|
||||||
Use the context output format.
|
Use the context output format.
|
||||||
|
|
||||||
`-C N'
|
'-C N'
|
||||||
`--context=N'
|
'--context=N'
|
||||||
Same as -c but use N lines of context.
|
Same as -c but use N lines of context.
|
||||||
|
|
||||||
`-d'
|
'-d'
|
||||||
`--minimal'
|
'--minimal'
|
||||||
Try hard to find a smaller set of changes.
|
Try hard to find a smaller set of changes.
|
||||||
|
|
||||||
`-E'
|
'-E'
|
||||||
`--ignore-tab-expansion'
|
'--ignore-tab-expansion'
|
||||||
Ignore changes due to tab expansion.
|
Ignore changes due to tab expansion.
|
||||||
|
|
||||||
`--format=[FMT1][,FMT2]'
|
'--format=[FMT1][,FMT2]'
|
||||||
Force the given compression formats. Any of FMT1 or FMT2 may be
|
Force the given compression formats. Any of FMT1 or FMT2 may be
|
||||||
omitted and the corresponding format will be automatically
|
omitted and the corresponding format will be automatically
|
||||||
detected. Valid values for FMT are `bz2', `gz', `lz' and `xz'. If
|
detected. Valid values for FMT are 'bz2', 'gz', 'lz' and 'xz'. If
|
||||||
at least one format is specified with this option, the exact file
|
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
|
names of both FILE1 and FILE2 must be given. Other names won't be
|
||||||
tried.
|
tried.
|
||||||
|
|
||||||
`-i'
|
'-i'
|
||||||
`--ignore-case'
|
'--ignore-case'
|
||||||
Ignore case differences in file contents.
|
Ignore case differences in file contents.
|
||||||
|
|
||||||
`-p'
|
'-p'
|
||||||
`--show-c-function'
|
'--show-c-function'
|
||||||
Show which C function each change is in.
|
Show which C function each change is in.
|
||||||
|
|
||||||
`-q'
|
'-q'
|
||||||
`--brief'
|
'--brief'
|
||||||
Output only whether files differ.
|
Output only whether files differ.
|
||||||
|
|
||||||
`-s'
|
'-s'
|
||||||
`--report-identical-files'
|
'--report-identical-files'
|
||||||
Report when two files are identical.
|
Report when two files are identical.
|
||||||
|
|
||||||
`-t'
|
'-t'
|
||||||
`--expand-tabs'
|
'--expand-tabs'
|
||||||
Expand tabs to spaces in output.
|
Expand tabs to spaces in output.
|
||||||
|
|
||||||
`-T'
|
'-T'
|
||||||
`--initial-tab'
|
'--initial-tab'
|
||||||
Make tabs line up by prepending a tab.
|
Make tabs line up by prepending a tab.
|
||||||
|
|
||||||
`-u'
|
'-u'
|
||||||
Use the unified output format.
|
Use the unified output format.
|
||||||
|
|
||||||
`-U N'
|
'-U N'
|
||||||
`--unified=N'
|
'--unified=N'
|
||||||
Same as -u but use N lines of context.
|
Same as -u but use N lines of context.
|
||||||
|
|
||||||
`-w'
|
'-w'
|
||||||
`--ignore-all-space'
|
'--ignore-all-space'
|
||||||
Ignore all white space.
|
Ignore all white space.
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,112 +438,113 @@ matches were found, and 2 means trouble.
|
||||||
|
|
||||||
Zgrep supports the following options:
|
Zgrep supports the following options:
|
||||||
|
|
||||||
`-a'
|
'-a'
|
||||||
`--text'
|
'--text'
|
||||||
Treat all files as text.
|
Treat all files as text.
|
||||||
|
|
||||||
`-A N'
|
'-A N'
|
||||||
`--after-context=N'
|
'--after-context=N'
|
||||||
Print N lines of trailing context.
|
Print N lines of trailing context.
|
||||||
|
|
||||||
`-b'
|
'-b'
|
||||||
`--byte-offset'
|
'--byte-offset'
|
||||||
Print the byte offset of each line.
|
Print the byte offset of each line.
|
||||||
|
|
||||||
`-B N'
|
'-B N'
|
||||||
`--before-context=N'
|
'--before-context=N'
|
||||||
Print N lines of leading context.
|
Print N lines of leading context.
|
||||||
|
|
||||||
`-c'
|
'-c'
|
||||||
`--count'
|
'--count'
|
||||||
Only print a count of matching lines per file.
|
Only print a count of matching lines per file.
|
||||||
|
|
||||||
`-C N'
|
'-C N'
|
||||||
`--context=N'
|
'--context=N'
|
||||||
Print N lines of output context.
|
Print N lines of output context.
|
||||||
|
|
||||||
`-e PATTERN'
|
'-e PATTERN'
|
||||||
`--regexp=PATTERN'
|
'--regexp=PATTERN'
|
||||||
Use PATTERN as the pattern to match.
|
Use PATTERN as the pattern to match.
|
||||||
|
|
||||||
`-E'
|
'-E'
|
||||||
`--extended-regexp'
|
'--extended-regexp'
|
||||||
Treat PATTERN as an extended regular expression.
|
Treat PATTERN as an extended regular expression.
|
||||||
|
|
||||||
`-f FILE'
|
'-f FILE'
|
||||||
`--file=FILE'
|
'--file=FILE'
|
||||||
Obtain patterns from FILE, one per line.
|
Obtain patterns from FILE, one per line.
|
||||||
|
|
||||||
`-F'
|
'-F'
|
||||||
`--fixed-strings'
|
'--fixed-strings'
|
||||||
Treat PATTERN as a set of newline-separated strings.
|
Treat PATTERN as a set of newline-separated strings.
|
||||||
|
|
||||||
`--format=FMT'
|
'--format=FMT'
|
||||||
Force the given compression format. Valid values for FMT are
|
Force the given compression format. Valid values for FMT are
|
||||||
`bz2', `gz', `lz' and `xz'. If this option is used, the exact file
|
'bz2', 'gz', 'lz' and 'xz'. If this option is used, the exact file
|
||||||
name must be given. Other names won't be tried.
|
name must be given. Other names won't be tried.
|
||||||
|
|
||||||
`-h'
|
'-h'
|
||||||
`--no-filename'
|
'--no-filename'
|
||||||
Suppress the prefixing of filenames on output when multiple files
|
Suppress the prefixing of filenames on output when multiple files
|
||||||
are searched.
|
are searched.
|
||||||
|
|
||||||
`-H'
|
'-H'
|
||||||
`--with-filename'
|
'--with-filename'
|
||||||
Print the filename for each match.
|
Print the filename for each match.
|
||||||
|
|
||||||
`-i'
|
'-i'
|
||||||
`--ignore-case'
|
'--ignore-case'
|
||||||
Ignore case distinctions.
|
Ignore case distinctions.
|
||||||
|
|
||||||
`-I'
|
'-I'
|
||||||
Ignore binary files.
|
Ignore binary files.
|
||||||
|
|
||||||
`-l'
|
'-l'
|
||||||
`--files-with-matches'
|
'--files-with-matches'
|
||||||
Only print names of files containing at least one match.
|
Only print names of files containing at least one match.
|
||||||
|
|
||||||
`-L'
|
'-L'
|
||||||
`--files-without-match'
|
'--files-without-match'
|
||||||
Only print names of files not containing any matches.
|
Only print names of files not containing any matches.
|
||||||
|
|
||||||
`-m N'
|
'-m N'
|
||||||
`--max-count=N'
|
'--max-count=N'
|
||||||
Stop after N matches.
|
Stop after N matches.
|
||||||
|
|
||||||
`-n'
|
'-n'
|
||||||
`--line-number'
|
'--line-number'
|
||||||
Prefix each matched line with its line number in the input file.
|
Prefix each matched line with its line number in the input file.
|
||||||
|
|
||||||
`-o'
|
'-o'
|
||||||
`--only-matching'
|
'--only-matching'
|
||||||
Show only the part of matching lines that actually matches PATTERN.
|
Show only the part of matching lines that actually matches PATTERN.
|
||||||
|
|
||||||
`-q'
|
'-q'
|
||||||
`--quiet'
|
'--quiet'
|
||||||
Suppress all messages.
|
Suppress all messages. Exit immediately with zero status if any
|
||||||
|
match is found, even if an error was detected.
|
||||||
|
|
||||||
`-r'
|
'-r'
|
||||||
`--recursive'
|
'--recursive'
|
||||||
Operate recursively on directories.
|
Operate recursively on directories.
|
||||||
|
|
||||||
`-s'
|
'-s'
|
||||||
`--no-messages'
|
'--no-messages'
|
||||||
Suppress error messages.
|
Suppress error messages about nonexistent or unreadable files.
|
||||||
|
|
||||||
`-v'
|
'-v'
|
||||||
`--invert-match'
|
'--invert-match'
|
||||||
Select non-matching lines.
|
Select non-matching lines.
|
||||||
|
|
||||||
`--verbose'
|
'--verbose'
|
||||||
Verbose mode. Show error messages.
|
Verbose mode. Show error messages.
|
||||||
|
|
||||||
`-w'
|
'-w'
|
||||||
`--word-regexp'
|
'--word-regexp'
|
||||||
Match only whole words.
|
Match only whole words.
|
||||||
|
|
||||||
`-x'
|
'-x'
|
||||||
`--line-regexp'
|
'--line-regexp'
|
||||||
Match only whole lines.
|
Match only whole lines.
|
||||||
|
|
||||||
|
|
||||||
|
@ -570,21 +572,21 @@ environmental problems (file not found, invalid flags, I/O errors, etc),
|
||||||
|
|
||||||
Ztest supports the following options:
|
Ztest supports the following options:
|
||||||
|
|
||||||
`--format=FMT'
|
'--format=FMT'
|
||||||
Force the given compression format. Valid values for FMT are
|
Force the given compression format. Valid values for FMT are
|
||||||
`bz2', `gz', `lz' and `xz'. If this option is used, all files not
|
'bz2', 'gz', 'lz' and 'xz'. If this option is used, all files not
|
||||||
in the given format will fail.
|
in the given format will fail.
|
||||||
|
|
||||||
`-q'
|
'-q'
|
||||||
`--quiet'
|
'--quiet'
|
||||||
Quiet operation. Suppress all messages.
|
Quiet operation. Suppress all messages.
|
||||||
|
|
||||||
`-r'
|
'-r'
|
||||||
`--recursive'
|
'--recursive'
|
||||||
Operate recursively on directories.
|
Operate recursively on directories.
|
||||||
|
|
||||||
`-v'
|
'-v'
|
||||||
`--verbose'
|
'--verbose'
|
||||||
Verbose mode. Show the verify status for each file processed.
|
Verbose mode. Show the verify status for each file processed.
|
||||||
Further -v's increase the verbosity level.
|
Further -v's increase the verbosity level.
|
||||||
|
|
||||||
|
@ -604,15 +606,15 @@ is chosen as destination because it is by far the most appropriate for
|
||||||
long-term data archiving.
|
long-term data archiving.
|
||||||
|
|
||||||
If the lzip compressed version of a file already exists, the file is
|
If the lzip compressed version of a file already exists, the file is
|
||||||
skipped unless the `--force' option is given. In this case, if the
|
skipped unless the '--force' option is given. In this case, if the
|
||||||
comparison fails, an error is returned and the original file is not
|
comparison fails, an error is returned and the original file is not
|
||||||
deleted. The operation of zupdate is meant to be safe and not produce
|
deleted. The operation of zupdate is meant to be safe and not produce
|
||||||
any data loss. Therefore, existing lzip compressed files are never
|
any data loss. Therefore, existing lzip compressed files are never
|
||||||
overwritten nor deleted.
|
overwritten nor deleted.
|
||||||
|
|
||||||
The names of the original files must have one of the following
|
The names of the original files must have one of the following
|
||||||
extensions: `.bz2', `.tbz', `.tbz2', `.gz', `.tgz', `.xz', `.txz'. The
|
extensions: '.bz2', '.tbz', '.tbz2', '.gz', '.tgz', '.xz', '.txz'. The
|
||||||
files produced have the extensions `.lz' or `.tar.lz'.
|
files produced have the extensions '.lz' or '.tar.lz'.
|
||||||
|
|
||||||
The format for running zupdate is:
|
The format for running zupdate is:
|
||||||
|
|
||||||
|
@ -623,35 +625,40 @@ recompressed (if needed), compared and deleted. Non-zero otherwise.
|
||||||
|
|
||||||
Zupdate supports the following options:
|
Zupdate supports the following options:
|
||||||
|
|
||||||
`-f'
|
'-f'
|
||||||
`--force'
|
'--force'
|
||||||
Do not skip a file for which a lzip compressed version already
|
Do not skip a file for which a lzip compressed version already
|
||||||
exists. `--force' compares the content of the input file with the
|
exists. '--force' compares the content of the input file with the
|
||||||
content of the lzip file and deletes the input file if both
|
content of the lzip file and deletes the input file if both
|
||||||
contents are identical.
|
contents are identical.
|
||||||
|
|
||||||
`-l'
|
'-k'
|
||||||
`--lzip-verbose'
|
'--keep'
|
||||||
Pass a `-v' option to the lzip compressor so that it shows the
|
Keep (don't delete) the input file after comparing it with the
|
||||||
compression ratio for each file processed. Using lzip 1.15 and
|
lzip file.
|
||||||
newer, a second `-l' shows the progress of compression. Use it
|
|
||||||
together with `-v' to see the name of the file.
|
|
||||||
|
|
||||||
`-q'
|
'-l'
|
||||||
`--quiet'
|
'--lzip-verbose'
|
||||||
|
Pass a '-v' option to the lzip compressor so that it shows the
|
||||||
|
compression ratio for each file processed. Using lzip 1.15 and
|
||||||
|
newer, a second '-l' shows the progress of compression. Use it
|
||||||
|
together with '-v' to see the name of the file.
|
||||||
|
|
||||||
|
'-q'
|
||||||
|
'--quiet'
|
||||||
Quiet operation. Suppress all messages.
|
Quiet operation. Suppress all messages.
|
||||||
|
|
||||||
`-r'
|
'-r'
|
||||||
`--recursive'
|
'--recursive'
|
||||||
Operate recursively on directories.
|
Operate recursively on directories.
|
||||||
|
|
||||||
`-v'
|
'-v'
|
||||||
`--verbose'
|
'--verbose'
|
||||||
Verbose mode. Show the files being processed. A second `-v' also
|
Verbose mode. Show the files being processed. A second '-v' also
|
||||||
shows the files being ignored.
|
shows the files being ignored.
|
||||||
|
|
||||||
`-0 .. -9'
|
'-0 .. -9'
|
||||||
Set the compression level of lzip. By default zupdate passes `-9'
|
Set the compression level of lzip. By default zupdate passes '-9'
|
||||||
to lzip.
|
to lzip.
|
||||||
|
|
||||||
|
|
||||||
|
@ -668,7 +675,7 @@ for all eternity, if not longer.
|
||||||
|
|
||||||
If you find a bug in zutils, please send electronic mail to
|
If you find a bug in zutils, please send electronic mail to
|
||||||
<zutils-bug@nongnu.org>. Include the version number, which you can find
|
<zutils-bug@nongnu.org>. Include the version number, which you can find
|
||||||
by running `zutils --version'.
|
by running 'zcmp --version'.
|
||||||
|
|
||||||
|
|
||||||
File: zutils.info, Node: Concept index, Prev: Problems, Up: Top
|
File: zutils.info, Node: Concept index, Prev: Problems, Up: Top
|
||||||
|
@ -694,18 +701,18 @@ Concept index
|
||||||
|
|
||||||
|
|
||||||
Tag Table:
|
Tag Table:
|
||||||
Node: Top224
|
Node: Top225
|
||||||
Node: Introduction1156
|
Node: Introduction1156
|
||||||
Node: Common options3258
|
Node: Common options3259
|
||||||
Node: The zutilsrc file4507
|
Node: The zutilsrc file4508
|
||||||
Node: Zcat5433
|
Node: Zcat5434
|
||||||
Node: Zcmp7355
|
Node: Zcmp7356
|
||||||
Node: Zdiff9679
|
Node: Zdiff9680
|
||||||
Node: Zgrep12182
|
Node: Zgrep12183
|
||||||
Node: Ztest15019
|
Node: Ztest15151
|
||||||
Node: Zupdate16243
|
Node: Zupdate16375
|
||||||
Node: Problems18477
|
Node: Problems18708
|
||||||
Node: Concept index19010
|
Node: Concept index19239
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
@finalout
|
@finalout
|
||||||
@c %**end of header
|
@c %**end of header
|
||||||
|
|
||||||
@set UPDATED 4 September 2013
|
@set UPDATED 11 October 2013
|
||||||
@set VERSION 1.2-pre2
|
@set VERSION 1.2-pre3
|
||||||
|
|
||||||
@dircategory Data Compression
|
@dircategory Data Compression
|
||||||
@direntry
|
@direntry
|
||||||
|
@ -80,7 +80,7 @@ similar to gzip's znew.
|
||||||
|
|
||||||
NOTE: Bzip2 and lzip provide well-defined values of exit status, which
|
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
|
makes them safe to use with zutils. Gzip and xz may return ambiguous
|
||||||
warning values, making them less reliable backends for zutils.
|
warning values, making them less reliable back ends for zutils.
|
||||||
|
|
||||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
|
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
|
||||||
have been compressed. Decompressed is used to refer to data which has
|
have been compressed. Decompressed is used to refer to data which has
|
||||||
|
@ -570,7 +570,8 @@ Show only the part of matching lines that actually matches @var{pattern}.
|
||||||
|
|
||||||
@item -q
|
@item -q
|
||||||
@itemx --quiet
|
@itemx --quiet
|
||||||
Suppress all messages.
|
Suppress all messages. Exit immediately with zero status if any match is
|
||||||
|
found, even if an error was detected.
|
||||||
|
|
||||||
@item -r
|
@item -r
|
||||||
@itemx --recursive
|
@itemx --recursive
|
||||||
|
@ -578,7 +579,7 @@ Operate recursively on directories.
|
||||||
|
|
||||||
@item -s
|
@item -s
|
||||||
@itemx --no-messages
|
@itemx --no-messages
|
||||||
Suppress error messages.
|
Suppress error messages about nonexistent or unreadable files.
|
||||||
|
|
||||||
@item -v
|
@item -v
|
||||||
@itemx --invert-match
|
@itemx --invert-match
|
||||||
|
@ -689,6 +690,10 @@ Do not skip a file for which a lzip compressed version already exists.
|
||||||
of the lzip file and deletes the input file if both contents are
|
of the lzip file and deletes the input file if both contents are
|
||||||
identical.
|
identical.
|
||||||
|
|
||||||
|
@item -k
|
||||||
|
@itemx --keep
|
||||||
|
Keep (don't delete) the input file after comparing it with the lzip file.
|
||||||
|
|
||||||
@item -l
|
@item -l
|
||||||
@itemx --lzip-verbose
|
@itemx --lzip-verbose
|
||||||
Pass a @samp{-v} option to the lzip compressor so that it shows the
|
Pass a @samp{-v} option to the lzip compressor so that it shows the
|
||||||
|
@ -728,7 +733,7 @@ for all eternity, if not longer.
|
||||||
|
|
||||||
If you find a bug in zutils, please send electronic mail to
|
If you find a bug in zutils, please send electronic mail to
|
||||||
@email{zutils-bug@@nongnu.org}. Include the version number, which you can
|
@email{zutils-bug@@nongnu.org}. Include the version number, which you can
|
||||||
find by running @w{@samp{zutils --version}}.
|
find by running @w{@samp{zcmp --version}}.
|
||||||
|
|
||||||
|
|
||||||
@node Concept index
|
@node Concept index
|
||||||
|
|
467
main.cc
467
main.cc
|
@ -1,467 +0,0 @@
|
||||||
/* Zutils - Utilities dealing with compressed files
|
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
#include <climits>
|
|
||||||
#include <csignal>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arg_parser.h"
|
|
||||||
#include "zutils.h"
|
|
||||||
#include "rc.h"
|
|
||||||
|
|
||||||
#if CHAR_BIT != 8
|
|
||||||
#error "Environments where CHAR_BIT != 8 are not supported."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
#ifdef O_BINARY
|
|
||||||
const int o_binary = O_BINARY;
|
|
||||||
#else
|
|
||||||
const int o_binary = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum Mode { m_none, m_zcat, m_zgrep, m_ztest };
|
|
||||||
|
|
||||||
|
|
||||||
void show_help()
|
|
||||||
{
|
|
||||||
std::printf( "Zutils is a collection of utilities able to deal with any combination of\n"
|
|
||||||
"compressed and uncompressed files transparently. If any given file,\n"
|
|
||||||
"including standard input, is compressed, its decompressed content is used.\n"
|
|
||||||
"\nThe supported formats are bzip2, gzip, lzip and xz.\n"
|
|
||||||
"\nUsage: %s <operation> [options] [files]\n", invocation_name );
|
|
||||||
std::printf( "\nTry '%s <operation> --help' for more specific help.\n", invocation_name );
|
|
||||||
std::printf( "\nOperations:\n"
|
|
||||||
" -h, --help display this help and exit\n"
|
|
||||||
" -V, --version output version information and exit\n"
|
|
||||||
" --zcat zcat operation\n"
|
|
||||||
" --zgrep zgrep operation\n"
|
|
||||||
" --ztest ztest operation\n" );
|
|
||||||
show_help_addr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 Mode program_mode,
|
|
||||||
const bool search )
|
|
||||||
{
|
|
||||||
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
|
||||||
if( infd < 0 )
|
|
||||||
{
|
|
||||||
if( search && ( program_mode == m_zcat || program_mode == m_zgrep ) &&
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "zcat.cc"
|
|
||||||
#include "zgrep.cc"
|
|
||||||
#include "ztest.cc"
|
|
||||||
|
|
||||||
} // end namespace
|
|
||||||
|
|
||||||
|
|
||||||
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,
|
|
||||||
zcat_opt, zgrep_opt, ztest_opt };
|
|
||||||
const Arg_parser::Option * options = 0;
|
|
||||||
int infd = -1;
|
|
||||||
int format_index = -1;
|
|
||||||
Mode program_mode = m_none;
|
|
||||||
bool recursive = false;
|
|
||||||
std::string input_filename;
|
|
||||||
std::list< std::string > filenames;
|
|
||||||
Cat_options cat_options;
|
|
||||||
std::vector< const char * > grep_args; // args to grep, maybe empty
|
|
||||||
std::vector< const char * > ztest_args; // args to ztest, maybe empty
|
|
||||||
invocation_name = argv[0];
|
|
||||||
|
|
||||||
const Arg_parser::Option m_zcat_options[] =
|
|
||||||
{
|
|
||||||
{ 'A', "show-all", Arg_parser::no }, // cat
|
|
||||||
{ 'b', "number-nonblank", Arg_parser::no }, // cat
|
|
||||||
{ 'c', "stdout", Arg_parser::no }, // gzip
|
|
||||||
{ 'd', "decompress", Arg_parser::no }, // gzip
|
|
||||||
{ 'e', 0, Arg_parser::no }, // cat
|
|
||||||
{ 'E', "show-ends", Arg_parser::no }, // cat
|
|
||||||
{ 'f', "force", Arg_parser::no }, // gzip
|
|
||||||
{ 'h', "help", Arg_parser::no },
|
|
||||||
{ 'l', "list", Arg_parser::no }, // gzip
|
|
||||||
{ 'L', "license", Arg_parser::no }, // gzip
|
|
||||||
{ 'n', "number", Arg_parser::no }, // cat
|
|
||||||
{ 'N', "no-rcfile", Arg_parser::no },
|
|
||||||
{ 'q', "quiet", Arg_parser::no },
|
|
||||||
{ 'r', "recursive", Arg_parser::no },
|
|
||||||
{ 's', "squeeze-blank", Arg_parser::no }, // cat
|
|
||||||
{ 't', 0, Arg_parser::no }, // cat
|
|
||||||
{ 'T', "show-tabs", Arg_parser::no }, // cat
|
|
||||||
{ 'v', "show-nonprinting", Arg_parser::no }, // cat
|
|
||||||
{ 'V', "version", Arg_parser::no },
|
|
||||||
{ format_opt, "format", Arg_parser::yes },
|
|
||||||
{ verbose_opt, "verbose", Arg_parser::no },
|
|
||||||
{ bz2_opt, "bz2", Arg_parser::yes },
|
|
||||||
{ gz_opt, "gz", Arg_parser::yes },
|
|
||||||
{ lz_opt, "lz", Arg_parser::yes },
|
|
||||||
{ xz_opt, "xz", Arg_parser::yes },
|
|
||||||
{ zcat_opt, "zcat", Arg_parser::no },
|
|
||||||
{ 0 , 0, Arg_parser::no } };
|
|
||||||
|
|
||||||
const Arg_parser::Option m_zgrep_options[] =
|
|
||||||
{
|
|
||||||
{ 'a', "text", Arg_parser::no }, // grep GNU
|
|
||||||
{ 'A', "after-context", Arg_parser::yes }, // grep GNU
|
|
||||||
{ 'b', "byte-offset", Arg_parser::no }, // grep GNU
|
|
||||||
{ 'B', "before-context", Arg_parser::yes }, // grep GNU
|
|
||||||
{ 'c', "count", Arg_parser::no }, // grep
|
|
||||||
{ 'C', "context", Arg_parser::yes }, // grep GNU
|
|
||||||
{ 'e', "regexp", Arg_parser::yes }, // grep
|
|
||||||
{ 'E', "extended-regexp", Arg_parser::no }, // grep
|
|
||||||
{ 'f', "file ", Arg_parser::yes }, // grep
|
|
||||||
{ 'F', "fixed-strings", Arg_parser::no }, // grep
|
|
||||||
{ 'h', "no-filename", Arg_parser::no }, // grep GNU
|
|
||||||
{ 'H', "with-filename", Arg_parser::no }, // grep GNU
|
|
||||||
{ 'i', "ignore-case", Arg_parser::no }, // grep
|
|
||||||
{ 'I', 0, Arg_parser::no }, // grep GNU
|
|
||||||
{ 'l', "files-with-matches", Arg_parser::no }, // grep
|
|
||||||
{ 'L', "files-without-match", Arg_parser::no }, // grep GNU
|
|
||||||
{ 'm', "max-count", Arg_parser::yes }, // grep GNU
|
|
||||||
{ 'n', "line-number", Arg_parser::no }, // grep
|
|
||||||
{ 'N', "no-rcfile", Arg_parser::no },
|
|
||||||
{ 'o', "only-matching", Arg_parser::no }, // grep
|
|
||||||
{ 'q', "quiet", Arg_parser::no },
|
|
||||||
{ 'r', "recursive", Arg_parser::no },
|
|
||||||
{ 's', "no-messages", Arg_parser::no }, // grep
|
|
||||||
{ 'v', "invert-match", Arg_parser::no }, // grep
|
|
||||||
{ 'V', "version", Arg_parser::no },
|
|
||||||
{ 'w', "word-regexp", Arg_parser::no }, // grep GNU
|
|
||||||
{ 'x', "line-regexp", Arg_parser::no }, // grep
|
|
||||||
{ format_opt, "format", Arg_parser::yes },
|
|
||||||
{ help_opt, "help", Arg_parser::no },
|
|
||||||
{ verbose_opt, "verbose", Arg_parser::no },
|
|
||||||
{ bz2_opt, "bz2", Arg_parser::yes },
|
|
||||||
{ gz_opt, "gz", Arg_parser::yes },
|
|
||||||
{ lz_opt, "lz", Arg_parser::yes },
|
|
||||||
{ xz_opt, "xz", Arg_parser::yes },
|
|
||||||
{ zgrep_opt, "zgrep", Arg_parser::no },
|
|
||||||
{ 0 , 0, Arg_parser::no } };
|
|
||||||
|
|
||||||
const Arg_parser::Option m_ztest_options[] =
|
|
||||||
{
|
|
||||||
{ 'h', "help", Arg_parser::no },
|
|
||||||
{ 'N', "no-rcfile", Arg_parser::no },
|
|
||||||
{ '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 },
|
|
||||||
{ xz_opt, "xz", Arg_parser::yes },
|
|
||||||
{ ztest_opt, "ztest", Arg_parser::no },
|
|
||||||
{ 0 , 0, Arg_parser::no } };
|
|
||||||
|
|
||||||
{ // parse operation
|
|
||||||
const Arg_parser::Option operations[] =
|
|
||||||
{
|
|
||||||
{ 'h', "help", Arg_parser::no },
|
|
||||||
{ 'V', "version", Arg_parser::no },
|
|
||||||
{ zcat_opt, "zcat", Arg_parser::no },
|
|
||||||
{ zgrep_opt, "zgrep", Arg_parser::no },
|
|
||||||
{ ztest_opt, "ztest", Arg_parser::no },
|
|
||||||
{ 0 , 0, Arg_parser::no } };
|
|
||||||
|
|
||||||
const Arg_parser parser( argv[1], ( argc > 2 ) ? argv[2] : 0, operations );
|
|
||||||
if( parser.error().size() ) // bad operation
|
|
||||||
{ show_error( parser.error().c_str(), 0, true ); return 1; }
|
|
||||||
|
|
||||||
if( parser.arguments() > 0 )
|
|
||||||
{
|
|
||||||
switch( parser.code( 0 ) )
|
|
||||||
{
|
|
||||||
case 0 : break;
|
|
||||||
case 'h': show_help(); return 0;
|
|
||||||
case 'V': show_version(); return 0;
|
|
||||||
case zcat_opt : program_mode = m_zcat; options = m_zcat_options;
|
|
||||||
util_name = "zcat"; break;
|
|
||||||
case zgrep_opt : program_mode = m_zgrep; options = m_zgrep_options;
|
|
||||||
util_name = "zgrep"; break;
|
|
||||||
case ztest_opt : program_mode = m_ztest; options = m_ztest_options;
|
|
||||||
util_name = "ztest"; break;
|
|
||||||
default : internal_error( "uncaught option" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__MSVCRT__) || defined(__OS2__)
|
|
||||||
setmode( STDIN_FILENO, O_BINARY );
|
|
||||||
setmode( STDOUT_FILENO, O_BINARY );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( program_mode == m_none )
|
|
||||||
{
|
|
||||||
show_error( "You must specify the operation to be performed.", 0, true );
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} // end parse operation
|
|
||||||
|
|
||||||
const int eretval = ( program_mode == m_zgrep ) ? 2 : 1;
|
|
||||||
const Arg_parser parser( argc, argv, options );
|
|
||||||
if( parser.error().size() ) // bad option
|
|
||||||
{ show_error( parser.error().c_str(), 0, true ); return eretval; }
|
|
||||||
|
|
||||||
maybe_process_config_file( parser );
|
|
||||||
|
|
||||||
int argind = 0;
|
|
||||||
int grep_show_name = -1;
|
|
||||||
int grep_list_mode = 0; // 1 = list matches, -1 = list non matches
|
|
||||||
bool grep_pattern_found = false;
|
|
||||||
for( ; argind < parser.arguments(); ++argind )
|
|
||||||
{
|
|
||||||
const int code = parser.code( argind );
|
|
||||||
const char * const arg = parser.argument( argind ).c_str();
|
|
||||||
if( !code )
|
|
||||||
{
|
|
||||||
if( program_mode == m_zgrep && !grep_pattern_found )
|
|
||||||
{ grep_args.push_back( arg ); grep_pattern_found = true; continue; }
|
|
||||||
else break; // no more options
|
|
||||||
}
|
|
||||||
switch( code ) // common options
|
|
||||||
{
|
|
||||||
case 'N': continue;
|
|
||||||
case format_opt: format_index = parse_format_type( arg ); continue;
|
|
||||||
case bz2_opt: parse_compressor( arg, fmt_bz2, eretval ); continue;
|
|
||||||
case gz_opt: parse_compressor( arg, fmt_gz, eretval ); continue;
|
|
||||||
case lz_opt: parse_compressor( arg, fmt_lz, eretval ); continue;
|
|
||||||
case xz_opt: parse_compressor( arg, fmt_xz, eretval ); continue;
|
|
||||||
}
|
|
||||||
switch( program_mode )
|
|
||||||
{
|
|
||||||
case m_none: internal_error( "invalid operation" ); break;
|
|
||||||
case m_zcat:
|
|
||||||
switch( code )
|
|
||||||
{
|
|
||||||
case 'A': cat_options.show_ends = true;
|
|
||||||
cat_options.show_nonprinting = true;
|
|
||||||
cat_options.show_tabs = true; break;
|
|
||||||
case 'b': cat_options.number_lines = 1; break;
|
|
||||||
case 'c': break;
|
|
||||||
case 'd': break;
|
|
||||||
case 'e': cat_options.show_nonprinting = true; // fall through
|
|
||||||
case 'E': cat_options.show_ends = true; break;
|
|
||||||
case 'f': break;
|
|
||||||
case 'h': show_zcat_help(); return 0;
|
|
||||||
case 'l': break;
|
|
||||||
case 'L': break;
|
|
||||||
case 'n': if( cat_options.number_lines == 0 )
|
|
||||||
{ cat_options.number_lines = 2; } break;
|
|
||||||
case 'q': verbosity = -1; break;
|
|
||||||
case 'r': recursive = true; break;
|
|
||||||
case 's': cat_options.squeeze_blank = true; break;
|
|
||||||
case 't': cat_options.show_nonprinting = true; // fall through
|
|
||||||
case 'T': cat_options.show_tabs = true; break;
|
|
||||||
case 'v': cat_options.show_nonprinting = true; break;
|
|
||||||
case 'V': show_version( "Zcat" ); return 0;
|
|
||||||
case verbose_opt : if( verbosity < 4 ) ++verbosity; break;
|
|
||||||
case zcat_opt : break;
|
|
||||||
default : internal_error( "uncaught option" );
|
|
||||||
} break;
|
|
||||||
case m_zgrep:
|
|
||||||
switch( code )
|
|
||||||
{
|
|
||||||
case 'a': grep_args.push_back( "-a" ); break;
|
|
||||||
case 'A': grep_args.push_back( "-A" ); grep_args.push_back( arg ); break;
|
|
||||||
case 'b': grep_args.push_back( "-b" ); break;
|
|
||||||
case 'B': grep_args.push_back( "-B" ); grep_args.push_back( arg ); 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 );
|
|
||||||
grep_pattern_found = true; break;
|
|
||||||
case 'E': grep_args.push_back( "-E" ); break;
|
|
||||||
case 'f': grep_args.push_back( "-f" ); grep_args.push_back( arg );
|
|
||||||
grep_pattern_found = true; break;
|
|
||||||
case 'F': grep_args.push_back( "-F" ); break;
|
|
||||||
case 'h': grep_show_name = false; break;
|
|
||||||
case 'H': grep_show_name = true; break;
|
|
||||||
case 'i': grep_args.push_back( "-i" ); break;
|
|
||||||
case 'I': grep_args.push_back( "-I" ); break;
|
|
||||||
case 'l': grep_args.push_back( "-l" ); grep_list_mode = 1; break;
|
|
||||||
case 'L': grep_args.push_back( "-L" ); grep_list_mode = -1; break;
|
|
||||||
case 'm': grep_args.push_back( "-m" ); grep_args.push_back( arg ); break;
|
|
||||||
case 'n': grep_args.push_back( "-n" ); break;
|
|
||||||
case 'o': grep_args.push_back( "-o" ); break;
|
|
||||||
case 'q': grep_args.push_back( "-q" ); verbosity = -1; break;
|
|
||||||
case 'r': recursive = true; break;
|
|
||||||
case 's': grep_args.push_back( "-s" ); verbosity = -1; break;
|
|
||||||
case 'v': grep_args.push_back( "-v" ); break;
|
|
||||||
case 'V': show_version( "Zgrep" ); return 0;
|
|
||||||
case 'w': grep_args.push_back( "-w" ); break;
|
|
||||||
case 'x': grep_args.push_back( "-x" ); break;
|
|
||||||
case help_opt : show_zgrep_help(); return 0;
|
|
||||||
case verbose_opt : if( verbosity < 4 ) ++verbosity; break;
|
|
||||||
case zgrep_opt : break;
|
|
||||||
default : internal_error( "uncaught option" );
|
|
||||||
} break;
|
|
||||||
case m_ztest:
|
|
||||||
switch( code )
|
|
||||||
{
|
|
||||||
case 'h': show_ztest_help(); return 0;
|
|
||||||
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( "Ztest" ); return 0;
|
|
||||||
case ztest_opt : break;
|
|
||||||
default : internal_error( "uncaught option" );
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
} // end process options
|
|
||||||
|
|
||||||
if( program_mode == m_zgrep && !grep_pattern_found )
|
|
||||||
{ show_error( "Pattern not found." ); return 2; }
|
|
||||||
|
|
||||||
for( ; argind < parser.arguments(); ++argind )
|
|
||||||
filenames.push_back( parser.argument( argind ) );
|
|
||||||
|
|
||||||
if( filenames.empty() ) filenames.push_back("-");
|
|
||||||
|
|
||||||
if( grep_show_name < 0 )
|
|
||||||
grep_show_name = ( filenames.size() != 1 || recursive );
|
|
||||||
|
|
||||||
int retval = ( program_mode == m_zgrep ) ? 1 : 0;
|
|
||||||
while( !filenames.empty() )
|
|
||||||
{
|
|
||||||
input_filename = filenames.front();
|
|
||||||
filenames.pop_front();
|
|
||||||
if( !input_filename.size() || input_filename == "-" )
|
|
||||||
{
|
|
||||||
input_filename.clear();
|
|
||||||
infd = STDIN_FILENO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( recursive )
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
if( stat( input_filename.c_str(), &st ) == 0 && S_ISDIR( st.st_mode ) )
|
|
||||||
{
|
|
||||||
DIR * const dirp = opendir( input_filename.c_str() );
|
|
||||||
if( !dirp )
|
|
||||||
{
|
|
||||||
show_error2( "Can't open directory", input_filename.c_str() );
|
|
||||||
if( retval < 1 ) retval = 1; continue;
|
|
||||||
}
|
|
||||||
std::list< std::string > tmp_list;
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
filenames.splice( filenames.begin(), tmp_list );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
infd = open_instream( input_filename, program_mode, format_index < 0 );
|
|
||||||
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
int tmp = 0;
|
|
||||||
switch( program_mode )
|
|
||||||
{
|
|
||||||
case m_none:
|
|
||||||
break;
|
|
||||||
case m_zcat:
|
|
||||||
tmp = cat( infd, format_index, input_filename, cat_options );
|
|
||||||
break;
|
|
||||||
case m_zgrep:
|
|
||||||
if( infd == STDIN_FILENO )
|
|
||||||
tmp = zgrep_stdin( infd, format_index, grep_args );
|
|
||||||
else tmp = zgrep_file( infd, format_index, input_filename, grep_args,
|
|
||||||
grep_list_mode, grep_show_name );
|
|
||||||
break;
|
|
||||||
case m_ztest:
|
|
||||||
if( infd == STDIN_FILENO )
|
|
||||||
tmp = ztest_stdin( infd, format_index, ztest_args );
|
|
||||||
else tmp = ztest_file( infd, format_index, input_filename, ztest_args );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if( program_mode == m_zgrep )
|
|
||||||
{ if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp; }
|
|
||||||
else if( tmp > retval ) retval = tmp;
|
|
||||||
|
|
||||||
if( input_filename.size() )
|
|
||||||
{ close( infd ); infd = -1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if( std::fclose( stdout ) != 0 )
|
|
||||||
{
|
|
||||||
show_error( "Can't close stdout", errno );
|
|
||||||
switch( program_mode )
|
|
||||||
{
|
|
||||||
case m_none: break;
|
|
||||||
case m_zcat: retval = 1; break;
|
|
||||||
case m_zgrep: if( retval != 0 || verbosity >= 0 ) retval = 2; break;
|
|
||||||
case m_ztest: if( retval == 0 ) retval = 1; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
112
rc.cc
112
rc.cc
|
@ -17,19 +17,28 @@
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdint.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
#include "zutils.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char * invocation_name = 0;
|
||||||
|
const char * program_name = 0;
|
||||||
|
int verbosity = 0;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const char * const config_file_name = "zutilsrc";
|
||||||
|
const char * const program_year = "2013";
|
||||||
|
|
||||||
std::string compressor_names[num_formats] =
|
std::string compressor_names[num_formats] =
|
||||||
{ "bzip2", "gzip", "lzip", "xz" }; // default compressor names
|
{ "bzip2", "gzip", "lzip", "xz" }; // default compressor names
|
||||||
|
|
||||||
|
@ -227,3 +236,102 @@ const std::vector< std::string > & get_compressor_args( const int format_index )
|
||||||
{
|
{
|
||||||
return compressor_args[format_index];
|
return compressor_args[format_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_help_addr()
|
||||||
|
{
|
||||||
|
std::printf( "\nReport bugs to zutils-bug@nongnu.org\n"
|
||||||
|
"Zutils home page: http://www.nongnu.org/zutils/zutils.html\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_version( const char * const Program_name )
|
||||||
|
{
|
||||||
|
std::printf( "%s (zutils) %s\n", Program_name, PROGVERSION );
|
||||||
|
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
||||||
|
std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
|
||||||
|
"This is free software: you are free to change and redistribute it.\n"
|
||||||
|
"There is NO WARRANTY, to the extent permitted by law.\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_error( const char * const msg, const int errcode, const bool help )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
{
|
||||||
|
if( msg && msg[0] )
|
||||||
|
{
|
||||||
|
std::fprintf( stderr, "%s: %s", program_name, msg );
|
||||||
|
if( errcode > 0 )
|
||||||
|
std::fprintf( stderr, ": %s", std::strerror( errcode ) );
|
||||||
|
std::fprintf( stderr, "\n" );
|
||||||
|
}
|
||||||
|
if( help )
|
||||||
|
std::fprintf( stderr, "Try '%s --help' for more information.\n",
|
||||||
|
invocation_name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_error2( const char * const msg, const char * const name )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: %s '%s': %s.\n",
|
||||||
|
program_name, msg, name, std::strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void internal_error( const char * const msg )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: internal error: %s.\n", program_name, msg );
|
||||||
|
std::exit( 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_close_error( const char * const prog_name )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: Can't close output of %s: %s.\n",
|
||||||
|
program_name, prog_name, std::strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_exec_error( const char * const prog_name )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: Can't exec '%s': %s.\n",
|
||||||
|
program_name, prog_name, std::strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_fork_error( const char * const prog_name )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: Can't fork '%s': %s.\n",
|
||||||
|
program_name, prog_name, std::strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wait_for_child( const pid_t pid, const char * const name,
|
||||||
|
const int eretval, const bool isgzxz )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
while( waitpid( pid, &status, 0 ) == -1 )
|
||||||
|
{
|
||||||
|
if( errno != EINTR )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: Error waiting termination of '%s': %s.\n",
|
||||||
|
program_name, name, std::strerror( errno ) );
|
||||||
|
_exit( eretval );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( WIFEXITED( status ) )
|
||||||
|
{
|
||||||
|
const int tmp = WEXITSTATUS( status );
|
||||||
|
if( isgzxz && eretval == 1 && tmp == 1 ) return 2; // for ztest
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
return eretval;
|
||||||
|
}
|
||||||
|
|
27
rc.h
27
rc.h
|
@ -15,6 +15,17 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum { fmt_bz2, fmt_gz, fmt_lz, fmt_xz, num_formats };
|
||||||
|
const char * const format_names[num_formats] = { "bz2", "gz", "lz", "xz" };
|
||||||
|
const char * const simple_extensions[num_formats] =
|
||||||
|
{ ".bz2", ".gz", ".lz", ".xz" };
|
||||||
|
const int format_order[num_formats] =
|
||||||
|
{ fmt_lz, fmt_bz2, fmt_gz, fmt_xz }; // search order
|
||||||
|
|
||||||
|
extern const char * invocation_name;
|
||||||
|
extern const char * program_name;
|
||||||
|
extern int verbosity;
|
||||||
|
|
||||||
class Arg_parser;
|
class Arg_parser;
|
||||||
|
|
||||||
void maybe_process_config_file( const Arg_parser & parser );
|
void maybe_process_config_file( const Arg_parser & parser );
|
||||||
|
@ -23,5 +34,19 @@ void parse_compressor( const std::string & arg, const int format_index,
|
||||||
const int eretval = 2 );
|
const int eretval = 2 );
|
||||||
|
|
||||||
const char * get_compressor_name( const int format_index );
|
const char * get_compressor_name( const int format_index );
|
||||||
|
|
||||||
const std::vector< std::string > & get_compressor_args( const int format_index );
|
const std::vector< std::string > & get_compressor_args( const int format_index );
|
||||||
|
|
||||||
|
void show_help_addr();
|
||||||
|
void show_version( const char * const Program_name );
|
||||||
|
void show_error( const char * const msg, const int errcode = 0,
|
||||||
|
const bool help = false );
|
||||||
|
void show_error2( const char * const msg, const char * const name );
|
||||||
|
void internal_error( const char * const msg );
|
||||||
|
void show_close_error( const char * const prog_name = "data feeder" );
|
||||||
|
void show_exec_error( const char * const prog_name );
|
||||||
|
void show_fork_error( const char * const prog_name );
|
||||||
|
|
||||||
|
// Returns exit status of child process 'pid', or 'eretval' in case of error.
|
||||||
|
//
|
||||||
|
int wait_for_child( const pid_t pid, const char * const name,
|
||||||
|
const int eretval = 2, const bool isgzxz = false );
|
||||||
|
|
61
recursive.cc
Normal file
61
recursive.cc
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* Zutils - Utilities dealing with compressed files
|
||||||
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool next_filename( std::list< std::string > & filenames,
|
||||||
|
std::string & input_filename, bool & error,
|
||||||
|
const bool recursive, const bool ignore_stdin = false,
|
||||||
|
const bool no_messages = false )
|
||||||
|
{
|
||||||
|
while( !filenames.empty() )
|
||||||
|
{
|
||||||
|
input_filename = filenames.front();
|
||||||
|
filenames.pop_front();
|
||||||
|
if( input_filename.empty() || input_filename == "-" )
|
||||||
|
{
|
||||||
|
if( ignore_stdin ) continue;
|
||||||
|
input_filename.clear(); return true;
|
||||||
|
}
|
||||||
|
if( recursive )
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if( stat( input_filename.c_str(), &st ) == 0 && S_ISDIR( st.st_mode ) )
|
||||||
|
{
|
||||||
|
DIR * const dirp = opendir( input_filename.c_str() );
|
||||||
|
if( !dirp )
|
||||||
|
{
|
||||||
|
if( !no_messages )
|
||||||
|
show_error2( "Can't open directory", input_filename.c_str() );
|
||||||
|
error = true; continue;
|
||||||
|
}
|
||||||
|
std::list< std::string > tmp_list;
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
filenames.splice( filenames.begin(), tmp_list );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
input_filename.clear();
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -46,9 +46,7 @@ cat in.lz > lz_only.lz || framework_failure
|
||||||
cat in in in in in in > in6 || framework_failure
|
cat in in in in in in > in6 || framework_failure
|
||||||
fail=0
|
fail=0
|
||||||
|
|
||||||
printf "testing zutils-%s..." "$2"
|
printf "testing zcat-%s..." "$2"
|
||||||
|
|
||||||
printf "\ntesting zcat-%s..." "$2"
|
|
||||||
|
|
||||||
for i in ${extensions}; do
|
for i in ${extensions}; do
|
||||||
"${ZCAT}" -N in.$i > copy || fail=1
|
"${ZCAT}" -N in.$i > copy || fail=1
|
||||||
|
@ -299,6 +297,8 @@ if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||||
if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi
|
if [ $? != 0 ] ; then printf . ; else printf - ; fail=1 ; fi
|
||||||
"${ZGREP}" -N --bad-option 2> /dev/null
|
"${ZGREP}" -N --bad-option 2> /dev/null
|
||||||
if [ $? = 2 ] ; 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
|
||||||
|
|
||||||
"${ZEGREP}" -N "GNU" in > /dev/null || fail=1
|
"${ZEGREP}" -N "GNU" in > /dev/null || fail=1
|
||||||
printf .
|
printf .
|
||||||
|
@ -388,8 +388,8 @@ rm -f x.lz || framework_failure
|
||||||
|
|
||||||
cat in.bz2 > x.bz2 || framework_failure
|
cat in.bz2 > x.bz2 || framework_failure
|
||||||
cat in.gz > x.gz || framework_failure
|
cat in.gz > x.gz || framework_failure
|
||||||
"${ZUPDATE}" -N -f x.bz2 x.gz 2> /dev/null
|
"${ZUPDATE}" -N -f -k x.bz2 x.gz 2> /dev/null
|
||||||
if [ $? = 0 ] && [ ! -e x.bz2 ] && [ ! -e x.gz ] && [ -e x.lz ] ; then printf .
|
if [ $? = 0 ] && [ -e x.bz2 ] && [ -e x.gz ] && [ -e x.lz ] ; then printf .
|
||||||
else printf - ; fail=1
|
else printf - ; fail=1
|
||||||
fi
|
fi
|
||||||
rm -f x.lz || framework_failure
|
rm -f x.lz || framework_failure
|
||||||
|
|
198
zcat.cc
198
zcat.cc
|
@ -15,6 +15,39 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <climits>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "arg_parser.h"
|
||||||
|
#include "rc.h"
|
||||||
|
#include "zutils.h"
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#include "recursive.cc"
|
||||||
|
|
||||||
struct Cat_options
|
struct Cat_options
|
||||||
{
|
{
|
||||||
int number_lines; // 0 = no, 1 = nonblank, 2 = all
|
int number_lines; // 0 = no, 1 = nonblank, 2 = all
|
||||||
|
@ -58,7 +91,7 @@ public:
|
||||||
Line_number line_number;
|
Line_number line_number;
|
||||||
|
|
||||||
|
|
||||||
void show_zcat_help()
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zcat copies each given file (\"-\" means standard input), to standard\n"
|
std::printf( "Zcat copies each given file (\"-\" means standard input), to standard\n"
|
||||||
"output. If any given file is compressed, its decompressed content is\n"
|
"output. If any given file is compressed, its decompressed content is\n"
|
||||||
|
@ -96,6 +129,41 @@ void show_zcat_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,
|
int do_cat( const int infd, const int buffer_size,
|
||||||
uint8_t * const inbuf, uint8_t * const outbuf,
|
uint8_t * const inbuf, uint8_t * const outbuf,
|
||||||
const std::string & input_filename,
|
const std::string & input_filename,
|
||||||
|
@ -210,7 +278,133 @@ int cat( int infd, const int format_index, const std::string & input_filename,
|
||||||
if( !good_status( children, retval == 0 ) ) retval = 1;
|
if( !good_status( children, retval == 0 ) ) retval = 1;
|
||||||
|
|
||||||
if( retval == 0 && close( infd ) != 0 )
|
if( retval == 0 && close( infd ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); retval = 1; }
|
{ show_close_error(); retval = 1; }
|
||||||
delete[] outbuf; delete[] inbuf;
|
delete[] outbuf; delete[] inbuf;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
|
|
||||||
|
|
||||||
|
int main( const int argc, const char * const argv[] )
|
||||||
|
{
|
||||||
|
enum { format_opt = 256, verbose_opt, bz2_opt, gz_opt, lz_opt, xz_opt };
|
||||||
|
int infd = -1;
|
||||||
|
int format_index = -1;
|
||||||
|
bool recursive = false;
|
||||||
|
std::string input_filename;
|
||||||
|
std::list< std::string > filenames;
|
||||||
|
Cat_options cat_options;
|
||||||
|
invocation_name = argv[0];
|
||||||
|
program_name = "zcat";
|
||||||
|
|
||||||
|
const Arg_parser::Option options[] =
|
||||||
|
{
|
||||||
|
{ 'A', "show-all", Arg_parser::no }, // cat
|
||||||
|
{ 'b', "number-nonblank", Arg_parser::no }, // cat
|
||||||
|
{ 'c', "stdout", Arg_parser::no }, // gzip
|
||||||
|
{ 'd', "decompress", Arg_parser::no }, // gzip
|
||||||
|
{ 'e', 0, Arg_parser::no }, // cat
|
||||||
|
{ 'E', "show-ends", Arg_parser::no }, // cat
|
||||||
|
{ 'f', "force", Arg_parser::no }, // gzip
|
||||||
|
{ 'h', "help", Arg_parser::no },
|
||||||
|
{ 'l', "list", Arg_parser::no }, // gzip
|
||||||
|
{ 'L', "license", Arg_parser::no }, // gzip
|
||||||
|
{ 'n', "number", Arg_parser::no }, // cat
|
||||||
|
{ 'N', "no-rcfile", Arg_parser::no },
|
||||||
|
{ 'q', "quiet", Arg_parser::no },
|
||||||
|
{ 'r', "recursive", Arg_parser::no },
|
||||||
|
{ 's', "squeeze-blank", Arg_parser::no }, // cat
|
||||||
|
{ 't', 0, Arg_parser::no }, // cat
|
||||||
|
{ 'T', "show-tabs", Arg_parser::no }, // cat
|
||||||
|
{ 'v', "show-nonprinting", Arg_parser::no }, // cat
|
||||||
|
{ 'V', "version", Arg_parser::no },
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
|
{ verbose_opt, "verbose", Arg_parser::no },
|
||||||
|
{ bz2_opt, "bz2", Arg_parser::yes },
|
||||||
|
{ gz_opt, "gz", Arg_parser::yes },
|
||||||
|
{ lz_opt, "lz", Arg_parser::yes },
|
||||||
|
{ xz_opt, "xz", Arg_parser::yes },
|
||||||
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
|
||||||
|
const Arg_parser parser( argc, argv, options );
|
||||||
|
if( parser.error().size() ) // bad option
|
||||||
|
{ show_error( parser.error().c_str(), 0, true ); return 1; }
|
||||||
|
|
||||||
|
maybe_process_config_file( parser );
|
||||||
|
|
||||||
|
int argind = 0;
|
||||||
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
|
{
|
||||||
|
const int code = parser.code( argind );
|
||||||
|
if( !code ) break; // no more options
|
||||||
|
const char * const arg = parser.argument( argind ).c_str();
|
||||||
|
switch( code )
|
||||||
|
{
|
||||||
|
case 'A': cat_options.show_ends = true;
|
||||||
|
cat_options.show_nonprinting = true;
|
||||||
|
cat_options.show_tabs = true; break;
|
||||||
|
case 'b': cat_options.number_lines = 1; break;
|
||||||
|
case 'c': break;
|
||||||
|
case 'd': break;
|
||||||
|
case 'e': cat_options.show_nonprinting = true; // fall through
|
||||||
|
case 'E': cat_options.show_ends = true; break;
|
||||||
|
case 'f': break;
|
||||||
|
case 'h': show_help(); return 0;
|
||||||
|
case 'l': break;
|
||||||
|
case 'L': break;
|
||||||
|
case 'n': if( cat_options.number_lines == 0 )
|
||||||
|
{ cat_options.number_lines = 2; } break;
|
||||||
|
case 'N': break;
|
||||||
|
case 'q': verbosity = -1; break;
|
||||||
|
case 'r': recursive = true; break;
|
||||||
|
case 's': cat_options.squeeze_blank = true; break;
|
||||||
|
case 't': cat_options.show_nonprinting = true; // fall through
|
||||||
|
case 'T': cat_options.show_tabs = true; break;
|
||||||
|
case 'v': cat_options.show_nonprinting = true; break;
|
||||||
|
case 'V': show_version( "Zcat" ); 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;
|
||||||
|
case lz_opt: parse_compressor( arg, fmt_lz, 1 ); break;
|
||||||
|
case xz_opt: parse_compressor( arg, fmt_xz, 1 ); break;
|
||||||
|
default : internal_error( "uncaught option" );
|
||||||
|
}
|
||||||
|
} // end process options
|
||||||
|
|
||||||
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
|
setmode( STDIN_FILENO, O_BINARY );
|
||||||
|
setmode( STDOUT_FILENO, O_BINARY );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
|
filenames.push_back( parser.argument( argind ) );
|
||||||
|
|
||||||
|
if( filenames.empty() ) filenames.push_back("-");
|
||||||
|
|
||||||
|
int retval = 0;
|
||||||
|
bool error = false;
|
||||||
|
while( next_filename( filenames, input_filename, error, recursive ) )
|
||||||
|
{
|
||||||
|
if( input_filename.empty() ) infd = STDIN_FILENO;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infd = open_instream( input_filename, format_index < 0 );
|
||||||
|
if( infd < 0 ) { error = true; continue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const int tmp = cat( infd, format_index, input_filename, cat_options );
|
||||||
|
if( tmp > retval ) retval = tmp;
|
||||||
|
|
||||||
|
if( input_filename.size() ) { close( infd ); infd = -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if( std::fclose( stdout ) != 0 )
|
||||||
|
{
|
||||||
|
show_error( "Can't close stdout", errno );
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
if( error && retval == 0 ) retval = 1;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
3
zcat.in
3
zcat.in
|
@ -1,3 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
|
||||||
exec "${bindir}"zutils --zcat "$@"
|
|
13
zcmp.cc
13
zcmp.cc
|
@ -36,12 +36,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
#include "zutils.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
|
#include "zutils.h"
|
||||||
#if CHAR_BIT != 8
|
|
||||||
#error "Environments where CHAR_BIT != 8 are not supported."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LLONG_MAX
|
#ifndef LLONG_MAX
|
||||||
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
|
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||||
|
@ -52,7 +48,6 @@ namespace {
|
||||||
|
|
||||||
#include "zcmpdiff.cc"
|
#include "zcmpdiff.cc"
|
||||||
|
|
||||||
|
|
||||||
void show_help()
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zcmp compares two files (\"-\" means standard input), and if they\n"
|
std::printf( "Zcmp compares two files (\"-\" means standard input), and if they\n"
|
||||||
|
@ -301,7 +296,7 @@ int cmp( const long long max_size, const int infd[2],
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: EOF on %s\n",
|
std::fprintf( stderr, "%s: EOF on %s\n",
|
||||||
util_name, filenames[rd[1]<rd[0]].c_str() );
|
program_name, filenames[rd[1]<rd[0]].c_str() );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if( min_rd != buffer_size ) break;
|
if( min_rd != buffer_size ) break;
|
||||||
|
@ -323,7 +318,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
int format_types[2] = { -1, -1 };
|
int format_types[2] = { -1, -1 };
|
||||||
bool print_bytes = false;
|
bool print_bytes = false;
|
||||||
invocation_name = argv[0];
|
invocation_name = argv[0];
|
||||||
util_name = "zcmp";
|
program_name = "zcmp";
|
||||||
|
|
||||||
const Arg_parser::Option options[] =
|
const Arg_parser::Option options[] =
|
||||||
{
|
{
|
||||||
|
@ -443,7 +438,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
for( int i = 0; i < 2; ++i )
|
for( int i = 0; i < 2; ++i )
|
||||||
{
|
{
|
||||||
if( close( infd[i] ) != 0 )
|
if( close( infd[i] ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); retval = 2; }
|
{ show_close_error(); retval = 2; }
|
||||||
if( filenames[i] != "-" && close( old_infd[i] ) != 0 )
|
if( filenames[i] != "-" && close( old_infd[i] ) != 0 )
|
||||||
{
|
{
|
||||||
show_error2( "Can't close input file", filenames[i].c_str() );
|
show_error2( "Can't close input file", filenames[i].c_str() );
|
||||||
|
|
12
zcmpdiff.cc
12
zcmpdiff.cc
|
@ -15,10 +15,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef O_BINARY
|
#ifndef O_BINARY
|
||||||
const int o_binary = O_BINARY;
|
#define O_BINARY 0
|
||||||
#else
|
|
||||||
const int o_binary = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct { const char * from; const char * to; } const known_extensions[] = {
|
struct { const char * from; const char * to; } const known_extensions[] = {
|
||||||
|
@ -36,7 +34,7 @@ struct { const char * from; const char * to; } const known_extensions[] = {
|
||||||
|
|
||||||
int open_instream( const std::string & input_filename )
|
int open_instream( const std::string & input_filename )
|
||||||
{
|
{
|
||||||
int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
|
int infd = open( input_filename.c_str(), O_RDONLY | O_BINARY );
|
||||||
if( infd < 0 )
|
if( infd < 0 )
|
||||||
show_error2( "Can't open input file", input_filename.c_str() );
|
show_error2( "Can't open input file", input_filename.c_str() );
|
||||||
return infd;
|
return infd;
|
||||||
|
@ -53,13 +51,13 @@ int open_other_instream( std::string & name )
|
||||||
{
|
{
|
||||||
name.resize( name.size() - from.size() );
|
name.resize( name.size() - from.size() );
|
||||||
name += known_extensions[i].to;
|
name += known_extensions[i].to;
|
||||||
return open( name.c_str(), O_RDONLY | o_binary );
|
return open( name.c_str(), O_RDONLY | O_BINARY );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int i = 0; i < num_formats; ++i )
|
for( int i = 0; i < num_formats; ++i )
|
||||||
{ // search compressed version
|
{ // search compressed version
|
||||||
const std::string s( name + simple_extensions[format_order[i]] );
|
const std::string s( name + simple_extensions[format_order[i]] );
|
||||||
const int infd = open( s.c_str(), O_RDONLY | o_binary );
|
const int infd = open( s.c_str(), O_RDONLY | O_BINARY );
|
||||||
if( infd >= 0 ) { name = s; return infd; }
|
if( infd >= 0 ) { name = s; return infd; }
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
21
zdiff.cc
21
zdiff.cc
|
@ -36,12 +36,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
#include "zutils.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
|
#include "zutils.h"
|
||||||
#if CHAR_BIT != 8
|
|
||||||
#error "Environments where CHAR_BIT != 8 are not supported."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -50,7 +46,6 @@ std::string fifonames[2]; // names of the two fifos passed to diff
|
||||||
|
|
||||||
#include "zcmpdiff.cc"
|
#include "zcmpdiff.cc"
|
||||||
|
|
||||||
|
|
||||||
void show_help()
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zdiff compares two files (\"-\" means standard input), and if they\n"
|
std::printf( "Zdiff compares two files (\"-\" means standard input), and if they\n"
|
||||||
|
@ -177,7 +172,7 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
!feed_data( infd, fda[1], magic_data, magic_size ) )
|
!feed_data( infd, fda[1], magic_data, magic_size ) )
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
if( close( fda[1] ) != 0 )
|
if( close( fda[1] ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); _exit( 2 ); }
|
{ show_close_error(); _exit( 2 ); }
|
||||||
_exit( 0 );
|
_exit( 0 );
|
||||||
}
|
}
|
||||||
if( pid < 0 ) // parent
|
if( pid < 0 ) // parent
|
||||||
|
@ -186,12 +181,12 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
const pid_t pid2 = fork();
|
const pid_t pid2 = fork();
|
||||||
if( pid2 == 0 ) // child 2 (compressor)
|
if( pid2 == 0 ) // child 2 (compressor)
|
||||||
{
|
{
|
||||||
const int outfd = open( fifoname.c_str(), O_WRONLY | o_binary );
|
const int outfd = open( fifoname.c_str(), O_WRONLY | O_BINARY );
|
||||||
if( outfd < 0 )
|
if( outfd < 0 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't open FIFO '%s' for writing: %s.\n",
|
std::fprintf( stderr, "%s: Can't open FIFO '%s' for writing: %s.\n",
|
||||||
util_name, fifoname.c_str(), std::strerror( errno ) );
|
program_name, fifoname.c_str(), std::strerror( errno ) );
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
}
|
}
|
||||||
if( dup2( fda[0], STDIN_FILENO ) >= 0 &&
|
if( dup2( fda[0], STDIN_FILENO ) >= 0 &&
|
||||||
|
@ -225,18 +220,18 @@ bool set_data_feeder( const std::string & fifoname, const int infd,
|
||||||
const pid_t pid = fork();
|
const pid_t pid = fork();
|
||||||
if( pid == 0 ) // child (feeder)
|
if( pid == 0 ) // child (feeder)
|
||||||
{
|
{
|
||||||
const int outfd = open( fifoname.c_str(), O_WRONLY | o_binary );
|
const int outfd = open( fifoname.c_str(), O_WRONLY | O_BINARY );
|
||||||
if( outfd < 0 )
|
if( outfd < 0 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't open FIFO '%s' for writing: %s.\n",
|
std::fprintf( stderr, "%s: Can't open FIFO '%s' for writing: %s.\n",
|
||||||
util_name, fifoname.c_str(), std::strerror( errno ) );
|
program_name, fifoname.c_str(), std::strerror( errno ) );
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
}
|
}
|
||||||
if( !feed_data( infd, outfd, magic_data, magic_size ) )
|
if( !feed_data( infd, outfd, magic_data, magic_size ) )
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
if( close( outfd ) != 0 )
|
if( close( outfd ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); _exit( 2 ); }
|
{ show_close_error(); _exit( 2 ); }
|
||||||
_exit( 0 );
|
_exit( 0 );
|
||||||
}
|
}
|
||||||
if( pid < 0 ) // parent
|
if( pid < 0 ) // parent
|
||||||
|
@ -272,7 +267,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
std::vector< const char * > diff_args; // args to diff, maybe empty
|
std::vector< const char * > diff_args; // args to diff, maybe empty
|
||||||
int format_types[2] = { -1, -1 };
|
int format_types[2] = { -1, -1 };
|
||||||
invocation_name = argv[0];
|
invocation_name = argv[0];
|
||||||
util_name = "zdiff";
|
program_name = "zdiff";
|
||||||
|
|
||||||
const Arg_parser::Option options[] =
|
const Arg_parser::Option options[] =
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
||||||
exec "${bindir}"zutils --zgrep -E "$@"
|
exec "${bindir}"zgrep -E "$@"
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
||||||
exec "${bindir}"zutils --zgrep -F "$@"
|
exec "${bindir}"zgrep -F "$@"
|
||||||
|
|
247
zgrep.cc
247
zgrep.cc
|
@ -15,7 +15,40 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void show_zgrep_help()
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <climits>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "arg_parser.h"
|
||||||
|
#include "rc.h"
|
||||||
|
#include "zutils.h"
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#include "recursive.cc"
|
||||||
|
|
||||||
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Zgrep is a front end to the grep program that allows transparent search\n"
|
std::printf( "Zgrep is a front end to the grep program that allows transparent search\n"
|
||||||
"on any combination of compressed and uncompressed files. If any given\n"
|
"on any combination of compressed and uncompressed files. If any given\n"
|
||||||
|
@ -68,6 +101,42 @@ void show_zgrep_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,
|
int zgrep_stdin( int infd, const int format_index,
|
||||||
const std::vector< const char * > & grep_args )
|
const std::vector< const char * > & grep_args )
|
||||||
{
|
{
|
||||||
|
@ -96,7 +165,7 @@ int zgrep_stdin( int infd, const int format_index,
|
||||||
if( !good_status( children, retval == 1 ) ) retval = 2;
|
if( !good_status( children, retval == 1 ) ) retval = 2;
|
||||||
|
|
||||||
if( close( infd ) != 0 )
|
if( close( infd ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); return 2; }
|
{ show_close_error(); return 2; }
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +173,7 @@ int zgrep_stdin( int infd, const int format_index,
|
||||||
int zgrep_file( int infd, const int format_index,
|
int zgrep_file( int infd, const int format_index,
|
||||||
const std::string & input_filename,
|
const std::string & input_filename,
|
||||||
const std::vector< const char * > & grep_args,
|
const std::vector< const char * > & grep_args,
|
||||||
const int grep_list_mode, const bool grep_show_name )
|
const int list_mode, const bool show_name )
|
||||||
{
|
{
|
||||||
Children children;
|
Children children;
|
||||||
if( !set_data_feeder( &infd, children, format_index ) ) return 2;
|
if( !set_data_feeder( &infd, children, format_index ) ) return 2;
|
||||||
|
@ -140,9 +209,9 @@ int zgrep_file( int infd, const int format_index,
|
||||||
const int size = readblock( fda[0], buffer, buffer_size );
|
const int size = readblock( fda[0], buffer, buffer_size );
|
||||||
if( size != buffer_size && errno )
|
if( size != buffer_size && errno )
|
||||||
{ show_error( "Read error", errno ); return 2; }
|
{ show_error( "Read error", errno ); return 2; }
|
||||||
if( size > 0 && !grep_list_mode )
|
if( size > 0 && !list_mode )
|
||||||
{
|
{
|
||||||
if( grep_show_name )
|
if( show_name )
|
||||||
for( int i = 0; i < size; ++i )
|
for( int i = 0; i < size; ++i )
|
||||||
{
|
{
|
||||||
if( line_begin )
|
if( line_begin )
|
||||||
|
@ -160,11 +229,175 @@ int zgrep_file( int infd, const int format_index,
|
||||||
|
|
||||||
if( !good_status( children, retval == 1 ) ) retval = 2;
|
if( !good_status( children, retval == 1 ) ) retval = 2;
|
||||||
|
|
||||||
if( grep_list_mode && (retval == 0) == (grep_list_mode == 1) )
|
if( list_mode && (retval == 0) == (list_mode == 1) )
|
||||||
std::printf( "%s\n", input_filename.c_str() );
|
std::printf( "%s\n", input_filename.c_str() );
|
||||||
if( close( infd ) != 0 )
|
if( close( infd ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); return 2; }
|
{ show_close_error(); return 2; }
|
||||||
if( close( fda[0] ) != 0 )
|
if( close( fda[0] ) != 0 )
|
||||||
{ show_close_error( GREP ); return 2; }
|
{ show_close_error( GREP ); return 2; }
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
|
|
||||||
|
|
||||||
|
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 };
|
||||||
|
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;
|
||||||
|
std::list< std::string > filenames;
|
||||||
|
std::vector< const char * > grep_args; // args to grep, maybe empty
|
||||||
|
invocation_name = argv[0];
|
||||||
|
program_name = "zgrep";
|
||||||
|
|
||||||
|
const Arg_parser::Option options[] =
|
||||||
|
{
|
||||||
|
{ 'a', "text", Arg_parser::no }, // grep GNU
|
||||||
|
{ 'A', "after-context", Arg_parser::yes }, // grep GNU
|
||||||
|
{ 'b', "byte-offset", Arg_parser::no }, // grep GNU
|
||||||
|
{ 'B', "before-context", Arg_parser::yes }, // grep GNU
|
||||||
|
{ 'c', "count", Arg_parser::no }, // grep
|
||||||
|
{ 'C', "context", Arg_parser::yes }, // grep GNU
|
||||||
|
{ 'e', "regexp", Arg_parser::yes }, // grep
|
||||||
|
{ 'E', "extended-regexp", Arg_parser::no }, // grep
|
||||||
|
{ 'f', "file ", Arg_parser::yes }, // grep
|
||||||
|
{ 'F', "fixed-strings", Arg_parser::no }, // grep
|
||||||
|
{ 'h', "no-filename", Arg_parser::no }, // grep GNU
|
||||||
|
{ 'H', "with-filename", Arg_parser::no }, // grep GNU
|
||||||
|
{ 'i', "ignore-case", Arg_parser::no }, // grep
|
||||||
|
{ 'I', 0, Arg_parser::no }, // grep GNU
|
||||||
|
{ 'l', "files-with-matches", Arg_parser::no }, // grep
|
||||||
|
{ 'L', "files-without-match", Arg_parser::no }, // grep GNU
|
||||||
|
{ 'm', "max-count", Arg_parser::yes }, // grep GNU
|
||||||
|
{ 'n', "line-number", Arg_parser::no }, // grep
|
||||||
|
{ 'N', "no-rcfile", Arg_parser::no },
|
||||||
|
{ 'o', "only-matching", Arg_parser::no }, // grep
|
||||||
|
{ 'q', "quiet", Arg_parser::no },
|
||||||
|
{ 'r', "recursive", Arg_parser::no },
|
||||||
|
{ 's', "no-messages", Arg_parser::no }, // grep
|
||||||
|
{ 'v', "invert-match", Arg_parser::no }, // grep
|
||||||
|
{ 'V', "version", Arg_parser::no },
|
||||||
|
{ 'w', "word-regexp", Arg_parser::no }, // grep GNU
|
||||||
|
{ 'x', "line-regexp", Arg_parser::no }, // grep
|
||||||
|
{ format_opt, "format", Arg_parser::yes },
|
||||||
|
{ help_opt, "help", Arg_parser::no },
|
||||||
|
{ verbose_opt, "verbose", Arg_parser::no },
|
||||||
|
{ bz2_opt, "bz2", Arg_parser::yes },
|
||||||
|
{ gz_opt, "gz", Arg_parser::yes },
|
||||||
|
{ lz_opt, "lz", Arg_parser::yes },
|
||||||
|
{ xz_opt, "xz", Arg_parser::yes },
|
||||||
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
|
||||||
|
const Arg_parser parser( argc, argv, options );
|
||||||
|
if( parser.error().size() ) // bad option
|
||||||
|
{ show_error( parser.error().c_str(), 0, true ); return 2; }
|
||||||
|
|
||||||
|
maybe_process_config_file( parser );
|
||||||
|
|
||||||
|
int argind = 0;
|
||||||
|
bool pattern_found = false;
|
||||||
|
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
|
||||||
|
}
|
||||||
|
switch( code )
|
||||||
|
{
|
||||||
|
case 'a': grep_args.push_back( "-a" ); break;
|
||||||
|
case 'A': grep_args.push_back( "-A" ); grep_args.push_back( arg ); break;
|
||||||
|
case 'b': grep_args.push_back( "-b" ); break;
|
||||||
|
case 'B': grep_args.push_back( "-B" ); grep_args.push_back( arg ); 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 '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" ); break;
|
||||||
|
case 'h': show_name = false; break;
|
||||||
|
case 'H': show_name = true; break;
|
||||||
|
case 'i': grep_args.push_back( "-i" ); break;
|
||||||
|
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 'n': grep_args.push_back( "-n" ); break;
|
||||||
|
case 'N': break;
|
||||||
|
case 'o': grep_args.push_back( "-o" ); 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;
|
||||||
|
case 'v': grep_args.push_back( "-v" ); break;
|
||||||
|
case 'V': show_version( "Zgrep" ); 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;
|
||||||
|
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;
|
||||||
|
case xz_opt: parse_compressor( arg, fmt_xz ); break;
|
||||||
|
default : internal_error( "uncaught option" );
|
||||||
|
}
|
||||||
|
} // end process options
|
||||||
|
|
||||||
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
|
setmode( STDIN_FILENO, O_BINARY );
|
||||||
|
setmode( STDOUT_FILENO, O_BINARY );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( !pattern_found ) { show_error( "Pattern not found." ); return 2; }
|
||||||
|
|
||||||
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
|
filenames.push_back( parser.argument( argind ) );
|
||||||
|
|
||||||
|
if( filenames.empty() ) filenames.push_back("-");
|
||||||
|
|
||||||
|
if( show_name < 0 ) show_name = ( filenames.size() != 1 || recursive );
|
||||||
|
|
||||||
|
int retval = 1;
|
||||||
|
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 );
|
||||||
|
if( infd < 0 ) { error = true; continue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp;
|
||||||
|
if( infd == STDIN_FILENO )
|
||||||
|
tmp = zgrep_stdin( infd, format_index, grep_args );
|
||||||
|
else tmp = zgrep_file( infd, format_index, input_filename, grep_args,
|
||||||
|
list_mode, show_name );
|
||||||
|
if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp;
|
||||||
|
|
||||||
|
if( input_filename.size() ) { close( infd ); infd = -1; }
|
||||||
|
if( retval == 0 && verbosity < 0 ) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( std::fclose( stdout ) != 0 )
|
||||||
|
{
|
||||||
|
show_error( "Can't close stdout", errno );
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
if( error && ( retval != 0 || verbosity >= 0 ) ) retval = 2;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
3
zgrep.in
3
zgrep.in
|
@ -1,3 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
|
||||||
exec "${bindir}"zutils --zgrep "$@"
|
|
145
ztest.cc
145
ztest.cc
|
@ -15,7 +15,40 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void show_ztest_help()
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <climits>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "arg_parser.h"
|
||||||
|
#include "rc.h"
|
||||||
|
#include "zutils.h"
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#include "recursive.cc"
|
||||||
|
|
||||||
|
void show_help()
|
||||||
{
|
{
|
||||||
std::printf( "Ztest verifies the integrity of the specified compressed files.\n"
|
std::printf( "Ztest verifies the integrity of the specified compressed files.\n"
|
||||||
"Uncompressed files are ignored. If no files are specified, the integrity\n"
|
"Uncompressed files are ignored. If no files are specified, the integrity\n"
|
||||||
|
@ -44,6 +77,15 @@ void show_ztest_help()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int open_instream( std::string & input_filename )
|
||||||
|
{
|
||||||
|
int infd = open( input_filename.c_str(), O_RDONLY | O_BINARY );
|
||||||
|
if( infd < 0 )
|
||||||
|
show_error2( "Can't open input file", input_filename.c_str() );
|
||||||
|
return infd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ztest_stdin( const int infd, int format_index,
|
int ztest_stdin( const int infd, int format_index,
|
||||||
const std::vector< const char * > & ztest_args )
|
const std::vector< const char * > & ztest_args )
|
||||||
{
|
{
|
||||||
|
@ -65,7 +107,7 @@ int ztest_stdin( const int infd, int format_index,
|
||||||
!feed_data( infd, fda[1], magic_data, magic_size ) )
|
!feed_data( infd, fda[1], magic_data, magic_size ) )
|
||||||
_exit( 1 );
|
_exit( 1 );
|
||||||
if( close( fda[1] ) != 0 )
|
if( close( fda[1] ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); _exit( 1 ); }
|
{ show_close_error(); _exit( 1 ); }
|
||||||
_exit( 0 );
|
_exit( 0 );
|
||||||
}
|
}
|
||||||
if( pid < 0 ) // parent
|
if( pid < 0 ) // parent
|
||||||
|
@ -145,3 +187,102 @@ int ztest_file( const int infd, int format_index,
|
||||||
const bool isgzxz = ( format_index == fmt_gz || format_index == fmt_xz );
|
const bool isgzxz = ( format_index == fmt_gz || format_index == fmt_xz );
|
||||||
return wait_for_child( pid, compressor_name, 1, isgzxz );
|
return wait_for_child( pid, compressor_name, 1, isgzxz );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
|
|
||||||
|
|
||||||
|
int main( const int argc, const char * const argv[] )
|
||||||
|
{
|
||||||
|
enum { format_opt = 256, bz2_opt, gz_opt, lz_opt, xz_opt };
|
||||||
|
int infd = -1;
|
||||||
|
int format_index = -1;
|
||||||
|
bool recursive = false;
|
||||||
|
std::string input_filename;
|
||||||
|
std::list< std::string > filenames;
|
||||||
|
std::vector< const char * > ztest_args; // args to ztest, maybe empty
|
||||||
|
invocation_name = argv[0];
|
||||||
|
program_name = "ztest";
|
||||||
|
|
||||||
|
const Arg_parser::Option options[] =
|
||||||
|
{
|
||||||
|
{ 'h', "help", Arg_parser::no },
|
||||||
|
{ 'N', "no-rcfile", Arg_parser::no },
|
||||||
|
{ '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 },
|
||||||
|
{ xz_opt, "xz", Arg_parser::yes },
|
||||||
|
{ 0 , 0, Arg_parser::no } };
|
||||||
|
|
||||||
|
const Arg_parser parser( argc, argv, options );
|
||||||
|
if( parser.error().size() ) // bad option
|
||||||
|
{ show_error( parser.error().c_str(), 0, true ); return 1; }
|
||||||
|
|
||||||
|
maybe_process_config_file( parser );
|
||||||
|
|
||||||
|
int argind = 0;
|
||||||
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
|
{
|
||||||
|
const int code = parser.code( argind );
|
||||||
|
if( !code ) break; // no more options
|
||||||
|
const char * const arg = parser.argument( argind ).c_str();
|
||||||
|
switch( code )
|
||||||
|
{
|
||||||
|
case 'h': show_help(); return 0;
|
||||||
|
case 'N': 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( "Ztest" ); 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;
|
||||||
|
case xz_opt: parse_compressor( arg, fmt_xz, 1 ); break;
|
||||||
|
default : internal_error( "uncaught option" );
|
||||||
|
}
|
||||||
|
} // end process options
|
||||||
|
|
||||||
|
#if defined(__MSVCRT__) || defined(__OS2__)
|
||||||
|
setmode( STDIN_FILENO, O_BINARY );
|
||||||
|
setmode( STDOUT_FILENO, O_BINARY );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( ; argind < parser.arguments(); ++argind )
|
||||||
|
filenames.push_back( parser.argument( argind ) );
|
||||||
|
|
||||||
|
if( filenames.empty() ) filenames.push_back("-");
|
||||||
|
|
||||||
|
int retval = 0;
|
||||||
|
bool error = false;
|
||||||
|
while( next_filename( filenames, input_filename, error, recursive ) )
|
||||||
|
{
|
||||||
|
if( input_filename.empty() ) infd = STDIN_FILENO;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infd = open_instream( input_filename );
|
||||||
|
if( infd < 0 ) { error = true; continue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp;
|
||||||
|
if( infd == STDIN_FILENO )
|
||||||
|
tmp = ztest_stdin( infd, format_index, ztest_args );
|
||||||
|
else tmp = ztest_file( infd, format_index, input_filename, ztest_args );
|
||||||
|
if( tmp > retval ) retval = tmp;
|
||||||
|
|
||||||
|
if( input_filename.size() ) { close( infd ); infd = -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if( std::fclose( stdout ) != 0 )
|
||||||
|
{
|
||||||
|
show_error( "Can't close stdout", errno );
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
if( error && retval == 0 ) retval = 1;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
3
ztest.in
3
ztest.in
|
@ -1,3 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
|
|
||||||
exec "${bindir}"zutils --ztest "$@"
|
|
103
zupdate.cc
103
zupdate.cc
|
@ -37,24 +37,18 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
#include "zutils.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
|
|
||||||
#if CHAR_BIT != 8
|
#ifndef O_BINARY
|
||||||
#error "Environments where CHAR_BIT != 8 are not supported."
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#ifdef O_BINARY
|
#include "recursive.cc"
|
||||||
const int o_binary = O_BINARY;
|
|
||||||
#else
|
|
||||||
const int o_binary = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
void show_help()
|
||||||
void show_zupdate_help()
|
|
||||||
{
|
{
|
||||||
std::printf( "Zupdate recompresses files from bzip2, gzip, and xz formats to lzip format.\n"
|
std::printf( "Zupdate recompresses files from bzip2, gzip, and xz formats to lzip format.\n"
|
||||||
"The originals are compared with the new files and then deleted.\n"
|
"The originals are compared with the new files and then deleted.\n"
|
||||||
|
@ -77,6 +71,7 @@ void show_zupdate_help()
|
||||||
" -h, --help display this help and exit\n"
|
" -h, --help display this help and exit\n"
|
||||||
" -V, --version output version information and exit\n"
|
" -V, --version output version information and exit\n"
|
||||||
" -f, --force do not skip a file even if the .lz exists\n"
|
" -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"
|
" -l, --lzip-verbose pass a -v option to the lzip compressor\n"
|
||||||
" -N, --no-rcfile don't read runtime configuration file\n"
|
" -N, --no-rcfile don't read runtime configuration file\n"
|
||||||
" -q, --quiet suppress all messages\n"
|
" -q, --quiet suppress all messages\n"
|
||||||
|
@ -97,10 +92,10 @@ int cant_execute( const std::string & command, const int status )
|
||||||
{
|
{
|
||||||
if( WIFEXITED( status ) )
|
if( WIFEXITED( status ) )
|
||||||
std::fprintf( stderr, "%s: Error executing '%s'. Exit status = %d.\n",
|
std::fprintf( stderr, "%s: Error executing '%s'. Exit status = %d.\n",
|
||||||
util_name, command.c_str(), WEXITSTATUS( status ) );
|
program_name, command.c_str(), WEXITSTATUS( status ) );
|
||||||
else
|
else
|
||||||
std::fprintf( stderr, "%s: Can't execute '%s'.\n",
|
std::fprintf( stderr, "%s: Can't execute '%s'.\n",
|
||||||
util_name, command.c_str() );
|
program_name, command.c_str() );
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -136,11 +131,13 @@ struct { const char * from; const char * to; int format_index; } const
|
||||||
{ ".txz", ".tar", fmt_xz },
|
{ ".txz", ".tar", fmt_xz },
|
||||||
{ 0, 0, -1 } };
|
{ 0, 0, -1 } };
|
||||||
|
|
||||||
|
int disable_xz = -1; // tri-state bool
|
||||||
|
|
||||||
|
|
||||||
// Returns 0 for success, -1 for file skipped, 1 for error.
|
// Returns 0 for success, -1 for file skipped, 1 for error.
|
||||||
int zupdate_file( const std::string & name, const char * const lzip_name,
|
int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||||
const std::vector< std::string > & lzip_args2,
|
const std::vector< std::string > & lzip_args2,
|
||||||
const bool force )
|
const bool force, const bool keep_input_files )
|
||||||
{
|
{
|
||||||
int format_index = -1;
|
int format_index = -1;
|
||||||
std::string dname; // decompressed_name
|
std::string dname; // decompressed_name
|
||||||
|
@ -158,7 +155,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||||
{
|
{
|
||||||
if( verbosity >= 2 )
|
if( verbosity >= 2 )
|
||||||
std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n",
|
std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n",
|
||||||
util_name, name.c_str(), known_extensions[i].from );
|
program_name, name.c_str(), known_extensions[i].from );
|
||||||
return 0; // ignore this file
|
return 0; // ignore this file
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -169,7 +166,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||||
{
|
{
|
||||||
if( verbosity >= 2 )
|
if( verbosity >= 2 )
|
||||||
std::fprintf( stderr, "%s: Unknown extension in file name '%s' -- ignored.\n",
|
std::fprintf( stderr, "%s: Unknown extension in file name '%s' -- ignored.\n",
|
||||||
util_name, name.c_str() );
|
program_name, name.c_str() );
|
||||||
return 0; // ignore this file
|
return 0; // ignore this file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,14 +175,14 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't stat input file '%s': %s.\n",
|
std::fprintf( stderr, "%s: Can't stat input file '%s': %s.\n",
|
||||||
util_name, name.c_str(), std::strerror( errno ) );
|
program_name, name.c_str(), std::strerror( errno ) );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if( !S_ISREG( in_stats.st_mode ) )
|
if( !S_ISREG( in_stats.st_mode ) )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Input file '%s' is not a regular file.\n",
|
std::fprintf( stderr, "%s: Input file '%s' is not a regular file.\n",
|
||||||
util_name, name.c_str() );
|
program_name, name.c_str() );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,10 +193,20 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
|
std::fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
|
||||||
util_name, rname.c_str() );
|
program_name, rname.c_str() );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( format_index == fmt_xz )
|
||||||
|
{
|
||||||
|
if( disable_xz < 0 )
|
||||||
|
{
|
||||||
|
std::string command( compressor_name ); command += " -V > /dev/null";
|
||||||
|
disable_xz = ( std::system( command.c_str() ) != 0 );
|
||||||
|
}
|
||||||
|
if( disable_xz ) return 0; // ignore this file if no xz installed
|
||||||
|
}
|
||||||
|
|
||||||
if( !lz_exists ) // recompress
|
if( !lz_exists ) // recompress
|
||||||
{
|
{
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
|
@ -280,11 +287,11 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||||
return cant_execute( zcmp_command, status ); }
|
return cant_execute( zcmp_command, status ); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if( std::remove( name.c_str() ) != 0 && errno != ENOENT )
|
if( !keep_input_files && std::remove( name.c_str() ) != 0 && errno != ENOENT )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Can't delete input file '%s': %s.\n",
|
std::fprintf( stderr, "%s: Can't delete input file '%s': %s.\n",
|
||||||
util_name, name.c_str(), std::strerror( errno ) );
|
program_name, name.c_str(), std::strerror( errno ) );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -300,9 +307,10 @@ int main( const int argc, const char * const argv[] )
|
||||||
std::list< std::string > filenames;
|
std::list< std::string > filenames;
|
||||||
std::vector< std::string > lzip_args2; // args to lzip, maybe empty
|
std::vector< std::string > lzip_args2; // args to lzip, maybe empty
|
||||||
bool force = false;
|
bool force = false;
|
||||||
|
bool keep_input_files = false;
|
||||||
bool recursive = false;
|
bool recursive = false;
|
||||||
invocation_name = argv[0];
|
invocation_name = argv[0];
|
||||||
util_name = "zupdate";
|
program_name = "zupdate";
|
||||||
|
|
||||||
const Arg_parser::Option options[] =
|
const Arg_parser::Option options[] =
|
||||||
{
|
{
|
||||||
|
@ -318,6 +326,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ '9', 0, Arg_parser::no },
|
{ '9', 0, Arg_parser::no },
|
||||||
{ 'f', "force", Arg_parser::no },
|
{ 'f', "force", Arg_parser::no },
|
||||||
{ 'h', "help", Arg_parser::no },
|
{ 'h', "help", Arg_parser::no },
|
||||||
|
{ 'k', "keep", Arg_parser::no },
|
||||||
{ 'l', "lzip-verbose", Arg_parser::no },
|
{ 'l', "lzip-verbose", Arg_parser::no },
|
||||||
{ 'N', "no-rcfile", Arg_parser::no },
|
{ 'N', "no-rcfile", Arg_parser::no },
|
||||||
{ 'q', "quiet", Arg_parser::no },
|
{ 'q', "quiet", Arg_parser::no },
|
||||||
|
@ -342,23 +351,24 @@ int main( const int argc, const char * const argv[] )
|
||||||
const int code = parser.code( argind );
|
const int code = parser.code( argind );
|
||||||
if( !code ) break; // no more options
|
if( !code ) break; // no more options
|
||||||
const char * const arg = parser.argument( argind ).c_str();
|
const char * const arg = parser.argument( argind ).c_str();
|
||||||
switch( code ) // common options
|
switch( code )
|
||||||
{
|
{
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
lzip_args2.push_back( "-" ); lzip_args2.back() += code; break;
|
lzip_args2.push_back( "-" ); lzip_args2.back() += code; break;
|
||||||
case 'f': force = true; break;
|
case 'f': force = true; break;
|
||||||
case 'h': show_zupdate_help(); return 0;
|
case 'h': show_help(); return 0;
|
||||||
|
case 'k': keep_input_files = true; break;
|
||||||
case 'l': lzip_args2.push_back( "-v" ); break;
|
case 'l': lzip_args2.push_back( "-v" ); break;
|
||||||
case 'N': continue;
|
case 'N': break;
|
||||||
case 'q': verbosity = -1; lzip_args2.push_back( "-q" ); break;
|
case 'q': verbosity = -1; lzip_args2.push_back( "-q" ); break;
|
||||||
case 'r': recursive = true; break;
|
case 'r': recursive = true; break;
|
||||||
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
||||||
case 'V': show_version( "Zupdate" ); return 0;
|
case 'V': show_version( "Zupdate" ); return 0;
|
||||||
case bz2_opt: parse_compressor( arg, fmt_bz2, 1 ); continue;
|
case bz2_opt: parse_compressor( arg, fmt_bz2, 1 ); break;
|
||||||
case gz_opt: parse_compressor( arg, fmt_gz, 1 ); continue;
|
case gz_opt: parse_compressor( arg, fmt_gz, 1 ); break;
|
||||||
case lz_opt: parse_compressor( arg, fmt_lz, 1 ); continue;
|
case lz_opt: parse_compressor( arg, fmt_lz, 1 ); break;
|
||||||
case xz_opt: parse_compressor( arg, fmt_xz, 1 ); continue;
|
case xz_opt: parse_compressor( arg, fmt_xz, 1 ); break;
|
||||||
default : internal_error( "uncaught option" );
|
default : internal_error( "uncaught option" );
|
||||||
}
|
}
|
||||||
} // end process options
|
} // end process options
|
||||||
|
@ -376,40 +386,15 @@ int main( const int argc, const char * const argv[] )
|
||||||
filenames.push_back( parser.argument( argind ) );
|
filenames.push_back( parser.argument( argind ) );
|
||||||
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
while( !filenames.empty() )
|
bool error = false;
|
||||||
|
while( next_filename( filenames, input_filename, error, recursive, true ) )
|
||||||
{
|
{
|
||||||
input_filename = filenames.front();
|
int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, force,
|
||||||
filenames.pop_front();
|
keep_input_files );
|
||||||
if( !input_filename.size() || input_filename == "-" ) continue;
|
if( tmp < 0 ) error = true;
|
||||||
if( recursive )
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
if( stat( input_filename.c_str(), &st ) == 0 && S_ISDIR( st.st_mode ) )
|
|
||||||
{
|
|
||||||
DIR * const dirp = opendir( input_filename.c_str() );
|
|
||||||
if( !dirp )
|
|
||||||
{
|
|
||||||
show_error2( "Can't open directory", input_filename.c_str() );
|
|
||||||
if( retval < 1 ) retval = 1; continue;
|
|
||||||
}
|
|
||||||
std::list< std::string > tmp_list;
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
filenames.splice( filenames.begin(), tmp_list );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, force );
|
|
||||||
if( tmp < 0 && retval < 1 ) retval = 1;
|
|
||||||
if( tmp > retval ) retval = tmp;
|
if( tmp > retval ) retval = tmp;
|
||||||
if( tmp > 0 ) break;
|
if( tmp > 0 ) break;
|
||||||
}
|
}
|
||||||
|
if( error && retval == 0 ) retval = 1;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
175
zutils.cc
175
zutils.cc
|
@ -27,14 +27,51 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include "zutils.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
|
#include "zutils.h"
|
||||||
|
|
||||||
|
|
||||||
const char * invocation_name = 0;
|
namespace {
|
||||||
const char * util_name = program_name;
|
|
||||||
|
|
||||||
int verbosity = 0;
|
// first magic byte must be different among formats
|
||||||
|
enum { bzip2_magic_size = 3,
|
||||||
|
gzip_magic_size = 2,
|
||||||
|
lzip_magic_size = 4,
|
||||||
|
xz_magic_size = 5 };
|
||||||
|
const uint8_t bzip2_magic[bzip2_magic_size] =
|
||||||
|
{ 0x42, 0x5A, 0x68 }; // "BZh"
|
||||||
|
const uint8_t gzip_magic[gzip_magic_size] =
|
||||||
|
{ 0x1F, 0x8B };
|
||||||
|
const uint8_t lzip_magic[lzip_magic_size] =
|
||||||
|
{ 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP"
|
||||||
|
const uint8_t xz_magic[xz_magic_size] =
|
||||||
|
{ 0xFD, 0x37, 0x7A, 0x58, 0x5A }; // 0xFD, "7zXZ"
|
||||||
|
|
||||||
|
|
||||||
|
// Returns -1 if child not terminated, 2 in case of error, or
|
||||||
|
// exit status of child process 'pid'.
|
||||||
|
//
|
||||||
|
int child_status( const pid_t pid, const char * const name )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
const int tmp = waitpid( pid, &status, WNOHANG );
|
||||||
|
if( tmp == -1 && errno != EINTR )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
std::fprintf( stderr, "%s: Error checking status of '%s': %s.\n",
|
||||||
|
program_name, name, std::strerror( errno ) );
|
||||||
|
_exit( 2 );
|
||||||
|
}
|
||||||
|
if( tmp == 0 ) return -1; // child not terminated
|
||||||
|
if( tmp == pid ) break; // child terminated
|
||||||
|
}
|
||||||
|
if( WIFEXITED( status ) ) return WEXITSTATUS( status );
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
|
|
||||||
|
|
||||||
int parse_format_type( const std::string & arg )
|
int parse_format_type( const std::string & arg )
|
||||||
|
@ -152,7 +189,7 @@ bool set_data_feeder( int * const infdp, Children & children, int format_index )
|
||||||
!feed_data( old_infd, fda[1], magic_data, magic_size ) )
|
!feed_data( old_infd, fda[1], magic_data, magic_size ) )
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
if( close( fda[1] ) != 0 )
|
if( close( fda[1] ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); _exit( 2 ); }
|
{ show_close_error(); _exit( 2 ); }
|
||||||
_exit( 0 );
|
_exit( 0 );
|
||||||
}
|
}
|
||||||
if( pid < 0 ) // parent
|
if( pid < 0 ) // parent
|
||||||
|
@ -201,7 +238,7 @@ bool set_data_feeder( int * const infdp, Children & children, int format_index )
|
||||||
!feed_data( old_infd, fda[1], magic_data, magic_size ) )
|
!feed_data( old_infd, fda[1], magic_data, magic_size ) )
|
||||||
_exit( 2 );
|
_exit( 2 );
|
||||||
if( close( fda[1] ) != 0 )
|
if( close( fda[1] ) != 0 )
|
||||||
{ show_close_error( "data feeder" ); _exit( 2 ); }
|
{ show_close_error(); _exit( 2 ); }
|
||||||
_exit( 0 );
|
_exit( 0 );
|
||||||
}
|
}
|
||||||
if( pid < 0 ) // parent
|
if( pid < 0 ) // parent
|
||||||
|
@ -214,84 +251,6 @@ bool set_data_feeder( int * const infdp, Children & children, int format_index )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void show_help_addr()
|
|
||||||
{
|
|
||||||
std::printf( "\nReport bugs to zutils-bug@nongnu.org\n"
|
|
||||||
"Zutils home page: http://www.nongnu.org/zutils/zutils.html\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_version( const char * const Util_name )
|
|
||||||
{
|
|
||||||
if( !Util_name || !Util_name[0] )
|
|
||||||
std::printf( "%s %s\n", Program_name, PROGVERSION );
|
|
||||||
else
|
|
||||||
std::printf( "%s (%s) %s\n", Util_name, program_name, PROGVERSION );
|
|
||||||
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
|
||||||
std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
|
|
||||||
"This is free software: you are free to change and redistribute it.\n"
|
|
||||||
"There is NO WARRANTY, to the extent permitted by law.\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_error( const char * const msg, const int errcode, const bool help )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
{
|
|
||||||
if( msg && msg[0] )
|
|
||||||
{
|
|
||||||
std::fprintf( stderr, "%s: %s", util_name, msg );
|
|
||||||
if( errcode > 0 )
|
|
||||||
std::fprintf( stderr, ": %s", std::strerror( errcode ) );
|
|
||||||
std::fprintf( stderr, "\n" );
|
|
||||||
}
|
|
||||||
if( help )
|
|
||||||
std::fprintf( stderr, "Try '%s --help' for more information.\n",
|
|
||||||
invocation_name );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_error2( const char * const msg, const char * const name )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: %s '%s': %s.\n",
|
|
||||||
util_name, msg, name, std::strerror( errno ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_close_error( const char * const prog_name )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: Can't close output of %s: %s.\n",
|
|
||||||
util_name, prog_name, std::strerror( errno ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_exec_error( const char * const prog_name )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: Can't exec '%s': %s.\n",
|
|
||||||
util_name, prog_name, std::strerror( errno ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_fork_error( const char * const prog_name )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: Can't fork '%s': %s.\n",
|
|
||||||
util_name, prog_name, std::strerror( errno ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void internal_error( const char * const msg )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: internal error: %s.\n", util_name, msg );
|
|
||||||
std::exit( 3 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int test_format( const int infd, const uint8_t ** const magic_datap,
|
int test_format( const int infd, const uint8_t ** const magic_datap,
|
||||||
int * const magic_sizep )
|
int * const magic_sizep )
|
||||||
{
|
{
|
||||||
|
@ -335,51 +294,3 @@ int test_format( const int infd, const uint8_t ** const magic_datap,
|
||||||
*magic_datap = buf; *magic_sizep = i;
|
*magic_datap = buf; *magic_sizep = i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wait_for_child( const pid_t pid, const char * const name,
|
|
||||||
const int eretval, const bool isgzxz )
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
while( waitpid( pid, &status, 0 ) == -1 )
|
|
||||||
{
|
|
||||||
if( errno != EINTR )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: Error waiting termination of '%s': %s.\n",
|
|
||||||
util_name, name, std::strerror( errno ) );
|
|
||||||
_exit( eretval );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( WIFEXITED( status ) )
|
|
||||||
{
|
|
||||||
const int tmp = WEXITSTATUS( status );
|
|
||||||
if( isgzxz && eretval == 1 && tmp == 1 ) return 2; // for ztest
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
return eretval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int child_status( const pid_t pid, const char * const name,
|
|
||||||
const int eretval )
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
const int tmp = waitpid( pid, &status, WNOHANG );
|
|
||||||
if( tmp == -1 && errno != EINTR )
|
|
||||||
{
|
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: Error checking status of '%s': %s.\n",
|
|
||||||
util_name, name, std::strerror( errno ) );
|
|
||||||
_exit( eretval );
|
|
||||||
}
|
|
||||||
if( tmp == 0 ) return -1; // child not terminated
|
|
||||||
if( tmp == pid ) break; // child terminated
|
|
||||||
}
|
|
||||||
|
|
||||||
if( WIFEXITED( status ) ) return WEXITSTATUS( status );
|
|
||||||
return eretval;
|
|
||||||
}
|
|
||||||
|
|
52
zutils.h
52
zutils.h
|
@ -15,37 +15,6 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char * const Program_name = "Zutils";
|
|
||||||
const char * const program_name = "zutils";
|
|
||||||
const char * const config_file_name = "zutilsrc";
|
|
||||||
const char * const program_year = "2013";
|
|
||||||
extern const char * invocation_name;
|
|
||||||
extern const char * util_name;
|
|
||||||
|
|
||||||
extern int verbosity;
|
|
||||||
|
|
||||||
enum { fmt_bz2, fmt_gz, fmt_lz, fmt_xz, num_formats };
|
|
||||||
const char * const format_names[num_formats] = { "bz2", "gz", "lz", "xz" };
|
|
||||||
const char * const simple_extensions[num_formats] =
|
|
||||||
{ ".bz2", ".gz", ".lz", ".xz" };
|
|
||||||
const int8_t format_order[num_formats] =
|
|
||||||
{ fmt_lz, fmt_bz2, fmt_gz, fmt_xz }; // search order
|
|
||||||
|
|
||||||
// first magic byte must be different among formats
|
|
||||||
enum { bzip2_magic_size = 3,
|
|
||||||
gzip_magic_size = 2,
|
|
||||||
lzip_magic_size = 4,
|
|
||||||
xz_magic_size = 5 };
|
|
||||||
const uint8_t bzip2_magic[bzip2_magic_size] =
|
|
||||||
{ 0x42, 0x5A, 0x68 }; // "BZh"
|
|
||||||
const uint8_t gzip_magic[gzip_magic_size] =
|
|
||||||
{ 0x1F, 0x8B };
|
|
||||||
const uint8_t lzip_magic[lzip_magic_size] =
|
|
||||||
{ 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP"
|
|
||||||
const uint8_t xz_magic[xz_magic_size] =
|
|
||||||
{ 0xFD, 0x37, 0x7A, 0x58, 0x5A }; // 0xFD, "7zXZ"
|
|
||||||
|
|
||||||
|
|
||||||
int parse_format_type( const std::string & arg );
|
int parse_format_type( const std::string & arg );
|
||||||
|
|
||||||
int readblock( const int fd, uint8_t * const buf, const int size );
|
int readblock( const int fd, uint8_t * const buf, const int size );
|
||||||
|
@ -61,28 +30,7 @@ struct Children
|
||||||
bool good_status( const Children & children, const bool finished );
|
bool good_status( const Children & children, const bool finished );
|
||||||
bool set_data_feeder( int * const infdp, Children & children, int format_index );
|
bool set_data_feeder( int * const infdp, Children & children, int format_index );
|
||||||
|
|
||||||
void show_help_addr();
|
|
||||||
void show_version( const char * const Util_name = 0 );
|
|
||||||
void show_error( const char * const msg, const int errcode = 0,
|
|
||||||
const bool help = false );
|
|
||||||
void show_error2( const char * const msg, const char * const name );
|
|
||||||
void show_close_error( const char * const prog_name );
|
|
||||||
void show_exec_error( const char * const prog_name );
|
|
||||||
void show_fork_error( const char * const prog_name );
|
|
||||||
void internal_error( const char * const msg );
|
|
||||||
|
|
||||||
// Returns format index or -1 if uncompressed
|
// Returns format index or -1 if uncompressed
|
||||||
//
|
//
|
||||||
int test_format( const int infd, const uint8_t ** const magic_datap,
|
int test_format( const int infd, const uint8_t ** const magic_datap,
|
||||||
int * const magic_sizep );
|
int * const magic_sizep );
|
||||||
|
|
||||||
// Returns exit status of child process 'pid', or 'eretval' in case of error.
|
|
||||||
//
|
|
||||||
int wait_for_child( const pid_t pid, const char * const name,
|
|
||||||
const int eretval = 2, const bool isgzxz = false );
|
|
||||||
|
|
||||||
// Returns -1 if child not terminated, 'eretval' in case of error, or
|
|
||||||
// exit status of child process 'pid'.
|
|
||||||
//
|
|
||||||
int child_status( const pid_t pid, const char * const name,
|
|
||||||
const int eretval = 2 );
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue