Compare commits
92 Commits
release_1_
...
origin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
970f999818 | ||
|
|
cd39b5a1b7 | ||
|
|
7f6e6e6a3e | ||
|
|
99e3a2604f | ||
|
|
b4ec8aedf9 | ||
|
|
5354888e40 | ||
|
|
57bfbbde90 | ||
|
|
7b69ee5a24 | ||
|
|
1428b7f176 | ||
|
|
6901594ac4 | ||
|
|
c78356feda | ||
|
|
60c00c18b5 | ||
|
|
c1b55e02b1 | ||
|
|
15abf5c4d9 | ||
|
|
1353511226 | ||
|
|
85c7909497 | ||
|
|
db83069aea | ||
|
|
dbbffde583 | ||
|
|
1d79c6734c | ||
|
|
3af9cc0f15 | ||
|
|
c9a7297a8a | ||
|
|
985637ab5a | ||
|
|
1024343a2b | ||
|
|
1efa1f3b43 | ||
|
|
5f1a4f9f12 | ||
|
|
969d2b986b | ||
|
|
d5f2066cac | ||
|
|
79ce0e6789 | ||
|
|
6a052fd5a3 | ||
|
|
8aa729b90e | ||
|
|
057dd26a60 | ||
|
|
b94eed6d03 | ||
|
|
192860abb8 | ||
|
|
c2d2e806a1 | ||
|
|
2a89f7a0a8 | ||
|
|
71d2a66f42 | ||
|
|
e496c1b529 | ||
|
|
6667fa7fb8 | ||
|
|
a16ad3112e | ||
|
|
7efe3850f6 | ||
|
|
d0694ee604 | ||
|
|
37f0faf1c0 | ||
|
|
b893aee6d2 | ||
|
|
f60d655908 | ||
|
|
549481a0a7 | ||
|
|
e08afc2002 | ||
|
|
338591a486 | ||
|
|
c0e0d06e69 | ||
|
|
6e85425618 | ||
|
|
336519aa4f | ||
|
|
5f4d99491d | ||
|
|
48d83be336 | ||
|
|
60d351cc5a | ||
|
|
e33be3d0a1 | ||
|
|
32562b9412 | ||
|
|
dfd87ba1d0 | ||
|
|
5d4a682a55 | ||
|
|
8e3a2a520d | ||
|
|
745832a280 | ||
|
|
458efab23b | ||
|
|
23dcaa117f | ||
|
|
5099ddf6cc | ||
|
|
8476145508 | ||
|
|
362492fe70 | ||
|
|
7111008659 | ||
|
|
ec4741d732 | ||
|
|
bed7de0271 | ||
|
|
eaaadcfd36 | ||
|
|
a8830fbb86 | ||
|
|
848659f1c6 | ||
|
|
17cbd4862c | ||
|
|
64ded9e702 | ||
|
|
ccd0a527e4 | ||
|
|
3f869877a4 | ||
|
|
8c528937a9 | ||
|
|
460f4ec146 | ||
|
|
eb59c14a1f | ||
|
|
3c4f4ca423 | ||
|
|
506b4db5d0 | ||
|
|
5bfb6c5f9d | ||
|
|
3725b5606f | ||
|
|
d1a7eebc30 | ||
|
|
dfe280dcca | ||
|
|
620a136e74 | ||
|
|
3fb5d67b28 | ||
|
|
c30a794679 | ||
|
|
00bb0d8f5c | ||
|
|
af3e05b6af | ||
|
|
6060d613d1 | ||
|
|
3f12066739 | ||
|
|
3b74fbfc3b | ||
|
|
14d39a2c14 |
@@ -12,5 +12,7 @@ build-aux
|
||||
config.*
|
||||
configure
|
||||
gnulib
|
||||
m4
|
||||
rmt
|
||||
stamp-h1
|
||||
tar-[0-9]*
|
||||
|
||||
395
ChangeLog
395
ChangeLog
@@ -1,3 +1,392 @@
|
||||
2008-11-30 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/xheader.c: Remove duplicate inclusion of fnmatch.h. Reported
|
||||
by Jim Meyering.
|
||||
|
||||
2008-11-25 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
Do not try to drain the input pipe before closing the
|
||||
archive.
|
||||
|
||||
* src/buffer.c (close_archive): Remove call to
|
||||
sys_drain_input_pipe. Pass hit_eof as the second
|
||||
argument to sys_wait_for_child.
|
||||
* src/common.h (sys_drain_input_pipe): Remove
|
||||
(sys_wait_for_child): Declare second argument.
|
||||
* src/system.c (sys_drain_input_pipe): Remove.
|
||||
(sys_wait_for_child): Take two arguments. The second one helps to
|
||||
decide whether to tolerate child termination on SIGPIPE.
|
||||
|
||||
2008-11-03 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/buffer.c (_write_volume_label): Fix typo, which prevented
|
||||
`-V label -M' from working.
|
||||
|
||||
2008-10-30 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS, configure.ac: Version 1.20.91
|
||||
* doc/tar.texi: Document transformation scope flags.
|
||||
* src/common.h (transform_symlinks_option): Remove in favor of
|
||||
transformation scope flags.
|
||||
(XFORM_REGFILE, XFORM_LINK, XFORM_SYMLINK, XFORM_ALL): New macros.
|
||||
(transform_name, transform_member_name, transform_name_fp): Take
|
||||
an additional argument, specifying scope flags.
|
||||
* src/create.c: Reflect changes to transform_name.
|
||||
* src/extract.c (extract_link, extract_symlink): Remove calls to
|
||||
transform_member_name. It is done in read_header.
|
||||
* src/list.c (decode_xform): Reflect change in data type of 2nd
|
||||
argument.
|
||||
(transform_member_name): 2nd arg is int.
|
||||
(decode_header): Transform file name and link target names.
|
||||
* src/tar.c: Remove --transform-symlinks.
|
||||
* src/transform.c (struct transform): New member `flags'.
|
||||
(transform_flags): New variable.
|
||||
(parse_transform_expr): Parse transformation scope flags. Allow to
|
||||
set global flags using `flags=' syntax.
|
||||
(_transform_name_to_obstack, transform_name_fp)
|
||||
(transform_name): Take an additional argument, specifying scope
|
||||
flags.
|
||||
|
||||
2008-10-19 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* THANKS: Add Ed Leaver.
|
||||
* src/buffer.c (short_read): Remove !read_full_records condition,
|
||||
which was always false on a first record and thus disabled record
|
||||
size autodetection. Thanks Ed Leaver for the patch.
|
||||
(_gnu_flush_read): Handle blocking_factor == 1.
|
||||
* tests/sparsemv.at: Reflect changes to buffer.c.
|
||||
* tests/sparsemvp.at: Likewise.
|
||||
* tests/volsize.at: Likewise.
|
||||
* NEWS: Update.
|
||||
|
||||
2008-10-16 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/common.h (transform_symlinks_option): New global.
|
||||
* src/create.c (dump_file0): Transform symlink targets only if
|
||||
explicitly required. Thanks Cyril Strejc for reporting the
|
||||
problem.
|
||||
* src/tar.c (parse_opt): New options --transform-symlinks and
|
||||
--no-transform-symlinks. New alias --xform to the --transform
|
||||
option.
|
||||
* doc/tar.texi: Document --transform-symlinks
|
||||
* NEWS: Update.
|
||||
* THANKS: Update.
|
||||
|
||||
* src/names.c (name_gather): Use xzalloc.
|
||||
* src/buffer.c (short_read): Move record size detection before
|
||||
the loop.
|
||||
|
||||
2008-10-07 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/tar.c (options): Add --lzop option.
|
||||
|
||||
2008-10-05 Xavier Hienne <xavier.hienne@free.fr> (tiny change)
|
||||
|
||||
* src/checkpoint.c (checkpoint_compile_action): Add missing
|
||||
`else'.
|
||||
|
||||
2008-09-24 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS: Update.
|
||||
* doc/tar.texi: Update.
|
||||
* src/tar.c: New option --no-null.
|
||||
|
||||
2008-09-23 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/common.h (filename_terminator): Remove global.
|
||||
* src/tar.c (filename_terminator): New static.
|
||||
* src/names.c (name_next_elt): Do not depend on
|
||||
filename_terminator, this was a leftover from 1.13.
|
||||
|
||||
2008-09-18 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/tar.texi: Remove incorrect example.
|
||||
|
||||
2008-09-07 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/incremen.c (dumpdir_create0): Eliminate gcc warning.
|
||||
(attach_directory): Bugfix - add missing return statement.
|
||||
* THANKS: Add Enric Hernandez
|
||||
|
||||
2008-07-31 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/incremen.c (struct directory): New member `next'. Change
|
||||
type of `name'.
|
||||
(dirhead, dirtail): New statics.
|
||||
(make_directory): Reflect changes to struct directory.
|
||||
(free_directory, attach_directory): New functions.
|
||||
(dirlist_replace_prefix): New function.
|
||||
(note_directory): Use attach_directory, instead of make_directory,
|
||||
(find_directory, find_directory_meta): Use free_directory.
|
||||
(procdir): Replace directory prefixes in directory list to avoid
|
||||
marking subdirectories as renamed after renaming their parent
|
||||
directory.
|
||||
(append_incremental_renames): Iterate over directory list, not
|
||||
hash table, to preserve logical ordering of renames.
|
||||
* tests/rename04.at, tests/rename05.at: New test cases.
|
||||
* tests/Makefile.am, tests/testsuite.at: Add rename04.at and
|
||||
rename05.at.
|
||||
* tests/atlocal.in (decho): New function.
|
||||
* tests/multiv06.at: Use decho instead of echo2.
|
||||
* tests/incremental.at: Raise wait interval to 2 seconds.
|
||||
|
||||
2008-07-24 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/tar.c (decode_options): Do not allow volume length less
|
||||
than record size.
|
||||
* src/buffer.c (_gnu_flush_write): Compensate for the effect
|
||||
of eventual flush_archive occurring in the middle of buffer
|
||||
move.
|
||||
Increment records_written only if _flush_write was able to write
|
||||
something.
|
||||
* tests/multiv06.at: New testcase.
|
||||
* tests/Makefile.am, test/testsuite.at: Add tests/multiv06.at
|
||||
|
||||
2008-06-26 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* configure.ac, NEWS: Version 1.20.90
|
||||
* doc/tar.texi: Document -J, --no-auto-compress, etc.
|
||||
* src/buffer.c (ct_tar): New constant.
|
||||
(magic): Add lzop support. Proposed by Kevin Day
|
||||
<thekevinday@gmail.com>.
|
||||
(check_compressed_archive): Do not use autodetect if the
|
||||
compression program was specified explicitly.
|
||||
Fall back to analyzing archive name, if the autodetection fails.
|
||||
* src/suffix.c: Add .lzo
|
||||
* src/tar.c: New options --lzop and --no-auto-compress.
|
||||
New short option -J (alias for --lzma).
|
||||
|
||||
* src/buffer.c (try_new_volume): Print more information with error
|
||||
diagnostics.
|
||||
(_gnu_flush_write): Improve error checking. Adjust
|
||||
real_s_sizeleft before calling new_volume to avoid creating
|
||||
malformed multivolume headers.
|
||||
* tests/delete05.at, tests/gzip.at, tests/ignfail.at,
|
||||
tests/longv7.at, tests/lustar01.at, tests/lustar02.at,
|
||||
tests/shortfile.at: Update to match new diagnostic wording
|
||||
(see 2008-05-06).
|
||||
|
||||
* NEWS: Update.
|
||||
|
||||
2008-06-14 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/tar.texi (exclude): Document support for new VCS.
|
||||
* THANKS: Update.
|
||||
* NEWS: Update.
|
||||
* tests/multiv05.at: Fix typos.
|
||||
* tests/volsize.at: Remove a TZ dependency.
|
||||
|
||||
2008-06-14 Dan Drake <dan@dandrake.org> (tiny change)
|
||||
|
||||
* src/tar.c (exclude_vcs_files): Support for Bazaar, Mercurial and
|
||||
Darcs.
|
||||
|
||||
2008-05-06 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/tar.c (main): Reword the "delayed error" message. New
|
||||
wording proposed by Karl Berry.
|
||||
|
||||
2008-02-20 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* 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-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 +419,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 +438,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
|
||||
|
||||
136
NEWS
136
NEWS
@@ -1,6 +1,138 @@
|
||||
GNU tar NEWS - User visible changes. 2007-10-10
|
||||
GNU tar NEWS - User visible changes. 2008-12-27
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
version 1.21 - Sergey Poznyakoff, 2008-12-27
|
||||
|
||||
* New short option -J
|
||||
|
||||
A shortcut for --lzma.
|
||||
|
||||
* New option --lzop
|
||||
|
||||
* New option --no-auto-compress
|
||||
|
||||
Cancels the effect of previous --auto-compress (-a) option.
|
||||
|
||||
* New option --no-null
|
||||
|
||||
Cancels the effect of previous --null option.
|
||||
|
||||
* Compressed format recognition
|
||||
|
||||
If tar is unable to determine archive compression format, it falls
|
||||
back to using archive suffix to determine it.
|
||||
|
||||
* VCS support.
|
||||
|
||||
Using --exclude-vcs handles also files used internally by Bazaar,
|
||||
Mercurial and Darcs.
|
||||
|
||||
* Transformation scope flags
|
||||
|
||||
Name transformation expressions understand additional flags that
|
||||
control type of archive members affected by them. The flags are:
|
||||
|
||||
- r
|
||||
Apply transformation to regular archive members.
|
||||
|
||||
- s
|
||||
Apply transformation to symbolic link targets.
|
||||
|
||||
- h
|
||||
Apply transformation to hard link targets.
|
||||
|
||||
Corresponding upper-case letters negate the meaning, so that
|
||||
`H' means ``do not apply transformation to hard link targets.''
|
||||
|
||||
The scope flags are listed in the third part of an `s' expression,
|
||||
e.g.:
|
||||
|
||||
tar --transform 's|^|/usr/local/|S'
|
||||
|
||||
Default is `rsh', which means that transformations are applied to
|
||||
both regular archive members and to the targets of symbolic and hard
|
||||
links. If several transform expressions are used, the default flags
|
||||
can be changed using `flags=' statement before the expressions, e.g.:
|
||||
|
||||
tar --transform 'flags=S;s|^|/usr/local/|S'
|
||||
|
||||
* Bugfixes
|
||||
|
||||
** The --null option disabled handling of tar options in list files. This
|
||||
is fixed.
|
||||
** Fixed record size autodetection. If detected record size differs from
|
||||
the expected value (either default, or set on the command line), tar
|
||||
always prints a warning if verbosity level is set to 1 or greater,
|
||||
i.e. if either -t or -v option is given.
|
||||
|
||||
|
||||
|
||||
version 1.20 - Sergey Poznyakoff, 2008-04-14
|
||||
|
||||
* 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.
|
||||
|
||||
* Incremental archives
|
||||
|
||||
Improved (sped up) extracting from incremental archives.
|
||||
|
||||
* 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 +1064,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.
|
||||
|
||||
|
||||
11
THANKS
11
THANKS
@@ -102,9 +102,11 @@ Clinton Carr clint@netcom.com
|
||||
Conrad Hughes chughes@maths.tcd.ie
|
||||
Constantin Belous const@cris.net
|
||||
Coranth Gryphon gryphon@bur.visidyne.com
|
||||
Cyril Strejc strejc@unicontrols.cz
|
||||
Dale R. Worley worley@world.std.com
|
||||
Dale Wiles wiles@geordi.calspan.com
|
||||
Dan Bloch dan@transarc.com
|
||||
Dan Drake dan@dandrake.org
|
||||
Dan Reish dreish@izzy.net
|
||||
Daniel Hagerty hag@gnu.org
|
||||
Daniel Quinlan quinlan@pathname.com
|
||||
@@ -145,12 +147,14 @@ Drew Sullivan drew@sni.ca
|
||||
Drew Trieger trieger@woodstock.abbott.com
|
||||
Dunstan Vavasour dev@cegelecproj.co.uk
|
||||
Ed Childs echilds@bgs.com
|
||||
Ed Leaver ewleaver@comcast.net
|
||||
Edgar Taube et@immd8.informatik.uni-erlangen.de
|
||||
Eduardo Kortright eduardo@cs.ua.edu
|
||||
Eduardo V. de Rivas eddie@asterion.com
|
||||
Edward Welbourne eddy@gen.cam.ac.uk
|
||||
Elmar Heeb heeb@itp.ethz.ch
|
||||
Elmer Fittery elmerf@ptw.com
|
||||
Enric Hernandez ehernandez@notariado.org
|
||||
Eric Backus ericb@lsid.hp.com
|
||||
Eric Benson eb@amazon.com
|
||||
Eric Blake ebb9@byu.net
|
||||
@@ -217,10 +221,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 +296,7 @@ Konno Hiroharu konno@pac.co.jp
|
||||
Kurt Jaeger pi@lf.net
|
||||
Larry Creech lcreech@lonestar.rcclub.org
|
||||
Larry Schwimmer rosebud@cyclone.stanford.edu
|
||||
Lasse Collin lasse.collin@tukaani.org
|
||||
Laurent Caillat-Vallet caillat@noe.lyon.cemagref.fr
|
||||
Laurent Sainte-Marthe smarthe@genethon.fr
|
||||
Leland Lucius llucius@tiny.net
|
||||
|
||||
152
bootstrap
152
bootstrap
@@ -49,9 +49,9 @@ Options:
|
||||
--force Attempt to bootstrap even if the sources seem
|
||||
not to have been checked out.
|
||||
--skip-po Do not download po files.
|
||||
--update-po[=LANG] Update po file(s) and exit.
|
||||
--update-po Update po files and exit.
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
the paxutils repository.
|
||||
|
||||
If the file bootstrap.conf exists in the current working directory, its
|
||||
contents are read as shell variables to configure the bootstrap.
|
||||
@@ -69,24 +69,34 @@ checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
case ${CVS_AUTH-pserver} in
|
||||
pserver)
|
||||
CVS_PREFIX=':pserver:anonymous@';;
|
||||
ssh)
|
||||
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
|
||||
*)
|
||||
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
case $1 in
|
||||
paxutils)
|
||||
case ${CVS_AUTH-pserver} in
|
||||
pserver)
|
||||
CVS_PREFIX=':pserver:anonymous@';;
|
||||
ssh)
|
||||
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
|
||||
*)
|
||||
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
case $CVS_RSH in
|
||||
'') CVS_RSH=ssh; export CVS_RSH;;
|
||||
case $CVS_RSH in
|
||||
'') CVS_RSH=ssh; export CVS_RSH;;
|
||||
esac
|
||||
|
||||
CVSURL=${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1"
|
||||
;;
|
||||
|
||||
gnulib)
|
||||
CVSURL=:pserver:anonymous@pserver.git.sv.gnu.org:/gnulib.git
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
trap "cleanup $1" 1 2 13 15
|
||||
|
||||
cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1" co $1 ||
|
||||
cleanup $1
|
||||
cvs -z3 -q -d $CVSURL co $1 || cleanup $1
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
@@ -106,11 +116,13 @@ gnulib_modules=
|
||||
# Any gnulib files needed that are not in modules.
|
||||
gnulib_files=
|
||||
|
||||
# Translation Project URL, for the registry of all projects
|
||||
# and for the translation-team master directory.
|
||||
tp_url() {
|
||||
echo "http://translationproject.org/domain/$1.html"
|
||||
}
|
||||
# The command to download all .po files for a specified domain into
|
||||
# a specified directory. Fill in the first %s is the domain name, and
|
||||
# the second with the destination directory. Use rsync's -L and -r
|
||||
# options because the latest/%s directory and the .po files within are
|
||||
# all symlinks.
|
||||
po_download_command_format=\
|
||||
"rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
|
||||
|
||||
extract_package_name='
|
||||
/^AC_INIT(/{
|
||||
@@ -213,78 +225,60 @@ echo "$0: Bootstrapping CVS $package..."
|
||||
|
||||
# Get translations.
|
||||
|
||||
get_translations() {
|
||||
download_po_files() {
|
||||
subdir=$1
|
||||
domain=$2
|
||||
po_file=$3
|
||||
|
||||
case $WGET_COMMAND in
|
||||
'')
|
||||
echo "$0: wget not available; skipping translations";;
|
||||
?*)
|
||||
url=`tp_url $domain`
|
||||
baseurl=`expr "$url" : '\(.*\)/.*'`
|
||||
echo "$0: getting translations into $subdir for $domain..." &&
|
||||
case $po_file in
|
||||
'') (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`);;
|
||||
esac &&
|
||||
|
||||
$WGET_COMMAND -O "$subdir/$domain.html" "$url" &&
|
||||
|
||||
sed -n 's|.*href="\(.*\)/\([^/][^/]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\2:\3:\1|p' <"$subdir/$domain.html" |
|
||||
sort -t: -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
|
||||
awk -F: '
|
||||
{ if (lang && $1 != lang) print lang, ver, $3 }
|
||||
{ lang = $1; ver = $2 }
|
||||
END { if (lang) print lang, ver, $3 }
|
||||
' | awk -v domain="$domain" -v baseurl="$baseurl" -v subdir="$subdir" \
|
||||
-v po_file="$po_file" '
|
||||
{
|
||||
lang = $1
|
||||
if (po_file && po_file != (lang ".po")) next
|
||||
ver = $2
|
||||
printf "{ $WGET_COMMAND -O %s/%s.po %s/%s/%s/%s-%s.%s.po &&\n", subdir, lang, baseurl, $3, lang, domain, ver, lang
|
||||
printf " msgfmt -c -o /dev/null %s/%s.po || {\n", subdir, lang
|
||||
printf " echo >&2 '\'"$0"': omitting translation for %s'\''\n", lang
|
||||
printf " rm -f %s/%s.po; }; } &&\n", subdir, lang
|
||||
}
|
||||
END { print ":" }
|
||||
' | WGET_COMMAND="$WGET_COMMAND" sh
|
||||
;;
|
||||
esac &&
|
||||
ls "$subdir"/*.po 2>/dev/null |
|
||||
sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
|
||||
rm -f "$subdir/$domain.html"
|
||||
echo "$0: getting translations into $subdir for $domain..."
|
||||
cmd=`printf "$po_download_command_format" "$domain" "$subdir"`
|
||||
eval "$cmd"
|
||||
}
|
||||
|
||||
case `wget --help` in
|
||||
*'--no-cache'*)
|
||||
WGET_COMMAND='wget -nv --no-cache';;
|
||||
*'--cache=on/off'*)
|
||||
WGET_COMMAND='wget -nv --cache=off';;
|
||||
*'--non-verbose'*)
|
||||
WGET_COMMAND='wget -nv';;
|
||||
*)
|
||||
WGET_COMMAND='';;
|
||||
esac
|
||||
# Download .po files to $po_dir/.reference and copy only the new
|
||||
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
|
||||
update_po_files() {
|
||||
# Directory containing primary .po files.
|
||||
# Overwrite them only when we're sure a .po file is new.
|
||||
po_dir=$1
|
||||
domain=$2
|
||||
|
||||
# Download *.po files into this dir.
|
||||
# Usually contains *.s1 checksum files.
|
||||
ref_po_dir="$po_dir/.reference"
|
||||
|
||||
test -d $ref_po_dir || mkdir $ref_po_dir || return
|
||||
download_po_files $ref_po_dir $domain \
|
||||
&& ls "$ref_po_dir"/*.po 2>/dev/null |
|
||||
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
|
||||
|
||||
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
|
||||
test "$langs" = '*' && langs=x
|
||||
for po in `cd $ref_po_dir && echo *.po|sed 's/\.po//g'`; do
|
||||
case $po in x) continue;; esac
|
||||
new_po="$ref_po_dir/$po.po"
|
||||
cksum_file="$ref_po_dir/$po.s1"
|
||||
if ! test -f "$cksum_file" ||
|
||||
! test -f "$po_dir/$po.po" ||
|
||||
! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
|
||||
echo "updated $po_dir/$po.po..."
|
||||
cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
'skip')
|
||||
;;
|
||||
'')
|
||||
get_translations po $package || exit
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
;;
|
||||
'only')
|
||||
get_translations po $package
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
exit
|
||||
;;
|
||||
*.po)
|
||||
get_translations po $package "$DOWNLOAD_PO"
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
get_translations po $package "${DOWNLOAD_PO}.po"
|
||||
exit
|
||||
esac
|
||||
|
||||
# Get paxutils files.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Configure template for GNU tar.
|
||||
# Configure template for GNU tar. -*- autoconf -*-
|
||||
|
||||
# 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.21], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
@@ -87,7 +87,7 @@ gl_INIT
|
||||
# paxutils modules
|
||||
tar_PAXUTILS
|
||||
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink strerror symlink setlocale utimes)
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
|
||||
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
|
||||
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
||||
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
||||
|
||||
@@ -31,7 +31,7 @@ tar_TEXINFOS = \
|
||||
snapshot.texi\
|
||||
sparse.texi\
|
||||
value.texi
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
|
||||
|
||||
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
|
||||
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
@@ -46,6 +46,18 @@ header.texi: $(top_srcdir)/src/tar.h
|
||||
master-menu: $(tar_TEXINFOS)
|
||||
emacs -batch -l mastermenu.el -f make-master-menu $(info_TEXINFOS)
|
||||
|
||||
untabify:
|
||||
emacs -batch -l untabify.el $(info_TEXINFOS) $(tar_TEXINFOS)
|
||||
|
||||
final: untabify master-menu
|
||||
|
||||
# Checking
|
||||
check-format:
|
||||
@if test -n "`cat $(info_TEXINFOS) $(tar_TEXINFOS) | tr -d -c '\t'`"; then \
|
||||
echo "Sources contain tabs; run make untabify"; \
|
||||
false; \
|
||||
fi
|
||||
|
||||
check-options:
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
|
||||
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
@@ -67,6 +79,52 @@ doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
fi;\
|
||||
rm report.$$$$
|
||||
|
||||
check-refs:
|
||||
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
|
||||
do \
|
||||
sed -e = $$file | \
|
||||
sed -n 'N;/@FIXME-.*ref/{s/\(^[0-9][0-9]*\).*@FIXME-.*ref{\([^}]*\).*/'$$file':\1: \2/gp}'; \
|
||||
done > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unresolved cross-references:"; \
|
||||
cat $@-t;\
|
||||
rm $@-t; \
|
||||
else \
|
||||
rm -f $@-t; \
|
||||
fi
|
||||
|
||||
check-fixmes:
|
||||
@for file in $(info_TEXINFOS); \
|
||||
do \
|
||||
sed -e = $$file | \
|
||||
sed -n 'N;/@FIXME{/{s/\(^[0-9][0-9]*\).*@FIXME{\([^}]*\).*/'$$file':\1: \2/gp}'; \
|
||||
done > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unresolved FIXMEs:"; \
|
||||
cat $@-t; \
|
||||
rm $@-t; \
|
||||
false; \
|
||||
else \
|
||||
rm -f $@-t; \
|
||||
fi
|
||||
|
||||
check-unrevised:
|
||||
@grep -Hn @UNREVISED $(info_TEXINFOS) > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unrevised nodes:"; \
|
||||
cat $@-t; \
|
||||
rm $@-t; \
|
||||
false;\
|
||||
else \
|
||||
rm $@-t; \
|
||||
fi
|
||||
|
||||
all-check-docs: check-format check-options check-refs check-fixmes check-unrevised
|
||||
|
||||
check-docs:
|
||||
$(MAKE) -k all-check-docs
|
||||
|
||||
#
|
||||
|
||||
clean-local:
|
||||
rm -rf manual
|
||||
@@ -82,5 +140,5 @@ manual:
|
||||
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
|
||||
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
|
||||
$(GENDOCS) tar 'GNU tar manual'
|
||||
$(GENDOCS) --texi2html tar 'GNU tar manual'
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<!-- $Id: gendocs_template,v 1.3 2007/01/19 15:41:39 gray Exp $ -->
|
||||
<!-- $Id: gendocs_template,v 1.5 2007/10/30 14:58:52 gray Exp $ -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<head>
|
||||
@@ -30,23 +30,40 @@
|
||||
alt=" [image of the head of a GNU] "
|
||||
width="129" height="122" />
|
||||
</a>
|
||||
<a href="/philosophy/gif.html">(no gifs due to patent problems)</a>
|
||||
</p>
|
||||
<hr />
|
||||
|
||||
The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="%%PACKAGE%%.html">HTML
|
||||
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
|
||||
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
|
||||
<li><a href="html_node/index.html">HTML</a> - with one web page per
|
||||
node.</li>
|
||||
%%IF HTML_SECTION%%
|
||||
<li><a href="html_section/index.html">HTML</a> - with one web page per
|
||||
section.</li>
|
||||
%%ENDIF HTML_SECTION%%
|
||||
%%IF HTML_CHAPTER%%
|
||||
<li><a href="html_chapter/index.html">HTML</a> - with one web page per
|
||||
chapter.</li>
|
||||
%%ENDIF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
|
||||
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
|
||||
one web page.</li>
|
||||
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
|
||||
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per node.</li>
|
||||
%%IF HTML_SECTION%%
|
||||
<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
|
||||
(%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per section.</li>
|
||||
%%ENDIF HTML_SECTION%%
|
||||
%%IF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
|
||||
(%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per chapter.</li>
|
||||
%%ENDIF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
|
||||
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt">ASCII text
|
||||
@@ -99,7 +116,7 @@ permitted in any medium, provided this notice is preserved.
|
||||
<p>
|
||||
Updated:
|
||||
<!-- timestamp start -->
|
||||
$Date: 2007/01/19 15:41:39 $ $Author: gray $
|
||||
$Date: 2007/10/30 14:58:52 $ $Author: gray $
|
||||
<!-- timestamp end -->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -36,8 +36,6 @@ Archives are permitted to have more than one member with the same
|
||||
member name. One way this situation can occur is if more than one
|
||||
version of a file has been stored in the archive. For information
|
||||
about adding new versions of a file to an archive, see @ref{update}.
|
||||
@FIXME-xref{To learn more about having more than one archive member with the
|
||||
same name, see -backup node, when it's written.}
|
||||
|
||||
In addition to entries describing archive members, an archive may
|
||||
contain entries which @command{tar} itself uses to store information.
|
||||
@@ -108,11 +106,11 @@ group permission could be copied from the @emph{other} permission.
|
||||
|
||||
The @code{uid} and @code{gid} fields are the numeric user and group
|
||||
@acronym{ID} of the file owners, respectively. If the operating system does
|
||||
not support numeric user or group @acronym{ID}s, these fields should be ignored.
|
||||
not support numeric user or group @acronym{ID}s, these fields should
|
||||
be ignored.
|
||||
|
||||
The @code{size} field is the size of the file in bytes; linked files
|
||||
are archived with this field specified as zero. @FIXME-xref{Modifiers, in
|
||||
particular the @option{--incremental} (@option{-G}) option.}
|
||||
are archived with this field specified as zero.
|
||||
|
||||
The @code{mtime} field is the data modification time of the file at
|
||||
the time it was archived. It is the ASCII representation of the octal
|
||||
|
||||
@@ -72,19 +72,28 @@
|
||||
@ifset PROOF
|
||||
@strong{<REF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
@cite{\string\}
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@macro FIXME-pxref{string}
|
||||
@ifset PROOF
|
||||
@strong{<PXREF>} \string\ @strong{</>}
|
||||
See @strong{<PXREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
See @cite{\string\}
|
||||
@end ifclear
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-xref{string}
|
||||
@ifset PROOF
|
||||
@strong{<XREF>} \string\ @strong{</>}
|
||||
See @strong{<XREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
See @cite{\string\}
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@c End of rendition.texi
|
||||
|
||||
788
doc/tar.texi
788
doc/tar.texi
File diff suppressed because it is too large
Load Diff
13
doc/untabify.el
Normal file
13
doc/untabify.el
Normal file
@@ -0,0 +1,13 @@
|
||||
;;;; Untabify the sources.
|
||||
;;;; Usage: emacs -batch -l untabify.el [file ...]
|
||||
|
||||
(defun global-untabify (buflist)
|
||||
(mapcar
|
||||
(lambda (bufname)
|
||||
(set-buffer (find-file bufname))
|
||||
(untabify (point-min) (point-max))
|
||||
(save-buffer)
|
||||
(kill-buffer (current-buffer)))
|
||||
buflist))
|
||||
|
||||
(global-untabify command-line-args-left)
|
||||
@@ -13,6 +13,7 @@ exclude
|
||||
exitfail
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
fseeko
|
||||
ftruncate
|
||||
full-write
|
||||
getdate
|
||||
@@ -38,6 +39,7 @@ safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
setenv
|
||||
snprintf
|
||||
stat-time
|
||||
stdbool
|
||||
stdint
|
||||
|
||||
101
lib/.cvsignore
101
lib/.cvsignore
@@ -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
|
||||
@@ -28,24 +25,31 @@ at-func.c
|
||||
backupfile.c
|
||||
backupfile.h
|
||||
basename.c
|
||||
c-ctype.c
|
||||
c-ctype.h
|
||||
canonicalize-lgpl.c
|
||||
canonicalize.h
|
||||
charset.alias
|
||||
chdir-long.c
|
||||
chdir-long.h
|
||||
chown.c
|
||||
close-stream.c
|
||||
close-stream.h
|
||||
close.c
|
||||
closeout.c
|
||||
closeout.h
|
||||
config.charset
|
||||
configmake.h
|
||||
creat-safer.c
|
||||
dirent_.h
|
||||
dirent.h
|
||||
dirent.in.h
|
||||
dirfd.c
|
||||
dirfd.h
|
||||
dirname.c
|
||||
dirname.h
|
||||
dup-safer.c
|
||||
dup2.c
|
||||
errno.in.h
|
||||
error.c
|
||||
error.h
|
||||
exclude.c
|
||||
@@ -56,31 +60,39 @@ fchdir.c
|
||||
fchmodat.c
|
||||
fchown-stub.c
|
||||
fchownat.c
|
||||
fclose.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 +106,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
|
||||
@@ -122,6 +135,7 @@ obstack.c
|
||||
obstack.h
|
||||
offtostr.c
|
||||
open-safer.c
|
||||
open.c
|
||||
openat-die.c
|
||||
openat-priv.h
|
||||
openat-proc.c
|
||||
@@ -141,8 +155,13 @@ quote.c
|
||||
quote.h
|
||||
quotearg.c
|
||||
quotearg.h
|
||||
rawmemchr.c
|
||||
rawmemchr.valgrind
|
||||
readlink.c
|
||||
realloc.c
|
||||
ref-add.sed
|
||||
ref-add.sin
|
||||
ref-del.sed
|
||||
ref-del.sin
|
||||
regcomp.c
|
||||
regex.c
|
||||
@@ -151,6 +170,7 @@ regex_internal.c
|
||||
regex_internal.h
|
||||
regexec.c
|
||||
rmdir.c
|
||||
rmt-command.h
|
||||
rmt.h
|
||||
rpmatch.c
|
||||
rtapelib.c
|
||||
@@ -166,18 +186,30 @@ savedir.h
|
||||
setenv.c
|
||||
setenv.h
|
||||
sleep.c
|
||||
snprintf.c
|
||||
stat-macros.h
|
||||
stat-time.h
|
||||
stdbool_.h
|
||||
stdint_.h
|
||||
stdio_.h
|
||||
stdlib_.h
|
||||
stdarg.in.h
|
||||
stdbool.h
|
||||
stdbool.in.h
|
||||
stdint.h
|
||||
stdint.in.h
|
||||
stdio-impl.h
|
||||
stdio-write.c
|
||||
stdio.h
|
||||
stdio.in.h
|
||||
stdlib.h
|
||||
stdlib.in.h
|
||||
stpcpy.c
|
||||
strcasecmp.c
|
||||
strchrnul.c
|
||||
strchrnul.valgrind
|
||||
strdup.c
|
||||
streq.h
|
||||
strerror.c
|
||||
string_.h
|
||||
string.h
|
||||
string.in.h
|
||||
strings.in.h
|
||||
stripslash.c
|
||||
strncasecmp.c
|
||||
strndup.c
|
||||
@@ -190,21 +222,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 +260,12 @@ 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
|
||||
write.c
|
||||
xalloc-die.c
|
||||
xalloc.h
|
||||
xgetcwd.c
|
||||
@@ -230,6 +274,7 @@ xmalloc.c
|
||||
xsize.h
|
||||
xstrndup.c
|
||||
xstrndup.h
|
||||
xstrtol-error.c
|
||||
xstrtol.c
|
||||
xstrtol.h
|
||||
xstrtoul.c
|
||||
|
||||
@@ -22,10 +22,13 @@
|
||||
lib/argmatch.c
|
||||
lib/argp-help.c
|
||||
lib/argp-parse.c
|
||||
lib/closeout.c
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
lib/obstack.c
|
||||
lib/human.c
|
||||
lib/obstack.c
|
||||
lib/openat-die.c
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
@@ -34,6 +37,8 @@ lib/rpmatch.c
|
||||
lib/rtapelib.c
|
||||
lib/xalloc-die.c
|
||||
lib/xmalloc.c
|
||||
lib/version-etc.c
|
||||
lib/xalloc-die.c
|
||||
|
||||
rmt/rmt.c
|
||||
|
||||
@@ -51,6 +56,7 @@ src/names.c
|
||||
src/tar.c
|
||||
src/update.c
|
||||
src/xheader.c
|
||||
src/checkpoint.c
|
||||
|
||||
# Testsuite
|
||||
tests/genfile.c
|
||||
|
||||
@@ -23,6 +23,7 @@ bin_PROGRAMS = tar
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
checkpoint.c\
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
@@ -33,6 +34,7 @@ tar_SOURCES = \
|
||||
misc.c\
|
||||
names.c\
|
||||
sparse.c\
|
||||
suffix.c\
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
|
||||
834
src/buffer.c
834
src/buffer.c
File diff suppressed because it is too large
Load Diff
270
src/checkpoint.c
Normal file
270
src/checkpoint.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/* Checkpoint management for tar.
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
|
||||
enum checkpoint_opcode
|
||||
{
|
||||
cop_dot,
|
||||
cop_bell,
|
||||
cop_echo,
|
||||
cop_ttyout,
|
||||
cop_sleep,
|
||||
cop_exec
|
||||
};
|
||||
|
||||
struct checkpoint_action
|
||||
{
|
||||
struct checkpoint_action *next;
|
||||
enum checkpoint_opcode opcode;
|
||||
union
|
||||
{
|
||||
time_t time;
|
||||
char *command;
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Checkpointing counter */
|
||||
static unsigned checkpoint;
|
||||
|
||||
/* List of checkpoint actions */
|
||||
static struct checkpoint_action *checkpoint_action, *checkpoint_action_tail;
|
||||
|
||||
static struct checkpoint_action *
|
||||
alloc_action (enum checkpoint_opcode opcode)
|
||||
{
|
||||
struct checkpoint_action *p = xzalloc (sizeof *p);
|
||||
if (checkpoint_action_tail)
|
||||
checkpoint_action_tail->next = p;
|
||||
else
|
||||
checkpoint_action = p;
|
||||
checkpoint_action_tail = p;
|
||||
p->opcode = opcode;
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *
|
||||
copy_string_unquote (const char *str)
|
||||
{
|
||||
char *output = xstrdup (str);
|
||||
size_t len = strlen (output);
|
||||
if ((*output == '"' || *output == '\'')
|
||||
&& output[len-1] == *output)
|
||||
{
|
||||
memmove (output, output+1, len-2);
|
||||
output[len-2] = 0;
|
||||
}
|
||||
unquote_string (output);
|
||||
return output;
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_compile_action (const char *str)
|
||||
{
|
||||
struct checkpoint_action *act;
|
||||
|
||||
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
|
||||
alloc_action (cop_dot);
|
||||
else 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);
|
||||
}
|
||||
|
||||
60
src/common.h
60
src/common.h
@@ -1,7 +1,7 @@
|
||||
/* Common declarations for the tar program.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -93,9 +93,6 @@ GLOBAL enum subcommand subcommand_option;
|
||||
/* Selected format for output archive. */
|
||||
GLOBAL enum archive_format archive_format;
|
||||
|
||||
/* Either NL or NUL, as decided by the --null option. */
|
||||
GLOBAL char filename_terminator;
|
||||
|
||||
/* Size of each record, once in blocks, once in bytes. Those two variables
|
||||
are always related, the second being BLOCKSIZE times the first. They do
|
||||
not have _option in their name, even if their values is derived from
|
||||
@@ -130,19 +127,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 +185,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 +486,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);
|
||||
@@ -696,8 +699,7 @@ char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
|
||||
|
||||
void sys_detect_dev_null_output (void);
|
||||
void sys_save_archive_dev_ino (void);
|
||||
void sys_drain_input_pipe (void);
|
||||
void sys_wait_for_child (pid_t);
|
||||
void sys_wait_for_child (pid_t, bool);
|
||||
void sys_spawn_shell (void);
|
||||
bool sys_compare_uid (struct stat *a, struct stat *b);
|
||||
bool sys_compare_gid (struct stat *a, struct stat *b);
|
||||
@@ -711,6 +713,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, ...);
|
||||
@@ -729,14 +734,21 @@ bool string_ascii_p (const char *str);
|
||||
bool utf8_convert (bool to_utf, char const *input, char **output);
|
||||
|
||||
/* Module transform.c */
|
||||
typedef enum
|
||||
{
|
||||
xform_regfile,
|
||||
xform_link,
|
||||
xform_symlink
|
||||
} xform_type;
|
||||
#define XFORM_REGFILE 0x01
|
||||
#define XFORM_LINK 0x02
|
||||
#define XFORM_SYMLINK 0x04
|
||||
#define XFORM_ALL (XFORM_REGFILE|XFORM_LINK|XFORM_SYMLINK)
|
||||
|
||||
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 *);
|
||||
bool transform_name (char **pinput, int type);
|
||||
bool transform_member_name (char **pinput, int type);
|
||||
bool transform_name_fp (char **pinput, int type,
|
||||
char *(*fun)(char *, void *), void *);
|
||||
|
||||
/* Module suffix.c */
|
||||
void set_comression_program_by_suffix (const char *name, const char *defprog);
|
||||
|
||||
/* Module checkpoint.c */
|
||||
void checkpoint_compile_action (const char *str);
|
||||
void checkpoint_finish_compile (void);
|
||||
void checkpoint_run (bool do_write);
|
||||
|
||||
@@ -366,7 +366,7 @@ dumpdir_cmp (const char *a, const char *b)
|
||||
static void
|
||||
diff_dumpdir (void)
|
||||
{
|
||||
char *dumpdir_buffer;
|
||||
const char *dumpdir_buffer;
|
||||
dev_t dev = 0;
|
||||
struct stat stat_data;
|
||||
|
||||
@@ -597,9 +597,23 @@ verify_volume (void)
|
||||
"VERIFY FAILURE: %d invalid headers detected",
|
||||
counter), counter));
|
||||
}
|
||||
if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE)
|
||||
if (status == HEADER_END_OF_FILE)
|
||||
break;
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
if (!ignore_zeros_option)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
}
|
||||
}
|
||||
|
||||
diff_archive ();
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
}
|
||||
|
||||
12
src/create.c
12
src/create.c
@@ -1041,7 +1041,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
while (size_left > 0)
|
||||
{
|
||||
size_t bufsize, count;
|
||||
|
||||
|
||||
mv_size_left (size_left);
|
||||
|
||||
blk = find_next_block ();
|
||||
@@ -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;
|
||||
@@ -1493,7 +1495,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
assign_string (&st->file_name,
|
||||
safer_name_suffix (p, false, absolute_names_option));
|
||||
|
||||
transform_name (&st->file_name);
|
||||
transform_name (&st->file_name, XFORM_REGFILE);
|
||||
|
||||
if (deref_stat (dereference_option, p, &st->stat) != 0)
|
||||
{
|
||||
@@ -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, XFORM_SYMLINK);
|
||||
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 */
|
||||
|
||||
@@ -917,7 +917,6 @@ extract_link (char *file_name, int typeflag)
|
||||
int interdir_made = 0;
|
||||
char const *link_name;
|
||||
|
||||
transform_member_name (¤t_stat_info.link_name, xform_link);
|
||||
link_name = current_stat_info.link_name;
|
||||
|
||||
if (! absolute_names_option && contains_dot_dot (link_name))
|
||||
@@ -974,8 +973,6 @@ extract_symlink (char *file_name, int typeflag)
|
||||
int status;
|
||||
int interdir_made = 0;
|
||||
|
||||
transform_member_name (¤t_stat_info.link_name, xform_symlink);
|
||||
|
||||
if (! absolute_names_option
|
||||
&& (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
|
||||
|| contains_dot_dot (current_stat_info.link_name)))
|
||||
|
||||
394
src/incremen.c
394
src/incremen.c
@@ -1,7 +1,7 @@
|
||||
/* GNU dump extensions to tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -49,14 +49,23 @@ 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 directory *next;
|
||||
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 */
|
||||
@@ -64,9 +73,132 @@ struct directory
|
||||
the original directory structure */
|
||||
const char *tagfile; /* Tag file, if the directory falls under
|
||||
exclusion_tag_under */
|
||||
char name[1]; /* file name of directory */
|
||||
char *name; /* file name of directory */
|
||||
};
|
||||
|
||||
struct dumpdir *
|
||||
dumpdir_create0 (const char *contents, const char *cmask)
|
||||
{
|
||||
struct dumpdir *dump;
|
||||
size_t i, total, ctsize, len;
|
||||
char *p;
|
||||
const char *q;
|
||||
|
||||
for (i = 0, total = 0, ctsize = 1, q = contents; *q; total++, q += len)
|
||||
{
|
||||
len = strlen (q) + 1;
|
||||
ctsize += len;
|
||||
if (!cmask || strchr (cmask, *q))
|
||||
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 struct directory *dirhead, *dirtail;
|
||||
static Hash_table *directory_table;
|
||||
static Hash_table *directory_meta_table;
|
||||
|
||||
@@ -118,27 +250,78 @@ static struct directory *
|
||||
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;
|
||||
struct directory *directory = xmalloc (sizeof (*directory));
|
||||
directory->next = 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 (name[namelen - 1]))
|
||||
namelen--;
|
||||
directory->name = xmalloc (namelen + 1);
|
||||
memcpy (directory->name, name, namelen);
|
||||
directory->name[namelen] = 0;
|
||||
directory->tagfile = NULL;
|
||||
return directory;
|
||||
}
|
||||
|
||||
static void
|
||||
free_directory (struct directory *dir)
|
||||
{
|
||||
free (dir->name);
|
||||
free (dir);
|
||||
}
|
||||
|
||||
static struct directory *
|
||||
attach_directory (const char *name)
|
||||
{
|
||||
struct directory *dir = make_directory (name);
|
||||
if (dirtail)
|
||||
dirtail->next = dir;
|
||||
else
|
||||
dirhead = dir;
|
||||
dirtail = dir;
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen)
|
||||
{
|
||||
char *name = *pname;
|
||||
size_t nlen = strlen (name);
|
||||
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
|
||||
{
|
||||
if (rlen > slen)
|
||||
{
|
||||
name = xrealloc (name, nlen - slen + rlen + 1);
|
||||
*pname = name;
|
||||
}
|
||||
memmove (name + rlen, name + slen, nlen - slen + 1);
|
||||
memcpy (name, repl, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dirlist_replace_prefix (const char *pref, const char *repl)
|
||||
{
|
||||
struct directory *dp;
|
||||
size_t pref_len = strlen (pref);
|
||||
size_t repl_len = strlen (repl);
|
||||
for (dp = dirhead; dp; dp = dp->next)
|
||||
replace_prefix (&dp->name, pref, pref_len, repl, repl_len);
|
||||
}
|
||||
|
||||
/* Create and link a new directory entry for directory NAME, having a
|
||||
device number DEV and an inode number INO, with NFS indicating
|
||||
whether it is an NFS device and FOUND indicating whether we have
|
||||
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);
|
||||
struct directory *directory = attach_directory (name);
|
||||
|
||||
directory->mtime = mtime;
|
||||
directory->device_number = dev;
|
||||
@@ -149,13 +332,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,
|
||||
@@ -185,7 +364,7 @@ find_directory (const char *name)
|
||||
{
|
||||
struct directory *dir = make_directory (name);
|
||||
struct directory *ret = hash_lookup (directory_table, dir);
|
||||
free (dir);
|
||||
free_directory (dir);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -204,7 +383,7 @@ find_directory_meta (dev_t dev, ino_t ino)
|
||||
dir->device_number = dev;
|
||||
dir->inode_number = ino;
|
||||
ret = hash_lookup (directory_meta_table, dir);
|
||||
free (dir);
|
||||
free_directory (dir);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -250,7 +429,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))
|
||||
{
|
||||
@@ -259,12 +439,16 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
stat_data->st_ino);
|
||||
if (d)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
if (strcmp (d->name, name_buffer))
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
dirlist_replace_prefix (d->name, name_buffer);
|
||||
}
|
||||
directory->children = CHANGED_CHILDREN;
|
||||
}
|
||||
else
|
||||
@@ -299,12 +483,16 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
|
||||
if (d)
|
||||
{
|
||||
if (verbose)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
if (strcmp (d->name, name_buffer))
|
||||
{
|
||||
if (verbose)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
dirlist_replace_prefix (d->name, name_buffer);
|
||||
}
|
||||
directory->children = CHANGED_CHILDREN;
|
||||
}
|
||||
else
|
||||
@@ -336,8 +524,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 +543,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 +558,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 +578,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 +614,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 +630,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 +645,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 +669,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 +729,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);
|
||||
@@ -622,12 +762,9 @@ obstack_code_rename (struct obstack *stk, char *from, char *to)
|
||||
obstack_grow (stk, s, strlen (s) + 1);
|
||||
}
|
||||
|
||||
static bool
|
||||
rename_handler (void *data, void *proc_data)
|
||||
static void
|
||||
store_rename (struct directory *dir, struct obstack *stk)
|
||||
{
|
||||
struct directory *dir = data;
|
||||
struct obstack *stk = proc_data;
|
||||
|
||||
if (DIR_IS_RENAMED (dir))
|
||||
{
|
||||
struct directory *prev, *p;
|
||||
@@ -666,7 +803,6 @@ rename_handler (void *data, void *proc_data)
|
||||
obstack_code_rename (stk, "", prev->name);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *
|
||||
@@ -674,8 +810,9 @@ append_incremental_renames (const char *dump)
|
||||
{
|
||||
struct obstack stk;
|
||||
size_t size;
|
||||
|
||||
if (directory_table == NULL)
|
||||
struct directory *dp;
|
||||
|
||||
if (dirhead == NULL)
|
||||
return dump;
|
||||
|
||||
obstack_init (&stk);
|
||||
@@ -687,7 +824,9 @@ append_incremental_renames (const char *dump)
|
||||
else
|
||||
size = 0;
|
||||
|
||||
hash_do_for_each (directory_table, rename_handler, &stk);
|
||||
for (dp = dirhead; dp; dp = dp->next)
|
||||
store_rename (dp, &stk);
|
||||
|
||||
if (obstack_object_size (&stk) != size)
|
||||
{
|
||||
obstack_1grow (&stk, 0);
|
||||
@@ -1171,14 +1310,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 +1507,7 @@ try_purge_directory (char const *directory_name)
|
||||
char *current_dir;
|
||||
char *cur, *arc, *p;
|
||||
char *temp_stub = NULL;
|
||||
struct dumpdir *dump;
|
||||
|
||||
if (!is_dumpdir (¤t_stat_info))
|
||||
return false;
|
||||
@@ -1417,12 +1559,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 +1584,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 +1606,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 +1632,8 @@ try_purge_directory (char const *directory_name)
|
||||
}
|
||||
}
|
||||
free (p);
|
||||
|
||||
dumpdir_free (dump);
|
||||
|
||||
free (current_dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
27
src/list.c
27
src/list.c
@@ -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)
|
||||
{
|
||||
@@ -472,11 +472,11 @@ read_header (bool raw_extended_headers)
|
||||
static char *
|
||||
decode_xform (char *file_name, void *data)
|
||||
{
|
||||
xform_type type = *(xform_type*)data;
|
||||
int type = *(int*)data;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case xform_symlink:
|
||||
case XFORM_SYMLINK:
|
||||
/* FIXME: It is not quite clear how and to which extent are the symbolic
|
||||
links subject to filename transformation. In the absence of another
|
||||
solution, symbolic links are exempt from component stripping and
|
||||
@@ -484,11 +484,11 @@ decode_xform (char *file_name, void *data)
|
||||
proper. */
|
||||
return file_name;
|
||||
|
||||
case xform_link:
|
||||
case XFORM_LINK:
|
||||
file_name = safer_name_suffix (file_name, true, absolute_names_option);
|
||||
break;
|
||||
|
||||
case xform_regfile:
|
||||
case XFORM_REGFILE:
|
||||
file_name = safer_name_suffix (file_name, false, absolute_names_option);
|
||||
break;
|
||||
}
|
||||
@@ -505,9 +505,9 @@ decode_xform (char *file_name, void *data)
|
||||
}
|
||||
|
||||
bool
|
||||
transform_member_name (char **pinput, xform_type type)
|
||||
transform_member_name (char **pinput, int type)
|
||||
{
|
||||
return transform_name_fp (pinput, decode_xform, &type);
|
||||
return transform_name_fp (pinput, type, decode_xform, &type);
|
||||
}
|
||||
|
||||
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
|
||||
@@ -628,7 +628,16 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
stat_info->is_dumpdir = true;
|
||||
}
|
||||
|
||||
transform_member_name (&stat_info->file_name, xform_regfile);
|
||||
transform_member_name (&stat_info->file_name, XFORM_REGFILE);
|
||||
switch (header->header.typeflag)
|
||||
{
|
||||
case SYMTYPE:
|
||||
transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
|
||||
break;
|
||||
|
||||
case LNKTYPE:
|
||||
transform_member_name (&stat_info->link_name, XFORM_LINK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert buffer at WHERE0 of size DIGS from external format to
|
||||
|
||||
16
src/names.c
16
src/names.c
@@ -289,9 +289,8 @@ static int matching_flags; /* exclude_fnmatch options */
|
||||
static storage and can't be relied upon across two calls.
|
||||
|
||||
If CHANGE_DIRS is true, treat any entries of type NELT_CHDIR as
|
||||
the request to change to the given directory. If filename_terminator
|
||||
is NUL, CHANGE_DIRS is effectively always false.
|
||||
|
||||
the request to change to the given directory.
|
||||
|
||||
Entries of type NELT_FMASK cause updates of the matching_flags
|
||||
value. */
|
||||
struct name_elt *
|
||||
@@ -301,9 +300,6 @@ name_next_elt (int change_dirs)
|
||||
const char *source;
|
||||
char *cursor;
|
||||
|
||||
if (filename_terminator == '\0')
|
||||
change_dirs = 0;
|
||||
|
||||
while (name_index != names)
|
||||
{
|
||||
struct name_elt *ep;
|
||||
@@ -392,9 +388,7 @@ name_gather (void)
|
||||
if (allocated_size == 0)
|
||||
{
|
||||
allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1;
|
||||
buffer = xmalloc (allocated_size);
|
||||
/* FIXME: This memset is overkill, and ugly... */
|
||||
memset (buffer, 0, allocated_size);
|
||||
buffer = xzalloc (allocated_size);
|
||||
}
|
||||
|
||||
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
|
||||
@@ -734,7 +728,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 +740,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;
|
||||
|
||||
|
||||
79
src/suffix.c
Normal file
79
src/suffix.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* 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) },
|
||||
{ S(lzo, lzop) },
|
||||
#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;
|
||||
}
|
||||
|
||||
96
src/system.c
96
src/system.c
@@ -1,6 +1,7 @@
|
||||
/* System-dependent calls for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 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
|
||||
@@ -17,7 +18,6 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <setenv.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <rmt.h>
|
||||
@@ -52,12 +52,7 @@ sys_detect_dev_null_output (void)
|
||||
}
|
||||
|
||||
void
|
||||
sys_drain_input_pipe (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_for_child (pid_t child_pid)
|
||||
sys_wait_for_child (pid_t child_pid, bool eof)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -161,26 +156,8 @@ sys_detect_dev_null_output (void)
|
||||
&& archive_stat.st_ino == dev_null_stat.st_ino));
|
||||
}
|
||||
|
||||
/* Manage to fully drain a pipe we might be reading, so to not break it on
|
||||
the producer after the EOF block. FIXME: one of these days, GNU tar
|
||||
might become clever enough to just stop working, once there is no more
|
||||
work to do, we might have to revise this area in such time. */
|
||||
|
||||
void
|
||||
sys_drain_input_pipe (void)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
if (access_mode == ACCESS_READ
|
||||
&& ! _isrmt (archive)
|
||||
&& (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
|
||||
while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
|
||||
&& r != SAFE_READ_ERROR)
|
||||
continue;
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_for_child (pid_t child_pid)
|
||||
sys_wait_for_child (pid_t child_pid, bool eof)
|
||||
{
|
||||
if (child_pid)
|
||||
{
|
||||
@@ -194,8 +171,11 @@ sys_wait_for_child (pid_t child_pid)
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
ERROR ((0, 0, _("Child died with signal %d"),
|
||||
WTERMSIG (wait_status)));
|
||||
{
|
||||
int sig = WTERMSIG (wait_status);
|
||||
if (!(!eof && sig == SIGPIPE))
|
||||
ERROR ((0, 0, _("Child died with signal %d"), sig));
|
||||
}
|
||||
else if (WEXITSTATUS (wait_status) != 0)
|
||||
ERROR ((0, 0, _("Child returned status %d"),
|
||||
WEXITSTATUS (wait_status)));
|
||||
@@ -773,9 +753,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 +766,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 +781,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 +805,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 +825,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 */
|
||||
|
||||
166
src/tar.c
166
src/tar.c
@@ -249,8 +249,11 @@ enum
|
||||
ANCHORED_OPTION = CHAR_MAX + 1,
|
||||
ATIME_PRESERVE_OPTION,
|
||||
BACKUP_OPTION,
|
||||
CHECK_DEVICE_OPTION,
|
||||
CHECKPOINT_OPTION,
|
||||
CHECKPOINT_ACTION_OPTION,
|
||||
DELAY_DIRECTORY_RESTORE_OPTION,
|
||||
HARD_DEREFERENCE_OPTION,
|
||||
DELETE_OPTION,
|
||||
EXCLUDE_CACHES_OPTION,
|
||||
EXCLUDE_CACHES_UNDER_OPTION,
|
||||
@@ -268,13 +271,17 @@ enum
|
||||
IGNORE_FAILED_READ_OPTION,
|
||||
INDEX_FILE_OPTION,
|
||||
KEEP_NEWER_FILES_OPTION,
|
||||
LZOP_OPTION,
|
||||
MODE_OPTION,
|
||||
MTIME_OPTION,
|
||||
NEWER_MTIME_OPTION,
|
||||
NO_ANCHORED_OPTION,
|
||||
NO_AUTO_COMPRESS_OPTION,
|
||||
NO_CHECK_DEVICE_OPTION,
|
||||
NO_DELAY_DIRECTORY_RESTORE_OPTION,
|
||||
NO_IGNORE_CASE_OPTION,
|
||||
NO_IGNORE_COMMAND_ERROR_OPTION,
|
||||
NO_NULL_OPTION,
|
||||
NO_OVERWRITE_DIR_OPTION,
|
||||
NO_QUOTE_CHARS_OPTION,
|
||||
NO_RECURSION_OPTION,
|
||||
@@ -345,7 +352,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 DEIQY and eqy. Consider the following
|
||||
assignments:
|
||||
|
||||
[For Solaris tar compatibility =/= Is it important at all?]
|
||||
@@ -408,6 +415,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 +587,34 @@ 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 },
|
||||
{"no-auto-compress", NO_AUTO_COMPRESS_OPTION, 0, 0,
|
||||
N_("do not use 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", 'J', 0, 0,
|
||||
N_("filter the archive through lzma"), GRID+1 },
|
||||
{"lzop", LZOP_OPTION, 0, 0,
|
||||
N_("filter the archive through lzop"), GRID+8 },
|
||||
{"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 },
|
||||
|
||||
@@ -599,6 +626,8 @@ static struct argp_option options[] = {
|
||||
N_("get names to extract or create from FILE"), GRID+1 },
|
||||
{"null", NULL_OPTION, 0, 0,
|
||||
N_("-T reads null-terminated names, disable -C"), GRID+1 },
|
||||
{"no-null", NO_NULL_OPTION, 0, 0,
|
||||
N_("disable the effect of the previous --null option"), GRID+1 },
|
||||
{"unquote", UNQUOTE_OPTION, 0, 0,
|
||||
N_("unquote filenames read with -T (default)"), GRID+1 },
|
||||
{"no-unquote", NO_UNQUOTE_OPTION, 0, 0,
|
||||
@@ -634,6 +663,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 +678,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,
|
||||
@@ -655,9 +686,10 @@ static struct argp_option options[] = {
|
||||
GRID+1 },
|
||||
{"transform", TRANSFORM_OPTION, N_("EXPRESSION"), 0,
|
||||
N_("use sed replace EXPRESSION to transform file names"), GRID+1 },
|
||||
{"xform", 0, 0, OPTION_ALIAS, NULL, 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 +711,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 +755,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 +763,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 +820,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 */
|
||||
};
|
||||
|
||||
|
||||
@@ -822,6 +859,16 @@ exclude_vcs_files ()
|
||||
"=RELEASE-ID",
|
||||
"=meta-update",
|
||||
"=update",
|
||||
/* Bazaar */
|
||||
".bzr",
|
||||
".bzrignore",
|
||||
".bzrtags",
|
||||
/* Mercurial */
|
||||
".hg",
|
||||
".hgignore",
|
||||
".hgtags",
|
||||
/* darcs */
|
||||
"_darcs",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -1002,6 +1049,9 @@ report_textual_dates (struct tar_args *args)
|
||||
|
||||
static volatile int _argp_hang;
|
||||
|
||||
/* Either NL or NUL, as decided by the --null option. */
|
||||
static char filename_terminator;
|
||||
|
||||
enum read_file_list_state /* Result of reading file name from the list file */
|
||||
{
|
||||
file_list_success, /* OK, name read successfully */
|
||||
@@ -1010,16 +1060,16 @@ enum read_file_list_state /* Result of reading file name from the list file */
|
||||
file_list_skip /* Empty (zero-length) entry encountered, skip it */
|
||||
};
|
||||
|
||||
/* Read from FP a sequence of characters up to FILENAME_TERMINATOR and put them
|
||||
/* Read from FP a sequence of characters up to TERM and put them
|
||||
into STK.
|
||||
*/
|
||||
static enum read_file_list_state
|
||||
read_name_from_file (FILE *fp, struct obstack *stk)
|
||||
read_name_from_file (FILE *fp, struct obstack *stk, int term)
|
||||
{
|
||||
int c;
|
||||
size_t counter = 0;
|
||||
|
||||
for (c = getc (fp); c != EOF && c != filename_terminator; c = getc (fp))
|
||||
for (c = getc (fp); c != EOF && c != term; c = getc (fp))
|
||||
{
|
||||
if (c == 0)
|
||||
{
|
||||
@@ -1100,7 +1150,8 @@ update_argv (const char *filename, struct argp_state *state)
|
||||
size_t new_argc;
|
||||
bool is_stdin = false;
|
||||
enum read_file_list_state read_state;
|
||||
|
||||
int term = filename_terminator;
|
||||
|
||||
if (!strcmp (filename, "-"))
|
||||
{
|
||||
is_stdin = true;
|
||||
@@ -1114,7 +1165,8 @@ update_argv (const char *filename, struct argp_state *state)
|
||||
open_fatal (filename);
|
||||
}
|
||||
|
||||
while ((read_state = read_name_from_file (fp, &argv_stk)) != file_list_end)
|
||||
while ((read_state = read_name_from_file (fp, &argv_stk, term))
|
||||
!= file_list_end)
|
||||
{
|
||||
switch (read_state)
|
||||
{
|
||||
@@ -1143,7 +1195,7 @@ update_argv (const char *filename, struct argp_state *state)
|
||||
obstack_1grow (&argv_stk, 0);
|
||||
count = 1;
|
||||
/* Read rest of files using new filename terminator */
|
||||
filename_terminator = 0;
|
||||
term = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1160,7 +1212,7 @@ update_argv (const char *filename, struct argp_state *state)
|
||||
|
||||
start = obstack_finish (&argv_stk);
|
||||
|
||||
if (filename_terminator == 0)
|
||||
if (term == 0)
|
||||
for (p = start; *p; p += strlen (p) + 1)
|
||||
if (p[0] == '-')
|
||||
count++;
|
||||
@@ -1176,7 +1228,7 @@ update_argv (const char *filename, struct argp_state *state)
|
||||
|
||||
for (i = state->next, p = start; *p; p += strlen (p) + 1, i++)
|
||||
{
|
||||
if (filename_terminator == 0 && p[0] == '-')
|
||||
if (term == 0 && p[0] == '-')
|
||||
state->argv[i++] = "--add-file";
|
||||
state->argv[i] = p;
|
||||
}
|
||||
@@ -1222,6 +1274,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
set_subcommand_option (CAT_SUBCOMMAND);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
args->compress_autodetect = true;
|
||||
break;
|
||||
|
||||
case NO_AUTO_COMPRESS_OPTION:
|
||||
args->compress_autodetect = false;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
{
|
||||
uintmax_t u;
|
||||
@@ -1292,6 +1352,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
|
||||
@@ -1310,6 +1374,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
set_use_compress_program_option ("bzip2");
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
set_use_compress_program_option ("lzma");
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
/* Don't replace existing files. */
|
||||
old_files_option = KEEP_OLD_FILES;
|
||||
@@ -1341,6 +1409,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
}
|
||||
break;
|
||||
|
||||
case LZOP_OPTION:
|
||||
set_use_compress_program_option ("lzop");
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
touch_option = true;
|
||||
break;
|
||||
@@ -1514,6 +1586,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 +1601,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 +1610,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)
|
||||
@@ -1670,6 +1754,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
filename_terminator = '\0';
|
||||
break;
|
||||
|
||||
case NO_NULL_OPTION:
|
||||
filename_terminator = '\n';
|
||||
break;
|
||||
|
||||
case NUMERIC_OWNER_OPTION:
|
||||
numeric_owner_option = true;
|
||||
break;
|
||||
@@ -1732,6 +1820,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
/* FIXME: What it is good for? */
|
||||
same_permissions_option = true;
|
||||
same_order_option = true;
|
||||
WARN ((0, 0, _("The --preserve option is deprecated, "
|
||||
"use --preserve-permissions --preserve-order instead")));
|
||||
break;
|
||||
|
||||
case RECORD_SIZE_OPTION:
|
||||
@@ -2001,7 +2091,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 +2108,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. */
|
||||
|
||||
@@ -2253,6 +2346,13 @@ decode_options (int argc, char **argv)
|
||||
else if (utc_option)
|
||||
verbose_option = 2;
|
||||
|
||||
if (tape_length_option && tape_length_option < record_size)
|
||||
USAGE_ERROR ((0, 0, _("Volume length cannot be less than record size")));
|
||||
|
||||
if (same_order_option && listed_incremental_option)
|
||||
USAGE_ERROR ((0, 0, _("--preserve-order is not compatible with "
|
||||
"--listed-incremental")));
|
||||
|
||||
/* Forbid using -c with no input files whatsoever. Check that `-f -',
|
||||
explicit or implied, is used correctly. */
|
||||
|
||||
@@ -2262,6 +2362,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 +2418,8 @@ decode_options (int argc, char **argv)
|
||||
backup_option = false;
|
||||
}
|
||||
|
||||
checkpoint_finish_compile ();
|
||||
|
||||
if (verbose_option)
|
||||
report_textual_dates (&args);
|
||||
}
|
||||
@@ -2420,7 +2526,7 @@ main (int argc, char **argv)
|
||||
name_term ();
|
||||
|
||||
if (exit_status == TAREXIT_FAILURE)
|
||||
error (0, 0, _("Error exit delayed from previous errors"));
|
||||
error (0, 0, _("Exiting with failure status due to previous errors"));
|
||||
|
||||
if (stdlis == stdout)
|
||||
close_stdout ();
|
||||
|
||||
278
src/transform.c
278
src/transform.c
@@ -1,5 +1,5 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -19,16 +19,11 @@
|
||||
#include <regex.h>
|
||||
#include "common.h"
|
||||
|
||||
static enum transform_type
|
||||
enum transform_type
|
||||
{
|
||||
transform_none,
|
||||
transform_first,
|
||||
transform_global
|
||||
}
|
||||
transform_type = transform_none;
|
||||
static unsigned match_number = 0;
|
||||
static regex_t regex;
|
||||
static struct obstack stk;
|
||||
};
|
||||
|
||||
enum replace_segm_type
|
||||
{
|
||||
@@ -62,31 +57,56 @@ 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;
|
||||
int flags;
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
int transform_flags = XFORM_ALL;
|
||||
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 +116,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,41 +127,87 @@ 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)
|
||||
static int
|
||||
parse_xform_flags (int *pflags, int c)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
switch (c)
|
||||
{
|
||||
case 'r':
|
||||
*pflags |= XFORM_REGFILE;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
*pflags &= ~XFORM_REGFILE;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
*pflags |= XFORM_LINK;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
*pflags &= ~XFORM_LINK;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
*pflags |= XFORM_SYMLINK;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
*pflags &= ~XFORM_SYMLINK;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
|
||||
{
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_case_ctl;
|
||||
segm->v.ctl = ctl;
|
||||
}
|
||||
|
||||
void
|
||||
set_transform_expr (const char *expr)
|
||||
static const char *
|
||||
parse_transform_expr (const char *expr)
|
||||
{
|
||||
int delim;
|
||||
int i, j, rc;
|
||||
char *str, *beg, *cur;
|
||||
const char *p;
|
||||
int cflags = 0;
|
||||
|
||||
if (transform_type == transform_none)
|
||||
obstack_init (&stk);
|
||||
else
|
||||
{
|
||||
/* Redefinition of the transform expression */
|
||||
regfree (®ex);
|
||||
}
|
||||
struct transform *tf = new_transform ();
|
||||
|
||||
if (expr[0] != 's')
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
{
|
||||
if (strncmp (expr, "flags=", 6) == 0)
|
||||
{
|
||||
transform_flags = 0;
|
||||
for (expr += 6; *expr; expr++)
|
||||
{
|
||||
if (*expr == ';')
|
||||
{
|
||||
expr++;
|
||||
break;
|
||||
}
|
||||
if (parse_xform_flags (&transform_flags, *expr))
|
||||
USAGE_ERROR ((0, 0, _("Unknown transform flag: %c"),
|
||||
*expr));
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
}
|
||||
|
||||
delim = expr[1];
|
||||
|
||||
/* Scan regular expression */
|
||||
@@ -161,12 +227,13 @@ 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;
|
||||
tf->flags = transform_flags;
|
||||
for (p = expr + j + 1; *p && *p != ';'; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case 'g':
|
||||
transform_type = transform_global;
|
||||
tf->transform_type = transform_global;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
@@ -176,33 +243,38 @@ set_transform_expr (const char *expr)
|
||||
case 'x':
|
||||
cflags |= REG_EXTENDED;
|
||||
break;
|
||||
|
||||
|
||||
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")));
|
||||
if (parse_xform_flags (&tf->flags, *p))
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression: %c"),
|
||||
*p));
|
||||
}
|
||||
|
||||
if (*p == ';')
|
||||
p++;
|
||||
|
||||
/* Extract and compile regex */
|
||||
str = xmalloc (i - 1);
|
||||
memcpy (str, expr + 2, i - 2);
|
||||
str[i - 2] = 0;
|
||||
|
||||
rc = regcomp (®ex, str, cflags);
|
||||
rc = regcomp (&tf->regex, str, cflags);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
char errbuf[512];
|
||||
regerror (rc, ®ex, errbuf, sizeof (errbuf));
|
||||
regerror (rc, &tf->regex, errbuf, sizeof (errbuf));
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
|
||||
}
|
||||
|
||||
if (str[0] == '^' || str[strlen (str) - 1] == '$')
|
||||
transform_type = transform_first;
|
||||
tf->transform_type = transform_first;
|
||||
|
||||
free (str);
|
||||
|
||||
@@ -218,91 +290,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 +384,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 +393,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 +453,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 +474,14 @@ _transform_name_to_obstack (char *input)
|
||||
save_ctl = ctl_stop; \
|
||||
}
|
||||
|
||||
if (transform_type == transform_none)
|
||||
return false;
|
||||
|
||||
rmp = xmalloc ((regex.re_nsub + 1) * sizeof (*rmp));
|
||||
rmp = xmalloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
|
||||
|
||||
while (*input)
|
||||
{
|
||||
size_t disp;
|
||||
char *ptr;
|
||||
|
||||
rc = regexec (®ex, input, regex.re_nsub + 1, rmp, 0);
|
||||
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
@@ -412,14 +493,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 +566,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 +575,46 @@ _transform_name_to_obstack (char *input)
|
||||
|
||||
obstack_1grow (&stk, 0);
|
||||
free (rmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
_transform_name_to_obstack (int flags, char *input, char **output)
|
||||
{
|
||||
struct transform *tf;
|
||||
bool alloced = false;
|
||||
|
||||
if (!stk_init)
|
||||
{
|
||||
obstack_init (&stk);
|
||||
stk_init = true;
|
||||
}
|
||||
|
||||
for (tf = transform_head; tf; tf = tf->next)
|
||||
{
|
||||
if (tf->flags & flags)
|
||||
{
|
||||
_single_transform_name_to_obstack (tf, input);
|
||||
input = obstack_finish (&stk);
|
||||
alloced = true;
|
||||
}
|
||||
}
|
||||
*output = input;
|
||||
return alloced;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
|
||||
transform_name_fp (char **pinput, int flags,
|
||||
char *(*fun)(char *, void *), void *dat)
|
||||
{
|
||||
char *str;
|
||||
bool ret = _transform_name_to_obstack (*pinput);
|
||||
bool ret = _transform_name_to_obstack (flags, *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);
|
||||
@@ -520,8 +624,8 @@ transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name (char **pinput)
|
||||
transform_name (char **pinput, int type)
|
||||
{
|
||||
return transform_name_fp (pinput, NULL, NULL);
|
||||
return transform_name_fp (pinput, type, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <fnmatch.h>
|
||||
|
||||
static bool xheader_protected_pattern_p (char const *pattern);
|
||||
static bool xheader_protected_keyword_p (char const *keyword);
|
||||
static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
|
||||
|
||||
@@ -89,6 +89,7 @@ TESTSUITE_AT = \
|
||||
multiv03.at\
|
||||
multiv04.at\
|
||||
multiv05.at\
|
||||
multiv06.at\
|
||||
old.at\
|
||||
options.at\
|
||||
options02.at\
|
||||
@@ -97,9 +98,12 @@ TESTSUITE_AT = \
|
||||
rename01.at\
|
||||
rename02.at\
|
||||
rename03.at\
|
||||
rename04.at\
|
||||
rename05.at\
|
||||
same-order01.at\
|
||||
same-order02.at\
|
||||
shortfile.at\
|
||||
shortupd.at\
|
||||
shortrec.at\
|
||||
sparse01.at\
|
||||
sparse02.at\
|
||||
|
||||
@@ -13,7 +13,7 @@ if test -z "$TEST_DATA_DIR"; then
|
||||
TEST_DATA_DIR=$abs_builddir
|
||||
fi
|
||||
|
||||
STAR_DATA_URL=http://download.berlios.de/pub/star/testscripts
|
||||
STAR_DATA_URL=ftp://ftp.berlios.de/pub/star/testscripts
|
||||
if test -z "$STAR_TESTSCRIPTS"; then
|
||||
STAR_TESTSCRIPTS=$TEST_DATA_DIR
|
||||
fi
|
||||
@@ -30,4 +30,8 @@ tarball_prereq() {
|
||||
echo "$2 $3/$1" | md5sum --status --check - >/dev/null 2>&1
|
||||
}
|
||||
|
||||
decho() {
|
||||
echo $*
|
||||
echo >&2 $*
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ tar tf archive
|
||||
to
|
||||
],
|
||||
[tar: tre: Not found in archive
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -35,7 +35,7 @@ test $? = 2 || exit 1
|
||||
[
|
||||
gzip: stdin: unexpected end of file
|
||||
tar: Child returned status 1
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],
|
||||
[],[])
|
||||
|
||||
|
||||
@@ -64,12 +64,12 @@ test $status = 0
|
||||
[
|
||||
-----
|
||||
tar: file: Cannot open: Permission denied
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
-----
|
||||
tar: file: Warning: Cannot open: Permission denied
|
||||
-----
|
||||
tar: directory: Cannot open: Permission denied
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
-----
|
||||
tar: directory: Warning: Cannot open: Permission denied
|
||||
])
|
||||
|
||||
@@ -34,6 +34,8 @@ mkdir directory
|
||||
genfile --file=directory/x
|
||||
genfile --file=directory/y
|
||||
|
||||
sleep 1
|
||||
|
||||
tar -cf archive.1 -g db directory
|
||||
|
||||
mv directory/x directory/z
|
||||
|
||||
@@ -38,6 +38,8 @@ awk 'BEGIN {
|
||||
printf("NAME_PREFIX[%03d]\n", i);
|
||||
}' < /dev/null | genfile --files-from -
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Initial dump"
|
||||
tar cvf a0.tar -g a.sna a
|
||||
mv a/b a/c
|
||||
|
||||
@@ -44,7 +44,10 @@ sleep 1
|
||||
tar cf archive --listed=list structure
|
||||
tar cfv archive --listed=list structure
|
||||
echo separator
|
||||
sleep 1
|
||||
# ReiserFS often offsets the timestamps of newly created files
|
||||
# 1 second to the past. Try to compensate for it, until a better
|
||||
# solution is found.
|
||||
sleep 2
|
||||
echo y >structure/file
|
||||
tar cfv archive --listed=list structure
|
||||
],
|
||||
|
||||
@@ -39,7 +39,7 @@ tar --create \
|
||||
|
||||
tar tf archive.1 || exit 1
|
||||
|
||||
sleep 1
|
||||
sleep 2
|
||||
|
||||
genfile --length 10240 --pattern zeros --file directory/file2
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ tar tf archive
|
||||
DIR/
|
||||
],
|
||||
[tar: DIR/FILE: file name is too long (max 99); not dumped
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],
|
||||
[],[],[v7])
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ tar cf archive LONGNAME
|
||||
[2],
|
||||
[],
|
||||
[tar: LONGNAME: file name is too long (cannot be split); not dumped
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],[],[],[ustar])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -36,7 +36,7 @@ tar cf archive PREFIX_155
|
||||
[2],
|
||||
[],
|
||||
[tar: PREFIX_155/: file name is too long (cannot be split); not dumped
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],[],[],[ustar])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for 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
|
||||
@@ -19,11 +19,11 @@
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Up to version 1.15.91 tar was unable to recognize all volumes
|
||||
# given after an aout-of-sync volume.
|
||||
# given after an out-of-sync volume.
|
||||
# Reported by: Joerg Weilbier <gnu@weilbier.net>
|
||||
# References: <200610011952.29880.gnu@weilbier.net>
|
||||
|
||||
AT_SETUP([Restoring after an out of sync folume])
|
||||
AT_SETUP([Restoring after an out of sync volume])
|
||||
AT_KEYWORDS([multivolume multiv multiv05 sync])
|
||||
m4_define([FILELIST],[jeden,dwa,trzy,cztery,piec,szesc])
|
||||
|
||||
|
||||
52
tests/multiv06.at
Normal file
52
tests/multiv06.at
Normal file
@@ -0,0 +1,52 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 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 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# When volume size equals record size, swapping buffers in
|
||||
# new_volume triggers a call to flush_archive. The size left variables
|
||||
# must be corrected after that, which was not done in versions <= 1.20.
|
||||
# Reported by: Marek Kielar <mkielar@go2.pl>
|
||||
# References: <1907cbb6.79e32b49.48887f09.fd55@o2.pl>
|
||||
|
||||
AT_SETUP([Multivolumes with L=record_size])
|
||||
AT_KEYWORDS([multivolume multiv multiv06])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
exec <&-
|
||||
decho Creating file
|
||||
genfile --length 20139 --file file
|
||||
decho Creating archive
|
||||
tar -c -M -L10 -b20 -farc.1 -farc.2 -farc.3 file
|
||||
decho Testing archive
|
||||
tar -t -M -farc.1 -farc.2 -farc.3],
|
||||
[0],
|
||||
[Creating file
|
||||
Creating archive
|
||||
Testing archive
|
||||
file
|
||||
],
|
||||
[Creating file
|
||||
Creating archive
|
||||
Testing archive
|
||||
],
|
||||
[],[],
|
||||
[gnu, pax])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -34,6 +34,8 @@ genfile --file foo/bar/file.r
|
||||
mkdir foo/bar/baz
|
||||
genfile --file foo/bar/baz/file.z
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Creating base archive"
|
||||
tar -g incr -cf arch.1 -v foo
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ genfile --file foo/b/fileb
|
||||
mkdir foo/c
|
||||
genfile --file foo/c/filec
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "First dump"
|
||||
echo "First dump">&2
|
||||
tar -g incr -cf arch.1 -v foo 2>tmperr
|
||||
|
||||
83
tests/rename04.at
Normal file
83
tests/rename04.at
Normal file
@@ -0,0 +1,83 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 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 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: Up to version 1.20, when storing a record for renamed
|
||||
# directory in an incremental archive, tar incorrectly flagged all its
|
||||
# subdirectories as renamed, which led to problems at archive extraction.
|
||||
# References: <00a401c8ecc0$56b7ef30$6a17a8c0@inti.com>
|
||||
# Reported by: Enric Hernandez <ehernandez@notariado.org>
|
||||
|
||||
AT_SETUP([renamed directory containing subdirectories])
|
||||
AT_KEYWORDS([incremental rename04 rename])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
decho Creating directory structure
|
||||
mkdir directory
|
||||
mkdir directory/subdir
|
||||
genfile --file=directory/file
|
||||
|
||||
decho Creating initial archive
|
||||
tar -cf archive.1 -g db.1 directory
|
||||
|
||||
decho Renaming
|
||||
mv directory dir
|
||||
|
||||
decho Creating incremental archive
|
||||
cp db.1 db.2
|
||||
tar -cf archive.2 -g db.2 dir
|
||||
|
||||
mv dir orig
|
||||
|
||||
decho First restore
|
||||
tar -xf archive.1 -g db.1
|
||||
find directory | sort
|
||||
|
||||
decho Second restore
|
||||
tar -xf archive.2 -g db.2
|
||||
find dir | sort
|
||||
],
|
||||
[0],
|
||||
[Creating directory structure
|
||||
Creating initial archive
|
||||
Renaming
|
||||
Creating incremental archive
|
||||
First restore
|
||||
directory
|
||||
directory/file
|
||||
directory/subdir
|
||||
Second restore
|
||||
dir
|
||||
dir/subdir
|
||||
],
|
||||
[Creating directory structure
|
||||
Creating initial archive
|
||||
Renaming
|
||||
Creating incremental archive
|
||||
First restore
|
||||
Second restore
|
||||
],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
# End of rename04.at
|
||||
|
||||
|
||||
81
tests/rename05.at
Normal file
81
tests/rename05.at
Normal file
@@ -0,0 +1,81 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 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 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: A continuation of rename04.at, that checks additionally if
|
||||
# renamed subdirectories are restored correctly.
|
||||
|
||||
AT_SETUP([renamed subdirectories])
|
||||
AT_KEYWORDS([incremental rename05 rename])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
decho Creating directory structure
|
||||
mkdir directory
|
||||
mkdir directory/subdir
|
||||
genfile --file=directory/file
|
||||
|
||||
decho Creating initial archive
|
||||
tar -cf archive.1 -g db.1 directory
|
||||
|
||||
decho Renaming
|
||||
mv directory/subdir directory/subdir.0
|
||||
mv directory dir
|
||||
|
||||
decho Creating incremental archive
|
||||
cp db.1 db.2
|
||||
tar -cf archive.2 -g db.2 dir
|
||||
|
||||
mv dir orig
|
||||
|
||||
decho First restore
|
||||
tar -xf archive.1 -g db.1
|
||||
find directory | sort
|
||||
|
||||
decho Second restore
|
||||
tar -xf archive.2 -g db.2
|
||||
find dir | sort
|
||||
],
|
||||
[0],
|
||||
[Creating directory structure
|
||||
Creating initial archive
|
||||
Renaming
|
||||
Creating incremental archive
|
||||
First restore
|
||||
directory
|
||||
directory/file
|
||||
directory/subdir
|
||||
Second restore
|
||||
dir
|
||||
dir/subdir.0
|
||||
],
|
||||
[Creating directory structure
|
||||
Creating initial archive
|
||||
Renaming
|
||||
Creating incremental archive
|
||||
First restore
|
||||
Second restore
|
||||
],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
# End of rename05.at
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -33,7 +33,7 @@ tar tf foo
|
||||
[2],
|
||||
[],
|
||||
[tar: This does not look like a tar archive
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],
|
||||
[],[],[gnu])
|
||||
|
||||
|
||||
39
tests/shortupd.at
Normal file
39
tests/shortupd.at
Normal file
@@ -0,0 +1,39 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Fixing improper small file recognition in version 1.18 (see shortfile.at
|
||||
# and ChangeLog:2007-08-24), introduced another bug: when updating a
|
||||
# non-existing archive, tar-1.19 complained about its not being a tar archive
|
||||
# and exited immediately, leaving the created zero-sized file after it.
|
||||
#
|
||||
# This bug was fixed on 2007-12-05.
|
||||
#
|
||||
# Reported by: Ozan @,{C}a@v{g}layan <ozancag@gmail.com>
|
||||
# References: <4755A82A.9060607@gmail.com>
|
||||
|
||||
AT_SETUP([updating short archives])
|
||||
AT_KEYWORDS([shortfile shortfile1 shortupd])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
touch foo
|
||||
tar uf archive foo
|
||||
],
|
||||
[0])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 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
|
||||
@@ -35,18 +35,18 @@ echo "Pass 1: Split between data blocks"
|
||||
echo "Create archive"
|
||||
tar --sparse -c --record-size=512 -M -L6 -f arc.1 -f arc.2 sparsefile || exit 1
|
||||
echo "Test archive"
|
||||
tar -t -M -f arc.1 -f arc.2
|
||||
tar --record-size=512 -t -M -f arc.1 -f arc.2
|
||||
echo "Compare archive"
|
||||
tar -d -M -f arc.1 -f arc.2
|
||||
tar --record-size=512 -d -M -f arc.1 -f arc.2
|
||||
|
||||
echo "Pass 2: Split within a data block"
|
||||
genfile --sparse --file sparsefile 0 ABCDEFGHIJ 1M ABCDEFGHI || AT_SKIP_TEST
|
||||
echo "Create archive"
|
||||
tar --sparse -c --record-size=512 -M -L6 -f arc.1 -f arc.2 sparsefile || exit 1
|
||||
echo "Test archive"
|
||||
tar -t -M -f arc.1 -f arc.2
|
||||
tar --record-size=512 -t -M -f arc.1 -f arc.2
|
||||
echo "Compare archive"
|
||||
tar -d -M -f arc.1 -f arc.2
|
||||
tar --record-size=512 -d -M -f arc.1 -f arc.2
|
||||
],
|
||||
[0],
|
||||
[Pass 1: Split between data blocks
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 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
|
||||
@@ -56,5 +56,7 @@ Test archive
|
||||
sparsefile
|
||||
Compare archive
|
||||
],
|
||||
[],[],[],[pax])])
|
||||
[tar: Record size = 12 blocks
|
||||
tar: Record size = 12 blocks
|
||||
],[],[],[pax])])
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -138,6 +138,8 @@ m4_include([incr04.at])
|
||||
m4_include([rename01.at])
|
||||
m4_include([rename02.at])
|
||||
m4_include([rename03.at])
|
||||
m4_include([rename04.at])
|
||||
m4_include([rename05.at])
|
||||
m4_include([chtype.at])
|
||||
|
||||
m4_include([ignfail.at])
|
||||
@@ -155,6 +157,7 @@ m4_include([multiv02.at])
|
||||
m4_include([multiv03.at])
|
||||
m4_include([multiv04.at])
|
||||
m4_include([multiv05.at])
|
||||
m4_include([multiv06.at])
|
||||
|
||||
m4_include([old.at])
|
||||
|
||||
@@ -180,6 +183,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])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for 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
|
||||
@@ -36,7 +36,7 @@ AT_TARBALL_PREREQ([abc.tar],[540f196ceddcad9e7bd2f2d7533d0474])
|
||||
echo Short Listing
|
||||
tar tf $TEST_DATA_DIR/abc.tar
|
||||
echo Verbose Listing
|
||||
tar tfv $TEST_DATA_DIR/abc.tar
|
||||
tar --utc -tvf $TEST_DATA_DIR/abc.tar
|
||||
echo Extracted directory
|
||||
tar xf $TEST_DATA_DIR/abc.tar
|
||||
find abc|sort
|
||||
@@ -46,11 +46,14 @@ find abc|sort
|
||||
abc/not-a-file.gif
|
||||
abc/CCC
|
||||
Verbose Listing
|
||||
V--------- 0/0 1536 2006-05-09 01:07 abc/not-a-file.gif--Volume Header--
|
||||
-rw-r--r-- tom/users 0 2006-04-22 22:52 abc/CCC
|
||||
V--------- 0/0 1536 2006-05-08 22:07 abc/not-a-file.gif--Volume Header--
|
||||
-rw-r--r-- tom/users 0 2006-04-22 19:52 abc/CCC
|
||||
Extracted directory
|
||||
abc
|
||||
abc/CCC
|
||||
],
|
||||
[tar: Record size = 5 blocks
|
||||
tar: Record size = 5 blocks
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
Reference in New Issue
Block a user