Merging upstream version 1.12~pre2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
64fda76e2e
commit
f4079ace26
19 changed files with 422 additions and 222 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,11 +1,26 @@
|
|||
2022-04-12 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.12-pre2 released.
|
||||
* zgrep.cc: Accept option '-Z, --null'. (Reported by Leah Neukirchen).
|
||||
* zupdate.cc: New options '-e, --expand-extensions',
|
||||
'-i, --ignore-errors'.
|
||||
* Support compress'd (.Z) files through gzip in all utilities.
|
||||
|
||||
2022-03-06 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.12-pre1 released.
|
||||
* zgrep.cc: Accept options '-G, --basic-regexp', '--label=<label>',
|
||||
'--line-buffered', '-P, --perl-regexp', '--silent',
|
||||
'-T, --initial-tab', '-U, --binary'. (Reported by Chris Jamboretz).
|
||||
|
||||
2022-01-25 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.11 released.
|
||||
* zcmp.cc, zdiff.cc (main): Fix race returning 1 instead of 2 when a
|
||||
compressor is not found or when the wrong format is forced.
|
||||
* zcmp.cc (getnum): Show option name and valid range if error.
|
||||
* All tools: Show option name if error in option argument.
|
||||
* Add support for zstd format to all tools.
|
||||
* All utilities: Show option name if error in option argument.
|
||||
* Add support for zstd format to all utilities.
|
||||
* 'zdiff -v -V' now prints the version of the diff program used.
|
||||
* 'zgrep --verbose -V' now prints the version of the grep program used.
|
||||
* zutils.texi: Document recompression of read-only files by linking.
|
||||
|
@ -18,7 +33,7 @@
|
|||
* zdiff.cc (set_fifonames): Encode pid in little endian order.
|
||||
* zupdate.cc (zupdate_file): Fix a portability issue with Solaris 10.
|
||||
* zutils.texi: Document that 'zgrep -L' fails with GNU grep 3.2 to 3.4.
|
||||
* check.sh: Test empty input files with all tools except zupdate.
|
||||
* check.sh: Test empty input files with all utilities except zupdate.
|
||||
|
||||
2020-06-27 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
|
@ -95,7 +110,7 @@
|
|||
|
||||
* Version 1.2 released.
|
||||
* New utility; zupdate.
|
||||
* Remove zutils executable. Utils are now independent executables.
|
||||
* Remove zutils executable. Utilities are now independent executables.
|
||||
* zgrep.cc: Fix the exit status returned on error.
|
||||
* zutils.texinfo: Rename to zutils.texi.
|
||||
|
||||
|
|
38
NEWS
38
NEWS
|
@ -1,30 +1,16 @@
|
|||
Changes in version 1.11:
|
||||
Changes in version 1.12:
|
||||
|
||||
A race has been fixed in zcmp and zdiff that sometimes made them return 1
|
||||
(files differ) instead of 2 (trouble) when a compressor is not found or when
|
||||
the wrong format is forced.
|
||||
zgrep now also accepts the following options: '-G, --basic-regexp',
|
||||
'--label=<label>', '--line-buffered', '-P, --perl-regexp', '--silent',
|
||||
'-T, --initial-tab', '-U, --binary', and '-Z, --null'.
|
||||
(Reported by Chris Jamboretz and Leah Neukirchen).
|
||||
|
||||
In case of error in an argument to a command line option, all tools now show
|
||||
the name of the option.
|
||||
zupdate now accepts option '-e, --expand-extensions', which makes it expand
|
||||
combined file name extensions; tgz -> tar.lz.
|
||||
|
||||
In case of error in a numerical argument to a command line option, zcmp
|
||||
now shows the name of the option and the range of valid values.
|
||||
zupdate now also accepts option '-i, --ignore-errors', which makes it ignore
|
||||
non-fatal errors.
|
||||
|
||||
Support for the zstd format has been added to all tools. This allows, among
|
||||
other things, zupdating zstd files to lzip format for long-term archiving,
|
||||
and using zcmp along with the unzcrash tool (from the lziprecover package)
|
||||
to test zstd files.
|
||||
|
||||
'zdiff --verbose --version' now prints the version of the diff program used
|
||||
if it supports the option '--version'.
|
||||
|
||||
'zgrep --verbose --version' now prints the version of the grep program used
|
||||
if it supports the option '--version'.
|
||||
|
||||
It has been documented in the manual how to recompress files with zupdate
|
||||
from a read-only file system to another place by first linking the files
|
||||
from the destination directory and then compressing the links:
|
||||
'ln -s /src/foo.gz . && zupdate foo.gz'
|
||||
|
||||
The texinfo category of the manual has been changed from 'Data Compression'
|
||||
to 'Compression' to match that of gzip. (Reported by Alfred M. Szmidt).
|
||||
All utilities now support compress'd (.Z) files through gzip. For this to
|
||||
work, the gzip program used (for example GNU gzip) must be able to
|
||||
decompress .Z files.
|
||||
|
|
7
README
7
README
|
@ -30,10 +30,9 @@ example, use the following command to search for the string 'foo' in
|
|||
gzip and lzip files only:
|
||||
'zgrep foo -r --format=gz,lz somedir somefile.tar'.
|
||||
|
||||
FORMAT NOTE 2: If the option '--force-format' is given, the files are
|
||||
passed to the corresponding decompressor without verifying their format,
|
||||
allowing for example the processing of compress'd (.Z) files with gzip:
|
||||
'zcmp --force-format=gz file.Z file.lz'.
|
||||
FORMAT NOTE 2: The standard POSIX compress format (.Z) is obsolete and is
|
||||
only supported through gzip. For this to work, the gzip program used (for
|
||||
example GNU gzip) must be able to decompress .Z files.
|
||||
|
||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never have
|
||||
been compressed. Decompressed is used to refer to data which have undergone
|
||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -6,7 +6,7 @@
|
|||
# to copy, distribute, and modify it.
|
||||
|
||||
pkgname=zutils
|
||||
pkgversion=1.11
|
||||
pkgversion=1.12-pre2
|
||||
srctrigger=doc/${pkgname}.texi
|
||||
|
||||
# clear some things potentially inherited from environment.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
|
||||
.TH ZCAT "1" "January 2022" "zutils 1.11" "User Commands"
|
||||
.TH ZCAT "1" "April 2022" "zutils 1.12-pre2" "User Commands"
|
||||
.SH NAME
|
||||
zcat \- decompress and concatenate files to standard output
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
|
||||
.TH ZCMP "1" "January 2022" "zutils 1.11" "User Commands"
|
||||
.TH ZCMP "1" "April 2022" "zutils 1.12-pre2" "User Commands"
|
||||
.SH NAME
|
||||
zcmp \- decompress and compare two files byte by byte
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
|
||||
.TH ZDIFF "1" "January 2022" "zutils 1.11" "User Commands"
|
||||
.TH ZDIFF "1" "April 2022" "zutils 1.12-pre2" "User Commands"
|
||||
.SH NAME
|
||||
zdiff \- decompress and compare two files line by line
|
||||
.SH SYNOPSIS
|
||||
|
@ -98,7 +98,7 @@ verbose mode (for \fB\-\-version\fR)
|
|||
ignore all white space
|
||||
.TP
|
||||
\fB\-W\fR, \fB\-\-width=\fR<n>
|
||||
output at most <n> print columns
|
||||
output at most <n> print columns (for \fB\-y\fR)
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-side\-by\-side\fR
|
||||
output in two columns
|
||||
|
|
25
doc/zgrep.1
25
doc/zgrep.1
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
|
||||
.TH ZGREP "1" "January 2022" "zutils 1.11" "User Commands"
|
||||
.TH ZGREP "1" "April 2022" "zutils 1.12-pre2" "User Commands"
|
||||
.SH NAME
|
||||
zgrep \- search compressed files for a regular expression
|
||||
.SH SYNOPSIS
|
||||
|
@ -69,6 +69,9 @@ obtain patterns from <file>
|
|||
\fB\-F\fR, \fB\-\-fixed\-strings\fR
|
||||
<pattern> is a set of newline\-separated strings
|
||||
.TP
|
||||
\fB\-G\fR, \fB\-\-basic\-regexp\fR
|
||||
<pattern> is a basic regular expression (default)
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-no\-filename\fR
|
||||
suppress the prefixing file name on output
|
||||
.TP
|
||||
|
@ -87,6 +90,12 @@ only print names of files containing matches
|
|||
\fB\-L\fR, \fB\-\-files\-without\-match\fR
|
||||
only print names of files containing no matches
|
||||
.TP
|
||||
\fB\-\-label=\fR<label>
|
||||
use <label> as file name for standard input
|
||||
.TP
|
||||
\fB\-\-line\-buffered\fR
|
||||
flush output on every line
|
||||
.TP
|
||||
\fB\-m\fR, \fB\-\-max\-count=\fR<n>
|
||||
stop after <n> matches
|
||||
.TP
|
||||
|
@ -105,7 +114,10 @@ show only the part of a line matching <pattern>
|
|||
\fB\-O\fR, \fB\-\-force\-format=\fR<fmt>
|
||||
force the format given (bz2, gz, lz, xz, zst)
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
\fB\-P\fR, \fB\-\-perl\-regexp\fR
|
||||
<pattern> is a Perl regular expression
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR, \fB\-\-silent\fR
|
||||
suppress all messages
|
||||
.TP
|
||||
\fB\-r\fR, \fB\-\-recursive\fR
|
||||
|
@ -117,6 +129,12 @@ recursively follow symbolic links
|
|||
\fB\-s\fR, \fB\-\-no\-messages\fR
|
||||
suppress error messages
|
||||
.TP
|
||||
\fB\-T\fR, \fB\-\-initial\-tab\fR
|
||||
make tabs line up (if needed)
|
||||
.TP
|
||||
\fB\-U\fR, \fB\-\-binary\fR
|
||||
don't strip CR characters at EOL (DOS/Windows)
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-invert\-match\fR
|
||||
select non\-matching lines
|
||||
.TP
|
||||
|
@ -129,6 +147,9 @@ match only whole words
|
|||
\fB\-x\fR, \fB\-\-line\-regexp\fR
|
||||
match only whole lines
|
||||
.TP
|
||||
\fB\-Z\fR, \fB\-\-null\fR
|
||||
print 0 byte (ASCII NUL) after file name
|
||||
.TP
|
||||
\fB\-\-bz2=\fR<command>
|
||||
set compressor and options for bzip2 format
|
||||
.TP
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
|
||||
.TH ZTEST "1" "January 2022" "zutils 1.11" "User Commands"
|
||||
.TH ZTEST "1" "April 2022" "zutils 1.12-pre2" "User Commands"
|
||||
.SH NAME
|
||||
ztest \- verify the integrity of compressed files
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
|
||||
.TH ZUPDATE "1" "January 2022" "zutils 1.11" "User Commands"
|
||||
.TH ZUPDATE "1" "April 2022" "zutils 1.12-pre2" "User Commands"
|
||||
.SH NAME
|
||||
zupdate \- recompress bzip2, gzip, xz, zstd files to lzip format
|
||||
.SH SYNOPSIS
|
||||
|
@ -26,12 +26,15 @@ compressed files are never overwritten nor deleted.
|
|||
.PP
|
||||
The names of the original files must have one of the following extensions:
|
||||
.PP
|
||||
\&'.bz2', '.gz', '.xz', or '.zst', which are recompressed to '.lz'.
|
||||
\&'.bz2', '.gz', '.xz', '.zst', or '.Z', which are recompressed to '.lz'.
|
||||
.PP
|
||||
\&'.tbz', '.tbz2', '.tgz', '.txz', or '.tzst', which are recompressed to '.tlz'.
|
||||
.PP
|
||||
Exit status is 0 if all the compressed files were successfully recompressed
|
||||
(if needed), compared, and deleted (if requested). Non\-zero otherwise.
|
||||
(if needed), compared, and deleted (if requested). 1 if a non\-fatal error
|
||||
occurred (file not found or not regular, or has invalid format, or can't be
|
||||
deleted). 2 if a fatal error occurred (compressor can't be run, or
|
||||
comparison fails).
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
|
@ -40,9 +43,15 @@ display this help and exit
|
|||
\fB\-V\fR, \fB\-\-version\fR
|
||||
output version information and exit
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-expand\-extensions\fR
|
||||
expand combined extensions; tgz \-> tar.lz
|
||||
.TP
|
||||
\fB\-f\fR, \fB\-\-force\fR
|
||||
don't skip a file even if the .lz exists
|
||||
.TP
|
||||
\fB\-i\fR, \fB\-\-ignore\-errors\fR
|
||||
ignore non\-fatal errors
|
||||
.TP
|
||||
\fB\-k\fR, \fB\-\-keep\fR
|
||||
keep (don't delete) input files
|
||||
.TP
|
||||
|
|
118
doc/zutils.info
118
doc/zutils.info
|
@ -11,7 +11,7 @@ File: zutils.info, Node: Top, Next: Introduction, Up: (dir)
|
|||
Zutils Manual
|
||||
*************
|
||||
|
||||
This manual is for Zutils (version 1.11, 25 January 2022).
|
||||
This manual is for Zutils (version 1.12-pre2, 12 April 2022).
|
||||
|
||||
* Menu:
|
||||
|
||||
|
@ -69,10 +69,9 @@ of formats in recursive mode and when trying compressed file names. For
|
|||
example, use the following command to search for the string 'foo' in gzip
|
||||
and lzip files only: 'zgrep foo -r --format=gz,lz somedir somefile.tar'.
|
||||
|
||||
FORMAT NOTE 2: If the option '--force-format' is given, the files are
|
||||
passed to the corresponding decompressor without verifying their format,
|
||||
allowing for example the processing of compress'd (.Z) files with gzip:
|
||||
'zcmp --force-format=gz file.Z file.lz'.
|
||||
FORMAT NOTE 2: The standard POSIX compress format (.Z) is obsolete and is
|
||||
only supported through gzip. For this to work, the gzip program used (for
|
||||
example GNU gzip) must be able to decompress .Z files.
|
||||
|
||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never
|
||||
have been compressed. Decompressed is used to refer to data which have
|
||||
|
@ -131,7 +130,7 @@ here. *Note Argument syntax: (arg_parser)Argument syntax.
|
|||
extensions:
|
||||
|
||||
bz2 enables .bz2 .tbz .tbz2
|
||||
gz enables .gz .tgz
|
||||
gz enables .gz .tgz .Z
|
||||
lz enables .lz .tlz
|
||||
xz enables .xz .txz
|
||||
zst enables .zst .tzst
|
||||
|
@ -468,6 +467,15 @@ program used supports them):
|
|||
'--ignore-all-space'
|
||||
Ignore all white space.
|
||||
|
||||
'-W COLUMNS'
|
||||
'--width=COLUMNS'
|
||||
Output at most the specified number of print columns per line in side
|
||||
by side format.
|
||||
|
||||
'-y'
|
||||
'--side-by-side'
|
||||
Use the side by side output format.
|
||||
|
||||
|
||||
|
||||
File: zutils.info, Node: Zgrep, Next: Ztest, Prev: Zdiff, Up: Top
|
||||
|
@ -496,8 +504,9 @@ directory, and nonrecursive searches read standard input.
|
|||
An exit status of 0 means at least one match was found, 1 means no matches
|
||||
were found, and 2 means trouble.
|
||||
|
||||
zgrep supports the following options (some options only work if the grep
|
||||
program used supports them):
|
||||
zgrep supports the following options (Some options only work if the grep
|
||||
program used supports them. Options -h, -H, -r, -R, and -Z are managed by
|
||||
zgrep and not passed to grep):
|
||||
|
||||
'-a'
|
||||
'--text'
|
||||
|
@ -532,7 +541,7 @@ program used supports them):
|
|||
|
||||
'-E'
|
||||
'--extended-regexp'
|
||||
Treat PATTERN as an extended regular expression.
|
||||
Interpret PATTERN as an extended regular expression (ERE).
|
||||
|
||||
'-f FILE'
|
||||
'--file=FILE'
|
||||
|
@ -543,7 +552,12 @@ program used supports them):
|
|||
|
||||
'-F'
|
||||
'--fixed-strings'
|
||||
Treat PATTERN as a set of newline-separated strings.
|
||||
Interpret PATTERN as a set of newline-separated strings.
|
||||
|
||||
'-G'
|
||||
'--basic-regexp'
|
||||
Interpret PATTERN as a basic regular expression (BRE). This is the
|
||||
default.
|
||||
|
||||
'-h'
|
||||
'--no-filename'
|
||||
|
@ -573,6 +587,13 @@ program used supports them):
|
|||
of a wrong change in the exit status of grep, which was reverted in
|
||||
GNU grep 3.5.
|
||||
|
||||
'--label=LABEL'
|
||||
Display input actually coming from standard input as input coming from
|
||||
file LABEL.
|
||||
|
||||
'--line-buffered'
|
||||
Use line buffering on output. This may cause a performance penalty.
|
||||
|
||||
'-m N'
|
||||
'--max-count=N'
|
||||
Stop after N matches.
|
||||
|
@ -593,8 +614,13 @@ program used supports them):
|
|||
format, and the exact file name must be given. Other names won't be
|
||||
tried.
|
||||
|
||||
'-P'
|
||||
'--perl-regexp'
|
||||
Interpret PATTERN as a Perl-compatible regular expression (PCRE).
|
||||
|
||||
'-q'
|
||||
'--quiet'
|
||||
'--silent'
|
||||
Suppress all messages. Exit immediately with zero status if any match
|
||||
is found, even if an error was detected.
|
||||
|
||||
|
@ -613,6 +639,16 @@ program used supports them):
|
|||
'--no-messages'
|
||||
Suppress error messages about nonexistent or unreadable files.
|
||||
|
||||
'-T'
|
||||
'--initial-tab'
|
||||
Make sure that the first character of actual line content lies on a tab
|
||||
stop, so that the alignment of tabs looks normal.
|
||||
|
||||
'-U'
|
||||
'--binary'
|
||||
Use binary I/O on platforms affected by the bug known as "text mode
|
||||
I/O". (MS-DOS, MS-Windows, OS/2).
|
||||
|
||||
'-v'
|
||||
'--invert-match'
|
||||
Select non-matching lines.
|
||||
|
@ -629,6 +665,14 @@ program used supports them):
|
|||
'--line-regexp'
|
||||
Match only whole lines.
|
||||
|
||||
'-Z'
|
||||
'--null'
|
||||
Output a zero byte (the ASCII NUL character) instead of the character
|
||||
that normally follows a file name. For example, 'zgrep -lZ' outputs a
|
||||
zero byte after each file name instead of the usual newline. This
|
||||
option makes the output unambiguous, even in the presence of file
|
||||
names containing unusual characters like newlines.
|
||||
|
||||
|
||||
|
||||
File: zutils.info, Node: Ztest, Next: Zupdate, Prev: Zgrep, Up: Top
|
||||
|
@ -675,9 +719,7 @@ compressed file is corrupt or invalid.
|
|||
'gz', 'lz', 'xz', and 'zst'. If this option is used, the files are
|
||||
passed to the corresponding decompressor without verifying their
|
||||
format, and any files in a format that the decompressor can't
|
||||
understand will fail. For example, '--force-format=gz' can test
|
||||
gzipped (.gz) and compress'd (.Z) files if the compressor used is GNU
|
||||
gzip.
|
||||
understand will fail.
|
||||
|
||||
'-q'
|
||||
'--quiet'
|
||||
|
@ -735,7 +777,7 @@ pair of files in a multiformat set of files.
|
|||
|
||||
The names of the original files must have one of the following
|
||||
extensions:
|
||||
'.bz2', '.gz', '.xz', or '.zst', which are recompressed to '.lz';
|
||||
'.bz2', '.gz', '.xz', '.zst', or '.Z', which are recompressed to '.lz';
|
||||
'.tbz', '.tbz2', '.tgz', '.txz', or '.tzst', which are recompressed to
|
||||
'.tlz'.
|
||||
Keeping the combined extensions ('.tgz' -> '.tlz') may be useful when
|
||||
|
@ -745,21 +787,29 @@ recompressing Slackware packages, for example.
|
|||
If the decompressor for the xz or zstd formats is not found, the
|
||||
corresponding files are ignored.
|
||||
|
||||
Recompressing a file is much like copying or moving it; therefore zupdate
|
||||
preserves the access and modification dates, permissions, and, when
|
||||
possible, ownership of the file just as 'cp -p' does. (If the user ID or
|
||||
the group ID can't be duplicated, the file permission bits S_ISUID and
|
||||
S_ISGID are cleared).
|
||||
Recompressing a file is much like copying or moving it. Therefore zupdate
|
||||
preserves the access and modification dates, permissions, and, if you have
|
||||
appropriate privileges, ownership of the file just as 'cp -p' does. (If the
|
||||
user ID or the group ID can't be duplicated, the file permission bits
|
||||
S_ISUID and S_ISGID are cleared).
|
||||
|
||||
The format for running zupdate is:
|
||||
|
||||
zupdate [OPTIONS] [FILES]
|
||||
|
||||
Exit status is 0 if all the compressed files were successfully recompressed
|
||||
(if needed), compared, and deleted (if requested). Non-zero otherwise.
|
||||
(if needed), compared, and deleted (if requested). 1 if a non-fatal error
|
||||
occurred (file not found or not regular, or has invalid format, or can't be
|
||||
deleted). 2 if a fatal error occurred (compressor can't be run, or
|
||||
comparison fails).
|
||||
|
||||
zupdate supports the following options:
|
||||
|
||||
'-e'
|
||||
'--expand-extensions'
|
||||
Expand combined file name extensions; recompress '.tbz', '.tbz2',
|
||||
'.tgz', '.txz', and '.tzst' to 'tar.lz'.
|
||||
|
||||
'-f'
|
||||
'--force'
|
||||
Don't skip a file for which a lzip compressed version already exists.
|
||||
|
@ -767,6 +817,10 @@ Exit status is 0 if all the compressed files were successfully recompressed
|
|||
the existing lzip file and deletes the input file if both contents are
|
||||
identical.
|
||||
|
||||
'-i'
|
||||
'--ignore-errors'
|
||||
Ignore non-fatal errors. (See exit status above).
|
||||
|
||||
'-k'
|
||||
'--keep'
|
||||
Keep (don't delete) the input file after comparing it with the lzip
|
||||
|
@ -845,18 +899,18 @@ Concept index
|
|||
|
||||
Tag Table:
|
||||
Node: Top217
|
||||
Node: Introduction1147
|
||||
Node: Common options3947
|
||||
Ref: compressor-requirements6181
|
||||
Node: The zutilsrc file6576
|
||||
Node: Zcat7544
|
||||
Node: Zcmp10119
|
||||
Node: Zdiff12620
|
||||
Node: Zgrep15478
|
||||
Node: Ztest19819
|
||||
Node: Zupdate22513
|
||||
Node: Problems26607
|
||||
Node: Concept index27141
|
||||
Node: Introduction1150
|
||||
Node: Common options3897
|
||||
Ref: compressor-requirements6134
|
||||
Node: The zutilsrc file6529
|
||||
Node: Zcat7497
|
||||
Node: Zcmp10072
|
||||
Node: Zdiff12573
|
||||
Node: Zgrep15623
|
||||
Node: Ztest21115
|
||||
Node: Zupdate23681
|
||||
Node: Problems28191
|
||||
Node: Concept index28725
|
||||
|
||||
End Tag Table
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
@finalout
|
||||
@c %**end of header
|
||||
|
||||
@set UPDATED 25 January 2022
|
||||
@set VERSION 1.11
|
||||
@set UPDATED 12 April 2022
|
||||
@set VERSION 1.12-pre2
|
||||
|
||||
@dircategory Compression
|
||||
@direntry
|
||||
|
@ -94,10 +94,9 @@ example, use the following command to search for the string @samp{foo} in
|
|||
gzip and lzip files only:
|
||||
@w{@samp{zgrep foo -r --format=gz,lz somedir somefile.tar}}.
|
||||
|
||||
FORMAT NOTE 2: If the option @samp{--force-format} is given, the files are
|
||||
passed to the corresponding decompressor without verifying their format,
|
||||
allowing for example the processing of compress'd (.Z) files with gzip:
|
||||
@w{@samp{zcmp --force-format=gz file.Z file.lz}}.
|
||||
FORMAT NOTE 2: The standard POSIX compress format (.Z) is obsolete and is
|
||||
only supported through gzip. For this to work, the gzip program used (for
|
||||
example GNU gzip) must be able to decompress .Z files.
|
||||
|
||||
LANGUAGE NOTE: Uncompressed = not compressed = plain data; it may never have
|
||||
been compressed. Decompressed is used to refer to data which have undergone
|
||||
|
@ -163,7 +162,7 @@ extensions:
|
|||
|
||||
@multitable {bz2} {enables} {any other file name}
|
||||
@item bz2 @tab enables @tab .bz2 .tbz .tbz2
|
||||
@item gz @tab enables @tab .gz .tgz
|
||||
@item gz @tab enables @tab .gz .tgz .Z
|
||||
@item lz @tab enables @tab .lz .tlz
|
||||
@item xz @tab enables @tab .xz .txz
|
||||
@item zst @tab enables @tab .zst .tzst
|
||||
|
@ -531,6 +530,15 @@ program used.
|
|||
@itemx --ignore-all-space
|
||||
Ignore all white space.
|
||||
|
||||
@item -W @var{columns}
|
||||
@itemx --width=@var{columns}
|
||||
Output at most the specified number of print columns per line in side by
|
||||
side format.
|
||||
|
||||
@item -y
|
||||
@itemx --side-by-side
|
||||
Use the side by side output format.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
|
@ -564,8 +572,9 @@ zgrep [@var{options}] @var{pattern} [@var{files}]
|
|||
An exit status of 0 means at least one match was found, 1 means no
|
||||
matches were found, and 2 means trouble.
|
||||
|
||||
zgrep supports the following options (some options only work if the grep
|
||||
program used supports them):
|
||||
zgrep supports the following options (Some options only work if the grep
|
||||
program used supports them. Options -h, -H, -r, -R, and -Z are managed by
|
||||
zgrep and not passed to grep):
|
||||
|
||||
@table @code
|
||||
@item -a
|
||||
|
@ -602,7 +611,7 @@ Use @var{pattern} as the pattern to match.
|
|||
|
||||
@item -E
|
||||
@itemx --extended-regexp
|
||||
Treat @var{pattern} as an extended regular expression.
|
||||
Interpret @var{pattern} as an extended regular expression (ERE).
|
||||
|
||||
@item -f @var{file}
|
||||
@itemx --file=@var{file}
|
||||
|
@ -614,7 +623,12 @@ used with @samp{-e} to read @var{file} only once, for example if
|
|||
|
||||
@item -F
|
||||
@itemx --fixed-strings
|
||||
Treat @var{pattern} as a set of newline-separated strings.
|
||||
Interpret @var{pattern} as a set of newline-separated strings.
|
||||
|
||||
@item -G
|
||||
@itemx --basic-regexp
|
||||
Interpret @var{pattern} as a basic regular expression (BRE). This is the
|
||||
default.
|
||||
|
||||
@item -h
|
||||
@itemx --no-filename
|
||||
|
@ -643,6 +657,13 @@ Note: option -L fails (prints wrong results, returns wrong status, and even
|
|||
hangs) when using GNU grep versions 3.2 to 3.4 inclusive because of a wrong
|
||||
change in the exit status of grep, which was reverted in GNU grep 3.5.
|
||||
|
||||
@item --label=@var{label}
|
||||
Display input actually coming from standard input as input coming from file
|
||||
@var{label}.
|
||||
|
||||
@item --line-buffered
|
||||
Use line buffering on output. This may cause a performance penalty.
|
||||
|
||||
@item -m @var{n}
|
||||
@itemx --max-count=@var{n}
|
||||
Stop after @var{n} matches.
|
||||
|
@ -663,8 +684,13 @@ is used, the files are passed to the corresponding decompressor without
|
|||
verifying their format, and the exact file name must be given. Other names
|
||||
won't be tried.
|
||||
|
||||
@item -P
|
||||
@itemx --perl-regexp
|
||||
Interpret @var{pattern} as a Perl-compatible regular expression (PCRE).
|
||||
|
||||
@item -q
|
||||
@itemx --quiet
|
||||
@itemx --silent
|
||||
Suppress all messages. Exit immediately with zero status if any match is
|
||||
found, even if an error was detected.
|
||||
|
||||
|
@ -683,6 +709,16 @@ recursively, following all symbolic links.
|
|||
@itemx --no-messages
|
||||
Suppress error messages about nonexistent or unreadable files.
|
||||
|
||||
@item -T
|
||||
@itemx --initial-tab
|
||||
Make sure that the first character of actual line content lies on a tab
|
||||
stop, so that the alignment of tabs looks normal.
|
||||
|
||||
@item -U
|
||||
@itemx --binary
|
||||
Use binary I/O on platforms affected by the bug known as "text mode I/O".
|
||||
(MS-DOS, MS-Windows, OS/2).
|
||||
|
||||
@item -v
|
||||
@itemx --invert-match
|
||||
Select non-matching lines.
|
||||
|
@ -699,6 +735,14 @@ Match only whole words.
|
|||
@itemx --line-regexp
|
||||
Match only whole lines.
|
||||
|
||||
@item -Z
|
||||
@itemx --null
|
||||
Output a zero byte (the ASCII NUL character) instead of the character that
|
||||
normally follows a file name. For example, 'zgrep -lZ' outputs a zero byte
|
||||
after each file name instead of the usual newline. This option makes the
|
||||
output unambiguous, even in the presence of file names containing unusual
|
||||
characters like newlines.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
|
@ -752,8 +796,7 @@ Force the compressed format given. Valid values for @var{format} are
|
|||
@samp{bz2}, @samp{gz}, @samp{lz}, @samp{xz}, and @samp{zst}. If this option
|
||||
is used, the files are passed to the corresponding decompressor without
|
||||
verifying their format, and any files in a format that the decompressor
|
||||
can't understand will fail. For example, @samp{--force-format=gz} can test
|
||||
gzipped (.gz) and compress'd (.Z) files if the compressor used is GNU gzip.
|
||||
can't understand will fail.
|
||||
|
||||
@item -q
|
||||
@itemx --quiet
|
||||
|
@ -810,8 +853,8 @@ Combining the options @samp{--force} and @samp{--keep}, as in
|
|||
between each pair of files in a multiformat set of files.
|
||||
|
||||
The names of the original files must have one of the following extensions:@*
|
||||
@samp{.bz2}, @samp{.gz}, @samp{.xz}, or @samp{.zst}, which are recompressed
|
||||
to @samp{.lz};@*
|
||||
@samp{.bz2}, @samp{.gz}, @samp{.xz}, @samp{.zst}, or @samp{.Z}, which are
|
||||
recompressed to @samp{.lz};@*
|
||||
@samp{.tbz}, @samp{.tbz2}, @samp{.tgz}, @samp{.txz}, or @samp{.tzst}, which
|
||||
are recompressed to @samp{.tlz}.@*
|
||||
Keeping the combined extensions (@samp{.tgz} --> @samp{.tlz}) may be useful
|
||||
|
@ -821,11 +864,11 @@ Bzip2, gzip, and lzip are the primary formats. Xz and zstd are optional. If
|
|||
the decompressor for the xz or zstd formats is not found, the corresponding
|
||||
files are ignored.
|
||||
|
||||
Recompressing a file is much like copying or moving it; therefore zupdate
|
||||
preserves the access and modification dates, permissions, and, when
|
||||
possible, ownership of the file just as @w{@samp{cp -p}} does. (If the user ID or
|
||||
the group ID can't be duplicated, the file permission bits S_ISUID and
|
||||
S_ISGID are cleared).
|
||||
Recompressing a file is much like copying or moving it. Therefore zupdate
|
||||
preserves the access and modification dates, permissions, and, if you have
|
||||
appropriate privileges, ownership of the file just as @w{@samp{cp -p}} does.
|
||||
(If the user ID or the group ID can't be duplicated, the file permission
|
||||
bits S_ISUID and S_ISGID are cleared).
|
||||
|
||||
The format for running zupdate is:
|
||||
|
||||
|
@ -835,11 +878,19 @@ zupdate [@var{options}] [@var{files}]
|
|||
|
||||
@noindent
|
||||
Exit status is 0 if all the compressed files were successfully recompressed
|
||||
(if needed), compared, and deleted (if requested). Non-zero otherwise.
|
||||
(if needed), compared, and deleted (if requested). 1 if a non-fatal error
|
||||
occurred (file not found or not regular, or has invalid format, or can't be
|
||||
deleted). 2 if a fatal error occurred (compressor can't be run, or
|
||||
comparison fails).
|
||||
|
||||
zupdate supports the following options:
|
||||
|
||||
@table @code
|
||||
@item -e
|
||||
@itemx --expand-extensions
|
||||
Expand combined file name extensions; recompress @samp{.tbz}, @samp{.tbz2},
|
||||
@samp{.tgz}, @samp{.txz}, and @samp{.tzst} to @samp{tar.lz}.
|
||||
|
||||
@item -f
|
||||
@itemx --force
|
||||
Don't skip a file for which a lzip compressed version already exists.
|
||||
|
@ -847,6 +898,10 @@ Don't skip a file for which a lzip compressed version already exists.
|
|||
of the existing lzip file and deletes the input file if both contents
|
||||
are identical.
|
||||
|
||||
@item -i
|
||||
@itemx --ignore-errors
|
||||
Ignore non-fatal errors. (See exit status above).
|
||||
|
||||
@item -k
|
||||
@itemx --keep
|
||||
Keep (don't delete) the input file after comparing it with the lzip file.
|
||||
|
|
1
rc.cc
1
rc.cc
|
@ -62,6 +62,7 @@ const struct { const char * from; const char * to; int format_index; }
|
|||
{ ".txz", ".tar", fmt_xz },
|
||||
{ ".zst", "", fmt_zst },
|
||||
{ ".tzst", ".tar", fmt_zst },
|
||||
{ ".Z", "", fmt_gz },
|
||||
{ 0, 0, -1 } };
|
||||
|
||||
|
||||
|
|
|
@ -321,6 +321,8 @@ done
|
|||
test_failed $LINENO
|
||||
"${ZGREP}" -N -l "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null ||
|
||||
test_failed $LINENO
|
||||
"${ZGREP}" -N -l -Z "GNU" in in.gz in.bz2 in.lz -- -in- > /dev/null ||
|
||||
test_failed $LINENO
|
||||
"${ZGREP}" -N -L "GNU" in in.gz in.bz2 in.lz -- -in- || test_failed $LINENO
|
||||
"${ZGREP}" -N -l "nx_pattern" in in.gz in.bz2 in.lz -- -in- &&
|
||||
test_failed $LINENO
|
||||
|
@ -402,15 +404,15 @@ cat in.gz > a.gz || framework_failure
|
|||
"${ZUPDATE}" -N --gz='gzip --bad-option' a.gz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
"${ZUPDATE}" -Nq --lz=bad_command a.gz
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${ZUPDATE}" -N --lz='lzip --bad-option' a.gz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
"${ZUPDATE}" -N --bad-option 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
|
||||
cat in.lz in.lz > a.lz || framework_failure
|
||||
"${ZUPDATE}" -Nq -f a.bz2 a.gz
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ $? = 2 ] || test_failed $LINENO
|
||||
[ -e a.bz2 ] || test_failed $LINENO
|
||||
[ -e a.gz ] || test_failed $LINENO
|
||||
[ -e a.lz ] || test_failed $LINENO
|
||||
|
@ -471,10 +473,30 @@ cat in.gz > c.tgz || framework_failure
|
|||
[ -e c.tlz ] || test_failed $LINENO
|
||||
rm -f a.tlz b.tlz c.tlz || framework_failure
|
||||
|
||||
cat in.bz2 > a.tbz || framework_failure # expand combined extensions
|
||||
cat in.bz2 > b.tbz2 || framework_failure
|
||||
cat in.gz > c.tgz || framework_failure
|
||||
"${ZUPDATE}" -N -e a.tbz b.tbz2 c.tgz || test_failed $LINENO
|
||||
[ ! -e a.tbz ] || test_failed $LINENO
|
||||
[ ! -e b.tbz2 ] || test_failed $LINENO
|
||||
[ ! -e c.tgz ] || test_failed $LINENO
|
||||
[ ! -e a ] || test_failed $LINENO
|
||||
[ ! -e b ] || test_failed $LINENO
|
||||
[ ! -e c ] || test_failed $LINENO
|
||||
[ -e a.tar.lz ] || test_failed $LINENO
|
||||
[ -e b.tar.lz ] || test_failed $LINENO
|
||||
[ -e c.tar.lz ] || test_failed $LINENO
|
||||
[ ! -e a.tlz ] || test_failed $LINENO
|
||||
[ ! -e b.tlz ] || test_failed $LINENO
|
||||
[ ! -e c.tlz ] || test_failed $LINENO
|
||||
rm -f a.tar.lz b.tar.lz c.tar.lz || framework_failure
|
||||
|
||||
# test decompression error
|
||||
cat in.bz2 > a.bz2 || framework_failure
|
||||
cat "${bad0_gz}" > b.gz || framework_failure
|
||||
cat in.gz > c.gz || framework_failure
|
||||
"${ZUPDATE}" -N -f a.bz2 b.gz c.gz 2> /dev/null && test_failed $LINENO
|
||||
"${ZUPDATE}" -N -f a.bz2 b.gz c.gz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ ! -e a.bz2 ] || test_failed $LINENO
|
||||
[ -e b.gz ] || test_failed $LINENO
|
||||
[ -e c.gz ] || test_failed $LINENO
|
||||
|
@ -482,6 +504,16 @@ cat in.gz > c.gz || framework_failure
|
|||
[ ! -e b ] || test_failed $LINENO
|
||||
[ ! -e c ] || test_failed $LINENO
|
||||
[ -e a.lz ] || test_failed $LINENO
|
||||
# ignore error
|
||||
cat in.bz2 > a.bz2 || framework_failure
|
||||
cat "${bad0_gz}" > b.gz || framework_failure
|
||||
cat in.gz > c.gz || framework_failure
|
||||
"${ZUPDATE}" -N -f -i a.bz2 b.gz c.gz 2> /dev/null
|
||||
[ $? = 1 ] || test_failed $LINENO
|
||||
[ ! -e a.bz2 ] || test_failed $LINENO
|
||||
[ -e b.gz ] || test_failed $LINENO
|
||||
[ ! -e c.gz ] || test_failed $LINENO
|
||||
[ -e a.lz ] || test_failed $LINENO
|
||||
rm -f a.lz b.gz c.gz || framework_failure
|
||||
|
||||
cat in.bz2 > a.bz2 || framework_failure
|
||||
|
|
23
zcmp.cc
23
zcmp.cc
|
@ -95,7 +95,7 @@ const char * format_num3( long long num )
|
|||
{
|
||||
const char * const si_prefix = "kMGTPEZY";
|
||||
const char * const binary_prefix = "KMGTPEZY";
|
||||
enum { buffers = 8, bufsize = 4 * sizeof (long long) };
|
||||
enum { buffers = 8, bufsize = 4 * sizeof num };
|
||||
static char buffer[buffers][bufsize]; // circle of static buffers for printf
|
||||
static int current = 0;
|
||||
|
||||
|
@ -408,26 +408,27 @@ int main( const int argc, const char * const argv[] )
|
|||
const int code = parser.code( argind );
|
||||
if( !code ) break; // no more options
|
||||
const char * const pn = parser.parsed_name( argind ).c_str();
|
||||
const std::string & arg = parser.argument( argind );
|
||||
const std::string & sarg = parser.argument( argind );
|
||||
const char * const arg = sarg.c_str();
|
||||
switch( code )
|
||||
{
|
||||
case 'b': print_bytes = true; break;
|
||||
case 'h': show_help(); return 0;
|
||||
case 'i': parse_ignore_initial( arg.c_str(), pn, ignore_initial ); break;
|
||||
case 'i': parse_ignore_initial( arg, pn, ignore_initial ); break;
|
||||
case 'l': verbosity = 1; break;
|
||||
case 'M': parse_format_list( arg, pn ); break;
|
||||
case 'n': max_size = getnum( arg.c_str(), pn ); break;
|
||||
case 'M': parse_format_list( sarg, pn ); break;
|
||||
case 'n': max_size = getnum( arg, pn ); break;
|
||||
case 'N': break;
|
||||
case 'O': parse_format_types2( arg, pn, format_types ); break;
|
||||
case 'O': parse_format_types2( sarg, pn, format_types ); break;
|
||||
case 'q':
|
||||
case 's': verbosity = -1; break;
|
||||
case 'v': verbosity = 1; break;
|
||||
case 'V': show_version(); return 0;
|
||||
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;
|
||||
case zst_opt: parse_compressor( arg, fmt_zst ); break;
|
||||
case bz2_opt: parse_compressor( sarg, fmt_bz2 ); break;
|
||||
case gz_opt: parse_compressor( sarg, fmt_gz ); break;
|
||||
case lz_opt: parse_compressor( sarg, fmt_lz ); break;
|
||||
case xz_opt: parse_compressor( sarg, fmt_xz ); break;
|
||||
case zst_opt: parse_compressor( sarg, fmt_zst ); break;
|
||||
default : internal_error( "uncaught option." );
|
||||
}
|
||||
} // end process options
|
||||
|
|
25
zdiff.cc
25
zdiff.cc
|
@ -89,7 +89,7 @@ void show_help()
|
|||
" -U, --unified=<n> same as -u but use <n> lines of context\n"
|
||||
" -v, --verbose verbose mode (for --version)\n"
|
||||
" -w, --ignore-all-space ignore all white space\n"
|
||||
" -W, --width=<n> output at most <n> print columns\n"
|
||||
" -W, --width=<n> output at most <n> print columns (for -y)\n"
|
||||
" -y, --side-by-side output in two columns\n"
|
||||
" --bz2=<command> set compressor and options for bzip2 format\n"
|
||||
" --gz=<command> set compressor and options for gzip format\n"
|
||||
|
@ -317,7 +317,8 @@ int main( const int argc, const char * const argv[] )
|
|||
const int code = parser.code( argind );
|
||||
if( !code ) break; // no more options
|
||||
const char * const pn = parser.parsed_name( argind ).c_str();
|
||||
const std::string & arg = parser.argument( argind );
|
||||
const std::string & sarg = parser.argument( argind );
|
||||
const char * const arg = sarg.c_str();
|
||||
switch( code )
|
||||
{
|
||||
case 'a': diff_args.push_back( "-a" ); break;
|
||||
|
@ -325,14 +326,14 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'B': diff_args.push_back( "-B" ); break;
|
||||
case 'c': diff_args.push_back( "-c" ); break;
|
||||
case 'C': diff_args.push_back( "-C" );
|
||||
diff_args.push_back( arg.c_str() ); break;
|
||||
diff_args.push_back( arg ); break;
|
||||
case 'd': diff_args.push_back( "-d" ); break;
|
||||
case 'E': diff_args.push_back( "-E" ); break;
|
||||
case 'h': show_help(); return 0;
|
||||
case 'i': diff_args.push_back( "-i" ); break;
|
||||
case 'M': parse_format_list( arg, pn ); break;
|
||||
case 'M': parse_format_list( sarg, pn ); break;
|
||||
case 'N': break;
|
||||
case 'O': parse_format_types2( arg, pn, format_types ); break;
|
||||
case 'O': parse_format_types2( sarg, pn, format_types ); break;
|
||||
case 'p': diff_args.push_back( "-p" ); break;
|
||||
case 'q': diff_args.push_back( "-q" ); break;
|
||||
case 's': diff_args.push_back( "-s" ); break;
|
||||
|
@ -340,18 +341,18 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'T': diff_args.push_back( "-T" ); break;
|
||||
case 'u': diff_args.push_back( "-u" ); break;
|
||||
case 'U': diff_args.push_back( "-U" );
|
||||
diff_args.push_back( arg.c_str() ); break;
|
||||
diff_args.push_back( arg ); break;
|
||||
case 'v': verbosity = 1; break;
|
||||
case 'V': show_version( DIFF " --version" ); return 0;
|
||||
case 'w': diff_args.push_back( "-w" ); break;
|
||||
case 'W': diff_args.push_back( "-W" );
|
||||
diff_args.push_back( arg.c_str() ); break;
|
||||
diff_args.push_back( arg ); break;
|
||||
case 'y': diff_args.push_back( "-y" ); 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;
|
||||
case zst_opt: parse_compressor( arg, fmt_zst ); break;
|
||||
case bz2_opt: parse_compressor( sarg, fmt_bz2 ); break;
|
||||
case gz_opt: parse_compressor( sarg, fmt_gz ); break;
|
||||
case lz_opt: parse_compressor( sarg, fmt_lz ); break;
|
||||
case xz_opt: parse_compressor( sarg, fmt_xz ); break;
|
||||
case zst_opt: parse_compressor( sarg, fmt_zst ); break;
|
||||
default : internal_error( "uncaught option." );
|
||||
}
|
||||
} // end process options
|
||||
|
|
154
zgrep.cc
154
zgrep.cc
|
@ -79,26 +79,33 @@ void show_help()
|
|||
" -E, --extended-regexp <pattern> is an extended regular expression\n"
|
||||
" -f, --file=<file> obtain patterns from <file>\n"
|
||||
" -F, --fixed-strings <pattern> is a set of newline-separated strings\n"
|
||||
" -G, --basic-regexp <pattern> is a basic regular expression (default)\n"
|
||||
" -h, --no-filename suppress the prefixing file name on output\n"
|
||||
" -H, --with-filename print the file name for each match\n"
|
||||
" -i, --ignore-case ignore case distinctions\n"
|
||||
" -I ignore binary files\n"
|
||||
" -l, --files-with-matches only print names of files containing matches\n"
|
||||
" -L, --files-without-match only print names of files containing no matches\n"
|
||||
" --label=<label> use <label> as file name for standard input\n"
|
||||
" --line-buffered flush output on every line\n"
|
||||
" -m, --max-count=<n> stop after <n> matches\n"
|
||||
" -M, --format=<list> process only the formats in <list>\n"
|
||||
" -n, --line-number print the line number of each line\n"
|
||||
" -N, --no-rcfile don't read runtime configuration file\n"
|
||||
" -o, --only-matching show only the part of a line matching <pattern>\n"
|
||||
" -O, --force-format=<fmt> force the format given (bz2, gz, lz, xz, zst)\n"
|
||||
" -q, --quiet suppress all messages\n"
|
||||
" -P, --perl-regexp <pattern> is a Perl regular expression\n"
|
||||
" -q, --quiet, --silent suppress all messages\n"
|
||||
" -r, --recursive operate recursively on directories\n"
|
||||
" -R, --dereference-recursive recursively follow symbolic links\n"
|
||||
" -s, --no-messages suppress error messages\n"
|
||||
" -T, --initial-tab make tabs line up (if needed)\n"
|
||||
" -U, --binary don't strip CR characters at EOL (DOS/Windows)\n"
|
||||
" -v, --invert-match select non-matching lines\n"
|
||||
" --verbose verbose mode (show error messages)\n"
|
||||
" -w, --word-regexp match only whole words\n"
|
||||
" -x, --line-regexp match only whole lines\n"
|
||||
" -Z, --null print 0 byte (ASCII NUL) after file name\n"
|
||||
" --bz2=<command> set compressor and options for bzip2 format\n"
|
||||
" --gz=<command> set compressor and options for gzip format\n"
|
||||
" --lz=<command> set compressor and options for lzip format\n"
|
||||
|
@ -110,43 +117,12 @@ void show_help()
|
|||
}
|
||||
|
||||
|
||||
int zgrep_stdin( int infd, const int format_index,
|
||||
const std::vector< const char * > & grep_args )
|
||||
{
|
||||
Children children;
|
||||
if( !set_data_feeder( "", &infd, children, format_index ) ) return 2;
|
||||
const pid_t grep_pid = fork();
|
||||
if( grep_pid == 0 ) // child (grep)
|
||||
{
|
||||
if( dup2( infd, STDIN_FILENO ) >= 0 && close( infd ) == 0 )
|
||||
{
|
||||
const char ** const argv = new const char *[grep_args.size()+2];
|
||||
argv[0] = GREP;
|
||||
for( unsigned i = 0; i < grep_args.size(); ++i )
|
||||
argv[i+1] = grep_args[i];
|
||||
argv[grep_args.size()+1] = 0;
|
||||
execvp( argv[0], (char **)argv );
|
||||
}
|
||||
show_exec_error( GREP );
|
||||
_exit( 2 );
|
||||
}
|
||||
if( grep_pid < 0 ) // parent
|
||||
{ show_fork_error( GREP ); return 2; }
|
||||
|
||||
int retval = wait_for_child( grep_pid, GREP );
|
||||
|
||||
if( !good_status( children, retval == 1 ) ) retval = 2;
|
||||
|
||||
if( close( infd ) != 0 )
|
||||
{ show_close_error(); return 2; }
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int zgrep_file( int infd, const int format_index,
|
||||
const std::string & input_filename,
|
||||
const std::vector< const char * > & grep_args,
|
||||
const int list_mode, const bool show_name )
|
||||
const int list_mode, const bool initial_tab,
|
||||
const bool line_buffered, const bool show_name,
|
||||
const bool z_null )
|
||||
{
|
||||
Children children;
|
||||
if( !set_data_feeder( input_filename, &infd, children, format_index ) )
|
||||
|
@ -178,34 +154,48 @@ int zgrep_file( int infd, const int format_index,
|
|||
enum { buffer_size = 256 };
|
||||
uint8_t buffer[buffer_size];
|
||||
bool line_begin = true;
|
||||
while( true )
|
||||
bool at_eof = false;
|
||||
while( !at_eof )
|
||||
{
|
||||
const int size = readblock( fda[0], buffer, buffer_size );
|
||||
if( size != buffer_size && errno )
|
||||
{ show_error( "Read error", errno ); return 2; }
|
||||
int size;
|
||||
bool error = false;
|
||||
if( line_buffered )
|
||||
for( size = 0; size < buffer_size; )
|
||||
{ if( readblock( fda[0], buffer + size, 1 ) == 1 )
|
||||
{ ++size; if( buffer[size-1] == '\n' ) break; }
|
||||
else { at_eof = true; if( errno ) { error = true; } break; } }
|
||||
else
|
||||
{ size = readblock( fda[0], buffer, buffer_size );
|
||||
if( size < buffer_size ) { at_eof = true; if( errno ) error = true; } }
|
||||
if( error )
|
||||
{ std::fflush( stdout ); show_error( "Read error", errno ); return 2; }
|
||||
if( size > 0 && !list_mode )
|
||||
{
|
||||
if( show_name )
|
||||
if( show_name ) // print the file name for each match
|
||||
for( int i = 0; i < size; ++i )
|
||||
{
|
||||
if( line_begin )
|
||||
{ line_begin = false; std::printf( "%s:", input_filename.c_str() ); }
|
||||
if( buffer[i] == '\n' ) line_begin = true;
|
||||
{ line_begin = false;
|
||||
const int len = std::printf( "%s%c", input_filename.c_str(),
|
||||
z_null ? 0 : ':' );
|
||||
if( initial_tab && len > 0 && len % 8 ) putchar( '\t' ); }
|
||||
putchar( buffer[i] );
|
||||
if( buffer[i] == '\n' )
|
||||
{ line_begin = true; if( line_buffered ) std::fflush( stdout ); }
|
||||
}
|
||||
else if( std::fwrite( buffer, 1, size, stdout ) != (unsigned)size )
|
||||
{ std::fflush( stdout ); show_error( "Write error", errno ); return 2; }
|
||||
std::fflush( stdout );
|
||||
}
|
||||
if( size < buffer_size ) break; // end of grep's output
|
||||
}
|
||||
std::fflush( stdout );
|
||||
|
||||
int retval = wait_for_child( grep_pid, GREP );
|
||||
|
||||
if( !good_status( children, retval == 1 ) ) retval = 2;
|
||||
|
||||
if( list_mode && (retval == 0) == (list_mode == 1) )
|
||||
{ std::printf( "%s\n", input_filename.c_str() ); std::fflush( stdout ); }
|
||||
{ std::printf( "%s%c", input_filename.c_str(), z_null ? 0 : '\n' );
|
||||
std::fflush( stdout ); }
|
||||
if( close( infd ) != 0 )
|
||||
{ show_close_error(); return 2; }
|
||||
if( close( fda[0] ) != 0 )
|
||||
|
@ -218,16 +208,21 @@ int zgrep_file( int infd, const int format_index,
|
|||
|
||||
int main( const int argc, const char * const argv[] )
|
||||
{
|
||||
enum { help_opt = 256, verbose_opt, color_opt,
|
||||
enum { help_opt = 256, verbose_opt, color_opt, label_opt, linebuf_opt,
|
||||
bz2_opt, gz_opt, lz_opt, xz_opt, zst_opt };
|
||||
int format_index = -1;
|
||||
int list_mode = 0; // 1 = list matches, -1 = list non-matches
|
||||
int recursive = 0; // 1 = '-r', 2 = '-R'
|
||||
int show_name = -1; // tri-state bool
|
||||
bool initial_tab = false;
|
||||
bool line_buffered = false;
|
||||
bool no_messages = false;
|
||||
bool z_null = false; // for '-Z, --null'
|
||||
std::list< std::string > filenames;
|
||||
std::vector< const char * > grep_args; // args to grep, maybe empty
|
||||
std::string color_option; // needed because of optional arg
|
||||
std::string color_option; // additional args to grep
|
||||
std::string label_option;
|
||||
std::string label = "(standard input)"; // prefix for standard input
|
||||
program_name = "zgrep";
|
||||
invocation_name = ( argc > 0 ) ? argv[0] : program_name;
|
||||
|
||||
|
@ -243,6 +238,7 @@ int main( const int argc, const char * const argv[] )
|
|||
{ 'E', "extended-regexp", Arg_parser::no }, // grep
|
||||
{ 'f', "file ", Arg_parser::yes }, // grep
|
||||
{ 'F', "fixed-strings", Arg_parser::no }, // grep
|
||||
{ 'G', "basic-regexp", Arg_parser::no }, // grep GNU
|
||||
{ 'h', "no-filename", Arg_parser::no }, // grep GNU
|
||||
{ 'H', "with-filename", Arg_parser::no }, // grep GNU
|
||||
{ 'i', "ignore-case", Arg_parser::no }, // grep
|
||||
|
@ -255,17 +251,24 @@ int main( const int argc, const char * const argv[] )
|
|||
{ 'N', "no-rcfile", Arg_parser::no },
|
||||
{ 'o', "only-matching", Arg_parser::no }, // grep
|
||||
{ 'O', "force-format", Arg_parser::yes },
|
||||
{ 'P', "perl-regexp", Arg_parser::no }, // grep GNU
|
||||
{ 'q', "quiet", Arg_parser::no },
|
||||
{ 'q', "silent", Arg_parser::no },
|
||||
{ 'r', "recursive", Arg_parser::no },
|
||||
{ 'R', "dereference-recursive", Arg_parser::no },
|
||||
{ 's', "no-messages", Arg_parser::no }, // grep
|
||||
{ 'T', "initial-tab", Arg_parser::no }, // grep GNU
|
||||
{ 'U', "binary", Arg_parser::no }, // grep GNU
|
||||
{ '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
|
||||
{ 'Z', "null", Arg_parser::no }, // grep GNU
|
||||
{ help_opt, "help", Arg_parser::no },
|
||||
{ verbose_opt, "verbose", Arg_parser::no },
|
||||
{ color_opt, "color", Arg_parser::maybe },
|
||||
{ label_opt, "label", Arg_parser::yes },
|
||||
{ linebuf_opt, "line-buffered", Arg_parser::no },
|
||||
{ bz2_opt, "bz2", Arg_parser::yes },
|
||||
{ gz_opt, "gz", Arg_parser::yes },
|
||||
{ lz_opt, "lz", Arg_parser::yes },
|
||||
|
@ -286,24 +289,26 @@ int main( const int argc, const char * const argv[] )
|
|||
const int code = parser.code( argind );
|
||||
if( !code ) break; // no more options
|
||||
const char * const pn = parser.parsed_name( argind ).c_str();
|
||||
const std::string & arg = parser.argument( argind );
|
||||
const std::string & sarg = parser.argument( argind );
|
||||
const char * const arg = sarg.c_str();
|
||||
switch( code )
|
||||
{
|
||||
case 'a': grep_args.push_back( "-a" ); break;
|
||||
case 'A': grep_args.push_back( "-A" );
|
||||
grep_args.push_back( arg.c_str() ); break;
|
||||
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.c_str() ); break;
|
||||
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.c_str() ); break;
|
||||
grep_args.push_back( arg ); break;
|
||||
case 'e': grep_args.push_back( "-e" );
|
||||
grep_args.push_back( arg.c_str() ); pattern_found = true; break;
|
||||
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.c_str() ); pattern_found = true; break;
|
||||
grep_args.push_back( arg ); pattern_found = true; break;
|
||||
case 'F': grep_args.push_back( "-F" ); break;
|
||||
case 'G': grep_args.push_back( "-G" ); break;
|
||||
case 'h': show_name = false; break;
|
||||
case 'H': show_name = true; break;
|
||||
case 'i': grep_args.push_back( "-i" ); break;
|
||||
|
@ -311,37 +316,46 @@ int main( const int argc, const char * const argv[] )
|
|||
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.c_str() ); break;
|
||||
case 'M': parse_format_list( arg, pn ); break;
|
||||
grep_args.push_back( arg ); break;
|
||||
case 'M': parse_format_list( sarg, pn ); break;
|
||||
case 'n': grep_args.push_back( "-n" ); break;
|
||||
case 'N': break;
|
||||
case 'o': grep_args.push_back( "-o" ); break;
|
||||
case 'O': format_index = parse_format_type( arg, pn ); break;
|
||||
case 'O': format_index = parse_format_type( sarg, pn ); break;
|
||||
case 'P': grep_args.push_back( "-P" ); break;
|
||||
case 'q': grep_args.push_back( "-q" ); verbosity = -1; break;
|
||||
case 'r': recursive = 1; break;
|
||||
case 'R': recursive = 2; break;
|
||||
case 's': grep_args.push_back( "-s" ); no_messages = true; break;
|
||||
case 'T': grep_args.push_back( "-T" ); initial_tab = true; break;
|
||||
case 'U': grep_args.push_back( "-U" ); break;
|
||||
case 'v': grep_args.push_back( "-v" ); break;
|
||||
case 'V': show_version( GREP " --version" ); return 0;
|
||||
case 'w': grep_args.push_back( "-w" ); break;
|
||||
case 'x': grep_args.push_back( "-x" ); break;
|
||||
case 'Z': z_null = true; break;
|
||||
case help_opt: show_help(); return 0;
|
||||
case verbose_opt: no_messages = false; if( verbosity < 4 ) ++verbosity;
|
||||
break;
|
||||
case color_opt: color_option = "--color";
|
||||
if( !arg.empty() ) { color_option += '='; color_option += arg; }
|
||||
if( !sarg.empty() ) { color_option += '='; color_option += sarg; }
|
||||
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;
|
||||
case zst_opt: parse_compressor( arg, fmt_zst ); break;
|
||||
case label_opt: label_option = label = sarg; break;
|
||||
case linebuf_opt: grep_args.push_back( "--line-buffered" );
|
||||
line_buffered = true; break;
|
||||
case bz2_opt: parse_compressor( sarg, fmt_bz2 ); break;
|
||||
case gz_opt: parse_compressor( sarg, fmt_gz ); break;
|
||||
case lz_opt: parse_compressor( sarg, fmt_lz ); break;
|
||||
case xz_opt: parse_compressor( sarg, fmt_xz ); break;
|
||||
case zst_opt: parse_compressor( sarg, fmt_zst ); break;
|
||||
default : internal_error( "uncaught option." );
|
||||
}
|
||||
} // end process options
|
||||
|
||||
if( !color_option.empty() ) // push the last value set
|
||||
grep_args.push_back( color_option.c_str() );
|
||||
if( !label_option.empty() ) // for "Binary file <label> matches"
|
||||
grep_args.push_back( label_option.insert( 0, "--label=" ).c_str() );
|
||||
|
||||
#if defined __MSVCRT__ || defined __OS2__
|
||||
setmode( STDIN_FILENO, O_BINARY );
|
||||
|
@ -352,9 +366,9 @@ int main( const int argc, const char * const argv[] )
|
|||
{
|
||||
if( argind >= parser.arguments() )
|
||||
{ show_error( "Pattern not found." ); return 2; }
|
||||
const std::string & arg = parser.argument( argind++ );
|
||||
if( arg.size() && arg[0] == '-' ) grep_args.push_back( "-e" );
|
||||
grep_args.push_back( arg.c_str() );
|
||||
const std::string & pat = parser.argument( argind++ );
|
||||
if( pat.size() && pat[0] == '-' ) grep_args.push_back( "-e" );
|
||||
grep_args.push_back( pat.c_str() );
|
||||
}
|
||||
|
||||
for( ; argind < parser.arguments(); ++argind )
|
||||
|
@ -375,7 +389,7 @@ int main( const int argc, const char * const argv[] )
|
|||
if( input_filename == "." )
|
||||
{
|
||||
if( stdin_used ) continue; else stdin_used = true;
|
||||
infd = STDIN_FILENO; input_filename = "-";
|
||||
infd = STDIN_FILENO; input_filename = label;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -383,11 +397,9 @@ int main( const int argc, const char * const argv[] )
|
|||
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 );
|
||||
const int tmp = zgrep_file( infd, format_index, input_filename, grep_args,
|
||||
list_mode, initial_tab, line_buffered,
|
||||
show_name, z_null );
|
||||
if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp;
|
||||
|
||||
if( close( infd ) != 0 )
|
||||
|
|
56
zupdate.cc
56
zupdate.cc
|
@ -67,15 +67,20 @@ void show_help()
|
|||
"to be safe and not cause any data loss. Therefore, existing lzip\n"
|
||||
"compressed files are never overwritten nor deleted.\n"
|
||||
"\nThe names of the original files must have one of the following extensions:\n"
|
||||
"\n'.bz2', '.gz', '.xz', or '.zst', which are recompressed to '.lz'.\n"
|
||||
"\n'.bz2', '.gz', '.xz', '.zst', or '.Z', which are recompressed to '.lz'.\n"
|
||||
"\n'.tbz', '.tbz2', '.tgz', '.txz', or '.tzst', which are recompressed to '.tlz'.\n"
|
||||
"\nUsage: zupdate [options] [files]\n"
|
||||
"\nExit status is 0 if all the compressed files were successfully recompressed\n"
|
||||
"(if needed), compared, and deleted (if requested). Non-zero otherwise.\n"
|
||||
"(if needed), compared, and deleted (if requested). 1 if a non-fatal error\n"
|
||||
"occurred (file not found or not regular, or has invalid format, or can't be\n"
|
||||
"deleted). 2 if a fatal error occurred (compressor can't be run, or\n"
|
||||
"comparison fails).\n"
|
||||
"\nOptions:\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
" -V, --version output version information and exit\n"
|
||||
" -e, --expand-extensions expand combined extensions; tgz -> tar.lz\n"
|
||||
" -f, --force don't skip a file even if the .lz exists\n"
|
||||
" -i, --ignore-errors ignore non-fatal errors\n"
|
||||
" -k, --keep keep (don't delete) input files\n"
|
||||
" -l, --lzip-verbose pass one option -v to the lzip compressor\n"
|
||||
" -M, --format=<list> process only the formats in <list>\n"
|
||||
|
@ -94,7 +99,7 @@ void show_help()
|
|||
}
|
||||
|
||||
|
||||
int cant_execute( const std::string & command, const int status )
|
||||
void cant_execute( const std::string & command, const int status )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
{
|
||||
|
@ -105,7 +110,6 @@ int cant_execute( const std::string & command, const int status )
|
|||
std::fprintf( stderr, "%s: Can't execute '%s'\n",
|
||||
program_name, command.c_str() );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,11 +134,11 @@ void set_permissions( const char * const rname, const struct stat & in_stats )
|
|||
}
|
||||
|
||||
|
||||
// Return 0 if success, -1 if file skipped, 1 if error.
|
||||
// Return value: 0 = success, -1 = file skipped, 1 = error, 2 = fatal error.
|
||||
int zupdate_file( const std::string & name, const char * const lzip_name,
|
||||
const std::vector< std::string > & lzip_args2,
|
||||
const bool force, const bool keep_input_files,
|
||||
const bool no_rcfile )
|
||||
const bool expand, const bool force,
|
||||
const bool keep_input_files, const bool no_rcfile )
|
||||
{
|
||||
// bzip2, gzip, and lzip are the primary formats. xz and zstd are optional.
|
||||
static int disable_xz = -1; // tri-state bool
|
||||
|
@ -155,7 +159,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
|||
}
|
||||
rname.assign( name, 0, name.size() - std::strlen( extension_from( eindex ) ) );
|
||||
rname += ( std::strcmp( extension_to( eindex ), ".tar" ) == 0 ) ?
|
||||
".tlz" : ".lz"; // keep combined extension
|
||||
( expand ? ".tar.lz" : ".tlz" ) : ".lz";
|
||||
}
|
||||
const char * const compressor_name = get_compressor_name( format_index );
|
||||
if( !compressor_name )
|
||||
|
@ -226,7 +230,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
|||
std::fprintf( stderr, "Recompressing file '%s'\n", name.c_str() );
|
||||
int fda[2]; // pipe between decompressor and compressor
|
||||
if( pipe( fda ) < 0 )
|
||||
{ show_error( "Can't create pipe", errno ); return 1; }
|
||||
{ show_error( "Can't create pipe", errno ); return 2; }
|
||||
|
||||
const pid_t pid = fork();
|
||||
if( pid == 0 ) // child1 (decompressor)
|
||||
|
@ -250,7 +254,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
|||
_exit( 1 );
|
||||
}
|
||||
if( pid < 0 ) // parent
|
||||
{ show_fork_error( compressor_name ); return 1; }
|
||||
{ show_fork_error( compressor_name ); return 2; }
|
||||
|
||||
const pid_t pid2 = fork();
|
||||
if( pid2 == 0 ) // child2 (lzip compressor)
|
||||
|
@ -276,19 +280,19 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
|||
_exit( 1 );
|
||||
}
|
||||
if( pid2 < 0 ) // parent
|
||||
{ show_fork_error( lzip_name ); return 1; }
|
||||
{ show_fork_error( lzip_name ); return 2; }
|
||||
|
||||
close( fda[0] ); close( fda[1] );
|
||||
int retval = wait_for_child( pid, compressor_name );
|
||||
int retval2 = wait_for_child( pid2, lzip_name );
|
||||
const int retval = wait_for_child( pid, compressor_name );
|
||||
const int retval2 = wait_for_child( pid2, lzip_name );
|
||||
if( retval || retval2 )
|
||||
{ if( !lz_lz_exists ) std::remove( rname2.c_str() ); // lzip < 1.20
|
||||
std::remove( rname.c_str() ); return 1; }
|
||||
std::remove( rname.c_str() ); return retval2 ? 2 : 1; }
|
||||
if( stat( rname.c_str(), &st ) != 0 &&
|
||||
( lz_lz_exists || stat( rname2.c_str(), &st ) != 0 ||
|
||||
std::rename( rname2.c_str(), rname.c_str() ) != 0 ) )
|
||||
{ show_file_error( rname.c_str(), "Error renaming output file", errno );
|
||||
return 1; } // lzip < 1.11
|
||||
return 2; } // lzip < 1.11
|
||||
set_permissions( rname.c_str(), in_stats );
|
||||
}
|
||||
|
||||
|
@ -296,8 +300,8 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
|||
if( lz_exists && verbosity >= 1 )
|
||||
std::fprintf( stderr, "Comparing file '%s'\n", name.c_str() );
|
||||
std::string zcmp_command( invocation_name );
|
||||
unsigned i = zcmp_command.size();
|
||||
while( i > 0 && zcmp_command[i-1] != '/' ) --i;
|
||||
unsigned i = zcmp_command.size();
|
||||
while( i > 0 && zcmp_command[i-1] != '/' ) --i; // strip "zupdate"
|
||||
zcmp_command.resize( i ); zcmp_command.insert( zcmp_command.begin(), '\'' );
|
||||
zcmp_command += "zcmp' "; // '[dir/]zcmp'
|
||||
if( no_rcfile ) zcmp_command += "-N ";
|
||||
|
@ -307,7 +311,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
|
|||
int status = std::system( zcmp_command.c_str() );
|
||||
if( status != 0 )
|
||||
{ if( !lz_exists ) std::remove( rname.c_str() );
|
||||
return cant_execute( zcmp_command, status ); }
|
||||
cant_execute( zcmp_command, status ); return 2; }
|
||||
}
|
||||
|
||||
if( !keep_input_files && std::remove( name.c_str() ) != 0 && errno != ENOENT )
|
||||
|
@ -329,7 +333,9 @@ int main( const int argc, const char * const argv[] )
|
|||
int recursive = 0; // 1 = '-r', 2 = '-R'
|
||||
std::list< std::string > filenames;
|
||||
std::vector< std::string > lzip_args2; // args to lzip, maybe empty
|
||||
bool expand = false;
|
||||
bool force = false;
|
||||
bool ignore_errors = false;
|
||||
bool keep_input_files = false;
|
||||
bool no_rcfile = false;
|
||||
program_name = "zupdate";
|
||||
|
@ -347,8 +353,10 @@ int main( const int argc, const char * const argv[] )
|
|||
{ '7', 0, Arg_parser::no },
|
||||
{ '8', 0, Arg_parser::no },
|
||||
{ '9', 0, Arg_parser::no },
|
||||
{ 'e', "expand-extensions", Arg_parser::no },
|
||||
{ 'f', "force", Arg_parser::no },
|
||||
{ 'h', "help", Arg_parser::no },
|
||||
{ 'i', "ignore-errors", Arg_parser::no },
|
||||
{ 'k', "keep", Arg_parser::no },
|
||||
{ 'l', "lzip-verbose", Arg_parser::no },
|
||||
{ 'M', "format", Arg_parser::yes },
|
||||
|
@ -367,7 +375,7 @@ int main( const int argc, const char * const argv[] )
|
|||
|
||||
const Arg_parser parser( argc, argv, options );
|
||||
if( parser.error().size() ) // bad option
|
||||
{ show_error( parser.error().c_str(), 0, true ); return 1; }
|
||||
{ show_error( parser.error().c_str(), 0, true ); return 2; }
|
||||
|
||||
maybe_process_config_file( parser );
|
||||
|
||||
|
@ -383,8 +391,10 @@ int main( const int argc, const char * const argv[] )
|
|||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
lzip_args2.push_back( "-" ); lzip_args2.back() += code; break;
|
||||
case 'e': expand = true; break;
|
||||
case 'f': force = true; break;
|
||||
case 'h': show_help(); return 0;
|
||||
case 'i': ignore_errors = true; break;
|
||||
case 'k': keep_input_files = true; break;
|
||||
case 'l': lzip_args2.push_back( "-v" ); break;
|
||||
case 'M': parse_format_list( arg, pn ); break;
|
||||
|
@ -410,7 +420,7 @@ int main( const int argc, const char * const argv[] )
|
|||
|
||||
const char * const lzip_name = get_compressor_name( fmt_lz );
|
||||
if( !lzip_name )
|
||||
{ show_error( "Missing name of compressor for lzip format." ); return 1; }
|
||||
{ show_error( "Missing name of compressor for lzip format." ); return 2; }
|
||||
|
||||
for( ; argind < parser.arguments(); ++argind )
|
||||
filenames.push_back( parser.argument( argind ) );
|
||||
|
@ -422,11 +432,11 @@ int main( const int argc, const char * const argv[] )
|
|||
bool error = false;
|
||||
while( next_filename( filenames, input_filename, error, recursive, true ) )
|
||||
{
|
||||
int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, force,
|
||||
keep_input_files, no_rcfile );
|
||||
int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, expand,
|
||||
force, keep_input_files, no_rcfile );
|
||||
if( tmp < 0 ) error = true;
|
||||
if( tmp > retval ) retval = tmp;
|
||||
if( tmp > 0 ) break;
|
||||
if( tmp >= 2 || ( tmp == 1 && !ignore_errors ) ) break;
|
||||
}
|
||||
if( error && retval == 0 ) retval = 1;
|
||||
return retval;
|
||||
|
|
|
@ -255,11 +255,14 @@ int test_format( const int infd, uint8_t magic_data[],
|
|||
gzip_magic_size = 2,
|
||||
lzip_magic_size = 5,
|
||||
xz_magic_size = 5,
|
||||
zstd_magic_size = 4 };
|
||||
zstd_magic_size = 4,
|
||||
compress_magic_size = 2 };
|
||||
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 compress_magic[compress_magic_size] =
|
||||
{ 0x1F, 0x9D };
|
||||
const uint8_t lzip_magic[lzip_magic_size] =
|
||||
{ 0x4C, 0x5A, 0x49, 0x50, 0x01 }; // "LZIP\001"
|
||||
const uint8_t xz_magic[xz_magic_size] =
|
||||
|
@ -277,7 +280,8 @@ int test_format( const int infd, uint8_t magic_data[],
|
|||
magic_data[3] >= '1' && magic_data[3] <= '9' &&
|
||||
std::memcmp( magic_data + 4, "1AY&SY", 6 ) == 0 )
|
||||
return fmt_bz2;
|
||||
if( std::memcmp( magic_data, gzip_magic, gzip_magic_size ) == 0 )
|
||||
if( std::memcmp( magic_data, gzip_magic, gzip_magic_size ) == 0 ||
|
||||
std::memcmp( magic_data, compress_magic, compress_magic_size ) == 0 )
|
||||
return fmt_gz;
|
||||
if( std::memcmp( magic_data, zstd_magic, zstd_magic_size ) == 0 )
|
||||
return fmt_zst;
|
||||
|
|
Loading…
Add table
Reference in a new issue