Compare commits
61 Commits
release_1_
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b94eed6d03 | ||
|
|
192860abb8 | ||
|
|
c2d2e806a1 | ||
|
|
2a89f7a0a8 | ||
|
|
71d2a66f42 | ||
|
|
e496c1b529 | ||
|
|
6667fa7fb8 | ||
|
|
a16ad3112e | ||
|
|
7efe3850f6 | ||
|
|
d0694ee604 | ||
|
|
37f0faf1c0 | ||
|
|
b893aee6d2 | ||
|
|
f60d655908 | ||
|
|
549481a0a7 | ||
|
|
e08afc2002 | ||
|
|
338591a486 | ||
|
|
c0e0d06e69 | ||
|
|
6e85425618 | ||
|
|
336519aa4f | ||
|
|
5f4d99491d | ||
|
|
48d83be336 | ||
|
|
60d351cc5a | ||
|
|
e33be3d0a1 | ||
|
|
32562b9412 | ||
|
|
dfd87ba1d0 | ||
|
|
5d4a682a55 | ||
|
|
8e3a2a520d | ||
|
|
745832a280 | ||
|
|
458efab23b | ||
|
|
23dcaa117f | ||
|
|
5099ddf6cc | ||
|
|
8476145508 | ||
|
|
362492fe70 | ||
|
|
7111008659 | ||
|
|
ec4741d732 | ||
|
|
bed7de0271 | ||
|
|
eaaadcfd36 | ||
|
|
a8830fbb86 | ||
|
|
848659f1c6 | ||
|
|
17cbd4862c | ||
|
|
64ded9e702 | ||
|
|
ccd0a527e4 | ||
|
|
3f869877a4 | ||
|
|
8c528937a9 | ||
|
|
460f4ec146 | ||
|
|
eb59c14a1f | ||
|
|
3c4f4ca423 | ||
|
|
506b4db5d0 | ||
|
|
5bfb6c5f9d | ||
|
|
3725b5606f | ||
|
|
d1a7eebc30 | ||
|
|
dfe280dcca | ||
|
|
620a136e74 | ||
|
|
3fb5d67b28 | ||
|
|
c30a794679 | ||
|
|
00bb0d8f5c | ||
|
|
af3e05b6af | ||
|
|
6060d613d1 | ||
|
|
3f12066739 | ||
|
|
3b74fbfc3b | ||
|
|
14d39a2c14 |
@@ -12,5 +12,7 @@ build-aux
|
||||
config.*
|
||||
configure
|
||||
gnulib
|
||||
m4
|
||||
rmt
|
||||
stamp-h1
|
||||
tar-[0-9]*
|
||||
|
||||
189
ChangeLog
189
ChangeLog
@@ -1,3 +1,186 @@
|
||||
2008-03-31 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/create.c (dump_file0): Count links only for actually dumped
|
||||
files.
|
||||
|
||||
2008-03-27 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS: Document --no-check-device and --check-device.
|
||||
* doc/rendition.texi: Change the way FIXME-*refs are handled in
|
||||
!PROOF.
|
||||
* doc/intern.texi, doc/tar.texi: Update.
|
||||
* doc/untabify.el: New file.
|
||||
* doc/Makefile.am (EXTRA_DIST): Add untabify.el
|
||||
(untabify, final, check-format, check-refs, check-fixmes)
|
||||
(check-unrevised, all-check-docs, check-docs): New rules.
|
||||
|
||||
* src/common.h (check_device_option): New global.
|
||||
* src/incremen.c (procdir): Use boolean and instead of bitwise
|
||||
one. Patch by Jean-Louis Martineau.
|
||||
Compare device numbers only if check_device_option is set.
|
||||
* src/tar.c: New command line options --no-check-device and
|
||||
--check-device. Proposed by Jean-Louis Martineau.
|
||||
(parse_opt): Hanlde new options.
|
||||
(decode_options): Initialize check_device_option to true.
|
||||
|
||||
* THANKS: Update
|
||||
|
||||
2008-03-06 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* bootstrap: Use rsync to get translations.
|
||||
* doc/tar.texi: Minor change.
|
||||
* lib/.cvsignore: Update
|
||||
* po/.cvsignore: Update
|
||||
* src/system.c: Remove include setenv.h.
|
||||
* tests/atlocal.in (STAR_DATA_URL): Update.
|
||||
* tests/star/README: Update URL.
|
||||
|
||||
2008-02-09 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/tar.texi: Fix a typo. Reported by Denis Excoffier.
|
||||
|
||||
2008-02-08 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS: Update.
|
||||
* configure.ac: Version 1.19.90
|
||||
* po/POTFILES.in: Add missing files.
|
||||
* src/compare.c (verify_volume): Honor --ignore-zeros.
|
||||
Proposed by Jan-Benedict Glaw.
|
||||
* tests/shortfile.at (AT_KEYWORDS): Add shortfile0.
|
||||
|
||||
2008-02-07 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS: Update.
|
||||
* src/create.c (dump_file0): Apply transform_name to symlink
|
||||
targets.
|
||||
|
||||
2008-02-04 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/transform.c: Support multiple --transform options. Support
|
||||
semicolon-separated lists of replace expressions.
|
||||
* NEWS, tar.texi: Document changes to the --transform option.
|
||||
|
||||
2008-01-30 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* doc/tar.texi: Update Back-Cover text to reflect new GNU wording.
|
||||
|
||||
2007-12-17 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Exit with nonzero status if a close fails on an archive.
|
||||
Problem (and initial trivial fix)
|
||||
* src/buffer.c (close_archive, new_volume): close_error, not
|
||||
close_warn.
|
||||
|
||||
2007-12-05 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/buffer.c (check_compressed_archive): Do not bail out if the
|
||||
file is too short, set boolean flag, passed as an argument
|
||||
instead. This fixes a bug introduced on 2007-08-24. See also
|
||||
tests/shortupd.at.
|
||||
|
||||
* tests/Makefile.am, tests/testsuite.at: Add shortupd.at.
|
||||
* tests/shortupd.at: New test.
|
||||
|
||||
2007-11-12 Jim Meyering <meyering@redhat.com>
|
||||
|
||||
Don't read from name[-1].
|
||||
* src/incremen.c (make_directory): Handle namelen == 0, since
|
||||
find_directory_meta calls make_directory ("").
|
||||
|
||||
2007-11-07 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* bootstrap (checkout): Use URL of the gnulib CVS mirror.
|
||||
* gnulib.modules: Add fseeko and snprintf.
|
||||
|
||||
2007-10-31 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/checkpoint.c: New actions: bell and ttyout
|
||||
* src/system.c (sys_exec_info_script)
|
||||
(sys_exec_checkpoint_script): pass the current blocking factor in
|
||||
TAR_BLOCKING_FACTOR environment variable.
|
||||
* doc/tar.texi: Update
|
||||
* NEWS: Update
|
||||
|
||||
2007-10-30 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/Makefile.am: Use texi2html and the CVS version of gendocs.sh
|
||||
to create HTML versions of the manual.
|
||||
* doc/gendocs_template: Likewise.
|
||||
* doc/tar.texi: Document --hard-dereference and
|
||||
--checkpoint-action options. Improve documentation of
|
||||
--check-links.
|
||||
|
||||
2007-10-29 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS: Update
|
||||
* configure.ac: Version 1.19.1
|
||||
* po/POTFILES.in: Add src/checkpoint.c
|
||||
* src/Makefile.am (tar_SOURCES): add checkpoint.c
|
||||
* src/checkpoint.c: New file - checkpoint handling.
|
||||
* src/buffer.c (checkpoint, do_checkpoint): Remove.
|
||||
(_flush_write, simple_flush_read, _gnu_flush_read): Use
|
||||
checkpoint_run.
|
||||
* src/common.h (enum checkpoint_style): Remove.
|
||||
(checkpoint_style): Remove.
|
||||
(DEFAULT_CHECKPOINT): New define.
|
||||
(hard_dereference_option): New variable.
|
||||
(sys_exec_checkpoint_script): New declaration.
|
||||
* src/create.c (file_count_links): do nothing if
|
||||
hard_dereference_option is set.
|
||||
* src/system.c (sys_exec_checkpoint_script): New function.
|
||||
(sys_exec_info_script): Restore SIGPIPE handler.
|
||||
* src/tar.c: (parse_opt): New options --hard-dereference,
|
||||
--checkpoint-action.
|
||||
(decode_options): Call checkpoint_finish_compile.
|
||||
|
||||
* src/system.c (sys_exec_info_script): Initialize buf. Problem
|
||||
reported by Bengt-Arne Fjellner.
|
||||
|
||||
2007-10-18 Jim Meyering <jim@meyering.net>
|
||||
|
||||
Avoid compiler warnings.
|
||||
* src/list.c (read_header_primitive): Define two locals, to
|
||||
avoid incorrect "may be used uninitialized" warnings.
|
||||
* src/incremen.c (procdir): Remove decl of unused local, "len".
|
||||
|
||||
2007-10-18 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/tar.texi (gzip): Remove compression patent
|
||||
warning. According to Brett Smith, the patent is
|
||||
expired.
|
||||
|
||||
2007-10-17 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/suffix.c: New file. Compress format detection by archive
|
||||
suffix (when creating). Suggested by Jean-Pierre Demailly.
|
||||
* src/Makefile.am: Add suffix.c
|
||||
* src/buffer.c (magic): Add an entry for new lzma format. Proposed
|
||||
by Lasse Collin.
|
||||
* src/common.h (set_comression_program_by_suffix): New prototype.
|
||||
* src/tar.c: New options --auto-compress (-a) and --lzma
|
||||
* THANKS: Add Lasse Collin and Jean-Pierre Demailly.
|
||||
* NEWS: Update
|
||||
* doc/tar.texi: Update
|
||||
|
||||
2007-10-12 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* src/utf8.c (string_ascii_p): Recode to avoid bogus GCC 4.2.1
|
||||
warning about "comparison is always true due to limited range of
|
||||
data type" when char is unsigned.
|
||||
|
||||
2007-10-11 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Adjust to recent gnulib changes.
|
||||
* configure.ac: Dont' check for strerror, since gnulib now does this.
|
||||
* .cvsignore: Add m4, tar-[0-9]*.
|
||||
* lib/.cvsignore: Adjust to various gnulib file name changes.
|
||||
Add .deps, rmt-command.h.
|
||||
|
||||
2007-10-10 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* configure.ac, NEWS: Raise version number to 1.19
|
||||
* tests/star/README: Update
|
||||
|
||||
2007-10-05 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/create.c (dump_regular_file): Fix file padding in case of
|
||||
@@ -30,8 +213,8 @@
|
||||
Implement --exclude-tag* and --exclude-cache* options for listed
|
||||
incremental archives.
|
||||
New option --exclude-vcs to exclude VCS-specific files and
|
||||
directories.
|
||||
|
||||
directories.
|
||||
|
||||
* NEWS: Update
|
||||
* doc/tar.texi: Document --exclude-vcs option
|
||||
* src/common.h (exclusion_tag_warning, check_exclusion_tags): New
|
||||
@@ -49,7 +232,7 @@
|
||||
(scan_directory): Hanlde exclusion tags.
|
||||
* src/tar.c: New option --exclude-vcs
|
||||
(exclude_vcs_files): New function
|
||||
|
||||
|
||||
2007-09-14 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* AUTHORS: Remove unnecessary information. Just list the
|
||||
|
||||
66
NEWS
66
NEWS
@@ -1,6 +1,68 @@
|
||||
GNU tar NEWS - User visible changes. 2007-10-10
|
||||
GNU tar NEWS - User visible changes. 2008-03-27
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
version 1.19.90 (CVS)
|
||||
|
||||
* New option --auto-compress (-a)
|
||||
|
||||
With --create, selects compression algorithm basing on the suffix
|
||||
of the archive file name.
|
||||
|
||||
* New option --lzma
|
||||
|
||||
Selects LZMA compression algorithm
|
||||
|
||||
* New option --hard-dereference
|
||||
|
||||
During archive creation, dereferences hard links and stores the files
|
||||
they refer to, instead of creating usual hard link members (type '1').
|
||||
|
||||
* New option --checkpoint-action
|
||||
|
||||
This action allows to specify an action to be executed upon hitting a
|
||||
checkpoint. Recognized actions are: dot, echo (the default),
|
||||
echo=string, ttyout=string, exec=cmdline, and sleep=value. Any number
|
||||
of `--checkpoint-action' options can be specified, the actions will be
|
||||
executed in order of their appearance in the command line. See
|
||||
chapter 3.8 "Checkpoints" for a complete description.
|
||||
|
||||
* New options --no-check-device, --check-device.
|
||||
|
||||
The `--no-check-device' option disables comparing device numbers during
|
||||
preparatory stage of an incremental dump. This allows to avoid
|
||||
creating full dumps if the device numbers change (e.g. when using an
|
||||
LVM snapshot).
|
||||
|
||||
The `--check-device' option enables comparing device numbers. This is
|
||||
the default. This option is provided to undo the effect of the previous
|
||||
`--no-check-device' option, e.g. if it was set in TAR_OPTIONS
|
||||
environment variable.
|
||||
|
||||
* The --transform option.
|
||||
|
||||
Any number of `--transform' options can be given in the command line.
|
||||
The specified transformations will be applied in turn.
|
||||
|
||||
The argument to `--transform' option can be a list of replace
|
||||
expressions, separated by a semicolon (as in `sed').
|
||||
|
||||
Filename transformations are applied to symbolic link targets
|
||||
during both creation and extraction. Tar 1.19 used them only
|
||||
during extraction.
|
||||
|
||||
For a detailed description, see chapter 6.7 "Modifying File and Member
|
||||
Names".
|
||||
|
||||
* Info (end-of-volume) scripts
|
||||
|
||||
The value of the blocking factor is made available to info and
|
||||
checkpoint scripts via environment variable TAR_BLOCKING_FACTOR.
|
||||
|
||||
* Bugfixes.
|
||||
** Fix bug introduced in version 1.19: tar refused to update non-existing
|
||||
archives.
|
||||
|
||||
|
||||
version 1.19 - Sergey Poznyakoff, 2007-10-10
|
||||
|
||||
@@ -932,7 +994,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
|
||||
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
|
||||
7
THANKS
7
THANKS
@@ -217,10 +217,12 @@ Janne Snabb snabb@niksula.hut.fi
|
||||
Jason R. Mastaler jason@webmaster.net
|
||||
Jason Armistead Jason.Armistead@otis.com
|
||||
Jay Fenlason hack@gnu.org
|
||||
Jean-Louis Martineau martineau@zmanda.com
|
||||
Jean-Michel Soenen soenen@lectra.fr
|
||||
Jean-Ph. Martin-Flatin syj@ecmwf.int
|
||||
Jean-loup Gailly jloup@chorus.fr
|
||||
Jean-Loup Gailly jloup@chorus.fr
|
||||
Jeff Moskow jeff@rtr.com
|
||||
Jean-Ph. Martin-Flatin syj@ecmwf.int
|
||||
Jean-Pierre Demailly Jean-Pierre.Demailly@ujf-grenoble.fr
|
||||
Jeff Prothero jsp@betz.biostr.washington.edu
|
||||
Jeff Siegel js@hornet.att.com
|
||||
Jeff Sorensen sorenj@alumni.rpi.edu
|
||||
@@ -290,6 +292,7 @@ Konno Hiroharu konno@pac.co.jp
|
||||
Kurt Jaeger pi@lf.net
|
||||
Larry Creech lcreech@lonestar.rcclub.org
|
||||
Larry Schwimmer rosebud@cyclone.stanford.edu
|
||||
Lasse Collin lasse.collin@tukaani.org
|
||||
Laurent Caillat-Vallet caillat@noe.lyon.cemagref.fr
|
||||
Laurent Sainte-Marthe smarthe@genethon.fr
|
||||
Leland Lucius llucius@tiny.net
|
||||
|
||||
152
bootstrap
152
bootstrap
@@ -49,9 +49,9 @@ Options:
|
||||
--force Attempt to bootstrap even if the sources seem
|
||||
not to have been checked out.
|
||||
--skip-po Do not download po files.
|
||||
--update-po[=LANG] Update po file(s) and exit.
|
||||
--update-po Update po files and exit.
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
the paxutils repository.
|
||||
|
||||
If the file bootstrap.conf exists in the current working directory, its
|
||||
contents are read as shell variables to configure the bootstrap.
|
||||
@@ -69,24 +69,34 @@ checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
case ${CVS_AUTH-pserver} in
|
||||
pserver)
|
||||
CVS_PREFIX=':pserver:anonymous@';;
|
||||
ssh)
|
||||
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
|
||||
*)
|
||||
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
case $1 in
|
||||
paxutils)
|
||||
case ${CVS_AUTH-pserver} in
|
||||
pserver)
|
||||
CVS_PREFIX=':pserver:anonymous@';;
|
||||
ssh)
|
||||
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
|
||||
*)
|
||||
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
case $CVS_RSH in
|
||||
'') CVS_RSH=ssh; export CVS_RSH;;
|
||||
case $CVS_RSH in
|
||||
'') CVS_RSH=ssh; export CVS_RSH;;
|
||||
esac
|
||||
|
||||
CVSURL=${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1"
|
||||
;;
|
||||
|
||||
gnulib)
|
||||
CVSURL=:pserver:anonymous@pserver.git.sv.gnu.org:/gnulib.git
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
trap "cleanup $1" 1 2 13 15
|
||||
|
||||
cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1" co $1 ||
|
||||
cleanup $1
|
||||
cvs -z3 -q -d $CVSURL co $1 || cleanup $1
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
@@ -106,11 +116,13 @@ gnulib_modules=
|
||||
# Any gnulib files needed that are not in modules.
|
||||
gnulib_files=
|
||||
|
||||
# Translation Project URL, for the registry of all projects
|
||||
# and for the translation-team master directory.
|
||||
tp_url() {
|
||||
echo "http://translationproject.org/domain/$1.html"
|
||||
}
|
||||
# The command to download all .po files for a specified domain into
|
||||
# a specified directory. Fill in the first %s is the domain name, and
|
||||
# the second with the destination directory. Use rsync's -L and -r
|
||||
# options because the latest/%s directory and the .po files within are
|
||||
# all symlinks.
|
||||
po_download_command_format=\
|
||||
"rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
|
||||
|
||||
extract_package_name='
|
||||
/^AC_INIT(/{
|
||||
@@ -213,78 +225,60 @@ echo "$0: Bootstrapping CVS $package..."
|
||||
|
||||
# Get translations.
|
||||
|
||||
get_translations() {
|
||||
download_po_files() {
|
||||
subdir=$1
|
||||
domain=$2
|
||||
po_file=$3
|
||||
|
||||
case $WGET_COMMAND in
|
||||
'')
|
||||
echo "$0: wget not available; skipping translations";;
|
||||
?*)
|
||||
url=`tp_url $domain`
|
||||
baseurl=`expr "$url" : '\(.*\)/.*'`
|
||||
echo "$0: getting translations into $subdir for $domain..." &&
|
||||
case $po_file in
|
||||
'') (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`);;
|
||||
esac &&
|
||||
|
||||
$WGET_COMMAND -O "$subdir/$domain.html" "$url" &&
|
||||
|
||||
sed -n 's|.*href="\(.*\)/\([^/][^/]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\2:\3:\1|p' <"$subdir/$domain.html" |
|
||||
sort -t: -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
|
||||
awk -F: '
|
||||
{ if (lang && $1 != lang) print lang, ver, $3 }
|
||||
{ lang = $1; ver = $2 }
|
||||
END { if (lang) print lang, ver, $3 }
|
||||
' | awk -v domain="$domain" -v baseurl="$baseurl" -v subdir="$subdir" \
|
||||
-v po_file="$po_file" '
|
||||
{
|
||||
lang = $1
|
||||
if (po_file && po_file != (lang ".po")) next
|
||||
ver = $2
|
||||
printf "{ $WGET_COMMAND -O %s/%s.po %s/%s/%s/%s-%s.%s.po &&\n", subdir, lang, baseurl, $3, lang, domain, ver, lang
|
||||
printf " msgfmt -c -o /dev/null %s/%s.po || {\n", subdir, lang
|
||||
printf " echo >&2 '\'"$0"': omitting translation for %s'\''\n", lang
|
||||
printf " rm -f %s/%s.po; }; } &&\n", subdir, lang
|
||||
}
|
||||
END { print ":" }
|
||||
' | WGET_COMMAND="$WGET_COMMAND" sh
|
||||
;;
|
||||
esac &&
|
||||
ls "$subdir"/*.po 2>/dev/null |
|
||||
sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
|
||||
rm -f "$subdir/$domain.html"
|
||||
echo "$0: getting translations into $subdir for $domain..."
|
||||
cmd=`printf "$po_download_command_format" "$domain" "$subdir"`
|
||||
eval "$cmd"
|
||||
}
|
||||
|
||||
case `wget --help` in
|
||||
*'--no-cache'*)
|
||||
WGET_COMMAND='wget -nv --no-cache';;
|
||||
*'--cache=on/off'*)
|
||||
WGET_COMMAND='wget -nv --cache=off';;
|
||||
*'--non-verbose'*)
|
||||
WGET_COMMAND='wget -nv';;
|
||||
*)
|
||||
WGET_COMMAND='';;
|
||||
esac
|
||||
# Download .po files to $po_dir/.reference and copy only the new
|
||||
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
|
||||
update_po_files() {
|
||||
# Directory containing primary .po files.
|
||||
# Overwrite them only when we're sure a .po file is new.
|
||||
po_dir=$1
|
||||
domain=$2
|
||||
|
||||
# Download *.po files into this dir.
|
||||
# Usually contains *.s1 checksum files.
|
||||
ref_po_dir="$po_dir/.reference"
|
||||
|
||||
test -d $ref_po_dir || mkdir $ref_po_dir || return
|
||||
download_po_files $ref_po_dir $domain \
|
||||
&& ls "$ref_po_dir"/*.po 2>/dev/null |
|
||||
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
|
||||
|
||||
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
|
||||
test "$langs" = '*' && langs=x
|
||||
for po in `cd $ref_po_dir && echo *.po|sed 's/\.po//g'`; do
|
||||
case $po in x) continue;; esac
|
||||
new_po="$ref_po_dir/$po.po"
|
||||
cksum_file="$ref_po_dir/$po.s1"
|
||||
if ! test -f "$cksum_file" ||
|
||||
! test -f "$po_dir/$po.po" ||
|
||||
! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
|
||||
echo "updated $po_dir/$po.po..."
|
||||
cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
'skip')
|
||||
;;
|
||||
'')
|
||||
get_translations po $package || exit
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
;;
|
||||
'only')
|
||||
get_translations po $package
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
exit
|
||||
;;
|
||||
*.po)
|
||||
get_translations po $package "$DOWNLOAD_PO"
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
get_translations po $package "${DOWNLOAD_PO}.po"
|
||||
exit
|
||||
esac
|
||||
|
||||
# Get paxutils files.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Configure template for GNU tar.
|
||||
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
# 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
|
||||
@@ -18,7 +18,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AC_INIT([GNU tar], [1.19], [bug-tar@gnu.org])
|
||||
AC_INIT([GNU tar], [1.20], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
@@ -87,7 +87,7 @@ gl_INIT
|
||||
# paxutils modules
|
||||
tar_PAXUTILS
|
||||
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink strerror symlink setlocale utimes)
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
|
||||
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
|
||||
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
||||
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
||||
|
||||
@@ -31,7 +31,7 @@ tar_TEXINFOS = \
|
||||
snapshot.texi\
|
||||
sparse.texi\
|
||||
value.texi
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
|
||||
|
||||
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
|
||||
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
@@ -46,6 +46,18 @@ header.texi: $(top_srcdir)/src/tar.h
|
||||
master-menu: $(tar_TEXINFOS)
|
||||
emacs -batch -l mastermenu.el -f make-master-menu $(info_TEXINFOS)
|
||||
|
||||
untabify:
|
||||
emacs -batch -l untabify.el $(info_TEXINFOS) $(tar_TEXINFOS)
|
||||
|
||||
final: untabify master-menu
|
||||
|
||||
# Checking
|
||||
check-format:
|
||||
@if test -n "`cat $(info_TEXINFOS) $(tar_TEXINFOS) | tr -d -c '\t'`"; then \
|
||||
echo "Sources contain tabs; run make untabify"; \
|
||||
false; \
|
||||
fi
|
||||
|
||||
check-options:
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
|
||||
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
@@ -67,6 +79,52 @@ doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
fi;\
|
||||
rm report.$$$$
|
||||
|
||||
check-refs:
|
||||
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
|
||||
do \
|
||||
sed -e = $$file | \
|
||||
sed -n 'N;/@FIXME-.*ref/{s/\(^[0-9][0-9]*\).*@FIXME-.*ref{\([^}]*\).*/'$$file':\1: \2/gp}'; \
|
||||
done > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unresolved cross-references:"; \
|
||||
cat $@-t;\
|
||||
rm $@-t; \
|
||||
else \
|
||||
rm -f $@-t; \
|
||||
fi
|
||||
|
||||
check-fixmes:
|
||||
@for file in $(info_TEXINFOS); \
|
||||
do \
|
||||
sed -e = $$file | \
|
||||
sed -n 'N;/@FIXME{/{s/\(^[0-9][0-9]*\).*@FIXME{\([^}]*\).*/'$$file':\1: \2/gp}'; \
|
||||
done > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unresolved FIXMEs:"; \
|
||||
cat $@-t; \
|
||||
rm $@-t; \
|
||||
false; \
|
||||
else \
|
||||
rm -f $@-t; \
|
||||
fi
|
||||
|
||||
check-unrevised:
|
||||
@grep -Hn @UNREVISED $(info_TEXINFOS) > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unrevised nodes:"; \
|
||||
cat $@-t; \
|
||||
rm $@-t; \
|
||||
false;\
|
||||
else \
|
||||
rm $@-t; \
|
||||
fi
|
||||
|
||||
all-check-docs: check-format check-options check-refs check-fixmes check-unrevised
|
||||
|
||||
check-docs:
|
||||
$(MAKE) -k all-check-docs
|
||||
|
||||
#
|
||||
|
||||
clean-local:
|
||||
rm -rf manual
|
||||
@@ -82,5 +140,5 @@ manual:
|
||||
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
|
||||
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
|
||||
$(GENDOCS) tar 'GNU tar manual'
|
||||
$(GENDOCS) --texi2html tar 'GNU tar manual'
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<!-- $Id: gendocs_template,v 1.3 2007/01/19 15:41:39 gray Exp $ -->
|
||||
<!-- $Id: gendocs_template,v 1.5 2007/10/30 14:58:52 gray Exp $ -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<head>
|
||||
@@ -30,23 +30,40 @@
|
||||
alt=" [image of the head of a GNU] "
|
||||
width="129" height="122" />
|
||||
</a>
|
||||
<a href="/philosophy/gif.html">(no gifs due to patent problems)</a>
|
||||
</p>
|
||||
<hr />
|
||||
|
||||
The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="%%PACKAGE%%.html">HTML
|
||||
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
|
||||
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
|
||||
<li><a href="html_node/index.html">HTML</a> - with one web page per
|
||||
node.</li>
|
||||
%%IF HTML_SECTION%%
|
||||
<li><a href="html_section/index.html">HTML</a> - with one web page per
|
||||
section.</li>
|
||||
%%ENDIF HTML_SECTION%%
|
||||
%%IF HTML_CHAPTER%%
|
||||
<li><a href="html_chapter/index.html">HTML</a> - with one web page per
|
||||
chapter.</li>
|
||||
%%ENDIF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
|
||||
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
|
||||
one web page.</li>
|
||||
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
|
||||
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per node.</li>
|
||||
%%IF HTML_SECTION%%
|
||||
<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
|
||||
(%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per section.</li>
|
||||
%%ENDIF HTML_SECTION%%
|
||||
%%IF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
|
||||
(%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per chapter.</li>
|
||||
%%ENDIF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
|
||||
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt">ASCII text
|
||||
@@ -99,7 +116,7 @@ permitted in any medium, provided this notice is preserved.
|
||||
<p>
|
||||
Updated:
|
||||
<!-- timestamp start -->
|
||||
$Date: 2007/01/19 15:41:39 $ $Author: gray $
|
||||
$Date: 2007/10/30 14:58:52 $ $Author: gray $
|
||||
<!-- timestamp end -->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -36,8 +36,6 @@ Archives are permitted to have more than one member with the same
|
||||
member name. One way this situation can occur is if more than one
|
||||
version of a file has been stored in the archive. For information
|
||||
about adding new versions of a file to an archive, see @ref{update}.
|
||||
@FIXME-xref{To learn more about having more than one archive member with the
|
||||
same name, see -backup node, when it's written.}
|
||||
|
||||
In addition to entries describing archive members, an archive may
|
||||
contain entries which @command{tar} itself uses to store information.
|
||||
@@ -108,11 +106,11 @@ group permission could be copied from the @emph{other} permission.
|
||||
|
||||
The @code{uid} and @code{gid} fields are the numeric user and group
|
||||
@acronym{ID} of the file owners, respectively. If the operating system does
|
||||
not support numeric user or group @acronym{ID}s, these fields should be ignored.
|
||||
not support numeric user or group @acronym{ID}s, these fields should
|
||||
be ignored.
|
||||
|
||||
The @code{size} field is the size of the file in bytes; linked files
|
||||
are archived with this field specified as zero. @FIXME-xref{Modifiers, in
|
||||
particular the @option{--incremental} (@option{-G}) option.}
|
||||
are archived with this field specified as zero.
|
||||
|
||||
The @code{mtime} field is the data modification time of the file at
|
||||
the time it was archived. It is the ASCII representation of the octal
|
||||
|
||||
@@ -72,19 +72,28 @@
|
||||
@ifset PROOF
|
||||
@strong{<REF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
@cite{\string\}
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@macro FIXME-pxref{string}
|
||||
@ifset PROOF
|
||||
@strong{<PXREF>} \string\ @strong{</>}
|
||||
See @strong{<PXREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
See @cite{\string\}
|
||||
@end ifclear
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-xref{string}
|
||||
@ifset PROOF
|
||||
@strong{<XREF>} \string\ @strong{</>}
|
||||
See @strong{<XREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
See @cite{\string\}
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@c End of rendition.texi
|
||||
|
||||
563
doc/tar.texi
563
doc/tar.texi
@@ -35,7 +35,7 @@ This manual is for @acronym{GNU} @command{tar} (version
|
||||
from archives.
|
||||
|
||||
Copyright @copyright{} 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
@@ -45,9 +45,9 @@ Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license
|
||||
is included in the section entitled "GNU Free Documentation License".
|
||||
|
||||
(a) The FSF's Back-Cover Text is: ``You are free to copy and modify
|
||||
this GNU Manual. Buying copies from GNU Press supports the FSF in
|
||||
developing GNU and promoting software freedom.''
|
||||
(a) The FSF's Back-Cover Text is: ``You have the freedom to
|
||||
copy and modify this GNU manual. Buying copies from the FSF
|
||||
supports it in developing GNU and promoting software freedom.''
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@@ -176,6 +176,7 @@ Invoking @GNUTAR{}
|
||||
* help::
|
||||
* defaults::
|
||||
* verbose::
|
||||
* checkpoints::
|
||||
* interactive::
|
||||
|
||||
The Three Option Styles
|
||||
@@ -330,6 +331,7 @@ Making @command{tar} Archives More Portable
|
||||
|
||||
* Portable Names:: Portable Names
|
||||
* dereference:: Symbolic Links
|
||||
* hard links:: Hard Links
|
||||
* old:: Old V7 Archives
|
||||
* ustar:: Ustar Archives
|
||||
* gnu:: GNU and old GNU format archives.
|
||||
@@ -451,11 +453,8 @@ concepts of using a Unix-type operating system; @pxref{Tutorial}.)
|
||||
The third chapter presents the remaining five operations, and
|
||||
information about using @command{tar} options and option syntax.
|
||||
|
||||
@FIXME{this sounds more like a @acronym{GNU} Project Manuals Concept [tm] more
|
||||
than the reality. should think about whether this makes sense to say
|
||||
here, or not.} The other chapters are meant to be used as a
|
||||
reference. Each chapter presents everything that needs to be said
|
||||
about a specific topic.
|
||||
The other chapters are meant to be used as a reference. Each chapter
|
||||
presents everything that needs to be said about a specific topic.
|
||||
|
||||
One of the chapters (@pxref{Date input formats}) exists in its
|
||||
entirety in other @acronym{GNU} manuals, and is mostly self-contained.
|
||||
@@ -685,7 +684,7 @@ change between directories; and how to figure out where you are in the
|
||||
file system. You should have some basic understanding of directory
|
||||
structure and how files are named according to which directory they are
|
||||
in. You should understand concepts such as standard output and standard
|
||||
input, what various definitions of the term ``argument'' mean, and the
|
||||
input, what various definitions of the term @samp{argument} mean, and the
|
||||
differences between relative and absolute file names. @FIXME{and what
|
||||
else?}
|
||||
|
||||
@@ -750,10 +749,9 @@ You can write most of the @command{tar} operations and options in any
|
||||
of three forms: long (mnemonic) form, short form, and old style. Some
|
||||
of the operations and options have no short or ``old'' forms; however,
|
||||
the operations and options which we will cover in this tutorial have
|
||||
corresponding abbreviations. @FIXME{make sure this is still the case,
|
||||
at the end}We will indicate those abbreviations appropriately to get
|
||||
you used to seeing them. (Note that the ``old style'' option forms
|
||||
exist in @GNUTAR{} for compatibility with Unix
|
||||
corresponding abbreviations. We will indicate those abbreviations
|
||||
appropriately to get you used to seeing them. (Note that the ``old
|
||||
style'' option forms exist in @GNUTAR{} for compatibility with Unix
|
||||
@command{tar}. In this book we present a full discussion of this way
|
||||
of writing options and operations (@pxref{Old Options}), and we discuss
|
||||
the other two styles of writing options (@xref{Long Options}, and
|
||||
@@ -1763,6 +1761,7 @@ use @w{@kbd{tar --list --verbose}} to list them correctly.
|
||||
|
||||
@node going further
|
||||
@section Going Further Ahead in this Manual
|
||||
@UNREVISED
|
||||
|
||||
@FIXME{need to write up a node here about the things that are going to
|
||||
be in the rest of the manual.}
|
||||
@@ -1801,6 +1800,7 @@ and @option{--interactive} options (@pxref{interactive}).
|
||||
* help::
|
||||
* defaults::
|
||||
* verbose::
|
||||
* checkpoints::
|
||||
* interactive::
|
||||
@end menu
|
||||
|
||||
@@ -2402,6 +2402,13 @@ a read-only loopback mount, or use the @samp{noatime} mount option
|
||||
available on some systems. However, mounting typically requires
|
||||
superuser privileges and can be a pain to manage.
|
||||
|
||||
@opsummary{auto-compress}
|
||||
@item --auto-compress
|
||||
@itemx -a
|
||||
|
||||
During a @option{--create} operation, enables automatic compressed
|
||||
format recognition based on the archive suffix. @xref{gzip}.
|
||||
|
||||
@opsummary{backup}
|
||||
@item --backup=@var{backup-type}
|
||||
|
||||
@@ -2430,14 +2437,63 @@ record. @xref{Blocking Factor}.
|
||||
This option tells @command{tar} to read or write archives through
|
||||
@code{bzip2}. @xref{gzip}.
|
||||
|
||||
@opsummary{check-device}
|
||||
@item --check-device
|
||||
Check device numbers when creating a list of modified files for
|
||||
incremental archiving. This is the default. @xref{device numbers},
|
||||
for a detailed description.
|
||||
|
||||
@opsummary{checkpoint}
|
||||
@item --checkpoint[=@var{number}]
|
||||
|
||||
This option directs @command{tar} to print periodic checkpoint
|
||||
messages as it reads through the archive. It is intended for when you
|
||||
want a visual indication that @command{tar} is still running, but
|
||||
don't want to see @option{--verbose} output. For a detailed
|
||||
description, see @ref{Progress information}.
|
||||
don't want to see @option{--verbose} output. You can also instruct
|
||||
@command{tar} to execute a list of actions on each checkpoint, see
|
||||
@option{--checklist-action} below. For a detailed description, see
|
||||
@ref{checkpoints}.
|
||||
|
||||
@opsummary{checkpoint-action}
|
||||
@item --checkpoint-action=@var{action}
|
||||
Instruct @command{tar} to execute an action upon hitting a
|
||||
breakpoint. Here we give only a brief outline. @xref{checkpoints},
|
||||
for a complete description.
|
||||
|
||||
The @var{action} argument can be one of the following:
|
||||
|
||||
@table @asis
|
||||
@item bell
|
||||
Produce an audible bell on the console.
|
||||
|
||||
@item dot
|
||||
@itemx .
|
||||
Print a single dot on the standard listing stream.
|
||||
|
||||
@item echo
|
||||
Display a textual message on the standard error, with the status and
|
||||
number of the checkpoint. This is the default.
|
||||
|
||||
@item echo=@var{string}
|
||||
Display @var{string} on the standard error. Before output, the string
|
||||
is subject to meta-character expansion.
|
||||
|
||||
@item exec=@var{command}
|
||||
Execute the given @var{command}.
|
||||
|
||||
@item sleep=@var{time}
|
||||
Wait for @var{time} seconds.
|
||||
|
||||
@item ttyout=@var{string}
|
||||
Output @var{string} on the current console (@file{/dev/tty}).
|
||||
@end table
|
||||
|
||||
Several @option{--checkpoint-action} options can be specified. The
|
||||
supplied actions will be executed in order of their appearance in the
|
||||
command line.
|
||||
|
||||
Using @option{--checkpoint-action} without @option{--checkpoint}
|
||||
assumes default checkpoint frequency of one checkpoint per 10 records.
|
||||
|
||||
@opsummary{check-links}
|
||||
@item --check-links
|
||||
@@ -2450,6 +2506,8 @@ synonym for @option{--one-file-system}. The current semantics, which
|
||||
complies to UNIX98, was introduced with version
|
||||
1.15.91. @xref{Changes}, for more information.}.
|
||||
|
||||
@xref{hard links}.
|
||||
|
||||
@opsummary{compress}
|
||||
@opsummary{uncompress}
|
||||
@item --compress
|
||||
@@ -2538,7 +2596,7 @@ named @var{file}, but dump the directory node itself. @xref{exclude}.
|
||||
@item --exclude-tag-all=@var{file}
|
||||
|
||||
Exclude from dump any directory containing file named @var{file}.
|
||||
@xref{exclude}.
|
||||
@xref{exclude}.
|
||||
|
||||
@opsummary{exclude-vcs}
|
||||
@item --exclude-vcs
|
||||
@@ -2623,6 +2681,13 @@ This option tells @command{tar} to read or write archives through
|
||||
@command{gzip}, allowing @command{tar} to directly operate on several
|
||||
kinds of compressed archives transparently. @xref{gzip}.
|
||||
|
||||
@opsummary{hard-dereference}
|
||||
@item --hard-dereference
|
||||
When creating an archive, dereference hard links and store the files
|
||||
they refer to, instead of creating usual hard link members.
|
||||
|
||||
@xref{hard links}.
|
||||
|
||||
@opsummary{help}
|
||||
@item --help
|
||||
@itemx -?
|
||||
@@ -2718,6 +2783,12 @@ backup, using @var{snapshot-file} to determine which files to backup.
|
||||
With other operations, informs @command{tar} that the archive is in
|
||||
incremental format. @xref{Incremental Dumps}.
|
||||
|
||||
@opsummary{lzma}
|
||||
@item --lzma
|
||||
|
||||
This option tells @command{tar} to read or write archives through
|
||||
@command{lzma}. @xref{gzip}.
|
||||
|
||||
@opsummary{mode}
|
||||
@item --mode=@var{permissions}
|
||||
|
||||
@@ -2772,6 +2843,12 @@ changed). @xref{after}.
|
||||
An exclude pattern can match any subsequence of the name's components.
|
||||
@xref{controlling pattern-matching}.
|
||||
|
||||
@opsummary{no-check-device}
|
||||
@item --no-check-device
|
||||
Do not check device numbers when creating a list of modified files
|
||||
for incremental archiving. @xref{device numbers}, for
|
||||
a detailed description.
|
||||
|
||||
@opsummary{no-delay-directory-restore}
|
||||
@item --no-delay-directory-restore
|
||||
|
||||
@@ -2893,9 +2970,7 @@ Synonym for @option{--format=v7}.
|
||||
@item --one-file-system
|
||||
Used when creating an archive. Prevents @command{tar} from recursing into
|
||||
directories that are on different file systems from the current
|
||||
directory @footnote{Earlier versions of @GNUTAR{} understood @option{-l} as a
|
||||
synonym for @option{--one-file-system}. This has changed in version
|
||||
1.15.91. @xref{Changes}, for more information.}.
|
||||
directory.
|
||||
|
||||
@opsummary{overwrite}
|
||||
@item --overwrite
|
||||
@@ -3374,7 +3449,7 @@ successfully. For example, @w{@samp{tar --version}} might print:
|
||||
|
||||
@smallexample
|
||||
tar (GNU tar) @value{VERSION}
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
This is free software. You may redistribute copies of it under the terms
|
||||
of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
@@ -3596,7 +3671,6 @@ after finishing the extraction, as well as when receiving signal
|
||||
|
||||
@anchor{Progress information}
|
||||
@cindex Progress information
|
||||
@opindex checkpoint
|
||||
The @option{--checkpoint} option prints an occasional message
|
||||
as @command{tar} reads or writes the archive. It is designed for
|
||||
those who don't need the more detailed (and voluminous) output of
|
||||
@@ -3614,13 +3688,19 @@ tar: Write checkpoint 3000
|
||||
|
||||
This example shows the default checkpoint message used by
|
||||
@command{tar}. If you place a dot immediately after the equal
|
||||
sign, it will print a @samp{.} at each checkpoint. For example:
|
||||
sign, it will print a @samp{.} at each checkpoint@footnote{This is
|
||||
actually a shortcut for @option{--checkpoint=@var{n}
|
||||
--checkpoint-action=dot}. @xref{checkpoints, dot}.}. For example:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=.1000} /var
|
||||
...
|
||||
@end smallexample
|
||||
|
||||
The @option{--checkpoint} option provides a flexible mechanism for
|
||||
executing arbitrary actions upon hitting checkpoints, see the next
|
||||
section (@pxref{checkpoints}), for more information on it.
|
||||
|
||||
@opindex show-omitted-dirs
|
||||
@anchor{show-omitted-dirs}
|
||||
The @option{--show-omitted-dirs} option, when reading an archive---with
|
||||
@@ -3653,6 +3733,196 @@ choose among several backup tapes when retrieving a file later, in
|
||||
favor of the tape where the file appears earliest (closest to the
|
||||
front of the tape). @xref{backup}.
|
||||
|
||||
@node checkpoints
|
||||
@section Checkpoints
|
||||
@cindex checkpoints, defined
|
||||
@opindex checkpoint
|
||||
@opindex checkpoint-action
|
||||
|
||||
A @dfn{checkpoint} is a moment of time before writing @var{n}th record to
|
||||
the archive (a @dfn{write checkpoint}), or before reading @var{n}th record
|
||||
from the archive (a @dfn{read checkpoint}). Checkpoints allow to
|
||||
periodically execute arbitrary actions.
|
||||
|
||||
The checkpoint facility is enabled using the following option:
|
||||
|
||||
@table @option
|
||||
@xopindex{checkpoint, defined}
|
||||
@item --checkpoint[=@var{n}]
|
||||
Schedule checkpoints before writing or reading each @var{n}th record.
|
||||
The default value for @var{n} is 10.
|
||||
@end table
|
||||
|
||||
A list of arbitrary @dfn{actions} can be executed at each checkpoint.
|
||||
These actions include: pausing, displaying textual messages, and
|
||||
executing arbitrary external programs. Actions are defined using
|
||||
the @option{--checkpoint-action} option.
|
||||
|
||||
@table @option
|
||||
@xopindex{checkpoint-action, defined}
|
||||
@item --checkpoint-action=@var{action}
|
||||
Execute an @var{action} at each checkpoint.
|
||||
@end table
|
||||
|
||||
@cindex @code{echo}, checkpoint action
|
||||
The simplest value of @var{action} is @samp{echo}. It instructs
|
||||
@command{tar} to display the default message on the standard error
|
||||
stream upon arriving at each checkpoint. The default message is (in
|
||||
@acronym{POSIX} locale) @samp{Write checkpoint @var{n}}, for write
|
||||
checkpoints, and @samp{Read checkpoint @var{n}}, for read checkpoints.
|
||||
Here, @var{n} represents ordinal number of the checkpoint.
|
||||
|
||||
In another locales, translated versions of this message are used.
|
||||
|
||||
This is the default action, so running:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=echo} /var
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
is equivalent to:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=1000} /var
|
||||
@end smallexample
|
||||
|
||||
The @samp{echo} action also allows to supply a customized message.
|
||||
You do so by placing an equals sign and the message right after it,
|
||||
e.g.:
|
||||
|
||||
@smallexample
|
||||
--checkpoint-action="echo=Hit %s checkpoint #%u"
|
||||
@end smallexample
|
||||
|
||||
The @samp{%s} and @samp{%u} in the above example are
|
||||
@dfn{meta-characters}. The @samp{%s} meta-character is replaced with
|
||||
the @dfn{type} of the checkpoint: @samp{write} or
|
||||
@samp{read} (or a corresponding translated version in locales other
|
||||
than @acronym{POSIX}). The @samp{%u} meta-character is replaced with
|
||||
the ordinal number of the checkpoint. Thus, the above example could
|
||||
produce the following output when used with the @option{--create}
|
||||
option:
|
||||
|
||||
@smallexample
|
||||
tar: Hit write checkpoint #10
|
||||
tar: Hit write checkpoint #20
|
||||
tar: Hit write checkpoint #30
|
||||
@end smallexample
|
||||
|
||||
Aside from meta-character expansion, the message string is subject to
|
||||
@dfn{unquoting}, during which the backslash @dfn{escape sequences} are
|
||||
replaced with their corresponding @acronym{ASCII} characters
|
||||
(@pxref{escape sequences}). E.g. the following action will produce an
|
||||
audible bell and the message described above at each checkpoint:
|
||||
|
||||
@smallexample
|
||||
--checkpoint-action='echo=\aHit %s checkpoint #%u'
|
||||
@end smallexample
|
||||
|
||||
@cindex @code{bell}, checkpoint action
|
||||
There is also a special action which produces an audible signal:
|
||||
@samp{bell}. It is not equivalent to @samp{echo='\a'}, because
|
||||
@samp{bell} sends the bell directly to the console (@file{/dev/tty}),
|
||||
whereas @samp{echo='\a'} sends it to the standard error.
|
||||
|
||||
@cindex @code{ttyout}, checkpoint action
|
||||
The @samp{ttyout=@var{string}} action outputs @var{string} to
|
||||
@file{/dev/tty}, so it can be used even if the standard output is
|
||||
redirected elsewhere. The @var{string} is subject to the same
|
||||
modifications as with @samp{echo} action. In contrast to the latter,
|
||||
@samp{ttyout} does not prepend @command{tar} executable name to the
|
||||
string, nor does it output a newline after it. For example, the
|
||||
following action will print the checkpoint message at the same screen
|
||||
line, overwriting any previous message:
|
||||
|
||||
@smallexample
|
||||
--checkpoint-action="ttyout=\rHit %s checkpoint #%u"
|
||||
@end smallexample
|
||||
|
||||
@cindex @code{dot}, checkpoint action
|
||||
Another available checkpoint action is @samp{dot} (or @samp{.}). It
|
||||
instructs @command{tar} to print a single dot on the standard listing
|
||||
stream, e.g.:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=dot} /var
|
||||
...
|
||||
@end smallexample
|
||||
|
||||
For compatibility with previous @GNUTAR{} versions, this action can
|
||||
be abbreviated by placing a dot in front of the checkpoint frequency,
|
||||
as shown in the previous section.
|
||||
|
||||
@cindex @code{sleep}, checkpoint action
|
||||
Yet another action, @samp{sleep}, pauses @command{tar} for a specified
|
||||
amount of seconds. The following example will stop for 30 seconds at each
|
||||
checkpoint:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=sleep=30}
|
||||
@end smallexample
|
||||
|
||||
@cindex @code{exec}, checkpoint action
|
||||
Finally, the @code{exec} action executes a given external program.
|
||||
For example:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=exec=/sbin/cpoint}
|
||||
@end smallexample
|
||||
|
||||
This program is executed using @command{/bin/sh -c}, with no
|
||||
additional arguments. Its exit code is ignored. It gets a copy of
|
||||
@command{tar}'s environment plus the following variables:
|
||||
|
||||
@table @env
|
||||
@vrindex TAR_VERSION, checkpoint script environment
|
||||
@item TAR_VERSION
|
||||
@GNUTAR{} version number.
|
||||
|
||||
@vrindex TAR_ARCHIVE, checkpoint script environment
|
||||
@item TAR_ARCHIVE
|
||||
The name of the archive @command{tar} is processing.
|
||||
|
||||
@vrindex TAR_BLOCKING_FACTOR, checkpoint script environment
|
||||
@item TAR_BLOCKING_FACTOR
|
||||
Current blocking factor (@pxref{Blocking}.
|
||||
|
||||
@vrindex TAR_CHECKPOINT, checkpoint script environment
|
||||
@item TAR_CHECKPOINT
|
||||
The checkpoint number.
|
||||
|
||||
@vrindex TAR_SUBCOMMAND, checkpoint script environment
|
||||
@item TAR_SUBCOMMAND
|
||||
A short option describing the operation @command{tar} is executing
|
||||
@xref{Operations}, for a complete list of subcommand options.
|
||||
|
||||
@vrindex TAR_FORMAT, checkpoint script environment
|
||||
@item TAR_FORMAT
|
||||
Format of the archive being processed. @xref{Formats}, for a complete
|
||||
list of archive format names.
|
||||
@end table
|
||||
|
||||
Any number of actions can be defined, by supplying several
|
||||
@option{--checkpoint-action} options in the command line. For
|
||||
example, the command below displays two messages, pauses
|
||||
execution for 30 seconds and executes the @file{/sbin/cpoint} script:
|
||||
|
||||
@example
|
||||
@group
|
||||
$ @kbd{tar -c -f arc.tar \
|
||||
--checkpoint-action='\aecho=Hit %s checkpoint #%u' \
|
||||
--checkpoint-action='echo=Sleeping for 30 seconds' \
|
||||
--checkpoint-action='sleep=30' \
|
||||
--checkpoint-action='exec=/sbin/cpoint'}
|
||||
@end group
|
||||
@end example
|
||||
|
||||
This example also illustrates the fact that
|
||||
@option{--checkpoint-action} can be used without
|
||||
@option{--checkpoint}. In this case, the default checkpoint frequency
|
||||
(at each 10th record) is assumed.
|
||||
|
||||
@node interactive
|
||||
@section Asking for Confirmation During Operations
|
||||
@cindex Interactive operation
|
||||
@@ -4874,7 +5144,7 @@ option is used.
|
||||
The command can obtain the information about the file it processes
|
||||
from the following environment variables:
|
||||
|
||||
@table @var
|
||||
@table @env
|
||||
@vrindex TAR_FILETYPE, to-command environment
|
||||
@item TAR_FILETYPE
|
||||
Type of the file. It is a single letter with the following meaning:
|
||||
@@ -5415,21 +5685,40 @@ unreliable if you modify a file's time stamps during dumping (e.g.,
|
||||
with the @option{--atime-preserve=replace} option), or if you set the clock
|
||||
backwards.
|
||||
|
||||
@anchor{device numbers}
|
||||
@cindex Device numbers, using in incremental backups
|
||||
Metadata stored in snapshot files include device numbers, which,
|
||||
obviously is supposed to be a non-volatile value. However, it turns
|
||||
out that NFS devices have undependable values when an automounter
|
||||
obviously are supposed to be a non-volatile values. However, it turns
|
||||
out that @acronym{NFS} devices have undependable values when an automounter
|
||||
gets in the picture. This can lead to a great deal of spurious
|
||||
redumping in incremental dumps, so it is somewhat useless to compare
|
||||
two NFS devices numbers over time. The solution implemented currently
|
||||
is to considers all NFS devices as being equal when it comes to
|
||||
comparing directories; this is fairly gross, but there does not seem
|
||||
to be a better way to go.
|
||||
two @acronym{NFS} devices numbers over time. The solution implemented
|
||||
currently is to considers all @acronym{NFS} devices as being equal
|
||||
when it comes to comparing directories; this is fairly gross, but
|
||||
there does not seem to be a better way to go.
|
||||
|
||||
If you are using the @i{Linux} kernel, the device numbers can also
|
||||
change when upgrading to some newer versions of the kernel. This can
|
||||
cause the next backup to be full backup on the affected filesystems.
|
||||
@xref{Fixing Snapshot Files}, for the information on how to handle this case.
|
||||
Apart from using @acronym{NFS}, there are a number of cases where
|
||||
relying on device numbers can cause spurious redumping of unmodified
|
||||
files. For example, this occurs when archiving @acronym{LVM} snapshot
|
||||
volumes. To avoid this, use @option{--no-check-device} option:
|
||||
|
||||
@table @option
|
||||
@xopindex{no-check-device, described}
|
||||
@item --no-check-device
|
||||
Do not rely on device numbers when preparing a list of changed files
|
||||
for an incremental dump.
|
||||
|
||||
@xopindex{check-device, described}
|
||||
@item --check-device
|
||||
Use device numbers when preparing a list of changed files
|
||||
for an incremental dump. This is the default behavior. The purpose
|
||||
of this option is to undo the effect of the @option{--no-check-device}
|
||||
if it was given in @env{TAR_OPTIONS} environment variable
|
||||
(@pxref{TAR_OPTIONS}).
|
||||
@end table
|
||||
|
||||
There is also another way to cope with changing device numbers. It is
|
||||
described in detail in @ref{Fixing Snapshot Files}.
|
||||
|
||||
Note that incremental archives use @command{tar} extensions and may
|
||||
not be readable by non-@acronym{GNU} versions of the @command{tar} program.
|
||||
@@ -5640,7 +5929,7 @@ their support files using the same file name that is used on the
|
||||
machine where the scripts are run (i.e., what @command{pwd} will print
|
||||
when in that directory on that machine). If the host that contains
|
||||
the file system does not have this capability, you can specify another
|
||||
host as long as it can access the file system through NFS.
|
||||
host as long as it can access the file system through @acronym{NFS}.
|
||||
|
||||
If the list of file systems is very long you may wish to put it
|
||||
in a separate file. This file is usually named
|
||||
@@ -6935,7 +7224,7 @@ quoting}. The characters in question are:
|
||||
|
||||
@itemize @bullet
|
||||
@item Non-printable control characters:
|
||||
|
||||
@anchor{escape sequences}
|
||||
@multitable @columnfractions 0.20 0.10 0.60
|
||||
@headitem Character @tab @acronym{ASCII} @tab Character name
|
||||
@item \a @tab 7 @tab Audible bell
|
||||
@@ -7023,7 +7312,7 @@ $ @kbd{tar tf arch.tar --quoting-style=literal}
|
||||
./a'single'quote
|
||||
./a"double"quote
|
||||
./a\backslash
|
||||
./a tab
|
||||
./a tab
|
||||
./a
|
||||
newline
|
||||
@end group
|
||||
@@ -7045,7 +7334,7 @@ $ @kbd{tar tf arch.tar --quoting-style=shell}
|
||||
'./a'\''single'\''quote'
|
||||
'./a"double"quote'
|
||||
'./a\backslash'
|
||||
'./a tab'
|
||||
'./a tab'
|
||||
'./a
|
||||
newline'
|
||||
@end group
|
||||
@@ -7063,7 +7352,7 @@ $ @kbd{tar tf arch.tar --quoting-style=shell-always}
|
||||
'./a'\''single'\''quote'
|
||||
'./a"double"quote'
|
||||
'./a\backslash'
|
||||
'./a tab'
|
||||
'./a tab'
|
||||
'./a
|
||||
newline'
|
||||
@end group
|
||||
@@ -7304,6 +7593,9 @@ replacement for each file name part that matches @var{regexp}. Both
|
||||
@var{regexp} and @var{replace} are described in detail in
|
||||
@ref{The "s" Command, The "s" Command, The `s' Command, sed, GNU sed}.
|
||||
|
||||
As in @command{sed}, you can give several replace expressions,
|
||||
separated by a semicolon.
|
||||
|
||||
Supported @var{flags} are:
|
||||
|
||||
@table @samp
|
||||
@@ -7397,6 +7689,18 @@ If both @option{--strip-components} and @option{--transform} are used
|
||||
together, then @option{--transform} is applied first, and the required
|
||||
number of components is then stripped from its result.
|
||||
|
||||
You can use as many @option{--transform} options in a single command
|
||||
line as you want. The specified expressions will then be applied in
|
||||
order of their appearance. For example, the following two invocations
|
||||
are equivalent:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -cf arch.tar --transform='s,/usr/var,/var/' \
|
||||
--transform='s,/usr/local,/usr/,'}
|
||||
$ @kbd{tar -cf arch.tar \
|
||||
--transform='s,/usr/var,/var/;s,/usr/local,/usr/,'}
|
||||
@end smallexample
|
||||
|
||||
@node after
|
||||
@section Operating Only on New Files
|
||||
@UNREVISED
|
||||
@@ -7941,18 +8245,18 @@ switch to @samp{posix}.
|
||||
@cindex Storing archives in compressed format
|
||||
|
||||
@GNUTAR{} is able to create and read compressed archives. It supports
|
||||
@command{gzip} and @command{bzip2} compression programs. For backward
|
||||
compatibility, it also supports @command{compress} command, although
|
||||
we strongly recommend against using it, since there is a patent
|
||||
covering the algorithm it uses and you could be sued for patent
|
||||
infringement merely by running @command{compress}! Besides, it is less
|
||||
effective than @command{gzip} and @command{bzip2}.
|
||||
@command{gzip}, @command{bzip2} and @command{lzma} compression
|
||||
programs. For backward compatibility, it also supports
|
||||
@command{compress} command, although we strongly recommend against
|
||||
using it, because it is by far less effective than other compression
|
||||
programs@footnote{It also had patent problems in the past.}.
|
||||
|
||||
Creating a compressed archive is simple: you just specify a
|
||||
@dfn{compression option} along with the usual archive creation
|
||||
commands. The compression option is @option{-z} (@option{--gzip}) to
|
||||
create a @command{gzip} compressed archive, @option{-j}
|
||||
(@option{--bzip2}) to create a @command{bzip2} compressed archive, and
|
||||
(@option{--bzip2}) to create a @command{bzip2} compressed archive,
|
||||
@option{--lzma} to create an @asis{LZMA} compressed archive and
|
||||
@option{-Z} (@option{--compress}) to use @command{compress} program.
|
||||
For example:
|
||||
|
||||
@@ -7960,6 +8264,26 @@ For example:
|
||||
$ @kbd{tar cfz archive.tar.gz .}
|
||||
@end smallexample
|
||||
|
||||
You can also let @GNUTAR{} select the compression program basing on
|
||||
the suffix of the archive file name. This is done using
|
||||
@option{--auto-compress} (@option{-a}) command line option. For
|
||||
example, the following invocation will use @command{bzip2} for
|
||||
compression:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar cfa archive.tar.bz2 .}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
whereas the following one will use @command{lzma}:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar cfa archive.tar.lzma .}
|
||||
@end smallexample
|
||||
|
||||
For a complete list of file name suffixes recognized by @GNUTAR{},
|
||||
@ref{auto-compress}.
|
||||
|
||||
Reading compressed archive is even simpler: you don't need to specify
|
||||
any additional options as @GNUTAR{} recognizes its format
|
||||
automatically. Thus, the following commands will list and extract the
|
||||
@@ -7992,15 +8316,38 @@ $ @kbd{cat archive.tar.gz | tar tfz -}
|
||||
|
||||
Notice also, that there are several restrictions on operations on
|
||||
compressed archives. First of all, compressed archives cannot be
|
||||
modified, i.e., you cannot update (@option{--update} (@option{-u})) them or delete
|
||||
(@option{--delete}) members from them. Likewise, you cannot append
|
||||
another @command{tar} archive to a compressed archive using
|
||||
@option{--append} (@option{-r})). Secondly, multi-volume archives cannot be
|
||||
compressed.
|
||||
modified, i.e., you cannot update (@option{--update} (@option{-u}))
|
||||
them or delete (@option{--delete}) members from them or
|
||||
add (@option{--append} (@option{-r})) members to them. Likewise, you
|
||||
cannot append another @command{tar} archive to a compressed archive using
|
||||
@option{--concatenate} (@option{-A})). Secondly, multi-volume
|
||||
archives cannot be compressed.
|
||||
|
||||
The following table summarizes compression options used by @GNUTAR{}.
|
||||
|
||||
@table @option
|
||||
@anchor{auto-compress}
|
||||
@opindex auto-compress
|
||||
@item --auto-compress
|
||||
@itemx -a
|
||||
Select a compression program to use by the archive file name
|
||||
suffix. The following suffixes are recognized:
|
||||
|
||||
@multitable @columnfractions 0.3 0.6
|
||||
@headitem Suffix @tab Compression program
|
||||
@item @samp{.gz} @tab @command{gzip}
|
||||
@item @samp{.tgz} @tab @command{gzip}
|
||||
@item @samp{.taz} @tab @command{gzip}
|
||||
@item @samp{.Z} @tab @command{compress}
|
||||
@item @samp{.taZ} @tab @command{compress}
|
||||
@item @samp{.bz2} @tab @command{bzip2}
|
||||
@item @samp{.tz2} @tab @command{bzip2}
|
||||
@item @samp{.tbz2} @tab @command{bzip2}
|
||||
@item @samp{.tbz} @tab @command{bzip2}
|
||||
@item @samp{.lzma} @tab @command{lzma}
|
||||
@item @samp{.tlz} @tab @command{lzma}
|
||||
@end multitable
|
||||
|
||||
@opindex gzip
|
||||
@opindex ungzip
|
||||
@item -z
|
||||
@@ -8047,6 +8394,10 @@ So, there are pros and cons. We'll see!
|
||||
@itemx --bzip2
|
||||
Filter the archive through @code{bzip2}. Otherwise like @option{--gzip}.
|
||||
|
||||
@opindex lzma
|
||||
@item --lzma
|
||||
Filter the archive through @command{lzma}. Otherwise like @option{--gzip}.
|
||||
|
||||
@opindex compress
|
||||
@opindex uncompress
|
||||
@item -Z
|
||||
@@ -8054,11 +8405,6 @@ Filter the archive through @code{bzip2}. Otherwise like @option{--gzip}.
|
||||
@itemx --uncompress
|
||||
Filter the archive through @command{compress}. Otherwise like @option{--gzip}.
|
||||
|
||||
The @acronym{GNU} Project recommends you not use
|
||||
@command{compress}, because there is a patent covering the algorithm it
|
||||
uses. You could be sued for patent infringement merely by running
|
||||
@command{compress}.
|
||||
|
||||
@opindex use-compress-program
|
||||
@item --use-compress-program=@var{prog}
|
||||
Use external compression program @var{prog}. Use this option if you
|
||||
@@ -8408,6 +8754,7 @@ archives and archive labels) in GNU and PAX formats.}
|
||||
@menu
|
||||
* Portable Names:: Portable Names
|
||||
* dereference:: Symbolic Links
|
||||
* hard links:: Hard Links
|
||||
* old:: Old V7 Archives
|
||||
* ustar:: Ustar Archives
|
||||
* gnu:: GNU and old GNU format archives.
|
||||
@@ -8465,6 +8812,100 @@ and use @option{--dereference} (@option{-h}): many systems do not support
|
||||
symbolic links, and moreover, your distribution might be unusable if
|
||||
it contains unresolved symbolic links.
|
||||
|
||||
@node hard links
|
||||
@subsection Hard Links
|
||||
@UNREVISED{}
|
||||
@cindex File names, using hard links
|
||||
@cindex hard links, dereferencing
|
||||
@cindex dereferencing hard links
|
||||
|
||||
Normally, when @command{tar} archives a hard link, it writes a
|
||||
block to the archive naming the target of the link (a @samp{1} type
|
||||
block). In that way, the actual file contents is stored in file only
|
||||
once. For example, consider the following two files:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
$ ls
|
||||
-rw-r--r-- 2 gray staff 4 2007-10-30 15:11 one
|
||||
-rw-r--r-- 2 gray staff 4 2007-10-30 15:11 jeden
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
Here, @file{jeden} is a link to @file{one}. When archiving this
|
||||
directory with a verbose level 2, you will get an output similar to
|
||||
the following:
|
||||
|
||||
@smallexample
|
||||
$ tar cfvv ../archive.tar .
|
||||
drwxr-xr-x gray/staff 0 2007-10-30 15:13 ./
|
||||
-rw-r--r-- gray/staff 4 2007-10-30 15:11 ./jeden
|
||||
hrw-r--r-- gray/staff 0 2007-10-30 15:11 ./one link to ./jeden
|
||||
@end smallexample
|
||||
|
||||
The last line shows that, instead of storing two copies of the file,
|
||||
@command{tar} stored it only once, under the name @file{jeden}, and
|
||||
stored file @file{one} as a hard link to this file.
|
||||
|
||||
It may be important to know that all hard links to the given file are
|
||||
stored in the archive. For example, this may be necessary for exact
|
||||
reproduction of the file system. The following option does that:
|
||||
|
||||
@table @option
|
||||
@xopindex{check-links, described}
|
||||
@item --check-links
|
||||
@itemx -l
|
||||
Check the number of links dumped for each processed file. If this
|
||||
number does not match the total number of hard links for the file, print
|
||||
a warning message.
|
||||
@end table
|
||||
|
||||
For example, trying to archive only file @file{jeden} with this option
|
||||
produces the following diagnostics:
|
||||
|
||||
@smallexample
|
||||
$ tar -c -f ../archive.tar jeden
|
||||
tar: Missing links to `jeden'.
|
||||
@end smallexample
|
||||
|
||||
Although creating special records for hard links helps keep a faithful
|
||||
record of the file system contents and makes archives more compact, it
|
||||
may present some difficulties when extracting individual members from
|
||||
the archive. For example, trying to extract file @file{one} from the
|
||||
archive created in previous examples produces, in the absense of file
|
||||
@file{jeden}:
|
||||
|
||||
@smallexample
|
||||
$ tar xf archive.tar ./one
|
||||
tar: ./one: Cannot hard link to `./jeden': No such file or directory
|
||||
tar: Error exit delayed from previous errors
|
||||
@end smallexample
|
||||
|
||||
The reason for this behavior is that @command{tar} cannot seek back in
|
||||
the archive to the previous member (in this case, @file{one}), to
|
||||
extract it@footnote{There are plans to fix this in future releases.}.
|
||||
If you wish to avoid such problems at the cost of a bigger archive,
|
||||
use the following option:
|
||||
|
||||
@table @option
|
||||
@xopindex{hard-dereference, described}
|
||||
@item --hard-dereference
|
||||
Dereference hard links and store the files they refer to.
|
||||
@end table
|
||||
|
||||
For example, trying this option on our two sample files, we get two
|
||||
copies in the archive, each of which can then be extracted
|
||||
independently of the other:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
$ tar -c -vv -f ../archive.tar --hard-dereference .
|
||||
drwxr-xr-x gray/staff 0 2007-10-30 15:13 ./
|
||||
-rw-r--r-- gray/staff 4 2007-10-30 15:11 ./jeden
|
||||
-rw-r--r-- gray/staff 4 2007-10-30 15:11 ./one
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@node old
|
||||
@subsection Old V7 Archives
|
||||
@cindex Format, old style
|
||||
@@ -8591,7 +9032,7 @@ from @var{string} after making the following substitutions:
|
||||
result of the @command{dirname} utility on the translated file name.
|
||||
@item %f @tab The name of the file with the directory information
|
||||
stripped, equivalent to the result of the @command{basename} utility
|
||||
on the translated file name.
|
||||
on the translated file name.
|
||||
@item %p @tab The process @acronym{ID} of the @command{tar} process.
|
||||
@item %% @tab A @samp{%} character.
|
||||
@end multitable
|
||||
@@ -10254,13 +10695,17 @@ environment variables:
|
||||
@item TAR_ARCHIVE
|
||||
The name of the archive @command{tar} is processing.
|
||||
|
||||
@vrindex TAR_BLOCKING_FACTOR, info script environment variable
|
||||
@item TAR_BLOCKING_FACTOR
|
||||
Current blocking factor (@pxref{Blocking}.
|
||||
|
||||
@vrindex TAR_VOLUME, info script environment variable
|
||||
@item TAR_VOLUME
|
||||
Ordinal number of the volume @command{tar} is about to start.
|
||||
|
||||
@vrindex TAR_SUBCOMMAND, info script environment variable
|
||||
@item TAR_SUBCOMMAND
|
||||
Short option describing the operation @command{tar} is executing
|
||||
A short option describing the operation @command{tar} is executing
|
||||
@xref{Operations}, for a complete list of subcommand options.
|
||||
|
||||
@vrindex TAR_FORMAT, info script environment variable
|
||||
@@ -10315,7 +10760,7 @@ name=`expr $TAR_ARCHIVE : '\(.*\)-.*'`
|
||||
case $TAR_SUBCOMMAND in
|
||||
-c) ;;
|
||||
-d|-x|-t) test -r $@{name:-$TAR_ARCHIVE@}-$TAR_VOLUME || exit 1
|
||||
;;
|
||||
;;
|
||||
*) exit 1
|
||||
esac
|
||||
|
||||
|
||||
13
doc/untabify.el
Normal file
13
doc/untabify.el
Normal file
@@ -0,0 +1,13 @@
|
||||
;;;; Untabify the sources.
|
||||
;;;; Usage: emacs -batch -l untabify.el [file ...]
|
||||
|
||||
(defun global-untabify (buflist)
|
||||
(mapcar
|
||||
(lambda (bufname)
|
||||
(set-buffer (find-file bufname))
|
||||
(untabify (point-min) (point-max))
|
||||
(save-buffer)
|
||||
(kill-buffer (current-buffer)))
|
||||
buflist))
|
||||
|
||||
(global-untabify command-line-args-left)
|
||||
@@ -13,6 +13,7 @@ exclude
|
||||
exitfail
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
fseeko
|
||||
ftruncate
|
||||
full-write
|
||||
getdate
|
||||
@@ -38,6 +39,7 @@ safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
setenv
|
||||
snprintf
|
||||
stat-time
|
||||
stdbool
|
||||
stdint
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
.cvsignore
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
__fpending.c
|
||||
__fpending.h
|
||||
alloca.c
|
||||
alloca_.h
|
||||
allocsa.c
|
||||
allocsa.h
|
||||
allocsa.valgrind
|
||||
alloca.h
|
||||
alloca.in.h
|
||||
argmatch.c
|
||||
argmatch.h
|
||||
argp-ba.c
|
||||
@@ -30,6 +27,7 @@ backupfile.h
|
||||
basename.c
|
||||
canonicalize-lgpl.c
|
||||
canonicalize.h
|
||||
charset.alias
|
||||
chdir-long.c
|
||||
chdir-long.h
|
||||
chown.c
|
||||
@@ -38,8 +36,10 @@ close-stream.h
|
||||
closeout.c
|
||||
closeout.h
|
||||
config.charset
|
||||
configmake.h
|
||||
creat-safer.c
|
||||
dirent_.h
|
||||
dirent.h
|
||||
dirent.in.h
|
||||
dirfd.c
|
||||
dirfd.h
|
||||
dirname.c
|
||||
@@ -58,29 +58,36 @@ fchown-stub.c
|
||||
fchownat.c
|
||||
fcntl--.h
|
||||
fcntl-safer.h
|
||||
fcntl_.h
|
||||
fcntl.h
|
||||
fcntl.in.h
|
||||
fd-safer.c
|
||||
fileblocks.c
|
||||
float+.h
|
||||
float_.h
|
||||
float.h
|
||||
float.in.h
|
||||
fnmatch.c
|
||||
fnmatch_.h
|
||||
fnmatch.h
|
||||
fnmatch.in.h
|
||||
fnmatch_loop.c
|
||||
fpending.c
|
||||
fpending.h
|
||||
fseeko.c
|
||||
fstatat.c
|
||||
ftruncate.c
|
||||
full-write.c
|
||||
full-write.h
|
||||
getcwd.c
|
||||
getdate.c
|
||||
getdate.h
|
||||
getdate.y
|
||||
getdelim.c
|
||||
getdelim.h
|
||||
getline.c
|
||||
getline.h
|
||||
getopt.c
|
||||
getopt.h
|
||||
getopt.in.h
|
||||
getopt1.c
|
||||
getopt_.h
|
||||
getopt_int.h
|
||||
getpagesize.c
|
||||
getpagesize.h
|
||||
gettext.h
|
||||
gettime.c
|
||||
@@ -94,11 +101,12 @@ imaxtostr.c
|
||||
intprops.h
|
||||
inttostr.c
|
||||
inttostr.h
|
||||
inttypes_.h
|
||||
inttypes.h
|
||||
inttypes.in.h
|
||||
lchown.c
|
||||
lchown.h
|
||||
localcharset.c
|
||||
localcharset.h
|
||||
lseek.c
|
||||
lstat.c
|
||||
lstat.h
|
||||
malloc.c
|
||||
@@ -142,7 +150,10 @@ quote.h
|
||||
quotearg.c
|
||||
quotearg.h
|
||||
readlink.c
|
||||
realloc.c
|
||||
ref-add.sed
|
||||
ref-add.sin
|
||||
ref-del.sed
|
||||
ref-del.sin
|
||||
regcomp.c
|
||||
regex.c
|
||||
@@ -151,6 +162,7 @@ regex_internal.c
|
||||
regex_internal.h
|
||||
regexec.c
|
||||
rmdir.c
|
||||
rmt-command.h
|
||||
rmt.h
|
||||
rpmatch.c
|
||||
rtapelib.c
|
||||
@@ -166,18 +178,26 @@ savedir.h
|
||||
setenv.c
|
||||
setenv.h
|
||||
sleep.c
|
||||
snprintf.c
|
||||
stat-macros.h
|
||||
stat-time.h
|
||||
stdbool_.h
|
||||
stdint_.h
|
||||
stdio_.h
|
||||
stdlib_.h
|
||||
stdbool.h
|
||||
stdbool.in.h
|
||||
stdint.h
|
||||
stdint.in.h
|
||||
stdio.h
|
||||
stdio.in.h
|
||||
stdlib.h
|
||||
stdlib.in.h
|
||||
stpcpy.c
|
||||
strcasecmp.c
|
||||
strchrnul.c
|
||||
strdup.c
|
||||
streq.h
|
||||
strerror.c
|
||||
string_.h
|
||||
string.h
|
||||
string.in.h
|
||||
strings.in.h
|
||||
stripslash.c
|
||||
strncasecmp.c
|
||||
strndup.c
|
||||
@@ -190,21 +210,30 @@ strtoll.c
|
||||
strtoul.c
|
||||
strtoull.c
|
||||
strtoumax.c
|
||||
sys_stat_.h
|
||||
sys_time_.h
|
||||
sysexits_.h
|
||||
sys
|
||||
sys_stat.h
|
||||
sys_stat.in.h
|
||||
sys_time.h
|
||||
sys_time.in.h
|
||||
sysexits.h
|
||||
sysexits.in.h
|
||||
system-ioctl.h
|
||||
system.h
|
||||
tempname.c
|
||||
tempname.h
|
||||
time_.h
|
||||
time.h
|
||||
time.in.h
|
||||
time_r.c
|
||||
timespec.h
|
||||
uinttostr.c
|
||||
umaxtostr.c
|
||||
unistd--.h
|
||||
unistd-safer.h
|
||||
unistd_.h
|
||||
unistd.h
|
||||
unistd.in.h
|
||||
unitypes.h
|
||||
uniwidth
|
||||
uniwidth.h
|
||||
unlinkdir.c
|
||||
unlinkdir.h
|
||||
unlocked-io.h
|
||||
@@ -219,9 +248,11 @@ version-etc-fsf.c
|
||||
version-etc.c
|
||||
version-etc.h
|
||||
vsnprintf.c
|
||||
wchar_.h
|
||||
wctype_.h
|
||||
wcwidth.h
|
||||
wchar.h
|
||||
wchar.in.h
|
||||
wctype.h
|
||||
wctype.in.h
|
||||
wcwidth.c
|
||||
xalloc-die.c
|
||||
xalloc.h
|
||||
xgetcwd.c
|
||||
@@ -230,6 +261,7 @@ xmalloc.c
|
||||
xsize.h
|
||||
xstrndup.c
|
||||
xstrndup.h
|
||||
xstrtol-error.c
|
||||
xstrtol.c
|
||||
xstrtol.h
|
||||
xstrtoul.c
|
||||
|
||||
@@ -22,10 +22,13 @@
|
||||
lib/argmatch.c
|
||||
lib/argp-help.c
|
||||
lib/argp-parse.c
|
||||
lib/closeout.c
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
lib/obstack.c
|
||||
lib/human.c
|
||||
lib/obstack.c
|
||||
lib/openat-die.c
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
@@ -34,6 +37,8 @@ lib/rpmatch.c
|
||||
lib/rtapelib.c
|
||||
lib/xalloc-die.c
|
||||
lib/xmalloc.c
|
||||
lib/version-etc.c
|
||||
lib/xalloc-die.c
|
||||
|
||||
rmt/rmt.c
|
||||
|
||||
@@ -51,6 +56,7 @@ src/names.c
|
||||
src/tar.c
|
||||
src/update.c
|
||||
src/xheader.c
|
||||
src/checkpoint.c
|
||||
|
||||
# Testsuite
|
||||
tests/genfile.c
|
||||
|
||||
@@ -23,6 +23,7 @@ bin_PROGRAMS = tar
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
checkpoint.c\
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
@@ -33,6 +34,7 @@ tar_SOURCES = \
|
||||
misc.c\
|
||||
names.c\
|
||||
sparse.c\
|
||||
suffix.c\
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
|
||||
80
src/buffer.c
80
src/buffer.c
@@ -74,9 +74,6 @@ static int read_error_count;
|
||||
/* Have we hit EOF yet? */
|
||||
static bool hit_eof;
|
||||
|
||||
/* Checkpointing counter */
|
||||
static unsigned checkpoint;
|
||||
|
||||
static bool read_full_records = false;
|
||||
|
||||
/* We're reading, but we just read the last block and it's time to update.
|
||||
@@ -204,7 +201,8 @@ enum compress_type {
|
||||
ct_none,
|
||||
ct_compress,
|
||||
ct_gzip,
|
||||
ct_bzip2
|
||||
ct_bzip2,
|
||||
ct_lzma
|
||||
};
|
||||
|
||||
struct zip_magic
|
||||
@@ -221,6 +219,7 @@ static struct zip_magic const magic[] = {
|
||||
{ ct_compress, 2, "\037\235", "compress", "-Z" },
|
||||
{ ct_gzip, 2, "\037\213", "gzip", "-z" },
|
||||
{ ct_bzip2, 3, "BZh", "bzip2", "-j" },
|
||||
{ ct_lzma, 6, "\xFFLZMA", "lzma", "--lzma" }, /* FIXME: ???? */
|
||||
};
|
||||
|
||||
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
|
||||
@@ -230,19 +229,21 @@ static struct zip_magic const magic[] = {
|
||||
|
||||
/* Check if the file ARCHIVE is a compressed archive. */
|
||||
enum compress_type
|
||||
check_compressed_archive ()
|
||||
check_compressed_archive (bool *pshort)
|
||||
{
|
||||
struct zip_magic const *p;
|
||||
bool sfr;
|
||||
bool short_file = false;
|
||||
bool temp;
|
||||
|
||||
if (!pshort)
|
||||
pshort = &temp;
|
||||
|
||||
/* Prepare global data needed for find_next_block: */
|
||||
record_end = record_start; /* set up for 1st record = # 0 */
|
||||
sfr = read_full_records;
|
||||
read_full_records = true; /* Suppress fatal error on reading a partial
|
||||
record */
|
||||
if (find_next_block () == 0)
|
||||
short_file = true;
|
||||
*pshort = find_next_block () == 0;
|
||||
|
||||
/* Restore global values */
|
||||
read_full_records = sfr;
|
||||
@@ -255,9 +256,6 @@ check_compressed_archive ()
|
||||
if (memcmp (record_start->buffer, p->magic, p->length) == 0)
|
||||
return p->type;
|
||||
|
||||
if (short_file)
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
|
||||
return ct_none;
|
||||
}
|
||||
|
||||
@@ -274,11 +272,16 @@ open_compressed_archive ()
|
||||
|
||||
if (!multi_volume_option)
|
||||
{
|
||||
enum compress_type type = check_compressed_archive ();
|
||||
bool shortfile;
|
||||
enum compress_type type = check_compressed_archive (&shortfile);
|
||||
|
||||
if (type == ct_none)
|
||||
return archive;
|
||||
|
||||
{
|
||||
if (shortfile)
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
return archive;
|
||||
}
|
||||
|
||||
/* FD is not needed any more */
|
||||
rmtclose (archive);
|
||||
|
||||
@@ -503,15 +506,18 @@ _open_archive (enum access_mode wanted_access)
|
||||
{
|
||||
case ACCESS_READ:
|
||||
{
|
||||
bool shortfile;
|
||||
enum compress_type type;
|
||||
|
||||
archive = STDIN_FILENO;
|
||||
|
||||
type = check_compressed_archive ();
|
||||
type = check_compressed_archive (&shortfile);
|
||||
if (type != ct_none)
|
||||
FATAL_ERROR ((0, 0,
|
||||
_("Archive is compressed. Use %s option"),
|
||||
compress_option (type)));
|
||||
if (shortfile)
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -555,7 +561,7 @@ _open_archive (enum access_mode wanted_access)
|
||||
O_RDWR | O_CREAT | O_BINARY,
|
||||
MODE_RW, rsh_command_option);
|
||||
|
||||
if (check_compressed_archive () != ct_none)
|
||||
if (check_compressed_archive (NULL) != ct_none)
|
||||
FATAL_ERROR ((0, 0,
|
||||
_("Cannot update compressed archives")));
|
||||
break;
|
||||
@@ -589,43 +595,13 @@ _open_archive (enum access_mode wanted_access)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_checkpoint (bool do_write)
|
||||
{
|
||||
if (checkpoint_option && !(++checkpoint % checkpoint_option))
|
||||
{
|
||||
switch (checkpoint_style)
|
||||
{
|
||||
case checkpoint_dot:
|
||||
fputc ('.', stdlis);
|
||||
fflush (stdlis);
|
||||
break;
|
||||
|
||||
case checkpoint_text:
|
||||
if (do_write)
|
||||
/* TRANSLATORS: This is a ``checkpoint of write operation'',
|
||||
*not* ``Writing a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
|
||||
*not* ``Escribiendo un punto de comprobaci@'on'' */
|
||||
WARN ((0, 0, _("Write checkpoint %u"), checkpoint));
|
||||
else
|
||||
/* TRANSLATORS: This is a ``checkpoint of read operation'',
|
||||
*not* ``Reading a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
|
||||
*not* ``Leyendo un punto de comprobaci@'on'' */
|
||||
WARN ((0, 0, _("Read checkpoint %u"), checkpoint));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform a write to flush the buffer. */
|
||||
ssize_t
|
||||
_flush_write (void)
|
||||
{
|
||||
ssize_t status;
|
||||
|
||||
do_checkpoint (true);
|
||||
checkpoint_run (true);
|
||||
if (tape_length_option && tape_length_option <= bytes_written)
|
||||
{
|
||||
errno = ENOSPC;
|
||||
@@ -635,7 +611,7 @@ _flush_write (void)
|
||||
status = record_size;
|
||||
else
|
||||
status = sys_write_archive_buffer ();
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -857,7 +833,7 @@ close_archive (void)
|
||||
verify_volume ();
|
||||
|
||||
if (rmtclose (archive) != 0)
|
||||
close_warn (*archive_name_cursor);
|
||||
close_error (*archive_name_cursor);
|
||||
|
||||
sys_wait_for_child (child_pid);
|
||||
|
||||
@@ -1045,7 +1021,7 @@ new_volume (enum access_mode mode)
|
||||
current_block = record_start;
|
||||
|
||||
if (rmtclose (archive) != 0)
|
||||
close_warn (*archive_name_cursor);
|
||||
close_error (*archive_name_cursor);
|
||||
|
||||
archive_name_cursor++;
|
||||
if (archive_name_cursor == archive_name_array + archive_names)
|
||||
@@ -1464,7 +1440,7 @@ simple_flush_read (void)
|
||||
{
|
||||
size_t status; /* result from system call */
|
||||
|
||||
do_checkpoint (false);
|
||||
checkpoint_run (false);
|
||||
|
||||
/* Clear the count of errors. This only applies to a single call to
|
||||
flush_read. */
|
||||
@@ -1523,7 +1499,7 @@ _gnu_flush_read (void)
|
||||
{
|
||||
size_t status; /* result from system call */
|
||||
|
||||
do_checkpoint (false);
|
||||
checkpoint_run (false);
|
||||
|
||||
/* Clear the count of errors. This only applies to a single call to
|
||||
flush_read. */
|
||||
|
||||
270
src/checkpoint.c
Normal file
270
src/checkpoint.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/* Checkpoint management for tar.
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
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, 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/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
|
||||
enum checkpoint_opcode
|
||||
{
|
||||
cop_dot,
|
||||
cop_bell,
|
||||
cop_echo,
|
||||
cop_ttyout,
|
||||
cop_sleep,
|
||||
cop_exec
|
||||
};
|
||||
|
||||
struct checkpoint_action
|
||||
{
|
||||
struct checkpoint_action *next;
|
||||
enum checkpoint_opcode opcode;
|
||||
union
|
||||
{
|
||||
time_t time;
|
||||
char *command;
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Checkpointing counter */
|
||||
static unsigned checkpoint;
|
||||
|
||||
/* List of checkpoint actions */
|
||||
static struct checkpoint_action *checkpoint_action, *checkpoint_action_tail;
|
||||
|
||||
static struct checkpoint_action *
|
||||
alloc_action (enum checkpoint_opcode opcode)
|
||||
{
|
||||
struct checkpoint_action *p = xzalloc (sizeof *p);
|
||||
if (checkpoint_action_tail)
|
||||
checkpoint_action_tail->next = p;
|
||||
else
|
||||
checkpoint_action = p;
|
||||
checkpoint_action_tail = p;
|
||||
p->opcode = opcode;
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *
|
||||
copy_string_unquote (const char *str)
|
||||
{
|
||||
char *output = xstrdup (str);
|
||||
size_t len = strlen (output);
|
||||
if ((*output == '"' || *output == '\'')
|
||||
&& output[len-1] == *output)
|
||||
{
|
||||
memmove (output, output+1, len-2);
|
||||
output[len-2] = 0;
|
||||
}
|
||||
unquote_string (output);
|
||||
return output;
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_compile_action (const char *str)
|
||||
{
|
||||
struct checkpoint_action *act;
|
||||
|
||||
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
|
||||
alloc_action (cop_dot);
|
||||
if (strcmp (str, "bell") == 0)
|
||||
alloc_action (cop_bell);
|
||||
else if (strcmp (str, "echo") == 0)
|
||||
alloc_action (cop_echo);
|
||||
else if (strncmp (str, "echo=", 5) == 0)
|
||||
{
|
||||
act = alloc_action (cop_echo);
|
||||
act->v.command = copy_string_unquote (str + 5);
|
||||
}
|
||||
else if (strncmp (str, "exec=", 5) == 0)
|
||||
{
|
||||
act = alloc_action (cop_exec);
|
||||
act->v.command = copy_string_unquote (str + 5);
|
||||
}
|
||||
else if (strncmp (str, "ttyout=", 7) == 0)
|
||||
{
|
||||
act = alloc_action (cop_ttyout);
|
||||
act->v.command = copy_string_unquote (str + 7);
|
||||
}
|
||||
else if (strncmp (str, "sleep=", 6) == 0)
|
||||
{
|
||||
char *p;
|
||||
time_t n = strtoul (str+6, &p, 10);
|
||||
if (*p)
|
||||
FATAL_ERROR ((0, 0, _("%s: not a valid timeout"), str));
|
||||
act = alloc_action (cop_sleep);
|
||||
act->v.time = n;
|
||||
}
|
||||
else
|
||||
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_finish_compile ()
|
||||
{
|
||||
if (checkpoint_option)
|
||||
{
|
||||
if (!checkpoint_action)
|
||||
/* Provide a historical default */
|
||||
checkpoint_compile_action ("echo");
|
||||
}
|
||||
else if (checkpoint_action)
|
||||
/* Otherwise, set default checkpoint rate */
|
||||
checkpoint_option = DEFAULT_CHECKPOINT;
|
||||
}
|
||||
|
||||
char *
|
||||
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
|
||||
{
|
||||
const char *opstr = do_write ? gettext ("write") : gettext ("read");
|
||||
size_t opstrlen = strlen (opstr);
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
|
||||
size_t cpslen = strlen (cps);
|
||||
const char *ip;
|
||||
char *op;
|
||||
char *output;
|
||||
size_t outlen = strlen (input); /* Initial guess */
|
||||
|
||||
/* Fix the initial length guess */
|
||||
for (ip = input; (ip = strchr (ip, '%')) != NULL; )
|
||||
{
|
||||
switch (ip[1])
|
||||
{
|
||||
case 'u':
|
||||
outlen += cpslen - 2;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
outlen += opstrlen - 2;
|
||||
}
|
||||
ip++;
|
||||
}
|
||||
|
||||
output = xmalloc (outlen + 1);
|
||||
for (ip = input, op = output; *ip; )
|
||||
{
|
||||
if (*ip == '%')
|
||||
{
|
||||
switch (*++ip)
|
||||
{
|
||||
case 'u':
|
||||
op = stpcpy (op, cps);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
op = stpcpy (op, opstr);
|
||||
break;
|
||||
|
||||
default:
|
||||
*op++ = '%';
|
||||
*op++ = *ip;
|
||||
break;
|
||||
}
|
||||
ip++;
|
||||
}
|
||||
else
|
||||
*op++ = *ip++;
|
||||
}
|
||||
*op = 0;
|
||||
return output;
|
||||
}
|
||||
|
||||
static void
|
||||
run_checkpoint_actions (bool do_write)
|
||||
{
|
||||
struct checkpoint_action *p;
|
||||
FILE *tty = NULL;
|
||||
|
||||
for (p = checkpoint_action; p; p = p->next)
|
||||
{
|
||||
switch (p->opcode)
|
||||
{
|
||||
case cop_dot:
|
||||
fputc ('.', stdlis);
|
||||
fflush (stdlis);
|
||||
break;
|
||||
|
||||
case cop_bell:
|
||||
if (!tty)
|
||||
tty = fopen ("/dev/tty", "w");
|
||||
if (tty)
|
||||
{
|
||||
fputc ('\a', tty);
|
||||
fflush (tty);
|
||||
}
|
||||
break;
|
||||
|
||||
case cop_echo:
|
||||
{
|
||||
char *tmp;
|
||||
const char *str = p->v.command;
|
||||
if (!str)
|
||||
{
|
||||
if (do_write)
|
||||
/* TRANSLATORS: This is a ``checkpoint of write operation'',
|
||||
*not* ``Writing a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
|
||||
*not* ``Escribiendo un punto de comprobaci@'on'' */
|
||||
str = gettext ("Write checkpoint %u");
|
||||
else
|
||||
/* TRANSLATORS: This is a ``checkpoint of read operation'',
|
||||
*not* ``Reading a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
|
||||
*not* ``Leyendo un punto de comprobaci@'on'' */
|
||||
str = gettext ("Read checkpoint %u");
|
||||
}
|
||||
tmp = expand_checkpoint_string (str, do_write, checkpoint);
|
||||
WARN ((0, 0, "%s", tmp));
|
||||
free (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case cop_ttyout:
|
||||
if (!tty)
|
||||
tty = fopen ("/dev/tty", "w");
|
||||
if (tty)
|
||||
{
|
||||
char *tmp = expand_checkpoint_string (p->v.command, do_write,
|
||||
checkpoint);
|
||||
fprintf (tty, "%s", tmp);
|
||||
fflush (tty);
|
||||
free (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case cop_sleep:
|
||||
sleep (p->v.time);
|
||||
break;
|
||||
|
||||
case cop_exec:
|
||||
sys_exec_checkpoint_script (p->v.command,
|
||||
archive_name_cursor[0],
|
||||
checkpoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tty)
|
||||
fclose (tty);
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_run (bool do_write)
|
||||
{
|
||||
if (checkpoint_option && !(++checkpoint % checkpoint_option))
|
||||
run_checkpoint_actions (do_write);
|
||||
}
|
||||
|
||||
37
src/common.h
37
src/common.h
@@ -1,7 +1,7 @@
|
||||
/* Common declarations for the tar program.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
@@ -130,19 +130,13 @@ GLOBAL enum backup_type backup_type;
|
||||
GLOBAL bool block_number_option;
|
||||
|
||||
GLOBAL unsigned checkpoint_option;
|
||||
|
||||
enum checkpoint_style
|
||||
{
|
||||
checkpoint_text,
|
||||
checkpoint_dot
|
||||
};
|
||||
|
||||
GLOBAL enum checkpoint_style checkpoint_style;
|
||||
#define DEFAULT_CHECKPOINT 10
|
||||
|
||||
/* Specified name of compression program, or "gzip" as implied by -z. */
|
||||
GLOBAL const char *use_compress_program_option;
|
||||
|
||||
GLOBAL bool dereference_option;
|
||||
GLOBAL bool hard_dereference_option;
|
||||
|
||||
/* Print a message if not all links are dumped */
|
||||
GLOBAL int check_links_option;
|
||||
@@ -194,6 +188,8 @@ GLOBAL enum old_files old_files_option;
|
||||
|
||||
/* Specified file name for incremental list. */
|
||||
GLOBAL const char *listed_incremental_option;
|
||||
/* Check device numbers when doing incremental dumps. */
|
||||
GLOBAL bool check_device_option;
|
||||
|
||||
/* Specified mode change string. */
|
||||
GLOBAL struct mode_change *mode_option;
|
||||
@@ -493,8 +489,18 @@ bool rename_directory (char *src, char *dst);
|
||||
void delete_archive_members (void);
|
||||
|
||||
/* Module incremen.c. */
|
||||
typedef struct dumpdir *dumpdir_t;
|
||||
typedef struct dumpdir_iter *dumpdir_iter_t;
|
||||
|
||||
char *get_directory_contents (char *dir_name, dev_t device);
|
||||
dumpdir_t dumpdir_create0 (const char *contents, const char *cmask);
|
||||
dumpdir_t dumpdir_create (const char *contents);
|
||||
void dumpdir_free (dumpdir_t);
|
||||
char *dumpdir_locate (dumpdir_t dump, const char *name);
|
||||
char *dumpdir_next (dumpdir_iter_t itr);
|
||||
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
|
||||
|
||||
|
||||
const char *get_directory_contents (char *dir_name, dev_t device);
|
||||
const char *append_incremental_renames (const char *dump);
|
||||
void read_directory_file (void);
|
||||
void write_directory_file (void);
|
||||
@@ -711,6 +717,9 @@ bool sys_get_archive_stat (void);
|
||||
int sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st);
|
||||
void sys_wait_command (void);
|
||||
int sys_exec_info_script (const char **archive_name, int volume_number);
|
||||
void sys_exec_checkpoint_script (const char *script_name,
|
||||
const char *archive_name,
|
||||
int checkpoint_number);
|
||||
|
||||
/* Module compare.c */
|
||||
void report_difference (struct tar_stat_info *st, const char *message, ...);
|
||||
@@ -740,3 +749,11 @@ void set_transform_expr (const char *expr);
|
||||
bool transform_name (char **pinput);
|
||||
bool transform_member_name (char **pinput, xform_type type);
|
||||
bool transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *);
|
||||
|
||||
/* Module suffix.c */
|
||||
void set_comression_program_by_suffix (const char *name, const char *defprog);
|
||||
|
||||
/* Module checkpoint.c */
|
||||
void checkpoint_compile_action (const char *str);
|
||||
void checkpoint_finish_compile (void);
|
||||
void checkpoint_run (bool do_write);
|
||||
|
||||
@@ -366,7 +366,7 @@ dumpdir_cmp (const char *a, const char *b)
|
||||
static void
|
||||
diff_dumpdir (void)
|
||||
{
|
||||
char *dumpdir_buffer;
|
||||
const char *dumpdir_buffer;
|
||||
dev_t dev = 0;
|
||||
struct stat stat_data;
|
||||
|
||||
@@ -597,9 +597,23 @@ verify_volume (void)
|
||||
"VERIFY FAILURE: %d invalid headers detected",
|
||||
counter), counter));
|
||||
}
|
||||
if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE)
|
||||
if (status == HEADER_END_OF_FILE)
|
||||
break;
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
if (!ignore_zeros_option)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
}
|
||||
}
|
||||
|
||||
diff_archive ();
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
}
|
||||
|
||||
@@ -1422,6 +1422,8 @@ dump_hard_link (struct tar_stat_info *st)
|
||||
static void
|
||||
file_count_links (struct tar_stat_info *st)
|
||||
{
|
||||
if (hard_dereference_option)
|
||||
return;
|
||||
if (st->stat.st_nlink > 1)
|
||||
{
|
||||
struct link *duplicate;
|
||||
@@ -1614,6 +1616,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
case dump_status_ok:
|
||||
case dump_status_short:
|
||||
mv_end ();
|
||||
file_count_links (st);
|
||||
break;
|
||||
|
||||
case dump_status_fail:
|
||||
@@ -1623,8 +1626,6 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
abort ();
|
||||
}
|
||||
|
||||
file_count_links (st);
|
||||
|
||||
ok = status == dump_status_ok;
|
||||
}
|
||||
|
||||
@@ -1704,6 +1705,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
}
|
||||
buffer[size] = '\0';
|
||||
assign_string (&st->link_name, buffer);
|
||||
transform_name (&st->link_name);
|
||||
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
|
||||
write_long_link (st);
|
||||
|
||||
@@ -1712,7 +1714,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
header = start_header (st);
|
||||
if (!header)
|
||||
return;
|
||||
tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
|
||||
tar_copy_str (header->header.linkname, st->link_name, NAME_FIELD_SIZE);
|
||||
header->header.typeflag = SYMTYPE;
|
||||
finish_header (st, header, block_ordinal);
|
||||
/* nothing more to do to it */
|
||||
|
||||
278
src/incremen.c
278
src/incremen.c
@@ -1,7 +1,7 @@
|
||||
/* GNU dump extensions to tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
@@ -49,14 +49,22 @@ enum children
|
||||
#define DIR_SET_FLAG(d,f) (d)->flags |= (f)
|
||||
#define DIR_CLEAR_FLAG(d,f) (d)->flags &= ~(f)
|
||||
|
||||
struct dumpdir /* Dump directory listing */
|
||||
{
|
||||
char *contents; /* Actual contents */
|
||||
size_t total; /* Total number of elements */
|
||||
size_t elc; /* Number of D/N/Y elements. */
|
||||
char **elv; /* Array of D/N/Y elements */
|
||||
};
|
||||
|
||||
/* Directory attributes. */
|
||||
struct directory
|
||||
{
|
||||
struct timespec mtime; /* Modification time */
|
||||
dev_t device_number; /* device number for directory */
|
||||
ino_t inode_number; /* inode number for directory */
|
||||
char *contents; /* Directory contents */
|
||||
char *icontents; /* Initial contents if the directory was
|
||||
struct dumpdir *dump; /* Directory contents */
|
||||
struct dumpdir *idump; /* Initial contents if the directory was
|
||||
rescanned */
|
||||
enum children children; /* What to save under this directory */
|
||||
unsigned flags; /* See DIRF_ macros above */
|
||||
@@ -67,6 +75,127 @@ struct directory
|
||||
char name[1]; /* file name of directory */
|
||||
};
|
||||
|
||||
struct dumpdir *
|
||||
dumpdir_create0 (const char *contents, const char *cmask)
|
||||
{
|
||||
struct dumpdir *dump;
|
||||
size_t i, total, ctsize, len;
|
||||
const char *p;
|
||||
|
||||
for (i = 0, total = 0, ctsize = 1, p = contents; *p; total++, p += len)
|
||||
{
|
||||
len = strlen (p) + 1;
|
||||
ctsize += len;
|
||||
if (!cmask || strchr (cmask, *p))
|
||||
i++;
|
||||
}
|
||||
dump = xmalloc (sizeof (*dump) + ctsize);
|
||||
dump->contents = (char*)(dump + 1);
|
||||
memcpy (dump->contents, contents, ctsize);
|
||||
dump->total = total;
|
||||
dump->elc = i;
|
||||
dump->elv = xcalloc (i + 1, sizeof (dump->elv[0]));
|
||||
|
||||
for (i = 0, p = dump->contents; *p; p += strlen (p) + 1)
|
||||
{
|
||||
if (!cmask || strchr (cmask, *p))
|
||||
dump->elv[i++] = p + 1;
|
||||
}
|
||||
dump->elv[i] = NULL;
|
||||
return dump;
|
||||
}
|
||||
|
||||
struct dumpdir *
|
||||
dumpdir_create (const char *contents)
|
||||
{
|
||||
return dumpdir_create0 (contents, "YND");
|
||||
}
|
||||
|
||||
void
|
||||
dumpdir_free (struct dumpdir *dump)
|
||||
{
|
||||
free (dump->elv);
|
||||
free (dump);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_dirnames (const void *first, const void *second)
|
||||
{
|
||||
char const *const *name1 = first;
|
||||
char const *const *name2 = second;
|
||||
return strcmp (*name1, *name2);
|
||||
}
|
||||
|
||||
/* Locate NAME in the dumpdir array DUMP.
|
||||
Return pointer to the slot in DUMP->contents, or NULL if not found */
|
||||
char *
|
||||
dumpdir_locate (struct dumpdir *dump, const char *name)
|
||||
{
|
||||
char **ptr;
|
||||
if (!dump)
|
||||
return NULL;
|
||||
|
||||
ptr = bsearch (&name, dump->elv, dump->elc, sizeof (dump->elv[0]),
|
||||
compare_dirnames);
|
||||
return ptr ? *ptr - 1: NULL;
|
||||
}
|
||||
|
||||
struct dumpdir_iter
|
||||
{
|
||||
struct dumpdir *dump; /* Dumpdir being iterated */
|
||||
int all; /* Iterate over all entries, not only D/N/Y */
|
||||
size_t next; /* Index of the next element */
|
||||
};
|
||||
|
||||
char *
|
||||
dumpdir_next (struct dumpdir_iter *itr)
|
||||
{
|
||||
size_t cur = itr->next;
|
||||
char *ret = NULL;
|
||||
|
||||
if (itr->all)
|
||||
{
|
||||
ret = itr->dump->contents + cur;
|
||||
if (*ret == 0)
|
||||
return NULL;
|
||||
itr->next += strlen (ret) + 1;
|
||||
}
|
||||
else if (cur < itr->dump->elc)
|
||||
{
|
||||
ret = itr->dump->elv[cur] - 1;
|
||||
itr->next++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
dumpdir_first (struct dumpdir *dump, int all, struct dumpdir_iter **pitr)
|
||||
{
|
||||
struct dumpdir_iter *itr = xmalloc (sizeof (*itr));
|
||||
itr->dump = dump;
|
||||
itr->all = all;
|
||||
itr->next = 0;
|
||||
*pitr = itr;
|
||||
return dumpdir_next (itr);
|
||||
}
|
||||
|
||||
/* Return size in bytes of the dumpdir array P */
|
||||
size_t
|
||||
dumpdir_size (const char *p)
|
||||
{
|
||||
size_t totsize = 0;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
size_t size = strlen (p) + 1;
|
||||
totsize += size;
|
||||
p += size;
|
||||
}
|
||||
return totsize + 1;
|
||||
}
|
||||
|
||||
|
||||
static Hash_table *directory_table;
|
||||
static Hash_table *directory_meta_table;
|
||||
|
||||
@@ -120,12 +249,12 @@ make_directory (const char *name)
|
||||
size_t namelen = strlen (name);
|
||||
size_t size = offsetof (struct directory, name) + namelen + 1;
|
||||
struct directory *directory = xmalloc (size);
|
||||
directory->contents = directory->icontents = NULL;
|
||||
directory->dump = directory->idump = NULL;
|
||||
directory->orig = NULL;
|
||||
directory->flags = false;
|
||||
strcpy (directory->name, name);
|
||||
if (ISSLASH (directory->name[namelen-1]))
|
||||
directory->name[namelen-1] = 0;
|
||||
if (namelen && ISSLASH (directory->name[namelen - 1]))
|
||||
directory->name[namelen - 1] = 0;
|
||||
directory->tagfile = NULL;
|
||||
return directory;
|
||||
}
|
||||
@@ -136,7 +265,8 @@ make_directory (const char *name)
|
||||
found that the directory exists. */
|
||||
static struct directory *
|
||||
note_directory (char const *name, struct timespec mtime,
|
||||
dev_t dev, ino_t ino, bool nfs, bool found, char *contents)
|
||||
dev_t dev, ino_t ino, bool nfs, bool found,
|
||||
const char *contents)
|
||||
{
|
||||
struct directory *directory = make_directory (name);
|
||||
|
||||
@@ -149,13 +279,9 @@ note_directory (char const *name, struct timespec mtime,
|
||||
if (found)
|
||||
DIR_SET_FLAG (directory, DIRF_FOUND);
|
||||
if (contents)
|
||||
{
|
||||
size_t size = dumpdir_size (contents);
|
||||
directory->contents = xmalloc (size);
|
||||
memcpy (directory->contents, contents, size);
|
||||
}
|
||||
directory->dump = dumpdir_create (contents);
|
||||
else
|
||||
directory->contents = NULL;
|
||||
directory->dump = NULL;
|
||||
|
||||
if (! ((directory_table
|
||||
|| (directory_table = hash_initialize (0, 0,
|
||||
@@ -250,7 +376,8 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
directories, consider all NFS devices as equal,
|
||||
relying on the i-node to establish differences. */
|
||||
|
||||
if (! (((DIR_IS_NFS (directory) & nfs)
|
||||
if (! ((!check_device_option
|
||||
|| (DIR_IS_NFS (directory) && nfs)
|
||||
|| directory->device_number == stat_data->st_dev)
|
||||
&& directory->inode_number == stat_data->st_ino))
|
||||
{
|
||||
@@ -336,8 +463,7 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
|
||||
{
|
||||
const char *tag_file_name;
|
||||
size_t len;
|
||||
|
||||
|
||||
switch (check_exclusion_tags (name_buffer, &tag_file_name))
|
||||
{
|
||||
case exclusion_tag_all:
|
||||
@@ -356,13 +482,13 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
_("contents not dumped"));
|
||||
directory->children = NO_CHILDREN;
|
||||
break;
|
||||
|
||||
|
||||
case exclusion_tag_under:
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
directory->tagfile = tag_file_name;
|
||||
break;
|
||||
|
||||
|
||||
case exclusion_tag_none:
|
||||
break;
|
||||
}
|
||||
@@ -371,64 +497,15 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
return directory;
|
||||
}
|
||||
|
||||
/* Locate NAME in the dumpdir array DUMP.
|
||||
Return pointer to the slot in the array, or NULL if not found */
|
||||
const char *
|
||||
dumpdir_locate (const char *dump, const char *name)
|
||||
{
|
||||
if (dump)
|
||||
while (*dump)
|
||||
{
|
||||
/* Ignore 'R' (rename) and 'X' (tempname) entries, since they break
|
||||
alphabetical ordering.
|
||||
They normally do not occur in dumpdirs from the snapshot files,
|
||||
but this function is also used by purge_directory, which operates
|
||||
on a dumpdir from the archive, hence the need for this test. */
|
||||
if (!strchr ("RX", *dump))
|
||||
{
|
||||
int rc = strcmp (dump + 1, name);
|
||||
if (rc == 0)
|
||||
return dump;
|
||||
if (rc > 1)
|
||||
break;
|
||||
}
|
||||
dump += strlen (dump) + 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return size in bytes of the dumpdir array P */
|
||||
size_t
|
||||
dumpdir_size (const char *p)
|
||||
{
|
||||
size_t totsize = 0;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
size_t size = strlen (p) + 1;
|
||||
totsize += size;
|
||||
p += size;
|
||||
}
|
||||
return totsize + 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_dirnames (const void *first, const void *second)
|
||||
{
|
||||
char const *const *name1 = first;
|
||||
char const *const *name2 = second;
|
||||
return strcmp (*name1, *name2);
|
||||
}
|
||||
|
||||
/* Compare dumpdir array from DIRECTORY with directory listing DIR and
|
||||
build a new dumpdir template.
|
||||
|
||||
DIR must be returned by a previous call to savedir().
|
||||
|
||||
File names in DIRECTORY->contents must be sorted
|
||||
File names in DIRECTORY->dump->contents must be sorted
|
||||
alphabetically.
|
||||
|
||||
DIRECTORY->contents is replaced with the created template. Each entry is
|
||||
DIRECTORY->dump is replaced with the created template. Each entry is
|
||||
prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
|
||||
|
||||
void
|
||||
@@ -440,15 +517,15 @@ makedumpdir (struct directory *directory, const char *dir)
|
||||
const char *p;
|
||||
char const **array;
|
||||
char *new_dump, *new_dump_ptr;
|
||||
const char *dump;
|
||||
struct dumpdir *dump;
|
||||
|
||||
if (directory->children == ALL_CHILDREN)
|
||||
dump = NULL;
|
||||
else if (DIR_IS_RENAMED (directory))
|
||||
dump = directory->orig->icontents ?
|
||||
directory->orig->icontents : directory->orig->contents;
|
||||
dump = directory->orig->idump ?
|
||||
directory->orig->idump : directory->orig->dump;
|
||||
else
|
||||
dump = directory->contents;
|
||||
dump = directory->dump;
|
||||
|
||||
/* Count the size of DIR and the number of elements it contains */
|
||||
dirsize = 0;
|
||||
@@ -476,11 +553,10 @@ makedumpdir (struct directory *directory, const char *dir)
|
||||
{
|
||||
if (directory->tagfile)
|
||||
*new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
|
||||
' ' : 'I';
|
||||
' ' : 'I';
|
||||
else
|
||||
*new_dump_ptr = ' ';
|
||||
new_dump_ptr++;
|
||||
dump = loc + strlen (loc) + 1;
|
||||
}
|
||||
else if (directory->tagfile)
|
||||
*new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
|
||||
@@ -493,13 +569,13 @@ makedumpdir (struct directory *directory, const char *dir)
|
||||
;
|
||||
}
|
||||
*new_dump_ptr = 0;
|
||||
directory->icontents = directory->contents;
|
||||
directory->contents = new_dump;
|
||||
directory->idump = directory->dump;
|
||||
directory->dump = dumpdir_create0 (new_dump, NULL);
|
||||
free (array);
|
||||
}
|
||||
|
||||
/* Recursively scan the given directory. */
|
||||
static char *
|
||||
static const char *
|
||||
scan_directory (char *dir, dev_t device)
|
||||
{
|
||||
char *dirp = savedir (dir); /* for scanning directory */
|
||||
@@ -508,7 +584,7 @@ scan_directory (char *dir, dev_t device)
|
||||
size_t name_length; /* used length in name_buffer */
|
||||
struct stat stat_data;
|
||||
struct directory *directory;
|
||||
|
||||
|
||||
if (! dirp)
|
||||
savedir_error (dir);
|
||||
|
||||
@@ -532,18 +608,20 @@ scan_directory (char *dir, dev_t device)
|
||||
|
||||
directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false,
|
||||
NULL);
|
||||
|
||||
|
||||
if (dirp && directory->children != NO_CHILDREN)
|
||||
{
|
||||
char *entry; /* directory entry being scanned */
|
||||
char *entry; /* directory entry being scanned */
|
||||
size_t entrylen; /* length of directory entry */
|
||||
dumpdir_iter_t itr;
|
||||
|
||||
makedumpdir (directory, dirp);
|
||||
|
||||
for (entry = directory->contents;
|
||||
(entrylen = strlen (entry)) != 0;
|
||||
entry += entrylen + 1)
|
||||
for (entry = dumpdir_first (directory->dump, 1, &itr);
|
||||
entry;
|
||||
entry = dumpdir_next (itr))
|
||||
{
|
||||
entrylen = strlen (entry);
|
||||
if (name_buffer_size <= entrylen - 1 + name_length)
|
||||
{
|
||||
do
|
||||
@@ -590,16 +668,17 @@ scan_directory (char *dir, dev_t device)
|
||||
*entry = 'Y';
|
||||
}
|
||||
}
|
||||
free (itr);
|
||||
}
|
||||
|
||||
free (name_buffer);
|
||||
if (dirp)
|
||||
free (dirp);
|
||||
|
||||
return directory->contents;
|
||||
return directory->dump ? directory->dump->contents : NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
const char *
|
||||
get_directory_contents (char *dir, dev_t device)
|
||||
{
|
||||
return scan_directory (dir, device);
|
||||
@@ -1171,14 +1250,16 @@ write_directory_file_entry (void *entry, void *data)
|
||||
fwrite (s, strlen (s) + 1, 1, fp);
|
||||
|
||||
fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
|
||||
if (directory->contents)
|
||||
if (directory->dump)
|
||||
{
|
||||
char *p;
|
||||
for (p = directory->contents; *p; p += strlen (p) + 1)
|
||||
{
|
||||
if (strchr ("YND", *p))
|
||||
fwrite (p, strlen (p) + 1, 1, fp);
|
||||
}
|
||||
const char *p;
|
||||
dumpdir_iter_t itr;
|
||||
|
||||
for (p = dumpdir_first (directory->dump, 0, &itr);
|
||||
p;
|
||||
p = dumpdir_next (itr))
|
||||
fwrite (p, strlen (p) + 1, 1, fp);
|
||||
free (itr);
|
||||
}
|
||||
fwrite ("\0\0", 2, 1, fp);
|
||||
}
|
||||
@@ -1366,6 +1447,7 @@ try_purge_directory (char const *directory_name)
|
||||
char *current_dir;
|
||||
char *cur, *arc, *p;
|
||||
char *temp_stub = NULL;
|
||||
struct dumpdir *dump;
|
||||
|
||||
if (!is_dumpdir (¤t_stat_info))
|
||||
return false;
|
||||
@@ -1417,12 +1499,12 @@ try_purge_directory (char const *directory_name)
|
||||
This is an extra safety precaution. Besides, it might be
|
||||
necessary to extract from archives created with tar versions
|
||||
prior to 1.19. */
|
||||
|
||||
|
||||
if (*src)
|
||||
src = safer_name_suffix (src, false, absolute_names_option);
|
||||
if (*dst)
|
||||
dst = safer_name_suffix (dst, false, absolute_names_option);
|
||||
|
||||
|
||||
if (*src == 0)
|
||||
src = temp_stub;
|
||||
else if (*dst == 0)
|
||||
@@ -1442,6 +1524,7 @@ try_purge_directory (char const *directory_name)
|
||||
free (temp_stub);
|
||||
|
||||
/* Process deletes */
|
||||
dump = dumpdir_create (current_stat_info.dumpdir);
|
||||
p = NULL;
|
||||
for (cur = current_dir; *cur; cur += strlen (cur) + 1)
|
||||
{
|
||||
@@ -1463,7 +1546,7 @@ try_purge_directory (char const *directory_name)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(entry = dumpdir_locate (current_stat_info.dumpdir, cur))
|
||||
if (!(entry = dumpdir_locate (dump, cur))
|
||||
|| (*entry == 'D' && !S_ISDIR (st.st_mode))
|
||||
|| (*entry == 'Y' && S_ISDIR (st.st_mode)))
|
||||
{
|
||||
@@ -1489,7 +1572,8 @@ try_purge_directory (char const *directory_name)
|
||||
}
|
||||
}
|
||||
free (p);
|
||||
|
||||
dumpdir_free (dump);
|
||||
|
||||
free (current_dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -301,8 +301,8 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
size_t size, written;
|
||||
union block *next_long_name = 0;
|
||||
union block *next_long_link = 0;
|
||||
size_t next_long_name_blocks;
|
||||
size_t next_long_link_blocks;
|
||||
size_t next_long_name_blocks = 0;
|
||||
size_t next_long_link_blocks = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
@@ -734,7 +734,7 @@ static void
|
||||
add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
{
|
||||
char *file_name = name->name;
|
||||
char *buffer = get_directory_contents (file_name, device);
|
||||
const char *buffer = get_directory_contents (file_name, device);
|
||||
|
||||
if (! buffer)
|
||||
name->dir_contents = "\0\0\0\0";
|
||||
@@ -746,7 +746,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
: NAME_FIELD_SIZE);
|
||||
char *namebuf = xmalloc (allocated_length + 1);
|
||||
/* FIXME: + 2 above? */
|
||||
char *string;
|
||||
const char *string;
|
||||
size_t string_length;
|
||||
int change_dir = name->change_dir;
|
||||
|
||||
|
||||
78
src/suffix.c
Normal file
78
src/suffix.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by Sergey Poznyakoff.
|
||||
|
||||
GNU tar 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, or (at your option) any later
|
||||
version.
|
||||
|
||||
GNU tar 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 GNU tar. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
|
||||
struct compression_suffix
|
||||
{
|
||||
const char *suffix;
|
||||
size_t length;
|
||||
const char *program;
|
||||
};
|
||||
|
||||
struct compression_suffix compression_suffixes[] = {
|
||||
#define S(s,p) #s, sizeof (#s) - 1, #p
|
||||
{ S(gz, gzip) },
|
||||
{ S(tgz, gzip) },
|
||||
{ S(taz, gzip) },
|
||||
{ S(Z, compress) },
|
||||
{ S(taZ, compress) },
|
||||
{ S(bz2, bzip2) },
|
||||
{ S(tbz, bzip2) },
|
||||
{ S(tbz2, bzip2) },
|
||||
{ S(tz2, bzip2) },
|
||||
{ S(lzma, lzma) },
|
||||
{ S(tlz, lzma) },
|
||||
#undef S
|
||||
};
|
||||
|
||||
int nsuffixes = sizeof (compression_suffixes) /
|
||||
sizeof (compression_suffixes[0]);
|
||||
|
||||
static const char *
|
||||
find_compression_program (const char *name, const char *defprog)
|
||||
{
|
||||
char *suf = strrchr (name, '.');
|
||||
|
||||
if (suf)
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
suf++;
|
||||
len = strlen (suf);
|
||||
|
||||
for (i = 0; i < nsuffixes; i++)
|
||||
{
|
||||
if (compression_suffixes[i].length == len
|
||||
&& memcmp (compression_suffixes[i].suffix, suf, len) == 0)
|
||||
return compression_suffixes[i].program;
|
||||
}
|
||||
}
|
||||
return defprog;
|
||||
}
|
||||
|
||||
void
|
||||
set_comression_program_by_suffix (const char *name, const char *defprog)
|
||||
{
|
||||
const char *program = find_compression_program (name, defprog);
|
||||
if (program)
|
||||
use_compress_program_option = program;
|
||||
}
|
||||
|
||||
59
src/system.c
59
src/system.c
@@ -17,7 +17,6 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <setenv.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <rmt.h>
|
||||
@@ -773,9 +772,10 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
int p[2];
|
||||
|
||||
static RETSIGTYPE (*saved_handler) (int sig);
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
saved_handler = signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
pid = xfork ();
|
||||
|
||||
@@ -785,7 +785,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
|
||||
int rc;
|
||||
int status;
|
||||
char *buf;
|
||||
char *buf = NULL;
|
||||
size_t size = 0;
|
||||
FILE *fp;
|
||||
|
||||
@@ -800,10 +800,13 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
signal (SIGPIPE, saved_handler);
|
||||
waitpid_error (info_script_option);
|
||||
return -1;
|
||||
}
|
||||
|
||||
signal (SIGPIPE, saved_handler);
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
if (WEXITSTATUS (status) == 0 && rc > 0)
|
||||
@@ -821,6 +824,8 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
|
||||
setenv ("TAR_ARCHIVE", *archive_name, 1);
|
||||
setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
|
||||
setenv ("TAR_BLOCKING_FACTOR",
|
||||
STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
|
||||
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
|
||||
setenv ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
@@ -839,5 +844,51 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
exec_fatal (info_script_option);
|
||||
}
|
||||
|
||||
void
|
||||
sys_exec_checkpoint_script (const char *script_name,
|
||||
const char *archive_name,
|
||||
int checkpoint_number)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* Master */
|
||||
|
||||
int status;
|
||||
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (script_name);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Child */
|
||||
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
|
||||
setenv ("TAR_ARCHIVE", archive_name, 1);
|
||||
setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
|
||||
setenv ("TAR_BLOCKING_FACTOR",
|
||||
STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
|
||||
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
|
||||
setenv ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
archive_format : current_format), 1);
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*) script_name;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (script_name);
|
||||
}
|
||||
|
||||
#endif /* not MSDOS */
|
||||
|
||||
102
src/tar.c
102
src/tar.c
@@ -249,8 +249,11 @@ enum
|
||||
ANCHORED_OPTION = CHAR_MAX + 1,
|
||||
ATIME_PRESERVE_OPTION,
|
||||
BACKUP_OPTION,
|
||||
CHECK_DEVICE_OPTION,
|
||||
CHECKPOINT_OPTION,
|
||||
CHECKPOINT_ACTION_OPTION,
|
||||
DELAY_DIRECTORY_RESTORE_OPTION,
|
||||
HARD_DEREFERENCE_OPTION,
|
||||
DELETE_OPTION,
|
||||
EXCLUDE_CACHES_OPTION,
|
||||
EXCLUDE_CACHES_UNDER_OPTION,
|
||||
@@ -268,10 +271,12 @@ enum
|
||||
IGNORE_FAILED_READ_OPTION,
|
||||
INDEX_FILE_OPTION,
|
||||
KEEP_NEWER_FILES_OPTION,
|
||||
LZMA_OPTION,
|
||||
MODE_OPTION,
|
||||
MTIME_OPTION,
|
||||
NEWER_MTIME_OPTION,
|
||||
NO_ANCHORED_OPTION,
|
||||
NO_CHECK_DEVICE_OPTION,
|
||||
NO_DELAY_DIRECTORY_RESTORE_OPTION,
|
||||
NO_IGNORE_CASE_OPTION,
|
||||
NO_IGNORE_COMMAND_ERROR_OPTION,
|
||||
@@ -345,7 +350,7 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n
|
||||
|
||||
/* NOTE:
|
||||
|
||||
Available option letters are DEIJQY and aeqy. Consider the following
|
||||
Available option letters are DEIJQY and eqy. Consider the following
|
||||
assignments:
|
||||
|
||||
[For Solaris tar compatibility =/= Is it important at all?]
|
||||
@@ -408,6 +413,12 @@ static struct argp_option options[] = {
|
||||
" NUMBER defaults to 1"), GRID+1 },
|
||||
{"seek", 'n', NULL, 0,
|
||||
N_("archive is seekable"), GRID+1 },
|
||||
{"no-check-device", NO_CHECK_DEVICE_OPTION, NULL, 0,
|
||||
N_("do not check device numbers when creating incremental archives"),
|
||||
GRID+1 },
|
||||
{"check-device", CHECK_DEVICE_OPTION, NULL, 0,
|
||||
N_("check device numbers when creating incremental archives (default)"),
|
||||
GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 30
|
||||
@@ -574,20 +585,29 @@ static struct argp_option options[] = {
|
||||
N_("control pax keywords"), GRID+8 },
|
||||
{"label", 'V', N_("TEXT"), 0,
|
||||
N_("create archive with volume name TEXT; at list/extract time, use TEXT as a globbing pattern for volume name"), GRID+8 },
|
||||
{"bzip2", 'j', 0, 0,
|
||||
N_("filter the archive through bzip2"), GRID+8 },
|
||||
{"gzip", 'z', 0, 0,
|
||||
N_("filter the archive through gzip"), GRID+8 },
|
||||
{"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
||||
{"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
||||
{"compress", 'Z', 0, 0,
|
||||
N_("filter the archive through compress"), GRID+8 },
|
||||
{"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
||||
{"use-compress-program", USE_COMPRESS_PROGRAM_OPTION, N_("PROG"), 0,
|
||||
N_("filter through PROG (must accept -d)"), GRID+8 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 90
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Compression options:"), GRID },
|
||||
{"auto-compress", 'a', 0, 0,
|
||||
N_("use archive suffix to determine the compression program"), GRID+1 },
|
||||
{"bzip2", 'j', 0, 0,
|
||||
N_("filter the archive through bzip2"), GRID+1 },
|
||||
{"gzip", 'z', 0, 0,
|
||||
N_("filter the archive through gzip"), GRID+1 },
|
||||
{"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
||||
{"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
||||
{"compress", 'Z', 0, 0,
|
||||
N_("filter the archive through compress"), GRID+1 },
|
||||
{"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
||||
{"lzma", LZMA_OPTION, 0, 0,
|
||||
N_("filter the archive through lzma"), GRID+1 },
|
||||
{"use-compress-program", USE_COMPRESS_PROGRAM_OPTION, N_("PROG"), 0,
|
||||
N_("filter through PROG (must accept -d)"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 100
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Local file selection:"), GRID },
|
||||
|
||||
@@ -634,6 +654,8 @@ static struct argp_option options[] = {
|
||||
N_("don't strip leading `/'s from file names"), GRID+1 },
|
||||
{"dereference", 'h', 0, 0,
|
||||
N_("follow symlinks; archive and dump the files they point to"), GRID+1 },
|
||||
{"hard-dereference", HARD_DEREFERENCE_OPTION, 0, 0,
|
||||
N_("follow hard links; archive and dump the files they refer to"), GRID+1 },
|
||||
{"starting-file", 'K', N_("MEMBER-NAME"), 0,
|
||||
N_("begin at member MEMBER-NAME in the archive"), GRID+1 },
|
||||
{"newer", 'N', N_("DATE-OR-FILE"), 0,
|
||||
@@ -647,7 +669,7 @@ static struct argp_option options[] = {
|
||||
N_("backup before removal, override usual suffix ('~' unless overridden by environment variable SIMPLE_BACKUP_SUFFIX)"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 92
|
||||
#define GRID 110
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("File name transformations:"), GRID },
|
||||
{"strip-components", STRIP_COMPONENTS_OPTION, N_("NUMBER"), 0,
|
||||
@@ -657,7 +679,7 @@ static struct argp_option options[] = {
|
||||
N_("use sed replace EXPRESSION to transform file names"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 95
|
||||
#define GRID 120
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("File name matching options (affect both exclude and include patterns):"),
|
||||
GRID },
|
||||
@@ -679,15 +701,18 @@ static struct argp_option options[] = {
|
||||
N_("wildcards match `/' (default for exclusion)"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 100
|
||||
#define GRID 130
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Informative output:"), GRID },
|
||||
|
||||
{"verbose", 'v', 0, 0,
|
||||
N_("verbosely list files processed"), GRID+1 },
|
||||
{"checkpoint", CHECKPOINT_OPTION, N_("[.]NUMBER"), OPTION_ARG_OPTIONAL,
|
||||
{"checkpoint", CHECKPOINT_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
|
||||
N_("display progress messages every NUMBERth record (default 10)"),
|
||||
GRID+1 },
|
||||
{"checkpoint-action", CHECKPOINT_ACTION_OPTION, N_("ACTION"), 0,
|
||||
N_("execute ACTION on each checkpoint"),
|
||||
GRID+1 },
|
||||
{"check-links", 'l', 0, 0,
|
||||
N_("print a message if not all links are dumped"), GRID+1 },
|
||||
{"totals", TOTALS_OPTION, N_("SIGNAL"), OPTION_ARG_OPTIONAL,
|
||||
@@ -720,7 +745,7 @@ static struct argp_option options[] = {
|
||||
N_("disable quoting for characters from STRING"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 110
|
||||
#define GRID 140
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Compatibility options:"), GRID },
|
||||
|
||||
@@ -728,7 +753,7 @@ static struct argp_option options[] = {
|
||||
N_("when creating, same as --old-archive; when extracting, same as --no-same-owner"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 120
|
||||
#define GRID 150
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Other options:"), GRID },
|
||||
|
||||
@@ -785,6 +810,8 @@ struct tar_args /* Variables used during option parsing */
|
||||
char const *backup_suffix_string; /* --suffix option argument */
|
||||
char const *version_control_string; /* --backup option argument */
|
||||
bool input_files; /* True if some input files where given */
|
||||
int compress_autodetect; /* True if compression autodetection should
|
||||
be attempted when creating archives */
|
||||
};
|
||||
|
||||
|
||||
@@ -1222,6 +1249,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
set_subcommand_option (CAT_SUBCOMMAND);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
args->compress_autodetect = true;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
{
|
||||
uintmax_t u;
|
||||
@@ -1292,6 +1323,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
dereference_option = true;
|
||||
break;
|
||||
|
||||
case HARD_DEREFERENCE_OPTION:
|
||||
hard_dereference_option = true;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
/* Ignore zero blocks (eofs). This can't be the default,
|
||||
because Unix tar writes two blocks of zeros, then pads out
|
||||
@@ -1341,6 +1376,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
}
|
||||
break;
|
||||
|
||||
case LZMA_OPTION:
|
||||
set_use_compress_program_option ("lzma");
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
touch_option = true;
|
||||
break;
|
||||
@@ -1514,6 +1553,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
" on this platform")));
|
||||
break;
|
||||
|
||||
case CHECK_DEVICE_OPTION:
|
||||
check_device_option = true;
|
||||
break;
|
||||
|
||||
case NO_CHECK_DEVICE_OPTION:
|
||||
check_device_option = false;
|
||||
break;
|
||||
|
||||
case CHECKPOINT_OPTION:
|
||||
if (arg)
|
||||
{
|
||||
@@ -1521,7 +1568,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
|
||||
if (*arg == '.')
|
||||
{
|
||||
checkpoint_style = checkpoint_dot;
|
||||
checkpoint_compile_action (".");
|
||||
arg++;
|
||||
}
|
||||
checkpoint_option = strtoul (arg, &p, 0);
|
||||
@@ -1530,9 +1577,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
_("--checkpoint value is not an integer")));
|
||||
}
|
||||
else
|
||||
checkpoint_option = 10;
|
||||
checkpoint_option = DEFAULT_CHECKPOINT;
|
||||
break;
|
||||
|
||||
case CHECKPOINT_ACTION_OPTION:
|
||||
checkpoint_compile_action (arg);
|
||||
break;
|
||||
|
||||
case BACKUP_OPTION:
|
||||
backup_option = true;
|
||||
if (arg)
|
||||
@@ -2001,7 +2052,8 @@ decode_options (int argc, char **argv)
|
||||
args.backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
|
||||
args.version_control_string = 0;
|
||||
args.input_files = false;
|
||||
|
||||
args.compress_autodetect = false;
|
||||
|
||||
subcommand_option = UNKNOWN_SUBCOMMAND;
|
||||
archive_format = DEFAULT_FORMAT;
|
||||
blocking_factor = DEFAULT_BLOCKING;
|
||||
@@ -2017,6 +2069,8 @@ decode_options (int argc, char **argv)
|
||||
owner_option = -1;
|
||||
group_option = -1;
|
||||
|
||||
check_device_option = true;
|
||||
|
||||
/* Convert old-style tar call by exploding option element and rearranging
|
||||
options accordingly. */
|
||||
|
||||
@@ -2262,6 +2316,10 @@ decode_options (int argc, char **argv)
|
||||
if (!args.input_files && !files_from_option)
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("Cowardly refusing to create an empty archive")));
|
||||
if (args.compress_autodetect && archive_names
|
||||
&& strcmp (archive_name_array[0], "-"))
|
||||
set_comression_program_by_suffix (archive_name_array[0],
|
||||
use_compress_program_option);
|
||||
break;
|
||||
|
||||
case EXTRACT_SUBCOMMAND:
|
||||
@@ -2314,6 +2372,8 @@ decode_options (int argc, char **argv)
|
||||
backup_option = false;
|
||||
}
|
||||
|
||||
checkpoint_finish_compile ();
|
||||
|
||||
if (verbose_option)
|
||||
report_textual_dates (&args);
|
||||
}
|
||||
|
||||
200
src/transform.c
200
src/transform.c
@@ -1,5 +1,5 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
@@ -19,16 +19,11 @@
|
||||
#include <regex.h>
|
||||
#include "common.h"
|
||||
|
||||
static enum transform_type
|
||||
enum transform_type
|
||||
{
|
||||
transform_none,
|
||||
transform_first,
|
||||
transform_global
|
||||
}
|
||||
transform_type = transform_none;
|
||||
static unsigned match_number = 0;
|
||||
static regex_t regex;
|
||||
static struct obstack stk;
|
||||
};
|
||||
|
||||
enum replace_segm_type
|
||||
{
|
||||
@@ -62,31 +57,53 @@ struct replace_segm
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Compiled replacement expression */
|
||||
static struct replace_segm *repl_head, *repl_tail;
|
||||
static size_t segm_count; /* Number of elements in the above list */
|
||||
struct transform
|
||||
{
|
||||
struct transform *next;
|
||||
enum transform_type transform_type;
|
||||
unsigned match_number;
|
||||
regex_t regex;
|
||||
/* Compiled replacement expression */
|
||||
struct replace_segm *repl_head, *repl_tail;
|
||||
size_t segm_count; /* Number of elements in the above list */
|
||||
};
|
||||
|
||||
|
||||
static struct transform *transform_head, *transform_tail;
|
||||
|
||||
static struct transform *
|
||||
new_transform ()
|
||||
{
|
||||
struct transform *p = xzalloc (sizeof *p);
|
||||
if (transform_tail)
|
||||
transform_tail->next = p;
|
||||
else
|
||||
transform_head = p;
|
||||
transform_tail = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct replace_segm *
|
||||
add_segment (void)
|
||||
add_segment (struct transform *tf)
|
||||
{
|
||||
struct replace_segm *segm = xmalloc (sizeof *segm);
|
||||
segm->next = NULL;
|
||||
if (repl_tail)
|
||||
repl_tail->next = segm;
|
||||
if (tf->repl_tail)
|
||||
tf->repl_tail->next = segm;
|
||||
else
|
||||
repl_head = segm;
|
||||
repl_tail = segm;
|
||||
segm_count++;
|
||||
tf->repl_head = segm;
|
||||
tf->repl_tail = segm;
|
||||
tf->segm_count++;
|
||||
return segm;
|
||||
}
|
||||
|
||||
static void
|
||||
add_literal_segment (char *str, char *end)
|
||||
add_literal_segment (struct transform *tf, char *str, char *end)
|
||||
{
|
||||
size_t len = end - str;
|
||||
if (len)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (len + 1);
|
||||
memcpy (segm->v.literal.ptr, str, len);
|
||||
@@ -96,9 +113,9 @@ add_literal_segment (char *str, char *end)
|
||||
}
|
||||
|
||||
static void
|
||||
add_char_segment (int chr)
|
||||
add_char_segment (struct transform *tf, int chr)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (2);
|
||||
segm->v.literal.ptr[0] = chr;
|
||||
@@ -107,37 +124,30 @@ add_char_segment (int chr)
|
||||
}
|
||||
|
||||
static void
|
||||
add_backref_segment (size_t ref)
|
||||
add_backref_segment (struct transform *tf, size_t ref)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_backref;
|
||||
segm->v.ref = ref;
|
||||
}
|
||||
|
||||
static void
|
||||
add_case_ctl_segment (enum case_ctl_type ctl)
|
||||
add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_case_ctl;
|
||||
segm->v.ctl = ctl;
|
||||
}
|
||||
|
||||
void
|
||||
set_transform_expr (const char *expr)
|
||||
static const char *
|
||||
parse_transform_expr (const char *expr)
|
||||
{
|
||||
int delim;
|
||||
int i, j, rc;
|
||||
char *str, *beg, *cur;
|
||||
const char *p;
|
||||
int cflags = 0;
|
||||
|
||||
if (transform_type == transform_none)
|
||||
obstack_init (&stk);
|
||||
else
|
||||
{
|
||||
/* Redefinition of the transform expression */
|
||||
regfree (®ex);
|
||||
}
|
||||
struct transform *tf = new_transform ();
|
||||
|
||||
if (expr[0] != 's')
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
@@ -161,12 +171,12 @@ set_transform_expr (const char *expr)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
/* Check flags */
|
||||
transform_type = transform_first;
|
||||
for (p = expr + j + 1; *p; p++)
|
||||
tf->transform_type = transform_first;
|
||||
for (p = expr + j + 1; *p && *p != ';'; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case 'g':
|
||||
transform_type = transform_global;
|
||||
tf->transform_type = transform_global;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
@@ -179,30 +189,34 @@ set_transform_expr (const char *expr)
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
match_number = strtoul (p, (char**) &p, 0);
|
||||
tf->match_number = strtoul (p, (char**) &p, 0);
|
||||
p--;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression")));
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression: %c"),
|
||||
*p));
|
||||
}
|
||||
|
||||
if (*p == ';')
|
||||
p++;
|
||||
|
||||
/* Extract and compile regex */
|
||||
str = xmalloc (i - 1);
|
||||
memcpy (str, expr + 2, i - 2);
|
||||
str[i - 2] = 0;
|
||||
|
||||
rc = regcomp (®ex, str, cflags);
|
||||
rc = regcomp (&tf->regex, str, cflags);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
char errbuf[512];
|
||||
regerror (rc, ®ex, errbuf, sizeof (errbuf));
|
||||
regerror (rc, &tf->regex, errbuf, sizeof (errbuf));
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
|
||||
}
|
||||
|
||||
if (str[0] == '^' || str[strlen (str) - 1] == '$')
|
||||
transform_type = transform_first;
|
||||
tf->transform_type = transform_first;
|
||||
|
||||
free (str);
|
||||
|
||||
@@ -218,91 +232,91 @@ set_transform_expr (const char *expr)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
add_literal_segment (beg, cur);
|
||||
add_literal_segment (tf, beg, cur);
|
||||
switch (*++cur)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
n = strtoul (cur, &cur, 10);
|
||||
if (n > regex.re_nsub)
|
||||
if (n > tf->regex.re_nsub)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform replacement: back reference out of range")));
|
||||
add_backref_segment (n);
|
||||
add_backref_segment (tf, n);
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
add_char_segment ('\\');
|
||||
add_char_segment (tf, '\\');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
add_char_segment ('\a');
|
||||
add_char_segment (tf, '\a');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
add_char_segment ('\b');
|
||||
add_char_segment (tf, '\b');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
add_char_segment ('\f');
|
||||
add_char_segment (tf, '\f');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
add_char_segment ('\n');
|
||||
add_char_segment (tf, '\n');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
add_char_segment ('\r');
|
||||
add_char_segment (tf, '\r');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
add_char_segment ('\t');
|
||||
add_char_segment (tf, '\t');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
add_char_segment ('\v');
|
||||
add_char_segment (tf, '\v');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
add_char_segment ('&');
|
||||
add_char_segment (tf, '&');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
/* Turn the replacement to lowercase until a `\U' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_locase);
|
||||
add_case_ctl_segment (tf, ctl_locase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
/* Turn the next character to lowercase, */
|
||||
add_case_ctl_segment (ctl_locase_next);
|
||||
add_case_ctl_segment (tf, ctl_locase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
/* Turn the replacement to uppercase until a `\L' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_upcase);
|
||||
add_case_ctl_segment (tf, ctl_upcase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
/* Turn the next character to uppercase, */
|
||||
add_case_ctl_segment (ctl_upcase_next);
|
||||
add_case_ctl_segment (tf, ctl_upcase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
/* Stop case conversion started by `\L' or `\U'. */
|
||||
add_case_ctl_segment (ctl_stop);
|
||||
add_case_ctl_segment (tf, ctl_stop);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
@@ -312,7 +326,7 @@ set_transform_expr (const char *expr)
|
||||
char buf[2];
|
||||
buf[0] = '\\';
|
||||
buf[1] = *cur;
|
||||
add_literal_segment (buf, buf + 2);
|
||||
add_literal_segment (tf, buf, buf + 2);
|
||||
}
|
||||
cur++;
|
||||
break;
|
||||
@@ -321,15 +335,23 @@ set_transform_expr (const char *expr)
|
||||
}
|
||||
else if (*cur == '&')
|
||||
{
|
||||
add_literal_segment (beg, cur);
|
||||
add_backref_segment (0);
|
||||
add_literal_segment (tf, beg, cur);
|
||||
add_backref_segment (tf, 0);
|
||||
beg = ++cur;
|
||||
}
|
||||
else
|
||||
cur++;
|
||||
}
|
||||
add_literal_segment (beg, cur);
|
||||
|
||||
add_literal_segment (tf, beg, cur);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
set_transform_expr (const char *expr)
|
||||
{
|
||||
while (*expr)
|
||||
expr = parse_transform_expr (expr);
|
||||
}
|
||||
|
||||
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
|
||||
@@ -373,8 +395,12 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
|
||||
return case_ctl_buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
_transform_name_to_obstack (char *input)
|
||||
|
||||
static struct obstack stk;
|
||||
static bool stk_init;
|
||||
|
||||
void
|
||||
_single_transform_name_to_obstack (struct transform *tf, char *input)
|
||||
{
|
||||
regmatch_t *rmp;
|
||||
int rc;
|
||||
@@ -390,17 +416,14 @@ _transform_name_to_obstack (char *input)
|
||||
save_ctl = ctl_stop; \
|
||||
}
|
||||
|
||||
if (transform_type == transform_none)
|
||||
return false;
|
||||
|
||||
rmp = xmalloc ((regex.re_nsub + 1) * sizeof (*rmp));
|
||||
rmp = xmalloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
|
||||
|
||||
while (*input)
|
||||
{
|
||||
size_t disp;
|
||||
char *ptr;
|
||||
|
||||
rc = regexec (®ex, input, regex.re_nsub + 1, rmp, 0);
|
||||
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
@@ -412,14 +435,14 @@ _transform_name_to_obstack (char *input)
|
||||
obstack_grow (&stk, input, rmp[0].rm_so);
|
||||
|
||||
nmatches++;
|
||||
if (match_number && nmatches < match_number)
|
||||
if (tf->match_number && nmatches < tf->match_number)
|
||||
{
|
||||
obstack_grow (&stk, input, disp);
|
||||
input += disp;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (segm = repl_head; segm; segm = segm->next)
|
||||
for (segm = tf->repl_head; segm; segm = segm->next)
|
||||
{
|
||||
switch (segm->type)
|
||||
{
|
||||
@@ -485,7 +508,7 @@ _transform_name_to_obstack (char *input)
|
||||
|
||||
input += disp;
|
||||
|
||||
if (transform_type == transform_first)
|
||||
if (tf->transform_type == transform_first)
|
||||
{
|
||||
obstack_grow (&stk, input, strlen (input));
|
||||
break;
|
||||
@@ -494,23 +517,40 @@ _transform_name_to_obstack (char *input)
|
||||
|
||||
obstack_1grow (&stk, 0);
|
||||
free (rmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
_transform_name_to_obstack (char *input, char **output)
|
||||
{
|
||||
struct transform *tf;
|
||||
|
||||
if (!stk_init)
|
||||
{
|
||||
obstack_init (&stk);
|
||||
stk_init = true;
|
||||
}
|
||||
|
||||
for (tf = transform_head; tf; tf = tf->next)
|
||||
{
|
||||
_single_transform_name_to_obstack (tf, input);
|
||||
input = obstack_finish (&stk);
|
||||
}
|
||||
*output = input;
|
||||
return transform_head != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
|
||||
{
|
||||
char *str;
|
||||
bool ret = _transform_name_to_obstack (*pinput);
|
||||
bool ret = _transform_name_to_obstack (*pinput, &str);
|
||||
if (ret)
|
||||
{
|
||||
str = obstack_finish (&stk);
|
||||
assign_string (pinput, fun ? fun (str, dat) : str);
|
||||
obstack_free (&stk, str);
|
||||
}
|
||||
else if (fun)
|
||||
{
|
||||
str = *pinput;
|
||||
*pinput = NULL;
|
||||
assign_string (pinput, fun (str, dat));
|
||||
free (str);
|
||||
|
||||
@@ -91,7 +91,7 @@ bool
|
||||
string_ascii_p (char const *p)
|
||||
{
|
||||
for (; *p; p++)
|
||||
if (! (0 <= *p && *p <= 127))
|
||||
if (*p & ~0x7f)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ TESTSUITE_AT = \
|
||||
same-order01.at\
|
||||
same-order02.at\
|
||||
shortfile.at\
|
||||
shortupd.at\
|
||||
shortrec.at\
|
||||
sparse01.at\
|
||||
sparse02.at\
|
||||
|
||||
@@ -13,7 +13,7 @@ if test -z "$TEST_DATA_DIR"; then
|
||||
TEST_DATA_DIR=$abs_builddir
|
||||
fi
|
||||
|
||||
STAR_DATA_URL=http://download.berlios.de/pub/star/testscripts
|
||||
STAR_DATA_URL=ftp://ftp.berlios.de/pub/star/testscripts
|
||||
if test -z "$STAR_TESTSCRIPTS"; then
|
||||
STAR_TESTSCRIPTS=$TEST_DATA_DIR
|
||||
fi
|
||||
|
||||
@@ -34,6 +34,8 @@ mkdir directory
|
||||
genfile --file=directory/x
|
||||
genfile --file=directory/y
|
||||
|
||||
sleep 1
|
||||
|
||||
tar -cf archive.1 -g db directory
|
||||
|
||||
mv directory/x directory/z
|
||||
|
||||
@@ -38,6 +38,8 @@ awk 'BEGIN {
|
||||
printf("NAME_PREFIX[%03d]\n", i);
|
||||
}' < /dev/null | genfile --files-from -
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Initial dump"
|
||||
tar cvf a0.tar -g a.sna a
|
||||
mv a/b a/c
|
||||
|
||||
@@ -34,6 +34,8 @@ genfile --file foo/bar/file.r
|
||||
mkdir foo/bar/baz
|
||||
genfile --file foo/bar/baz/file.z
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Creating base archive"
|
||||
tar -g incr -cf arch.1 -v foo
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ genfile --file foo/b/fileb
|
||||
mkdir foo/c
|
||||
genfile --file foo/c/filec
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "First dump"
|
||||
echo "First dump">&2
|
||||
tar -g incr -cf arch.1 -v foo 2>tmperr
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2007-08/msg00038.html
|
||||
|
||||
AT_SETUP([short input files])
|
||||
AT_KEYWORDS([shortfile])
|
||||
AT_KEYWORDS([shortfile shortfile0])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile --length 511 --file foo || exit 5
|
||||
|
||||
39
tests/shortupd.at
Normal file
39
tests/shortupd.at
Normal file
@@ -0,0 +1,39 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
# 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, 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/>.
|
||||
|
||||
# Fixing improper small file recognition in version 1.18 (see shortfile.at
|
||||
# and ChangeLog:2007-08-24), introduced another bug: when updating a
|
||||
# non-existing archive, tar-1.19 complained about its not being a tar archive
|
||||
# and exited immediately, leaving the created zero-sized file after it.
|
||||
#
|
||||
# This bug was fixed on 2007-12-05.
|
||||
#
|
||||
# Reported by: Ozan @,{C}a@v{g}layan <ozancag@gmail.com>
|
||||
# References: <4755A82A.9060607@gmail.com>
|
||||
|
||||
AT_SETUP([updating short archives])
|
||||
AT_KEYWORDS([shortfile shortfile1 shortupd])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
touch foo
|
||||
tar uf archive foo
|
||||
],
|
||||
[0])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
This directory contains scripts for testing GNU tar using
|
||||
star "test archives". The archives themselves can be obtained
|
||||
from http://download.berlios.de/pub/star/testscripts.
|
||||
from ftp://ftp.berlios.de/pub/star/testscripts.
|
||||
|
||||
These tests are disabled by default. There are two ways to run
|
||||
them. The simplest is by `make check-full' command. It requires wget
|
||||
@@ -52,9 +52,9 @@ containing very large files (in this case -- 10 GB).
|
||||
|
||||
This is a test for compliance to POSIX.1-1990 tar specification. It
|
||||
requires two files: ustar-all-quicktest.tar and quicktest.filelist,
|
||||
(they usually reside in star/tartest directory), and `tartest' program
|
||||
(they usually reside in star/testscripts directory), and `tartest' program
|
||||
(also part of star distribution). The test must be run only with root
|
||||
privileges, so it is a good idea to test contents of
|
||||
privileges, so it is a good idea to verify the contents of
|
||||
ustar-all-quicktest.tar before running it.
|
||||
|
||||
If `tartest' is not in your PATH, use TARTEST variable to specify its
|
||||
|
||||
@@ -180,6 +180,7 @@ m4_include([volsize.at])
|
||||
|
||||
m4_include([comprec.at])
|
||||
m4_include([shortfile.at])
|
||||
m4_include([shortupd.at])
|
||||
|
||||
m4_include([truncate.at])
|
||||
m4_include([grow.at])
|
||||
|
||||
Reference in New Issue
Block a user