61 Commits

Author SHA1 Message Date
Sergey Poznyakoff
b94eed6d03 Version 1.20.
* configure.ac: Raise version number to 1.20
* src/compare.c (diff_dumpdir): const.
* src/common.h (dumpdir_t,dumpdir_iter_t): New data types.
(dumpdir_create0,dumpdir_create,dumpdir_free,dumpdir_locate)
(dumpdir_first,dumpdir_next): New functions.
* src/incremen.c (dumpdir_create0,dumpdir_create,dumpdir_free)
(dumpdir_first,dumpdir_next): New functions.
(dumpdir_locate): Rewrite using binary search.
(struct directory): Change members char *contents, *icontents to
struct dumpdir *dump, *idump. All references updated.
(note_directory): Last arg is const.
* src/names.c (add_hierarchy_to_namelist): buffer is const.
* tests/incr03.at, tests/incr04.at, tests/rename02.at,
tests/rename03.at: Insert calls to sleep between creation of files
and adding them to the archive.
2008-05-05 21:30:57 +00:00
Sergey Poznyakoff
192860abb8 Update 2008-03-31 08:03:00 +00:00
Sergey Poznyakoff
c2d2e806a1 (dump_file0): Count links only for actually dumped files 2008-03-31 08:02:53 +00:00
Sergey Poznyakoff
2a89f7a0a8 * 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.
2008-03-27 10:11:05 +00:00
Sergey Poznyakoff
71d2a66f42 * 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.
2008-03-27 08:56:26 +00:00
Sergey Poznyakoff
e496c1b529 * 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-03-06 08:17:33 +00:00
Sergey Poznyakoff
6667fa7fb8 Update 2008-02-09 10:36:40 +00:00
Sergey Poznyakoff
a16ad3112e Fix a typo 2008-02-09 10:35:55 +00:00
Sergey Poznyakoff
7efe3850f6 * 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-08 14:12:22 +00:00
Sergey Poznyakoff
d0694ee604 Update the description 2008-02-08 10:32:15 +00:00
Sergey Poznyakoff
37f0faf1c0 (dump_file0): Apply transform_name to symlink targets. 2008-02-07 15:46:41 +00:00
Sergey Poznyakoff
b893aee6d2 Update 2008-02-07 15:46:28 +00:00
Sergey Poznyakoff
f60d655908 Update 2008-02-04 10:39:05 +00:00
Sergey Poznyakoff
549481a0a7 Update 2008-02-04 10:38:27 +00:00
Sergey Poznyakoff
e08afc2002 Document changes to the --transform option. 2008-02-04 10:38:18 +00:00
Sergey Poznyakoff
338591a486 Support multiple --transform options. Support semicolon-separated lists of replace expressions. 2008-02-04 10:35:20 +00:00
Paul Eggert
c0e0d06e69 * 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.
2008-01-31 00:50:12 +00:00
Sergey Poznyakoff
6e85425618 Update 2007-12-05 09:48:37 +00:00
Sergey Poznyakoff
336519aa4f Add shortupd.at. 2007-12-05 09:45:35 +00:00
Sergey Poznyakoff
5f4d99491d (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.
2007-12-05 09:45:22 +00:00
Paul Eggert
48d83be336 Don't read from name[-1].
* src/incremen.c (make_directory): Handle namelen == 0, since
find_directory_meta calls make_directory ("").
2007-11-13 07:01:26 +00:00
Sergey Poznyakoff
60d351cc5a Update 2007-11-07 08:48:39 +00:00
Sergey Poznyakoff
e33be3d0a1 Add fseeko and snprintf. 2007-11-07 08:48:28 +00:00
Sergey Poznyakoff
32562b9412 (checkout): Use URL of the gnulib CVS mirror. 2007-11-07 08:48:19 +00:00
Sergey Poznyakoff
dfd87ba1d0 (magic): Fix lzma option 2007-10-31 13:10:55 +00:00
Sergey Poznyakoff
5d4a682a55 Update 2007-10-31 12:57:04 +00:00
Sergey Poznyakoff
8e3a2a520d (sys_exec_info_script,sys_exec_checkpoint_script): pass the current blocking factor in TAR_BLOCKING_FACTOR environment variable. 2007-10-31 12:56:46 +00:00
Sergey Poznyakoff
745832a280 New actions: bell and ttyout 2007-10-31 12:56:27 +00:00
Sergey Poznyakoff
458efab23b Minor fix 2007-10-30 14:58:52 +00:00
Sergey Poznyakoff
23dcaa117f Update 2007-10-30 14:09:20 +00:00
Sergey Poznyakoff
5099ddf6cc Document --hard-dereference and --checkpoint-action options. Improve documentation of --check-links. 2007-10-30 14:09:04 +00:00
Sergey Poznyakoff
8476145508 Use texi2html and the CVS version of gendocs.sh to create HTML versions of the manual 2007-10-30 14:08:41 +00:00
Sergey Poznyakoff
362492fe70 Use texi2html and the CVS version of gendocs.sh to create HTML versions of the manual 2007-10-30 14:08:21 +00:00
Sergey Poznyakoff
7111008659 Update 2007-10-29 16:57:32 +00:00
Sergey Poznyakoff
ec4741d732 (parse_opt): New options --hard-dereference, --checkpoint-action.
(decode_options): Call checkpoint_finish_compile.
2007-10-29 16:56:56 +00:00
Sergey Poznyakoff
bed7de0271 (sys_exec_checkpoint_script): New function.
(sys_exec_info_script): Restore SIGPIPE handler.
2007-10-29 16:56:33 +00:00
Sergey Poznyakoff
eaaadcfd36 (file_count_links): do nothing if hard_dereference_option is set. 2007-10-29 16:56:13 +00:00
Sergey Poznyakoff
a8830fbb86 (enum checkpoint_style): Remove.
(checkpoint_style): Remove.
(DEFAULT_CHECKPOINT): New define.
(hard_dereference_option): New variable.
(sys_exec_checkpoint_script): New declaration.
2007-10-29 16:55:58 +00:00
Sergey Poznyakoff
848659f1c6 (checkpoint, do_checkpoint): Remove.
(_flush_write, simple_flush_read, _gnu_flush_read): Use
checkpoint_run.
2007-10-29 16:55:37 +00:00
Sergey Poznyakoff
17cbd4862c checkpoint handling 2007-10-29 16:55:16 +00:00
Sergey Poznyakoff
64ded9e702 (tar_SOURCES): add checkpoint.c 2007-10-29 16:54:51 +00:00
Sergey Poznyakoff
ccd0a527e4 Version 1.19.1 2007-10-29 16:54:38 +00:00
Sergey Poznyakoff
3f869877a4 Version 1.19.1 2007-10-29 16:53:28 +00:00
Sergey Poznyakoff
8c528937a9 Update 2007-10-29 16:53:20 +00:00
Sergey Poznyakoff
460f4ec146 Update 2007-10-29 08:53:58 +00:00
Sergey Poznyakoff
eb59c14a1f (sys_exec_info_script): Initialize buf. Problem reported by Bengt-Arne Fjellner. 2007-10-29 08:51:46 +00:00
Paul Eggert
3c4f4ca423 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".

expired.
SCALAR(0x830b08c)
2007-10-18 21:36:38 +00:00
Sergey Poznyakoff
506b4db5d0 Update 2007-10-18 07:59:48 +00:00
Sergey Poznyakoff
5bfb6c5f9d (gzip): Remove compression patent warning. According to Brett Smith, the patent is expired. 2007-10-18 07:59:39 +00:00
Sergey Poznyakoff
3725b5606f Update 2007-10-17 09:12:54 +00:00
Sergey Poznyakoff
d1a7eebc30 Update 2007-10-17 09:12:03 +00:00
Sergey Poznyakoff
dfe280dcca Add Lasse Collin and Jean-Pierre Demailly. 2007-10-17 09:11:50 +00:00
Sergey Poznyakoff
620a136e74 New options --auto-compress (-a) and --lzma 2007-10-17 09:11:34 +00:00
Sergey Poznyakoff
3fb5d67b28 (set_comression_program_by_suffix): New prototype. 2007-10-17 09:11:23 +00:00
Sergey Poznyakoff
c30a794679 (magic): Add an entry for new lzma format. Proposed by Lasse Collin 2007-10-17 09:11:08 +00:00
Sergey Poznyakoff
00bb0d8f5c Add suffix.c 2007-10-17 09:10:46 +00:00
Sergey Poznyakoff
af3e05b6af New file. Determine compression algorithm by archive file name suffix. Suggested by Jean-Pierre Demailly. 2007-10-17 09:10:34 +00:00
Paul Eggert
6060d613d1 * 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-13 05:49:18 +00:00
Paul Eggert
3f12066739 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.

SCALAR(0x830b0dc)
directories.

SCALAR(0x831ad2c)
2007-10-11 22:04:44 +00:00
Sergey Poznyakoff
3b74fbfc3b Update 2007-10-10 11:04:25 +00:00
Sergey Poznyakoff
14d39a2c14 Update 2007-10-10 11:03:42 +00:00
39 changed files with 1936 additions and 469 deletions

View File

@@ -12,5 +12,7 @@ build-aux
config.*
configure
gnulib
m4
rmt
stamp-h1
tar-[0-9]*

189
ChangeLog
View File

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 (&current_stat_info);
}

View File

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

View File

@@ -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 (&current_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;
}

View File

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

View File

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

View File

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

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

View File

@@ -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 (&regex);
}
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 (&regex, str, cflags);
rc = regcomp (&tf->regex, str, cflags);
if (rc)
{
char errbuf[512];
regerror (rc, &regex, 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 (&regex, 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);

View File

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

View File

@@ -100,6 +100,7 @@ TESTSUITE_AT = \
same-order01.at\
same-order02.at\
shortfile.at\
shortupd.at\
shortrec.at\
sparse01.at\
sparse02.at\

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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