188 Commits

Author SHA1 Message Date
Sergey Poznyakoff
b500277de7 Version 1.28 2014-07-27 23:45:19 +03:00
Nathan Stratton Treadway
002bf86821 Minor change in docstrings.
nor ch#
2014-07-27 23:31:26 +03:00
Nathan Stratton Treadway
fcde08534b Restructure the remfiles testsuite. 2014-07-27 23:27:28 +03:00
Sergey Poznyakoff
a5db4ba5cb Don't build ttyemu and run tty I/O test if grantpt is not available.
* configure.ac (TAR_COND_GRANTPT): Define conditional depending
on whether grantpt is available.
* gnulib.modules: Remove grantpt. It relies upon a helper binary
pt_chown which it installs and which is useless in the testsuite.
* tests/Makefile.am [TAR_COND_GRANTPT]: Build ttyemu
* tests/iotty.at: Skip test if ttyemu is not build.
* tests/ttyemu.c (noecho): Fix error message
(main): Use TIOCSCTTY if it is defined.
2014-07-22 04:29:25 +03:00
Benno Schulenberg
20ab569dc3 Fix a typo and some wordings in the documentation.
* doc/tar.texi: Fix some missing articles, and make it clearer
that "any" does not mean "anything" but "either of the two".
2014-07-22 03:37:41 +03:00
Nathan Stratton Treadway
f86e0605d0 Fix the testsuite
* tests/incr07.at: Don't assume case-sensitive filesystem.
2014-07-22 03:34:20 +03:00
Paul Eggert
4423e1743e tar: minor fixups related to recent checkpoint.c change
* src/checkpoint.c (getwidth, format_checkpoint_string):
Use long and strtol, not int, to avoid overflow issues.
(getwidth): Don't assume termios.h defines TIOCGWINSZ,
as it doesn't on some older hosts.
2014-07-10 22:35:05 -07:00
Sergey Poznyakoff
8d087fbb0b Bugfixes
* gnulib.modules: Add faccessat
* src/checkpoint.c: Include termios.h
2014-07-11 08:09:30 +03:00
Nathan Stratton Treadway
dc72f4d114 tar: document xgetcwd test case better
* src/misc.c (normalize_filename): Add commentary for clarity.
* tests/extrac09.at: Retitle test case and add comments for clarity.
2014-06-28 23:57:58 -07:00
Sergey Poznyakoff
576e99a21c Fix typos in ChangeLog
* ChangeLog.CVS: Fix typos.
* ChangeLog.amend: New file.
* Makefile.am: Define changelog_amend_file.
2014-06-24 11:53:35 +03:00
Paul Eggert
fc58a8bd98 tar: do not dereference NULL pointer with '--remove-files .'
Problem reported by Thorsten Hirsch in:
http://lists.gnu.org/archive/html/bug-tar/2014-04/msg00011.html
* src/unlink.c (flush_deferred_unlinks):
Do not attempt to find the parent of "." when "." is
at the top level.
* tests/remfiles10.at: New file.
* tests/Makefile.am (TESTSUITE_AT):
* tests/testsuite.at: Add it.
2014-04-29 14:22:59 -07:00
Sergey Poznyakoff
7808b6981b Refuse to write archive contents to a tty.
* NEWS: Update.
* src/buffer.c (_open_archive): Refuse to write to a tty.
* tests/iotty.at: Test output to a tty.
2014-03-27 07:06:02 +02:00
Vitezslav Cizek
852895847f fix an eternal loop in handle_option
* src/names.c (handle_option): increment loop counter
2014-03-26 23:01:22 +02:00
Sergey Poznyakoff
b0902369e7 Fail if archive comes from a terminal.
Based on patch from Pavel Raiskup <praiskup@redhat.com>.

* gnulib.modules: Add new modules.
* src/buffer.c (_open_archive): Refuse to read archive from a tty.
* tests/Makefile.am (TESTSUITE_AT): Add iotty.at
(check_PROGRAMS): New program ttyemu
* tests/testsuite.at: Include iotty.at
* tests/iotty.at: New file.
* tests/ttyemu.c: New file.
2014-03-20 19:46:30 +02:00
Paul Eggert
da546e69af tar: port to Solaris 9
Problem reported by Jesse C in:
http://lists.gnu.org/archive/html/bug-tar/2014-03/msg00034.html
* gnulib.modules: Add strtoimax and strtoumax, since tar invokes
these functions directly and they don't exist on Solaris 9.
2014-03-12 21:02:06 -07:00
Sergey Poznyakoff
f24b30ec8c Test the --[no-]recursive options (see commit 2bd9c153_.
* tests/recurs02.at: New test case.
* tests/Makefile.am: Add new file.
* tests/testsuite.at: Add new file.
2014-02-25 10:38:06 +02:00
Sergey Poznyakoff
93906c238d Support exclusion patterns from various VCS ignore lists.
* src/Makefile.am (tar_SOURCES): Add exclist.c
* src/common.h (EXCL_DEFAULT, EXCL_RECURSIVE)
(EXCL_NON_RECURSIVE): New flags.
(excfile_add, info_attach_exclist)
(info_cleanup_exclist,info_free_exclist)
(exclude_vcs_ignores): New prototypes.
* src/create.c (dump_dir0): Call info_attach_exclist.
* src/exclist.c: New file.
* src/incremen.c (scan_directory): Call info_attach_exclist.
* src/names.c (excluded_name): Moved to exclist.c. Change signature.
All uses updated.
* src/tar.c: New options: --exclude-ignore, --exclude-ignore-recursive
and --exclude-vcs-ignores.
(tar_stat_destroy): Free exclist.
* src/tar.h (tar_stat_info): New member exclude_list.

* NEWS: Document new exclusion options.
* doc/tar.texi: Likewise.
* doc/tar.1: Likewise.
2014-02-22 08:13:30 +02:00
Sergey Poznyakoff
9df17e6005 Fix in testsuite
* acls03.at: Fix improper invocation of setfacl.
2014-02-14 13:03:58 +02:00
Pavel Raiskup
efbf4cce0b testsuite: add test for buggy default ACLs
* tests/Makefile.am: Mention acls03.at.
* tests/testsuite.at: Likewise.
* tests/acls03.at: New testcase.
2014-02-14 12:38:25 +02:00
Pavel Raiskup
7fe7adcbb9 acls: bugfix for default ACLs extraction
When --acls option is on (regardless of tarball contents or
tarball format), we should explicitly set OR delete default ACLs
for extracted directories.  Prior to this update, we always
created arbitrary default ACLs based standard file permissions.

* configure.ac (with_posix_acls): Check also for acl_free and
acl_delete_def_file to mark IEEE 1003.1e ACLs as supported.
* src/xattrs.c (acl_delete_def_file_at): New function.
(xattrs__acls_set): Do not treat acls_option at all;  Delete
default ACLs if appropriate.

References:
http://www.mail-archive.com/bug-tar@gnu.org/msg04355.html
Thanks: Juan J. Martínez and Mark Steinborn
2014-02-14 12:38:20 +02:00
Pavel Raiskup
8e10d93d01 tar: imply --xattrs when --xattrs-{inc,exc}lude used
Options --xattrs-include=MASK and --xattrs-exclude=MASK now turn
on the --xattrs option.

Fix also bug in printing in xattrs.c - don't print when option is
negative.

* src/tar.c (set_xattr_option): New static function.
(parse_opt): Call new function when --xatrrs, --xattrs-include or
--xattrs-exclude option is used.
* src/xattrs.c (xattrs_print, xattrs_print_char): Expect positive
values in options.
2014-02-14 12:32:34 +02:00
Sergey Poznyakoff
3cb4693c65 THANKS: Add Anthony G. Basile. 2014-02-14 11:02:40 +02:00
Sergey Poznyakoff
48a546b02c Use correct headers/libraries when providing xattr support
See https://savannah.gnu.org/patch/index.php?8252. Patch provided
by Anthony G. Basile.

* acinclude.m4 (TAR_HEADERS_ATTR_XATTR_H): Look for <sys/xattr.h>
first and then for <attr/xattr.h>.  Link against libattr.so if
needed.
* lib/xattr-at.h: Include sys/xattr.h or attr/xattr.h, depending
on which one is detected.
* src/Makefile.am [TAR_LIB_ATTR] (tar_LDADD): Link against -lattr.
2014-02-14 10:55:26 +02:00
Sergey Poznyakoff
46da9968df Minor change
* src/tar.c (decode_options): Silently ignore --one-top-level
if used with a non-reading command.
2014-02-14 10:44:19 +02:00
Sergey Poznyakoff
29a6964af3 New option --sort=ORDER
This option makes tar sort the entries of directories that will be
added to an archive according to ORDER (none, name, or order).

Based on proposition by Dick Streefland (https://savannah.gnu.org/patch/?7892).

* src/common.h (savedir_sort_order): New global.
* src/create.c: Pass savedir_sort_order to streamsavedir.
* src/misc.c: Likewise.
* src/tar.c: New option --sort.

* NEWS: Update.
* doc/tar.texi: Document the --sort option.
* doc/tar.1: Likewise.
2014-02-14 00:26:49 +02:00
Sergey Poznyakoff
62497f0e26 Fix the testsuite
* tests/opcomp01.at: Update expected error messages.
* tests/opcomp03.at: Likewise.
2014-02-13 23:58:35 +02:00
Sergey Poznyakoff
c86b0c2149 Fix --one-top-level used together with --list.
* src/extract.c: Move one_top_level stuff to tar.c (decode_options).
* src/tar.c (option_conflict_error): New function.
(decode_options): Use option_conflict_error to complain about
conflicting options in a uniform manner.
Process one_top_level options here.
(request_stdin): Fix error message.
* tests/onetop04.at: New testcase: check --one-top-level with --list.
* tests/Makefile.am: Add new testcase.
* tests/testsuite.at: Add new testcase.
2014-02-13 19:17:27 +02:00
Sergey Poznyakoff
8b6a1a5990 Fix NEWS
* NEWS: Remove duplicate description of the --one-top-level option.
2014-02-13 10:29:19 +02:00
Sergey Poznyakoff
8cfcbfddd4 configure.ac: look for host-prefixed ar
See https://savannah.gnu.org/patch/?8183
2014-02-12 15:07:13 +02:00
Sergey Poznyakoff
e9e94531f0 Bugfix
* src/suffix.c (find_compression_suffix): Fix eventual coredump.
2014-02-10 19:51:55 +02:00
Sergey Poznyakoff
288dd472e3 Fix docs. 2014-02-10 18:46:24 +02:00
Sergey Poznyakoff
8706301479 Update docs.
* NEWS: Document --one-top-level
* THANKS: Mention Connor Behan
2014-02-10 18:29:39 +02:00
Sergey Poznyakoff
45ccda1193 Update copyright years. 2014-01-30 13:54:15 +02:00
Sergey Poznyakoff
1689ed4388 Improve one-top-level functionality
Make sure the changes become visible with --show-transformed-names.

* src/common.h (strip_compression_suffix): New function.
(one_top_level): Rename to one_top_level_dir. All uses changed.
* src/extract.c (extr_init): Use strip_compression_suffix.
Bail out if unable to determine top-level directory.
(maybe_prepend_name): Remove. All uses removed.
* src/tar.c (options): --one-top-level takes optional argument.
(parse_opt): Handle it.
* src/list.c (enforce_one_top_level): New function.
(transform_stat_info): Call enforce_one_top_level if required.
* src/suffix.c (compression_suffixes): List "tar" (no compression);
terminate with NULL entry.
(find_compression_suffix): New static.
(strip_compression_suffix): New function.

* doc/tar.1: Update.
* doc/tar.texi: Update.

* tests/onetop01.at: New testcase.
* tests/onetop02.at: New testcase.
* tests/onetop03.at: New testcase.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
2014-01-28 12:35:39 +02:00
Connor Behan
2af87fa277 Detect tarbombs while extracting
* src/common.h (one_top_level_option): New global.
(one_top_level): New global.
* src/extract.c (extr_init): If one_top_level_option is set, determine
the name one_top_level that might have to be prepended.
(extract_archive): If one_top_level_option is set, prepend one_top_level
to all names that don't already start with it.
* src/tar.c (ONE_TOP_LEVEL_OPTION): New contant.
(options): New option --one-top-level.
(parse_opt): Handle this option.
(decode_options): Make it conflict with --absolute-names.
2014-01-27 14:42:09 +02:00
Sergey Poznyakoff
95a51b93d0 Don't install rmt.8 if rmt is not built.
* doc/Makefile.am [PU_RMT_COND]: Define RMT_8
(dist_man_MANS): use RMT_8 instead of the hardcoded rmt.8
2014-01-27 14:32:46 +02:00
Sergey Poznyakoff
f504821589 Provide tar(1) and rmt(8) manpages.
* NEWS: Update.
* doc/Makefile.am: Add manpages.
* doc/tar.1: New file.

* src/tar.c (tar_help_filter): Handle LZOP_OPTION.
2014-01-27 13:20:11 +02:00
Sergey Poznyakoff
a09e840507 Make sure transformed file names retain trailing slash in listing.
* src/list.c (simple_print_header): Print trailing slash
if using the transformed name.
Use had_trailing_slash instead of analyzing last byte if temp_name
2014-01-23 18:04:36 +02:00
Sergey Poznyakoff
eb7e2aa933 checkpoint actions: further improvements.
* NEWS: Update.
* doc/tar.texi: Update.
* src/buffer.c (print_stats): Avoid use of additional string buffer.
Allow for text to be NULL.
Call gettext if it is not.
(format_total_stats): Don't use gettext when calling print_stats.
* src/checkpoint.c (def_format): Change default format.
(format_checkpoint_string): Implement optional arguments for
T conversion.
(finish_checkpoint_actions): Rename to checkpoint_flush_actions,
make extern.  All uses changed.
* src/common.h (checkpoint_flush_actions): New proto.
* src/tar.c (main): Set error_hook
2014-01-22 17:35:43 +02:00
Sergey Poznyakoff
717a07e208 Improve checkpoint interface.
* src/buffer.c (format_total_stats): The format arg is const
All uses updated.
(default_total_format): const
* src/checkpoint.c (tty, tty_cleanup): New static.
(format_checkpoint_string): New "canned" format %c
(checkpoint_finish): New function.
* src/common.h (checkpoint_finish): New proto.
* src/tar.c (main): Call checkpoint_finish.`
2014-01-22 07:28:02 +02:00
Sergey Poznyakoff
f0a1f78196 Implement statistics display in checkpoint actions.
* NEWS: Update.
* configure.ac: Version 1.27.90
* gnulib.modules: Add fprintftime.
* doc/tar.texi: Document the "totals" action and new format specifiers
for echo and ttyout checkpoint actions.
* src/buffer.c (compute_duration): Return computed value.
(print_stats): Don't print trailing newline.  Return number of
characters output.
(format_total_stats): New function.
(print_total_stats): Rewrite via format_total_stats.
* src/checkpoint.c (checkpoint_opcode) <cop_totals>: New opcode.
(checkpoint_compile_action): Handle cop_totals.
(expand_checkpoint_string): Remove.
(format_checkpoint_string): New function to be used instead of
expand_checkpoint_string.  All callers updated.
* src/common.h (TF_READ,TF_WRITE)
(TF_DELETED): New constants.
(format_total_stats,print_total_stats): New protos.
2014-01-21 17:57:46 +02:00
Sergey Poznyakoff
7f21a4d3f5 Remove shar archives from distribution.
These are going to phase out in automake 2.0
2014-01-10 11:37:50 +02:00
Sergey Poznyakoff
2bd9c15391 Fix the use of --no-recursion and --recursion options.
Each option remains in effect until cancelled by the next ocurrence
of its counterpart, as stated in the documentation.

* src/names.c (name_next_elt): Restore recursion_option from the
value of matching_flags.
2014-01-10 00:14:53 +02:00
Sergey Poznyakoff
481572c63f Minor bugfixes
* src/compare.c (diff_dumpdir): Close descriptor if fstat failed.
(diff_multivol): Make sure the descriptor is closed and eventual
errors reported if lseek fails.
Both reported by Jiri Kukacka.
2014-01-09 17:24:21 +02:00
Paul Eggert
47da28892e tar: work aruond IBM XL C bug
* src/incremen.c (show_snapshot_field_ranges)
(write_directory_file_entry): Use simpler array size expression,
one that evaluates to the same value.  This works around a compiler
bug with IBM XL C.  Problem reported by Yannick Bergeron in
<http://lists.gnu.org/archive/html/bug-tar/2014-01/msg00009.html>.
2014-01-07 11:16:23 -08:00
Paul Eggert
5c5f62e0dc tar: update ancient configure cruft
* configure.ac: Use AC_PROG_CC_STDC, not just AC_PROG_CC.
Remove obsolete macros AC_ISC_POSIX, AC_HEADER_SYS_WAIT,
AC_HEADER_DIRENT, AC_HEADER_STAT, AC_HEADER_STDC, AC_TYPE_SIGNAL,
AC_TYPE_SIZE_T.
* lib/prepargs.c (IN_CTYPE_DOMAIN): Remove.  All uses removed.
* src/list.c (from_header): Use isspace, not ISSPACE.
* src/system.c (pipe_handler, sys_exec_info_script):
* src/tar.c (sigstat):
Use void, not RETSIGTYPE.
2014-01-03 11:48:57 -08:00
Sergey Poznyakoff
49f3145092 Version 1.27.1 2013-11-17 18:37:50 +02:00
Sergey Poznyakoff
ca8cb48d02 Fix star compatibility (sparse headers)
* src/sparse.c (star_get_sparse_info): Update file->dumped_size
2013-11-17 17:35:01 +02:00
Sergey Poznyakoff
b4afdd0e28 Fix GNU long link header.
* src/create.c (write_gnu_long_link): Set timestamp to
0 for backward compatibility.  Bug reported by David Barri.
* THANKS: Update.
2013-11-17 17:31:41 +02:00
Sergey Poznyakoff
6e8bca8b56 Fix unquoting of input file names.
* src/names.c (read_next_name): Unquote file names coming from the
-T argument.  Bug reported by Nicolas Dudebout.
* THANKS: Update.
2013-11-17 17:27:53 +02:00
Paul Eggert
00054440c7 build: fix bug where 'configure --with-posix-acls' disables ACLs
Reported by Lars Wendler in
<http://lists.gnu.org/archive/html/bug-tar/2013-10/msg00022.html>.
* configure.ac (with_posix_acls): Fix typo.
2013-10-23 18:38:56 -07:00
Paul Eggert
a2e0cd0c05 Fix core dump on Solaris 10 when "." isn't readable.
Reported by Peter Kruse in
<http://lists.gnu.org/archive/html/bug-tar/2013-10/msg00017.html>.
This doesn't fix all the Solaris 10 test failures, just the core dump.
* src/common.h, src/misc.c (tar_getcdpath): Now static.
* src/misc.c (normalize_filename): Report a fatal error
if cdpath is null, since we don't know the absolute name
of the working directory in that case.  FIXME: there should
be no need to know absolute file names.
(chdir_arg): Simplify wd allocation.
Don't assume that xgetcwd returns non-null.
2013-10-22 19:17:23 -07:00
Sergey Poznyakoff
f6c25db5fe Version 1.27
* NEWS: Update.
* configure.ac: Update.
2013-10-06 00:02:17 +03:00
Sergey Poznyakoff
6d5cfeb757 Minor fixes.
* src/names.c: Include argp.h
* tests/testsuite.at (AT_XATTRS_UTILS_PREREQ)
(AT_SELINUX_UTILS_PREREQ,AT_ACLS_UTILS_PREREQ)
(AT_CAPABILITIES_UTILS_PREREQ)
(AT_XATTRS_PREREQ,AT_SELINUX_PREREQ)
(AT_ACLS_PREREQ): Use POSIX-compatible syntax for
mktemp.
* tests/incr08.at: Fix find usage.
2013-10-06 00:01:32 +03:00
Sergey Poznyakoff
3de5db2a15 Xfail the remfiles09b test.
* tests/remfiles09b.at: Turn into expected failure.
2013-10-05 09:29:55 +03:00
Nathan Stratton Treadway
db9b81eb6b Tiny change
* scripts/tar-snapshot-edit: Mention --show-snapshot-field-ranges option
2013-10-05 09:28:52 +03:00
Pavel Raiskup
f3c8bc7c3f Tiny change
* configure.ac (RSH): Define as AC_ARG_VAR.
2013-10-05 09:26:52 +03:00
Sergey Poznyakoff
576e1fcd6a Fix namespace contamination in testsuite.
* tests/append01.at: Use m4_pushdef/m4_popdef to define local macros.
* tests/delete03.at: Likewise.
* tests/exclude06.at: Likewise.
* tests/incr04.at: Likewise.
* tests/link03.at: Likewise.
* tests/long01.at: Likewise.
* tests/longv7.at: Likewise.
* tests/lustar01.at: Likewise.
* tests/lustar02.at: Likewise.
* tests/lustar03.at: Likewise.
* tests/multiv05.at: Likewise.
* tests/sparse04.at: Likewise.
2013-10-05 09:10:35 +03:00
Nathan Stratton Treadway
3125d311e1 Provide comprehensive testcases for various file removal modes.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
* tests/incr09.at: Add description.
* tests/remfiles04a.at: New file.
* tests/remfiles05.at: Rename to ...
* tests/remfiles04b.at: ... this.
* tests/remfiles04.at: Rename to ...
* tests/remfiles04c.at: ... this.
* tests/remfiles05a.at: New file.
* tests/remfiles05b.at: New file.
* tests/remfiles06.at: Rename to ...
* tests/remfiles05c.at: ... this.
* tests/remfiles06a.at: New file.
* tests/remfiles06b.at: New file.
* tests/remfiles06c.at: New file.
* tests/remfiles07a.at: New file.
* tests/remfiles07b.at: New file.
* tests/remfiles07c.at: New file.
* tests/remfiles08a.at: New file.
* tests/remfiles08b.at: New file.
* tests/remfiles08c.at: New file.
* tests/remfiles08.at: Rename to ...
* tests/remfiles09a.at: ... this.
* tests/remfiles09b.at: New file.
* tests/remfiles07.at: Rename to ...
* tests/remfiles09c.at: ... this.
2013-10-05 08:57:42 +03:00
Sergey Poznyakoff
74ce228f6d Tiny changes.
* src/misc.c: Fix comments, rename wd.cwd to wd.abspath (Nathan Stratton
Treadway);
* src/tar.c (options): Reword description of the --starting-file and
--preserve-order options.
(decode_options): Both --starting-file and --preserve-order have meaning
only when used together with an archive reading command. (Pavel Raiskup).
2013-10-03 22:41:04 +03:00
Sergey Poznyakoff
d28eee6b4f Revamp tar_getcwd/normalize_filename stuff.
The changes are based on the discussion with Nathan.

* src/common.h (normalize_filename): Take two arguments. All
callers updated.
(tar_getcwd): Replaced with ..
(tar_getcdpath): New proto.
* src/misc.c (normalize_filename): Take two arguments.
(chdir_arg): Populate cwd along with creating the
structure.
(tar_getcwd): Removed.
(tar_getcdpath): New function.

* tests/incr09.at: New test case.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Likewise.
2013-10-01 21:48:30 +03:00
Sergey Poznyakoff
d3fd92c6fb Bugfix
* tests/remfiles08.at: Restore missing find
2013-09-27 00:59:49 +03:00
Sergey Poznyakoff
f7077dd38b Use relative addressing in deferred unlinks.
* src/common.h (tar_dirname): New function.
* src/misc.c (normalize_filename_x): Make extern.
(tar_dirname): New function.
(tar_getcwd): Take into account absoulte pathnames.
* src/unlink.c (deferred_unlink) <dir_idx>: New member; keeps the
value of chdir_current at the moment of structure allocation.
(flush_deferred_unlinks): Use chdir_do and relative addressing.
(queue_deferred_unlink): Initialize dir_idx.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Add new tests.
* tests/remfiles06.at: Fix description.
* tests/remfiles07.at: Fix description.
* tests/remfiles08.at: New test case.
2013-09-26 15:46:44 +03:00
Nathan Stratton Treadway
5cb79ed519 Improve tar-snapshot-edit
Support architecture-specific field ranges for the "-c" function.
Better handle negative or larger-than-32-bit field values even
when running in 32-bit Perl (for the default "print a summary"
function)
2013-09-25 18:02:05 +03:00
Sergey Poznyakoff
b41b004638 Improve tar_getcwd
* src/common.h (tar_getcwd): Return pointer is const.
* src/misc.c (wd) <cwd>: New member.
(chdir_arg): Initialize cwd.
(tar_getcwd): Use cwd member to cache the result.  Take into
account absolute pathnames,
(normalize_filename): Don't free the value
returned from tar_getcwd.
* src/names.c (name_next_elt): Remove leftover call chdir().
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Likewise.

* tests/incr08.at: New testcase.
* tests/remfiles04.at: New testcase.
* tests/remfiles05.at: New testcase.
* tests/remfiles06.at: New testcase.
* tests/remfiles07.at: New testcase.
2013-09-25 16:04:21 +03:00
Sergey Poznyakoff
e3d28d84bd Fix normalize_filename.
The function did not take into account eventual -C options, which
in particular led to various problems when using -C and --remove-files
together.

* src/common.h (namebuf_add_dir,namebuf_finish)
(tar_getcwd): New prototypes.
* src/misc.c (namebuf_add_dir,namebuf_finish)
(tar_getcwd): New functions.
(normalize_filename): Use tar_getcwd.
2013-09-24 14:01:13 +03:00
Sergey Poznyakoff
2c06a80918 Changes for compatibility with Slackware installation scripts.
* src/buffer.c (short_read): the "Record size" message
is controlled by the WARN_RECORD_SIZE warning_option bit.
* src/common.h (keep_directory_symlink_option): New global.
(WARN_RECORD_SIZE): New constant.
(WARN_VERBOSE_WARNINGS): Add WARN_RECORD_SIZE.
* src/extract.c (extract_dir): If keep_directory_symlink_option is
set, follow symlinks to directories.
* src/suffix.c (compression_suffixes): Add support for txz
suffix.
* src/tar.c (KEEP_DIRECTORY_SYMLINK_OPTION): New constant.
(options): New option --keep-directory-symlink.
(parse_opt): Handle this option.
* src/warning.c: Implement "record-size" warning control.

* NEWS: Update.
* doc/tar.texi: Document new features.
2013-09-23 19:35:29 +03:00
Sergey Poznyakoff
570a2c5f3d Fix error message (complements 0ea6e686)
* src/tar.c (set_subcommand_option): Mention --delete in the error message.
2013-09-21 15:08:24 +03:00
Sergey Poznyakoff
b6979c7278 Improve the incr07 test 2013-09-15 20:38:57 +03:00
Nathan Stratton Treadway
751b61ab25 Implement the --show-snapshot-field-ranges option
* src/common.h (show_snapshot_field_ranges): New prototype.
* src/incremen.c (show_snapshot_field_ranges): New function.
* src/tar.c: New option --show-snapshot-field-ranges.
* doc/snapshot.texi: Document the --show-snapshot-field-ranges
option.
* doc/tar.texi: Likewise.
2013-09-15 16:02:30 +03:00
Sergey Poznyakoff
738fb9c2f4 Take into account chdir_fd when extracting from incremental dumps.
* src/common.h (tar_savedir): New prototype.
* src/misc.c (tar_savedir): New function.
(remove_any_file): Use tar_savedir.
* src/incremen.c (try_purge_directory): Use tar_savedir.
* src/update.c (update_archive): Use tar_savedir.
* tests/incr07.at: New testcase.
* tests/Makefile.am (TESTSUITE_AT): Add new test.
* tests/testsuite.at: Likewise.
* THANKS: Updated.
2013-09-15 10:13:45 +03:00
Sergey Poznyakoff
0ea6e68655 Minor fix
* src/tar.c (main): Mention --delete in the error message.
* THANKS: Update
2013-09-15 09:00:46 +03:00
Paul Eggert
dd549cc257 * src/names.c (file_list_name): Properly prototype. 2013-09-13 11:10:39 -07:00
Paul Eggert
28b44aaacb tar: don't warn about zero timestamps
* src/extract.c (check_time): Suppress warniing when t.tv_sec == 0.
Problem reported by Denis Excoffier.
2013-09-13 11:10:39 -07:00
Pavel Raiskup
88cb5008a6 Minor fix in the testsuite.
* tests/T-cd.at: sort the 'tar cf' output.
2013-08-19 14:26:18 +03:00
Sergey Poznyakoff
bff9c3637d Improve error diagnostics
* src/names.c (file_list_name): New static function.
(add_file_id): If a filelist is being read twice, print the names
of the files that caused it.
* tests/T-rec.at: New test case.
* tests/Makefile.am: Add new file.
* tests/testsuite.at: Include new file.
2013-08-17 13:48:24 +03:00
Sergey Poznyakoff
1fe0c83de4 Revamp initial name collection functions to ensure proper argument ordering.
* src/names.c (NELT_NOOP): New constant
(name_elt) <next,prev>: New members.
(name_array,allocated_entries,entries,scanned): Remove.
(check_name_alloc): Remove function.
(name_elt_alloc): New static.
(name_list_adjust,name_list_advance): New functions.
(name_add_name,name_add_dir)
(name_add_file): Use new allocation functions.
(read_next_name): Advance list head pointer as necessary
before returning.
(name_next_elt): Read elements from list.
* tests/T-cd.at: New file.
* tests/T-mult.at: New file.
* tests/T-nest.at: New file.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
2013-08-16 23:03:35 +03:00
Sergey Poznyakoff
077d7bceff Don't treat attempts to read an already read file list as fatal errors.
* src/names.c (add_file_id): Report error and return 1 if the file
has already been read.
(read_next_name): Don't try to open file if add_file_id returns 1.
(name_next_elt): Simplify conditional.
2013-08-16 15:17:22 +03:00
Sergey Poznyakoff
162bbcb45f Minor change.
* src/names.c (name_next_elt): Simplify conditional.
2013-08-16 14:29:51 +03:00
Pavel Raiskup
69007e652a Fix use of uninitialized memory
* src/names.c (name_add_file): Initialize the ep->v.file.fp pointer
after structure allocation.
2013-08-15 13:56:04 +03:00
Sergey Poznyakoff
95d7b37a34 Minor changes
* src/names.c (handle_option): Use program_invocation_short_name
instead of the constant string.
(read_next_name): Remove unused variable.
2013-08-05 15:14:08 +03:00
Sergey Poznyakoff
ddff3e9038 Update the docs.
* doc/tar.texi: Parsing of the options found in the file list
follows the same rules as for command line.  Remove the obsolete
description.  This complements 26538c9b.
2013-08-04 19:40:11 +03:00
Sergey Poznyakoff
47560a0498 Fix interacton of --verbose and --append.
* src/buffer.c (_open_archive): don't overwrite existing archive
if given the --verify option.
* tests/append04.at: New file.
* tests/Makefile.am: Add new testcase.
* tests/testsuite.at: Add new testcase.
* THANKS: Update.
2013-08-04 19:00:46 +03:00
Sergey Poznyakoff
6e5e4420f4 Bugfix.
* src/names.c (read_name_from_file): Fix a typo. Remove
unused variable.
2013-08-04 18:45:15 +03:00
Sergey Poznyakoff
26538c9bfc Reduce memory consuption when handling the -T option.
The commit cdb27293 made the -T option more flexible, but
incurred a very considerable memory overhead by storing
all file names in the argument array.  In case of very
big file lists this caused tar to run out of memory.  This
was reported by Christian Wetzel <wetzel@phoenix-pacs.de>
on March 14, 2013
(http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00018.html).

On the other hand, Michal Žeidl discovered that tar misfunctioned
when given empty file lists or lists with the trailing newline
misssing in the last entry.  This was reported by Pavel Raiskup
on July 23
(http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html and
msg00010.html).

This change fixes both issues.

* src/common.h (name_add_file,request_stdin): New prototype.
(more_options): New prototype.
* src/names.c (NELT_FILE): New entry type.
(name_elt) <file>: New union member.
(name_add_file): New function.
(read_name_from_file): New function, a rewrite of
the same function from tar.c
(read_next_name,copy_name): New static functions.
(name_next_elt): Handle NELT_FILE entries.
* src/tar.c (request_stdin): Make extern.
(read_name_from_file,add_file_id)
(update_argv): Removed.
(parse_opt): Change handling of the -T option.
(more_options): New function.

* tests/T-null.at: Rewrite test.
* tests/T-zfile.at: New file.
* tests/T-nonl.at: New file.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.

* THANKS: Update.
2013-08-04 18:22:02 +03:00
Sergey Poznyakoff
8a834dfa10 Fix the compatibility check for the --occurrence option.
* src/tar.c (SUBCL_OCCUR): New class.
(subcommand_class): Update.
(decode_options): Accept the --occurrence option
with any subcommand from the SUBCL_OCCUR class.
2013-06-29 15:05:21 +03:00
Pavel Raiskup
cf199be81d testsuite: do not resist on file order in archive
On my Fedora 19 box, the exclude08 & exclude11 tests failed before
this fix.  The reason was that the directory traversing chosen the
file order differently than the testsuite expected.

* tests/exclude08.at: Sort the tarball content output.
* tests/exclude09.at: Likewise.
* tests/exclude10.at: Likewise.
* tests/exclude11.at: Likewise.
* tests/exclude12.at: Likewise.
* tests/exclude13.at: Likewise.
* tests/exclude14.at: Likewise.
* tests/exclude15.at: Likewise.
* tests/exclude16.at: Likewise.
2013-06-29 10:45:45 +03:00
Sergey Poznyakoff
cfebb3cedf Improve checks for incompatible options.
* src/common.h (READ_LIKE_SUBCOMMAND): Remove define.
* src/tar.c (IS_SUBCOMMAND_CLASS): New macro.
(decode_options): Use IS_SUBCOMMAND_CLASS in checking
option compatibility.
Accept the --verify option only with subcommands that
write to the archive.

* tests/opcomp01.at: New test case.
* tests/opcomp02.at: New test case.
* tests/opcomp03.at: New test case.
* tests/opcomp04.at: New test case.
* tests/opcomp05.at: New test case.
* tests/opcomp06.at: New test case.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
2013-06-29 10:38:47 +03:00
Paul Eggert
87369861f9 tar: port to Mingw Shell
* src/extract.c (extract_symlink) [!HAVE_SYMLINK]:
Fix typo by replacing WARN_SYMBOLIC_CAST with WARN_SYMLINK_CAST.
Problem reported by kaka in
<http://lists.gnu.org/archive/html/bug-tar/2013-06/msg00008.html>.
2013-06-27 22:33:26 -07:00
Paul Eggert
f547c0332d maint: revert previous change
It wasn't actually needed.  Reported by Stefano Lattarini in
<http://lists.gnu.org/archive/html/bug-tar/2013-04/msg00041.html>.
* configure.ac (AM_GNU_GETTEXT_VERSION): Decrease from 0.18.2 back to 0.16.
2013-05-06 06:23:28 -07:00
Paul Eggert
57e5a7a1e7 maint: port to bleeding-edge Automake by assuming Gettext 0.18.2
Reported by Stefano Lattarini in
<http://lists.gnu.org/archive/html/bug-tar/2013-04/msg00009.html>.
* configure.ac (AM_GNU_GETTEXT_VERSION): Increase from 0.16 to 0.18.2.
README-alpha says that we do not make any efforts to accommodate
older versions of Gettext.
2013-04-24 21:22:23 -07:00
Paul Eggert
f678e47eb0 tar: port to --without-xattrs --enable-gcc-warnings
Reported by Pavel Raiskup in
<http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00029.html>.
* src/xattrs.c (xattrs__fd_set) [!HAVE_XATTRS]: Omit.
2013-04-24 21:06:54 -07:00
Paul Eggert
f92cb1fe16 doc: port to texinfo 5
* doc/tar.texi (Reports, assumptions, Mixing):
Put FIXMEs at line start.
2013-04-24 18:44:18 -07:00
Sergey Poznyakoff
beca89bccb Continue extracting from a separate volume after skipping a partial member.
Reported by Göran Udeborg on 2013-03-09.

* src/extract.c (extract_skip): New function.
(prepare_to_extract): Set extractor to extract_skip if starting
at a partial member.
2013-03-12 23:19:39 +02:00
Sergey Poznyakoff
a40e565719 Fix interaction of various --exclude-tag options with --listed-incremental.
* src/incremen.c (procdir): Set directory->tagfile in
the exclusion_tag_contents case.
(makedumpdir): Mark all entries as ignored if directory->tagfile
is set.
Free new_dump before returning.
(maketagdumpdir): New function.
(scan_directory): If directory->children is set to
NO_CHILDREN and directory->tagfile is set, create a
dumpdir consisting of the tagfile only.

* tests/exclude08.at: New testcase.
* tests/exclude09.at: New testcase.
* tests/exclude10.at: New testcase.
* tests/exclude11.at: New testcase.
* tests/exclude12.at: New testcase.
* tests/exclude13.at: New testcase.
* tests/exclude14.at: New testcase.
* tests/exclude15.at: New testcase.
* tests/exclude16.at: New testcase.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Include new tests.
* tests/atlocal.in (mkexcltest): New function.
* tests/chtype.at: Update keywords.
* tests/filerem01.at: Likewise.
* tests/filerem02.at: Likewise.
* tests/incremental.at: Likewise.
* tests/multiv04.at: Likewise.
2013-03-12 23:08:53 +02:00
Paul Eggert
17f99bc6f1 tar: remove lint
* lib/wordsplit.c (_wsplit_error): Mark with printf attribute.
(expvar): "Use" defstr to pacify GCC.
* src/system.c (xexec): Now _Noreturn, to pacify GCC.
(run_decompress_program): Add cast to pacify GCC.
(sys_exec_command, sys_exec_info_script, sys_exec_checkpoint_script):
Remove unused variables.
2013-02-20 08:10:10 -08:00
Sergey Poznyakoff
7b5e803963 Pass command line arguments to external commands.
Any option taking a command name as its argument accepts
additional arguments as well.

* lib/wordsplit.c: New file.
* lib/wordsplit.h: New file.
* lib/Makefile.am: Add new files.
* src/system.c (xexec): New function.
(run_decompress_program): Use wordsplit.
(sys_child_open_for_compress,sys_exec_command)
(sys_exec_info_script)
(sys_exec_checkpoint_script): Use xexec to invoke external
command.

* NEWS: Update.
* doc/tar.texi: Update.
2013-02-10 14:43:43 +02:00
Nathan Stratton Treadway
20dcc4d122 tar: improve compile-time diagnostics
* src/misc.c (sysinttostr, strtosysint): Improve #error wording.
2013-01-28 22:49:08 -08:00
Paul Eggert
9cf743abf8 tar: improve quality of diagnostics with incrementals
Inspired by a prototype by Nathan Stratton Treadway in
<http://lists.gnu.org/archive/html/bug-tar/2013-01/msg00000.html>.
* src/incremen.c (read_num): Rewrite by merging read_negative_num
and read_unsigned_num.  Use strtosysint rather than rolling this
stuff ourselves.  Change return type to bool.  All uses changed.
(read_negative_num, read_unsigned_num): Remove.
(read_num, read_timespec, read_incr_db_2): Improve quality of
diagnostics, e.g., by supplying byte offset of error.
2013-01-27 08:42:06 -08:00
Paul Eggert
2f6c03cba2 tar: fix bug with sparse files with effective size of 8 GiB or more
Reported by Pavel Raiskup in
<http://lists.gnu.org/archive/html/bug-tar/2013-01/msg00001.html>.
* NEWS: Document the fix.
* src/sparse.c (pax_start_header): New function.
(pax_dump_header_0, pax_dump_header_1): Use it.
2013-01-26 09:54:02 -08:00
Paul Eggert
cd7bdd4076 maint: update copyrights for 2013 and as per current GNU standards 2012-12-31 13:17:15 -08:00
Paul Eggert
d99ecd6c75 maint: remove unnecessary file
* src/configure.in: Remove.  This file has been obsolete for a while.
2012-12-31 13:17:06 -08:00
Paul Eggert
53358983eb maint: don't enable warnings by default unless GCC 4.6 or later
* configure.ac (gl_GCC_VERSION_IFELSE): New macro, from coreutils.
(gl_gcc_warnings): By default, disable warnings for GCC versions
before 4.6.  This works around a failure when building from git on
Ubuntu 10, reported privately by Nathan Stratton Treadway.
2012-12-23 17:11:05 -08:00
Paul Eggert
7c43775f4f Handle incremental format 2 with negative numbers, too.
* src/incremen.c (read_unsigned_num): Last arg is intmax_t *, not
uintmax_t, for consistency with other readers.  All callers changed.
Avoid signed integer overflow.
(read_num):
2012-12-22 22:28:04 -08:00
Paul Eggert
df7b55a8f6 Fix some problems with negative and out-of-range integers.
Original problem reported for HP-UX LVM v2.2 by Michael White in
<http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00000.html>.
This patch fixes some other gotchas that I noticed.
* gnulib.modules: Add extern-inline.
* src/common.h: Use _GL_INLINE_HEADER_BEGIN, _GL_INLINE_HEADER_END.
(COMMON_INLINE, max, min): New macros.
(represent_uintmax, valid_timespec): New inline functions.
(SYSINT_BUFSIZE): New constant.
(sysinttostr, strtosysint, decode_timespec): New decls.
* src/create.c (start_private_header): Silently bring the time_t
value into range; it is now the caller's responsibility to deal
with any overflow error.  Use uid 0 and gid 0 rather than the
user's uid/gid, since the faked header isn't "owned" by the user
and the uid/gid could in theory be out of range.  Leave major and
minor zeroed.
(FILL): Remove.
(write_gnu_long_link): Let start_private_header zero things out.
* src/create.c (write_gnu_long_link, write_extended):
* src/xheader.c (xheader_write_global):
Use start_time, not current time; no point hammering on the clock.
* src/compare.c (diff_multivol): Check that offset, size are in range.
* src/incremen.c (read_incr_db_01, write_directory_file_entry):
Allow negative time_t, dev_t, and ino_t.
* src/list.c (max): Remove (moved to common.h).
(read_header): Check that size is in range.
(from_header): Return intmax_t, not uintmax_t, to allow negative.
All callers changed.  At compile time, check assumptions about
intmax_t and uintmax_t.  Use bool for booleans.  Avoid overflow
hassles on picky hosts.
(mode_from_header): Last arg is now bool *, not unsigned *.
All callers changed.
(simple_print_header): Do not assume UID, GID fit in 'long'.
* src/list.c (from_header):
* src/xheader.c (out_of_range_header):
Arg is now a plain minimum value, not minus minval converted to
uintmax_t.  All callers changed.
* src/misc.c (COMMON_INLINE): New macro.
(sysinttostr, strtosysint, decode_timespec): New functions.
* src/sparse.c (oldgnu_add_sparse, oldgnu_fixup_header)
(star_fixup_header):
Check for offset overflow.
(decode_num): Clear errno before calling strtoumax.
* src/tar.c (expand_pax_option): Don't discard nanoseconds.
* src/xheader.c (assign_time_option): Allow negative time_t.
(decode_record): Simplify, since out-of-range string is guaranteed
to produce a value exceeding len_max.
(xheader_read): Last arg is off_t, not size_t.
Caller should diagnose negative arg, as needed.
Check that it's in range.
(enum decode_time_status): Remove.
(_decode_time): Remove, folding into decode_time.
(decode_time): Return bool, not enum decode_time_status.
Rely on decode_timespec to do most of the work.
(code_signed_num): New function.
(code_num): Use it.
(decode_signed_num): New function.
(decode_num): Use it.
(gid_coder, gid_decoder, uid_coder, uid_decoder, sparse_map_decoder)
(sparse_map_decoder): Code and decode negative values.
(sparse_map_decoder): Improve check for out-of-range values.
* tests/time01.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2012-12-22 20:41:52 -08:00
Paul Eggert
d8ac237663 Port use of mkdirat etc. to Solaris 10.
* gnulib.modules (fchmodat, fchownat, fstatat, mkdirat, unlinkat):
Add.  These were split out in gnulib, so we now need to request
them separately.  mkdirat, for example, is not in Solaris 10.
2012-12-22 13:25:39 -08:00
Paul Eggert
f39eadac4b Port ACL configuration to Solaris 10.
* configure.ac (with_posix_acls): Fix misspellings.
Stop checking at the first failure, to speed up 'configure'.
2012-12-22 13:25:33 -08:00
Paul Eggert
8ebbef8a15 tar: remove unused externs, or make them static
* src/buffer.c (record_buffer_aligned, flush_write_ptr, flush_read_ptr)
(duration):
* src/list.c (recent_global_header):
* src/unlink.c (deferred_unlink_delay):
* src/transform.c (transform_flags):
* src/xattrs.c (acl_get_file_at, acl_set_file_at, file_has_acl_at):
Now static.
* src/common.h (rmt_command_option): Remove; unused.
* src/tar.c (check_links_option, allocated_archive_names):
Move decls here from common.h; these are now static.
2012-12-19 12:34:24 -08:00
Paul Eggert
616e421350 * .gitignore: Regenerate. 2012-12-19 12:34:19 -08:00
Paul Eggert
cbc51277aa build: new configure option --enable-gcc-warnings
This has a similar meaning as in other GNU applications
such as coreutils and Emacs.
* NEWS: Document it.
* .gitignore: Remove redundant build-aux.
Remove gnu, since gnu/Makefile.am is now in git.
Add gnu/.gitignore, gnu/charset.alias, gnu/*.h, gnu/*/ to cover
autogenerated files.
* bootstrap.conf (gnulib_mk): Remove.
* configure.ac: Add support for --enable-gcc-warnings,
taken from coreutils and simplified.
* gnu/Makefile.am: New file.  Formerly this was autogenerated,
but the autogenerated file has been renamed to gnulib.mk,
its usual name when bootstrapping from gnulib.
This way, AM_CFLAGS can incorporate warning options.
* gnulib.modules: Add manywarnings.
* lib/Makefile.am, src/Makefile.am (AM_CFLAGS): New macro,
incorporating warning options.
* lib/attr-xattr.in.h (ENOATTR): New macro, if not already defined.
* src/buffer.c (magic): Don't rely on incomplete initializers.
* src/common.h (report_difference): Add printf format attribute.
* src/system.c (sys_exec_command, sys_exec_info_script)
(sys_exec_checkpoint_script):
* src/tar.c (update_argv):
Add casts to char * to pacify GCC warnings about using string
literals in a char * context.
* src/xattrs.c, src/xattrs.h (xattrs_clear_setup):
Declare parameters as (void), not ().
* src/xheader.c (xheader_format_name): Initialize pptr to null,
to pacify GCC.  Remove unnecessary test of nptr versus null.
2012-12-18 20:37:03 -08:00
Paul Eggert
8c0146d2c9 tar: don't truncate diagnostic
* src/list.c (from_header): Fix buffer size calculation when
generating a diagnostic.
2012-12-18 20:36:57 -08:00
Sergey Poznyakoff
4bfa82acd5 Bugfix.
* tests/Makefile.am: Fix double AM_CPPFLAGS
2012-12-03 23:54:19 +02:00
Sergey Poznyakoff
d350b509c0 Use AM_CPPFLAGS instead of INCLUDES. 2012-12-01 19:07:47 +02:00
Sergey Poznyakoff
383701a590 Housekeeping.
* NEWS: Mention the support for POSIX ACLs, extended
attributes and SELinux context.
* THANKS: List James Antill and Pavel Raiskup.
2012-11-19 23:51:09 +02:00
Sergey Poznyakoff
545e4cd69d Fix indentation. 2012-11-19 23:29:55 +02:00
Pavel Raiskup
a974e9c997 Allow to store/extract '=' character in xattr keyword
* src/xheader.c (xattr_decode_keyword)
(xattr_encode_keyword): New functions.
(xheader_print_n,xattr_decoder): Use them.
* tests/xattr05.at: New test case.
* tests/Makefile.am: Add new test case.
* tests/testsuite.at: Likewise.
2012-11-19 23:25:49 +02:00
Pavel Raiskup
4a3564fe85 Bugfixes.
* configure.ac: Avoid linking against -lacl when
--without-posix-acls is given.
* tests/selacl01.at: Call restorecon
* tests/selnx01.at: Likewise.
* tests/testsuite.at (AT_SELINUX_UTILS_PREREQ): Likewise.
(AT_SELINUX_PREREQ,AT_ACLS_PREREQ): Use the right _PREREQ macros.
2012-11-19 23:08:04 +02:00
Pavel Raiskup
6bd463c97e Fix bootstrapping.
* bootstrap (gnulib_extra_files): Remove $build_aux/missing
2012-11-19 22:54:17 +02:00
Sergey Poznyakoff
3c4e51fad6 Various fixes.
* src/xattrs.c: Don't mix variable declarations and statements.
Use proper data types.  Remove improper use of const qualifiers.
Use x2nrealloc to reallocate memory buffers.
2012-11-19 00:14:31 +02:00
Sergey Poznyakoff
4ac671c49b Minor change.
* src/xattrs.c: Fix indentation. Fix copyleft statement, promote to GPLv3+.
* src/xattrs.h: Likewise
2012-11-18 23:05:00 +02:00
Pavel Raiskup
085cace180 Add SELinux context store/restore/list support.
* gnulib.modules: Add selinux-at.
* src/Makefile.am (tar_LDADD): Add LIB_SELINUX.

* src/create.c (start_header, dump_file0): Handle selinux contexts.
* src/extract.c (delayed_set_stat) <cntx_name>: New member.
(delayed_link) <cntx_name>: New member.
(set_stat, delay_set_stat)
(apply_nonancestor_delayed_set_stat): Handle selinux contexts.
* src/tar.c: New options: "--selinux", "--no-selinux".
(tar_stat_destroy): Free cntx_name.
* src/tar.h (tar_stat_info) <cntx_name>: New member.
* src/xattrs.c (xattrs_selinux_get)
(xattrs_selinux_set): New functions.
(xattrs_print_char): Honor selinux_context_option.
(xattrs_print): Print selinux context.
* src/xheader.c: Handle new keyword "RHT.security.selinux".
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Likewise.
* tests/selacl01.at: New test.
* tests/selnx01.at: New test.
2012-11-18 22:28:01 +02:00
Pavel Raiskup
d36f5a3cc3 Support for POSIX ACLs
* configure.ac: Check whether ACLs are available on the
host system.
* gnulib.modules: Add acl
* src/create.c (start_header): Store ACLs when creating
a POSIX archive.
(dump_file0): Handle ACLs.
* src/extract.c (delayed_set_stat) <acls_a_ptr, acls_a_len>
<acls_d_ptr, acls_d_len>: New members.
(delayed_link): Likewise.
(set_stat,delay_set_stat)
(apply_nonancestor_delayed_set_stat): Set ACLs.
* src/tar.c: New options: "--acls", "--no-acls"
(tar_stat_destroy): Free acls_a_ptr and acls_d_ptr fields.
* src/tar.h (tar_stat_info) <acls_a_ptr, acls_a_len>
<acls_d_ptr, acls_d_len>: New members.
* src/xattrs.c (xattrs_acls_get, xattrs_acls_set): New functions.
* src/xheader.c: Support new keywors: "SCHILY.acl.access" and
"SCHILY.acl.default".
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Likewise.
* tests/acls01.at: New test.
* tests/acls02.at: New test.
2012-11-18 20:54:02 +02:00
Pavel Raiskup
696338043e Add basic suuport for extended attributes.
* src/Makefile.am: Add xattrs.[ch]
* src/xattrs.c: New file.
* src/xattrs.h: New file.
* src/common.h (READ_LIKE_SUBCOMMAND): New define.
(selinux_context_option, acls_option, xattrs_option): New globals.
(xheader_xattr_init, xheader_xattr_free)
(xheader_xattr_copy, xheader_xattr_add): New protos.
(WARN_XATTR_WRITE): New mask.
* src/create.c (start_header): Handle xattrs pairs if in POSIX format.
(dump_file0): Handle extended attributes.
* src/extract.c (delayed_set_stat,delayed_link) <xattr_map_size>
<xattr_map>: New members.
(set_xattr): New static function.
(open_output_file): Accept an additional argument indicating
whether the file has already been created.
(set_stat,delay_set_stat)
(apply_nonancestor_delayed_set_stat)
(extract_file): Handle extended attributes.
* src/list.c (decode_header, simple_print_header): Display
extended attributes.
* src/tar.c: New options --xattrs, --no-xattrs, --xattrs-include,
--xattrs-exclude
(tar_stat_destroy): Free the xattr_map storage.
* src/tar.h (xattr_array): New struct.
(tar_stat_info) <xattr_map_size, xattr_map>: New members.
* src/warning.c: New warning control keyword "xattr-write".
* src/xheader.c (xheader_xattr_init)
(xheader_xattr_free, xheader_xattr_add)
(xheader_xattr_copy): New functions.
(struct xhdr_tab) <prefix>: New member.
(locate_handler): Permit selecting the keyword based on its
prefix.
(xheader_protected_pattern_p)
(xheader_protected_keyword_p): Likewise.
(xattr_coder, xattr_decoder): New functions.
(xhdr_tab): Reflect the changes to struct xhdr_tab.
New keyword "SCHILY.xattr".
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Likewise.
(AT_CHECK_UTIL, AT_XATTRS_UTILS_PREREQ)
(AT_CAPABILITIES_UTILS_PREREQ, AT_XATTRS_PREREQ): New defuns.
* tests/xattr01.at: New test.
* tests/xattr02.at: New test.
* tests/xattr03.at: New test.
* tests/xattr04.at: New test.
* tests/capabs_raw01.at: New test.
2012-11-18 20:15:03 +02:00
Sergey Poznyakoff
b997c90f9e Prepare for implementing extended attribute support.
This patch adds *xattr() stubs in case extended attribute support is
not present and implements the *attrat() family of functions.  Based
on the patch by Pavel Raiskup <pavel@raiskup.cz> for gnulib.

* acinclude.m4 (TAR_HEADERS_ATTR_XATTR_H): New defun.
* configure.ac: Call TAR_HEADERS_ATTR_XATTR_H
* lib/Makefile.am: Add xattr-at.[ch], distribute attr-xattr.in.h
[!TAR_COND_XATTR_H]: Build attr/xattr.h
* lib/attr-xattr.in.h: New file.
* lib/xattr-at.c: New file.
* lib/xattr-at.h: New file.
2012-11-18 19:55:43 +02:00
Sergey Poznyakoff
643a8844a5 Fix creation of incremental archives when a subdirectory becomes a mountpoint.
When used with --listed-incrfental and --one-file-system, tar
was unable to cope with directories that had once been part of the
dumped system and became separate mount points afterwards.  The bug
has been reported and a fix proposed by Nathan Stratton Treadway.

* src/incremen.c (procdir): If one_file_system_option is in effect,
clear out dumpdir info from the directory.
* tests/Makefile.am: Add new testcase.
* tests/listed05.at: New testcase.
* tests/testsuite.at (AT_PRIVILEGED_PREREQ): New macro.
include listed05.at.
* THANKS: Update.
2012-11-14 09:09:47 +02:00
Jim Meyering
099f71f78d maint: try to avoid unwanted chatter in ChangeLog
* bootstrap.conf: Do not alter ChangeLog if it already exists.
2012-07-27 01:32:31 -07:00
Paul Eggert
07ef59cab8 doc: improve discussion of compressed archives
* doc/tar.texi (gzip): Don't claim that -I 'gzip --best' works.
Problem reported by Davide Brini in
<http://lists.gnu.org/archive/html/bug-tar/2012-07/msg00025.html>.
Also, improve some of the surrounding text.

This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist.  Run make ChangeLog if you wish to create it earlier.
2012-07-26 08:50:17 -07:00
Paul Eggert
0708c153e4 tests: fix permissions-assumption bug in test
* tests/owner.at: Don't assume umask is 022.
Reported by Pavel Raiskup in
<http://lists.gnu.org/archive/html/bug-tar/2012-06/msg00015.html>.
2012-06-27 09:56:31 -07:00
Paul Eggert
1cd2725227 tar: don't assume root is uid 0
This is not true for Tandem NonStop Kernel.  See Joachim Schmitz's
comment in <http://bugs.gnu.org/10305#111>.
* gnulib.modules: Add root-uid.
* src/extract.c: Include <root-uid.h>.
(extr_init): Don't assume root is uid 0.
2012-06-26 17:15:21 -07:00
Paul Eggert
6a61354ea0 * src/compare.c (diff_dumpdir): Omit useless 'stat'. 2012-04-24 22:06:00 -07:00
Paul Eggert
273dfb16cc * doc/tar.texi (Option Summary): Fix xref typo.
Reported by Nathan Stratton Treadway in
<http://lists.gnu.org/archive/html/bug-tar/2012-04/msg00035.html>.

This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist.  Run make ChangeLog if you wish to create it earlier.
2012-04-24 21:39:56 -07:00
Sergey Poznyakoff
2a61a3701f Fix unrecognized option.
* src/tar.c (parse_opt): Handle OLD_ARCHIVE_OPTION.
2012-03-29 08:57:29 +03:00
Paul Eggert
5bb0433507 tar: remove lint
This lint was found by GCC 4.6.2 on Fedora 15 x86-64.
* src/buffer.c (buffer_write_global_xheader, mv_end, set_start_time)
(compute_duration, print_total_stats, flush_read, flush_write):
* src/checkpoint.c (checkpoint_finish_compile):
* src/list.c (test_archive_label):
* src/misc.c (chdir_count):
* src/names.c (const):
* src/unlink.c (finish_deferred_unlinks):
Define with (void) instead of with (), for slightly-better C type
checking and to avoid a GCC warning.
* src/compare.c (diff_dumpdir):
* src/tar.c (parse_owner_group): Remove unused local.
* src/misc.c (chdir_do):
* src/tar.c (add_exclude_array): Rename local to avoid shadowing.
(LOW_DENSITY_NUM, MID_DENSITY_NUM, HIGH_DENSITY_NUM):
Define only if needed.
* src/update.c (update_archive): Initialize a local; this fixes
what appears to be a real bug.
2012-03-11 13:01:51 -07:00
Paul Eggert
8c75b1387a doc: suggest Bash for large-fd script
* doc/tar.texi (Multi-Volume Archives): Suggest Bash for shell
script that might use >&10.  Problem reported by Edward F Eaglehouse in
<http://lists.gnu.org/archive/html/bug-tar/2012-02/msg00002.html>.
2012-02-14 10:18:30 -08:00
Paul Eggert
debc485626 tar: quote 'like this', not `like this'
This fixes some test failures recently introduced by gnulib updates
prompted by recent changes to the GNU coding standards,
which now advise to use quotes 'like this' or "like this"
rather than `like this'.
* NEWS: Document this.
* README, README-hacking, doc/Makefile.am, scripts/backup.in:
* scripts/backup.sh.in, scripts/dump-remind.in:
* src/buffer.c, src/checkpoint.c, src/create.c, src/incremen.c:
* src/misc.c, src/names.c, src/sparse.c, src/transform.c:
* tests/incr02.at, tests/incremental.at, tests/multiv08.at:
* tests/sparse04.at, tests/star/README, tests/update01.at:
Quote 'like this' in comments.
* src/tar.h:
Quote "like this" in comments, when quoting English phrases rather
than code.
* configure.ac:
* scripts/xsparse.c (get_var, read_xheader, main):
* src/compare.c (diff_archive):
* src/extract.c (prepare_to_extract):
* src/tar.c (request_stdin, tar_set_quoting_style, doc, options)
(set_subcommand_option, report_textual_dates, parse_opt)
(decode_options, main):
* src/xheader.c (decx):
Quote 'like this' in diagnostics.
* doc/tar.texi (list, warnings, override)
(Selecting Archive Members, quoting styles, after, hard links)
(Sparse Recovery, Multi-Volume Archives, label):
Adjust documentation to match new output.
* tests/backup01.at, tests/incr01.at, tests/incr04.at:
* tests/label04.at, tests/label05.at, tests/link03.at:
* tests/listed02.at, tests/multiv03.at, tests/multiv05.at:
* tests/rename01.at, tests/rename02.at, tests/rename03.at:
* tests/volume.at:
Adjust tests to match new quoting behavior.
2012-01-18 00:25:23 -08:00
Paul Eggert
6689e8db4f tar: port --overwrite symlink test to GNU/Hurd
Problem reported by Pino Toscano in
<http://lists.gnu.org/archive/html/bug-tar/2012-01/msg00040.html>.
* gnulib.modules: Add fcntl-h, which defines
HAVE_WORKING_O_NOFOLLOW.
* src/extract.c (open_output_file): Use HAVE_WORKING_O_NOFOLLOW,
not O_NOFOLLOW, when testing whther O_NOFOLLOW works.

This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist.  Run make ChangeLog if you wish to create it earlier.
2012-01-17 22:22:23 -08:00
Paul Eggert
9a82a0215b tar: fix core dump with --index-file=bad_path
* src/tar.c (decode_options): Exit cleanly if index file won't open.
Problem reported by Khanh-Dang Nguyen Thu Lam in
<http://lists.gnu.org/archive/html/bug-tar/2012-01/msg00018.html>.
2012-01-11 11:37:33 -08:00
Paul Eggert
03858cf583 tar: don't assume O_NONBLOCK is benign on regular files
On Data Migration Facility (DMF), High Peformance Storage System (HPSS),
and presumably other file systems based on hierarchical storage, opening
a regular file with O_NONBLOCK can cause later reads to fail with
errno == EAGAIN.  We need the O_NONBLOCK to avoid some security races.
Work around the problem by using fcntl to clear the O_NONBLOCK
flag if I/O fails with that errno value.
Problem reported by Vitezslav Cizek in
<http://lists.gnu.org/archive/html/bug-tar/2012-01/msg00000.html>.
* src/common.h (blocking_read, blocking_write): New decls.
* src/misc.c (blocking_read, blocking_write): New functions.
* src/compare.c (process_rawdata):
* src/create.c (dump_regular_file):
* src/extract.c (extract_file):
* src/sparse.c (sparse_scan_file, sparse_extract_region):
2012-01-06 12:40:47 -08:00
Sergey Poznyakoff
7a5a3708cb Fix --keep-old-files option.
The regression was introduced by 8f390db9.  This patch implements additional
option --skip-old-files, which silently skips members which would cause
writing over existing files, and restores --keep-old-files to its traditional
behavior.

* NEWS: Update.
* configure.ac: Update.
* doc/tar.texi: Document the changes.
* src/common.h (SKIP_OLD_FILES): New old_files mode.
* src/extract.c (maybe_recoverable): Restore KEEP_OLD_FILES behavior.
Handle SKIP_OLD_FILES.
* src/tar.c: New option --skip-old-files.
* tests/extrac18.at: New file.
* tests/extrac19.at: New file.
* tests/Makefile.am: Add new test cases.
* tests/testsuite.at: Likewise.
2011-11-26 15:50:40 +02:00
Sergey Poznyakoff
02bf3a96a9 Warn about existing files in keep-old-files mode (complements 8f390db9).
This is controlled by "existing-file" warning code, which is off
by default.

* src/common.h (WARN_EXISTING_FILE): New warning code.
(WARN_VERBOSE_WARNINGS): Add WARN_EXISTING_FILE.
* src/extract.c (maybe_recoverable): warn about existing file
if WARN_EXISTING_FILE is set.
* src/warning.c: New warning type: "existing-file"
2011-11-17 22:19:05 +02:00
Sergey Poznyakoff
79138eaef1 Fix the "Creating directory:" output
* src/list.c (print_for_mkdir): don't use unquoted name length for
computing its output width.
2011-11-17 10:27:52 +02:00
Sergey Poznyakoff
d88b2a613f Fix operation of --verify in conjunction with --listed-incremental
* src/common.h (clear_directory_table): New proto.
* src/incremen.c (clear_directory_table): New function.
* src/compare.c (diff_dumpdir): Take a pointer to struct
tar_stat_info as argument.
Initialize its fd.
(diff_archive): Update call to diff_dumpdir.
(verify_volume): Call clear_directory_table.
2011-11-15 13:23:44 +02:00
Paul Eggert
1e1fc0336b * doc/tar.texi (Option Summary, absolute): Document -P better,
by describing how it deals with symbolic links on extraction.
2011-10-18 13:07:29 -07:00
Paul Eggert
02533d1a60 2011-09-27 Paul Eggert <eggert@cs.ucla.edu>
* src/tar.c (stat_on_signal): Use SA_RESTART if available.
2011-09-27 21:22:15 -07:00
Paul Eggert
d0dd0473f7 * doc/tar.texi: Remove front- and back-cover texts.
These are no longer needed for this manual, according to the
GNU maintainers guide.	Update copyright date to 2011.
2011-09-20 10:29:30 -07:00
Sergey Poznyakoff
8f70a3294c Minor changes.
* scripts/tar-snapshot-edit: License under GPLv3+.
Remove trailing whitespace.
2011-09-19 20:23:40 +03:00
Nathan Stratton Treadway
a6cc856fbe Minor changes.
* doc/snapshot.texi: Clarify the use of nfs field in 0 and 1 formats.
Give more precise information about which versions of tar used each
format.
2011-09-19 16:13:47 +03:00
Nathan Stratton Treadway
51b272f572 Upgrade tar-snapshot-edit script.
* scripts/tar-snapshot-edit: Update Perl syntax to work
correctly with more recent versions of Perl.  (The original
code worked with in the v5.8 timeframe but not with
Perl v5.10.1 and later.)
Add a "-c" option to check the snapshot file for invalid
field values.
Handle NFS indicator character ("+") in version 0 and 1 files.
Preserve the original header/version line when editing version 1
or 2 files.
Tweak output formatting.
* doc/tar-snapshot-edit.texi: Update documentation.
2011-09-19 15:29:00 +03:00
Paul Eggert
1f9b376c90 tar: --owner and --group names and numbers
The --owner and --group options now accept operands of the form
NAME:NUM, so that you can specify both symbolic name and numeric
ID for owner and group.  Also, in these options, NAME no longer
needs to be present in the current host's user and group
databases; this implements Debian enhancement request 136231
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=136231> reported
by Mark W. Eichin, communicated by Thayne Harbaugh to bug-tar in
<http://lists.gnu.org/archive/html/bug-tar/2011-08/msg00001.html>.
* NEWS, doc/tar.texi (Option Summary, override): Document enhancement.
* src/common.h (group_name_option, owner_name_option): New decls.
* src/create.c (start_header): Don't assume owner and group names
are in current host database.
* src/tar.c (parse_owner_group): New function, for parsing NAME:NUM.
(parse_opt): Use it.
(decode_options): Initialize owner_name_option, group_name_option.
* tests/owner.at: New file, to test this enhancement.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2011-08-13 10:20:40 -07:00
Paul Eggert
9fe65e2520 .gitignore: update
* .gitignore: Add rmt.
* lib/.gitignore: New file.
2011-08-13 10:20:40 -07:00
Sergey Poznyakoff
fa307a6655 Fix the --exclude-backups option.
* src/tar.c (add_exclude_array): Take exclude option filags in its
second argument.
(parse_opt): Register backup_file_table with the EXCLUDE_WILDCARDS flag.
* tests/exclude07.at: New testcase.
* tests/Makefile.am (TESTSUITE_AT): Add testsuite.at.
* tests/testsuite.at: Include exclude07.at.
2011-07-30 18:26:38 +03:00
Paul Eggert
49bd102a1b tar: simplify birthtime calculations
* src/extract.c (same_birthtime): Remove.
(extract_link, apply_delayed_links): Go back to using timestamp_cmp
instead of same_birthtime, as this is a bit simpler.  This fix relies
on an up-to-date gnulib.
2011-06-07 16:07:29 -07:00
Paul Eggert
189e436474 tar: use birthtime rather than ctime when checking identity
Without this fix, tar would sometimes mishandle the extraction of
hard links to symbolic links.  Problem reported in
<http://lists.gnu.org/archive/html/bug-tar/2011-06/msg00000.html>
by Andreas Stolcke.
* src/extract.c (struct delayed_link): Change ctime member to birthtime.
(same_birthtime): New function.
(create_placeholder_file, extract_link, apply_delayed_links):
Use it to compare birthtimes (when available) instead of ctime.
2011-06-07 15:18:01 -07:00
Paul Eggert
9708b248e8 * doc/tar.texi (Old Options): Clarify distinction from short options.
Adjust other parts of the manual to use examples that parse the
same regardless of whether "-" is in front of the option clump.  See
<http://lists.gnu.org/archive/html/bug-tar/2011-05/msg00022.html>.
2011-05-26 12:10:39 -07:00
Sergey Poznyakoff
afcdb89492 Testsuite fix.
* tests/sparse04.at: Use the -f option.
2011-03-12 22:22:21 +02:00
Sergey Poznyakoff
aea443b9e8 Version 1.26
* NEWS, configure.ac: Update.
* po/POTFILES.in: Remove paxexit.c (see bb971a1e).
2011-03-12 12:20:07 +02:00
Paul Eggert
881e5626c5 --atime-preserve=replace: fix correctness and performance bugs
reported by Eric Blake in
<http://lists.gnu.org/archive/html/bug-tar/2011-03/msg00000.html>.
* src/compare.c (diff_file): Do not restore atime of size-zero files.
* src/create.c (dump_file0): Likewise.  Also, do not restore atime
when fd is zero, because that indicates a file we haven't opened.
2011-03-07 15:40:56 -08:00
Paul Eggert
67ae04ba31 * doc/tar.texi: Adjust example commands and output for accuracy.
The original problem was reported by Michael Witten in
<http://lists.gnu.org/archive/html/bug-tar/2011-02/msg00033.html>.
2011-02-22 16:41:10 -08:00
Paul Eggert
2807513841 tar: if (p) free (p); -> free (p);
There is no longer (since SunOS 4) any need to guard against
free (NULL), so replace each "if (p) free (p);" with "free (p);".
From Jim Meyering in
<http://lists.gnu.org/archive/html/bug-tar/2011-01/msg00026.html>.
* src/incremen.c (scan_directory, read_directory_file): As above.
(try_purge_directory): Likewise.
* src/list.c (read_header): Likewise.
* src/misc.c (assign_string): Likewise.
2011-02-16 13:47:28 -08:00
Sergey Poznyakoff
bb0af96c54 Correctly store long sparse file names in PAX archives.
* src/sparse.c (pax_dump_header_1): Make sure the created header name is
shorter than NAME_FIELD_SIZE bytes.
* tests/sparse04.at: New testcase.
* tests/Makefile.am (TESTSUITE_AT): Add sparse04.at.
* tests/testsuite.at: Include sparse04.at.
* NEWS: Update.
2010-12-14 15:27:55 +02:00
Paul Eggert
ec586b37e0 tests: make the truncate test smaller and less buggy (tiny change)
Reported by Solar Designer in
<http://lists.gnu.org/archive/html/bug-tar/2010-12/msg00003.html>.
* tests/truncate.at: Use a smaller test case, and make its
race condition less likely.
2010-12-06 14:27:29 -08:00
Paul Eggert
a7fc5ecead tests: skip SIGPIPE-dependent tests in environments ignoring SIGPIPE
Problem reported by Sven Joachim in
<http://lists.gnu.org/archive/html/bug-tar/2010-11/msg00043.html>.
* tests/remfiles01.at: Use AT_SIGPIPE_PREREQ.
* tests/sigpipe.at: Likewise.
* tests/testsuite.at (AT_SIGPIPE_PREREQ): New macro.
2010-11-26 19:36:05 -08:00
Paul Eggert
649b747913 tar: work around NetBSD and Tru64 symlink incompatibility with POSIX
Problem reported by Bruno Haible in
<http://lists.gnu.org/archive/html/bug-gnulib/2010-11/msg00306.html>.
* src/extract.c (maybe_recoverable):  Also treat EFTYPE (if defined)
and ENOTSUP like ELOOP.
2010-11-24 23:08:07 -08:00
Paul Eggert
bb971a1e8a tar: adjust to paxutils change: paxexit.c -> paxexit-status.c
* lib/Makefile.am (libtar_a_SOURCES): paxexit.c renamed to
paxexit-status.c.
2010-11-23 21:41:50 -08:00
Paul Eggert
50a57a0147 tar: remove unused function dir_removed_diag
* src/common.h (dir_removed_diag): Remove unused decl.
* src/misc.c (dir_removed_diag): Remove unused function.
2010-11-23 17:56:58 -08:00
Paul Eggert
1584b72ff2 tar: work around FreeBSD symlink incompatibility with POSIX
* src/extract.c (maybe_recoverable): Treat EMLINK like ELOOP, for
FreeBSD.  Problem reported by Christian Weisgerber in
<http://lists.gnu.org/archive/html/bug-tar/2010-11/msg00080.html>.
2010-11-23 12:58:09 -08:00
Paul Eggert
065cf0958c * src/names.c: tar: fix bug with --one-file-system --listed-incremental
Problem (and idea for fix) reported by Martin Weigel
<http://lists.gnu.org/archive/html/bug-tar/2010-11/msg00071.html>.
* src/common.h (is_individual_file): Remove decl.
* src/create.c (dump_file0): Replace "is_individual_file (p)"
with "top_level".
* src/incremen.c (procdir): Replace "!is_individual_file
(name_buffer)" with "st->parent".  Fix bug with --one-file-system
and --listed-incremental.
* src/names.c (individual_file_table, register_individual_file):
(is_individual_file): Remove.  All uses removed.
2010-11-22 22:51:29 -08:00
Paul Eggert
2a55b4b037 tests: new test listed04 for --one-file-system --listed-incremental
* tests/Makefile.am (TESTSUITE_AT): Add listed04.at.
* tests/listed04.at: New file.
* tests/testsuite.at: Include it.
2010-11-22 17:59:21 -08:00
Paul Eggert
27225be1a3 scripts: fix option parsing
Problem reported by Dennis Wydra in
<http://lists.gnu.org/archive/html/bug-tar/2010-11/msg00082.html>.
* scripts/backup.in: Accept "-l LEVEL".  Be more systematic about
backslashes inside ``; it shouldn't matter for modern shells but
it might matter for older ones.
* scripts/restore.in: Likewise.
* scripts/backup.in: Adjust implementation of -t/--time to match
the new implementation of -l/--level.
2010-11-22 15:18:41 -08:00
Sergey Poznyakoff
73d0d1a0f8 Issue a warning if the archive being compared contais transformed file names.
* src/common.h (transform_program_p): New proto.
* src/transform.c (transform_program_p): New function.
* src/compare.c (verify_volume): Warn if the archive contains
transformed file names.
2010-11-15 11:22:27 +02:00
Sergey Poznyakoff
ff2bc5c0a1 Minor change.
* doc/tar.texi: Reword the description of decompress-program.
2010-11-15 11:21:45 +02:00
Paul Eggert
24214ca5d5 tar: fix --verify option, which broke in 1.24
* NEWS: Document this.
* src/compare.c (verify_volume): Decode the header before invoking
diff_archive, as diff_archive no longer does this as of the
2010-06-28 commit.  Also, don't try to invoke diff_archive on a
zero block.
* tests/Makefile.am (TESTSUITE_AT): Add verify.at.
* tests/testsuite.at: Include verify.at.
* tests/verify.at: New file.
2010-11-15 00:08:27 -08:00
Paul Eggert
777042e024 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/tar 2010-11-08 11:14:28 -08:00
Jim Meyering
1801399830 tests: avoid spurious failure when VERSION_CONTROL envvar is set
* tests/backup01.at: Unset VERSION_CONTROL.  Otherwise,
when set to e.g., 'always', it would cause this test to fail.
2010-11-08 11:13:39 -08:00
Sergey Poznyakoff
ecd700fbfb Version 1.25
* configure.ac: Version 1.25
* NEWS: Describe the changes.
2010-11-07 16:04:48 +02:00
Sergey Poznyakoff
f1fed3996a Run alternative decompression programs if the principal one is not available.
Some compression programs are able to handle various compression formats
(e.g. `gzip' can decompress files created by `compress', `xz' is able
to handle lzma, etc.)  Tar tries to use such programs for decompression
if the principal decompressor cannot be started.

* src/buffer.c (compress_type): Swap ct_none and ct_tar.
(archive_compression_type): New static variable.
(zip_magic): Remove program and option fields.
(zip_program): New structure and static.
(compress_program): Remove macro.
(find_zip_program): New static function.
(first_decompress_program,next_decompress_program): New functions.
(open_compressed_archive): Set archive_compression_type instead of
use_compress_program_option.
* src/common.h (first_decompress_program)
(next_decompress_program): New functions.
(WARN_DECOMPRESS_PROGRAM): New flag.
(WARN_VERBOSE_WARNINGS): Include WARN_DECOMPRESS_PROGRAM.
* src/warning.c (warning_args): Add "decompress-program".
(warning_types): Add WARN_DECOMPRESS_PROGRAM.
* src/system.c (run_decompress_program): New function.
(sys_child_open_for_uncompress): Use run_decompress_program
instead of calling execlp directly.
2010-11-05 10:09:51 +02:00
Paul Eggert
b32edff5aa tests: fix some issues with signals, timestamps, "test" typo
* tests/extrac17.at: Add --warning=no-timestamp, to avoid
bogus warning due to NFS clock skew.
* tests/remfiles01.at: Discard diagnostics that some shells
generate about broken pipes.
* tests/sigpipe.at: Likewise.
* tests/remfiles01.at: Fix typo: "test $EC" was written where
"test $EC -ne 0" was intended.
2010-11-02 01:05:16 -07:00
Sergey Poznyakoff
3913675640 Fix extraction of device nodes.
* src/extract.c (extract_node): Do not mask out node type.
The bug was introduced in commit ea964cce.
2010-11-01 15:05:25 +02:00
Paul Eggert
b8feb2b142 tar: don't cross struct member boundaries with OLDGNU_MAGIC
* src/create.c (write_gnu_long_link, start_header): Access
header->buffer + offsetof (struct posix_header, magic), instead of
header->header.magic, when reading or writing the OLDGNU_MAGIC
pattern.  The code violates the C standard without this change,
and GCC warns about this if fortify checking is enabled.  It's not
a bug on traditional (i.e., non-debugging) platforms, but it does
violate the C standard so it should be fixed.  Problem originally
reported by John Emil Karlson in
<http://lists.gnu.org/archive/html/bug-tar/2010-04/msg00023.html>.
* src/list.c (decode_header): Likewise.
2010-10-27 22:31:16 -07:00
Paul Eggert
3fe59ed5ef tests: port to sh variants that squirrel away file descriptors
OpenBSD /bin/sh, and some other sh variants, squirrel away file
descriptors before closing them.  For example, for "cat 3<&-" they
first dup file descriptor 3 to a fd that is 10 or greater, then
close 3 (because if "cat" had been a builtin command like ":" then
they would have wanted to avoid the fork and restore the fd after
":" finished); and they treat ordinary (forking) commands the same
as builtin commands.  This approach fails after "ulimit -n 10".
Work around this deficiency by closing the file descriptors before
invoking ulimit.  Problem reported by Christian Weisgerber in
<http://lists.gnu.org/archive/html/bug-tar/2010-10/msg00041.html>;
solution suggested by Jilles Tjoelker in
<http://article.gmane.org/gmane.comp.shells.dash/415>.

* tests/extrac11.at (scarce file descriptors): Close file
descriptors before invoking ulimit -n.
2010-10-27 20:25:56 -07:00
Sergey Poznyakoff
5af29cb944 Transform file names when updating and appendig to archives.
This complements 28e91b48.

* src/common.h (transform_stat_info): New prototype.
* src/list.c (transform_stat_info): Remove static qualifier.
* src/update.c (update_archive): Call transform_stat_info.
* tests/Makefile.am (TESTSUITE_AT): Add append03.at
* tests/testsuite.at: Include append03.at
2010-10-27 14:07:46 +03:00
Paul Eggert
7dd57ebdfa tests: port to Solaris diff
* tests/extrac13.at: Don't assume that "diff -c" outputs nothing
when there are no differences.  This is not true on Solaris,
where it outputs "No differences encounted".
2010-10-26 18:13:03 -07:00
Paul Eggert
e23d123b93 tar: fix -x --overwrite bug (no --dereference, ! O_NOFOLLOW)
This bug was discovered on Solaris 8.  On older hosts lacking
O_NOFOLLOW, tar -x --overwrite (without --dereference) follows
symbolic links, causing the "extract over symlinks" test to fail.

* src/extract.c (open_output_file): If O_NOFOLLOW is needed but
does not work, check for a symlink separately.
2010-10-26 17:58:53 -07:00
Paul Eggert
6398c7a79c tar: don't use "((" in shell scripts
* tests/extrac11.at: Replace "((" with "( (" in shell scripts, as
"((" is not portable to the Korn shell, and POSIX 1003.1-2008 says
that "((" is not portable.
2010-10-26 15:04:56 -07:00
Sergey Poznyakoff
28e91b48f6 Make sure name matching occurs before name transformation.
The commit 9c194c99 altered that order.

* src/list.c (transform_stat_info): New function.  Split off from
decode_header.
(read_and): Call transform_stat_info right before do_something,
and after deciding if we should proceed with this member name,
so that name matching occurs before name transformation.

* tests/extrac17.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add extrac17.at
* tests/testsuite.at: Include extrac17.at.
2010-10-26 22:29:02 +03:00
Paul Eggert
3c0bedd494 tar: don't assume stdin is open when testing fd limits
* tests/extrac11.at: Redirect stdin from /dev/null, in case
the parent 'make' is running with stdin closed.
2010-10-26 11:33:38 -07:00
Sergey Poznyakoff
c520964e84 Further fixes in bootstrap.
* bootstrap: Restore the default for gnulib_path
(symlink_to_dir): Re-apply 67cad07.
2010-10-26 16:48:40 +03:00
Paul Eggert
acb77ac5bd tar: fix bug with -C and extracting directories
Problem reported by Denis Excoffier in
<http://lists.gnu.org/archive/html/bug-tar/2010-10/msg00034.html>.

* src/extract.c (extract_dir): Use mkdirat, not mkdir.
* tests/extrac16.at: New file, to test for this bug.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.

This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist.  Run make ChangeLog if you wish to create it earlier.
2010-10-25 20:21:06 -07:00
275 changed files with 15794 additions and 3526 deletions

6
.gitignore vendored
View File

@@ -23,9 +23,13 @@ config.h.in
config.log
config.status
configure
gnu
gnu/*.h
gnu/*/
gnu/.gitignore
gnu/charset.alias
gnulib
libtool
m4
paxutils
rmt
stamp-h1

View File

@@ -2,25 +2,22 @@ Currently there is just one ChangeLog file for tar, but
there used to be separate ChangeLog files for each subdirectory.
This file records what used to be in those separate files.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
Free Software Foundation, Inc.
Copyright 1989-1997, 2013 Free Software Foundation, Inc.
This file is part of GNU Tar.
This file is part of GNU tar.
GNU Tar is free software; you can redistribute it and/or modify
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 2, or (at your option)
any later version.
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Tar is distributed in the hope that it will be useful,
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; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
along with this program. If not, see <http://www.gnu.org/licenses/>.
----- ChangeLog -----

View File

@@ -1,3 +1,24 @@
Currently the ChangeLog is generated automatically from the Git
revision history, but from 1997 to 2009 the ChangeLog file was
maintained by hand, under CVS. This file records the older log.
Copyright 1997-2001, 2003-2009, 2013 Free Software Foundation, Inc.
This file is part of GNU tar.
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
2009-03-05 Sergey Poznyakoff <gray@gnu.org.ua>
* src/incremen.c: --no-recursive works with --incremental.
@@ -1007,7 +1028,7 @@
this has undefined behavior. Likewise for assigning arbitrary
uintmax_t values to other types.
(read_negative_num, read_unsigned_num, read_timespec):
New functions, to check input values a bit more carefuly.
New functions, to check input values a bit more carefully.
(read_num): Use read_unsigned_num. New arg MAX_VAL;
all callers changed.
(read_incr_db_2): Use these new functions.
@@ -1187,7 +1208,7 @@
* src/delete.c: Remove second argument from calls to name_scan
* src/update.c: Likewise
* src/incremen.c (procdir): Use is_individual_file to check for
files explicitely specified in the command line. Fixes bug
files explicitly specified in the command line. Fixes bug
reported by Dat Head on 19 Jun 2006 (descending into mountpoints
with --one-file-system in use)
* src/misc.c (maybe_backup_file): Second argument is bool
@@ -1246,7 +1267,7 @@
* src/delete.c (records_skipped): Remove static qualifier, the
variable is used by print_total_stats in buffer.c
* src/extract.c (check_time): Use volume_start_time when checking
for timestamp plausability.
for timestamp plausibility.
* src/tar.c: (options, parse_opt): Allow for optional argument to
the --totals option, which specifies a signal upon delivery of which
the statistics must be output.
@@ -1304,7 +1325,7 @@
* src/transform.c (set_transform_expr,_transform_name_to_obstack):
Implement NUMBER flag.
(add_char_segment): Fix length assignement
(add_char_segment): Fix length assignment
* doc/tar.texi: Update
@@ -1361,7 +1382,7 @@
* doc/tar.texi: Update
* configure.ac (AM_INIT_AUTOMAKE): Use tar-ustar option. Raise
version requirement to 1.9
* src/common.h (struct name): Refactured
* src/common.h (struct name): Refactored
(warn_regex_usage): New variable.
(dump_file): First argument is const char*.
(name_init,name_add): Removed
@@ -1736,13 +1757,13 @@
* src/common.h (struct name): New member `explicit'. Remove unused
member `isdir'.
* src/incremen.c (procdir): If name_scan() returns something,
check if it was explicitely given in the command line
check if it was explicitly given in the command line
* src/names.c (addname,add_hierarchy_to_namelist): Initialize
explicit member appropriately.
* src/incremen.c (procdir): If --one-file-system is given and a
directory is found to be on another device, *and* this directory
is explicitely given in the command line, then do not omit it.
is explicitly given in the command line, then do not omit it.
2005-12-11 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -1777,7 +1798,7 @@
(mode_to_chars, off_to_chars, size_to_chars, time_to_chars)
(uid_to_chars, uintmax_to_chars): Return bool
(to_chars): Return bool
(start_header): Check return values of convertion routines. Fail
(start_header): Check return values of conversion routines. Fail
if unable to store data in the header.
2005-12-07 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -2077,13 +2098,13 @@
archives.
* src/incremen.c (dumpdir_size, get_gnu_dumpdir): New functions.
(purge_directory): Use stat_info.dumpdir instead of getting its
value explicitely.
value explicitly.
* src/list.c (list_archive): Handle incremental backups in pax
format.
(decode_header): Initialize stat_info.dumpdir
* src/sparse.c (sparse_diff_file): Bugfix: set seekable.
(pax_dump_header): Store sparse map in GNU.sparse.map. If this
variable has been explicitely deleted, use GNU.sparse.offset/
variable has been explicitly deleted, use GNU.sparse.offset/
GNU.sparse.numbytes variables.
* src/tar.c (decode_options): Incremental options are allowed with
--format=pax
@@ -2161,7 +2182,7 @@
* bootstrap: Fix quoting in help output.
(update_po): Use backward-compatible wget option --cache instead
of deprecated -C to accomodate for wget 1.10.
of deprecated -C to accommodate for wget 1.10.
Changes proposed by Eric Blake
* THANKS: Add Eric Blake
@@ -2712,7 +2733,7 @@
* src/list.c: Likewise
* tests/multiv03.at: Modified to match the new behavior
* tests/multiv04.at: New file. Test splittind directory members between
* tests/multiv04.at: New file. Test splitting directory members between
the archive volumes.
* tests/Makefile.am: Add multiv04.at
* tests/testsuite.at: Likewise.
@@ -4466,7 +4487,7 @@
* src/create.c: Do not zero-terminate name field if
the name is exactly 100 characters long.
(write_ustar_long_name): Fixed cheking for unsplittable
(write_ustar_long_name): Fixed checking for unsplittable
names.
2003-11-14 Sergey Poznyakoff <gray@Mirddin.farlep.net>
@@ -5163,7 +5184,7 @@
interface.
(child_open_for_compress): Do not increase size to BLOCKSIZE.
(open_archive): Open index file name.
Strip trailing slahes from file names.
Strip trailing slashes from file names.
(flush_write): Set size to 0 if not saving names.
(flush_write, flush_read): Use safer_name_suffix rather than
inline code.
@@ -5996,7 +6017,7 @@
(decode_options): Dates that look like an absolute path name,
or that start with '.', are presumed to be file names whose
dates are taken.
Remove 'I' as an aliase for 'T'.
Remove 'I' as an alias for 'T'.
Update copyright.
* src/extract.c (<time.h>): Do not include; system.h now does this.
@@ -8806,26 +8827,6 @@
See ChangeLog.1 for earlier changes.
-----
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GNU tar.
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; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
Local Variables:
mode: change-log

70
ChangeLog.amend Normal file
View File

@@ -0,0 +1,70 @@
# Fix typos in tar ChangeLog entries generated from git log
f24b30ec8ca1851b7bd14694241de3b38194c99c
s/commit 2bd9c153_\./commit 2bd9c153)./
29a6964af3e1baabe978ce608e0466e1250d08ab
s/ORDER \(none, name, or order\)\./ORDER (none, name, or inode)./
2af87fa2776c8125a587a9b0c2c4fae3bf921ff7
s/contant\./content./
2bd9c15391b0bd6ef0bff76aebf09cfb53003199
s/ocurrence/occurrence/
47da28892e6860a3a6fc06745f640e3bb878c757
s/aruond/around/
f7077dd38b018f19d3a5c7df6accc6b07b8a2356
s/absoulte/absolute/
28b44aaacb45680aa6640e0a6d7ceab04cfdbf11
s/warniing/warning/
47560a0498bde20621ce4e367b1d68bf8cd8f1a3
s/interacton/interaction/
26538c9bfc5fd726d625bef5fa3f08212d50173a
s/consuption/consumption/;
s/misfunctioned/malfunctioned/;
s/misssing/missing/;
696338043e52f440853e1143c52b81b41cd59723
s/suuport/support/
643a8844a578ff146cfe746fe6091d29502b6c40
s/incrfental/incremental/;
s/afterwards/afterward/;
03858cf583ce299b836d8a848967ce290a6bf303
s/Peformance/Performance/
fa307a665545753b6729191fd2559ce872fa470a
s/filags/flags/
73d0d1a0f883be5f67534362c99382f1eae8d178
s/contais/contains/
5af29cb944c84e2d539ce9df527d63c29f6012b9
s/appendig/appending/
7dd57ebdfa9ac0d2af4622449f45b5025f6c184f
s/encounted/encountered/
ecbcb7b6d74c2d69386c8d7e435486a4690c9993
s/inadvertantly/inadvertently/
4dfcd6c054a5e9e1a371c822a3be90564dd9b690
s/succesfully/successfully/

View File

@@ -1,22 +1,22 @@
# Main Makefile for GNU tar.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007,
# 2009 Free Software Foundation, Inc.
# Copyright 1994-1997, 1999-2001, 2003, 2007, 2009, 2013-2014 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 file is part of GNU tar.
## 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.
# 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 of the License, or
# (at your option) any later version.
## 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.
# 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 this program. If not, see <http://www.gnu.org/licenses/>.
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = ChangeLog.1 Make.rules
@@ -36,3 +36,4 @@ include Make.rules
gen_start_date = 2009-03-06
prev_change_log = ChangeLog.CVS
changelog_dir = .
changelog_amend_file=ChangeLog.amend

372
NEWS
View File

@@ -1,12 +1,227 @@
GNU tar NEWS - User visible changes. 2010-10-24
GNU tar NEWS - User visible changes. 2014-07-27
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.28, 2014-07-28
* New checkpoint action: totals
The --checkpoint-action=totals option instructs tar to output the
total number of bytes transferred at each checkpoint.
* Extended checkpoint format specification.
New conversion specifiers are implemented. Some of them take
optional arguments, supplied in curly braces between the percent
sign and the specifier letter.
%d - Number of seconds since tar started.
%{r,w,d}T - I/O totals; optional arguments supply prefixes
to be used before number of bytes read, written and
deleted, correspondingly.
%{FMT}t - Current local time using FMT as strftime(3) format.
If {FMT} is omitted, use %c.
%{N}* - Pad output with spaces to the Nth column, or to the
current screen width, if {N} is not given.
%c - A shortcut for "%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r"
* New option --one-top-level
The option --one-top-level tells tar to extract all files into a
subdirectory named by the base name of the archive (minus standard
compression suffixes recognizable by --auto-compress). When used with
an argument, as in --one-top-level=DIR, the files are extracted into the
supplied DIRectory. This ensures that no archive members are
extracted outside of the specified directory, even if the archive is
crafted so as to put them elsewhere.
* New option --sort
The --sort=ORDER option instructs tar to sort directory entries
according to ORDER. It takes effect when creating archives.
Available ORDERs are: none (the default), name and inode. The
latter may be absent, if the underlying system does not provide
the necessary information.
Using --sort=name ensures the member ordering in the created archive
is uniform and reproducible. Using --sort=inode reduces the number
of disk seeks made when creating the archive and thus can considerably
speed up archivation.
* New exclusion options
--exclude-ignore=FILE Before dumping a directory check if it
contains FILE, and if so read exclude
patterns for this directory from FILE.
--exclude-ignore-recursive=FILE
Same as above, but the exclusion patterns
read from FILE remain in effect for any
subdirectory, recursively.
--exclude-vcs-ignores Read exclude tags from VCS ignore files,
where such files exist. Supported VCS's
are: CVS, Git, Bazaar, Mercurial.
* Tar refuses to read input from and write output to a tty device.
* Manpages
This release includes official tar(1) and rmt(8) manpages.
Distribution maintainers are kindly asked to use these instead of the
home-made pages they have been providing so far.
version 1.27.1 - Sergey Poznyakoff, 2013-11-17
* Bug fixes
* Fix unquoting of file names obtained via the -T option.
* Fix GNU long link header timestamp (backward compatibility).
* Fix extracting sparse members from star archives.
version 1.27 - Sergey Poznyakoff, 2013-10-05
* Bug fixes
** Sparse files with large data
When creating a PAX-format archive, tar no longer arbitrarily restricts
the size of the representation of a sparse file to be less than 8 GiB.
* Quoting
In the default C locale, diagnostics and output of 'tar' have been
adjusted to quote 'like this' (with apostrophes) instead of `like this'
(with an accent grave character and an apostrophe). This tracks
recent changes to the GNU coding standards.
* --owner and --group names and numbers
The --owner and --group options now accept operands of the form
NAME:NUM, so that you can specify both symbolic name and numeric ID
for owner and group. In these options, NAME no longer needs to be
present in the current host's user and group databases.
* The --keep-old-files and --skip-old-files options.
This release restores the traditional functionality of the
--keep-old-files. This option causes tar to avoid replacing
existing files while extracting and to treat such files as errors.
Tar will emit a prominent error message upon encountering such files
and will exit with code 2 when finished extracting the archive.
A new option --skip-old-files is introduced, which acts exactly as
--keep-old-files, except that it does not treat existing files as
errors. Instead it just silently skips them. An additional level of
verbosity can be obtained by using the option --warning=existing-file
together with this option.
* Support for POSIX ACLs, extended attributes and SELinux context.
Starting with this version tar is able to store, extract and list
extended file attributes, POSIX.1e ACLs and SELinux context. This is
controlled by the command line options --xattrs, --acls and --selinux,
correspondingly. Each of these options has a `--no-' counterpart
(e.g. --no-xattrs), which disables the corresponding feature.
Additionally, the options --xattrs-include and --xattrs-exclude allow
you to selectively control for which files to store (or extract) the
extended attributes.
* Passing command line arguments to external commands.
Any option taking a command name as its argument now accepts a full
command line as well. Thus, it is now possible to pass additional
arguments to invoked programs. The affected options are:
--checkpoint-action=exec
-I, --use-compress-program
-F, --info-script
--to-command
Furthermore, if any additional information is supplied to such a
command via environment variables, these variables can now be used in
the command line itself. Care should be taken to escape them, to
prevent from being expanded too early, for example:
tar -x -f a.tar --info-script='changevol $TAR_ARCHIVE $TAR_VOLUME'
* New configure option --enable-gcc-warnings, intended for debugging.
* New warning control option --warning=[no-]record-size
On extraction, this option controls whether to display actual record
size, if it differs from the default.
* New command line option --keep-directory-symlink
By default, if trying to extract a directory from the archive,
tar discovers that the corresponding file name already exists and is a
symbolic link, it first unlinks the entry, and then extracts the directory.
This option disables this behavior and instructs tar to follow
symlinks to directories when extracting from the archive.
It is mainly intended to provide compatibility with the Slackware
installation scripts.
version 1.26 - Sergey Poznyakoff, 2011-03-12
* Bugfixes
** Fix the --verify option, which broke in version 1.24.
** Fix storing long sparse file names in PAX archives.
** Fix correctness of --atime-preserve=replace
tar --atime-preserve=replace no longer tries to restore atime of
zero-sized files.
** Work around POSIX incompatibilities on FreeBSD, NetBSD and Tru64
** Fix bug with --one-file-system --listed-incremental
When invoked with these two options, tar 1.25 would add only the
top-level directory to the archive, but not its contents.
version 1.25 - Sergey Poznyakoff, 2010-11-07
* Fix extraction of empty directories with the -C option in effect.
* Fix extraction of device nodes.
* Make sure name matching occurs before eventual name transformation.
Tar 1.24 changed the ordering of name matching and name transformation
so that the former saw already transformed file names. This made it
impossible to match file names in certain cases. It is fixed now.
* Fix the behavior of tar -x --overwrite on hosts lacking O_NOFOLLOW.
* Improve the testsuite.
* Alternative decompression programs.
If extraction from a compressed archive fails because the corresponding
compression program is not installed and the following two conditions
are met, tar retries extraction using an alternative decompressor:
1. Another compression program supported by tar is able to handle this
compression format.
2. The compression program was not explicitly requested in the command
line by the use of such options as -z, -j, etc.
For example, if 'compress' is not available, tar will try 'gzip'.
version 1.24 - Sergey Poznyakoff, 2010-10-24
* The --full-time option.
New command line option `--full-time' instructs tar to output file
New command line option '--full-time' instructs tar to output file
time stamps to the full resolution.
* Bugfixes.
@@ -59,15 +274,15 @@ invoked as in the example below:
** --remove-files
`Tar --remove-files' failed to remove a directory which contained
'tar --remove-files' failed to remove a directory which contained
symlinks to another files within that directory.
** --test-label behavior
In case of a mismatch, `tar --test-label LABEL' exits with code 1,
In case of a mismatch, 'tar --test-label LABEL' exits with code 1,
not 2 as it did in previous versions.
The `--verbose' option used with `--test-label' provides additional
The '--verbose' option used with '--test-label' provides additional
diagnostics.
Several volume labels may be specified in a command line, e.g.:
@@ -79,7 +294,7 @@ matches the actual volume label.
** --label used with --update
The `--label' option can be used with `--update' to prevent accidental
The '--label' option can be used with '--update' to prevent accidental
update of an archive:
tar -rf archive --label 'My volume' .
@@ -107,28 +322,28 @@ to regular files and pipes).
When a read-only operation (e.g. --list or --extract) is requested
on a regular file, tar attemtps to speed up accesses by using lseek.
* New command line option `--warning'
* New command line option '--warning'
The `--warning' command line option allows to suppress or enable
particular warning messages during `tar' run. It takes a single
argument (a `keyword'), identifying the class of warning messages
to affect. If the argument is prefixed with `no-', such warning
The '--warning' command line option allows to suppress or enable
particular warning messages during 'tar' run. It takes a single
argument (a 'keyword'), identifying the class of warning messages
to affect. If the argument is prefixed with 'no-', such warning
messages are suppressed. For example,
tar --warning=no-alone-zero-block -x -f archive
suppresses the output of `A lone zero block' diagnostics, which is
normally issued if `archive' ends with a single block of zeros.
suppresses the output of "A lone zero block" diagnostics, which is
normally issued if 'archive' ends with a single block of zeros.
See Tar Manual, section 3.9 "Controlling Warning Messages", for a
detailed discussion.
* New command line option `--level'
* New command line option '--level'
The `--level=N' option sets the incremental dump level N. It
The '--level=N' option sets the incremental dump level N. It
is valid when used in conjunction with the -c and --listed-incremental
options. So far the only meaningful value for N is 0. The
`--level=0' option forces creating the level 0 dump, by truncating
'--level=0' option forces creating the level 0 dump, by truncating
the snapshot file if it exists.
* Files removed during incremental dumps
@@ -157,7 +372,7 @@ can be overridden by the
--pax-opion='exthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a `Time reference' (see below).
the Epoch or a "Time reference" (see below).
Modification times in ustar header blocks of global extended
headers are set to the time when tar was invoked.
@@ -167,7 +382,7 @@ This can be overridden by the
--pax-opion='globexthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a `Time reference' (see below).
the Epoch or a "Time reference" (see below).
* Time references in --pax-option argument.
@@ -175,7 +390,7 @@ Any value from the --pax-option argument that is enclosed in a pair
of curly braces represents a time reference. The string between the
braces is understood either as a textual time representation, as described in
chapter 7, "Date input formats", of the Tar manual, or as a name of
an existing file, starting with `/' or `.'. In the latter
an existing file, starting with '/' or '.'. In the latter
case, it is replaced with the modification time of that file.
* Environment of --to-command script.
@@ -210,7 +425,7 @@ Tar uses xz for compression if one of the following conditions is met:
1. The option --xz or -J (see below) is used.
2. The xz binary is set as compressor using --use-compress-program option.
3. The file name of the archive being created ends in `.xz' and
3. The file name of the archive being created ends in '.xz' and
auto-compress option (-a) is used.
Xz is used for decompression if one of the following conditions is met:
@@ -270,17 +485,17 @@ control type of archive members affected by them. The flags are:
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.''
'H' means "do not apply transformation to hard link targets".
The scope flags are listed in the third part of an `s' expression,
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
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.:
can be changed using 'flags=' statement before the expressions, e.g.:
tar --transform 'flags=S;s|^|/usr/local/|S'
@@ -316,29 +531,29 @@ they refer to, instead of creating usual hard link members (type '1').
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
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
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 '--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
'--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.
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').
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
@@ -424,7 +639,7 @@ option affects hard and soft link targets and the --strip-components
option affects hard link targets as well.
* End-of-volume script can send the new volume name to tar by writing
it to the file descriptor stored in the environment variable `TAR_FD'.
it to the file descriptor stored in the environment variable TAR_FD.
version 1.16.1 - Sergey Poznyakoff, 2006-12-09
@@ -494,7 +709,7 @@ following command line options:
--wildcards use wildcards
--anchored patterns match file name start
--ignore-case ignore case
--wildcards-match-slash wildcards match `/'
--wildcards-match-slash wildcards match '/'
Each of these options has a '--no-' counterpart that disables its
effect (e.g. --no-wildcards).
@@ -534,7 +749,7 @@ or archive. It generalizes --show-stored-names option, introduced in
1.15.90. In particular, when creating an archive in verbose mode, it lists
member names as stored in the archive, i.e., with any eventual prefixes
removed and file name transformations applied. The option is useful,
for example, while comparing `tar cv' and `tar tv' outputs.
for example, while comparing 'tar cv' and 'tar tv' outputs.
** New incremental snapshot file format keeps information about file names
as well as that about directories.
@@ -559,7 +774,7 @@ version 1.15.90 - Sergey Poznyakoff, 2006-02-19
* New features
** Any number of -T (--files-from) options may be used in the command line.
The file specified with -T may include any valid `tar' options,
The file specified with -T may include any valid 'tar' options,
including another -T option.
Compatibility note: older versions of tar would only recognize -C
as an option name within the file list file. Now any file whose name
@@ -570,7 +785,7 @@ dash, use the --add-file option.
automatically. It is no longer necessary to give the --null option.
** New option --no-unquote disables the unquoting of input file names.
This is useful for processing output from `find dir -print0'.
This is useful for processing output from 'find dir -print0'.
An orthogonal option --unquote is provided as well.
** New option --test-label tests the archive volume label.
@@ -584,7 +799,7 @@ tar prints the label name if present and exits with code 0.
** New option --show-stored-names. When creating an archive in verbose mode,
it lists member names as stored in the archive, i.e., with any eventual
prefixes removed. The option is useful, for example, while comparing
`tar cv' and `tar tv' outputs.
'tar cv' and 'tar tv' outputs.
** New option --to-command pipes the contents of archive members to the
specified command.
@@ -657,7 +872,7 @@ version 1.15 - Sergey Poznyakoff, 2004-12-20
* Compressed archives are recognised automatically, it is no longer
necessary to specify -Z, -z, or -j options to read them. Thus, you can
now run `tar tf archive.tar.gz'.
now run 'tar tf archive.tar.gz'.
* When restoring incremental dumps, --one-file-system option
prevents directory hierarchies residing on different devices
@@ -677,7 +892,7 @@ seeks.
* Restore script starts restoring only if it is given --all (-a) option,
or some patterns. This is to prevent accidental restores.
* `tar --verify' prints a warning if during archive creation some of
* 'tar --verify' prints a warning if during archive creation some of
the file names had their prefixes stripped off.
* New option --exclude-caches instructs tar to exclude cache directories
@@ -687,11 +902,11 @@ containing a standardized tag file, as specified at:
http://www.brynosaurus.com/cachedir/spec.html
* New configure option --with-rmt allows to specify full path name to
the `rmt' utility. This supersedes DEFAULT_RMT_COMMAND variable
the 'rmt' utility. This supersedes DEFAULT_RMT_COMMAND variable
introduced in version 1.14
* New configure variable DEFAULT_RMT_DIR allows to specify the directory
where to install `rmt' utility. This is necessary since modifying
where to install 'rmt' utility. This is necessary since modifying
--libexecdir as was suggested for version 1.14 produced a side effect: it
also modified installation prefix for backup scripts (if
--enable-backup-scripts was given).
@@ -745,12 +960,12 @@ version 1.14 - Sergey Poznyakoff, 2004-05-11
the subcommands --delete, --diff, --extract or --list when a list of
files is given either on the command line or via -T option. This
option instructs tar to process only the Nth occurrence of each named
file. N defaults to 1, so `tar -x -f archive --occurrence filename'
extracts the first occurrence of `filename' from `archive'
file. N defaults to 1, so 'tar -x -f archive --occurrence filename'
extracts the first occurrence of 'filename' from 'archive'
and terminates without scanning to the end of the archive.
* New option --pax-option allows to control the handling of POSIX
keywords in `pax' extended headers. It is equivalent to `pax'
keywords in 'pax' extended headers. It is equivalent to 'pax'
-o option.
* --incremental and --listed-incremental options work correctly on
@@ -856,7 +1071,7 @@ version 1.13.19 - Paul Eggert, 2001-01-13
version 1.13.18 - Paul Eggert, 2000-10-29
* Some security problems have been fixed. `tar -x' now modifies only
* Some security problems have been fixed. 'tar -x' now modifies only
files under the working directory, unless you also specify an unsafe
option like --absolute-names or --overwrite.
@@ -882,12 +1097,12 @@ version 1.13.18 - Paul Eggert, 2000-10-29
* This version of tar works best with GNU gzip test version 1.3 or later.
Please see <ftp://alpha.gnu.org/gnu/gzip/>.
* `tar --delete -f -' now works again.
* 'tar --delete -f -' now works again.
version 1.13.17 - Paul Eggert, 2000-01-07.
* `tar --delete -f -' is no longer allowed; it was too buggy.
* 'tar --delete -f -' is no longer allowed; it was too buggy.
* Diagnostic messages have been made more regular and consistent.
@@ -904,12 +1119,12 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
The new --overwrite option enables the old default behavior.
For regular files, tar implements this change by using the O_EXCL
option of `open' to ensure that it creates the file; if this fails, it
option of 'open' to ensure that it creates the file; if this fails, it
removes the file and tries again. This is similar to the behavior of
the --unlink-first option, but it is faster in the common case of
extracting a new directory.
* By default, tar now ignores file names containing a component of `..'
* By default, tar now ignores file names containing a component of '..'
when extracting, and warns about such file names when creating an archive.
To enable the old behavior, use the -P or --absolute-names option.
@@ -951,20 +1166,20 @@ version 1.13.14 - Paul Eggert, 1999-11-07.
version 1.13.13 - Paul Eggert, 1999-10-11.
* Invalid headers in tar files now elicit errors, not just warnings.
* `tar --version' output conforms to the latest GNU coding standards.
* If you specify an invalid date, `tar' now substitutes (time_t) -1.
* `configure --with-dmalloc' is no longer available.
* 'tar --version' output conforms to the latest GNU coding standards.
* If you specify an invalid date, 'tar' now substitutes (time_t) -1.
* 'configure --with-dmalloc' is no longer available.
version 1.13.12 - Paul Eggert, 1999-09-24.
* `tar' now supports hard links to symbolic links.
* 'tar' now supports hard links to symbolic links.
* New options --no-same-owner, --no-same-permissions.
* --total now also outputs a human-readable size, and a throughput value.
* `tar' now uses two's-complement base-256 when outputting header
* 'tar' now uses two's-complement base-256 when outputting header
values that are out of the range of the standard unsigned base-8
format. This affects archive members with negative or huge time
stamps or uids, and archive members 8 GB or larger. The new tar
@@ -973,12 +1188,12 @@ version 1.13.12 - Paul Eggert, 1999-09-24.
behavior, which uses unportable representations for negative values,
and which rejects large files.
* On 32-bit hosts, `tar' now assumes that an incoming time stamp T in
* On 32-bit hosts, 'tar' now assumes that an incoming time stamp T in
the range 2**31 <= T < 2**32 represents the negative time (T -
2**32). This behavior is nonstandard and is not portable to 64-bit
time_t hosts, so `tar' issues a warning.
time_t hosts, so 'tar' issues a warning.
* `tar' no longer gives up extracting immediately upon discovering
* 'tar' no longer gives up extracting immediately upon discovering
that an archive contains garbage at the end. It attempts to extract
as many files as possible from the good data before the garbage.
@@ -995,40 +1210,40 @@ version 1.13.11 - Paul Eggert, 1999-08-23.
* -T /dev/null now matches nothing; previously, it matched anything
if no explicit operands were given.
* The `--' option now works the same as with other GNU utilities;
* The '--' option now works the same as with other GNU utilities;
it causes later operands to be interpreted as file names, not options,
even if they begin with `-'.
even if they begin with '-'.
* For the --newer and --after-date options, the table of time zone
abbreviations like `EST' has been updated to match current practice.
abbreviations like 'EST' has been updated to match current practice.
Also, local time abbreviations are now recognized, even if they are
not in tar's hardwired table. Remember, though, that you should use
numeric UTC offsets like `-0500' instead of abbreviations like
`EST', as abbreviations are not standardized and are ambiguous.
numeric UTC offsets like '-0500' instead of abbreviations like
'EST', as abbreviations are not standardized and are ambiguous.
version 1.13.10 - Paul Eggert, 1999-08-20.
* `tar' now uses signed base-64 when outputting header values that are
* 'tar' now uses signed base-64 when outputting header values that are
out of the range of the standard unsigned base-8 format. [This
change was superseded in 1.13.12, described above.]
version 1.13.9 - Paul Eggert, 1999-08-18.
* `tar' now writes two zero blocks at end-of-archive instead of just one.
POSIX.1 requires this, and some other `tar' implementations check for it.
* 'tar' now writes two zero blocks at end-of-archive instead of just one.
POSIX.1 requires this, and some other 'tar' implementations check for it.
* `tar' no longer silently accepts a block containing nonzero checksum bytes
* 'tar' no longer silently accepts a block containing nonzero checksum bytes
as a zero block.
* `tar' now reads buggy tar files that have a null byte at the start of a
* 'tar' now reads buggy tar files that have a null byte at the start of a
numeric header field.
version 1.13.8 - Paul Eggert, 1999-08-16.
* For compatibility with traditional `tar', intermediate directories
* For compatibility with traditional 'tar', intermediate directories
created automatically by root are no longer given the uid and gid of
the original file or directory.
@@ -1037,7 +1252,7 @@ version 1.13.7 - Paul Eggert, 1999-08-14.
* --listed-incremental and --newer are now incompatible options.
* When creating an archive, leading `./' is no longer stripped,
* When creating an archive, leading './' is no longer stripped,
to match traditional tar's behavior (and simplify the documentation).
* --diff without --absolute-names no longer falls back on absolute names.
@@ -1128,7 +1343,7 @@ Creation
* Implement --numeric-owner for ignoring symbolic names at create time.
* New --owner, --group --mode options, still preliminary.
* Recognize creating an archive on /dev/null, so Amanda works faster.
* Object to the creation of an empty archive (like in `tar cf FILE').
* Object to the creation of an empty archive (like in 'tar cf FILE').
* Barely start implementing --posix and POSIXLY_CORRECT.
Extraction
@@ -1207,7 +1422,7 @@ Version 1.10.13 - 1992-01.
* Now uses GNU standard configure, generated by Autoconf.
* Long options now use `--'; use of `+' is deprecated and support
* Long options now use '--'; use of '+' is deprecated and support
for it will eventually be removed.
* New option --null causes filenames read by -T to be
@@ -1236,8 +1451,8 @@ the various tape drives will get used in sequence and then wrap
around to the beginning.
* Remote archive names no longer have to be in /dev: any file with a
`:' is interpreted as remote. If new option --force-local is given,
then even archive files with a `:' are considered local.
':' is interpreted as remote. If new option --force-local is given,
then even archive files with a ':' are considered local.
* New option --atime-preserve restores (if possible) atimes to
their original values after dumping the file.
@@ -1290,15 +1505,14 @@ 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, 2008, 2009, 2010 Free Software Foundation, Inc.
Copyright 1994-2001, 2003-2010, 2013-2014 Free Software Foundation, Inc.
This file is part of GNU tar.
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.
the Free Software Foundation; either version 3 of the License, 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
@@ -1306,9 +1520,7 @@ 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 tar; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
along with this program. If not, see <http://www.gnu.org/licenses/>.
Local variables:
mode: outline

130
README
View File

@@ -4,31 +4,31 @@ See the end of file for copying conditions.
* Introduction
Please glance through *all* sections of this
`README' file before starting configuration. Also make sure you read files
`ABOUT-NLS' and `INSTALL' if you are not familiar with them already.
'README' file before starting configuration. Also make sure you read files
'ABOUT-NLS' and 'INSTALL' if you are not familiar with them already.
If you got the `tar' distribution in `shar' format, time stamps ought to be
properly restored; do not ignore such complaints at `unshar' time.
If you got the 'tar' distribution in 'shar' format, time stamps ought to be
properly restored; do not ignore such complaints at 'unshar' time.
GNU `tar' saves many files together into a single tape or disk
GNU 'tar' saves many files together into a single tape or disk
archive, and can restore individual files from the archive. It includes
multivolume support, the ability to archive sparse files, automatic archive
compression/decompression, remote archives and special features that allow
`tar' to be used for incremental and full backups. This distribution
also includes `rmt', the remote tape server. The `mt' tape drive control
program is in the GNU `cpio' distribution.
'tar' to be used for incremental and full backups. This distribution
also includes 'rmt', the remote tape server. The 'mt' tape drive control
program is in the GNU 'cpio' distribution.
GNU `tar' is derived from John Gilmore's public domain `tar'.
GNU 'tar' is derived from John Gilmore's public domain 'tar'.
See file `ABOUT-NLS' for how to customize this program to your language.
See file `COPYING' for copying conditions.
See file `INSTALL' for compilation and installation instructions.
See file `PORTS' for various ports of GNU tar to non-Unix systems.
See file `NEWS' for a list of major changes in the current release.
See file `THANKS' for a list of contributors.
See file 'ABOUT-NLS' for how to customize this program to your language.
See file 'COPYING' for copying conditions.
See file 'INSTALL' for compilation and installation instructions.
See file 'PORTS' for various ports of GNU tar to non-Unix systems.
See file 'NEWS' for a list of major changes in the current release.
See file 'THANKS' for a list of contributors.
Besides those configure options documented in files `INSTALL' and
`ABOUT-NLS', an extra option may be accepted after `./configure':
Besides those configure options documented in files 'INSTALL' and
'ABOUT-NLS', an extra option may be accepted after './configure':
* Install
@@ -40,11 +40,11 @@ values are GNU, V7, OLDGNU, USTAR and POSIX.
** Selecting the default archive device
The default archive device is now `stdin' on read and `stdout' on write.
The installer can still override this by presetting `DEFAULT_ARCHIVE'
in the environment before configuring (the behavior of `-[0-7]' or
`-[0-7]lmh' options in `tar' are then derived automatically). Similarly,
`DEFAULT_BLOCKING' can be preset to something else than 20.
The default archive device is now 'stdin' on read and 'stdout' on write.
The installer can still override this by presetting 'DEFAULT_ARCHIVE'
in the environment before configuring (the behavior of '-[0-7]' or
'-[0-7]lmh' options in 'tar' are then derived automatically). Similarly,
'DEFAULT_BLOCKING' can be preset to something else than 20.
** Selecting full pathname of the "rmt" binary.
@@ -76,13 +76,13 @@ directory.
Use option --enable-backup-scripts to compile and install these
scripts.
** `--disable-largefile' omits support for large files, even if the
** '--disable-largefile' omits support for large files, even if the
operating system supports large files. Typically, large files are
those larger than 2 GB on a 32-bit host.
* Installation hints
Here are a few hints which might help installing `tar' on some systems.
Here are a few hints which might help installing 'tar' on some systems.
** gzip and bzip2.
@@ -103,7 +103,7 @@ then you have encountered a gzip incompatibility that should be fixed
in gzip test version 1.3, which as of this writing is available at
<ftp://alpha.gnu.org/gnu/gzip/>. You can work around the
incompatibility by using a shell command like
`gzip -d <file.tar.gz | tar -xzf -'.
'gzip -d <file.tar.gz | tar -xzf -'.
** Solaris issues.
@@ -118,13 +118,13 @@ understand these headers.
** Static linking.
Some platform will, by default, prepare a smaller `tar' executable
which depends on shared libraries. Since GNU `tar' may be used for
Some platform will, by default, prepare a smaller 'tar' executable
which depends on shared libraries. Since GNU 'tar' may be used for
system-level backups and disaster recovery, installers might prefer to
force static linking, making a bigger `tar' executable maybe, but able to
force static linking, making a bigger 'tar' executable maybe, but able to
work standalone, in situations where shared libraries are not available.
The way to achieve static linking varies between systems. Set LDFLAGS
to a value from the table below, before configuration (see `INSTALL').
to a value from the table below, before configuration (see 'INSTALL').
Platform Compiler LDFLAGS
@@ -137,18 +137,18 @@ to a value from the table below, before configuration (see `INSTALL').
Solaris (vendor) -Bstatic
SunOS (vendor) -Bstatic
** Failed tests `ignfail.sh' or `incremen.sh'.
** Failed tests 'ignfail.sh' or 'incremen.sh'.
In an NFS environment, lack of synchronization between machine clocks
might create difficulties to any tool comparing dates and file time stamps,
like `tar' in incremental dumps. This has been a recurrent problem with
like 'tar' in incremental dumps. This has been a recurrent problem with
GNU Make for the last few years. We would like a general solution.
** BSD compatibility matters.
Set LIBS to `-lbsd' before configuration (see `INSTALL') if the linker
complains about `bsd_ioctl' (Slackware). Also set CPPFLAGS to
`-I/usr/include/bsd' if <sgtty.h> is not found (Slackware).
Set LIBS to '-lbsd' before configuration (see 'INSTALL') if the linker
complains about 'bsd_ioctl' (Slackware). Also set CPPFLAGS to
'-I/usr/include/bsd' if <sgtty.h> is not found (Slackware).
** OPENStep 4.2 swap files
@@ -159,43 +159,43 @@ the simplest workaround is to avoid tarring this file.
* Special topics
Here are a few special matters about GNU `tar', not related to build
Here are a few special matters about GNU 'tar', not related to build
matters. See previous section for such.
** File attributes.
About *security*, it is probable that future releases of `tar' will have
About *security*, it is probable that future releases of 'tar' will have
some behavior changed. There are many pending suggestions to choose from.
Today, extracting an archive not being `root', `tar' will restore suid/sgid
bits on files but owned by the extracting user. `root' automatically gets
a lot of special privileges, `-p' might later become required to get them.
Today, extracting an archive not being 'root', 'tar' will restore suid/sgid
bits on files but owned by the extracting user. 'root' automatically gets
a lot of special privileges, '-p' might later become required to get them.
GNU `tar' does not properly restore symlink attributes. Various systems
GNU 'tar' does not properly restore symlink attributes. Various systems
implement flavors of symbolic links showing different behavior and
properties. We did not successfully sorted all these out yet. Currently,
the `lchown' call will be used if available, but that's all.
the 'lchown' call will be used if available, but that's all.
** POSIX compliance.
GNU `tar' is able to create archive in the following formats:
GNU 'tar' is able to create archive in the following formats:
*** The format of UNIX version 7
*** POSIX.1-1988 format, also known as "ustar format"
*** POSIX.1-2001 format, also known as "pax format"
*** Old GNU format (described below)
In addition to those, GNU `tar' is also able to read archives
produced by `star' archiver.
In addition to those, GNU 'tar' is also able to read archives
produced by 'star' archiver.
A so called `Old GNU' format is based on an early draft of the
POSIX 1003.1 `ustar' standard which is different from the final
A so called 'Old GNU' format is based on an early draft of the
POSIX 1003.1 'ustar' standard which is different from the final
standard. It defines its extensions (such as incremental backups
and handling of the long file names) in a way incompatible with
any existing tar archive format, therefore the use of old GNU
format is strongly discouraged.
Please read the file NEWS for more information about POSIX compliance
and new `tar' features.
and new 'tar' features.
* What's next?
@@ -216,32 +216,36 @@ to the report address; rather take special arrangement with the maintainer.
Your feedback will help us to make a better and more portable package.
Consider documentation errors as bugs, and report them as such. If you
develop anything pertaining to `tar' or have suggestions, let us know
develop anything pertaining to 'tar' or have suggestions, let us know
and share your findings by writing to <bug-tar@gnu.org>.
* Copying
Copyright (C) 1990, 1991, 1992, 1994, 1997, 1998, 1999, 2000,
2001, 2003, 2004, 2007 Free Software Foundation, Inc.
Copyright 1990-1992, 1994, 1997-2001, 2003-2004, 2007, 2012-2014 Free
Software Foundation, Inc.
This file is part of GNU tar.
This file is part of GNU tar.
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 free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
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.
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 tar; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
NOTE ON COPYRIGHT YEARS
In copyright notices where the copyright holder is the Free Software
Foundation, then where a range of years appears, this is an inclusive
range that applies to every year in the range. For example: 2005-2008
represents the years 2005, 2006, 2007, and 2008.
Local Variables:
mode: outline

View File

@@ -62,14 +62,15 @@ some other value.
Copyright (C) 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Copyright 2001, 2003-2005, 2007, 2013-2014 Free Software Foundation,
Inc.
This file is part of GNU tar.
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.
the Free Software Foundation; either version 3 of the License, 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
@@ -77,6 +78,4 @@ 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 tar; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@@ -36,30 +36,35 @@ Normally you will have to run bootstrap only once. However, if you
intend to hack on GNU tar, you might need to run it again later. In
this case, you will probably want to save some time and bandwidth by
avoiding downloading the same files again. If so, create in GNU tar
root directory the file named `.bootstrap' with the following
root directory the file named '.bootstrap' with the following
contents:
--gnulib-srcdir=$HOME/gnulib
Replace `$HOME/gnulib' with the actual directory where the Gnulib
Replace '$HOME/gnulib' with the actual directory where the Gnulib
sources reside.
For more information about `bootstrap', run `bootstrap --help'.
For more information about 'bootstrap', run 'bootstrap --help'.
* Copyright information
Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
Copyright 2007-2009, 2013-2014 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
copyright notice and this permission notice are preserved,
thus giving the recipient permission to redistribute in turn.
This file is part of GNU tar.
Permission is granted to distribute modified versions
of this document, or of portions of it,
under the above conditions, provided also that they
carry prominent notices stating who last changed them.
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
^L
Local Variables:

12
THANKS
View File

@@ -36,6 +36,7 @@ Andrew Torda torda@igc.chem.ethz.ch
Andrey A. Chernov ache@astral.msk.su
Andy Gay andy@rdl.co.uk
Antonio Jose Coutinho ajc@di.uminho.pt
Anthony G. Basile blueness@gentoo.org
Ariel Faigon ariel@engr.sgi.com
Arne Wichmann aw@math.uni-sb.de
Arnold Robbins arnold@gnu.org
@@ -91,6 +92,7 @@ Christian Kirsch ck@held.mind.de
Christian Laubscher christian.laubscher@tiscalinet.ch
Christian T. Dum ctd@mpe-garching.mpg.de
Christian von Roques roques@pond.sub.org
Christian Wetzel wetzel@phoenix-pacs.de
Christoph Litauer litauer@mailhost.uni-koblenz.de
Christophe Colle colle@krtkg1.rug.ac.be
Christophe Kalt Christophe.Kalt@kbcfp.com
@@ -100,6 +102,7 @@ Claude Scarpelli claude@genethon.fr
Claus Heine Claus_Heine@ac2.maus.de
Cliff Krumvieda cliff@cs.cornell.edu
Clinton Carr clint@netcom.com
Connor Behan connor.behan@gmail.com
Conrad Hughes chughes@maths.tcd.ie
Constantin Belous const@cris.net
Coranth Gryphon gryphon@bur.visidyne.com
@@ -118,6 +121,7 @@ Danny R. Johnston danny@cs.weber.edu
Dave Barr barr@math.psu.edu
Dave Gentzel gentzel@nova.enet.dec.com
Dave Gregorich dtg@ipac.caltech.edu
David Barri japgolly@gmail.com
David Brown davidb@davidb.org
David J. MacKenzie djm@uunet.uu.net
David Johnson David.W.Johnson@colorado.edu
@@ -241,6 +245,7 @@ Jim Clausing jac@postbox.acs.ohio-state.edu
Jim Farrell jwf@platinum.com
Jim Meyering meyering@na-net.ornl.gov
Jim Murray jjm@jjm.com
Jivko Angelov jivko@siteground.com
Joachim Holzfuss Joachim.Holzfuss@iap.physik.th-darmstadt.de
Joachim Seelig joachim@kruemel.han.de
Joe DeBattista joed@itsa.ucsf.edu
@@ -296,6 +301,7 @@ Kimmy Posey kimmyd@bnr.ca
Koji Kishi kis@rqa.sony.co.jp
Konno Hiroharu konno@pac.co.jp
Kurt Jaeger pi@lf.net
James Antill jantill@redhat.com
Larry Creech lcreech@lonestar.rcclub.org
Larry Schwimmer rosebud@cyclone.stanford.edu
Lasse Collin lasse.collin@tukaani.org
@@ -349,6 +355,7 @@ Michael P Urban urban@cobra.jpl.nasa.gov
Michael Schmidt michael@muc.de
Michael Schwingen m.schwingen@stochastik.rwth-aachen.de
Michael Smolsky fnsiguc@astro.weizmann.ac.il
Michal Žejdl zejdl@suas.cz
Mike Muuss mike@brl.mil
Mike Nolan nolan@lpl.arizona.edu
Mike Rogers mike@demon.net
@@ -357,11 +364,14 @@ Mike Walker M.D.Walker@larc.nasa.gov
Milan Hodoscek milan@kihp6.ki.si
Minh Tran-Le tranle@intellicorp.com
Mitsuaki Masuhara masuhara@mcprv.mec.mei.co.jp
Natalie Alifanova na@nxc.no
Nate Eldredge nate@cs.hmc.edu
Nathan Stratton Treadway nathanst+bugtar@ontko.com
Neil Faulks neil@dcs.kcl.ac.uk
Neil Jerram nj104@cus.cam.ac.uk
Nelson H.F. Beebe beebe@math.utah.edu
Nick Barron nikb@cix.compulink.co.uk
Nicolas Dudebout nicolas.dudebout@gmail.com
Noah Friedman friedman@gnu.org
Noel Cragg noel@red-bean.com
Norbert Kiesel norbert@rwthi3.informatik.rwth-aachen.de
@@ -374,6 +384,7 @@ Oswald P. Backus IV backus@lks.csi.com
Pascal Meheut pascal@cnam.cnam.fr
Patrick Fulconis fulco@sig.uvsq.fr
Patrick Timmons timmons@electech.polymtl.ca
Pavel Raiskup praiskup@redhat.com
Paul Eggert eggert@twinsun.com
Paul Kanz paul@icx.com
Paul Mitchell P.Mitchell@surrey.ac.uk
@@ -395,6 +406,7 @@ Phil Proudman phil@proudman51.freeserve.co.uk
Philippe Defert defert@cern.ch
Piercarlo Grandi piercarl@sabi.demon.co.uk
Pierce Cantrell cantrell@ee.tamu.edu
Piotr Rotter piotr.rotter@active24.pl
R. Kent Dybvig dyb@cadence.bloomington.in.us
R. Scott Butler butler@prism.es.dupont.com
Rainer Orth ro@TechFak.Uni-Bielefeld.DE

26
TODO
View File

@@ -45,24 +45,22 @@ Suggestions for improving GNU tar.
* Copyright notice
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
Copyright 2003-2004, 2007, 2013-2014 Free Software Foundation, Inc.
This file is part of GNU tar.
This file is part of GNU tar.
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 free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
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.
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 tar; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Local variables:

View File

@@ -1,18 +1,21 @@
dnl Special Autoconf macros for GNU Tar -*- autoconf -*-
dnl Copyright (C) 2009 Free Software Foundation, Inc.
dnl Special Autoconf macros for GNU tar -*- autoconf -*-
dnl Copyright 2009, 2013-2014 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU tar.
dnl
dnl GNU tar is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 3, or (at your option)
dnl any later version.
dnl the Free Software Foundation; either version 3 of the License, or
dnl (at your option) any later version.
dnl
dnl GNU tar is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License along
dnl with GNU tar. If not, see <http://www.gnu.org/licenses/>.
dnl You should have received a copy of the GNU General Public License
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_DEFUN([TAR_COMPR_PROGRAM],[
m4_pushdef([tar_compr_define],translit($1,[a-z+-],[A-ZX_])[_PROGRAM])
@@ -24,3 +27,50 @@ AC_DEFUN([TAR_COMPR_PROGRAM],[
[tar_compr_var=m4_if($2,,$1,$2)])
AC_DEFINE_UNQUOTED(tar_compr_define, "$tar_compr_var",
[Define to the program name of ]$1[ compressor program])])
# Provide <attr/xattr.h>, if necessary
AC_DEFUN([TAR_HEADERS_ATTR_XATTR_H],
[
AC_ARG_WITH([xattrs],
AS_HELP_STRING([--without-xattrs], [don't use linux extended attributes]),
[], [with_xattrs=maybe]
)
# First check for <sys/xattr.h>
AC_CHECK_HEADERS([sys/xattr.h])
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_sys_xattr_h" = yes])
AM_CONDITIONAL([TAR_LIB_ATTR],[false])
if test "$ac_cv_header_sys_xattr_h" = yes; then
AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
setxattr fsetxattr lsetxattr \
listxattr flistxattr llistxattr,
# only when functions are present
AC_DEFINE([HAVE_SYS_XATTR_H], [1],
[define to 1 if we have <sys/xattr.h> header])
if test "$with_xattrs" != no; then
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
fi
)
fi
# If <sys/xattr.h> is not found, then check for <attr/xattr.h>
if test "$ac_cv_header_sys_xattr_h" != yes; then
AC_CHECK_HEADERS([attr/xattr.h])
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_attr_xattr_h" = yes])
AC_CHECK_LIB([attr],[fgetxattr])
AM_CONDITIONAL([TAR_LIB_ATTR],[test "$ac_cv_lib_attr_fgetxattr" = yes])
if test "$ac_cv_header_attr_xattr_h" = yes; then
AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
setxattr fsetxattr lsetxattr \
listxattr flistxattr llistxattr,
# only when functions are present
AC_DEFINE([HAVE_ATTR_XATTR_H], [1],
[define to 1 if we have <attr/xattr.h> header])
if test "$with_xattrs" != no; then
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
fi
)
fi
fi
])

View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Print a version string.
scriptversion=2010-10-24.18; # UTC
scriptversion=2012-12-31.16; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2010 Free Software Foundation, Inc.
# Copyright (C) 2003-2010, 2013-2014 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
@@ -131,7 +131,6 @@ tests_base=tests
# Extra files from gnulib, which override files from other sources.
gnulib_extra_files="
$build_aux/install-sh
$build_aux/missing
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
@@ -464,8 +463,7 @@ git_modules_config () {
}
gnulib_path=`git_modules_config submodule.gnulib.path`
: ${gnulib_path=gnulib}
: ${gnulib_path:=gnulib}
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
@@ -623,6 +621,7 @@ symlink_to_dir()
/*) ;;
*)
case /$dst/ in
/./*) ;;
*//* | */../* | */./* | /*/*/*/*/*/)
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
exit 1;;

View File

@@ -1,25 +1,24 @@
# Bootstrap configuration for GNU tar.
# Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# Copyright 2006-2009, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
source_base=gnu
gnulib_name=libgnu
gnulib_mk=Makefile.am
# We don't need these modules, even though gnulib-tool mistakenly
# includes them because of gettext dependencies.
@@ -68,7 +67,7 @@ fi
test -d m4 || mkdir m4
test -d $source_base || mkdir $source_base
cat > ChangeLog <<EOT
test -f ChangeLog || cat > ChangeLog <<EOT
This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist. Run make ChangeLog if you wish to create it earlier.
EOT

View File

@@ -1,42 +1,40 @@
# Configure template for GNU tar. -*- autoconf -*-
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
# Software Foundation, Inc.
# Copyright 1991, 1994-2010, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_INIT([GNU tar], [1.24], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.28], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_PREREQ([2.63])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-xz dist-shar std-options silent-rules])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-xz std-options silent-rules])
# Enable silent rules by default:
AM_SILENT_RULES([yes])
AC_PROG_CC
AC_PROG_CC_STDC
AC_EXEEXT
AC_PROG_RANLIB
AC_PROG_YACC
gl_EARLY
AC_CHECK_TOOLS([AR], [ar])
AC_SYS_LARGEFILE
AC_ISC_POSIX
AC_C_INLINE
AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h memory.h net/errno.h \
@@ -51,12 +49,7 @@ AC_CHECK_HEADERS([sys/buf.h], [], [],
#include <sys/param.h>
#endif])
AC_HEADER_SYS_WAIT
AC_HEADER_DIRENT
AC_HEADER_MAJOR
AC_HEADER_STAT
AC_HEADER_STDC
AC_MSG_CHECKING([for st_fstype string in struct stat])
AC_CACHE_VAL(diff_cv_st_fstype_string,
@@ -70,11 +63,33 @@ if test $diff_cv_st_fstype_string = yes; then
[Define if struct stat has a char st_fstype[] member.])
fi
AC_TYPE_SIGNAL
# even if we use gnulib's acl.h with integrated m4 file later on (used because
# of very useful file_has_acl() function) we need following checks that restrict
# tar to use POSIX.1e ACLs only.
AC_ARG_WITH([posix-acls],
AS_HELP_STRING([--without-posix-acls],
[do not use POSIX.1e access control lists]),
[],
[with_posix_acls=yes])
if test "x$with_posix_acls" != "xno"; then
AC_CHECK_HEADERS(sys/acl.h,, [with_posix_acls=no])
for tar_acl_func in acl_get_file acl_get_fd acl_set_file acl_set_fd \
acl_to_text acl_from_text acl_delete_def_file \
acl_free; do \
test "x$with_posix_acls" = xno && break
AC_SEARCH_LIBS([$tar_acl_func], [acl pacl], [], [with_posix_acls=no])
done
if test "x$with_posix_acls" != xno; then
AC_DEFINE(HAVE_POSIX_ACLS,,[Define when we have working POSIX acls])
fi
else
# disable acls in gnulib's checks
export enable_acl=no
fi
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T
AC_CHECK_TYPE(major_t, , AC_DEFINE(major_t, int,
[Type of major device numbers.]))
@@ -90,13 +105,115 @@ gl_INIT
# paxutils modules
tar_PAXUTILS
AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink])
# gl_GCC_VERSION_IFELSE([major], [minor], [run-if-found], [run-if-not-found])
# ------------------------------------------------
# If $CPP is gcc-MAJOR.MINOR or newer, then run RUN-IF-FOUND.
# Otherwise, run RUN-IF-NOT-FOUND.
AC_DEFUN([gl_GCC_VERSION_IFELSE],
[AC_PREPROC_IFELSE(
[AC_LANG_PROGRAM(
[[
#if ($1) < __GNUC__ || (($1) == __GNUC__ && ($2) <= __GNUC_MINOR__)
/* ok */
#else
# error "your version of gcc is older than $1.$2"
#endif
]]),
], [$3], [$4])
]
)
AC_ARG_ENABLE([gcc-warnings],
[AS_HELP_STRING([--enable-gcc-warnings],
[turn on many GCC warnings (for developers; best with GNU make)])],
[case $enableval in
yes|no) ;;
*) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;;
esac
gl_gcc_warnings=$enableval],
[gl_gcc_warnings=no
if test -d "$srcdir"/.git; then
gl_GCC_VERSION_IFELSE([4], [6], [gl_gcc_warnings=yes])
fi]
)
if test "$gl_gcc_warnings" = yes; then
gl_WARN_ADD([-Werror], [WERROR_CFLAGS])
AC_SUBST([WERROR_CFLAGS])
nw=
# This, $nw, is the list of warnings we disable.
nw="$nw -Wformat-nonliteral" # warnings in Fedora 17 stdio.h
nw="$nw -Wvla" # warnings in gettext.h
nw="$nw -Wswitch-default" # Too many warnings for now
nw="$nw -Wunsafe-loop-optimizations" # It's OK to omit unsafe optimizations.
nw="$nw -Winline" # It's OK to not inline.
nw="$nw -Wstrict-overflow" # It's OK to optimize strictly.
nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now.
gl_MANYWARN_ALL_GCC([ws])
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
for w in $ws; do
gl_WARN_ADD([$w])
done
gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now
gl_WARN_ADD([-Wno-type-limits]) # It's OK to optimize based on types.
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
gl_WARN_ADD([-Wno-format-nonliteral])
gl_WARN_ADD([-fdiagnostics-show-option])
gl_WARN_ADD([-funit-at-a-time])
AC_SUBST([WARN_CFLAGS])
AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
AH_VERBATIM([FORTIFY_SOURCE],
[/* Enable compile-time and run-time bounds-checking, and some warnings,
without upsetting glibc 2.15+. */
#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__
# define _FORTIFY_SOURCE 2
#endif
])
AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks])
# Use a slightly smaller set of warning options for lib/.
# Remove the following and save the result in GNULIB_WARN_CFLAGS.
nw=
nw="$nw -Wmissing-prototypes"
nw="$nw -Wunused-macros"
#
# These are for argp.
nw="$nw -Wmissing-field-initializers"
nw="$nw -Wshadow"
#
gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
# This is also for argp.
gl_WARN_ADD([-Wno-missing-field-initializers], [GNULIB_WARN_CFLAGS])
AC_SUBST([GNULIB_WARN_CFLAGS])
# For gnulib-tests, the set is slightly smaller still.
nw=
# It's not worth being this picky about test programs.
nw="$nw -Wsuggest-attribute=const"
gl_MANYWARN_COMPLEMENT([GNULIB_TEST_WARN_CFLAGS],
[$GNULIB_WARN_CFLAGS], [$nw])
AC_SUBST([GNULIB_TEST_WARN_CFLAGS])
fi
TAR_HEADERS_ATTR_XATTR_H
AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink grantpt])
AM_CONDITIONAL([TAR_COND_GRANTPT], [test $ac_cv_func_grantpt = yes])
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
AC_CHECK_DECLS([time],,, [#include <time.h>])
AC_REPLACE_FUNCS(waitpid)
AC_ARG_VAR([RSH], [Configure absolute path to default remote shell binary])
AC_CACHE_CHECK(for remote shell, tar_cv_path_RSH,
[if test -n "$RSH"; then
tar_cv_path_RSH=$RSH
@@ -157,7 +274,7 @@ if test -z "$DEFAULT_ARCHIVE"; then
DEFAULT_ARCHIVE=-
else
if test -z "`ls $DEFAULT_ARCHIVE 2>/dev/null`"; then
AC_MSG_WARN(DEFAULT_ARCHIVE \`$DEFAULT_ARCHIVE' not found on this system)
AC_MSG_WARN(DEFAULT_ARCHIVE '$DEFAULT_ARCHIVE' not found on this system)
fi
# FIXME: Look for DEFTAPE in <sys/mtio.h>.
# FIXME: Let DEVICE_PREFIX be configured from the environment.

View File

@@ -1,11 +1,11 @@
%%comments:
Copyright (C) 2004 Free Software Foundation, Inc.
Copyright 2004, 2013-2014 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2 or
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts. A copy of the license is included in the file COPYING.
Texts. For a copy of the license, see <http://www.gnu.org/licenses/>.
%%name: tar

View File

@@ -1,21 +1,22 @@
# Makefile for GNU tar documentation.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007 Free Software Foundation, Inc.
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2013-2014 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 file is part of GNU tar.
## 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.
# 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 of the License, or
# (at your option) any later version.
## 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.
# 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 this program. If not, see <http://www.gnu.org/licenses/>.
info_TEXINFOS = tar.texi
tar_TEXINFOS = \
@@ -31,10 +32,16 @@ tar_TEXINFOS = \
snapshot.texi\
sparse.texi\
value.texi
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
dist_man_MANS=tar.1 $(RMT_8)
if PU_RMT_COND
RMT_8=rmt.8
endif
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el rmt.8
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
# Just call 'make RENDITION=PROOF [target]' if you want PROOF rendition.
RENDITION = DISTRIB
MAKEINFOFLAGS=-D$(RENDITION)

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006, 2007 Free Software Foundation, Inc.
@c Copyright (C) 2006-2007, 2014 Free Software Foundation, Inc.
@c Written by Sergey Poznyakoff
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.

View File

@@ -5,7 +5,8 @@
@c hence no sectioning command or @node.
@display
Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
Copyright @copyright{} 2000-2002, 2007-2008, 2014 Free Software
Foundation, Inc.
@uref{http://fsf.org/}
Everyone is permitted to copy and distribute verbatim copies

View File

@@ -106,7 +106,7 @@ Please send broken links and other corrections (or suggestions) to
</p>
<p>
Copyright (C) 2004 Free Software Foundation, Inc.,
Copyright 2004, 2013-2014 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02111, USA
<br />
Verbatim copying and distribution of this entire article is

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006 Free Software Foundation, Inc.
@c Copyright (C) 2006, 2014 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.

View File

@@ -1,26 +1,25 @@
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
;; Copyright 2006-2007, 2013-2014 Free Software Foundation, Inc.
;; Author: Sergey Poznyakoff
;; Maintainer: bug-tar@gnu.org
;; Keywords: maint, tex, docs
;; This file is part of GNU tar documentation suite
;; This file is part of GNU tar.
;; This program is free software; you can redistribute it and/or modify
;; 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.
;; the Free Software Foundation; either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; 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 this program; if not, write to the Free Software Foundation,
;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:

View File

@@ -1,6 +1,6 @@
@c This is part of GNU tar manual.
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
@c 2003, 2004, 2006 Free Software Foundation, Inc.
@c Copyright 1992, 1994-1997, 1999-2004, 2006, 2013-2014 Free Software
@c Foundation, Inc.
@c See file tar.texi for copying conditions.
@c This file contains support for 'renditions' by Fran@,{c}ois Pinard

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2005, 2007 Free Software Foundation, Inc.
@c Copyright (C) 2005, 2007, 2014 Free Software Foundation, Inc.
@c Written by Sergey Poznyakoff
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@@ -11,11 +11,11 @@ used to determine which files were modified since the last backup.
@GNUTAR{} version @value{VERSION} supports three snapshot file
formats. The first format, called @dfn{format 0}, is the one used by
@GNUTAR{} versions up to 1.15.1. The second format, called @dfn{format
1} is an extended version of this format, that contains more metadata
and allows for further extensions. It was used by version
1.15.1. Starting from version 1.16 and up to @value{VERSION}, the
@dfn{format 2} is used.
@GNUTAR{} versions up to and including 1.15.1. The second format, called
@dfn{format 1} is an extended version of this format, that contains more
metadata and allows for further extensions. It was used by alpha release
version 1.15.90. For alpha version 1.15.91 and stable releases
version 1.16 up through @value{VERSION}, the @dfn{format 2} is used.
@GNUTAR{} is able to read all three formats, but will create
snapshots only in format 2.
@@ -33,7 +33,7 @@ metadata descriptions, one per line. Each description has the
following format:
@smallexample
@var{nfs}@var{dev} @var{inode} @var{name}
[@var{nfs}]@var{dev} @var{inode} @var{name}
@end smallexample
@noindent
@@ -42,7 +42,10 @@ where:
@table @var
@item nfs
A single plus character (@samp{+}), if this directory is located on
an @acronym{NFS}-mounted partition, or a single space otherwise;
an @acronym{NFS}-mounted partition, otherwise empty.
(That is, for non-NFS directories, the first character on the
description line contains the start of the @var{dev} field.)
@item dev
Device number of the directory;
@@ -91,7 +94,6 @@ as with @samp{format 0}.
@cindex format 2, snapshot file
@cindex snapshot file, format 2
@FIXME{}
@item
@samp{Format 2} snapshot file begins with a format identifier, as described for
version 1, e.g.:
@@ -105,7 +107,7 @@ records, separated by null (@acronym{ASCII} 0)
characters. Thus, in contrast to the previous formats, format 2
snapshot is a binary file.
First two records are decimal numbers, representing the
First two records are decimal integers, representing the
time of the last backup. First number is the number of seconds, the
second one is the number of nanoseconds, since the beginning of the
epoch. These are followed by arbitrary number of directory records.
@@ -113,17 +115,18 @@ epoch. These are followed by arbitrary number of directory records.
Each @dfn{directory record} contains a set of metadata describing a
particular directory. Parts of a directory record are delimited with
@acronym{ASCII} 0 characters. The following table describes each
part. The @dfn{Number} type in this table stands for a decimal number
in @acronym{ASCII} notation.
part. The @dfn{Number} type in this table stands for a decimal integer
in @acronym{ASCII} notation. (Negative values are preceeded with a "-"
character, while positive values have no leading punctuation.)
@multitable @columnfractions 0.2 0.2 0.6
@multitable @columnfractions 0.25 0.15 0.6
@headitem Field @tab Type @tab Description
@item nfs @tab Character @tab @samp{1} if the directory is located on
an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
@item mtime-sec @tab Number @tab Modification time, seconds;
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
@item dev-no @tab Number @tab Device number;
@item i-no @tab Number @tab I-node number;
@item timestamp_sec @tab Number @tab Modification time, seconds;
@item timestamp_nsec @tab Number @tab Modification time, nanoseconds;
@item dev @tab Number @tab Device number;
@item ino @tab Number @tab I-node number;
@item name @tab String @tab Directory name; in contrast to the
previous versions it is not quoted;
@item contents @tab Dumpdir @tab Contents of the directory;
@@ -134,6 +137,28 @@ previous versions it is not quoted;
Dumpdirs stored in snapshot files contain only records of types
@samp{Y}, @samp{N} and @samp{D}.
@cindex snapshot file field ranges
@opindex show-snapshot-field-ranges
The specific range of values allowed in each of the @dfn{Number} fields
depends on the underlying C datatypes as determined when @command{tar}
is compiled. To see the specific ranges allowed for a particular
@command{tar} binary, you can use the
@option{--show-snapshot-field-ranges} option:
@smallexample
$ @kbd{tar --show-shapshot-field-ranges}
This tar's snapshot file field ranges are
(field name => [ min, max ]):
nfs => [ 0, 1 ],
timestamp_sec => [ -9223372036854775808, 9223372036854775807 ],
timestamp_nsec => [ 0, 999999999 ],
dev => [ 0, 18446744073709551615 ],
ino => [ 0, 18446744073709551615 ],
@end smallexample
(This example is from a GNU/Linux x86_64 system.)
@end enumerate
@c End of snapshot.texi

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006 Free Software Foundation, Inc.
@c Copyright (C) 2006, 2014 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.

View File

@@ -1,29 +1,33 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2007 Free Software Foundation, Inc.
@c Copyright (C) 2007, 2014 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@cindex Device numbers, changing
@cindex snapshot files, editing
@cindex snapshot files, fixing device numbers
Sometimes device numbers can change after upgrading your kernel
version or reconfiguring the hardware. Reportedly this is the case with
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
Various situations can cause device numbers to change: upgrading your
kernel version, reconfiguring your hardware, loading kernel modules in a
different order, using virtual volumes that are assembled dynamically
(such as with @acronym{LVM} or @acronym{RAID}), hot-plugging drives
(e.g. external USB or Firewire drives), etc. In the majority of
cases this change is unnoticed by the users. However, it influences
@command{tar} incremental backups: the device number is stored in tar
snapshot files (@pxref{Snapshot Files}) and is used to determine whether
the file has changed since the last backup. If the device numbers
change for some reason, the next backup you run will be a full backup.
change for some reason, by default the next backup you run will be a
full backup.
@pindex tar-snapshot-edit
To minimize the impact in these cases, GNU @command{tar} comes with
the @command{tar-snapshot-edit} utility for inspecting and updating
device numbers in snapshot files. The utility, written by
Dustin J.@: Mitchell, is available from
device numbers in snapshot files. (The utility, written by
Dustin J.@: Mitchell, is also available from the
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
@GNUTAR{} home page}.
@GNUTAR{} home page}.)
To obtain the device numbers used in the snapshot file, run
To obtain a summary of the device numbers found in the snapshot file, run
@smallexample
$ @kbd{tar-snapshot-edit @var{snapfile}}
@@ -31,10 +35,19 @@ $ @kbd{tar-snapshot-edit @var{snapfile}}
@noindent
where @var{snapfile} is the name of the snapshot file (you can supply as many
files as you wish in a single command line).
files as you wish in a single command line). You can then compare the
numbers across snapshot files, or against those currently in use on the
live filesystem (using @command{ls -l} or @command{stat}).
To update all occurrences of the given device number in the file, use
@option{-r} option. It takes a single argument of the form
Assuming the device numbers have indeed changed, it's often possible
to simply tell @GNUTAR{} to ignore the device number when processing the
incremental snapshot files for these backups, using the
@option{--no-check-device} option (@pxref{device numbers}).
Alternatively, you can use the @command{tar-edit-snapshot} script's
@option{-r} option to update all occurrences of the given device
number in the snapshot file(s). It takes a single argument
of the form
@samp{@var{olddev}-@var{newdev}}, where @var{olddev} is the device number
used in the snapshot file, and @var{newdev} is the corresponding new device
number. Both numbers may be specified in hex (e.g., @samp{0xfe01}),
@@ -49,9 +62,30 @@ backup file is obtained by appending @samp{~} to the original file name.
An example session:
@smallexample
$ @kbd{tar-snapshot-edit /var/backup/snap.a}
file version 2
/tmp/snap: Device 0x0306 occurs 634 times.
$ @kbd{tar-snapshot-edit -b -r 0x0306-0x4500 /var/backup/snap.a}
file version 2
$ @kbd{tar-snapshot-edit root_snap.0 boot_snap.0}
File: root_snap.0
Detected snapshot file version: 2
Device 0x0000 occurs 1 times.
Device 0x0003 occurs 1 times.
Device 0x0005 occurs 1 times.
Device 0x0013 occurs 1 times.
Device 0x6801 occurs 1 times.
Device 0x6803 occurs 6626 times.
Device 0xfb00 occurs 1 times.
File: boot_snap.0
Detected snapshot file version: 2
Device 0x6801 occurs 3 times.
$ @kbd{tar-snapshot-edit -b -r 0x6801-0x6901,0x6803-0x6903 root_snap.0 boot_snap.0}
File: root_snap.0
Detected snapshot file version: 2
Updated 6627 records.
File: boot_snap.0
Detected snapshot file version: 2
Updated 3 records.
@end smallexample

1174
doc/tar.1 Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,19 @@
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
#
# 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.
#
# Copyright 2006-2007, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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, write to the Free Software
# Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1{s,/\*,@comment ,
b

View File

@@ -1,6 +1,6 @@
@c This is part of GNU tar manual.
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
@c 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@c Copyright 1992, 1994-1997, 1999-2006, 2013-2014 Free Software
@c Foundation, Inc.
@c See file tar.texi for copying conditions.
@macro GNUTAR

3
gnu/Makefile.am Normal file
View File

@@ -0,0 +1,3 @@
# Make the subset of Gnulib that GNU tar needs.
include gnulib.mk
AM_CFLAGS += $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)

View File

@@ -1,6 +1,24 @@
# List of gnulib modules needed for GNU tar.
# A module name per line. Empty lines and comments are ignored.
# Copyright 2005-2010, 2012-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
acl
alloca
argmatch
argp
@@ -11,12 +29,19 @@ configmake
dirname
error
exclude
extern-inline
exitfail
faccessat
fchmodat
fchownat
fcntl-h
fdopendir
fdutimensat
fileblocks
fnmatch-gnu
fprintftime
fseeko
fstatat
full-write
futimens
getline
@@ -32,21 +57,27 @@ inttypes
lchown
linkat
localcharset
manywarnings
mkdirat
mkdtemp
mkfifoat
modechange
obstack
openat
parse-datetime
posix_openpt
ptsname
priv-set
progname
quote
quotearg
readlinkat
renameat
root-uid
rpmatch
safe-read
savedir
selinux-at
setenv
snprintf
stat-time
@@ -55,12 +86,16 @@ stdint
stpcpy
strdup-posix
strerror
strtoimax
strtol
strtoul
strtoumax
symlinkat
timespec
unlinkat
unlinkdir
unlocked-io
unlockpt
utimensat
version-etc-fsf
xalloc

10
lib/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
paxerror.c
paxexit-status.c
paxexit.c
paxlib.h
paxnames.c
rmt-command.h
rmt.h
rtapelib.c
system-ioctl.h
system.h

View File

@@ -1,21 +1,22 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
# 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
# Copyright 1994-1997, 1999-2001, 2003-2007, 2009-2010, 2013-2014 Free
# Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
noinst_LIBRARIES=libtar.a
rmt-command.h : Makefile
@@ -26,13 +27,36 @@ rmt-command.h : Makefile
$(AM_V_at)mv $@-t $@
BUILT_SOURCES = rmt-command.h
CLEANFILES = rmt-command.h rmt-command.h-t
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu
AM_CFLAGS = $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)
noinst_HEADERS = \
paxlib.h\
rmt.h\
stdopen.h\
system.h\
system-ioctl.h\
wordsplit.h\
xattr-at.h
noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h
libtar_a_SOURCES = \
paxerror.c paxexit.c paxlib.h paxnames.c \
paxerror.c paxexit-status.c paxlib.h paxnames.c \
prepargs.c prepargs.h \
rtapelib.c \
rmt.h \
stdopen.c stdopen.h \
system.h system-ioctl.h
system.h system-ioctl.h \
wordsplit.c\
xattr-at.c
if !TAR_COND_XATTR_H
BUILT_SOURCES += attr/xattr.h
attr/xattr.h: attr-xattr.in.h $(top_builddir)/config.status
$(AM_V_at)$(MKDIR_P) attr
$(AM_V_GEN)rm -f $@-t $@ && \
cp $(srcdir)/attr-xattr.in.h attr/xattr.h
endif
MOSTLYCLEANFILES = attr/xattr.h
EXTRA_DIST = attr-xattr.in.h

60
lib/attr-xattr.in.h Normal file
View File

@@ -0,0 +1,60 @@
/* Replacement <attr/xattr.h> for platforms that lack it.
Copyright 2012-2014 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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef TAR_ATTR_XATTR_H
#define TAR_ATTR_XATTR_H
#include <errno.h>
#ifndef ENOATTR
# define ENOATTR ENODATA /* No such attribute */
#endif
/* setting */
static inline int setxattr (const char *path, const char *name, const void
*value, size_t size, int flags)
{ errno = ENOTSUP; return -1; }
static inline int lsetxattr (const char *path, const char *name, const void
*value, size_t size, int flags)
{ errno = ENOTSUP; return -1; }
static inline int fsetxattr (int filedes, const char *name, const void *value,
size_t size, int flags)
{ errno = ENOTSUP; return -1; }
/* getting */
static inline ssize_t getxattr (const char *path, const char *name, void *value,
size_t size)
{ errno = ENOTSUP; return -1; }
static inline ssize_t lgetxattr (const char *path, const char *name, void
*value, size_t size)
{ errno = ENOTSUP; return -1; }
static inline ssize_t fgetxattr (int filedes, const char *name, void *value,
size_t size)
{ errno = ENOTSUP; return -1; }
/* listing */
static inline ssize_t listxattr (const char *path, char *list, size_t size)
{ errno = ENOTSUP; return -1; }
static inline ssize_t llistxattr (const char *path, char *list, size_t size)
{ errno = ENOTSUP; return -1; }
static inline ssize_t flistxattr (int filedes, char *list, size_t size)
{ errno = ENOTSUP; return -1; }
#endif

View File

@@ -1,5 +1,5 @@
/* Parse arguments from a string and prepend them to an argv.
Copyright 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
Copyright 1999-2001, 2007, 2013-2014 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
@@ -12,9 +12,7 @@
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. */
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Paul Eggert <eggert@twinsun.com>. */
@@ -31,16 +29,6 @@
#include <ctype.h>
/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
as an argument to <ctype.h> macros like "isspace". */
#ifdef STDC_HEADERS
# define IN_CTYPE_DOMAIN(c) 1
#else
# define IN_CTYPE_DOMAIN(c) ((c) <= 0177)
#endif
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
/* Find the white-space-separated options specified by OPTIONS, and
using BUF to store copies of these options, set ARGV[0], ARGV[1],
etc. to the option copies. Return the number N of options found.
@@ -55,7 +43,7 @@ prepend_args (char const *options, char *buf, char **argv)
for (;;)
{
while (ISSPACE ((unsigned char) *o))
while (isspace ((unsigned char) *o))
o++;
if (!*o)
return n;
@@ -66,7 +54,7 @@ prepend_args (char const *options, char *buf, char **argv)
do
if ((*b++ = *o++) == '\\' && *o)
b[-1] = *o++;
while (*o && ! ISSPACE ((unsigned char) *o));
while (*o && ! isspace ((unsigned char) *o));
*b++ = '\0';
}

View File

@@ -1,6 +1,6 @@
/* stdopen.c - ensure that the three standard file descriptors are in use
Copyright (C) 2005, 2007 Free Software Foundation, Inc.
Copyright 2005, 2007, 2013-2014 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
@@ -13,8 +13,7 @@
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. */
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Paul Eggert and Jim Meyering. */

1628
lib/wordsplit.c Normal file

File diff suppressed because it is too large Load Diff

162
lib/wordsplit.h Normal file
View File

@@ -0,0 +1,162 @@
/* wordsplit - a word splitter
Copyright (C) 2009-2014 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 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
Written by Sergey Poznyakoff
*/
#ifndef __WORDSPLIT_H
#define __WORDSPLIT_H
#include <stddef.h>
struct wordsplit
{
size_t ws_wordc;
char **ws_wordv;
size_t ws_offs;
size_t ws_wordn;
int ws_flags;
const char *ws_delim;
const char *ws_comment;
const char *ws_escape;
void (*ws_alloc_die) (struct wordsplit * wsp);
void (*ws_error) (const char *, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
void (*ws_debug) (const char *, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
const char **ws_env;
const char *(*ws_getvar) (const char *, size_t, void *);
void *ws_closure;
const char *ws_input;
size_t ws_len;
size_t ws_endp;
int ws_errno;
struct wordsplit_node *ws_head, *ws_tail;
};
/* Wordsplit flags. Only 2 bits of a 32-bit word remain unused.
It is getting crowded... */
/* Append the words found to the array resulting from a previous
call. */
#define WRDSF_APPEND 0x00000001
/* Insert we_offs initial NULLs in the array ws_wordv.
(These are not counted in the returned ws_wordc.) */
#define WRDSF_DOOFFS 0x00000002
/* Don't do command substitution. Reserved for future use. */
#define WRDSF_NOCMD 0x00000004
/* The parameter p resulted from a previous call to
wordsplit(), and wordsplit_free() was not called. Reuse the
allocated storage. */
#define WRDSF_REUSE 0x00000008
/* Print errors */
#define WRDSF_SHOWERR 0x00000010
/* Consider it an error if an undefined shell variable
is expanded. */
#define WRDSF_UNDEF 0x00000020
/* Don't do variable expansion. */
#define WRDSF_NOVAR 0x00000040
/* Abort on ENOMEM error */
#define WRDSF_ENOMEMABRT 0x00000080
/* Trim off any leading and trailind whitespace */
#define WRDSF_WS 0x00000100
/* Handle single quotes */
#define WRDSF_SQUOTE 0x00000200
/* Handle double quotes */
#define WRDSF_DQUOTE 0x00000400
/* Handle quotes and escape directives */
#define WRDSF_QUOTE (WRDSF_SQUOTE|WRDSF_DQUOTE)
/* Replace each input sequence of repeated delimiters with a single
delimiter */
#define WRDSF_SQUEEZE_DELIMS 0x00000800
/* Return delimiters */
#define WRDSF_RETURN_DELIMS 0x00001000
/* Treat sed expressions as words */
#define WRDSF_SED_EXPR 0x00002000
/* ws_delim field is initialized */
#define WRDSF_DELIM 0x00004000
/* ws_comment field is initialized */
#define WRDSF_COMMENT 0x00008000
/* ws_alloc_die field is initialized */
#define WRDSF_ALLOC_DIE 0x00010000
/* ws_error field is initialized */
#define WRDSF_ERROR 0x00020000
/* ws_debug field is initialized */
#define WRDSF_DEBUG 0x00040000
/* ws_env field is initialized */
#define WRDSF_ENV 0x00080000
/* ws_getvar field is initialized */
#define WRDSF_GETVAR 0x00100000
/* enable debugging */
#define WRDSF_SHOWDBG 0x00200000
/* Don't split input into words. Useful for side effects. */
#define WRDSF_NOSPLIT 0x00400000
/* Keep undefined variables in place, instead of expanding them to
empty string */
#define WRDSF_KEEPUNDEF 0x00800000
/* Warn about undefined variables */
#define WRDSF_WARNUNDEF 0x01000000
/* Handle C escapes */
#define WRDSF_CESCAPES 0x02000000
/* ws_closure is set */
#define WRDSF_CLOSURE 0x04000000
/* ws_env is a Key/Value environment, i.e. the value of a variable is
stored in the element that follows its name. */
#define WRDSF_ENV_KV 0x08000000
/* ws_escape is set */
#define WRDSF_ESCAPE 0x10000000
/* Incremental mode */
#define WRDSF_INCREMENTAL 0x20000000
#define WRDSF_DEFFLAGS \
(WRDSF_NOVAR | WRDSF_NOCMD | \
WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_CESCAPES)
#define WRDSE_EOF 0
#define WRDSE_QUOTE 1
#define WRDSE_NOSPACE 2
#define WRDSE_NOSUPP 3
#define WRDSE_USAGE 4
#define WRDSE_CBRACE 5
#define WRDSE_UNDEF 6
#define WRDSE_NOINPUT 7
int wordsplit (const char *s, struct wordsplit *p, int flags);
int wordsplit_len (const char *s, size_t len,
struct wordsplit *p, int flags);
void wordsplit_free (struct wordsplit *p);
void wordsplit_free_words (struct wordsplit *ws);
int wordsplit_c_unquote_char (int c);
int wordsplit_c_quote_char (int c);
size_t wordsplit_c_quoted_length (const char *str, int quote_hex,
int *quote);
void wordsplit_general_unquote_copy (char *dst, const char *src, size_t n,
const char *escapable);
void wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n);
void wordsplit_c_unquote_copy (char *dst, const char *src, size_t n);
void wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex);
void wordsplit_perror (struct wordsplit *ws);
const char *wordsplit_strerror (struct wordsplit *ws);
#endif

110
lib/xattr-at.c Normal file
View File

@@ -0,0 +1,110 @@
/* openat-style fd-relative functions for operating with extended file
attributes.
Copyright 2012-2014 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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "xattr-at.h"
#include "openat.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#include "save-cwd.h"
#include "openat-priv.h"
/* setxattrat */
#define AT_FUNC_NAME setxattrat
#define AT_FUNC_F1 setxattr
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, const void *value \
, size_t size, int flags
#define AT_FUNC_POST_FILE_ARGS , name, value, size, flags
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* lsetxattrat */
#define AT_FUNC_NAME lsetxattrat
#define AT_FUNC_F1 lsetxattr
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, const void *value \
, size_t size, int flags
#define AT_FUNC_POST_FILE_ARGS , name, value, size, flags
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* getxattrat */
#define AT_FUNC_NAME getxattrat
#define AT_FUNC_RESULT ssize_t
#define AT_FUNC_F1 getxattr
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, void *value \
, size_t size
#define AT_FUNC_POST_FILE_ARGS , name, value, size
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_RESULT
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* lgetxattrat */
#define AT_FUNC_NAME lgetxattrat
#define AT_FUNC_RESULT ssize_t
#define AT_FUNC_F1 lgetxattr
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, void *value \
, size_t size
#define AT_FUNC_POST_FILE_ARGS , name, value, size
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_RESULT
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* listxattrat */
#define AT_FUNC_NAME listxattrat
#define AT_FUNC_RESULT ssize_t
#define AT_FUNC_F1 listxattr
#define AT_FUNC_POST_FILE_PARAM_DECLS , char *list , size_t size
#define AT_FUNC_POST_FILE_ARGS , list , size
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_RESULT
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* llistxattrat */
#define AT_FUNC_NAME llistxattrat
#define AT_FUNC_RESULT ssize_t
#define AT_FUNC_F1 llistxattr
#define AT_FUNC_POST_FILE_PARAM_DECLS , char *list , size_t size
#define AT_FUNC_POST_FILE_ARGS , list , size
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_RESULT
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS

74
lib/xattr-at.h Normal file
View File

@@ -0,0 +1,74 @@
/* Prototypes for openat-style fd-relative functions for operating with
extended file attributes.
Copyright 2012-2014 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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef XATTRS_AT_H
#define XATTRS_AT_H
#include <sys/types.h>
#if defined(HAVE_SYS_XATTR_H)
# include <sys/xattr.h>
#elif defined(HAVE_ATTR_XATTR_H)
# include <attr/xattr.h>
#endif
#ifndef ENOATTR
# define ENOATTR ENODATA /* No such attribute */
#endif
/* These are the dir-fd-relative variants of the functions without the
"at" suffix. For example, setxattrat (AT_FDCWD, path, name, value, size,
flags &c) is usually equivalent to setxattr (file, name, value, size,
flags). For more info use the setxattr(2), getxattr(2) or listxattr(2)
manpages. */
/* dir-fd-relative setxattr. Operation sets the VALUE of the extended
attribute identified by NAME and associated with the given PATH in the
filesystem relatively to directory identified by DIR_FD. See the
setxattr(2) manpage for the description of all parameters. */
int setxattrat (int dir_fd, const char *path, const char *name,
const void *value, size_t size, int flags);
/* dir-fd-relative lsetxattr. This function is just like setxattrat,
except when DIR_FD and FILE specify a symlink: lsetxattrat operates on the
symlink, while the setxattrat operates on the referent of the symlink. */
int lsetxattrat (int dir_fd, const char *path, const char *name,
const void *value, size_t size, int flags);
/* dir-fd-relative getxattr. Operation gets the VALUE of the extended
attribute idenfified by NAME and associated with the given PATH in the
filesystem relatively to directory identified by DIR_FD. For more info
about all parameters see the getxattr(2) manpage. */
ssize_t getxattrat (int dir_fd, const char *path, const char *name,
void *value, size_t size);
/* dir-fd-relative lgetxattr. This function is just like getxattrat,
except when DIR_FD and FILE specify a symlink: lgetxattrat operates on the
symlink, while the getxattrat operates on the referent of the symlink. */
ssize_t lgetxattrat (int dir_fd, const char *path, const char *name,
void *value, size_t size);
/* dir-fd-relative listxattr. Obtain the list of extended attrubtes names. For
more info see the listxattr(2) manpage. */
ssize_t listxattrat (int dir_fd, const char *path, char *list, size_t size);
/* dir-fd-relative llistxattr. This function is just like listxattrat,
except when DIR_FD and FILE specify a symlink: llistxattr operates on the
symlink, while the listxattrat operates on the referent of the symlink. */
ssize_t llistxattrat (int dir_fd, const char *path, char *list, size_t size);
#endif /* XATTRS_AT_H */

View File

@@ -1,22 +1,22 @@
# List of files which contain translatable strings.
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005, 2007 Free Software
# Copyright 1996, 1999-2000, 2003-2005, 2007, 2013-2014 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 file is part of GNU tar.
# This program is distributed in the hope that it will be useful,
# 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 of the License, 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Library files
gnu/argmatch.c
@@ -37,7 +37,6 @@ gnu/version-etc.c
gnu/xalloc-die.c
lib/paxerror.c
lib/paxexit.c
lib/paxnames.c
lib/rtapelib.c

View File

@@ -1,19 +1,21 @@
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
# Make GNU tar scripts.
## 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.
# Copyright 2004, 2006-2007, 2013-2014 Free Software Foundation, Inc.
## 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.
# This file is part of GNU tar.
## 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.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
BACKUP_LIBEXEC_SCRIPTS_LIST=backup.sh dump-remind
BACKUP_SBIN_SCRIPTS_LIST=backup restore

View File

@@ -82,19 +82,19 @@ SLEEP_MESSAGE="`awk '
}' /dev/null`"
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
# Copyright 2004, 2007, 2013-2014 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 file is part of GNU tar.
## 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.
# 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 of the License, or
# (at your option) any later version.
## 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.
# 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 this program. If not, see <http://www.gnu.org/licenses/>.

View File

@@ -1,21 +1,22 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright (C) 2004, 2005, 2006 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# Make backups.
# Copyright 2004-2006, 2013 Free Software Foundation
# This file is part of GNU tar.
# 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 1, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# the Free Software Foundation; either version 3 of the License, 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
@@ -72,8 +73,9 @@ do
--l=*|--le=*|--lev=*|--leve=*|--level=*)
DUMP_LEVEL=$optarg
;;
-l?*) DUMP_LEVEL=`expr $option : '-l\(.*\)'`;;
-l|--l|--le|--lev|--leve|--level)
prev=$option
prev=--level
;;
--verb=*|--verbo=*|--verbos=*|--verbose=*)
VERBOSE=$optarg
@@ -81,14 +83,13 @@ do
-v|--verb|--verbo|--verbos|--verbose)
VERBOSE=100
;;
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
-v*) VERBOSE=`expr $option : '-v\(.*\)'`;;
--t=*|--ti=*|--tim=*|--time=*)
TIME=$optarg
;;
-t) prev=--t;;
-t*) TIME=`expr $option : "-t\(.*\)"`;;
--t|--ti|--tim|--time)
prev=$option
-t?*) TIME=`expr $option : '-t\(.*\)'`;;
-t|--t|--ti|--tim|--time)
prev=--time
;;
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "backup (@PACKAGE_NAME@) @VERSION@"
@@ -149,7 +150,7 @@ message 20 "BACKUP_DIRS=$BACKUP_DIRS"
message 20 "BACKUP_FILES=$BACKUP_FILES"
# The buch of commands below is run in a subshell for which all output is
# piped through `tee' to the logfile. Doing this, instead of having
# piped through 'tee' to the logfile. Doing this, instead of having
# multiple pipelines all over the place, is cleaner and allows access to
# the exit value from various commands more easily.
(
@@ -187,7 +188,7 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
"--label='`print_level` backup of ${fs} on ${remotehost} at ${NOW}'" \
-C ${fs} .
# `rsh' doesn't exit with the exit status of the remote command. What
# 'rsh' doesn't exit with the exit status of the remote command. What
# stupid lossage. TODO: think of a reliable workaround.
if [ $? -ne 0 ] ; then
echo "Backup of ${1} failed." 1>&2

View File

@@ -1,21 +1,22 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# Make backups.
# Copyright 2004-2006, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 1, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# the Free Software Foundation; either version 3 of the License, 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PROGNAME=`basename $0`
CONFIGPATH="$SYSCONFDIR/backup"
@@ -48,7 +49,7 @@ MT_REWIND=mt_rewind
MT_OFFLINE=mt_offline
MT_STATUS=mt_status
# Insure `mail' is in PATH.
# Insure 'mail' is in PATH.
PATH="/usr/ucb:${PATH}"
export PATH
# Put startdate in the subject line of mailed report, since if it happens
@@ -211,8 +212,8 @@ init_backup() {
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
fi
# Set logfile name
# Logfile name should be in the form ``log-1993-03-18-level-0''
# They go in the directory `@sysconfdir@/log'.
# Logfile name should be in the form 'log-1993-03-18-level-0'
# They go in the directory '@sysconfdir@/log'.
# i.e. year-month-date. This format is useful for sorting by name, since
# logfiles are intentionally kept online for future reference.
LOGFILE="${LOGPATH}/log-`now`-level-${DUMP_LEVEL}"
@@ -305,7 +306,7 @@ backup_host() {
if [ "z${localhost}" != "z$rhost" ] ; then
$RSH "$rhost" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" $@
else
# Using `sh -c exec' causes nested quoting and shell substitution
# Using 'sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
CMD="exec ${TAR_PART1} -f \"${TAPE_FILE}\" $@"
message 10 "CMD: $CMD"
@@ -339,9 +340,9 @@ remote_run() {
license() {
cat - <<EOF
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software. You may redistribute copies of it under the terms of
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
EOF
}

View File

@@ -7,9 +7,25 @@
# This script should be run by tar with --info-script (-F) to inform
# interested parties that a tape for the next volume of the backup needs to
# be put in the tape drive.
#
# Include location of `sendmail' and GNU finger.
# Copyright 2004-2005, 2010, 2012-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
# Include location of 'sendmail' and GNU finger.
PATH="/usr/lib:/usr/local/gnubin:${PATH}"
export PATH
@@ -25,8 +41,8 @@ MT_OFFLINE
# which users are logged into consoles (and thus in the office and capable
# of changing tapes).
#
# Certain users (like `root') aren't real users, and shouldn't be notified.
# Neither should `zippy', `elvis', etc. (on the GNU machines) since they're
# Certain users (like 'root') aren't real users, and shouldn't be notified.
# Neither should 'zippy', 'elvis', etc. (on the GNU machines) since they're
# just test accounts.
recipients="`
finger .clients 2> /dev/null \

View File

@@ -1,21 +1,22 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# Restore backups.
# Copyright 2004, 2006, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 1, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# the Free Software Foundation; either version 3 of the License, 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
@@ -60,8 +61,9 @@ do
--l=*|--le=*|--lev=*|--leve=*|--level=*)
DUMP_LEVEL=$optarg
;;
-l?*) DUMP_LEVEL=`expr $option : '-l\(.*\)'`;;
-l|--l|--le|--lev|--leve|--level)
prev=$option
prev=--level
;;
--verb=*|--verbo=*|--verbos=*|--verbose=*)
VERBOSE=$optarg
@@ -69,7 +71,7 @@ do
-v|--verb|--verbo|--verbos|--verbose)
VERBOSE=100
;;
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
-v*) VERBOSE=`expr $option : '-v\(.*\)'`;;
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "restore (@PACKAGE_NAME@) @VERSION@"
license

View File

@@ -1,31 +1,66 @@
#! /usr/bin/perl -w
# Display and edit the 'dev' field in tar's snapshots
# Copyright (C) 2007 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# Copyright 2007, 2011, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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.
#
# This program is distributed in the hope that it will be useful,
# the Free Software Foundation; either version 3 of the License, 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# Author: Dustin J. Mitchell <dustin@zmanda.com>
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# tar-snapshot-edit
#
# This script is capable of replacing values in the 'dev' field of an
# incremental backup 'snapshot' file. This is useful when the device
# used to store files in a tar archive changes, without the files
# themselves changing. This may happen when, for example, a device
# driver changes major or minor numbers.
#
# It can also run a check on all the field values found in the
# snapshot file, printing out a detailed message when it finds values
# that would cause an "Unexpected field value in snapshot file",
# "Numerical result out of range", or "Invalid argument" error
# if tar were run using that snapshot file as input. (See the
# comments included in the definition of the check_field_values
# routine for more detailed information regarding these checks.)
#
#
#
# Author: Dustin J. Mitchell <dustin@zmanda.com>
#
# Modified Aug 25, 2011 by Nathan Stratton Treadway <nathanst AT ontko.com>:
# * update Perl syntax to work correctly with more recent versions of
# Perl. (The original code worked with in the v5.8 timeframe but
# not with Perl v5.10.1 and later.)
# * added a "-c" option to check the snapshot file for invalid field values.
# * handle NFS indicator character ("+") in version 0 and 1 files
# * preserve the original header/version line when editing version 1
# or 2 files.
# * tweak output formatting
#
# Modified March 13, 2013 by Nathan Stratton Treadway <nathanst AT ontko.com>:
# * configure field ranges used for -c option based on the system
# architecture (in response to the December 2012 update to GNU tar
# enabling support for systems with signed dev_t values).
# * when printing the list of device ids found in the snapshot file
# (when run in the default mode), print the raw device id values
# instead of the hex-string version in those cases where they
# can't be converted successfully.
use Getopt::Std;
use Config;
my %snapshot_field_ranges; # used in check_field_values function
## reading
@@ -41,14 +76,15 @@ sub read_incr_db ($) {
$file_version = 0;
}
print "file version $file_version\n";
print "\nFile: $filename\n";
print " Detected snapshot file version: $file_version\n\n";
if ($file_version == 0) {
return read_incr_db_0($file, $header_str);
} elsif ($file_version == 1) {
return read_incr_db_1($file);
return read_incr_db_1($file, $header_str);
} elsif ($file_version == 2) {
return read_incr_db_2($file);
return read_incr_db_2($file, $header_str);
} else {
die "Unrecognized snapshot version in header '$header_str'";
}
@@ -62,48 +98,66 @@ sub read_incr_db_0 ($$) {
chop $hdr_timestamp_sec;
my $hdr_timestamp_nsec = ''; # not present in file format 0
my $nfs;
my @dirs;
while (<$file>) {
/^([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
/^(\+?)([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
push @dirs, { dev=>$1,
ino=>$2,
name=>$3 };
if ( $1 eq "+" ) {
$nfs="1";
} else {
$nfs="0";
}
push @dirs, { nfs=>$nfs,
dev=>$2,
ino=>$3,
name=>$4 };
}
close($file);
# file version, timestamp, timestamp, dir list
return [ 0, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
# file version, timestamp, timestamp, dir list, file header line
return [ 0, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs, ""];
}
sub read_incr_db_1 ($) {
sub read_incr_db_1 ($$) {
my $file = shift;
my $header_str = shift;
my $timestamp = <$file>; # "sec nsec"
my ($hdr_timestamp_sec, $hdr_timestamp_nsec) = ($timestamp =~ /([0-9]*) ([0-9]*)/);
my $nfs;
my @dirs;
while (<$file>) {
/^([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
/^(\+?)([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
push @dirs, { timestamp_sec=>$1,
timestamp_nsec=>$2,
dev=>$3,
ino=>$4,
name=>$5 };
if ( $1 eq "+" ) {
$nfs="1";
} else {
$nfs="0";
}
push @dirs, { nfs=>$nfs,
timestamp_sec=>$2,
timestamp_nsec=>$3,
dev=>$4,
ino=>$5,
name=>$6 };
}
close($file);
# file version, timestamp, timestamp, dir list
return [ 1, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
# file version, timestamp, timestamp, dir list, file header line
return [ 1, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs, $header_str ];
}
sub read_incr_db_2 ($) {
sub read_incr_db_2 ($$) {
my $file = shift;
my $header_str = shift;
$/="\0"; # $INPUT_RECORD_SEPARATOR
my $hdr_timestamp_sec = <$file>;
@@ -150,40 +204,257 @@ sub read_incr_db_2 ($) {
close($file);
$/ = "\n"; # reset to normal
# file version, timestamp, timestamp, dir list
return [ 2, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
# file version, timestamp, timestamp, dir list, file header line
return [ 2, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs, $header_str];
}
## display
sub show_device_counts ($$) {
sub show_device_counts ($) {
my $info = shift;
my $filename = shift;
my %devices;
foreach my $dir (@{${@$info}[3]}) {
my $dev = ${%$dir}{'dev'};
foreach my $dir (@{$info->[3]}) {
my $dev = $dir->{'dev'};
$devices{$dev}++;
}
foreach $dev (sort keys %devices) {
printf "$filename: Device 0x%04x occurs $devices{$dev} times.\n", $dev;
my $devstr;
foreach $dev (sort {$a <=> $b} keys %devices) {
$devstr = sprintf ("0x%04x", $dev);
if ( $dev > 0xffffffff or $dev < 0 or hex($devstr) != $dev ) {
# sprintf "%x" will not return a useful value for device ids
# that are negative or which overflow the integer size on this
# instance of Perl, so we convert the hex string back to a
# number, and if it doesn't (numerically) equal the original
# device id value, we know the hex conversion hasn't worked.
#
# Unfortunately, since we're running in "-w" mode, Perl will
# also print a warning message if the hex() routine is called
# on anything larger than "0xffffffff", even in 64-bit Perl
# where such values are actually supported... so we have to
# avoid calling hex() at all if the device id is too large or
# negative. (If it's negative, the conversion to an unsigned
# integer for the "%x" specifier will mean the result will
# always trigger hex()'s warning on a 64-bit machine.)
#
# These situations don't seem to occur very often, so for now
# when they do occur, we simply print the original text value
# that was read from the snapshot file; it will look a bit
# funny next to the values that do print in hex, but that's
# preferable to printing values that aren't actually correct.
$devstr = $dev;
}
printf " Device %s occurs $devices{$dev} times.\n", $devstr;
}
}
## check field values
# initializes the global %snapshot_field_ranges hash, based on the "-a"
# command-line option if given, otherwise based on the "archname" of
# the current system.
#
# Each value in the hash is a two-element array containing the minimum
# and maximum allowed values, respectively, for that field in the snapshot
# file. GNU tar's allowed values for each architecture are determined
# in the incremen.c source file, where the TYPE_MIN and TYPE_MAX
# pre-processor expressions are used to determine the range that can be
# expressed by the C data type used for each field; the values in the
# array defined below should match those calculations. (For tar v1.27
# and later, the valid ranges for a particular tar binary can easily
# be determined using the "tar --show-snapshot-field-ranges" command.)
sub choose_architecture ($) {
my $opt_a = shift;
my $arch = $opt_a ? $opt_a : $Config{'archname'};
# These ranges apply to Linux 2.4/2.6 on iX86 systems, but are used
# by default on unrecognized/unsupported systems, too.
%iX86_linux_field_ranges = (
timestamp_sec => [ -2147483648, 2147483647 ], # min/max of time_t
timestamp_nsec => [ 0, 999999999 ], # 0 to BILLION-1
nfs => [ 0, 1 ],
dev => [ 0, 18446744073709551615 ], # min/max of dev_t
ino => [ 0, 4294967295 ], # min/max of ino_t
);
if ( $arch =~ m/^i[\dxX]86-linux/i ) {
%snapshot_field_ranges = %iX86_linux_field_ranges;
print "Checking snapshot field values using \"iX86-linux\" ranges.\n\n";
} elsif ( $arch =~ m/^x86_64-linux/i ) {
%snapshot_field_ranges = (
timestamp_sec => [ -9223372036854775808, 9223372036854775807 ],
timestamp_nsec => [ 0, 999999999 ],
nfs => [ 0, 1 ],
dev => [ 0, 18446744073709551615 ],
ino => [ 0, 18446744073709551615 ],
);
print "Checking snapshot field values using \"x86_64-linux\" ranges.\n\n";
} elsif ( $arch =~ m/^IA64.ARCHREV_0/i ) {
# HP/UX running on Itanium/ia64 architecture
%snapshot_field_ranges = (
timestamp_sec => [ -2147483648, 2147483647 ],
timestamp_nsec => [ 0, 999999999 ],
nfs => [ 0, 1 ],
dev => [ -2147483648, 2147483647 ],
ino => [ 0, 4294967295 ],
);
print "Checking snapshot field values using \"IA64.ARCHREV_0\" (HP/UX) ranges.\n\n";
} else {
%snapshot_field_ranges = %iX86_linux_field_ranges;
print "Unrecognized architecture \"$arch\"; defaulting to \"iX86-linux\".\n";
print "(Use -a option to override.)\n" unless $opt_a;
print "\n";
}
if ( ref(1) ne "" ) {
print "(\"bignum\" mode is in effect; skipping 64-bit-integer check.)\n\n"
} else {
# find the largest max value in the current set of ranges
my $maxmax = 0;
for $v (values %snapshot_field_ranges ) {
$maxmax = $v->[1] if ($v->[1] > $maxmax);
}
# "~0" translates into a platform-native integer with all bits turned
# on -- that is, the largest value that can be represented as
# an integer. We print a warning if our $maxmax value is greater
# than that largest integer, since in that case Perl will switch
# to using floats for those large max values. The wording of
# the message assumes that the only way this situation can exist
# is that the platform uses 32-bit integers but some of the
# snapshot-file fields have 64-bit values.
if ( ~0 < $maxmax ) {
print <<EOF
Note: this version of Perl uses 32-bit integers, which means that it
will switch to using floating-point numbers when checking the ranges
for 64-bit snapshot-file fields. This normally will work fine, but
might fail to detect cases where the value in the input field value is
only slightly out of range. (For example, a "9223372036854775808"
might not be recognized as being larger than 9223372036854775807.)
If you suspect you are experiencing this problem, you can try running
the program using the "-Mbignum" option, as in
\$ perl $0 -Mbignum -c [FILES]
(but doing so will make the program run *much* slower).
EOF
}
}
}
# returns a warning message if $field_value isn't a valid string
# representation of an integer, or if the resulting integer is out of range
# defined by the two-element array retrieved using up the $field_name key in
# the global %snapshot_field_ranges hash.
sub validate_integer_field ($$) {
my $field_value = shift;
my $field_name = shift;
my ($min, $max) = @{$snapshot_field_ranges{$field_name}};
my $msg = "";
if ( not $field_value =~ /^-?\d+$/ ) {
$msg = " $field_name value contains invalid characters: \"$field_value\"\n";
} else {
if ( $field_value < $min ) {
$msg = " $field_name value too low: \"$field_value\" < $min \n";
} elsif ( $field_value > $max ) {
$msg = " $field_name value too high: \"$field_value\" > $max \n";
}
}
return $msg;
}
# This routine loops through each directory entry in the $info data
# structure and prints a warning message if tar would abort with an
# "Unexpected field value in snapshot file", "Numerical result out of
# range", or "Invalid argument" error upon reading this snapshot file.
#
# (Note that the "Unexpected field value in snapshot file" error message
# was introduced along with the change to snapshot file format "2",
# starting with tar v1.16 [or, more precisely, v1.15.91], while the
# other two were introduced in v1.27.)
#
# The checks here are intended to match those found in the incremen.c
# source file. See the choose_architecture() function (above) for more
# information on how to configure the range of values considered valid
# by this script.
#
# (Note: the checks here are taken from the code that processes
# version 2 snapshot files, but to keep things simple we apply those
# same checks to files having earlier versions -- but only for
# the fields that actually exist in those input files.)
sub check_field_values ($) {
my $info = shift;
my $msg;
my $error_found = 0;
print " Checking field values in snapshot file...\n";
$snapver = $info->[0];
$msg = "";
$msg .= validate_integer_field($info->[1], 'timestamp_sec');
if ($snapver >= 1) {
$msg .= validate_integer_field($info->[2], 'timestamp_nsec');
}
if ( $msg ne "" ) {
$error_found = 1;
print "\n shapshot file header:\n";
print $msg;
}
foreach my $dir (@{$info->[3]}) {
$msg = "";
$msg .= validate_integer_field($dir->{'nfs'}, 'nfs');
if ($snapver >= 1) {
$msg .= validate_integer_field($dir->{'timestamp_sec'}, 'timestamp_sec');
$msg .= validate_integer_field($dir->{'timestamp_nsec'}, 'timestamp_nsec');
}
$msg .= validate_integer_field($dir->{'dev'}, 'dev');
$msg .= validate_integer_field($dir->{'ino'}, 'ino');
if ( $msg ne "" ) {
$error_found = 1;
print "\n directory: $dir->{'name'}\n";
print $msg;
}
}
print "\n Snapshot field value check complete" ,
$error_found ? "" : ", no errors found" ,
".\n";
}
## editing
sub replace_device_number ($@) {
my $info = shift(@_);
my @repl = @_;
foreach my $dir (@{${@$info}[3]}) {
foreach $x (@repl) {
if (${%$dir}{'dev'} eq $$x[0]) {
${%$dir}{'dev'} = $$x[1];
last;
}
my $count = 0;
foreach my $dir (@{$info->[3]}) {
foreach $x (@repl) {
if ($dir->{'dev'} eq $$x[0]) {
$dir->{'dev'} = $$x[1];
$count++;
last;
}
}
}
print " Updated $count records.\n"
}
## writing
@@ -215,10 +486,13 @@ sub write_incr_db_0 ($$) {
my $timestamp_sec = $info->[1];
print $file "$timestamp_sec\n";
foreach my $dir (@{${@$info}[3]}) {
print $file "${%$dir}{'dev'} ";
print $file "${%$dir}{'ino'} ";
print $file "${%$dir}{'name'}\n";
foreach my $dir (@{$info->[3]}) {
if ($dir->{'nfs'}) {
print $file '+'
}
print $file "$dir->{'dev'} ";
print $file "$dir->{'ino'} ";
print $file "$dir->{'name'}\n";
}
}
@@ -227,18 +501,21 @@ sub write_incr_db_1 ($$) {
my $info = shift;
my $file = shift;
print $file "GNU tar-1.15-1\n";
print $file $info->[4];
my $timestamp_sec = $info->[1];
my $timestamp_nsec = $info->[2];
print $file "$timestamp_sec $timestamp_nsec\n";
foreach my $dir (@{${@$info}[3]}) {
print $file "${%$dir}{'timestamp_sec'} ";
print $file "${%$dir}{'timestamp_nsec'} ";
print $file "${%$dir}{'dev'} ";
print $file "${%$dir}{'ino'} ";
print $file "${%$dir}{'name'}\n";
foreach my $dir (@{$info->[3]}) {
if ($dir->{'nfs'}) {
print $file '+'
}
print $file "$dir->{'timestamp_sec'} ";
print $file "$dir->{'timestamp_nsec'} ";
print $file "$dir->{'dev'} ";
print $file "$dir->{'ino'} ";
print $file "$dir->{'name'}\n";
}
}
@@ -247,21 +524,21 @@ sub write_incr_db_2 ($$) {
my $info = shift;
my $file = shift;
print $file "GNU tar-1.16-2\n";
print $file $info->[4];
my $timestamp_sec = $info->[1];
my $timestamp_nsec = $info->[2];
print $file $timestamp_sec . "\0";
print $file $timestamp_nsec . "\0";
foreach my $dir (@{${@$info}[3]}) {
print $file ${%$dir}{'nfs'} . "\0";
print $file ${%$dir}{'timestamp_sec'} . "\0";
print $file ${%$dir}{'timestamp_nsec'} . "\0";
print $file ${%$dir}{'dev'} . "\0";
print $file ${%$dir}{'ino'} . "\0";
print $file ${%$dir}{'name'} . "\0";
foreach my $dirent (@{${%$dir}{'dirents'}}) {
foreach my $dir (@{$info->[3]}) {
print $file $dir->{'nfs'} . "\0";
print $file $dir->{'timestamp_sec'} . "\0";
print $file $dir->{'timestamp_nsec'} . "\0";
print $file $dir->{'dev'} . "\0";
print $file $dir->{'ino'} . "\0";
print $file $dir->{'name'} . "\0";
foreach my $dirent (@{$dir->{'dirents'}}) {
print $file $dirent . "\0";
}
print $file "\0";
@@ -271,9 +548,10 @@ sub write_incr_db_2 ($$) {
## main
sub main {
our ($opt_b, $opt_r, $opt_h);
getopts('br:h');
HELP_MESSAGE() if ($opt_h || $#ARGV == -1 || ($opt_b && !$opt_r));
our ($opt_b, $opt_r, $opt_h, $opt_c, $opt_a);
getopts('br:hca:');
HELP_MESSAGE() if ($opt_h || $#ARGV == -1 || ($opt_b && !$opt_r) ||
($opt_a && !$opt_c) || ($opt_r && $opt_c) );
my @repl;
if ($opt_r) {
@@ -283,31 +561,61 @@ sub main {
}
}
choose_architecture($opt_a) if ($opt_c);
foreach my $snapfile (@ARGV) {
my $info = read_incr_db($snapfile);
if ($opt_r ) {
if ($opt_r) {
if ($opt_b) {
rename($snapfile, $snapfile . "~") || die "Could not rename '$snapfile' to backup";
}
replace_device_number($info, @repl);
write_incr_db($info, $snapfile);
} elsif ($opt_c) {
check_field_values($info);
} else {
show_device_counts($info, $snapfile);
show_device_counts($info);
}
}
}
sub HELP_MESSAGE {
print "Usage: tar-snapshot-edit.pl [-r 'DEV1-DEV2[,DEV3-DEV4...]' [-b]] SNAPFILE [SNAPFILE [..]]\n";
print "\n";
print " Without -r, summarize the 'device' values in each SNAPFILE.\n";
print "\n";
print " With -r, replace occurrences of DEV1 with DEV2 in each SNAPFILE.\n";
print " DEV1 and DEV2 may be specified in hex (e.g., 0xfe01), decimal (e.g.,\n";
print " 65025), or MAJ:MIN (e.g., 254:1). To replace multiple occurrences,\n";
print " separate them with commas. If -b is also specified, backup\n";
print " files (ending with '~') will be created.\n";
print <<EOF;
Usage:
tar-snapshot-edit SNAPFILE [SNAPFILE [...]]
tar-snapshot-edit -r 'DEV1-DEV2[,DEV3-DEV4...]' [-b] SNAPFILE [SNAPFILE [...]]
tar-snapshot-edit -c [-aARCH] SNAPFILE [SNAPFILE [...]]
With no options specified: print a summary of the 'device' values
found in each SNAPFILE.
With -r: replace occurrences of DEV1 with DEV2 in each SNAPFILE.
DEV1 and DEV2 may be specified in hex (e.g., 0xfe01), decimal (e.g.,
65025), or MAJ:MIN (e.g., 254:1). To replace multiple occurrences,
separate them with commas. If -b is also specified, backup files
(ending with '~') will be created.
With -c: Check the field values in each SNAPFILE and print warning
messages if any invalid values are found. (An invalid value is one
that would cause \"tar\" to abort with an error message such as
Unexpected field value in snapshot file
Numerical result out of range
or
Invalid argument
as it processed the snapshot file.)
Normally the program automatically chooses the valid ranges for
the fields based on the current system's architecture, but the
-a option can be used to override the selection, e.g. in order
to validate a snapshot file generated on a some other system.
(Currently only three architectures are supported, "iX86-linux",
"x86_64-linux", and "IA64.ARCHREV_0" [HP/UX running on Itanium/ia64],
and if the current system isn't recognized, then the iX86-linux
values are used by default.)
EOF
exit 1;
}

View File

@@ -3,6 +3,23 @@
# concatenates a GNU tar multi-volume archive into a single tar archive.
# Author: Bruno Haible <bruno@clisp.org>, Sergey Poznyakoff <gray@gnu.org.ua>
# Copyright 2004-2005, 2010, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
# dump_type FILE [N]
# Print type character from block N (default 0) of tar archive FILE
dump_type() {

View File

@@ -1,23 +1,24 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
Copyright 2006-2007, 2010, 2013-2014 Free Software Foundation, Inc.
Written by Sergey Poznyakoff
This file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by Sergey Poznyakoff */
#include <stdlib.h>
#include <stdint.h>
@@ -164,7 +165,7 @@ get_var (FILE *fp, char **name, char **value)
p += 11;
q = strchr (p, '=');
if (!q)
die (1, "malformed header: expected `=' not found");
die (1, "malformed header: expected '=' not found");
*q++ = 0;
q[strlen (q) - 1] = 0;
*name = p;
@@ -194,7 +195,7 @@ read_xheader (char *name)
printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
if (expect && strcmp (kw, expect))
die (1, "bad keyword sequence: expected `%s' but found `%s'",
die (1, "bad keyword sequence: expected '%s' but found '%s'",
expect, kw);
expect = NULL;
if (strcmp (kw, "name") == 0)
@@ -235,13 +236,13 @@ read_xheader (char *name)
{
sparse_map[i].offset = string_to_off (val, &val);
if (*val != ',')
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
die (1, "bad GNU.sparse.map: expected ',' but found '%c'",
*val);
sparse_map[i].numbytes = string_to_off (val+1, &val);
if (*val != ',')
{
if (!(*val == 0 && i == sparse_map_size-1))
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
die (1, "bad GNU.sparse.map: expected ',' but found '%c'",
*val);
}
else
@@ -252,7 +253,7 @@ read_xheader (char *name)
}
}
if (expect)
die (1, "bad keyword sequence: expected `%s' not found", expect);
die (1, "bad keyword sequence: expected '%s' not found", expect);
if (version_major == 0 && sparse_map_size == 0)
die (1, "size of the sparse map unknown");
if (i != sparse_map_size)
@@ -449,7 +450,7 @@ main (int argc, char **argv)
die (1, "cannot open file %s (%d)", outname, errno);
if (verbose)
printf ("Expanding file `%s' to `%s'\n", inname, outname);
printf ("Expanding file '%s' to '%s'\n", inname, outname);
if (dry_run)
{

View File

@@ -1,26 +1,26 @@
# Makefile for GNU tar sources.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007, 2009 Free Software Foundation, Inc.
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2009, 2013-2014 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 file is part of GNU tar.
## 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.
# 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 of the License, or
# (at your option) any later version.
## 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.
# 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 this program. If not, see <http://www.gnu.org/licenses/>.
bin_PROGRAMS = tar
noinst_HEADERS = arith.h common.h tar.h
noinst_HEADERS = arith.h common.h tar.h xattrs.h
tar_SOURCES = \
buffer.c\
checkpoint.c\
@@ -28,6 +28,7 @@ tar_SOURCES = \
create.c\
delete.c\
exit.c\
exclist.c\
extract.c\
xheader.c\
incremen.c\
@@ -42,10 +43,16 @@ tar_SOURCES = \
unlink.c\
update.c\
utf8.c\
warning.c
warning.c\
xattrs.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)
if TAR_LIB_ATTR
tar_LDADD += -lattr
endif

View File

@@ -1,19 +1,20 @@
/* Long integers, for GNU tar.
Copyright 1999, 2007 Free Software Foundation, Inc.
Copyright 1999, 2007, 2013-2014 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
This file is part of GNU tar.
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.
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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 this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Handle large integers for calculating big tape lengths and the
like. In practice, double precision does for now. On the vast

View File

@@ -1,24 +1,24 @@
/* Buffer management for tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
Foundation, Inc.
Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2013-2014 Free
Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
This file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by John Gilmore, on 1985-08-25. */
#include <system.h>
#include <system-ioctl.h>
@@ -41,7 +41,7 @@
static tarlong prev_written; /* bytes written on previous volumes */
static tarlong bytes_written; /* bytes written on this volume */
static void *record_buffer[2]; /* allocated memory */
union block *record_buffer_aligned[2];
static union block *record_buffer_aligned[2];
static int record_index;
/* FIXME: The following variables should ideally be static to this
@@ -83,8 +83,8 @@ extern bool time_to_start_writing;
bool write_archive_to_stdout;
void (*flush_write_ptr) (size_t);
void (*flush_read_ptr) (void);
static void (*flush_write_ptr) (size_t);
static void (*flush_read_ptr) (void);
char *volume_label;
@@ -103,7 +103,7 @@ bool write_archive_to_stdout;
/* Multi-volume tracking support */
/* When creating a multi-volume archive, each `bufmap' represents
/* When creating a multi-volume archive, each 'bufmap' represents
a member stored (perhaps partly) in the current record buffer.
After flushing the record to the output media, all bufmaps that
represent fully written members are removed from the list, then
@@ -193,7 +193,7 @@ bufmap_reset (struct bufmap *map, ssize_t fixup)
static struct tar_stat_info dummy;
void
buffer_write_global_xheader ()
buffer_write_global_xheader (void)
{
xheader_write_global (&dummy.xhdr);
}
@@ -205,7 +205,7 @@ mv_begin_read (struct tar_stat_info *st)
}
void
mv_end ()
mv_end (void)
{
if (multi_volume_option)
bufmap_free (NULL);
@@ -230,10 +230,10 @@ clear_read_error_count (void)
/* Time-related functions */
double duration;
static double duration;
void
set_start_time ()
set_start_time (void)
{
gettime (&start_time);
volume_start_time = start_time;
@@ -247,22 +247,23 @@ set_volume_start_time (void)
last_stat_time = volume_start_time;
}
void
compute_duration ()
double
compute_duration (void)
{
struct timespec now;
gettime (&now);
duration += ((now.tv_sec - last_stat_time.tv_sec)
+ (now.tv_nsec - last_stat_time.tv_nsec) / 1e9);
gettime (&last_stat_time);
return duration;
}
/* Compression detection */
enum compress_type {
ct_tar, /* Plain tar file */
ct_none, /* Unknown compression type */
ct_tar, /* Plain tar file */
ct_compress,
ct_gzip,
ct_bzip2,
@@ -272,31 +273,102 @@ enum compress_type {
ct_xz
};
static enum compress_type archive_compression_type = ct_none;
struct zip_magic
{
enum compress_type type;
size_t length;
char const *magic;
};
struct zip_program
{
enum compress_type type;
char const *program;
char const *option;
};
static struct zip_magic const magic[] = {
{ ct_tar },
{ ct_none, },
{ ct_compress, 2, "\037\235", COMPRESS_PROGRAM, "-Z" },
{ ct_gzip, 2, "\037\213", GZIP_PROGRAM, "-z" },
{ ct_bzip2, 3, "BZh", BZIP2_PROGRAM, "-j" },
{ ct_lzip, 4, "LZIP", LZIP_PROGRAM, "--lzip" },
{ ct_lzma, 6, "\xFFLZMA", LZMA_PROGRAM, "--lzma" },
{ ct_lzop, 4, "\211LZO", LZOP_PROGRAM, "--lzop" },
{ ct_xz, 6, "\xFD" "7zXZ", XZ_PROGRAM, "-J" },
{ ct_none, 0, 0 },
{ ct_tar, 0, 0 },
{ ct_compress, 2, "\037\235" },
{ ct_gzip, 2, "\037\213" },
{ ct_bzip2, 3, "BZh" },
{ ct_lzip, 4, "LZIP" },
{ ct_lzma, 6, "\xFFLZMA" },
{ ct_lzop, 4, "\211LZO" },
{ ct_xz, 6, "\xFD" "7zXZ" },
};
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
#define compress_option(t) magic[t].option
#define compress_program(t) magic[t].program
static struct zip_program zip_program[] = {
{ ct_compress, COMPRESS_PROGRAM, "-Z" },
{ ct_compress, GZIP_PROGRAM, "-z" },
{ ct_gzip, GZIP_PROGRAM, "-z" },
{ ct_bzip2, BZIP2_PROGRAM, "-j" },
{ ct_bzip2, "lbzip2", "-j" },
{ ct_lzip, LZIP_PROGRAM, "--lzip" },
{ ct_lzma, LZMA_PROGRAM, "--lzma" },
{ ct_lzma, XZ_PROGRAM, "-J" },
{ ct_lzop, LZOP_PROGRAM, "--lzop" },
{ ct_xz, XZ_PROGRAM, "-J" },
{ ct_none }
};
static struct zip_program const *
find_zip_program (enum compress_type type, int *pstate)
{
int i;
for (i = *pstate; zip_program[i].type != ct_none; i++)
{
if (zip_program[i].type == type)
{
*pstate = i + 1;
return zip_program + i;
}
}
*pstate = i;
return NULL;
}
const char *
first_decompress_program (int *pstate)
{
struct zip_program const *zp;
if (use_compress_program_option)
return use_compress_program_option;
if (archive_compression_type == ct_none)
return NULL;
*pstate = 0;
zp = find_zip_program (archive_compression_type, pstate);
return zp ? zp->program : NULL;
}
const char *
next_decompress_program (int *pstate)
{
struct zip_program const *zp;
if (use_compress_program_option)
return NULL;
zp = find_zip_program (archive_compression_type, pstate);
return zp ? zp->program : NULL;
}
static const char *
compress_option (enum compress_type type)
{
struct zip_program const *zp;
int i = 0;
zp = find_zip_program (type, &i);
return zp ? zp->option : NULL;
}
/* Check if the file ARCHIVE is a compressed archive. */
static enum compress_type
@@ -395,7 +467,7 @@ open_compressed_archive (void)
break;
default:
use_compress_program_option = compress_program (type);
archive_compression_type = type;
break;
}
}
@@ -417,64 +489,98 @@ open_compressed_archive (void)
return archive;
}
static void
static int
print_stats (FILE *fp, const char *text, tarlong numbytes)
{
char bytes[sizeof (tarlong) * CHAR_BIT];
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
int n = 0;
int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
sprintf (bytes, TARLONG_FORMAT, numbytes);
fprintf (fp, "%s: %s (%s, %s/s)\n",
text, bytes,
human_readable (numbytes, abbr, human_opts, 1, 1),
(0 < duration && numbytes / duration < (uintmax_t) -1
? human_readable (numbytes / duration, rate, human_opts, 1, 1)
: "?"));
if (text && text[0])
n += fprintf (fp, "%s: ", gettext (text));
return n + fprintf (fp, TARLONG_FORMAT " (%s, %s/s)",
numbytes,
human_readable (numbytes, abbr, human_opts, 1, 1),
(0 < duration && numbytes / duration < (uintmax_t) -1
? human_readable (numbytes / duration, rate, human_opts, 1, 1)
: "?"));
}
void
print_total_stats ()
/* Format totals to file FP. FORMATS is an array of strings to output
before each data item (bytes read, written, deleted, in that order).
EOR is a delimiter to output after each item (used only if deleting
from the archive), EOL is a delimiter to add at the end of the output
line. */
int
format_total_stats (FILE *fp, const char **formats, int eor, int eol)
{
int n;
switch (subcommand_option)
{
case CREATE_SUBCOMMAND:
case CAT_SUBCOMMAND:
case UPDATE_SUBCOMMAND:
case APPEND_SUBCOMMAND:
/* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
print_stats (stderr, _("Total bytes written"),
prev_written + bytes_written);
n = print_stats (fp, formats[TF_WRITE],
prev_written + bytes_written);
break;
case DELETE_SUBCOMMAND:
{
char buf[UINTMAX_STRSIZE_BOUND];
print_stats (stderr, _("Total bytes read"),
records_read * record_size);
print_stats (stderr, _("Total bytes written"),
prev_written + bytes_written);
fprintf (stderr, _("Total bytes deleted: %s\n"),
STRINGIFY_BIGINT ((records_read - records_skipped)
* record_size
- (prev_written + bytes_written), buf));
n = print_stats (fp, formats[TF_READ],
records_read * record_size);
fputc (eor, fp);
n++;
n += print_stats (fp, formats[TF_WRITE],
prev_written + bytes_written);
fputc (eor, fp);
n++;
if (formats[TF_DELETED] && formats[TF_DELETED][0])
n += fprintf (fp, "%s: ", gettext (formats[TF_DELETED]));
n += fprintf (fp, "%s",
STRINGIFY_BIGINT ((records_read - records_skipped)
* record_size
- (prev_written + bytes_written), buf));
}
break;
case EXTRACT_SUBCOMMAND:
case LIST_SUBCOMMAND:
case DIFF_SUBCOMMAND:
print_stats (stderr, _("Total bytes read"),
records_read * record_size);
n = print_stats (fp, _(formats[TF_READ]),
records_read * record_size);
break;
default:
abort ();
}
if (eol)
{
fputc (eol, fp);
n++;
}
return n;
}
const char *default_total_format[] = {
N_("Total bytes read"),
/* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
N_("Total bytes written"),
N_("Total bytes deleted")
};
void
print_total_stats (void)
{
format_total_stats (stderr, default_total_format, '\n', '\n');
}
/* Compute and return the block ordinal at current_block. */
@@ -562,6 +668,22 @@ init_buffer (void)
record_end = record_start + blocking_factor;
}
static void
check_tty (enum access_mode mode)
{
/* Refuse to read archive from and write it to a tty. */
if (strcmp (archive_name_array[0], "-") == 0
&& isatty (mode == ACCESS_READ ? STDIN_FILENO : STDOUT_FILENO))
{
FATAL_ERROR ((0, 0,
mode == ACCESS_READ
? _("Refusing to read archive contents from terminal "
"(missing -f option?)")
: _("Refusing to write archive contents to terminal "
"(missing -f option?)")));
}
}
/* Open an archive file. The argument specifies whether we are
reading or writing, or both. */
static void
@@ -582,6 +704,7 @@ _open_archive (enum access_mode wanted_access)
/* When updating the archive, we start with reading. */
access_mode = wanted_access == ACCESS_UPDATE ? ACCESS_READ : wanted_access;
check_tty (access_mode);
read_full_records = read_full_records_option;
@@ -625,7 +748,6 @@ _open_archive (enum access_mode wanted_access)
enum compress_type type;
archive = STDIN_FILENO;
type = check_compressed_archive (&shortfile);
if (type != ct_tar && type != ct_none)
FATAL_ERROR ((0, 0,
@@ -651,9 +773,6 @@ _open_archive (enum access_mode wanted_access)
break;
}
}
else if (verify_option)
archive = rmtopen (archive_name_array[0], O_RDWR | O_CREAT | O_BINARY,
MODE_RW, rsh_command_option);
else
switch (wanted_access)
{
@@ -669,8 +788,12 @@ _open_archive (enum access_mode wanted_access)
maybe_backup_file (archive_name_array[0], 1);
backed_up_flag = 1;
}
archive = rmtcreat (archive_name_array[0], MODE_RW,
rsh_command_option);
if (verify_option)
archive = rmtopen (archive_name_array[0], O_RDWR | O_CREAT | O_BINARY,
MODE_RW, rsh_command_option);
else
archive = rmtcreat (archive_name_array[0], MODE_RW,
rsh_command_option);
break;
case ACCESS_UPDATE:
@@ -812,16 +935,16 @@ short_read (size_t status)
left = record_size - status;
if (left && left % BLOCKSIZE == 0
&& verbose_option
&& (warning_option & WARN_RECORD_SIZE)
&& record_start_block == 0 && status != 0
&& archive_is_dev ())
{
unsigned long rsize = status / BLOCKSIZE;
WARN ((0, 0,
ngettext ("Record size = %lu block",
"Record size = %lu blocks",
rsize),
rsize));
ngettext ("Record size = %lu block",
"Record size = %lu blocks",
rsize),
rsize));
}
while (left % BLOCKSIZE != 0
@@ -1857,13 +1980,13 @@ gnu_flush_write (size_t buffer_level)
}
void
flush_read ()
flush_read (void)
{
flush_read_ptr ();
}
void
flush_write ()
flush_write (void)
{
flush_write_ptr (record_size);
}

View File

@@ -1,22 +1,28 @@
/* Checkpoint management for tar.
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright 2007, 2013-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"
#include "wordsplit.h"
#include <sys/ioctl.h>
#include <termios.h>
#include "fprintftime.h"
enum checkpoint_opcode
{
@@ -25,7 +31,8 @@ enum checkpoint_opcode
cop_echo,
cop_ttyout,
cop_sleep,
cop_exec
cop_exec,
cop_totals
};
struct checkpoint_action
@@ -108,12 +115,14 @@ checkpoint_compile_action (const char *str)
act = alloc_action (cop_sleep);
act->v.time = n;
}
else if (strcmp (str, "totals") == 0)
alloc_action (cop_totals);
else
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
}
void
checkpoint_finish_compile ()
checkpoint_finish_compile (void)
{
if (checkpoint_option)
{
@@ -126,68 +135,211 @@ checkpoint_finish_compile ()
checkpoint_option = DEFAULT_CHECKPOINT;
}
static char *
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
static const char *checkpoint_total_format[] = {
"R",
"W",
"D"
};
static long
getwidth (FILE *fp)
{
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 */
char const *columns;
/* Fix the initial length guess */
for (ip = input; (ip = strchr (ip, '%')) != NULL; )
#ifdef TIOCGWINSZ
struct winsize ws;
if (ioctl (fileno (fp), TIOCGWINSZ, &ws) == 0 && 0 < ws.ws_col)
return ws.ws_col;
#endif
columns = getenv ("COLUMNS");
if (columns)
{
switch (ip[1])
{
case 'u':
outlen += cpslen - 2;
break;
case 's':
outlen += opstrlen - 2;
}
ip++;
long int col = strtol (columns, NULL, 10);
if (0 < col)
return col;
}
output = xmalloc (outlen + 1);
for (ip = input, op = output; *ip; )
return 80;
}
static char *
getarg (const char *input, const char ** endp, char **argbuf, size_t *arglen)
{
if (input[0] == '{')
{
char *p = strchr (input + 1, '}');
if (p)
{
size_t n = p - input;
if (n > *arglen)
{
*arglen = n;
*argbuf = xrealloc (*argbuf, *arglen);
}
n--;
memcpy (*argbuf, input + 1, n);
(*argbuf)[n] = 0;
*endp = p + 1;
return *argbuf;
}
}
*endp = input;
return NULL;
}
static int tty_cleanup;
static const char *def_format =
"%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r";
static int
format_checkpoint_string (FILE *fp, size_t len,
const char *input, bool do_write,
unsigned cpn)
{
const char *opstr = do_write ? gettext ("write") : gettext ("read");
char uintbuf[UINTMAX_STRSIZE_BOUND];
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
const char *ip;
static char *argbuf = NULL;
static size_t arglen = 0;
char *arg = NULL;
if (!input)
{
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" */
input = 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" */
input = gettext ("Read checkpoint %u");
}
for (ip = input; *ip; ip++)
{
if (*ip == '%')
{
switch (*++ip)
if (*++ip == '{')
{
arg = getarg (ip, &ip, &argbuf, &arglen);
if (!arg)
{
fputc ('%', fp);
fputc (*ip, fp);
len += 2;
continue;
}
}
switch (*ip)
{
case 'c':
len += format_checkpoint_string (fp, len, def_format, do_write,
cpn);
break;
case 'u':
op = stpcpy (op, cps);
fputs (cps, fp);
len += strlen (cps);
break;
case 's':
op = stpcpy (op, opstr);
fputs (opstr, fp);
len += strlen (opstr);
break;
case 'd':
len += fprintf (fp, "%.0f", compute_duration ());
break;
case 'T':
{
const char **fmt = checkpoint_total_format, *fmtbuf[3];
struct wordsplit ws;
compute_duration ();
if (arg)
{
ws.ws_delim = ",";
if (wordsplit (arg, &ws, WRDSF_NOVAR | WRDSF_NOCMD |
WRDSF_QUOTE | WRDSF_DELIM))
ERROR ((0, 0, _("cannot split string '%s': %s"),
arg, wordsplit_strerror (&ws)));
else
{
int i;
for (i = 0; i < ws.ws_wordc; i++)
fmtbuf[i] = ws.ws_wordv[i];
for (; i < 3; i++)
fmtbuf[i] = NULL;
fmt = fmtbuf;
}
}
len += format_total_stats (fp, fmt, ',', 0);
if (arg)
wordsplit_free (&ws);
}
break;
case 't':
{
struct timeval tv;
struct tm *tm;
const char *fmt = arg ? arg : "%c";
gettimeofday (&tv, NULL);
tm = localtime (&tv.tv_sec);
len += fprintftime (fp, fmt, tm, 0, tv.tv_usec * 1000);
}
break;
case '*':
{
long w = arg ? strtol (arg, NULL, 10) : getwidth (fp);
for (; w > len; len++)
fputc (' ', fp);
}
break;
default:
*op++ = '%';
*op++ = *ip;
fputc ('%', fp);
fputc (*ip, fp);
len += 2;
break;
}
ip++;
arg = NULL;
}
else
*op++ = *ip++;
{
fputc (*ip, fp);
if (*ip == '\r')
{
len = 0;
tty_cleanup = 1;
}
else
len++;
}
}
*op = 0;
return output;
fflush (fp);
return len;
}
static FILE *tty = NULL;
static void
run_checkpoint_actions (bool do_write)
{
struct checkpoint_action *p;
FILE *tty = NULL;
for (p = checkpoint_action; p; p = p->next)
{
@@ -210,26 +362,10 @@ run_checkpoint_actions (bool do_write)
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);
int n = fprintf (stderr, "%s: ", program_name);
format_checkpoint_string (stderr, n, p->v.command, do_write,
checkpoint);
fputc ('\n', stderr);
}
break;
@@ -237,13 +373,8 @@ run_checkpoint_actions (bool do_write)
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);
}
format_checkpoint_string (tty, 0, p->v.command, do_write,
checkpoint);
break;
case cop_sleep:
@@ -255,10 +386,37 @@ run_checkpoint_actions (bool do_write)
archive_name_cursor[0],
checkpoint);
break;
case cop_totals:
compute_duration ();
print_total_stats ();
}
}
}
void
checkpoint_flush_actions (void)
{
struct checkpoint_action *p;
for (p = checkpoint_action; p; p = p->next)
{
switch (p->opcode)
{
case cop_ttyout:
if (tty && tty_cleanup)
{
long w = getwidth (tty);
while (w--)
fputc (' ', tty);
fputc ('\r', tty);
fflush (tty);
}
break;
default:
/* nothing */;
}
}
if (tty)
fclose (tty);
}
void
@@ -267,3 +425,14 @@ checkpoint_run (bool do_write)
if (checkpoint_option && !(++checkpoint % checkpoint_option))
run_checkpoint_actions (do_write);
}
void
checkpoint_finish (void)
{
if (checkpoint_option)
{
checkpoint_flush_actions ();
if (tty)
fclose (tty);
}
}

View File

@@ -1,22 +1,22 @@
/* Common declarations for the tar program.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
Inc.
Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2012-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
/* Declare the GNU tar archive format. */
#include "tar.h"
@@ -70,6 +70,11 @@
#define LG_8 3
#define LG_64 6
#define LG_256 8
_GL_INLINE_HEADER_BEGIN
#ifndef COMMON_INLINE
# define COMMON_INLINE _GL_INLINE
#endif
/* Information gleaned from the command line. */
@@ -138,9 +143,6 @@ 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;
/* Patterns that match file names to be excluded. */
GLOBAL struct exclude *excluded;
@@ -158,7 +160,8 @@ enum exclusion_tag_type
};
/* Specified value to be put into tar file in place of stat () results, or
just -1 if such an override should not take place. */
just null and -1 if such an override should not take place. */
GLOBAL char const *group_name_option;
GLOBAL gid_t group_option;
GLOBAL bool ignore_failed_read_option;
@@ -182,10 +185,13 @@ enum old_files
OVERWRITE_OLD_FILES, /* --overwrite */
UNLINK_FIRST_OLD_FILES, /* --unlink-first */
KEEP_OLD_FILES, /* --keep-old-files */
SKIP_OLD_FILES, /* --skip-old-files */
KEEP_NEWER_FILES /* --keep-newer-files */
};
GLOBAL enum old_files old_files_option;
GLOBAL bool keep_directory_symlink_option;
/* Specified file name for incremental list. */
GLOBAL const char *listed_incremental_option;
/* Incremental dump level */
@@ -229,8 +235,13 @@ GLOBAL bool numeric_owner_option;
GLOBAL bool one_file_system_option;
/* Create a top-level directory for extracting based on the archive name. */
GLOBAL bool one_top_level_option;
GLOBAL char *one_top_level_dir;
/* Specified value to be put into tar file in place of stat () results, or
just -1 if such an override should not take place. */
just null and -1 if such an override should not take place. */
GLOBAL char const *owner_name_option;
GLOBAL uid_t owner_option;
GLOBAL bool recursive_unlink_option;
@@ -239,9 +250,6 @@ GLOBAL bool read_full_records_option;
GLOBAL bool remove_files_option;
/* Specified rmt command. */
GLOBAL const char *rmt_command_option;
/* Specified remote shell command. */
GLOBAL const char *rsh_command_option;
@@ -253,6 +261,15 @@ GLOBAL int same_owner_option;
/* If positive, preserve permissions when extracting. */
GLOBAL int same_permissions_option;
/* If positive, save the SELinux context. */
GLOBAL int selinux_context_option;
/* If positive, save the ACLs. */
GLOBAL int acls_option;
/* If positive, save the user and root xattrs. */
GLOBAL int xattrs_option;
/* When set, strip the given number of file name components from the file name
before extracting */
GLOBAL size_t strip_name_components;
@@ -313,11 +330,10 @@ GLOBAL struct timespec last_stat_time; /* when the statistics was last
GLOBAL struct tar_stat_info current_stat_info;
/* List of tape drive names, number of such tape drives, allocated number,
/* List of tape drive names, number of such tape drives,
and current cursor in list. */
GLOBAL const char **archive_name_array;
GLOBAL size_t archive_names;
GLOBAL size_t allocated_archive_names;
GLOBAL const char **archive_name_cursor;
/* Output index file name. */
@@ -370,6 +386,8 @@ GLOBAL dev_t root_device;
/* Unquote filenames */
GLOBAL bool unquote_option;
GLOBAL int savedir_sort_order;
/* Show file or archive names after transformation.
In particular, when creating archive in verbose mode, list member names
as stored in the archive */
@@ -415,7 +433,7 @@ size_t available_space_after (union block *pointer);
off_t current_block_ordinal (void);
void close_archive (void);
void closeout_volume_number (void);
void compute_duration (void);
double compute_duration (void);
union block *find_next_block (void);
void flush_read (void);
void flush_write (void);
@@ -432,6 +450,12 @@ void archive_read_error (void);
off_t seek_archive (off_t size);
void set_start_time (void);
#define TF_READ 0
#define TF_WRITE 1
#define TF_DELETED 2
int format_total_stats (FILE *fp, const char **formats, int eor, int eol);
void print_total_stats (void);
void mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft);
void mv_begin_read (struct tar_stat_info *st);
@@ -440,6 +464,9 @@ void mv_size_left (off_t size);
void buffer_write_global_xheader (void);
const char *first_decompress_program (int *pstate);
const char *next_decompress_program (int *pstate);
/* Module create.c. */
enum dump_status
@@ -511,6 +538,7 @@ void rebase_directory (struct directory *dir,
const char *repl, size_t rlen);
void append_incremental_renames (struct directory *dir);
void show_snapshot_field_ranges (void);
void read_directory_file (void);
void write_directory_file (void);
void purge_directory (char const *directory_name);
@@ -519,6 +547,7 @@ void update_parent_directory (struct tar_stat_info *st);
size_t dumpdir_size (const char *p);
bool is_dumpdir (struct tar_stat_info *stat_info);
void clear_directory_table (void);
/* Module list.c. */
@@ -550,6 +579,7 @@ extern size_t recent_long_link_blocks;
void decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group);
void transform_stat_info (int typeflag, struct tar_stat_info *stat_info);
char const *tartime (struct timespec t, bool full_time);
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
@@ -573,23 +603,62 @@ void skip_member (void);
/* Module misc.c. */
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) < (b) ? (b) : (a))
void assign_string (char **dest, const char *src);
int unquote_string (char *str);
char *zap_slashes (char *name);
char *normalize_filename (const char *name);
char *normalize_filename (int cdidx, const char *name);
void normalize_filename_x (char *name);
void replace_prefix (char **pname, const char *samp, size_t slen,
const char *repl, size_t rlen);
char *tar_savedir (const char *name, int must_exist);
typedef struct namebuf *namebuf_t;
namebuf_t namebuf_create (const char *dir);
void namebuf_free (namebuf_t buf);
char *namebuf_name (namebuf_t buf, const char *name);
void namebuf_add_dir (namebuf_t buf, const char *name);
char *namebuf_finish (namebuf_t buf);
const char *tar_dirname (void);
/* Represent N using a signed integer I such that (uintmax_t) I == N.
With a good optimizing compiler, this is equivalent to (intmax_t) i
and requires zero machine instructions. */
#if ! (UINTMAX_MAX / 2 <= INTMAX_MAX)
# error "represent_uintmax returns intmax_t to represent uintmax_t"
#endif
COMMON_INLINE intmax_t
represent_uintmax (uintmax_t n)
{
if (n <= INTMAX_MAX)
return n;
else
{
/* Avoid signed integer overflow on picky platforms. */
intmax_t nd = n - INTMAX_MIN;
return nd + INTMAX_MIN;
}
}
enum { SYSINT_BUFSIZE =
max (UINTMAX_STRSIZE_BOUND, INT_BUFSIZE_BOUND (intmax_t)) };
char *sysinttostr (uintmax_t, intmax_t, uintmax_t, char buf[SYSINT_BUFSIZE]);
intmax_t strtosysint (char const *, char **, intmax_t, uintmax_t);
void code_ns_fraction (int ns, char *p);
char const *code_timespec (struct timespec ts, char *sbuf);
enum { BILLION = 1000000000, LOG10_BILLION = 9 };
enum { TIMESPEC_STRSIZE_BOUND =
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
struct timespec decode_timespec (char const *, char **, bool);
/* Return true if T does not represent an out-of-range or invalid value. */
COMMON_INLINE bool
valid_timespec (struct timespec t)
{
return 0 <= t.tv_nsec;
}
bool must_be_dot_or_slash (char const *);
@@ -613,6 +682,9 @@ void undo_last_backup (void);
int deref_stat (char const *name, struct stat *buf);
size_t blocking_read (int fd, void *buf, size_t count);
size_t blocking_write (int fd, void const *buf, size_t count);
extern int chdir_current;
extern int chdir_fd;
int chdir_arg (char const *dir);
@@ -628,8 +700,6 @@ void seek_diag_details (char const *name, off_t offset);
void stat_diag (char const *name);
void file_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name));
void dir_removed_diag (char const *name, bool top_level,
void (*diagfn) (char const *name));
void write_error_details (char const *name, size_t status, size_t size);
void write_fatal (char const *name) __attribute__ ((noreturn));
void write_fatal_details (char const *name, ssize_t status, size_t size)
@@ -655,6 +725,7 @@ int uname_to_uid (char const *uname, uid_t *puid);
void name_init (void);
void name_add_name (const char *name, int matching_flags);
void name_add_dir (const char *name);
void name_add_file (const char *name, int term);
void name_term (void);
const char *name_next (int change_dirs);
void name_gather (void);
@@ -672,11 +743,8 @@ char *new_name (const char *dir_name, const char *name);
size_t stripped_prefix_len (char const *file_name, size_t num);
bool all_names_found (struct tar_stat_info *st);
bool excluded_name (char const *name);
void add_avoided_name (char const *name);
bool is_avoided_name (char const *name);
bool is_individual_file (char const *name);
bool contains_dot_dot (char const *name);
@@ -700,19 +768,25 @@ const char *archive_format_string (enum archive_format fmt);
const char *subcommand_string (enum subcommand c);
void set_exit_status (int val);
void request_stdin (const char *option);
void more_options (int argc, char **argv);
/* Module update.c. */
extern char *output_start;
void update_archive (void);
/* Module attrs.c. */
#include "xattrs.h"
/* Module xheader.c. */
void xheader_decode (struct tar_stat_info *stat);
void xheader_decode_global (struct xheader *xhdr);
void xheader_store (char const *keyword, struct tar_stat_info *st,
void const *data);
void xheader_read (struct xheader *xhdr, union block *header, size_t size);
void xheader_read (struct xheader *xhdr, union block *header, off_t size);
void xheader_write (char type, char *name, time_t t, struct xheader *xhdr);
void xheader_write_global (struct xheader *xhdr);
void xheader_finish (struct xheader *hdr);
@@ -726,6 +800,12 @@ bool xheader_string_end (struct xheader *xhdr, char const *keyword);
bool xheader_keyword_deleted_p (const char *kw);
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
size_t n);
void xheader_xattr_init (struct tar_stat_info *st);
void xheader_xattr_free (struct xattr_array *vals, size_t sz);
void xheader_xattr_copy (const struct tar_stat_info *st,
struct xattr_array **vals, size_t *sz);
void xheader_xattr_add (struct tar_stat_info *st,
const char *key, const char *val, size_t len);
/* Module system.c */
@@ -750,7 +830,8 @@ void sys_exec_checkpoint_script (const char *script_name,
int checkpoint_number);
/* Module compare.c */
void report_difference (struct tar_stat_info *st, const char *message, ...);
void report_difference (struct tar_stat_info *st, const char *message, ...)
__attribute__ ((format (printf, 2, 3)));
/* Module sparse.c */
bool sparse_member_p (struct tar_stat_info *st);
@@ -775,14 +856,18 @@ void set_transform_expr (const char *expr);
bool transform_name (char **pinput, int type);
bool transform_name_fp (char **pinput, int type,
char *(*fun)(char *, void *), void *);
bool transform_program_p (void);
/* Module suffix.c */
void set_compression_program_by_suffix (const char *name, const char *defprog);
char *strip_compression_suffix (const char *name);
/* Module checkpoint.c */
void checkpoint_compile_action (const char *str);
void checkpoint_finish_compile (void);
void checkpoint_run (bool do_write);
void checkpoint_finish (void);
void checkpoint_flush_actions (void);
/* Module warning.c */
#define WARN_ALONE_ZERO_BLOCK 0x00000001
@@ -804,10 +889,15 @@ void checkpoint_run (bool do_write);
#define WARN_UNKNOWN_CAST 0x00010000
#define WARN_UNKNOWN_KEYWORD 0x00020000
#define WARN_XDEV 0x00040000
#define WARN_DECOMPRESS_PROGRAM 0x00080000
#define WARN_EXISTING_FILE 0x00100000
#define WARN_XATTR_WRITE 0x00200000
#define WARN_RECORD_SIZE 0x00400000
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
in verbose mode */
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY)
/* These warnings are enabled by default in verbose mode: */
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
WARN_DECOMPRESS_PROGRAM|WARN_EXISTING_FILE|\
WARN_RECORD_SIZE)
#define WARN_ALL (~WARN_VERBOSE_WARNINGS)
void set_warning_option (const char *arg);
@@ -828,3 +918,17 @@ void finish_deferred_unlinks (void);
/* Module exit.c */
extern void (*fatal_exit_hook) (void);
/* Module exclist.c */
#define EXCL_DEFAULT 0x00
#define EXCL_RECURSIVE 0x01
#define EXCL_NON_RECURSIVE 0x02
void excfile_add (const char *name, int flags);
void info_attach_exclist (struct tar_stat_info *dir);
void info_cleanup_exclist (struct tar_stat_info *dir);
void info_free_exclist (struct tar_stat_info *dir);
bool excluded_name (char const *name, struct tar_stat_info *st);
void exclude_vcs_ignores (void);
_GL_INLINE_HEADER_END

View File

@@ -1,23 +1,24 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2007,
2009-2010, 2012-2014 Free Software Foundation, Inc.
Written by John Gilmore, on 1987-04-30.
This file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by John Gilmore, on 1987-04-30. */
#include <system.h>
#include <system-ioctl.h>
@@ -80,7 +81,7 @@ process_noop (size_t size __attribute__ ((unused)),
static int
process_rawdata (size_t bytes, char *buffer)
{
size_t status = safe_read (diff_handle, diff_buffer, bytes);
size_t status = blocking_read (diff_handle, diff_buffer, bytes);
if (status != bytes)
{
@@ -234,7 +235,8 @@ diff_file (void)
else
read_and_process (&current_stat_info, process_rawdata);
if (atime_preserve_option == replace_atime_preserve)
if (atime_preserve_option == replace_atime_preserve
&& stat_data.st_size != 0)
{
struct timespec atime = get_stat_atime (&stat_data);
if (set_file_atime (diff_handle, chdir_fd, file_name, atime)
@@ -358,31 +360,38 @@ dumpdir_cmp (const char *a, const char *b)
}
static void
diff_dumpdir (void)
diff_dumpdir (struct tar_stat_info *dir)
{
const char *dumpdir_buffer;
dev_t dev = 0;
struct stat stat_data;
if (deref_stat (current_stat_info.file_name, &stat_data) != 0)
if (dir->fd == 0)
{
if (errno == ENOENT)
stat_warn (current_stat_info.file_name);
void (*diag) (char const *) = NULL;
int fd = subfile_open (dir->parent, dir->orig_file_name, open_read_flags);
if (fd < 0)
diag = open_diag;
else if (fstat (fd, &dir->stat))
{
diag = stat_diag;
close (fd);
}
else
stat_error (current_stat_info.file_name);
dir->fd = fd;
if (diag)
{
file_removed_diag (dir->orig_file_name, false, diag);
return;
}
}
else
dev = stat_data.st_dev;
dumpdir_buffer = directory_contents (scan_directory (&current_stat_info));
dumpdir_buffer = directory_contents (scan_directory (dir));
if (dumpdir_buffer)
{
if (dumpdir_cmp (current_stat_info.dumpdir, dumpdir_buffer))
report_difference (&current_stat_info, _("Contents differ"));
if (dumpdir_cmp (dir->dumpdir, dumpdir_buffer))
report_difference (dir, _("Contents differ"));
}
else
read_and_process (&current_stat_info, process_noop);
read_and_process (dir, process_noop);
}
static void
@@ -409,7 +418,9 @@ diff_multivol (void)
}
offset = OFF_FROM_HEADER (current_header->oldgnu_header.offset);
if (stat_data.st_size != current_stat_info.stat.st_size + offset)
if (offset < 0
|| INT_ADD_OVERFLOW (current_stat_info.stat.st_size, offset)
|| stat_data.st_size != current_stat_info.stat.st_size + offset)
{
report_difference (&current_stat_info, _("Size differs"));
skip_member ();
@@ -431,10 +442,9 @@ diff_multivol (void)
{
seek_error_details (current_stat_info.file_name, offset);
report_difference (&current_stat_info, NULL);
return;
}
read_and_process (&current_stat_info, process_rawdata);
else
read_and_process (&current_stat_info, process_rawdata);
status = close (fd);
if (status != 0)
@@ -460,7 +470,7 @@ diff_archive (void)
switch (current_header->header.typeflag)
{
default:
ERROR ((0, 0, _("%s: Unknown file type `%c', diffed as normal file"),
ERROR ((0, 0, _("%s: Unknown file type '%c', diffed as normal file"),
quotearg_colon (current_stat_info.file_name),
current_header->header.typeflag));
/* Fall through. */
@@ -497,7 +507,7 @@ diff_archive (void)
case GNUTYPE_DUMPDIR:
case DIRTYPE:
if (is_dumpdir (&current_stat_info))
diff_dumpdir ();
diff_dumpdir (&current_stat_info);
diff_dir ();
break;
@@ -512,13 +522,24 @@ diff_archive (void)
void
verify_volume (void)
{
int may_fail = 0;
if (removed_prefixes_p ())
{
WARN((0, 0,
_("Archive contains file names with leading prefixes removed.")));
WARN((0, 0,
_("Verification may fail to locate original files.")));
may_fail = 1;
}
if (transform_program_p ())
{
WARN((0, 0,
_("Archive contains transformed file names.")));
may_fail = 1;
}
if (may_fail)
WARN((0, 0,
_("Verification may fail to locate original files.")));
clear_directory_table ();
if (!diff_buffer)
diff_init ();
@@ -611,8 +632,10 @@ verify_volume (void)
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
}
continue;
}
decode_header (current_header, &current_stat_info, &current_format, 1);
diff_archive ();
tar_stat_destroy (&current_stat_info);
}

View File

@@ -1,57 +0,0 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(tar.h)
PROGS="tar"
AC_SUBST(PROGS)dnl
AC_PROG_CC
AC_PROG_CPP
AC_GCC_TRADITIONAL
AC_PROG_INSTALL
AC_PROG_YACC
AC_AIX
AC_MINIX
AC_ISC_POSIX
AC_CONST
AC_RETSIGTYPE
AC_SIZE_T
AC_MAJOR_HEADER
AC_DIR_HEADER
# The 3-argument open happens to go along with the O_* defines,
# which are easier to check for.
AC_HEADER_CHECK(fcntl.h, open_header=fcntl.h, open_header=sys/file.h)
AC_COMPILE_CHECK(3-argument open,
[#include <$open_header>], [int x = O_RDONLY;], , AC_DEFINE(EMUL_OPEN3))
AC_REMOTE_TAPE
AC_RSH
AC_STDC_HEADERS
AC_UNISTD_H
echo checking for getgrgid declaration
AC_HEADER_EGREP(getgrgid, grp.h, AC_DEFINE(HAVE_GETGRGID))
echo checking for getpwuid declaration
AC_HEADER_EGREP(getpwuid, pwd.h, AC_DEFINE(HAVE_GETPWUID))
AC_HAVE_HEADERS(string.h limits.h)
echo checking default archive
# This might guess wrong, but it's not very important.
for dev in rmt8 rmt0 rmt0h rct0 rst0 tape rct/c7d0s2
do
if test -n "`ls /dev/$dev 2>/dev/null`"; then
DEF_AR_FILE=/dev/$dev
break
fi
done
if test -z "$DEF_AR_FILE"; then
DEF_AR_FILE=-
fi
AC_SUBST(DEF_AR_FILE)dnl
AC_HAVE_FUNCS(strstr valloc mkdir mknod rename ftruncate ftime getcwd)
AC_VPRINTF
AC_ALLOCA
echo checking for BSD
( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && AC_DEFINE(BSD42)
echo checking for HP-UX
test "`(uname -s) 2> /dev/null`" = 'HP-UX' && MALLOC=malloc.o
AC_SUBST(MALLOC)
AC_XENIX_DIR
AC_HAVE_LIBRARY(socket, [LIBS="$LIBS -lsocket"])
AC_HAVE_LIBRARY(nsl, [LIBS="$LIBS -lnsl"])
AC_OUTPUT(Makefile)

View File

@@ -1,23 +1,24 @@
/* Create a tar archive.
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Copyright 1985, 1992-1994, 1996-1997, 1999-2001, 2003-2007,
2009-2010, 2012-2014 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
This file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by John Gilmore, on 1985-08-25. */
#include <system.h>
@@ -511,12 +512,11 @@ start_private_header (const char *name, size_t size, time_t t)
tar_name_copy_str (header->header.name, name, NAME_FIELD_SIZE);
OFF_TO_CHARS (size, header->header.size);
TIME_TO_CHARS (t, header->header.mtime);
TIME_TO_CHARS (t < 0 ? 0 : min (t, MAX_OCTAL_VAL (header->header.mtime)),
header->header.mtime);
MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
UID_TO_CHARS (getuid (), header->header.uid);
GID_TO_CHARS (getgid (), header->header.gid);
MAJOR_TO_CHARS (0, header->header.devmajor);
MINOR_TO_CHARS (0, header->header.devminor);
UID_TO_CHARS (0, header->header.uid);
GID_TO_CHARS (0, header->header.gid);
strncpy (header->header.magic, TMAGIC, TMAGLEN);
strncpy (header->header.version, TVERSION, TVERSLEN);
return header;
@@ -534,11 +534,6 @@ write_short_name (struct tar_stat_info *st)
return header;
}
#define FILL(field,byte) do { \
memset(field, byte, sizeof(field)-1); \
(field)[sizeof(field)-1] = 0; \
} while (0)
/* Write a GNUTYPE_LONGLINK or GNUTYPE_LONGNAME block. */
static void
write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
@@ -548,13 +543,7 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
union block *header;
char *tmpname;
header = start_private_header ("././@LongLink", size, time (NULL));
FILL (header->header.mtime, '0');
FILL (header->header.mode, '0');
FILL (header->header.uid, '0');
FILL (header->header.gid, '0');
FILL (header->header.devmajor, 0);
FILL (header->header.devminor, 0);
header = start_private_header ("././@LongLink", size, 0);
uid_to_uname (0, &tmpname);
UNAME_TO_CHARS (tmpname, header->header.uname);
free (tmpname);
@@ -562,7 +551,8 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
GNAME_TO_CHARS (tmpname, header->header.gname);
free (tmpname);
strcpy (header->header.magic, OLDGNU_MAGIC);
strcpy (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC);
header->header.typeflag = type;
finish_header (st, header, -1);
@@ -710,7 +700,7 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
{
type = XGLTYPE;
p = xheader_ghdr_name ();
time (&t);
t = start_time.tv_sec;
}
else
{
@@ -784,9 +774,9 @@ start_header (struct tar_stat_info *st)
. . . . . . . . . 9 = Omron UNIOS-B 4.3BSD 1.60Beta
. = works
# = ``impossible file type''
# = "impossible file type"
The following mask for old archive removes the `#'s in column 4
The following mask for old archive removes the '#'s in column 4
above, thus making GNU tar both a universal donor and a universal
acceptor for Paul's test. */
@@ -899,7 +889,8 @@ start_header (struct tar_stat_info *st)
case OLDGNU_FORMAT:
case GNU_FORMAT: /*FIXME?*/
/* Overwrite header->header.magic and header.version in one blow. */
strcpy (header->header.magic, OLDGNU_MAGIC);
strcpy (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC);
break;
case POSIX_FORMAT:
@@ -918,8 +909,15 @@ start_header (struct tar_stat_info *st)
}
else
{
uid_to_uname (st->stat.st_uid, &st->uname);
gid_to_gname (st->stat.st_gid, &st->gname);
if (owner_name_option)
st->uname = xstrdup (owner_name_option);
else
uid_to_uname (st->stat.st_uid, &st->uname);
if (group_name_option)
st->gname = xstrdup (group_name_option);
else
gid_to_gname (st->stat.st_gid, &st->gname);
if (archive_format == POSIX_FORMAT
&& (strlen (st->uname) > UNAME_FIELD_SIZE
@@ -934,6 +932,30 @@ start_header (struct tar_stat_info *st)
GNAME_TO_CHARS (st->gname, header->header.gname);
}
if (archive_format == POSIX_FORMAT)
{
if (acls_option > 0)
{
if (st->acls_a_ptr)
xheader_store ("SCHILY.acl.access", st, NULL);
if (st->acls_d_ptr)
xheader_store ("SCHILY.acl.default", st, NULL);
}
if ((selinux_context_option > 0) && st->cntx_name)
xheader_store ("RHT.security.selinux", st, NULL);
if (xattrs_option > 0)
{
size_t scan_xattr = 0;
struct xattr_array *xattr_map = st->xattr_map;
while (scan_xattr < st->xattr_map_size)
{
xheader_store (xattr_map[scan_xattr].xkey, st, &scan_xattr);
++scan_xattr;
}
}
}
return header;
}
@@ -1042,7 +1064,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
}
count = (fd <= 0) ? bufsize : safe_read (fd, blk->buffer, bufsize);
count = (fd <= 0) ? bufsize : blocking_read (fd, blk->buffer, bufsize);
if (count == SAFE_READ_ERROR)
{
read_diag_details (st->orig_file_name,
@@ -1091,6 +1113,8 @@ dump_dir0 (struct tar_stat_info *st, char const *directory)
if (!blk)
return;
info_attach_exclist (st);
if (incremental_option && archive_format != POSIX_FORMAT)
blk->header.typeflag = GNUTYPE_DUMPDIR;
else /* if (standard_option) */
@@ -1174,7 +1198,7 @@ dump_dir0 (struct tar_stat_info *st, char const *directory)
char const *entry;
size_t entry_len;
size_t name_len;
name_buf = xstrdup (st->orig_file_name);
name_size = name_len = strlen (name_buf);
@@ -1188,7 +1212,7 @@ dump_dir0 (struct tar_stat_info *st, char const *directory)
name_buf = xrealloc (name_buf, name_size + 1);
}
strcpy (name_buf + name_len, entry);
if (!excluded_name (name_buf))
if (!excluded_name (name_buf, st))
dump_file (st, entry, name_buf);
}
@@ -1266,7 +1290,7 @@ get_directory_entries (struct tar_stat_info *st)
while (! (st->dirstream = fdopendir (st->fd)))
if (! open_failure_recover (st))
return 0;
return streamsavedir (st->dirstream);
return streamsavedir (st->dirstream, savedir_sort_order);
}
/* Dump the directory ST. Return true if successful, false (emitting
@@ -1317,12 +1341,12 @@ create_archive (void)
collect_and_sort_names ();
while ((p = name_from_list ()) != NULL)
if (!excluded_name (p->name))
if (!excluded_name (p->name, NULL))
dump_file (0, p->name, p->name);
blank_name_list ();
while ((p = name_from_list ()) != NULL)
if (!excluded_name (p->name))
if (!excluded_name (p->name, NULL))
{
struct tar_stat_info st;
size_t plen = strlen (p->name);
@@ -1336,7 +1360,7 @@ create_archive (void)
if (! ISSLASH (buffer[plen - 1]))
buffer[plen++] = DIRECTORY_SEPARATOR;
tar_stat_init (&st);
q = directory_contents (gnu_list_name->directory);
q = directory_contents (p->directory);
if (q)
while (*q)
{
@@ -1379,7 +1403,7 @@ create_archive (void)
{
const char *name;
while ((name = name_next (1)) != NULL)
if (!excluded_name (name))
if (!excluded_name (name, NULL))
dump_file (0, name, name);
}
@@ -1676,9 +1700,9 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
put in the archive.
This check is omitted if incremental_option is set *and* the
requested file is not explicitely listed in the command line. */
requested file is not explicitly listed in the command line. */
if (!(incremental_option && !is_individual_file (p))
if (! (incremental_option && ! top_level)
&& !S_ISDIR (st->stat.st_mode)
&& OLDER_TAR_STAT_TIME (*st, m)
&& (!after_date_option || OLDER_TAR_STAT_TIME (*st, c)))
@@ -1709,6 +1733,10 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
bool ok;
struct stat final_stat;
xattrs_acls_get (parentfd, name, st, 0, !is_dir);
xattrs_selinux_get (parentfd, name, st, fd);
xattrs_xattrs_get (parentfd, name, st, fd);
if (is_dir)
{
const char *tag_file_name;
@@ -1795,6 +1823,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
set_exit_status (TAREXIT_DIFFERS);
}
else if (atime_preserve_option == replace_atime_preserve
&& fd && (is_dir || original_size != 0)
&& set_file_atime (fd, parentfd, name, st->atime) != 0)
utime_error (p);
}
@@ -1826,6 +1855,9 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
write_long_link (st);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
block_ordinal = current_block_ordinal ();
st->stat.st_size = 0; /* force 0 size on symlink */
header = start_header (st);
@@ -1844,11 +1876,26 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
}
#endif
else if (S_ISCHR (st->stat.st_mode))
type = CHRTYPE;
{
type = CHRTYPE;
xattrs_acls_get (parentfd, name, st, 0, true);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
}
else if (S_ISBLK (st->stat.st_mode))
type = BLKTYPE;
{
type = BLKTYPE;
xattrs_acls_get (parentfd, name, st, 0, true);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
}
else if (S_ISFIFO (st->stat.st_mode))
type = FIFOTYPE;
{
type = FIFOTYPE;
xattrs_acls_get (parentfd, name, st, 0, true);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
}
else if (S_ISSOCK (st->stat.st_mode))
{
WARNOPT (WARN_FILE_IGNORED,

View File

@@ -1,21 +1,22 @@
/* Delete entries from a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
2005, 2006, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994, 1996-1997, 2000-2001, 2003-2006, 2010,
2013-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <system-ioctl.h>

361
src/exclist.c Normal file
View File

@@ -0,0 +1,361 @@
/* Per-directory exclusion files for tar.
Copyright 2014 Free Software Foundation, Inc.
This file is part of GNU tar.
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <system.h>
#include <quotearg.h>
#include <fnmatch.h>
#include <wordsplit.h>
#include "common.h"
typedef void (*add_fn) (struct exclude *, char const *, int, void *);
struct vcs_ignore_file
{
char const *filename;
int flags;
add_fn addfn;
void *(*initfn) (void *);
void *data;
};
static struct vcs_ignore_file *get_vcs_ignore_file (const char *name);
struct excfile
{
struct excfile *next;
int flags;
char name[1];
};
struct excfile *excfile_head, *excfile_tail;
void
excfile_add (const char *name, int flags)
{
struct excfile *p = xmalloc (sizeof (*p) + strlen (name));
p->next = NULL;
p->flags = flags;
strcpy (p->name, name);
if (excfile_tail)
excfile_tail->next = p;
else
excfile_head = p;
excfile_tail = p;
}
struct exclist
{
struct exclist *next, *prev;
int flags;
struct exclude *excluded;
};
void
info_attach_exclist (struct tar_stat_info *dir)
{
struct excfile *file;
struct exclist *head = NULL, *tail = NULL, *ent;
struct vcs_ignore_file *vcsfile;
if (dir->exclude_list)
return;
for (file = excfile_head; file; file = file->next)
{
if (faccessat (dir ? dir->fd : chdir_fd, file->name, F_OK, 0) == 0)
{
FILE *fp;
struct exclude *ex = NULL;
int fd = subfile_open (dir, file->name, O_RDONLY);
if (fd == -1)
{
open_error (file->name);
continue;
}
fp = fdopen (fd, "r");
if (!fp)
{
ERROR ((0, errno, _("%s: fdopen failed"), file->name));
close (fd);
continue;
}
if (!ex)
ex = new_exclude ();
vcsfile = get_vcs_ignore_file (file->name);
if (vcsfile->initfn)
vcsfile->data = vcsfile->initfn (vcsfile->data);
if (add_exclude_fp (vcsfile->addfn, ex, fp,
EXCLUDE_WILDCARDS|EXCLUDE_ANCHORED, '\n',
vcsfile->data))
{
int e = errno;
FATAL_ERROR ((0, e, "%s", quotearg_colon (file->name)));
}
fclose (fp);
ent = xmalloc (sizeof (*ent));
ent->excluded = ex;
ent->flags = file->flags == EXCL_DEFAULT
? file->flags : vcsfile->flags;
ent->prev = tail;
ent->next = NULL;
if (tail)
tail->next = ent;
else
head = ent;
tail = ent;
}
}
dir->exclude_list = head;
}
void
info_cleanup_exclist (struct tar_stat_info *dir)
{
struct exclist *ep = dir->exclude_list;
while (ep)
{
struct exclist *next = ep->next;
if (ep->flags & EXCL_NON_RECURSIVE)
{
/* Remove the entry */
if (ep->prev)
ep->prev->next = ep->next;
else
dir->exclude_list = ep->next;
if (ep->next)
ep->next->prev = ep->prev;
free_exclude (ep->excluded);
free (ep);
}
ep = next;
}
}
void
info_free_exclist (struct tar_stat_info *dir)
{
struct exclist *ep = dir->exclude_list;
while (ep)
{
struct exclist *next = ep->next;
free_exclude (ep->excluded);
free (ep);
ep = next;
}
dir->exclude_list = NULL;
}
/* Return nonzero if file NAME is excluded. */
bool
excluded_name (char const *name, struct tar_stat_info *st)
{
struct exclist *ep;
const char *rname = NULL;
char *bname = NULL;
bool result;
int nr = 0;
name += FILE_SYSTEM_PREFIX_LEN (name);
/* Try global exclusion list first */
if (excluded_file_name (excluded, name))
return true;
if (!st)
return false;
for (result = false; st && !result; st = st->parent, nr = EXCL_NON_RECURSIVE)
{
for (ep = st->exclude_list; ep; ep = ep->next)
{
if (ep->flags & nr)
continue;
if ((result = excluded_file_name (ep->excluded, name)))
break;
if (!rname)
{
rname = name;
/* Skip leading ./ */
while (*rname == '.' && ISSLASH (rname[1]))
rname += 2;
}
if ((result = excluded_file_name (ep->excluded, rname)))
break;
if (!bname)
bname = base_name (name);
if ((result = excluded_file_name (ep->excluded, bname)))
break;
}
}
free (bname);
return result;
}
static void
cvs_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
struct wordsplit ws;
size_t i;
if (wordsplit (pattern, &ws,
WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS))
return;
for (i = 0; i < ws.ws_wordc; i++)
add_exclude (ex, ws.ws_wordv[i], options);
wordsplit_free (&ws);
}
static void
git_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
while (isspace (*pattern))
++pattern;
if (*pattern == 0 || *pattern == '#')
return;
if (*pattern == '\\' && pattern[1] == '#')
++pattern;
add_exclude (ex, pattern, options);
}
static void
bzr_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
while (isspace (*pattern))
++pattern;
if (*pattern == 0 || *pattern == '#')
return;
if (*pattern == '!')
{
if (*++pattern == '!')
++pattern;
else
options |= EXCLUDE_INCLUDE;
}
/* FIXME: According to the docs, globbing patterns are rsync-style,
and regexps are perl-style. */
if (strncmp (pattern, "RE:", 3) == 0)
{
pattern += 3;
options &= ~EXCLUDE_WILDCARDS;
options |= EXCLUDE_REGEX;
}
add_exclude (ex, pattern, options);
}
static void *
hg_initfn (void *data)
{
int *hgopt;
static int hg_options;
if (!data)
hgopt = &hg_options;
*hgopt = EXCLUDE_REGEX;
return hgopt;
}
static void
hg_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
int *hgopt = data;
size_t len;
while (isspace (*pattern))
++pattern;
if (*pattern == 0 || *pattern == '#')
return;
if (strncmp (pattern, "syntax:", 7) == 0)
{
for (pattern += 7; isspace (*pattern); ++pattern)
;
if (strcmp (pattern, "regexp") == 0)
/* FIXME: Regexps must be perl-style */
*hgopt = EXCLUDE_REGEX;
else if (strcmp (pattern, "glob") == 0)
*hgopt = EXCLUDE_WILDCARDS;
/* Ignore unknown syntax */
return;
}
len = strlen(pattern);
if (pattern[len-1] == '/')
{
char *p;
--len;
p = xmalloc (len+1);
memcpy (p, pattern, len);
p[len] = 0;
pattern = p;
exclude_add_pattern_buffer (ex, p);
options |= FNM_LEADING_DIR|EXCLUDE_ALLOC;
}
add_exclude (ex, pattern,
((*hgopt == EXCLUDE_REGEX)
? (options & ~EXCLUDE_WILDCARDS)
: (options & ~EXCLUDE_REGEX)) | *hgopt);
}
struct vcs_ignore_file vcs_ignore_files[] = {
{ ".cvsignore", EXCL_NON_RECURSIVE, cvs_addfn, NULL, NULL },
{ ".gitignore", 0, git_addfn, NULL, NULL },
{ ".bzrignore", 0, bzr_addfn, NULL, NULL },
{ ".hgignore", 0, hg_addfn, hg_initfn , NULL },
{ NULL, 0, git_addfn, NULL, NULL }
};
static struct vcs_ignore_file *
get_vcs_ignore_file (const char *name)
{
struct vcs_ignore_file *p;
for (p = vcs_ignore_files; p->filename; p++)
if (strcmp (p->filename, name) == 0)
break;
return p;
}
void
exclude_vcs_ignores (void)
{
struct vcs_ignore_file *p;
for (p = vcs_ignore_files; p->filename; p++)
excfile_add (p->filename, EXCL_DEFAULT);
}

View File

@@ -1,19 +1,21 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
/* Exit from GNU tar.
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.
Copyright 2009, 2013-2014 Free Software Foundation, Inc.
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.
This file is part of GNU tar.
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. */
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"

View File

@@ -1,28 +1,30 @@
/* Extract files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014 Free
Software Foundation, Inc.
Written by John Gilmore, on 1985-11-19.
This file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by John Gilmore, on 1985-11-19. */
#include <system.h>
#include <quotearg.h>
#include <errno.h>
#include <priv-set.h>
#include <root-uid.h>
#include <utimens.h>
#include "common.h"
@@ -97,6 +99,14 @@ struct delayed_set_stat
/* Directory that the name is relative to. */
int change_dir;
/* extended attributes*/
char *cntx_name;
char *acls_a_ptr;
size_t acls_a_len;
char *acls_d_ptr;
size_t acls_d_len;
size_t xattr_map_size;
struct xattr_array *xattr_map;
/* Length and contents of name. */
size_t file_name_len;
char file_name[1];
@@ -110,12 +120,15 @@ struct delayed_link
/* The next delayed link in the list. */
struct delayed_link *next;
/* The device, inode number and ctime of the placeholder. Use
ctime, not mtime, to make false matches less likely if some
other process removes the placeholder. */
/* The device, inode number and birthtime of the placeholder.
birthtime.tv_nsec is negative if the birthtime is not available.
Don't use mtime as this would allow for false matches if some
other process removes the placeholder. Don't use ctime as
this would cause race conditions and other screwups, e.g.,
when restoring hard-linked symlinks. */
dev_t dev;
ino_t ino;
struct timespec ctime;
struct timespec birthtime;
/* True if the link is symbolic. */
bool is_symlink;
@@ -134,6 +147,18 @@ struct delayed_link
hard-linked together. */
struct string_list *sources;
/* SELinux context */
char *cntx_name;
/* ACLs */
char *acls_a_ptr;
size_t acls_a_len;
char *acls_d_ptr;
size_t acls_d_len;
size_t xattr_map_size;
struct xattr_array *xattr_map;
/* The desired target of the desired link. */
char target[1];
};
@@ -150,7 +175,7 @@ struct string_list
void
extr_init (void)
{
we_are_root = geteuid () == 0;
we_are_root = geteuid () == ROOT_UID;
same_permissions_option += we_are_root;
same_owner_option += we_are_root;
@@ -272,7 +297,7 @@ set_mode (char const *file_name,
static void
check_time (char const *file_name, struct timespec t)
{
if (t.tv_sec <= 0)
if (t.tv_sec < 0)
WARNOPT (WARN_TIMESTAMP,
(0, 0, _("%s: implausibly old time stamp %s"),
file_name, tartime (t, true)));
@@ -360,6 +385,12 @@ set_stat (char const *file_name,
st->stat.st_mode & ~ current_umask,
0 < same_permissions_option && ! interdir ? MODE_ALL : MODE_RWX,
fd, current_mode, current_mode_mask, typeflag, atflag);
/* these three calls must be done *after* fd_chown() call because fd_chown
causes that linux capabilities becomes cleared. */
xattrs_xattrs_set (st, file_name, typeflag, 1);
xattrs_acls_set (st, file_name, typeflag);
xattrs_selinux_set (st, file_name, typeflag);
}
/* For each entry H in the leading prefix of entries in HEAD that do
@@ -431,6 +462,36 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->atflag = atflag;
data->after_links = 0;
data->change_dir = chdir_current;
data->cntx_name = NULL;
if (st)
assign_string (&data->cntx_name, st->cntx_name);
if (st && st->acls_a_ptr)
{
data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
data->acls_a_len = st->acls_a_len;
}
else
{
data->acls_a_ptr = NULL;
data->acls_a_len = 0;
}
if (st && st->acls_d_ptr)
{
data->acls_d_ptr = xmemdup (st->acls_d_ptr, st->acls_d_len + 1);
data->acls_d_len = st->acls_d_len;
}
else
{
data->acls_d_ptr = NULL;
data->acls_d_len = 0;
}
if (st)
xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
else
{
data->xattr_map = NULL;
data->xattr_map_size = 0;
}
strcpy (data->file_name, file_name);
delayed_set_stat_head = data;
if (must_be_dot_or_slash (file_name))
@@ -609,6 +670,18 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
switch (e)
{
case ELOOP:
/* With open ("symlink", O_NOFOLLOW|...), POSIX says errno == ELOOP,
but some operating systems do not conform to the standard. */
#ifdef EFTYPE
/* NetBSD uses errno == EFTYPE; see <http://gnats.netbsd.org/43154>. */
case EFTYPE:
#endif
/* FreeBSD 8.1 uses errno == EMLINK. */
case EMLINK:
/* Tru64 5.1B uses errno == ENOTSUP. */
case ENOTSUP:
if (! regular
|| old_files_option != OVERWRITE_OLD_FILES || dereference_option)
break;
@@ -627,9 +700,14 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
switch (old_files_option)
{
case KEEP_OLD_FILES:
case SKIP_OLD_FILES:
WARNOPT (WARN_EXISTING_FILE,
(0, 0, _("%s: skipping existing file"), file_name));
return RECOVER_SKIP;
case KEEP_OLD_FILES:
return RECOVER_NO;
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, stp, &current_stat_info))
break;
@@ -661,6 +739,40 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
return RECOVER_NO;
}
/* Restore stat extended attributes (xattr) for FILE_NAME, using information
given in *ST. Restore before extraction because they may affect file layout
(e.g. on Lustre distributed parallel filesystem - setting info about how many
servers is this file striped over, stripe size, mirror copies, etc.
in advance dramatically improves the following performance of reading and
writing a file). If not restoring permissions, invert the INVERT_PERMISSIONS
bits from the file's current permissions. TYPEFLAG specifies the type of the
file. FILE_CREATED indicates set_xattr has created the file */
static int
set_xattr (char const *file_name, struct tar_stat_info const *st,
mode_t invert_permissions, char typeflag, int *file_created)
{
int status = 0;
#ifdef HAVE_XATTRS
bool interdir_made = false;
if ((xattrs_option > 0) && st->xattr_map_size)
{
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
do
status = mknodat (chdir_fd, file_name, mode ^ invert_permissions, 0);
while (status && maybe_recoverable ((char *)file_name, false,
&interdir_made));
xattrs_xattrs_set (st, file_name, typeflag, 0);
*file_created = 1;
}
#endif
return(status);
}
/* Fix the statuses of all directories whose statuses need fixing, and
which are not ancestors of FILE_NAME. If AFTER_LINKS is
nonzero, do this for all such directories; otherwise, stop at the
@@ -721,18 +833,43 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
sb.stat.st_gid = data->gid;
sb.atime = data->atime;
sb.mtime = data->mtime;
sb.cntx_name = data->cntx_name;
sb.acls_a_ptr = data->acls_a_ptr;
sb.acls_a_len = data->acls_a_len;
sb.acls_d_ptr = data->acls_d_ptr;
sb.acls_d_len = data->acls_d_len;
sb.xattr_map = data->xattr_map;
sb.xattr_map_size = data->xattr_map_size;
set_stat (data->file_name, &sb,
-1, current_mode, current_mode_mask,
DIRTYPE, data->interdir, data->atflag);
}
delayed_set_stat_head = data->next;
xheader_xattr_free (data->xattr_map, data->xattr_map_size);
free (data->cntx_name);
free (data->acls_a_ptr);
free (data->acls_d_ptr);
free (data);
}
}
static bool
is_directory_link (const char *file_name)
{
struct stat st;
int e = errno;
int res;
res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
S_ISLNK (st.st_mode) &&
fstatat (chdir_fd, file_name, &st, 0) == 0 &&
S_ISDIR (st.st_mode));
errno = e;
return res;
}
/* Extractor functions for various member types */
static int
@@ -777,7 +914,7 @@ extract_dir (char *file_name, int typeflag)
for (;;)
{
status = mkdir (file_name, mode);
status = mkdirat (chdir_fd, file_name, mode);
if (status == 0)
{
current_mode = mode & ~ current_umask;
@@ -788,10 +925,15 @@ extract_dir (char *file_name, int typeflag)
if (errno == EEXIST
&& (interdir_made
|| keep_directory_symlink_option
|| old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES))
{
struct stat st;
if (keep_directory_symlink_option && is_directory_link (file_name))
return 0;
if (deref_stat (file_name, &st) == 0)
{
current_mode = st.st_mode;
@@ -842,7 +984,8 @@ extract_dir (char *file_name, int typeflag)
static int
open_output_file (char const *file_name, int typeflag, mode_t mode,
mode_t *current_mode, mode_t *current_mode_mask)
int file_created, mode_t *current_mode,
mode_t *current_mode_mask)
{
int fd;
bool overwriting_old_files = old_files_option == OVERWRITE_OLD_FILES;
@@ -852,6 +995,10 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW)
: O_EXCL));
/* File might be created in set_xattr. So clear O_EXCL to avoid open() fail */
if (file_created)
openflag = openflag & ~O_EXCL;
if (typeflag == CONTTYPE)
{
static int conttype_diagnosed;
@@ -864,6 +1011,21 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
}
}
/* If O_NOFOLLOW is needed but does not work, check for a symlink
separately. There's a race condition, but that cannot be avoided
on hosts lacking O_NOFOLLOW. */
if (! HAVE_WORKING_O_NOFOLLOW
&& overwriting_old_files && ! dereference_option)
{
struct stat st;
if (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0
&& S_ISLNK (st.st_mode))
{
errno = ELOOP;
return -1;
}
}
fd = openat (chdir_fd, file_name, openflag, mode);
if (0 <= fd)
{
@@ -908,6 +1070,8 @@ extract_file (char *file_name, int typeflag)
bool interdir_made = false;
mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
& ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
mode_t invert_permissions = 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO)
: 0;
mode_t current_mode = 0;
mode_t current_mode_mask = 0;
@@ -924,8 +1088,18 @@ extract_file (char *file_name, int typeflag)
}
else
{
int file_created = 0;
if (set_xattr (file_name, &current_stat_info, invert_permissions,
typeflag, &file_created))
{
skip_member ();
open_error (file_name);
return 1;
}
while ((fd = open_output_file (file_name, typeflag, mode,
&current_mode, &current_mode_mask))
file_created, &current_mode,
&current_mode_mask))
< 0)
{
int recover = maybe_recoverable (file_name, true, &interdir_made);
@@ -964,7 +1138,7 @@ extract_file (char *file_name, int typeflag)
if (written > size)
written = size;
errno = 0;
count = full_write (fd, data_block->buffer, written);
count = blocking_write (fd, data_block->buffer, written);
size -= written;
set_next_block_after ((union block *)
@@ -1050,7 +1224,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
delayed_link_head = p;
p->dev = st.st_dev;
p->ino = st.st_ino;
p->ctime = get_stat_ctime (&st);
p->birthtime = get_stat_birthtime (&st);
p->is_symlink = is_symlink;
if (is_symlink)
{
@@ -1065,6 +1239,13 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
+ strlen (file_name) + 1);
p->sources->next = 0;
strcpy (p->sources->string, file_name);
p->cntx_name = NULL;
assign_string (&p->cntx_name, current_stat_info.cntx_name);
p->acls_a_ptr = NULL;
p->acls_a_len = 0;
p->acls_d_ptr = NULL;
p->acls_d_len = 0;
xheader_xattr_copy (&current_stat_info, &p->xattr_map, &p->xattr_map_size);
strcpy (p->target, current_stat_info.link_name);
h = delayed_set_stat_head;
@@ -1108,7 +1289,8 @@ extract_link (char *file_name, int typeflag)
if (ds->change_dir == chdir_current
&& ds->dev == st1.st_dev
&& ds->ino == st1.st_ino
&& timespec_cmp (ds->ctime, get_stat_ctime (&st1)) == 0)
&& (timespec_cmp (ds->birthtime, get_stat_birthtime (&st1))
== 0))
{
struct string_list *p = xmalloc (offsetof (struct string_list, string)
+ strlen (file_name) + 1);
@@ -1178,7 +1360,7 @@ extract_symlink (char *file_name, int typeflag)
if (!warned_once)
{
warned_once = 1;
WARNOPT (WARN_SYMBOLIC_CAST,
WARNOPT (WARN_SYMLINK_CAST,
(0, 0,
_("Attempting extraction of symbolic links as hard links")));
}
@@ -1191,7 +1373,7 @@ static int
extract_node (char *file_name, int typeflag)
{
bool interdir_made = false;
mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
mode_t mode = (current_stat_info.stat.st_mode & (MODE_RWX | S_IFBLK | S_IFCHR)
& ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
while (mknodat (chdir_fd, file_name, mode, current_stat_info.stat.st_rdev)
@@ -1258,6 +1440,13 @@ extract_failure (char *file_name, int typeflag)
return 1;
}
static int
extract_skip (char *file_name, int typeflag)
{
skip_member ();
return 0;
}
typedef int (*tar_extractor_t) (char *file_name, int typeflag);
@@ -1338,7 +1527,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
ERROR ((0, 0,
_("%s: Cannot extract -- file is continued from another volume"),
quotearg_colon (current_stat_info.file_name)));
*fun = extract_failure;
*fun = extract_skip;
break;
case GNUTYPE_LONGNAME:
@@ -1350,7 +1539,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
default:
WARNOPT (WARN_UNKNOWN_CAST,
(0, 0,
_("%s: Unknown file type `%c', extracted as normal file"),
_("%s: Unknown file type '%c', extracted as normal file"),
quotearg_colon (file_name), typeflag));
*fun = extract_file;
}
@@ -1474,7 +1663,7 @@ apply_delayed_links (void)
if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
&& st.st_dev == ds->dev
&& st.st_ino == ds->ino
&& timespec_cmp (get_stat_ctime (&st), ds->ctime) == 0)
&& timespec_cmp (get_stat_birthtime (&st), ds->birthtime) == 0)
{
/* Unlink the placeholder, then create a hard link if possible,
a symbolic link otherwise. */
@@ -1499,6 +1688,13 @@ apply_delayed_links (void)
st1.stat.st_gid = ds->gid;
st1.atime = ds->atime;
st1.mtime = ds->mtime;
st1.cntx_name = ds->cntx_name;
st1.acls_a_ptr = ds->acls_a_ptr;
st1.acls_a_len = ds->acls_a_len;
st1.acls_d_ptr = ds->acls_d_ptr;
st1.acls_d_len = ds->acls_d_len;
st1.xattr_map = ds->xattr_map;
st1.xattr_map_size = ds->xattr_map_size;
set_stat (source, &st1, -1, 0, 0, SYMTYPE,
false, AT_SYMLINK_NOFOLLOW);
valid_source = source;
@@ -1513,6 +1709,9 @@ apply_delayed_links (void)
sources = next;
}
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
free (ds->cntx_name);
{
struct delayed_link *next = ds->next;
free (ds);

View File

@@ -1,21 +1,22 @@
/* GNU dump extensions to tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2009, 2013-2014
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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <hash.h>
@@ -279,7 +280,7 @@ free_directory (struct directory *dir)
static struct directory *
attach_directory (const char *name)
{
char *cname = normalize_filename (name);
char *cname = normalize_filename (chdir_current, name);
struct directory *dir = make_directory (name, cname);
if (dirtail)
dirtail->next = dir;
@@ -300,6 +301,24 @@ dirlist_replace_prefix (const char *pref, const char *repl)
replace_prefix (&dp->name, pref, pref_len, repl, repl_len);
}
void
clear_directory_table (void)
{
struct directory *dp;
if (directory_table)
hash_clear (directory_table);
if (directory_meta_table)
hash_clear (directory_meta_table);
for (dp = dirhead; dp; )
{
struct directory *next = dp->next;
free_directory (dp);
dp = next;
}
dirhead = dirtail = NULL;
}
/* 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
@@ -327,7 +346,8 @@ note_directory (char const *name, struct timespec mtime,
if (! ((directory_table
|| (directory_table = hash_initialize (0, 0,
hash_directory_canonical_name,
compare_directory_canonical_names, 0)))
compare_directory_canonical_names,
0)))
&& hash_insert (directory_table, directory)))
xalloc_die ();
@@ -350,7 +370,7 @@ find_directory (const char *name)
return 0;
else
{
char *caname = normalize_filename (name);
char *caname = normalize_filename (chdir_current, name);
struct directory *dir = make_directory (name, caname);
struct directory *ret = hash_lookup (directory_table, dir);
free_directory (dir);
@@ -426,8 +446,8 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
{
struct directory *directory;
struct stat *stat_data = &st->stat;
dev_t device = st->parent ? st->parent->stat.st_dev : 0;
bool nfs = NFS_FILE_STAT (*stat_data);
bool perhaps_renamed = false;
if ((directory = find_directory (name_buffer)) != NULL)
{
@@ -482,9 +502,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
}
else
{
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0, _("%s: Directory has been renamed"),
quotearg_colon (name_buffer)));
perhaps_renamed = true;
directory->children = ALL_CHILDREN;
directory->device_number = stat_data->st_dev;
directory->inode_number = stat_data->st_ino;
@@ -503,7 +521,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
stat_data->st_ino);
directory = note_directory (name_buffer,
get_stat_mtime(stat_data),
get_stat_mtime (stat_data),
stat_data->st_dev,
stat_data->st_ino,
nfs,
@@ -540,18 +558,23 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
}
}
/* If the directory is on another device and --one-file-system was given,
omit it... */
if (one_file_system_option && device != stat_data->st_dev
/* ... except if it was explicitely given in the command line */
&& !is_individual_file (name_buffer))
/* FIXME:
WARNOPT (WARN_XDEV,
(0, 0,
_("%s: directory is on a different filesystem; not dumped"),
quotearg_colon (directory->name)));
*/
directory->children = NO_CHILDREN;
if (one_file_system_option && st->parent
&& stat_data->st_dev != st->parent->stat.st_dev)
{
WARNOPT (WARN_XDEV,
(0, 0,
_("%s: directory is on a different filesystem; not dumped"),
quotearg_colon (directory->name)));
directory->children = NO_CHILDREN;
/* If there is any dumpdir info in that directory, remove it */
if (directory->dump)
{
dumpdir_free (directory->dump);
directory->dump = NULL;
}
perhaps_renamed = false;
}
else if (flag & PD_FORCE_CHILDREN)
{
directory->children = PD_CHILDREN(flag);
@@ -559,6 +582,11 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
*entry = 'N';
}
if (perhaps_renamed)
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0, _("%s: Directory has been renamed"),
quotearg_colon (name_buffer)));
DIR_SET_FLAG (directory, DIRF_INIT);
if (directory->children != NO_CHILDREN)
@@ -581,6 +609,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
exclusion_tag_warning (name_buffer, tag_file_name,
_("contents not dumped"));
directory->children = NO_CHILDREN;
directory->tagfile = tag_file_name;
break;
case exclusion_tag_under:
@@ -652,15 +681,13 @@ makedumpdir (struct directory *directory, const char *dir)
if (loc)
{
if (directory->tagfile)
*new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
' ' : 'I';
*new_dump_ptr = 'I';
else
*new_dump_ptr = ' ';
new_dump_ptr++;
}
else if (directory->tagfile)
*new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
' ' : 'I';
*new_dump_ptr++ = 'I';
else
*new_dump_ptr++ = 'Y'; /* New entry */
@@ -671,9 +698,26 @@ makedumpdir (struct directory *directory, const char *dir)
*new_dump_ptr = 0;
directory->idump = directory->dump;
directory->dump = dumpdir_create0 (new_dump, NULL);
free (new_dump);
free (array);
}
/* Create a dumpdir containing only one entry: that for the
tagfile. */
static void
maketagdumpdir (struct directory *directory)
{
size_t len = strlen (directory->tagfile) + 1;
char *new_dump = xmalloc (len + 2);
new_dump[0] = 'Y';
memcpy (new_dump + 1, directory->tagfile, len);
new_dump[len + 1] = 0;
directory->idump = directory->dump;
directory->dump = dumpdir_create0 (new_dump, NULL);
free (new_dump);
}
/* Recursively scan the directory identified by ST. */
struct directory *
scan_directory (struct tar_stat_info *st)
@@ -690,6 +734,8 @@ scan_directory (struct tar_stat_info *st)
if (! dirp)
savedir_error (dir);
info_attach_exclist (st);
tmp = xstrdup (dir);
zap_slashes (tmp);
@@ -701,90 +747,97 @@ scan_directory (struct tar_stat_info *st)
nbuf = namebuf_create (dir);
if (dirp && directory->children != NO_CHILDREN)
if (dirp)
{
char *entry; /* directory entry being scanned */
struct dumpdir_iter *itr;
makedumpdir (directory, dirp);
for (entry = dumpdir_first (directory->dump, 1, &itr);
entry;
entry = dumpdir_next (itr))
if (directory->children != NO_CHILDREN)
{
char *full_name = namebuf_name (nbuf, entry + 1);
char *entry; /* directory entry being scanned */
struct dumpdir_iter *itr;
if (*entry == 'I') /* Ignored entry */
*entry = 'N';
else if (excluded_name (full_name))
*entry = 'N';
else
makedumpdir (directory, dirp);
for (entry = dumpdir_first (directory->dump, 1, &itr);
entry;
entry = dumpdir_next (itr))
{
int fd = st->fd;
void (*diag) (char const *) = 0;
struct tar_stat_info stsub;
tar_stat_init (&stsub);
char *full_name = namebuf_name (nbuf, entry + 1);
if (fd < 0)
{
errno = - fd;
diag = open_diag;
}
else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0)
diag = stat_diag;
else if (S_ISDIR (stsub.stat.st_mode))
{
int subfd = subfile_open (st, entry + 1, open_read_flags);
if (subfd < 0)
diag = open_diag;
else
{
stsub.fd = subfd;
if (fstat (subfd, &stsub.stat) != 0)
diag = stat_diag;
}
}
if (diag)
{
file_removed_diag (full_name, false, diag);
*entry = 'N';
}
else if (S_ISDIR (stsub.stat.st_mode))
{
int pd_flag = 0;
if (!recursion_option)
pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
else if (directory->children == ALL_CHILDREN)
pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
*entry = 'D';
stsub.parent = st;
procdir (full_name, &stsub, pd_flag, entry);
restore_parent_fd (&stsub);
}
else if (one_file_system_option && device != stsub.stat.st_dev)
if (*entry == 'I') /* Ignored entry */
*entry = 'N';
else if (*entry == 'Y')
/* New entry, skip further checks */;
/* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
else if (OLDER_STAT_TIME (stsub.stat, m)
&& (!after_date_option
|| OLDER_STAT_TIME (stsub.stat, c)))
else if (excluded_name (full_name, st))
*entry = 'N';
else
*entry = 'Y';
{
int fd = st->fd;
void (*diag) (char const *) = 0;
struct tar_stat_info stsub;
tar_stat_init (&stsub);
tar_stat_destroy (&stsub);
if (fd < 0)
{
errno = - fd;
diag = open_diag;
}
else if (fstatat (fd, entry + 1, &stsub.stat,
fstatat_flags) != 0)
diag = stat_diag;
else if (S_ISDIR (stsub.stat.st_mode))
{
int subfd = subfile_open (st, entry + 1,
open_read_flags);
if (subfd < 0)
diag = open_diag;
else
{
stsub.fd = subfd;
if (fstat (subfd, &stsub.stat) != 0)
diag = stat_diag;
}
}
if (diag)
{
file_removed_diag (full_name, false, diag);
*entry = 'N';
}
else if (S_ISDIR (stsub.stat.st_mode))
{
int pd_flag = 0;
if (!recursion_option)
pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
else if (directory->children == ALL_CHILDREN)
pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
*entry = 'D';
stsub.parent = st;
procdir (full_name, &stsub, pd_flag, entry);
restore_parent_fd (&stsub);
}
else if (one_file_system_option &&
device != stsub.stat.st_dev)
*entry = 'N';
else if (*entry == 'Y')
/* New entry, skip further checks */;
/* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
else if (OLDER_STAT_TIME (stsub.stat, m)
&& (!after_date_option
|| OLDER_STAT_TIME (stsub.stat, c)))
*entry = 'N';
else
*entry = 'Y';
tar_stat_destroy (&stsub);
}
}
free (itr);
}
free (itr);
else if (directory->tagfile)
maketagdumpdir (directory);
}
namebuf_free (nbuf);
if (dirp)
free (dirp);
free (dirp);
return directory;
}
@@ -834,7 +887,7 @@ store_rename (struct directory *dir, struct obstack *stk)
are ignored when hit by this function next time.
If the chain forms a cycle, prev points to the entry DIR is renamed
from. In this case it still retains DIRF_RENAMED flag, which will be
cleared in the `else' branch below */
cleared in the 'else' branch below */
for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
@@ -920,8 +973,6 @@ read_incr_db_01 (int version, const char *initbuf)
{
int n;
uintmax_t u;
time_t sec;
long int nsec;
char *buf = NULL;
size_t bufsize = 0;
char *ebuf;
@@ -943,21 +994,15 @@ read_incr_db_01 (int version, const char *initbuf)
bufsize = strlen (buf) + 1;
}
sec = TYPE_MINIMUM (time_t);
nsec = -1;
errno = 0;
u = strtoumax (buf, &ebuf, 10);
if (!errno && TYPE_MAXIMUM (time_t) < u)
errno = ERANGE;
if (errno || buf == ebuf)
newer_mtime_option = decode_timespec (buf, &ebuf, false);
if (! valid_timespec (newer_mtime_option))
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option),
lineno,
_("Invalid time stamp")));
else
{
sec = u;
if (version == 1 && *ebuf)
{
char const *buf_ns = ebuf + 1;
@@ -971,20 +1016,13 @@ read_incr_db_01 (int version, const char *initbuf)
quotearg_colon (listed_incremental_option),
lineno,
_("Invalid time stamp")));
sec = TYPE_MINIMUM (time_t);
newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
newer_mtime_option.tv_nsec = -1;
}
else
nsec = u;
}
else
{
/* pre-1 incremental format does not contain nanoseconds */
nsec = 0;
newer_mtime_option.tv_nsec = u;
}
}
newer_mtime_option.tv_sec = sec;
newer_mtime_option.tv_nsec = nsec;
while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
{
@@ -1001,20 +1039,12 @@ read_incr_db_01 (int version, const char *initbuf)
if (version == 1)
{
errno = 0;
u = strtoumax (strp, &ebuf, 10);
if (!errno && TYPE_MAXIMUM (time_t) < u)
errno = ERANGE;
if (errno || strp == ebuf || *ebuf != ' ')
{
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time (seconds)")));
sec = (time_t) -1;
}
else
sec = u;
mtime = decode_timespec (strp, &ebuf, false);
strp = ebuf;
if (!valid_timespec (mtime) || *strp != ' ')
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time")));
errno = 0;
u = strtoumax (strp, &ebuf, 10);
@@ -1025,46 +1055,30 @@ read_incr_db_01 (int version, const char *initbuf)
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time (nanoseconds)")));
nsec = -1;
mtime.tv_nsec = -1;
}
else
nsec = u;
mtime.tv_sec = sec;
mtime.tv_nsec = nsec;
mtime.tv_nsec = u;
strp = ebuf;
}
else
memset (&mtime, 0, sizeof mtime);
mtime.tv_sec = mtime.tv_nsec = 0;
errno = 0;
u = strtoumax (strp, &ebuf, 10);
if (!errno && TYPE_MAXIMUM (dev_t) < u)
errno = ERANGE;
if (errno || strp == ebuf || *ebuf != ' ')
{
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid device number")));
dev = (dev_t) -1;
}
else
dev = u;
dev = strtosysint (strp, &ebuf,
TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t));
strp = ebuf;
if (errno || *strp != ' ')
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid device number")));
errno = 0;
u = strtoumax (strp, &ebuf, 10);
if (!errno && TYPE_MAXIMUM (ino_t) < u)
errno = ERANGE;
if (errno || strp == ebuf || *ebuf != ' ')
{
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid inode number")));
ino = (ino_t) -1;
}
else
ino = u;
ino = strtosysint (strp, &ebuf,
TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t));
strp = ebuf;
if (errno || *strp != ' ')
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid inode number")));
strp++;
unquote_string (strp);
@@ -1091,97 +1105,84 @@ read_obstack (FILE *fp, struct obstack *stk, size_t *pcount)
return c;
}
/* Read from file FP a nul-terminated string and convert it to
intmax_t. Return the resulting value in PVAL. Assume '-' has
already been read.
/* Read from file FP a null-terminated string and convert it to an
integer. FIELDNAME is the intended use of the integer, useful for
diagnostics. MIN_VAL and MAX_VAL are its minimum and maximum
permissible values; MIN_VAL must be nonpositive and MAX_VAL positive.
Store into *PVAL the resulting value, converted to intmax_t.
Throw a fatal error if the string cannot be converted or if the
converted value is less than MIN_VAL. */
converted value is out of range.
static void
read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
Return true if successful, false if end of file. */
static bool
read_num (FILE *fp, char const *fieldname,
intmax_t min_val, uintmax_t max_val, intmax_t *pval)
{
int c;
size_t i;
int i;
char buf[INT_BUFSIZE_BOUND (intmax_t)];
char *ep;
buf[0] = '-';
char offbuf[INT_BUFSIZE_BOUND (off_t)];
char minbuf[INT_BUFSIZE_BOUND (intmax_t)];
char maxbuf[INT_BUFSIZE_BOUND (intmax_t)];
int conversion_errno;
int c = getc (fp);
bool negative = c == '-';
for (i = 1; ISDIGIT (c = getc (fp)); i++)
for (i = 0; (i == 0 && negative) || ISDIGIT (c); i++)
{
if (i == sizeof buf - 1)
FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
buf[i] = c;
}
if (c < 0)
{
if (ferror (fp))
FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
else
FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
}
buf[i] = 0;
errno = 0;
*pval = strtoimax (buf, &ep, 10);
if (c || errno || *pval < min_val)
FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
}
/* Read from file FP a nul-terminated string and convert it to
uintmax_t. Return the resulting value in PVAL. Assume C has
already been read.
Throw a fatal error if the string cannot be converted or if the
converted value exceeds MAX_VAL.
Return the last character read or EOF on end of file. */
static int
read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
{
size_t i;
char buf[UINTMAX_STRSIZE_BOUND], *ep;
for (i = 0; ISDIGIT (c); i++)
{
if (i == sizeof buf - 1)
FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
buf[i] = c;
FATAL_ERROR ((0, 0,
_("%s: byte %s: %s %.*s... too long"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (fp), offbuf),
fieldname, i + 1, buf));
c = getc (fp);
}
buf[i] = 0;
if (c < 0)
{
if (ferror (fp))
FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
else if (i == 0)
return c;
else
FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
read_fatal (listed_incremental_option);
if (i != 0)
FATAL_ERROR ((0, 0, "%s: %s",
quotearg_colon (listed_incremental_option),
_("Unexpected EOF in snapshot file")));
return false;
}
buf[i] = 0;
errno = 0;
*pval = strtoumax (buf, &ep, 10);
if (c || errno || max_val < *pval)
FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
return c;
}
if (c)
FATAL_ERROR ((0, 0,
_("%s: byte %s: %s %s followed by invalid byte 0x%02x"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (fp), offbuf),
fieldname, buf, c));
/* Read from file FP a nul-terminated string and convert it to
uintmax_t. Return the resulting value in PVAL.
*pval = strtosysint (buf, NULL, min_val, max_val);
conversion_errno = errno;
Throw a fatal error if the string cannot be converted or if the
converted value exceeds MAX_VAL.
switch (conversion_errno)
{
case ERANGE:
FATAL_ERROR ((0, conversion_errno,
_("%s: byte %s: (valid range %s..%s)\n\t%s %s"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (fp), offbuf),
imaxtostr (min_val, minbuf),
umaxtostr (max_val, maxbuf), fieldname, buf));
default:
FATAL_ERROR ((0, conversion_errno,
_("%s: byte %s: %s %s"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (fp), offbuf), fieldname, buf));
case 0:
break;
}
Return the last character read or EOF on end of file. */
static int
read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
{
return read_unsigned_num (getc (fp), fp, max_val, pval);
return true;
}
/* Read from FP two NUL-terminated strings representing a struct
@@ -1192,35 +1193,28 @@ read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
static void
read_timespec (FILE *fp, struct timespec *pval)
{
int c = getc (fp);
intmax_t i;
uintmax_t u;
intmax_t s, ns;
if (c == '-')
if (read_num (fp, "sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &s)
&& read_num (fp, "nsec", 0, BILLION - 1, &ns))
{
read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
c = 0;
pval->tv_sec = i;
pval->tv_sec = s;
pval->tv_nsec = ns;
}
else
{
c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
pval->tv_sec = u;
FATAL_ERROR ((0, 0, "%s: %s",
quotearg_colon (listed_incremental_option),
_("Unexpected EOF in snapshot file")));
}
if (c || read_num (fp, BILLION - 1, &u))
FATAL_ERROR ((0, 0, "%s: %s",
quotearg_colon (listed_incremental_option),
_("Unexpected EOF in snapshot file")));
pval->tv_nsec = u;
}
/* Read incremental snapshot format 2 */
static void
read_incr_db_2 (void)
{
uintmax_t u;
struct obstack stk;
char offbuf[INT_BUFSIZE_BOUND (off_t)];
obstack_init (&stk);
@@ -1228,6 +1222,7 @@ read_incr_db_2 (void)
for (;;)
{
intmax_t i;
struct timespec mtime;
dev_t dev;
ino_t ino;
@@ -1236,20 +1231,22 @@ read_incr_db_2 (void)
char *content;
size_t s;
if (read_num (listed_incremental_stream, 1, &u))
if (! read_num (listed_incremental_stream, "nfs", 0, 1, &i))
return; /* Normal return */
nfs = u;
nfs = i;
read_timespec (listed_incremental_stream, &mtime);
if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
if (! read_num (listed_incremental_stream, "dev",
TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i))
break;
dev = u;
dev = i;
if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
if (! read_num (listed_incremental_stream, "ino",
TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i))
break;
ino = u;
ino = i;
if (read_obstack (listed_incremental_stream, &stk, &s))
break;
@@ -1259,8 +1256,9 @@ read_incr_db_2 (void)
while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
;
if (getc (listed_incremental_stream) != 0)
FATAL_ERROR ((0, 0, "%s: %s",
FATAL_ERROR ((0, 0, _("%s: byte %s: %s"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (listed_incremental_stream), offbuf),
_("Missing record terminator")));
content = obstack_finish (&stk);
@@ -1272,6 +1270,51 @@ read_incr_db_2 (void)
_("Unexpected EOF in snapshot file")));
}
/* Display (to stdout) the range of allowed values for each field
in the snapshot file. The array below should be kept in sync
with any changes made to the read_num() calls in the parsing
loop inside read_incr_db_2().
(This function is invoked via the --show-snapshot-field-ranges
command line option.) */
struct field_range
{
char const *fieldname;
intmax_t min_val;
uintmax_t max_val;
};
static struct field_range const field_ranges[] = {
{ "nfs", 0, 1 },
{ "timestamp_sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t) },
{ "timestamp_nsec", 0, BILLION - 1 },
{ "dev", TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t) },
{ "ino", TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t) },
{ NULL, 0, 0 }
};
void
show_snapshot_field_ranges (void)
{
struct field_range const *p;
char minbuf[SYSINT_BUFSIZE];
char maxbuf[SYSINT_BUFSIZE];
printf("This tar's snapshot file field ranges are\n");
printf (" (%-15s => [ %s, %s ]):\n\n", "field name", "min", "max");
for (p=field_ranges; p->fieldname != NULL; p++)
{
printf (" %-15s => [ %s, %s ],\n", p->fieldname,
sysinttostr (p->min_val, p->min_val, p->max_val, minbuf),
sysinttostr (p->max_val, p->min_val, p->max_val, maxbuf));
}
printf("\n");
}
/* Read incremental snapshot file (directory file).
If the file has older incremental version, make sure that it is processed
correctly and that tar will use the most conservative backup method among
@@ -1352,8 +1395,7 @@ read_directory_file (void)
if (ferror (listed_incremental_stream))
read_error (listed_incremental_option);
if (buf)
free (buf);
free (buf);
}
/* Output incremental data for the directory ENTRY to the file DATA.
@@ -1366,20 +1408,21 @@ write_directory_file_entry (void *entry, void *data)
if (DIR_IS_FOUND (directory))
{
char buf[UINTMAX_STRSIZE_BOUND];
char buf[SYSINT_BUFSIZE];
char const *s;
s = DIR_IS_NFS (directory) ? "1" : "0";
fwrite (s, 2, 1, fp);
s = (TYPE_SIGNED (time_t)
? imaxtostr (directory->mtime.tv_sec, buf)
: umaxtostr (directory->mtime.tv_sec, buf));
s = sysinttostr (directory->mtime.tv_sec, TYPE_MINIMUM (time_t),
TYPE_MAXIMUM (time_t), buf);
fwrite (s, strlen (s) + 1, 1, fp);
s = umaxtostr (directory->mtime.tv_nsec, buf);
s = imaxtostr (directory->mtime.tv_nsec, buf);
fwrite (s, strlen (s) + 1, 1, fp);
s = umaxtostr (directory->device_number, buf);
s = sysinttostr (directory->device_number,
TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf);
fwrite (s, strlen (s) + 1, 1, fp);
s = umaxtostr (directory->inode_number, buf);
s = sysinttostr (directory->inode_number,
TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), buf);
fwrite (s, strlen (s) + 1, 1, fp);
fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
@@ -1586,7 +1629,7 @@ try_purge_directory (char const *directory_name)
if (!is_dumpdir (&current_stat_info))
return false;
current_dir = savedir (directory_name);
current_dir = tar_savedir (directory_name, 0);
if (!current_dir)
/* The directory doesn't exist now. It'll be created. In any
@@ -1664,8 +1707,7 @@ try_purge_directory (char const *directory_name)
{
const char *entry;
struct stat st;
if (p)
free (p);
free (p);
p = new_name (directory_name, cur);
if (deref_stat (p, &st) != 0)

View File

@@ -1,23 +1,24 @@
/* List a tar archive, with support routines for reading a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014 Free
Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
This file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by John Gilmore, on 1985-08-26. */
#include <system.h>
#include <inttostr.h>
@@ -25,15 +26,13 @@
#include "common.h"
#define max(a, b) ((a) < (b) ? (b) : (a))
union block *current_header; /* points to current archive header */
enum archive_format current_format; /* recognized format */
union block *recent_long_name; /* recent long name header and contents */
union block *recent_long_link; /* likewise, for long link */
size_t recent_long_name_blocks; /* number of blocks in recent_long_name */
size_t recent_long_link_blocks; /* likewise, for long link */
union block *recent_global_header; /* Recent global header block */
static union block *recent_global_header; /* Recent global header block */
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
@@ -46,11 +45,11 @@ union block *recent_global_header; /* Recent global header block */
static gid_t gid_from_header (const char *buf, size_t size);
static major_t major_from_header (const char *buf, size_t size);
static minor_t minor_from_header (const char *buf, size_t size);
static mode_t mode_from_header (const char *buf, size_t size, unsigned *hbits);
static mode_t mode_from_header (const char *buf, size_t size, bool *hbits);
static time_t time_from_header (const char *buf, size_t size);
static uid_t uid_from_header (const char *buf, size_t size);
static uintmax_t from_header (const char *, size_t, const char *,
uintmax_t, uintmax_t, bool, bool);
static intmax_t from_header (const char *, size_t, const char *,
intmax_t, uintmax_t, bool, bool);
/* Base 64 digits; see Internet RFC 2045 Table 1. */
static char const base_64_digits[64] =
@@ -75,6 +74,93 @@ base64_init (void)
base64_map[(int) base_64_digits[i]] = i;
}
static char *
decode_xform (char *file_name, void *data)
{
int type = *(int*)data;
switch (type)
{
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
name suffix normalization, but subject to filename transformation
proper. */
return file_name;
case XFORM_LINK:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case XFORM_REGFILE:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
prefix_len = strlen (file_name);
file_name += prefix_len;
}
return file_name;
}
static bool
transform_member_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, decode_xform, &type);
}
static void
enforce_one_top_level (char **pfile_name)
{
char *file_name = *pfile_name;
char *p;
for (p = file_name; *p && (ISSLASH (*p) || *p == '.'); p++)
;
if (!*p)
return;
if (strncmp (p, one_top_level_dir, strlen (one_top_level_dir)) == 0)
{
int pos = strlen (one_top_level_dir);
if (ISSLASH (p[pos]) || p[pos] == 0)
return;
}
*pfile_name = new_name (one_top_level_dir, file_name);
normalize_filename_x (*pfile_name);
free (file_name);
}
void
transform_stat_info (int typeflag, struct tar_stat_info *stat_info)
{
if (typeflag == GNUTYPE_VOLHDR)
/* Name transformations don't apply to volume headers. */
return;
transform_member_name (&stat_info->file_name, XFORM_REGFILE);
switch (typeflag)
{
case SYMTYPE:
transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
break;
case LNKTYPE:
transform_member_name (&stat_info->link_name, XFORM_LINK);
}
if (one_top_level_option)
enforce_one_top_level (&current_stat_info.file_name);
}
/* Main loop for reading an archive. */
void
read_and (void (*do_something) (void))
@@ -117,7 +203,8 @@ read_and (void (*do_something) (void))
mtime.tv_nsec = 0,
current_stat_info.mtime = mtime,
OLDER_TAR_STAT_TIME (current_stat_info, m)))
|| excluded_name (current_stat_info.file_name))
|| excluded_name (current_stat_info.file_name,
current_stat_info.parent))
{
switch (current_header->header.typeflag)
{
@@ -136,6 +223,8 @@ read_and (void (*do_something) (void))
}
}
transform_stat_info (current_header->header.typeflag,
&current_stat_info);
(*do_something) ();
continue;
@@ -256,7 +345,7 @@ tar_checksum (union block *header, bool silent)
int unsigned_sum = 0; /* the POSIX one :-) */
int signed_sum = 0; /* the Sun one :-( */
int recorded_sum;
uintmax_t parsed_sum;
int parsed_sum;
char *p;
p = header->buffer;
@@ -281,9 +370,8 @@ tar_checksum (union block *header, bool silent)
parsed_sum = from_header (header->header.chksum,
sizeof header->header.chksum, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (int), true, silent);
if (parsed_sum == (uintmax_t) -1)
0, INT_MAX, true, silent);
if (parsed_sum < 0)
return HEADER_FAILURE;
recorded_sum = parsed_sum;
@@ -346,7 +434,11 @@ read_header (union block **return_block, struct tar_stat_info *info,
if (header->header.typeflag == LNKTYPE)
info->stat.st_size = 0; /* links 0 size on tape */
else
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
{
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
if (info->stat.st_size < 0)
return HEADER_FAILURE;
}
if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK
@@ -372,15 +464,13 @@ read_header (union block **return_block, struct tar_stat_info *info,
if (header->header.typeflag == GNUTYPE_LONGNAME)
{
if (next_long_name)
free (next_long_name);
free (next_long_name);
next_long_name = header_copy;
next_long_name_blocks = size / BLOCKSIZE;
}
else
{
if (next_long_link)
free (next_long_link);
free (next_long_link);
next_long_link = header_copy;
next_long_link_blocks = size / BLOCKSIZE;
}
@@ -439,8 +529,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
struct posix_header const *h = &header->header;
char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
if (recent_long_name)
free (recent_long_name);
free (recent_long_name);
if (next_long_name)
{
@@ -471,8 +560,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
assign_string (&info->file_name, name);
info->had_trailing_slash = strip_trailing_slashes (info->file_name);
if (recent_long_link)
free (recent_long_link);
free (recent_long_link);
if (next_long_link)
{
@@ -495,47 +583,6 @@ read_header (union block **return_block, struct tar_stat_info *info,
}
}
static char *
decode_xform (char *file_name, void *data)
{
int type = *(int*)data;
switch (type)
{
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
name suffix normalization, but subject to filename transformation
proper. */
return file_name;
case XFORM_LINK:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case XFORM_REGFILE:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
prefix_len = strlen (file_name);
file_name += prefix_len;
}
return file_name;
}
static bool
transform_member_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, decode_xform, &type);
}
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
/* Decode things from a file HEADER block into STAT_INFO, also setting
@@ -556,7 +603,7 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group)
{
enum archive_format format;
unsigned hbits; /* high bits of the file mode. */
bool hbits;
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
if (strcmp (header->header.magic, TMAGIC) == 0)
@@ -572,7 +619,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
else
format = USTAR_FORMAT;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
else if (strcmp (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC)
== 0)
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
else
format = V7_FORMAT;
@@ -586,6 +635,8 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
assign_string (&stat_info->gname,
header->header.gname[0] ? header->header.gname : NULL);
xheader_xattr_init (stat_info);
if (format == OLDGNU_FORMAT && incremental_option)
{
stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
@@ -655,38 +706,34 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|| stat_info->dumpdir)
stat_info->is_dumpdir = true;
}
if (header->header.typeflag == GNUTYPE_VOLHDR)
/* Name transformations don't apply to volume headers. */
return;
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
uintmax_t. DIGS must be positive. If TYPE is nonnull, the data
are of type TYPE. The buffer must represent a value in the range
-MINUS_MINVAL through MAXVAL. If OCTAL_ONLY, allow only octal
intmax_t. DIGS must be positive. If TYPE is nonnull, the data are
of type TYPE. The buffer must represent a value in the range
MINVAL through MAXVAL; if the mathematically correct result V would
be greater than INTMAX_MAX, return a negative integer V such that
(uintmax_t) V yields the correct result. If OCTAL_ONLY, allow only octal
numbers instead of the other GNU extensions. Return -1 on error,
diagnosing the error if TYPE is nonnull and if !SILENT. */
static uintmax_t
#if ! (INTMAX_MAX <= UINTMAX_MAX && - (INTMAX_MIN + 1) <= UINTMAX_MAX)
# error "from_header internally represents intmax_t as uintmax_t + sign"
#endif
#if ! (UINTMAX_MAX / 2 <= INTMAX_MAX)
# error "from_header returns intmax_t to represent uintmax_t"
#endif
static intmax_t
from_header (char const *where0, size_t digs, char const *type,
uintmax_t minus_minval, uintmax_t maxval,
intmax_t minval, uintmax_t maxval,
bool octal_only, bool silent)
{
uintmax_t value;
uintmax_t uminval = minval;
uintmax_t minus_minval = - uminval;
char const *where = where0;
char const *lim = where + digs;
int negative = 0;
bool negative = false;
/* Accommodate buggy tar of unknown vintage, which outputs leading
NUL if the previous field overflows. */
@@ -705,7 +752,7 @@ from_header (char const *where0, size_t digs, char const *type,
type));
return -1;
}
if (!ISSPACE ((unsigned char) *where))
if (!isspace ((unsigned char) *where))
break;
where++;
}
@@ -714,14 +761,14 @@ from_header (char const *where0, size_t digs, char const *type,
if (ISODIGIT (*where))
{
char const *where1 = where;
uintmax_t overflow = 0;
bool overflow = false;
for (;;)
{
value += *where++ - '0';
if (where == lim || ! ISODIGIT (*where))
break;
overflow |= value ^ (value << LG_8 >> LG_8);
overflow |= value != (value << LG_8 >> LG_8);
value <<= LG_8;
}
@@ -745,7 +792,7 @@ from_header (char const *where0, size_t digs, char const *type,
if (where == lim || ! ISODIGIT (*where))
break;
digit = *where - '0';
overflow |= value ^ (value << LG_8 >> LG_8);
overflow |= value != (value << LG_8 >> LG_8);
value <<= LG_8;
}
value++;
@@ -758,7 +805,7 @@ from_header (char const *where0, size_t digs, char const *type,
/* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
_("Archive octal value %.*s is out of %s range; assuming two's complement"),
(int) (where - where1), where1, type));
negative = 1;
negative = true;
}
}
@@ -838,12 +885,12 @@ from_header (char const *where0, size_t digs, char const *type,
return -1;
}
}
negative = signbit;
negative = signbit != 0;
if (negative)
value = -value;
}
if (where != lim && *where && !ISSPACE ((unsigned char) *where))
if (where != lim && *where && !isspace ((unsigned char) *where))
{
if (type)
{
@@ -858,7 +905,7 @@ from_header (char const *where0, size_t digs, char const *type,
while (where0 != lim && ! lim[-1])
lim--;
quotearg_buffer (buf, sizeof buf, where0, lim - where, o);
quotearg_buffer (buf, sizeof buf, where0, lim - where0, o);
if (!silent)
ERROR ((0, 0,
/* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
@@ -870,7 +917,7 @@ from_header (char const *where0, size_t digs, char const *type,
}
if (value <= (negative ? minus_minval : maxval))
return negative ? -value : value;
return represent_uintmax (negative ? -value : value);
if (type && !silent)
{
@@ -896,8 +943,7 @@ static gid_t
gid_from_header (const char *p, size_t s)
{
return from_header (p, s, "gid_t",
- (uintmax_t) TYPE_MINIMUM (gid_t),
(uintmax_t) TYPE_MAXIMUM (gid_t),
TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t),
false, false);
}
@@ -905,26 +951,26 @@ static major_t
major_from_header (const char *p, size_t s)
{
return from_header (p, s, "major_t",
- (uintmax_t) TYPE_MINIMUM (major_t),
(uintmax_t) TYPE_MAXIMUM (major_t), false, false);
TYPE_MINIMUM (major_t), TYPE_MAXIMUM (major_t),
false, false);
}
static minor_t
minor_from_header (const char *p, size_t s)
{
return from_header (p, s, "minor_t",
- (uintmax_t) TYPE_MINIMUM (minor_t),
(uintmax_t) TYPE_MAXIMUM (minor_t), false, false);
TYPE_MINIMUM (minor_t), TYPE_MAXIMUM (minor_t),
false, false);
}
/* Convert P to the file mode, as understood by tar.
Store unrecognized mode bits (from 10th up) in HBITS. */
Set *HBITS if there are any unrecognized bits. */
static mode_t
mode_from_header (const char *p, size_t s, unsigned *hbits)
mode_from_header (const char *p, size_t s, bool *hbits)
{
unsigned u = from_header (p, s, "mode_t",
- (uintmax_t) TYPE_MINIMUM (mode_t),
TYPE_MAXIMUM (uintmax_t), false, false);
intmax_t u = from_header (p, s, "mode_t",
INTMAX_MIN, UINTMAX_MAX,
false, false);
mode_t mode = ((u & TSUID ? S_ISUID : 0)
| (u & TSGID ? S_ISGID : 0)
| (u & TSVTX ? S_ISVTX : 0)
@@ -937,7 +983,7 @@ mode_from_header (const char *p, size_t s, unsigned *hbits)
| (u & TOREAD ? S_IROTH : 0)
| (u & TOWRITE ? S_IWOTH : 0)
| (u & TOEXEC ? S_IXOTH : 0));
*hbits = mode ^ u;
*hbits = (u & ~07777) != 0;
return mode;
}
@@ -946,31 +992,31 @@ off_from_header (const char *p, size_t s)
{
/* Negative offsets are not allowed in tar files, so invoke
from_header with minimum value 0, not TYPE_MINIMUM (off_t). */
return from_header (p, s, "off_t", (uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (off_t), false, false);
return from_header (p, s, "off_t",
0, TYPE_MAXIMUM (off_t),
false, false);
}
static time_t
time_from_header (const char *p, size_t s)
{
return from_header (p, s, "time_t",
- (uintmax_t) TYPE_MINIMUM (time_t),
(uintmax_t) TYPE_MAXIMUM (time_t), false, false);
TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t),
false, false);
}
static uid_t
uid_from_header (const char *p, size_t s)
{
return from_header (p, s, "uid_t",
- (uintmax_t) TYPE_MINIMUM (uid_t),
(uintmax_t) TYPE_MAXIMUM (uid_t), false, false);
TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t),
false, false);
}
uintmax_t
uintmax_from_header (const char *p, size_t s)
{
return from_header (p, s, "uintmax_t", (uintmax_t) 0,
TYPE_MAXIMUM (uintmax_t), false, false);
return from_header (p, s, "uintmax_t", 0, UINTMAX_MAX, false, false);
}
@@ -1060,13 +1106,14 @@ static void
simple_print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal)
{
char modes[11];
char modes[12];
char const *time_stamp;
int time_stamp_len;
char *temp_name;
/* These hold formatted ints. */
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
char uform[max (INT_BUFSIZE_BOUND (intmax_t), UINTMAX_STRSIZE_BOUND)];
char gform[sizeof uform];
char *user, *group;
char size[2 * UINTMAX_STRSIZE_BOUND];
/* holds formatted size or major,minor */
@@ -1093,7 +1140,10 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
if (verbose_option <= 1)
{
/* Just the fax, mam. */
fprintf (stdlis, "%s\n", quotearg (temp_name));
fputs (quotearg (temp_name), stdlis);
if (show_transformed_names_option && st->had_trailing_slash)
fputc ('/', stdlis);
fputc ('\n', stdlis);
}
else
{
@@ -1120,9 +1170,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
case GNUTYPE_SPARSE:
case REGTYPE:
case AREGTYPE:
modes[0] = '-';
if (temp_name[strlen (temp_name) - 1] == '/')
modes[0] = 'd';
modes[0] = st->had_trailing_slash ? 'd' : '-';
break;
case LNKTYPE:
modes[0] = 'h';
@@ -1152,6 +1200,9 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
pax_decode_mode (st->stat.st_mode, modes + 1);
/* extended attributes: GNU `ls -l'-like preview */
xattrs_print_char (st, modes + 10);
/* Time stamp. */
time_stamp = tartime (st->mtime, full_time_option);
@@ -1173,17 +1224,11 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
ids that are too large to fit in a uid_t. */
uintmax_t u = from_header (blk->header.uid,
sizeof blk->header.uid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
0, UINTMAX_MAX,
false, false);
if (u != -1)
user = STRINGIFY_BIGINT (u, uform);
else
{
sprintf (uform, "%ld",
(long) UID_FROM_HEADER (blk->header.uid));
user = uform;
}
user = (u != -1
? STRINGIFY_BIGINT (u, uform)
: imaxtostr (UID_FROM_HEADER (blk->header.uid), uform));
}
if (st->gname
@@ -1198,17 +1243,11 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
ids that are too large to fit in a gid_t. */
uintmax_t g = from_header (blk->header.gid,
sizeof blk->header.gid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
0, UINTMAX_MAX,
false, false);
if (g != -1)
group = STRINGIFY_BIGINT (g, gform);
else
{
sprintf (gform, "%ld",
(long) GID_FROM_HEADER (blk->header.gid));
group = gform;
}
group = (g != -1
? STRINGIFY_BIGINT (g, gform)
: imaxtostr (GID_FROM_HEADER (blk->header.gid), gform));
}
/* Format the file size or major/minor device numbers. */
@@ -1242,6 +1281,8 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
datewidth, time_stamp);
fprintf (stdlis, " %s", quotearg (temp_name));
if (show_transformed_names_option && st->had_trailing_slash)
fputc ('/', stdlis);
switch (blk->header.typeflag)
{
@@ -1297,6 +1338,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
}
}
fflush (stdlis);
xattrs_print (st);
}
@@ -1353,8 +1395,8 @@ print_for_mkdir (char *dirname, int length, mode_t mode)
STRINGIFY_BIGINT (current_block_ordinal (), buf));
}
fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + 1 + datewidth,
_("Creating directory:"), length, quotearg (dirname));
fprintf (stdlis, "%s %*s %s\n", modes, ugswidth + 1 + datewidth,
_("Creating directory:"), quotearg (dirname));
}
}
@@ -1411,7 +1453,7 @@ skip_member (void)
}
void
test_archive_label ()
test_archive_label (void)
{
base64_init ();
name_gather ();

View File

@@ -1,7 +1,7 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010,
2012-2014 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
@@ -14,9 +14,9 @@
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. */
with this program. If not, see <http://www.gnu.org/licenses/>. */
#define COMMON_INLINE _GL_EXTERN_INLINE
#include <system.h>
#include <rmt.h>
#include "common.h"
@@ -29,6 +29,8 @@
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
#endif
static const char *tar_getcdpath (int);
/* Handling strings. */
@@ -37,8 +39,7 @@
void
assign_string (char **string, const char *value)
{
if (*string)
free (*string);
free (*string);
*string = value ? xstrdup (value) : 0;
}
@@ -106,7 +107,7 @@ quote_copy_string (const char *string)
completes the unquoting anyway.
This is used for reading the saved directory file in incremental
dumps. It is used for decoding old `N' records (demangling names).
dumps. It is used for decoding old 'N' records (demangling names).
But also, it is used for decoding file arguments, would they come
from the shell or a -T file, and for decoding the --exclude
argument. */
@@ -230,11 +231,12 @@ zap_slashes (char *name)
}
/* Normalize FILE_NAME by removing redundant slashes and "."
components, including redundant trailing slashes. Leave ".."
alone, as it may be significant in the presence of symlinks and on
platforms where "/.." != "/". Destructive version: modifies its
argument. */
static void
components, including redundant trailing slashes.
Leave ".." alone, as it may be significant in the presence
of symlinks and on platforms where "/.." != "/".
Destructive version: modifies its argument. */
void
normalize_filename_x (char *file_name)
{
char *name = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
@@ -268,37 +270,42 @@ normalize_filename_x (char *file_name)
}
/* Normalize NAME by removing redundant slashes and "." components,
including redundant trailing slashes. Return a normalized
newly-allocated copy. */
including redundant trailing slashes.
Return a normalized newly-allocated copy. */
char *
normalize_filename (const char *name)
normalize_filename (int cdidx, const char *name)
{
char *copy = NULL;
if (IS_RELATIVE_FILE_NAME (name))
{
/* Set COPY to the absolute file name if possible.
/* Set COPY to the absolute path for this name.
FIXME: There should be no need to get the absolute file name.
getcwd is slow, it might fail, and it does not necessarily
return a canonical name even when it succeeds. Perhaps we
can use dev+ino pairs instead of names? */
copy = xgetcwd ();
if (copy)
{
size_t copylen = strlen (copy);
bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& copylen == 2 && ISSLASH (copy[1]));
copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1);
copy[copylen] = DIRECTORY_SEPARATOR;
strcpy (copy + copylen + need_separator, name);
}
else
WARN ((0, errno, _("Cannot get working directory")));
tar_getcdpath does not return a true "canonical" path, so
this following approach may lead to situations where the same
file or directory is processed twice under different absolute
paths without that duplication being detected. Perhaps we
should use dev+ino pairs instead of names? (See listed03.at for
a related test case.) */
const char *cdpath = tar_getcdpath (cdidx);
size_t copylen;
bool need_separator;
if (!cdpath)
call_arg_fatal ("getcwd", ".");
copylen = strlen (cdpath);
need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& copylen == 2 && ISSLASH (cdpath[1]));
copy = xmalloc (copylen + need_separator + strlen (name) + 1);
strcpy (copy, cdpath);
copy[copylen] = DIRECTORY_SEPARATOR;
strcpy (copy + copylen + need_separator, name);
}
if (! copy)
if (!copy)
copy = xstrdup (name);
normalize_filename_x (copy);
return copy;
@@ -326,6 +333,76 @@ replace_prefix (char **pname, const char *samp, size_t slen,
/* Handling numbers. */
/* Convert VALUE, which is converted from a system integer type whose
minimum value is MINVAL and maximum MINVAL, to an decimal
integer string. Use the storage in BUF and return a pointer to the
converted string. If VALUE is converted from a negative integer in
the range MINVAL .. -1, represent it with a string representation
of the negative integer, using leading '-'. */
#if ! (INTMAX_MAX <= UINTMAX_MAX / 2)
# error "sysinttostr: uintmax_t cannot represent all intmax_t values"
#endif
char *
sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval,
char buf[SYSINT_BUFSIZE])
{
if (value <= maxval)
return umaxtostr (value, buf);
else
{
intmax_t i = value - minval;
return imaxtostr (i + minval, buf);
}
}
/* Convert a prefix of the string ARG to a system integer type whose
minimum value is MINVAL and maximum MAXVAL. If MINVAL is negative,
negative integers MINVAL .. -1 are assumed to be represented using
leading '-' in the usual way. If the represented value exceeds
INTMAX_MAX, return a negative integer V such that (uintmax_t) V
yields the represented value. If ARGLIM is nonnull, store into
*ARGLIM a pointer to the first character after the prefix.
This is the inverse of sysinttostr.
On a normal return, set errno = 0.
On conversion error, return 0 and set errno = EINVAL.
On overflow, return an extreme value and set errno = ERANGE. */
#if ! (INTMAX_MAX <= UINTMAX_MAX)
# error "strtosysint: nonnegative intmax_t does not fit in uintmax_t"
#endif
intmax_t
strtosysint (char const *arg, char **arglim, intmax_t minval, uintmax_t maxval)
{
errno = 0;
if (maxval <= INTMAX_MAX)
{
if (ISDIGIT (arg[*arg == '-']))
{
intmax_t i = strtoimax (arg, arglim, 10);
intmax_t imaxval = maxval;
if (minval <= i && i <= imaxval)
return i;
errno = ERANGE;
return i < minval ? minval : maxval;
}
}
else
{
if (ISDIGIT (*arg))
{
uintmax_t i = strtoumax (arg, arglim, 10);
if (i <= maxval)
return represent_uintmax (i);
errno = ERANGE;
return maxval;
}
}
errno = EINVAL;
return 0;
}
/* Output fraction and trailing digits appropriate for a nanoseconds
count equal to NS, but don't output unnecessary '.' or trailing
zeros. */
@@ -382,6 +459,84 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND);
return np;
}
struct timespec
decode_timespec (char const *arg, char **arg_lim, bool parse_fraction)
{
time_t s = TYPE_MINIMUM (time_t);
int ns = -1;
char const *p = arg;
bool negative = *arg == '-';
struct timespec r;
if (! ISDIGIT (arg[negative]))
errno = EINVAL;
else
{
errno = 0;
if (negative)
{
intmax_t i = strtoimax (arg, arg_lim, 10);
if (TYPE_SIGNED (time_t) ? TYPE_MINIMUM (time_t) <= i : 0 <= i)
s = i;
else
errno = ERANGE;
}
else
{
uintmax_t i = strtoumax (arg, arg_lim, 10);
if (i <= TYPE_MAXIMUM (time_t))
s = i;
else
errno = ERANGE;
}
p = *arg_lim;
ns = 0;
if (parse_fraction && *p == '.')
{
int digits = 0;
bool trailing_nonzero = false;
while (ISDIGIT (*++p))
if (digits < LOG10_BILLION)
digits++, ns = 10 * ns + (*p - '0');
else
trailing_nonzero |= *p != '0';
while (digits < LOG10_BILLION)
digits++, ns *= 10;
if (negative)
{
/* Convert "-1.10000000000001" to s == -2, ns == 89999999.
I.e., truncate time stamps towards minus infinity while
converting them to internal form. */
ns += trailing_nonzero;
if (ns != 0)
{
if (s == TYPE_MINIMUM (time_t))
ns = -1;
else
{
s--;
ns = BILLION - ns;
}
}
}
}
if (errno == ERANGE)
ns = -1;
}
*arg_lim = (char *) p;
r.tv_sec = s;
r.tv_nsec = ns;
return r;
}
/* File handling. */
@@ -484,7 +639,7 @@ remove_any_file (const char *file_name, enum remove_option option)
case RECURSIVE_REMOVE_OPTION:
{
char *directory = savedir (file_name);
char *directory = tar_savedir (file_name, 0);
char const *entry;
size_t entrylen;
@@ -617,6 +772,57 @@ deref_stat (char const *name, struct stat *buf)
return fstatat (chdir_fd, name, buf, fstatat_flags);
}
/* Read from FD into the buffer BUF with COUNT bytes. Attempt to fill
BUF. Wait until input is available; this matters because files are
opened O_NONBLOCK for security reasons, and on some file systems
this can cause read to fail with errno == EAGAIN. Return the
actual number of bytes read, zero for EOF, or
SAFE_READ_ERROR upon error. */
size_t
blocking_read (int fd, void *buf, size_t count)
{
size_t bytes = safe_read (fd, buf, count);
#if defined F_SETFL && O_NONBLOCK
if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
{
int flags = fcntl (fd, F_GETFL);
if (0 <= flags && flags & O_NONBLOCK
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
bytes = safe_read (fd, buf, count);
}
#endif
return bytes;
}
/* Write to FD from the buffer BUF with COUNT bytes. Do a full write.
Wait until an output buffer is available; this matters because
files are opened O_NONBLOCK for security reasons, and on some file
systems this can cause write to fail with errno == EAGAIN. Return
the actual number of bytes written, setting errno if that is less
than COUNT. */
size_t
blocking_write (int fd, void const *buf, size_t count)
{
size_t bytes = full_write (fd, buf, count);
#if defined F_SETFL && O_NONBLOCK
if (bytes < count && errno == EAGAIN)
{
int flags = fcntl (fd, F_GETFL);
if (0 <= flags && flags & O_NONBLOCK
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
{
char const *buffer = buf;
bytes += full_write (fd, buffer + bytes, count - bytes);
}
}
#endif
return bytes;
}
/* Set FD's (i.e., assuming the working directory is PARENTFD, FILE's)
access time to ATIME. */
int
@@ -633,7 +839,11 @@ struct wd
{
/* The directory's name. */
char const *name;
/* "Absolute" path representing this directory; in the contrast to
the real absolute pathname, it can contain /../ components (see
normalize_filename_x for the reason of it). It is NULL if the
absolute path could not be determined. */
char *abspath;
/* If nonzero, the file descriptor of the directory, or AT_FDCWD if
the working directory. If zero, the directory needs to be opened
to be used. */
@@ -663,7 +873,7 @@ static int wdcache[CHDIR_CACHE_SIZE];
static size_t wdcache_count;
int
chdir_count ()
chdir_count (void)
{
if (wd_count == 0)
return wd_count;
@@ -675,19 +885,18 @@ chdir_count ()
int
chdir_arg (char const *dir)
{
char *absdir;
if (wd_count == wd_alloc)
{
if (wd_alloc == 0)
{
wd_alloc = 2;
wd = xmalloc (sizeof *wd * wd_alloc);
}
else
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
wd_alloc = 2;
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
if (! wd_count)
{
wd[wd_count].name = ".";
wd[wd_count].abspath = xgetcwd ();
wd[wd_count].fd = AT_FDCWD;
wd_count++;
}
@@ -704,7 +913,22 @@ chdir_arg (char const *dir)
return wd_count - 1;
}
/* If the given name is absolute, use it to represent this directory;
otherwise, construct a name based on the previous -C option. */
if (IS_ABSOLUTE_FILE_NAME (dir))
absdir = xstrdup (dir);
else if (wd[wd_count - 1].abspath)
{
namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
namebuf_add_dir (nbuf, dir);
absdir = namebuf_finish (nbuf);
}
else
absdir = 0;
wd[wd_count].name = dir;
wd[wd_count].abspath = absdir;
wd[wd_count].fd = 0;
return wd_count++;
}
@@ -764,11 +988,11 @@ chdir_do (int i)
int prev = wdcache[0];
for (ci = 1; prev != i; ci++)
{
int curr = wdcache[ci];
int cur = wdcache[ci];
wdcache[ci] = prev;
if (curr == i)
if (cur == i)
break;
prev = curr;
prev = cur;
}
wdcache[0] = i;
}
@@ -778,6 +1002,32 @@ chdir_do (int i)
}
}
const char *
tar_dirname (void)
{
return wd[chdir_current].name;
}
/* Return the absolute path that represents the working
directory referenced by IDX.
If wd is empty, then there were no -C options given, and
chdir_args() has never been called, so we simply return the
process's actual cwd. (Note that in this case IDX is ignored,
since it should always be 0.) */
static const char *
tar_getcdpath (int idx)
{
if (!wd)
{
static char *cwd;
if (!cwd)
cwd = xgetcwd ();
return cwd;
}
return wd[idx].abspath;
}
void
close_diag (char const *name)
{
@@ -856,21 +1106,6 @@ file_removed_diag (const char *name, bool top_level,
diagfn (name);
}
void
dir_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name))
{
if (!top_level && errno == ENOENT)
{
WARNOPT (WARN_FILE_REMOVED,
(0, 0, _("%s: Directory removed before we read it"),
quotearg_colon (name)));
set_exit_status (TAREXIT_DIFFERS);
}
else
diagfn (name);
}
void
write_fatal_details (char const *name, ssize_t status, size_t size)
{
@@ -927,7 +1162,7 @@ page_aligned_alloc (void **ptr, size_t size)
struct namebuf
{
char *buffer; /* directory, `/', and directory member */
char *buffer; /* directory, '/', and directory member */
size_t buffer_size; /* allocated size of name_buffer */
size_t dir_length; /* length of directory part in buffer */
};
@@ -961,3 +1196,55 @@ namebuf_name (namebuf_t buf, const char *name)
strcpy (buf->buffer + buf->dir_length, name);
return buf->buffer;
}
void
namebuf_add_dir (namebuf_t buf, const char *name)
{
static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
{
namebuf_name (buf, dirsep);
buf->dir_length++;
}
namebuf_name (buf, name);
buf->dir_length += strlen (name);
}
char *
namebuf_finish (namebuf_t buf)
{
char *res = buf->buffer;
if (ISSLASH (buf->buffer[buf->dir_length - 1]))
buf->buffer[buf->dir_length] = 0;
free (buf);
return res;
}
/* Return the filenames in directory NAME, relative to the chdir_fd.
If the directory does not exist, report error if MUST_EXIST is
true.
Return NULL on errors.
*/
char *
tar_savedir (const char *name, int must_exist)
{
char *ret = NULL;
DIR *dir = NULL;
int fd = openat (chdir_fd, name, open_read_flags | O_DIRECTORY);
if (fd < 0)
{
if (!must_exist && errno == ENOENT)
return NULL;
open_error (name);
}
else if (! ((dir = fdopendir (fd))
&& (ret = streamsavedir (dir, savedir_sort_order))))
savedir_error (name);
if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
savedir_error (name);
return ret;
}

View File

@@ -1,7 +1,7 @@
/* Various processing of names.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994, 1996-2001, 2003-2007, 2009, 2013-2014
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
@@ -14,14 +14,15 @@
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. */
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <fnmatch.h>
#include <hash.h>
#include <quotearg.h>
#include <wordsplit.h>
#include <argp.h>
#include "common.h"
@@ -47,8 +48,6 @@ static char *cached_no_such_gname;
static uid_t cached_no_such_uid;
static gid_t cached_no_such_gid;
static void register_individual_file (char const *name);
/* Given UID, find the corresponding UNAME. */
void
uid_to_uname (uid_t uid, char **uname)
@@ -199,7 +198,7 @@ static struct name *namelist; /* first name in list, if any */
static struct name *nametail; /* end of name list */
/* File name arguments are processed in two stages: first a
name_array (see below) is filled, then the names from it
name element list (see below) is filled, then the names from it
are moved into the namelist.
This awkward process is needed only to implement --same-order option,
@@ -209,39 +208,72 @@ static struct name *nametail; /* end of name list */
However, I very much doubt if we still need this -- Sergey */
/* A name_array element contains entries of three types: */
/* A name_list element contains entries of three types: */
#define NELT_NAME 0 /* File name */
#define NELT_CHDIR 1 /* Change directory request */
#define NELT_FMASK 2 /* Change fnmatch options request */
#define NELT_FILE 3 /* Read file names from that file */
#define NELT_NOOP 4 /* No operation */
struct name_elt /* A name_array element. */
{
struct name_elt *next, *prev;
char type; /* Element type, see NELT_* constants above */
union
{
const char *name; /* File or directory name */
int matching_flags;/* fnmatch options if type == NELT_FMASK */
struct /* File, if type == NELT_FILE */
{
const char *name;/* File name */
int term; /* File name terminator in the list */
FILE *fp;
} file;
} v;
};
static struct name_elt *name_array; /* store an array of names */
static size_t allocated_entries; /* how big is the array? */
static size_t entries; /* how many entries does it have? */
static size_t scanned; /* how many of the entries have we scanned? */
size_t name_count; /* how many of the entries are names? */
static struct name_elt *name_head; /* store a list of names */
size_t name_count; /* how many of the entries are names? */
/* Check the size of name_array, reallocating it as necessary. */
static void
check_name_alloc (void)
static struct name_elt *
name_elt_alloc (void)
{
if (entries == allocated_entries)
struct name_elt *elt;
elt = xmalloc (sizeof (*elt));
if (!name_head)
{
if (allocated_entries == 0)
allocated_entries = 10; /* Set initial allocation */
name_array = x2nrealloc (name_array, &allocated_entries,
sizeof (name_array[0]));
name_head = elt;
name_head->prev = name_head->next = NULL;
name_head->type = NELT_NOOP;
elt = xmalloc (sizeof (*elt));
}
elt->prev = name_head->prev;
if (name_head->prev)
name_head->prev->next = elt;
elt->next = name_head;
name_head->prev = elt;
return elt;
}
static void
name_list_adjust (void)
{
if (name_head)
while (name_head->prev)
name_head = name_head->prev;
}
static void
name_list_advance (void)
{
struct name_elt *elt = name_head;
name_head = elt->next;
if (name_head)
name_head->prev = NULL;
free (elt);
}
/* Add to name_array the file NAME with fnmatch options MATCHING_FLAGS */
@@ -249,17 +281,14 @@ void
name_add_name (const char *name, int matching_flags)
{
static int prev_flags = 0; /* FIXME: Or EXCLUDE_ANCHORED? */
struct name_elt *ep;
struct name_elt *ep = name_elt_alloc ();
check_name_alloc ();
ep = &name_array[entries++];
if (prev_flags != matching_flags)
{
ep->type = NELT_FMASK;
ep->v.matching_flags = matching_flags;
prev_flags = matching_flags;
check_name_alloc ();
ep = &name_array[entries++];
ep = name_elt_alloc ();
}
ep->type = NELT_NAME;
ep->v.name = name;
@@ -270,13 +299,20 @@ name_add_name (const char *name, int matching_flags)
void
name_add_dir (const char *name)
{
struct name_elt *ep;
check_name_alloc ();
ep = &name_array[entries++];
struct name_elt *ep = name_elt_alloc ();
ep->type = NELT_CHDIR;
ep->v.name = name;
}
void
name_add_file (const char *name, int term)
{
struct name_elt *ep = name_elt_alloc ();
ep->type = NELT_FILE;
ep->v.file.name = name;
ep->v.file.term = term;
ep->v.file.fp = NULL;
}
/* Names from external name file. */
@@ -290,15 +326,224 @@ name_init (void)
{
name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
name_buffer_length = NAME_FIELD_SIZE;
name_list_adjust ();
}
void
name_term (void)
{
free (name_buffer);
free (name_array);
}
/* Prevent recursive inclusion of the same file */
struct file_id_list
{
struct file_id_list *next;
ino_t ino;
dev_t dev;
const char *from_file;
};
static struct file_id_list *file_id_list;
/* Return the name of the file from which the file names and options
are being read.
*/
static const char *
file_list_name (void)
{
struct name_elt *elt;
for (elt = name_head; elt; elt = elt->next)
if (elt->type == NELT_FILE && elt->v.file.fp)
return elt->v.file.name;
return _("command line");
}
static int
add_file_id (const char *filename)
{
struct file_id_list *p;
struct stat st;
const char *reading_from;
if (stat (filename, &st))
stat_fatal (filename);
reading_from = file_list_name ();
for (p = file_id_list; p; p = p->next)
if (p->ino == st.st_ino && p->dev == st.st_dev)
{
int oldc = set_char_quoting (NULL, ':', 1);
ERROR ((0, 0,
_("%s: file list requested from %s already read from %s"),
quotearg_n (0, filename),
reading_from, p->from_file));
set_char_quoting (NULL, ':', oldc);
return 1;
}
p = xmalloc (sizeof *p);
p->next = file_id_list;
p->ino = st.st_ino;
p->dev = st.st_dev;
p->from_file = reading_from;
file_id_list = p;
return 0;
}
enum read_file_list_state /* Result of reading file name from the list file */
{
file_list_success, /* OK, name read successfully */
file_list_end, /* End of list file */
file_list_zero, /* Zero separator encountered where it should not */
file_list_skip /* Empty (zero-length) entry encountered, skip it */
};
/* 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 (struct name_elt *ent)
{
int c;
size_t counter = 0;
FILE *fp = ent->v.file.fp;
int term = ent->v.file.term;
for (c = getc (fp); c != EOF && c != term; c = getc (fp))
{
if (counter == name_buffer_length)
name_buffer = x2realloc (name_buffer, &name_buffer_length);
name_buffer[counter++] = c;
if (c == 0)
{
/* We have read a zero separator. The file possibly is
zero-separated */
return file_list_zero;
}
}
if (counter == 0 && c != EOF)
return file_list_skip;
if (counter == name_buffer_length)
name_buffer = x2realloc (name_buffer, &name_buffer_length);
name_buffer[counter] = 0;
return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
}
static int
handle_option (const char *str)
{
struct wordsplit ws;
int i;
while (*str && isspace (*str))
++str;
if (*str != '-')
return 1;
ws.ws_offs = 1;
if (wordsplit (str, &ws, WRDSF_DEFFLAGS|WRDSF_DOOFFS))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
str, wordsplit_strerror (&ws)));
ws.ws_wordv[0] = program_invocation_short_name;
more_options (ws.ws_wordc+ws.ws_offs, ws.ws_wordv);
for (i = 0; i < ws.ws_wordc+ws.ws_offs; i++)
ws.ws_wordv[i] = NULL;
wordsplit_free (&ws);
return 0;
}
static int
read_next_name (struct name_elt *ent, struct name_elt *ret)
{
if (!ent->v.file.fp)
{
if (!strcmp (ent->v.file.name, "-"))
{
request_stdin ("-T");
ent->v.file.fp = stdin;
}
else
{
if (add_file_id (ent->v.file.name))
{
name_list_advance ();
return 1;
}
if ((ent->v.file.fp = fopen (ent->v.file.name, "r")) == NULL)
open_fatal (ent->v.file.name);
}
}
while (1)
{
switch (read_name_from_file (ent))
{
case file_list_skip:
continue;
case file_list_zero:
WARNOPT (WARN_FILENAME_WITH_NULS,
(0, 0, N_("%s: file name read contains nul character"),
quotearg_colon (ent->v.file.name)));
ent->v.file.term = 0;
/* fall through */
case file_list_success:
if (unquote_option)
unquote_string (name_buffer);
if (handle_option (name_buffer) == 0)
{
name_list_adjust ();
return 1;
}
ret->type = NELT_NAME;
ret->v.name = name_buffer;
return 0;
case file_list_end:
if (strcmp (ent->v.file.name, "-"))
fclose (ent->v.file.fp);
ent->v.file.fp = NULL;
name_list_advance ();
return 1;
}
}
}
static void
copy_name (struct name_elt *ep)
{
const char *source;
size_t source_len;
char *cursor;
source = ep->v.name;
source_len = strlen (source);
if (name_buffer_length < source_len)
{
do
{
name_buffer_length *= 2;
if (! name_buffer_length)
xalloc_die ();
}
while (name_buffer_length < source_len);
free (name_buffer);
name_buffer = xmalloc(name_buffer_length + 2);
}
strcpy (name_buffer, source);
/* Zap trailing slashes. */
cursor = name_buffer + strlen (name_buffer) - 1;
while (cursor > name_buffer && ISSLASH (*cursor))
*cursor-- = '\0';
}
static int matching_flags; /* exclude_fnmatch options */
/* Get the next NELT_NAME element from name_array. Result is in
@@ -313,57 +558,42 @@ static struct name_elt *
name_next_elt (int change_dirs)
{
static struct name_elt entry;
const char *source;
char *cursor;
struct name_elt *ep;
while (scanned != entries)
while ((ep = name_head) != NULL)
{
struct name_elt *ep;
size_t source_len;
ep = &name_array[scanned++];
if (ep->type == NELT_FMASK)
switch (ep->type)
{
case NELT_NOOP:
name_list_advance ();
break;
case NELT_FMASK:
matching_flags = ep->v.matching_flags;
recursion_option = matching_flags & FNM_LEADING_DIR;
name_list_advance ();
continue;
}
source = ep->v.name;
source_len = strlen (source);
if (name_buffer_length < source_len)
{
do
case NELT_FILE:
if (read_next_name (ep, &entry) == 0)
return &entry;
continue;
case NELT_CHDIR:
if (change_dirs)
{
name_buffer_length *= 2;
if (! name_buffer_length)
xalloc_die ();
chdir_do (chdir_arg (xstrdup (ep->v.name)));
name_list_advance ();
break;
}
while (name_buffer_length < source_len);
free (name_buffer);
name_buffer = xmalloc (name_buffer_length + 2);
}
strcpy (name_buffer, source);
/* Zap trailing slashes. */
cursor = name_buffer + strlen (name_buffer) - 1;
while (cursor > name_buffer && ISSLASH (*cursor))
*cursor-- = '\0';
if (change_dirs && ep->type == NELT_CHDIR)
{
if (chdir (name_buffer) < 0)
chdir_fatal (name_buffer);
}
else
{
/* fall through */
case NELT_NAME:
copy_name (ep);
if (unquote_option)
unquote_string (name_buffer);
if (incremental_option)
register_individual_file (name_buffer);
entry.type = ep->type;
entry.v.name = name_buffer;
name_list_advance ();
return &entry;
}
}
@@ -673,9 +903,9 @@ label_notfound (void)
/* Sort *singly* linked LIST of names, of given LENGTH, using COMPARE
to order names. Return the sorted list. Note that after calling
this function, the `prev' links in list elements are messed up.
this function, the 'prev' links in list elements are messed up.
Apart from the type `struct name' and the definition of SUCCESSOR,
Apart from the type 'struct name' and the definition of SUCCESSOR,
this is a generic list-sorting function, but it's too painful to
make it both generic and portable
in C. */
@@ -898,7 +1128,7 @@ name_compare (void const *entry1, void const *entry2)
}
/* Rebase `name' member of CHILD and all its siblings to
/* Rebase 'name' member of CHILD and all its siblings to
the new PARENT. */
static void
rebase_child_list (struct name *child, struct name *parent)
@@ -1012,13 +1242,11 @@ collect_and_sort_names (void)
namelist = merge_sort (namelist, num_names, compare_names);
num_names = 0;
nametab = hash_initialize (0, 0,
name_hash,
name_compare, NULL);
nametab = hash_initialize (0, 0, name_hash, name_compare, NULL);
for (name = namelist; name; name = next_name)
{
next_name = name->next;
name->caname = normalize_filename (name->name);
name->caname = normalize_filename (name->change_dir, name->name);
if (prev_name)
{
struct name *p = hash_lookup (nametab, name);
@@ -1104,7 +1332,7 @@ name_scan (const char *file_name)
struct name *gnu_list_name;
struct name const *
name_from_list ()
name_from_list (void)
{
if (!gnu_list_name)
gnu_list_name = namelist;
@@ -1145,34 +1373,6 @@ new_name (const char *file_name, const char *name)
return buffer;
}
/* Return nonzero if file NAME is excluded. */
bool
excluded_name (char const *name)
{
return excluded_file_name (excluded, name + FILE_SYSTEM_PREFIX_LEN (name));
}
static Hash_table *individual_file_table;
static void
register_individual_file (char const *name)
{
struct stat st;
if (deref_stat (name, &st) != 0)
return; /* Will be complained about later */
if (S_ISDIR (st.st_mode))
return;
hash_string_insert (&individual_file_table, name);
}
bool
is_individual_file (char const *name)
{
return hash_string_lookup (individual_file_table, name);
}
/* Return the size of the prefix of FILE_NAME that is removed after

View File

@@ -1,7 +1,6 @@
/* Functions for dealing with sparse files
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Free Software
Foundation, Inc.
Copyright 2003-2007, 2010, 2013-2014 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
@@ -14,8 +13,7 @@
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. */
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <inttostr.h>
@@ -230,7 +228,7 @@ sparse_scan_file (struct tar_sparse_file *file)
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
while ((count = blocking_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
{
/* Analyze the block. */
@@ -360,7 +358,7 @@ sparse_extract_region (struct tar_sparse_file *file, size_t i)
return false;
}
set_next_block_after (blk);
count = full_write (file->fd, blk->buffer, wrbytes);
count = blocking_write (file->fd, blk->buffer, wrbytes);
write_size -= count;
file->dumped_size += count;
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
@@ -591,18 +589,18 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
/* Old GNU Format. The sparse file information is stored in the
oldgnu_header in the following manner:
The header is marked with type 'S'. Its `size' field contains
The header is marked with type 'S'. Its 'size' field contains
the cumulative size of all non-empty blocks of the file. The
actual file size is stored in `realsize' member of oldgnu_header.
actual file size is stored in 'realsize' member of oldgnu_header.
The map of the file is stored in a list of `struct sparse'.
The map of the file is stored in a list of 'struct sparse'.
Each struct contains offset to the block of data and its
size (both as octal numbers). The first file header contains
at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
contains more structs, then the field `isextended' of the main
header is set to 1 (binary) and the `struct sparse_header'
contains more structs, then the field 'isextended' of the main
header is set to 1 (binary) and the 'struct sparse_header'
header follows, containing at most 21 following structs
(SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
(SPARSES_IN_SPARSE_HEADER). If more structs follow, 'isextended'
field of the extended header is set and next next extension header
follows, etc... */
@@ -629,8 +627,8 @@ oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
return add_finish;
sp.offset = OFF_FROM_HEADER (s->offset);
sp.numbytes = OFF_FROM_HEADER (s->numbytes);
if (sp.offset < 0
|| sp.offset + sp.numbytes < 0
if (sp.offset < 0 || sp.numbytes < 0
|| INT_ADD_OVERFLOW (sp.offset, sp.numbytes)
|| file->stat_info->stat.st_size < sp.offset + sp.numbytes
|| file->stat_info->archive_file_size < 0)
return add_fail;
@@ -644,10 +642,10 @@ oldgnu_fixup_header (struct tar_sparse_file *file)
{
/* NOTE! st_size was initialized from the header
which actually contains archived size. The following fixes it */
off_t realsize = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size =
OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
return true;
file->stat_info->stat.st_size = max (0, realsize);
return 0 <= realsize;
}
/* Convert old GNU format sparse data to internal representation */
@@ -768,10 +766,10 @@ star_fixup_header (struct tar_sparse_file *file)
{
/* NOTE! st_size was initialized from the header
which actually contains archived size. The following fixes it */
off_t realsize = OFF_FROM_HEADER (current_header->star_in_header.realsize);
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size =
OFF_FROM_HEADER (current_header->star_in_header.realsize);
return true;
file->stat_info->stat.st_size = max (0, realsize);
return 0 <= realsize;
}
/* Convert STAR format sparse data to internal representation */
@@ -811,6 +809,7 @@ star_get_sparse_info (struct tar_sparse_file *file)
set_next_block_after (h);
for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)
rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);
file->dumped_size += BLOCKSIZE;
}
if (rc == add_fail)
@@ -919,6 +918,18 @@ pax_sparse_member_p (struct tar_sparse_file *file)
|| file->stat_info->sparse_major > 0;
}
/* Start a header that uses the effective (shrunken) file size. */
static union block *
pax_start_header (struct tar_stat_info *st)
{
off_t realsize = st->stat.st_size;
union block *blk;
st->stat.st_size = st->archive_file_size;
blk = start_header (st);
st->stat.st_size = realsize;
return blk;
}
static bool
pax_dump_header_0 (struct tar_sparse_file *file)
{
@@ -968,9 +979,7 @@ pax_dump_header_0 (struct tar_sparse_file *file)
return false;
}
}
blk = start_header (file->stat_info);
/* Store the effective (shrunken) file size */
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
blk = pax_start_header (file->stat_info);
finish_header (file->stat_info, blk, block_ordinal);
if (save_file_name)
{
@@ -1029,12 +1038,13 @@ pax_dump_header_1 (struct tar_sparse_file *file)
xheader_store ("GNU.sparse.name", file->stat_info, NULL);
xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);
file->stat_info->file_name = xheader_format_name (file->stat_info,
"%d/GNUSparseFile.%p/%f", 0);
file->stat_info->file_name =
xheader_format_name (file->stat_info, "%d/GNUSparseFile.%p/%f", 0);
/* Make sure the created header name is shorter than NAME_FIELD_SIZE: */
if (strlen (file->stat_info->file_name) > NAME_FIELD_SIZE)
file->stat_info->file_name[NAME_FIELD_SIZE] = 0;
blk = start_header (file->stat_info);
/* Store the effective (shrunken) file size */
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
blk = pax_start_header (file->stat_info);
finish_header (file->stat_info, blk, block_ordinal);
free (file->stat_info->file_name);
file->stat_info->file_name = save_file_name;
@@ -1077,6 +1087,7 @@ decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
if (!ISDIGIT (*arg))
return false;
errno = 0;
u = strtoumax (arg, &arg_lim, 10);
if (! (u <= maxval && errno != ERANGE) || *arg_lim)

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright (C) 2007, 2009 Free Software Foundation, Inc.
Copyright 2007, 2009, 2013-2014 Free Software Foundation, Inc.
Written by Sergey Poznyakoff.
@@ -29,6 +29,7 @@ struct compression_suffix
static struct compression_suffix compression_suffixes[] = {
#define __CAT2__(a,b) a ## b
#define S(s,p) #s, sizeof (#s) - 1, __CAT2__(p,_PROGRAM)
{ "tar", 3, NULL },
{ S(gz, GZIP) },
{ S(tgz, GZIP) },
{ S(taz, GZIP) },
@@ -43,33 +44,44 @@ static struct compression_suffix compression_suffixes[] = {
{ S(tlz, LZMA) },
{ S(lzo, LZOP) },
{ S(xz, XZ) },
{ S(txz, XZ) }, /* Slackware */
{ NULL }
#undef S
#undef __CAT2__
};
static int nsuffixes = sizeof (compression_suffixes) /
sizeof (compression_suffixes[0]);
static const char *
find_compression_program (const char *name, const char *defprog)
static struct compression_suffix const *
find_compression_suffix (const char *name, size_t *ret_len)
{
char *suf = strrchr (name, '.');
if (suf)
{
int i;
size_t len;
struct compression_suffix *p;
suf++;
len = strlen (suf);
for (i = 0; i < nsuffixes; i++)
for (p = compression_suffixes; p->suffix; p++)
{
if (compression_suffixes[i].length == len
&& memcmp (compression_suffixes[i].suffix, suf, len) == 0)
return compression_suffixes[i].program;
if (p->length == len && memcmp (p->suffix, suf, len) == 0)
{
if (ret_len)
*ret_len = strlen (name) - len - 1;
return p;
}
}
}
return NULL;
}
static const char *
find_compression_program (const char *name, const char *defprog)
{
struct compression_suffix const *p = find_compression_suffix (name, NULL);
if (p)
return p->program;
return defprog;
}
@@ -80,3 +92,23 @@ set_compression_program_by_suffix (const char *name, const char *defprog)
if (program)
use_compress_program_option = program;
}
char *
strip_compression_suffix (const char *name)
{
char *s = NULL;
size_t len;
if (find_compression_suffix (name, &len))
{
if (strncmp (name + len - 4, ".tar", 4) == 0)
len -= 4;
if (len == 0)
return NULL;
s = xmalloc (len + 1);
memcpy (s, name, len);
s[len] = 0;
}
return s;
}

View File

@@ -1,7 +1,6 @@
/* System-dependent calls for tar.
Copyright (C) 2003, 2004, 2005, 2006, 2007,
2008, 2010 Free Software Foundation, Inc.
Copyright 2003-2008, 2010, 2013-2014 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
@@ -14,8 +13,7 @@
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. */
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
@@ -23,6 +21,20 @@
#include <priv-set.h>
#include <rmt.h>
#include <signal.h>
#include <wordsplit.h>
static _Noreturn void
xexec (const char *cmd)
{
struct wordsplit ws;
ws.ws_env = (const char **) environ;
if (wordsplit (cmd, &ws, (WRDSF_DEFFLAGS | WRDSF_ENV) & ~WRDSF_NOVAR))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
cmd, wordsplit_strerror (&ws)));
execvp (ws.ws_wordv[0], ws.ws_wordv);
exec_fatal (cmd);
}
#if MSDOS
@@ -194,7 +206,7 @@ sys_spawn_shell (void)
if (child == 0)
{
priv_set_restore_linkdir ();
execlp (shell, "-sh", "-i", (char *) 0);
execlp (shell, "-sh", "-i", NULL);
exec_fatal (shell);
}
else
@@ -365,8 +377,7 @@ sys_child_open_for_compress (void)
xdup2 (archive, STDOUT_FILENO);
}
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option, NULL);
exec_fatal (use_compress_program_option);
xexec (use_compress_program_option);
}
/* We do need a grandchild tar. */
@@ -383,9 +394,7 @@ sys_child_open_for_compress (void)
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
xclose (child_pipe[PREAD]);
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option,
(char *) 0);
exec_fatal (use_compress_program_option);
xexec (use_compress_program_option);
}
/* The child tar is still here! */
@@ -455,6 +464,42 @@ sys_child_open_for_compress (void)
wait_for_grandchild (grandchild_pid);
}
static void
run_decompress_program (void)
{
int i;
const char *p, *prog = NULL;
struct wordsplit ws;
int wsflags = (WRDSF_DEFFLAGS | WRDSF_ENV | WRDSF_DOOFFS) & ~WRDSF_NOVAR;
ws.ws_env = (const char **) environ;
ws.ws_offs = 1;
for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
{
if (prog)
{
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, errno, _("cannot run %s"), prog));
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, 0, _("trying %s"), p));
}
if (wordsplit (p, &ws, wsflags))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
p, wordsplit_strerror (&ws)));
wsflags |= WRDSF_REUSE;
memmove(ws.ws_wordv, ws.ws_wordv + ws.ws_offs,
sizeof(ws.ws_wordv[0])*ws.ws_wordc);
ws.ws_wordv[ws.ws_wordc] = (char *) "-d";
prog = p;
execvp (ws.ws_wordv[0], ws.ws_wordv);
ws.ws_wordv[ws.ws_wordc] = NULL;
}
if (!prog)
FATAL_ERROR ((0, 0, _("unable to run decompression program")));
exec_fatal (prog);
}
/* Set ARCHIVE for uncompressing, then reading an archive. */
pid_t
sys_child_open_for_uncompress (void)
@@ -501,9 +546,7 @@ sys_child_open_for_uncompress (void)
open_fatal (archive_name_array[0]);
xdup2 (archive, STDIN_FILENO);
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
exec_fatal (use_compress_program_option);
run_decompress_program ();
}
/* We do need a grandchild tar. */
@@ -520,9 +563,7 @@ sys_child_open_for_uncompress (void)
xdup2 (child_pipe[PREAD], STDIN_FILENO);
xclose (child_pipe[PWRITE]);
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
exec_fatal (use_compress_program_option);
run_decompress_program ();
}
/* The child tar is still here! */
@@ -679,13 +720,12 @@ stat_to_env (char *name, char type, struct tar_stat_info *st)
}
static pid_t global_pid;
static RETSIGTYPE (*pipe_handler) (int sig);
static void (*pipe_handler) (int sig);
int
sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
{
int p[2];
char *argv[4];
xpipe (p);
pipe_handler = signal (SIGPIPE, SIG_IGN);
@@ -703,15 +743,8 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
stat_to_env (file_name, typechar, st);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = to_command_option;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv ("/bin/sh", argv);
exec_fatal (file_name);
xexec (to_command_option);
}
void
@@ -753,10 +786,9 @@ int
sys_exec_info_script (const char **archive_name, int volume_number)
{
pid_t pid;
char *argv[4];
char uintbuf[UINTMAX_STRSIZE_BOUND];
int p[2];
static RETSIGTYPE (*saved_handler) (int sig);
static void (*saved_handler) (int sig);
xpipe (p);
saved_handler = signal (SIGPIPE, SIG_IGN);
@@ -818,15 +850,8 @@ sys_exec_info_script (const char **archive_name, int volume_number)
xclose (p[PREAD]);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = (char *) info_script_option;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv (argv[0], argv);
exec_fatal (info_script_option);
xexec (info_script_option);
}
void
@@ -835,7 +860,6 @@ sys_exec_checkpoint_script (const char *script_name,
int checkpoint_number)
{
pid_t pid;
char *argv[4];
char uintbuf[UINTMAX_STRSIZE_BOUND];
pid = xfork ();
@@ -866,15 +890,8 @@ sys_exec_checkpoint_script (const char *script_name,
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;
priv_set_restore_linkdir ();
execv (argv[0], argv);
exec_fatal (script_name);
xexec (script_name);
}
#endif /* not MSDOS */

683
src/tar.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,22 @@
/* GNU tar Archive Format description.
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright 1988-1989, 1991-1997, 2000-2001, 2003-2007, 2012-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
/* tar Header Block, from POSIX 1003.1-1990. */
@@ -80,9 +81,9 @@ struct posix_header
/* tar Header Block, GNU extensions. */
/* In GNU tar, SYMTYPE is for to symbolic links, and CONTTYPE is for
contiguous files, so maybe disobeying the `reserved' comment in POSIX
contiguous files, so maybe disobeying the "reserved" comment in POSIX
header description. I suspect these were meant to be used this way, and
should not have really been `reserved' in the published standards. */
should not have really been "reserved" in the published standards. */
/* *BEWARE* *BEWARE* *BEWARE* that the following information is still
boiling, and may change. Even if the OLDGNU format description should be
@@ -276,6 +277,14 @@ struct xheader
uintmax_t string_length;
};
/* Information about xattrs for a file. */
struct xattr_array
{
char *xkey;
char *xval_ptr;
size_t xval_len;
};
struct tar_stat_info
{
char *orig_file_name; /* name of file read from the archive header */
@@ -287,6 +296,15 @@ struct tar_stat_info
char *uname; /* user name of owner */
char *gname; /* group name of owner */
char *cntx_name; /* SELinux context for the current archive entry. */
char *acls_a_ptr; /* Access ACLs for the current archive entry. */
size_t acls_a_len; /* Access ACLs for the current archive entry. */
char *acls_d_ptr; /* Default ACLs for the current archive entry. */
size_t acls_d_len; /* Default ACLs for the current archive entry. */
struct stat stat; /* regular filesystem stat */
/* STAT doesn't always have access, data modification, and status
@@ -309,6 +327,9 @@ struct tar_stat_info
size_t sparse_map_size; /* Size of the sparse map */
struct sp_array *sparse_map;
size_t xattr_map_size; /* Size of the xattr map */
struct xattr_array *xattr_map;
/* Extended headers */
struct xheader xhdr;
@@ -337,6 +358,9 @@ struct tar_stat_info
It is negative if it could not be reopened after it was closed.
Negate it to find out what errno was when the reopen failed. */
int fd;
/* Exclusion list */
struct exclist *exclude_list;
};
union block

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright 2006-2008, 2013-2014 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
@@ -12,8 +12,7 @@
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. */
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <regex.h>
@@ -71,7 +70,7 @@ struct transform
int transform_flags = XFORM_ALL;
static int transform_flags = XFORM_ALL;
static struct transform *transform_head, *transform_tail;
static struct transform *
@@ -347,7 +346,7 @@ parse_transform_expr (const char *expr)
break;
case 'L':
/* Turn the replacement to lowercase until a `\U' or `\E'
/* Turn the replacement to lowercase until a '\U' or '\E'
is found, */
add_case_ctl_segment (tf, ctl_locase);
cur++;
@@ -360,7 +359,7 @@ parse_transform_expr (const char *expr)
break;
case 'U':
/* Turn the replacement to uppercase until a `\L' or `\E'
/* Turn the replacement to uppercase until a '\L' or '\E'
is found, */
add_case_ctl_segment (tf, ctl_upcase);
cur++;
@@ -373,7 +372,7 @@ parse_transform_expr (const char *expr)
break;
case 'E':
/* Stop case conversion started by `\L' or `\U'. */
/* Stop case conversion started by '\L' or '\U'. */
add_case_ctl_segment (tf, ctl_stop);
cur++;
break;
@@ -628,3 +627,9 @@ transform_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, NULL, NULL);
}
bool
transform_program_p (void)
{
return transform_head != NULL;
}

View File

@@ -1,19 +1,21 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
/* Unlink files.
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.
Copyright 2009, 2013-2014 Free Software Foundation, Inc.
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.
This file is part of GNU tar.
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. */
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"
@@ -22,7 +24,9 @@
struct deferred_unlink
{
struct deferred_unlink *next; /* Next unlink in the queue */
char *file_name; /* Absolute name of the file to unlink */
int dir_idx; /* Directory index in wd */
char *file_name; /* Name of the file to unlink, relative
to dir_idx */
bool is_dir; /* True if file_name is a directory */
off_t records_written; /* Number of records written when this
entry got added to the queue */
@@ -39,7 +43,7 @@ static struct deferred_unlink *dunlink_avail;
/* Delay (number of records written) between adding entry to the
list and its actual removal. */
size_t deferred_unlink_delay = 0;
static size_t deferred_unlink_delay = 0;
static struct deferred_unlink *
dunlink_alloc (void)
@@ -68,16 +72,31 @@ static void
flush_deferred_unlinks (bool force)
{
struct deferred_unlink *p, *prev = NULL;
int saved_chdir = chdir_current;
for (p = dunlink_head; p; )
{
struct deferred_unlink *next = p->next;
if (force
|| records_written > p->records_written + deferred_unlink_delay)
{
chdir_do (p->dir_idx);
if (p->is_dir)
{
if (unlinkat (chdir_fd, p->file_name, AT_REMOVEDIR) != 0)
const char *fname;
if (p->dir_idx
&& (p->file_name[0] == 0
|| strcmp (p->file_name, ".") == 0))
{
fname = tar_dirname ();
chdir_do (p->dir_idx - 1);
}
else
fname = p->file_name;
if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
{
switch (errno)
{
@@ -95,7 +114,7 @@ flush_deferred_unlinks (bool force)
}
/* fall through */
default:
rmdir_error (p->file_name);
rmdir_error (fname);
}
}
}
@@ -120,10 +139,11 @@ flush_deferred_unlinks (bool force)
}
if (!dunlink_head)
dunlink_tail = NULL;
chdir_do (saved_chdir);
}
void
finish_deferred_unlinks ()
finish_deferred_unlinks (void)
{
flush_deferred_unlinks (true);
while (dunlink_avail)
@@ -145,7 +165,9 @@ queue_deferred_unlink (const char *name, bool is_dir)
p = dunlink_alloc ();
p->next = NULL;
p->file_name = normalize_filename (name);
p->dir_idx = chdir_current;
p->file_name = xstrdup (name);
normalize_filename_x (p->file_name);
p->is_dir = is_dir;
p->records_written = records_written;

View File

@@ -1,21 +1,22 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
2004, 2005, 2007, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994, 1996-1997, 1999-2001, 2003-2005, 2007,
2010, 2013-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
/* Implement the 'r', 'u' and 'A' options for tar. 'A' means that the
file names are tar files, and they should simply be appended to the end
@@ -130,6 +131,8 @@ update_archive (void)
decode_header (current_header, &current_stat_info,
&current_format, 0);
transform_stat_info (current_header->header.typeflag,
&current_stat_info);
archive_format = current_format;
if (subcommand_option == UPDATE_SUBCOMMAND
@@ -142,16 +145,8 @@ update_archive (void)
{
if (S_ISDIR (s.st_mode))
{
char *p, *dirp;
DIR *stream;
int fd = openat (chdir_fd, name->name,
open_read_flags | O_DIRECTORY);
if (fd < 0)
open_error (name->name);
else if (! ((stream = fdopendir (fd))
&& (dirp = streamsavedir (stream))))
savedir_error (name->name);
else
char *p, *dirp = tar_savedir (name->name, 1);
if (dirp)
{
namebuf_t nbuf = namebuf_create (name->name);
@@ -164,11 +159,6 @@ update_archive (void)
remname (name);
}
if (stream
? closedir (stream) != 0
: 0 <= fd && close (fd) != 0)
savedir_error (name->name);
}
else if (tar_timespec_cmp (get_stat_mtime (&s),
current_stat_info.mtime)
@@ -226,7 +216,7 @@ update_archive (void)
while ((p = name_from_list ()) != NULL)
{
char *file_name = p->name;
if (excluded_name (file_name))
if (excluded_name (file_name, NULL))
continue;
if (interactive_option && !confirm ("add", file_name))
continue;

View File

@@ -1,20 +1,21 @@
/* Charset handling for GNU tar.
Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
Copyright 2004, 2006-2007, 2013-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <quotearg.h>

View File

@@ -1,19 +1,21 @@
/* This file is part of GNU tar.
/* Warnings for GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
Copyright 2009, 2012-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <argmatch.h>
@@ -41,6 +43,10 @@ static char const *const warning_args[] = {
"unknown-cast",
"unknown-keyword",
"xdev",
"decompress-program",
"existing-file",
"xattr-write",
"record-size",
NULL
};
@@ -64,7 +70,11 @@ static int warning_types[] = {
WARN_TIMESTAMP,
WARN_UNKNOWN_CAST,
WARN_UNKNOWN_KEYWORD,
WARN_XDEV
WARN_XDEV,
WARN_DECOMPRESS_PROGRAM,
WARN_EXISTING_FILE,
WARN_XATTR_WRITE,
WARN_RECORD_SIZE
};
ARGMATCH_VERIFY (warning_args, warning_types);

755
src/xattrs.c Normal file
View File

@@ -0,0 +1,755 @@
/* Support for extended attributes.
Copyright (C) 2006-2014 Free Software Foundation, Inc.
This file is part of GNU tar.
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
Written by James Antill, on 2006-07-27. */
#include <config.h>
#include <system.h>
#include <fnmatch.h>
#include <quotearg.h>
#include "common.h"
#include "xattr-at.h"
#include "selinux-at.h"
struct xattrs_mask_map
{
const char **masks;
size_t size;
size_t used;
};
/* list of fnmatch patterns */
static struct
{
/* lists of fnmatch patterns */
struct xattrs_mask_map incl;
struct xattrs_mask_map excl;
} xattrs_setup;
/* disable posix acls when problem found in gnulib script m4/acl.m4 */
#if ! USE_ACL
# undef HAVE_POSIX_ACLS
#endif
#ifdef HAVE_POSIX_ACLS
# include "acl.h"
# include <sys/acl.h>
#endif
#ifdef HAVE_POSIX_ACLS
/* acl-at wrappers, TODO: move to gnulib in future? */
static acl_t acl_get_file_at (int, const char *, acl_type_t);
static int acl_set_file_at (int, const char *, acl_type_t, acl_t);
static int file_has_acl_at (int, char const *, struct stat const *);
static int acl_delete_def_file_at (int, char const *);
/* acl_get_file_at */
#define AT_FUNC_NAME acl_get_file_at
#define AT_FUNC_RESULT acl_t
#define AT_FUNC_FAIL (acl_t)NULL
#define AT_FUNC_F1 acl_get_file
#define AT_FUNC_POST_FILE_PARAM_DECLS , acl_type_t type
#define AT_FUNC_POST_FILE_ARGS , type
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_RESULT
#undef AT_FUNC_FAIL
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* acl_set_file_at */
#define AT_FUNC_NAME acl_set_file_at
#define AT_FUNC_F1 acl_set_file
#define AT_FUNC_POST_FILE_PARAM_DECLS , acl_type_t type, acl_t acl
#define AT_FUNC_POST_FILE_ARGS , type, acl
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* acl_delete_def_file_at */
#define AT_FUNC_NAME acl_delete_def_file_at
#define AT_FUNC_F1 acl_delete_def_file
#define AT_FUNC_POST_FILE_PARAM_DECLS
#define AT_FUNC_POST_FILE_ARGS
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* gnulib file_has_acl_at */
#define AT_FUNC_NAME file_has_acl_at
#define AT_FUNC_F1 file_has_acl
#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat const *st
#define AT_FUNC_POST_FILE_ARGS , st
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
/* convert unix permissions into an ACL ... needed due to "default" ACLs */
static acl_t
perms2acl (int perms)
{
char val[] = "user::---,group::---,other::---";
/* 0123456789 123456789 123456789 123456789 */
/* user */
if (perms & 0400)
val[6] = 'r';
if (perms & 0200)
val[7] = 'w';
if (perms & 0100)
val[8] = 'x';
/* group */
if (perms & 0040)
val[17] = 'r';
if (perms & 0020)
val[18] = 'w';
if (perms & 0010)
val[19] = 'x';
/* other */
if (perms & 0004)
val[28] = 'r';
if (perms & 0002)
val[29] = 'w';
if (perms & 0001)
val[30] = 'x';
return acl_from_text (val);
}
static char *
skip_to_ext_fields (char *ptr)
{
/* skip tag name (user/group/default/mask) */
ptr += strcspn (ptr, ":,\n");
if (*ptr != ':')
return ptr;
++ptr;
ptr += strcspn (ptr, ":,\n"); /* skip user/group name */
if (*ptr != ':')
return ptr;
++ptr;
ptr += strcspn (ptr, ":,\n"); /* skip perms */
return ptr;
}
/* The POSIX draft allows extra fields after the three main ones. Star
uses this to add a fourth field for user/group which is the numeric ID.
This function removes such extra fields by overwriting them with the
characters that follow. */
static char *
fixup_extra_acl_fields (char *ptr)
{
char *src = ptr;
char *dst = ptr;
while (*src)
{
const char *old = src;
size_t len = 0;
src = skip_to_ext_fields (src);
len = src - old;
if (old != dst)
memmove (dst, old, len);
dst += len;
if (*src == ':') /* We have extra fields, skip them all */
src += strcspn (src, "\n,");
if ((*src == '\n') || (*src == ','))
*dst++ = *src++; /* also done when dst == src, but that's ok */
}
if (src != dst)
*dst = 0;
return ptr;
}
/* Set the "system.posix_acl_access/system.posix_acl_default" extended
attribute. Called only when acls_option > 0. */
static void
xattrs__acls_set (struct tar_stat_info const *st,
char const *file_name, int type,
char *ptr, size_t len, bool def)
{
acl_t acl;
if (ptr)
{
/* assert (strlen (ptr) == len); */
ptr = fixup_extra_acl_fields (ptr);
acl = acl_from_text (ptr);
}
else if (def)
{
/* No "default" IEEE 1003.1e ACL set for directory. At this moment,
FILE_NAME may already have inherited default acls from parent
directory; clean them up. */
if (acl_delete_def_file_at (chdir_fd, file_name))
WARNOPT (WARN_XATTR_WRITE,
(0, errno,
_("acl_delete_def_file_at: Cannot drop default POSIX ACLs "
"for file '%s'"),
file_name));
return;
}
else
acl = perms2acl (st->stat.st_mode);
if (!acl)
{
call_arg_warn ("acl_from_text", file_name);
return;
}
if (acl_set_file_at (chdir_fd, file_name, type, acl) == -1)
/* warn even if filesystem does not support acls */
WARNOPT (WARN_XATTR_WRITE,
(0, errno,
_ ("acl_set_file_at: Cannot set POSIX ACLs for file '%s'"),
file_name));
acl_free (acl);
}
static void
xattrs__acls_get_a (int parentfd, const char *file_name,
struct tar_stat_info *st,
char **ret_ptr, size_t * ret_len)
{
char *val = NULL;
ssize_t len;
acl_t acl;
if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS)))
{
if (errno != ENOTSUP)
call_arg_warn ("acl_get_file_at", file_name);
return;
}
val = acl_to_text (acl, &len);
acl_free (acl);
if (!val)
{
call_arg_warn ("acl_to_text", file_name);
return;
}
*ret_ptr = xstrdup (val);
*ret_len = len;
acl_free (val);
}
/* "system.posix_acl_default" */
static void
xattrs__acls_get_d (int parentfd, char const *file_name,
struct tar_stat_info *st,
char **ret_ptr, size_t * ret_len)
{
char *val = NULL;
ssize_t len;
acl_t acl;
if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)))
{
if (errno != ENOTSUP)
call_arg_warn ("acl_get_file_at", file_name);
return;
}
val = acl_to_text (acl, &len);
acl_free (acl);
if (!val)
{
call_arg_warn ("acl_to_text", file_name);
return;
}
*ret_ptr = xstrdup (val);
*ret_len = len;
acl_free (val);
}
#endif /* HAVE_POSIX_ACLS */
static void
acls_one_line (const char *prefix, char delim,
const char *aclstring, size_t len)
{
/* support both long and short text representation of posix acls */
struct obstack stk;
int pref_len = strlen (prefix);
const char *oldstring = aclstring;
int pos = 0;
if (!aclstring || !len)
return;
obstack_init (&stk);
while (pos <= len)
{
int move = strcspn (aclstring, ",\n");
if (!move)
break;
if (oldstring != aclstring)
obstack_1grow (&stk, delim);
obstack_grow (&stk, prefix, pref_len);
obstack_grow (&stk, aclstring, move);
aclstring += move + 1;
}
obstack_1grow (&stk, '\0');
fprintf (stdlis, "%s", (char *) obstack_finish (&stk));
obstack_free (&stk, NULL);
}
void
xattrs_acls_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd, int xisfile)
{
if (acls_option > 0)
{
#ifndef HAVE_POSIX_ACLS
static int done = 0;
if (!done)
WARN ((0, 0, _("POSIX ACL support is not available")));
done = 1;
#else
int err = file_has_acl_at (parentfd, file_name, &st->stat);
if (err == 0)
return;
if (err == -1)
{
call_arg_warn ("file_has_acl_at", file_name);
return;
}
xattrs__acls_get_a (parentfd, file_name, st,
&st->acls_a_ptr, &st->acls_a_len);
if (!xisfile)
xattrs__acls_get_d (parentfd, file_name, st,
&st->acls_d_ptr, &st->acls_d_len);
#endif
}
}
void
xattrs_acls_set (struct tar_stat_info const *st,
char const *file_name, char typeflag)
{
if (acls_option > 0 && typeflag != SYMTYPE)
{
#ifndef HAVE_POSIX_ACLS
static int done = 0;
if (!done)
WARN ((0, 0, _("POSIX ACL support is not available")));
done = 1;
#else
xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS,
st->acls_a_ptr, st->acls_a_len, false);
if (typeflag == DIRTYPE || typeflag == GNUTYPE_DUMPDIR)
xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT,
st->acls_d_ptr, st->acls_d_len, true);
#endif
}
}
static void
mask_map_realloc (struct xattrs_mask_map *map)
{
if (map->used == map->size)
{
if (map->size == 0)
map->size = 4;
map->masks = x2nrealloc (map->masks, &map->size, sizeof (map->masks[0]));
}
}
void
xattrs_mask_add (const char *mask, bool incl)
{
struct xattrs_mask_map *mask_map =
incl ? &xattrs_setup.incl : &xattrs_setup.excl;
/* ensure there is enough space */
mask_map_realloc (mask_map);
/* just assign pointers -- we silently expect that pointer "mask" is valid
through the whole program (pointer to argv array) */
mask_map->masks[mask_map->used++] = mask;
}
static void
clear_mask_map (struct xattrs_mask_map *mask_map)
{
if (mask_map->size)
free (mask_map->masks);
}
void
xattrs_clear_setup (void)
{
clear_mask_map (&xattrs_setup.incl);
clear_mask_map (&xattrs_setup.excl);
}
/* get all xattrs from file given by FILE_NAME or FD (when non-zero). This
includes all the user.*, security.*, system.*, etc. available domains */
void
xattrs_xattrs_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd)
{
if (xattrs_option > 0)
{
#ifndef HAVE_XATTRS
static int done = 0;
if (!done)
WARN ((0, 0, _("XATTR support is not available")));
done = 1;
#else
static size_t xsz = 1024;
static char *xatrs = NULL;
ssize_t xret = -1;
if (!xatrs)
xatrs = x2nrealloc (xatrs, &xsz, 1);
while (((fd == 0) ?
((xret =
llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) :
((xret = flistxattr (fd, xatrs, xsz)) == -1))
&& (errno == ERANGE))
{
xatrs = x2nrealloc (xatrs, &xsz, 1);
}
if (xret == -1)
call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name);
else
{
const char *attr = xatrs;
static size_t asz = 1024;
static char *val = NULL;
if (!val)
val = x2nrealloc (val, &asz, 1);
while (xret > 0)
{
size_t len = strlen (attr);
ssize_t aret = 0;
/* Archive all xattrs during creation, decide at extraction time
* which ones are of interest/use for the target filesystem. */
while (((fd == 0)
? ((aret = lgetxattrat (parentfd, file_name, attr,
val, asz)) == -1)
: ((aret = fgetxattr (fd, attr, val, asz)) == -1))
&& (errno == ERANGE))
{
val = x2nrealloc (val, &asz, 1);
}
if (aret != -1)
xheader_xattr_add (st, attr, val, aret);
else if (errno != ENOATTR)
call_arg_warn ((fd == 0) ? "lgetxattrat"
: "fgetxattr", file_name);
attr += len + 1;
xret -= len + 1;
}
}
#endif
}
}
#ifdef HAVE_XATTRS
static void
xattrs__fd_set (struct tar_stat_info const *st,
char const *file_name, char typeflag,
const char *attr, const char *ptr, size_t len)
{
if (ptr)
{
const char *sysname = "setxattrat";
int ret = -1;
if (typeflag != SYMTYPE)
ret = setxattrat (chdir_fd, file_name, attr, ptr, len, 0);
else
{
sysname = "lsetxattr";
ret = lsetxattrat (chdir_fd, file_name, attr, ptr, len, 0);
}
if (ret == -1)
WARNOPT (WARN_XATTR_WRITE,
(0, errno,
_("%s: Cannot set '%s' extended attribute for file '%s'"),
sysname, attr, file_name));
}
}
#endif
/* lgetfileconat is called against FILE_NAME iff the FD parameter is set to
zero, otherwise the fgetfileconat is used against correct file descriptor */
void
xattrs_selinux_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd)
{
if (selinux_context_option > 0)
{
#if HAVE_SELINUX_SELINUX_H != 1
static int done = 0;
if (!done)
WARN ((0, 0, _("SELinux support is not available")));
done = 1;
#else
int result = fd ?
fgetfilecon (fd, &st->cntx_name)
: lgetfileconat (parentfd, file_name, &st->cntx_name);
if (result == -1 && errno != ENODATA && errno != ENOTSUP)
call_arg_warn (fd ? "fgetfilecon" : "lgetfileconat", file_name);
#endif
}
}
void
xattrs_selinux_set (struct tar_stat_info const *st,
char const *file_name, char typeflag)
{
if (selinux_context_option > 0)
{
#if HAVE_SELINUX_SELINUX_H != 1
static int done = 0;
if (!done)
WARN ((0, 0, _("SELinux support is not available")));
done = 1;
#else
const char *sysname = "setfilecon";
int ret;
if (!st->cntx_name)
return;
if (typeflag != SYMTYPE)
{
ret = setfileconat (chdir_fd, file_name, st->cntx_name);
sysname = "setfileconat";
}
else
{
ret = lsetfileconat (chdir_fd, file_name, st->cntx_name);
sysname = "lsetfileconat";
}
if (ret == -1)
WARNOPT (WARN_XATTR_WRITE,
(0, errno,
_("%s: Cannot set SELinux context for file '%s'"),
sysname, file_name));
#endif
}
}
static bool
xattrs_matches_mask (const char *kw, struct xattrs_mask_map *mm)
{
int i;
if (!mm->size)
return false;
for (i = 0; i < mm->used; i++)
if (fnmatch (mm->masks[i], kw, 0) == 0)
return true;
return false;
}
#define USER_DOT_PFX "user."
static bool
xattrs_kw_included (const char *kw, bool archiving)
{
if (xattrs_setup.incl.size)
return xattrs_matches_mask (kw, &xattrs_setup.incl);
else if (archiving)
return true;
else
return strncmp (kw, USER_DOT_PFX, sizeof (USER_DOT_PFX) - 1) == 0;
}
static bool
xattrs_kw_excluded (const char *kw, bool archiving)
{
return xattrs_setup.excl.size ?
xattrs_matches_mask (kw, &xattrs_setup.excl) : false;
}
/* Check whether the xattr with keyword KW should be discarded from list of
attributes that are going to be archived/excluded (set ARCHIVING=true for
archiving, false for excluding) */
static bool
xattrs_masked_out (const char *kw, bool archiving)
{
return xattrs_kw_included (kw, archiving) ?
xattrs_kw_excluded (kw, archiving) : true;
}
void
xattrs_xattrs_set (struct tar_stat_info const *st,
char const *file_name, char typeflag, int later_run)
{
if (xattrs_option > 0)
{
#ifndef HAVE_XATTRS
static int done = 0;
if (!done)
WARN ((0, 0, _("XATTR support is not available")));
done = 1;
#else
size_t scan = 0;
if (!st->xattr_map_size)
return;
for (; scan < st->xattr_map_size; ++scan)
{
char *keyword = st->xattr_map[scan].xkey;
keyword += strlen ("SCHILY.xattr.");
/* TODO: this 'later_run' workaround is temporary solution -> once
capabilities should become fully supported by it's API and there
should exist something like xattrs_capabilities_set() call.
For a regular files: all extended attributes are restored during
the first run except 'security.capability' which is restored in
'later_run == 1'. */
if (typeflag == REGTYPE
&& later_run == !!strcmp (keyword, "security.capability"))
continue;
if (xattrs_masked_out (keyword, false /* extracting */ ))
/* we don't want to restore this keyword */
continue;
xattrs__fd_set (st, file_name, typeflag, keyword,
st->xattr_map[scan].xval_ptr,
st->xattr_map[scan].xval_len);
}
#endif
}
}
void
xattrs_print_char (struct tar_stat_info const *st, char *output)
{
int i;
if (verbose_option < 2)
{
*output = 0;
return;
}
if (xattrs_option > 0 || selinux_context_option > 0 || acls_option > 0)
{
/* placeholders */
*output = ' ';
output[1] = 0;
}
if (xattrs_option > 0 && st->xattr_map_size)
for (i = 0; i < st->xattr_map_size; ++i)
{
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
{
*output = '*';
break;
}
}
if (selinux_context_option > 0 && st->cntx_name)
*output = '.';
if (acls_option > 0 && (st->acls_a_len || st->acls_d_len))
*output = '+';
}
void
xattrs_print (struct tar_stat_info const *st)
{
if (verbose_option < 3)
return;
/* selinux */
if (selinux_context_option > 0 && st->cntx_name)
fprintf (stdlis, " s: %s\n", st->cntx_name);
/* acls */
if (acls_option > 0 && (st->acls_a_len || st->acls_d_len))
{
fprintf (stdlis, " a: ");
acls_one_line ("", ',', st->acls_a_ptr, st->acls_a_len);
acls_one_line ("default:", ',', st->acls_d_ptr, st->acls_d_len);
fprintf (stdlis, "\n");
}
/* xattrs */
if (xattrs_option > 0 && st->xattr_map_size)
{
int i;
for (i = 0; i < st->xattr_map_size; ++i)
{
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
fprintf (stdlis, " x: %lu %s\n",
(unsigned long) st->xattr_map[i].xval_len, keyword);
}
}
}

50
src/xattrs.h Normal file
View File

@@ -0,0 +1,50 @@
/* Support for extended attributes.
Copyright (C) 2006-2014 Free Software Foundation, Inc.
This file is part of GNU tar.
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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
Written by James Antill, on 2006-07-27. */
#ifndef GUARD_XATTTRS_H
#define GUARD_XATTTRS_H
/* Add include/exclude fnmatch pattern for xattr key domain. Set INCL parameter
to true/false if you want to add include/exclude pattern */
extern void xattrs_mask_add (const char *mask, bool incl);
/* clear helping structures when tar finishes */
extern void xattrs_clear_setup (void);
extern void xattrs_acls_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd, int xisfile);
extern void xattrs_selinux_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd);
extern void xattrs_xattrs_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd);
extern void xattrs_acls_set (struct tar_stat_info const *st,
char const *file_name, char typeflag);
extern void xattrs_selinux_set (struct tar_stat_info const *st,
char const *file_name, char typeflag);
extern void xattrs_xattrs_set (struct tar_stat_info const *st,
char const *file_name, char typeflag,
int later_run);
extern void xattrs_print_char (struct tar_stat_info const *st, char *output);
extern void xattrs_print (struct tar_stat_info const *st);
#endif /* GUARD_XATTTRS_H */

View File

@@ -1,21 +1,22 @@
/* POSIX extended headers for tar.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software
Copyright (C) 2003-2007, 2009-2010, 2012-2014 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 file is part of GNU tar.
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.
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 of the License, or
(at your option) any later version.
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. */
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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
@@ -86,10 +87,10 @@ struct keyword_list
/* List of keyword patterns set by delete= option */
static struct keyword_list *keyword_pattern_list;
/* List of keyword/value pairs set by `keyword=value' option */
/* List of keyword/value pairs set by 'keyword=value' option */
static struct keyword_list *keyword_global_override_list;
/* List of keyword/value pairs set by `keyword:=value' option */
/* List of keyword/value pairs set by 'keyword:=value' option */
static struct keyword_list *keyword_override_list;
/* List of keyword/value pairs decoded from the last 'g' type header */
@@ -167,14 +168,13 @@ xheader_set_single_keyword (char *kw)
static void
assign_time_option (char **sval, time_t *tval, const char *input)
{
uintmax_t u;
char *p;
time_t t = u = strtoumax (input, &p, 10);
if (t != u || *p || errno == ERANGE)
struct timespec t = decode_timespec (input, &p, false);
if (! valid_timespec (t) || *p)
ERROR ((0, 0, _("Time stamp is out of allowed range")));
else
{
*tval = t;
*tval = t.tv_sec;
assign_string (sval, input);
}
}
@@ -262,7 +262,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
char *dir = NULL;
char *base = NULL;
char pidbuf[UINTMAX_STRSIZE_BOUND];
char const *pptr;
char const *pptr = NULL;
char nbuf[UINTMAX_STRSIZE_BOUND];
char const *nptr = NULL;
@@ -335,13 +335,10 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
break;
case 'n':
if (nptr)
{
q = stpcpy (q, nptr);
p += 2;
break;
}
/* else fall through */
q = stpcpy (q, nptr);
p += 2;
break;
default:
*q++ = *p++;
@@ -455,11 +452,129 @@ xheader_write_global (struct xheader *xhdr)
char *name;
xheader_finish (xhdr);
xheader_write (XGLTYPE, name = xheader_ghdr_name (), time (NULL), xhdr);
name = xheader_ghdr_name ();
xheader_write (XGLTYPE, name, start_time.tv_sec, xhdr);
free (name);
}
}
void
xheader_xattr_init (struct tar_stat_info *st)
{
st->xattr_map = NULL;
st->xattr_map_size = 0;
st->acls_a_ptr = NULL;
st->acls_a_len = 0;
st->acls_d_ptr = NULL;
st->acls_d_len = 0;
st->cntx_name = NULL;
}
void
xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
{
size_t scan = 0;
while (scan < xattr_map_size)
{
free (xattr_map[scan].xkey);
free (xattr_map[scan].xval_ptr);
++scan;
}
free (xattr_map);
}
static void
xheader_xattr__add (struct xattr_array **xattr_map,
size_t *xattr_map_size,
const char *key, const char *val, size_t len)
{
size_t pos = (*xattr_map_size)++;
*xattr_map = xrealloc (*xattr_map,
*xattr_map_size * sizeof(struct xattr_array));
(*xattr_map)[pos].xkey = xstrdup (key);
(*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1);
(*xattr_map)[pos].xval_len = len;
}
/* This is reversal function for xattr_encode_keyword. See comment for
xattr_encode_keyword() for more info. */
static void
xattr_decode_keyword (char *keyword)
{
char *kpr, *kpl; /* keyword pointer left/right */
kpr = kpl = keyword;
for (;;)
{
if (*kpr == '%')
{
if (kpr[1] == '3' && kpr[2] == 'D')
{
*kpl = '=';
kpr += 3;
kpl ++;
continue;
}
else if (kpr[1] == '2' && kpr[2] == '5')
{
*kpl = '%';
kpr += 3;
kpl ++;
continue;
}
}
*kpl = *kpr;
if (*kpr == 0)
break;
kpr++;
kpl++;
}
}
void
xheader_xattr_add (struct tar_stat_info *st,
const char *key, const char *val, size_t len)
{
size_t klen = strlen (key);
char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1);
char *tmp = xkey;
tmp = stpcpy (tmp, "SCHILY.xattr.");
stpcpy (tmp, key);
xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len);
free (xkey);
}
void
xheader_xattr_copy (const struct tar_stat_info *st,
struct xattr_array **xattr_map, size_t *xattr_map_size)
{
size_t scan = 0;
*xattr_map = NULL;
*xattr_map_size = 0;
while (scan < st->xattr_map_size)
{
char *key = st->xattr_map[scan].xkey;
char *val = st->xattr_map[scan].xval_ptr;
size_t len = st->xattr_map[scan].xval_len;
xheader_xattr__add(xattr_map, xattr_map_size, key, val, len);
++scan;
}
}
/* General Interface */
@@ -473,6 +588,7 @@ struct xhdr_tab
struct xheader *, void const *data);
void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
int flags;
bool prefix; /* select handler comparing prefix only */
};
/* This declaration must be extern, because ISO C99 section 6.9.2
@@ -489,8 +605,17 @@ locate_handler (char const *keyword)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
if (strcmp (p->keyword, keyword) == 0)
return p;
if (p->prefix)
{
if (strncmp (p->keyword, keyword, strlen(p->keyword)) == 0)
return p;
}
else
{
if (strcmp (p->keyword, keyword) == 0)
return p;
}
return NULL;
}
@@ -500,7 +625,8 @@ xheader_protected_pattern_p (const char *pattern)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
if (!p->prefix && (p->flags & XHDR_PROTECTED)
&& fnmatch (pattern, p->keyword, 0) == 0)
return true;
return false;
}
@@ -511,7 +637,8 @@ xheader_protected_keyword_p (const char *keyword)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
if (!p->prefix && (p->flags & XHDR_PROTECTED)
&& strcmp (p->keyword, keyword) == 0)
return true;
return false;
}
@@ -526,7 +653,6 @@ decode_record (struct xheader *xhdr,
{
char *start = *ptr;
char *p = start;
uintmax_t u;
size_t len;
char *len_lim;
char const *keyword;
@@ -543,13 +669,7 @@ decode_record (struct xheader *xhdr,
return false;
}
errno = 0;
len = u = strtoumax (p, &len_lim, 10);
if (len != u || errno == ERANGE)
{
ERROR ((0, 0, _("Extended header length is out of allowed range")));
return false;
}
len = strtoumax (p, &len_lim, 10);
if (len_max < len)
{
@@ -618,7 +738,7 @@ decx (void *data, char const *keyword, char const *value, size_t size)
t->decoder (st, keyword, value, size);
else
WARNOPT (WARN_UNKNOWN_KEYWORD,
(0, 0, _("Ignoring unknown extended header keyword `%s'"),
(0, 0, _("Ignoring unknown extended header keyword '%s'"),
keyword));
}
@@ -691,10 +811,16 @@ xheader_store (char const *keyword, struct tar_stat_info *st,
}
void
xheader_read (struct xheader *xhdr, union block *p, size_t size)
xheader_read (struct xheader *xhdr, union block *p, off_t size)
{
size_t j = 0;
if (size < 0)
size = 0; /* Already diagnosed. */
if (SIZE_MAX - BLOCKSIZE <= size)
xalloc_die ();
size += BLOCKSIZE;
xhdr->size = size;
xhdr->buffer = xmalloc (size + 1);
@@ -721,15 +847,71 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
while (size > 0);
}
/* xattr_encode_keyword() substitutes '=' ~~> '%3D' and '%' ~~> '%25'
in extended attribute keywords. This is needed because the '=' character
has special purpose in extended attribute header - it splits keyword and
value part of header. If there was the '=' occurrence allowed inside
keyword, there would be no unambiguous way how to decode this extended
attribute.
(http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html)
*/
static char *
xattr_encode_keyword(const char *keyword)
{
static char *encode_buffer = NULL;
static size_t encode_buffer_size = 0;
size_t bp; /* keyword/buffer pointers */
if (!encode_buffer)
{
encode_buffer_size = 256;
encode_buffer = xmalloc (encode_buffer_size);
}
else
*encode_buffer = 0;
for (bp = 0; *keyword != 0; ++bp, ++keyword)
{
char c = *keyword;
if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
{
encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
}
if (c == '%')
{
strcpy (encode_buffer + bp, "%25");
bp += 2;
}
else if (c == '=')
{
strcpy (encode_buffer + bp, "%3D");
bp += 2;
}
else
encode_buffer[bp] = c;
}
encode_buffer[bp] = 0;
return encode_buffer;
}
static void
xheader_print_n (struct xheader *xhdr, char const *keyword,
char const *value, size_t vsize)
{
size_t len = strlen (keyword) + vsize + 3; /* ' ' + '=' + '\n' */
size_t p;
size_t n = 0;
char nbuf[UINTMAX_STRSIZE_BOUND];
char const *np;
size_t len, klen;
keyword = xattr_encode_keyword (keyword);
klen = strlen (keyword);
len = klen + vsize + 3; /* ' ' + '=' + '\n' */
do
{
@@ -741,7 +923,7 @@ xheader_print_n (struct xheader *xhdr, char const *keyword,
x_obstack_grow (xhdr, np, n);
x_obstack_1grow (xhdr, ' ');
x_obstack_grow (xhdr, keyword, strlen (keyword));
x_obstack_grow (xhdr, keyword, klen);
x_obstack_1grow (xhdr, '=');
x_obstack_grow (xhdr, value, vsize);
x_obstack_1grow (xhdr, '\n');
@@ -849,14 +1031,12 @@ xheader_string_end (struct xheader *xhdr, char const *keyword)
static void
out_of_range_header (char const *keyword, char const *value,
uintmax_t minus_minval, uintmax_t maxval)
intmax_t minval, uintmax_t maxval)
{
char minval_buf[UINTMAX_STRSIZE_BOUND + 1];
char minval_buf[INT_BUFSIZE_BOUND (intmax_t)];
char maxval_buf[UINTMAX_STRSIZE_BOUND];
char *minval_string = umaxtostr (minus_minval, minval_buf + 1);
char *minval_string = imaxtostr (minval, minval_buf);
char *maxval_string = umaxtostr (maxval, maxval_buf);
if (minus_minval)
*--minval_string = '-';
/* TRANSLATORS: The first %s is the pax extended header keyword
(atime, gid, etc.). */
@@ -899,140 +1079,74 @@ code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
xheader_print (xhdr, keyword, code_timespec (t, buf));
}
enum decode_time_status
{
decode_time_success,
decode_time_range,
decode_time_bad_header
};
static enum decode_time_status
_decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
time_t s;
unsigned long int ns = 0;
char *p;
char *arg_lim;
bool negative = *arg == '-';
errno = 0;
if (ISDIGIT (arg[negative]))
{
if (negative)
{
intmax_t i = strtoimax (arg, &arg_lim, 10);
if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
return decode_time_range;
s = i;
}
else
{
uintmax_t i = strtoumax (arg, &arg_lim, 10);
if (TYPE_MAXIMUM (time_t) < i)
return decode_time_range;
s = i;
}
p = arg_lim;
if (errno == ERANGE)
return decode_time_range;
if (*p == '.')
{
int digits = 0;
bool trailing_nonzero = false;
while (ISDIGIT (*++p))
if (digits < LOG10_BILLION)
{
ns = 10 * ns + (*p - '0');
digits++;
}
else
trailing_nonzero |= *p != '0';
while (digits++ < LOG10_BILLION)
ns *= 10;
if (negative)
{
/* Convert "-1.10000000000001" to s == -2, ns == 89999999.
I.e., truncate time stamps towards minus infinity while
converting them to internal form. */
ns += trailing_nonzero;
if (ns != 0)
{
if (s == TYPE_MINIMUM (time_t))
return decode_time_range;
s--;
ns = BILLION - ns;
}
}
}
if (! *p)
{
ts->tv_sec = s;
ts->tv_nsec = ns;
return decode_time_success;
}
}
return decode_time_bad_header;
}
static bool
decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
switch (_decode_time (ts, arg, keyword))
char *arg_lim;
struct timespec t = decode_timespec (arg, &arg_lim, true);
if (! valid_timespec (t))
{
case decode_time_success:
return true;
case decode_time_bad_header:
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
case decode_time_range:
out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
TYPE_MAXIMUM (time_t));
if (arg < arg_lim && !*arg_lim)
out_of_range_header (keyword, arg, TYPE_MINIMUM (time_t),
TYPE_MAXIMUM (time_t));
else
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
}
*ts = t;
return true;
}
static void
code_signed_num (uintmax_t value, char const *keyword,
intmax_t minval, uintmax_t maxval, struct xheader *xhdr)
{
char sbuf[SYSINT_BUFSIZE];
xheader_print (xhdr, keyword, sysinttostr (value, minval, maxval, sbuf));
}
static void
code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
{
char sbuf[UINTMAX_STRSIZE_BOUND];
xheader_print (xhdr, keyword, umaxtostr (value, sbuf));
code_signed_num (value, keyword, 0, UINTMAX_MAX, xhdr);
}
static bool
decode_signed_num (intmax_t *num, char const *arg,
intmax_t minval, uintmax_t maxval,
char const *keyword)
{
char *arg_lim;
intmax_t u = strtosysint (arg, &arg_lim, minval, maxval);
if (errno == EINVAL || *arg_lim)
{
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
}
if (errno == ERANGE)
{
out_of_range_header (keyword, arg, minval, maxval);
return false;
}
*num = u;
return true;
}
static bool
decode_num (uintmax_t *num, char const *arg, uintmax_t maxval,
char const *keyword)
{
uintmax_t u;
char *arg_lim;
if (! (ISDIGIT (*arg)
&& (errno = 0, u = strtoumax (arg, &arg_lim, 10), !*arg_lim)))
{
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
}
if (! (u <= maxval && errno != ERANGE))
{
out_of_range_header (keyword, arg, 0, maxval);
return false;
}
*num = u;
intmax_t i;
if (! decode_signed_num (&i, arg, 0, maxval, keyword))
return false;
*num = i;
return true;
}
@@ -1074,7 +1188,8 @@ static void
gid_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_num (st->stat.st_gid, keyword, xhdr);
code_signed_num (st->stat.st_gid, keyword,
TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t), xhdr);
}
static void
@@ -1083,8 +1198,9 @@ gid_decoder (struct tar_stat_info *st,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), keyword))
intmax_t u;
if (decode_signed_num (&u, arg, TYPE_MINIMUM (gid_t),
TYPE_MAXIMUM (gid_t), keyword))
st->stat.st_gid = u;
}
@@ -1197,7 +1313,8 @@ static void
uid_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_num (st->stat.st_uid, keyword, xhdr);
code_signed_num (st->stat.st_uid, keyword,
TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t), xhdr);
}
static void
@@ -1206,8 +1323,9 @@ uid_decoder (struct tar_stat_info *st,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), keyword))
intmax_t u;
if (decode_signed_num (&u, arg, TYPE_MINIMUM (uid_t),
TYPE_MAXIMUM (uid_t), keyword))
st->stat.st_uid = u;
}
@@ -1329,7 +1447,7 @@ sparse_map_decoder (struct tar_stat_info *st,
st->sparse_map_avail = 0;
while (1)
{
uintmax_t u;
intmax_t u;
char *delim;
struct sp_array e;
@@ -1341,11 +1459,16 @@ sparse_map_decoder (struct tar_stat_info *st,
}
errno = 0;
u = strtoumax (arg, &delim, 10);
u = strtoimax (arg, &delim, 10);
if (TYPE_MAXIMUM (off_t) < u)
{
u = TYPE_MAXIMUM (off_t);
errno = ERANGE;
}
if (offset)
{
e.offset = u;
if (!(u == e.offset && errno != ERANGE))
if (errno == ERANGE)
{
out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
return;
@@ -1354,7 +1477,7 @@ sparse_map_decoder (struct tar_stat_info *st,
else
{
e.numbytes = u;
if (!(u == e.numbytes && errno != ERANGE))
if (errno == ERANGE)
{
out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
return;
@@ -1469,6 +1592,80 @@ volume_filename_decoder (struct tar_stat_info *st,
decode_string (&continued_file_name, arg);
}
static void
xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
code_string (st->cntx_name, keyword, xhdr);
}
static void
xattr_selinux_decoder (struct tar_stat_info *st,
char const *keyword, char const *arg, size_t size)
{
decode_string (&st->cntx_name, arg);
}
static void
xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
struct xheader *xhdr, void const *data)
{
xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len);
}
static void
xattr_acls_a_decoder (struct tar_stat_info *st,
char const *keyword, char const *arg, size_t size)
{
st->acls_a_ptr = xmemdup (arg, size + 1);
st->acls_a_len = size;
}
static void
xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword,
struct xheader *xhdr, void const *data)
{
xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len);
}
static void
xattr_acls_d_decoder (struct tar_stat_info *st,
char const *keyword, char const *arg, size_t size)
{
st->acls_d_ptr = xmemdup (arg, size + 1);
st->acls_d_len = size;
}
static void
xattr_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
struct xattr_array *xattr_map = st->xattr_map;
const size_t *off = data;
xheader_print_n (xhdr, keyword,
xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
}
static void
xattr_decoder (struct tar_stat_info *st,
char const *keyword, char const *arg, size_t size)
{
char *xstr, *xkey;
/* copy keyword */
size_t klen_raw = strlen (keyword);
xkey = alloca (klen_raw + 1);
memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
/* copy value */
xstr = alloca (size + 1);
memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
xattr_decode_keyword (xkey);
xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
}
static void
sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
@@ -1506,53 +1703,53 @@ sparse_minor_decoder (struct tar_stat_info *st,
}
struct xhdr_tab const xhdr_tab[] = {
{ "atime", atime_coder, atime_decoder, 0 },
{ "comment", dummy_coder, dummy_decoder, 0 },
{ "charset", dummy_coder, dummy_decoder, 0 },
{ "ctime", ctime_coder, ctime_decoder, 0 },
{ "gid", gid_coder, gid_decoder, 0 },
{ "gname", gname_coder, gname_decoder, 0 },
{ "linkpath", linkpath_coder, linkpath_decoder, 0 },
{ "mtime", mtime_coder, mtime_decoder, 0 },
{ "path", path_coder, path_decoder, 0 },
{ "size", size_coder, size_decoder, 0 },
{ "uid", uid_coder, uid_decoder, 0 },
{ "uname", uname_coder, uname_decoder, 0 },
{ "atime", atime_coder, atime_decoder, 0, false },
{ "comment", dummy_coder, dummy_decoder, 0, false },
{ "charset", dummy_coder, dummy_decoder, 0, false },
{ "ctime", ctime_coder, ctime_decoder, 0, false },
{ "gid", gid_coder, gid_decoder, 0, false },
{ "gname", gname_coder, gname_decoder, 0, false },
{ "linkpath", linkpath_coder, linkpath_decoder, 0, false },
{ "mtime", mtime_coder, mtime_decoder, 0, false },
{ "path", path_coder, path_decoder, 0, false },
{ "size", size_coder, size_decoder, 0, false },
{ "uid", uid_coder, uid_decoder, 0, false },
{ "uname", uname_coder, uname_decoder, 0, false },
/* Sparse file handling */
{ "GNU.sparse.name", path_coder, path_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
{ "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
{ "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
{ "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
/* tar 1.14 - 1.15.90 keywords. */
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
/* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
headers, and each of them was meaningful. It confilcted with POSIX specs,
which requires that "when extended header records conflict, the last one
given in the header shall take precedence." */
{ "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
/* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
{ "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
sparse_map_decoder, 0 },
sparse_map_decoder, 0, false },
{ "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
XHDR_PROTECTED },
XHDR_PROTECTED, false },
/* Keeps the tape/volume label. May be present only in the global headers.
Equivalent to GNUTYPE_VOLHDR. */
{ "GNU.volume.label", volume_label_coder, volume_label_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
XHDR_PROTECTED | XHDR_GLOBAL, false },
/* These may be present in a first global header of the archive.
They provide the same functionality as GNUTYPE_MULTIVOL header.
@@ -1561,11 +1758,28 @@ struct xhdr_tab const xhdr_tab[] = {
GNU.volume.offset keeps the offset of the start of this volume,
otherwise kept in oldgnu_header.offset. */
{ "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
XHDR_PROTECTED | XHDR_GLOBAL, false },
{ "GNU.volume.size", volume_size_coder, volume_size_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
XHDR_PROTECTED | XHDR_GLOBAL, false },
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
XHDR_PROTECTED | XHDR_GLOBAL, false },
{ NULL, NULL, NULL, 0 }
/* We get the SELinux value from filecon, so add a namespace for SELinux
instead of storing it in SCHILY.xattr.* (which would be RAW). */
{ "RHT.security.selinux",
xattr_selinux_coder, xattr_selinux_decoder, 0, false },
/* ACLs, use the star format... */
{ "SCHILY.acl.access",
xattr_acls_a_coder, xattr_acls_a_decoder, 0, false },
{ "SCHILY.acl.default",
xattr_acls_d_coder, xattr_acls_d_decoder, 0, false },
/* We are storing all extended attributes using this rule even if some of them
were stored by some previous rule (duplicates) -- we just have to make sure
they are restored *only once* during extraction later on. */
{ "SCHILY.xattr", xattr_coder, xattr_decoder, 0, true },
{ NULL, NULL, NULL, 0, false }
};

View File

@@ -1,25 +1,21 @@
# Makefile for GNU tar regression tests.
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
# 2006, 2007, 2009 Free Software Foundation, Inc.
# Copyright 1996-1997, 1999-2001, 2003-2007, 2009, 2012-2013 Free Software
# François Pinard <pinard@iro.umontreal.ca>, 1988.
# Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
# This file is part of GNU tar.
## 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.
# 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 of the License, or
# (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# 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 this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301, USA.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 star/README star/quicktest.sh
DISTCLEANFILES = atconfig $(check_SCRIPTS)
@@ -46,12 +42,20 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## ------------ ##
TESTSUITE_AT = \
T-cd.at\
T-empty.at\
T-null.at\
T-rec.at\
T-zfile.at\
T-nonl.at\
T-mult.at\
T-nest.at\
testsuite.at\
append.at\
append01.at\
append02.at\
append03.at\
append04.at\
backup01.at\
chtype.at\
comprec.at\
@@ -67,6 +71,16 @@ TESTSUITE_AT = \
exclude04.at\
exclude05.at\
exclude06.at\
exclude07.at\
exclude08.at\
exclude09.at\
exclude10.at\
exclude11.at\
exclude12.at\
exclude13.at\
exclude14.at\
exclude15.at\
exclude16.at\
extrac01.at\
extrac02.at\
extrac03.at\
@@ -82,6 +96,10 @@ TESTSUITE_AT = \
extrac13.at\
extrac14.at\
extrac15.at\
extrac16.at\
extrac17.at\
extrac18.at\
extrac19.at\
filerem01.at\
filerem02.at\
gzip.at\
@@ -93,8 +111,12 @@ TESTSUITE_AT = \
incr04.at\
incr05.at\
incr06.at\
incr07.at\
incr08.at\
incr09.at\
indexfile.at\
ignfail.at\
iotty.at\
label01.at\
label02.at\
label03.at\
@@ -107,6 +129,8 @@ TESTSUITE_AT = \
listed01.at\
listed02.at\
listed03.at\
listed04.at\
listed05.at\
long01.at\
longv7.at\
lustar01.at\
@@ -121,10 +145,22 @@ TESTSUITE_AT = \
multiv07.at\
multiv08.at\
old.at\
onetop01.at\
onetop02.at\
onetop03.at\
onetop04.at\
opcomp01.at\
opcomp02.at\
opcomp03.at\
opcomp04.at\
opcomp05.at\
opcomp06.at\
options.at\
options02.at\
owner.at\
pipe.at\
recurse.at\
recurs02.at\
rename01.at\
rename02.at\
rename03.at\
@@ -133,6 +169,25 @@ TESTSUITE_AT = \
remfiles01.at\
remfiles02.at\
remfiles03.at\
remfiles04a.at\
remfiles04b.at\
remfiles04c.at\
remfiles05a.at\
remfiles05b.at\
remfiles05c.at\
remfiles06a.at\
remfiles06b.at\
remfiles06c.at\
remfiles07a.at\
remfiles07b.at\
remfiles07c.at\
remfiles08a.at\
remfiles08b.at\
remfiles08c.at\
remfiles09a.at\
remfiles09b.at\
remfiles09c.at\
remfiles10.at\
same-order01.at\
same-order02.at\
shortfile.at\
@@ -142,11 +197,13 @@ TESTSUITE_AT = \
sparse01.at\
sparse02.at\
sparse03.at\
sparse04.at\
sparsemv.at\
sparsemvp.at\
spmvp00.at\
spmvp01.at\
spmvp10.at\
time01.at\
truncate.at\
update.at\
update01.at\
@@ -154,6 +211,7 @@ TESTSUITE_AT = \
volsize.at\
volume.at\
verbose.at\
verify.at\
version.at\
xform-h.at\
xform01.at\
@@ -162,7 +220,18 @@ TESTSUITE_AT = \
star/multi-fail.at\
star/ustar-big-2g.at\
star/ustar-big-8g.at\
star/pax-big-10g.at
star/pax-big-10g.at\
xattr01.at\
xattr02.at\
xattr03.at\
xattr04.at\
xattr05.at\
acls01.at\
acls02.at\
acls03.at\
selnx01.at\
selacl01.at\
capabs_raw01.at
TESTSUITE = $(srcdir)/testsuite
@@ -196,9 +265,20 @@ installcheck-local:
check_PROGRAMS = genfile
if TAR_COND_GRANTPT
check_PROGRAMS += ttyemu
endif
genfile_SOURCES = genfile.c argcv.c argcv.h
ttyemu_SOURCES = ttyemu.c
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/gnu -I../gnu -I$(top_srcdir)/gnu -I$(top_srcdir)/lib
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
AM_CPPFLAGS = \
-I$(top_srcdir)/gnu\
-I../gnu\
-I$(top_srcdir)/gnu\
-I$(top_srcdir)/lib\
-DLOCALEDIR=\"$(localedir)\"
LDADD = ../gnu/libgnu.a $(LIBINTL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)

44
tests/T-cd.at Normal file
View File

@@ -0,0 +1,44 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([-C in file lists])
AT_KEYWORDS([files-from T-cd])
AT_TAR_CHECK([
AT_SORT_PREREQ
>file1
mkdir dir
>dir/file2
>dir/file3
AT_DATA([F1],[file1
-C dir
.
])
tar cf archive -T F1
tar tf archive | sort
],
[0],
[./
./file2
./file3
file1
],[],[],[],[ustar])
AT_CLEANUP

View File

@@ -1,30 +1,30 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
# Copyright 2006-2007, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Tar 1.16 coredumped if a filelist file contained empty (zero-length)
# entries
# Reported by: Karl Berry <karl@freefriends.org>
# References: <200610301353.k9UDr1O30680@f7.net>
AT_SETUP([files-from: empty entries])
AT_KEYWORDS([files-from empty])
AT_SETUP([empty entries])
AT_KEYWORDS([files-from empty-line])
AT_DATA([file-list],
[jeden
@@ -34,17 +34,16 @@ trzy
])
AT_TAR_CHECK([
AT_SORT_PREREQ
genfile --file jeden
genfile --file dwa
genfile --file trzy
tar cfvT archive ../file-list | sort
tar cfvT archive ../file-list
],
[0],
[dwa
jeden
[jeden
dwa
trzy
],
[],[],[],[ustar]) # Testing one format is enough

46
tests/T-mult.at Normal file
View File

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([multiple file lists])
AT_KEYWORDS([files-from T-mult])
AT_TAR_CHECK([
>file1
>file2
>file3
>file4
AT_DATA([F1],[file1
file2
])
AT_DATA([F2],[file3
file4
])
tar cf archive -T F1 -T F2
tar tf archive
],
[0],
[file1
file2
file3
file4
],[],[],[],[ustar])
AT_CLEANUP

46
tests/T-nest.at Normal file
View File

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([nested file lists])
AT_KEYWORDS([files-from T-nest])
AT_TAR_CHECK([
>file1
>file2
>file3
>file4
AT_DATA([F1],[file1
-T F2
file2
])
AT_DATA([F2],[file3
file4
])
tar cf archive -T F1
tar tf archive
],
[0],
[file1
file3
file4
file2
],[],[],[],[ustar])
AT_CLEANUP

62
tests/T-nonl.at Normal file
View File

@@ -0,0 +1,62 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
# Tar malfunctioned when given a file list with the last line not ending
# in a newline.
#
# Reported by: Michal Žejdl <zejdl@suas.cz>
# References: <http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html>
AT_SETUP([entries with missing newlines])
AT_KEYWORDS([files-from nonewline nonl T-nonl])
AT_TAR_CHECK([
genfile --length=0 --file empty
AS_ECHO_N(c) > 1.nonl
echo d > 2.nonl
AS_ECHO_N(e) >> 2.nonl
touch a b c d e
AT_DATA([filelist],[a
b
])
tar cf archive -T empty -T 1.nonl -T 2.nonl -T filelist
tar tf archive
echo ==
tar cf archive -T 2.nonl -T empty -T filelist -T 1.nonl
tar tf archive
],
[0],
[c
d
e
a
b
==
d
e
a
b
c
],
[],[],[],[ustar])
AT_CLEANUP

View File

@@ -1,47 +1,45 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
# Copyright 2006-2007, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([files-from: 0-separated file without -0])
AT_SETUP([0-separated file without -0])
AT_KEYWORDS([files-from null T-null])
AT_DATA([expout],[jeden\ndwa
trzy
])
AT_TAR_CHECK([
AT_SORT_PREREQ
echo dwa > temp
echo jeden > temp
echo dwa >> temp
echo trzy >> temp
cat temp | tr '\n' '\0' > temp1
echo jeden > file-list
cat temp1 >> file-list
cat temp | tr '\n' '\0' > file-list
genfile -f "jeden
dwa" || AT_SKIP_TEST
genfile -f jeden
genfile -f dwa
genfile -f trzy
tar cfTv archive file-list | sort
tar cfTv archive file-list
],
[0],
[expout],
[jeden
dwa
trzy
],
[tar: file-list: file name read contains nul character
],[],[],[ustar]) # Testing one format is enough

46
tests/T-rec.at Normal file
View File

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([recursive file lists])
AT_KEYWORDS([files-from T-rec])
AT_TAR_CHECK([
>file1
>file2
AT_DATA([F1],[file1
-T F2
])
AT_DATA([F2],[file2
-T F1
])
tar cf archive -T F1
echo $?
tar tf archive
],
[0],
[2
file1
file2
],
[tar: F1: file list requested from F2 already read from command line
tar: Exiting with failure status due to previous errors
],[],[],[ustar])
AT_CLEANUP

52
tests/T-zfile.at Normal file
View File

@@ -0,0 +1,52 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
# Tar malfunctioned when given empty file as an argument to -T.
#
# Reported by: Michal Žejdl <zejdl@suas.cz>
# References: <http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html>
AT_SETUP([empty file])
AT_KEYWORDS([files-from empty-file])
AT_TAR_CHECK([
genfile --length=0 --file empty
genfile --file a
genfile --file b
AT_DATA([valid],[a
b
])
tar cf archive -T empty -T valid
tar tf archive
echo "=="
tar cf archive -T valid -T empty
tar tf archive
],
[0],
[a
b
==
a
b
],
[],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

55
tests/acls01.at Normal file
View File

@@ -0,0 +1,55 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2011, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# Test description:
#
# This is basic test for acl support.
AT_SETUP([acls: basic functionality])
AT_KEYWORDS([xattrs acls acls01])
AT_TAR_CHECK([
AT_XATTRS_UTILS_PREREQ
AT_ACLS_PREREQ
mkdir dir
genfile --file dir/file
MYNAME=$( id -un )
setfacl -m u:$MYNAME:--x dir/file
setfacl -m u:$MYNAME:--x dir
getfattr -h -m. -d dir dir/file > before
tar --acls -cf archive.tar dir
rm -rf dir
tar --acls -xf archive.tar
getfattr -h -m. -d dir dir/file > after
diff before after
test "$?" = 0
],
[0],
[])
AT_CLEANUP

61
tests/acls02.at Normal file
View File

@@ -0,0 +1,61 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2011, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# Test description:
#
# This is basic test for acl support.
AT_SETUP([acls: work with -C])
AT_KEYWORDS([xattrs acls acls02])
AT_TAR_CHECK([
AT_XATTRS_UTILS_PREREQ
AT_ACLS_PREREQ
mkdir dir
mkdir dir/subdir
genfile --file dir/subdir/file
MYNAME=$( id -un )
setfacl -m u:$MYNAME:--x dir/subdir
setfacl -m u:$MYNAME:--x dir/subdir/file
cd dir
getfattr -h -m. -d subdir subdir/file > ../before
cd ..
tar --acls -cf archive.tar -C dir subdir
rm -rf dir
mkdir dir
tar --acls -xf archive.tar -C dir
cd dir
getfattr -h -m. -d subdir subdir/file > ../after
cd ..
diff before after
test "$?" = 0
],
[0],
[])
AT_CLEANUP

131
tests/acls03.at Normal file
View File

@@ -0,0 +1,131 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013, 2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# Test description:
#
# Check the storing/restoring with/without default ACLs. When --acls is passed,
# restored directory tree should always match archive contents (even when the
# archive does not contain any ACLs).
#
# References:
# http://www.mail-archive.com/bug-tar@gnu.org/msg04355.html
AT_SETUP([acls: default ACLs])
AT_KEYWORDS([xattrs acls acls03])
m4_define([ACL_LISTDIR], [
cd $1
$1="$(find d1 | sort | xargs -n 1 getfacl)"
cd ..
])
m4_define([ACL_ASSERT], [
echo "$$1" > $1.log
echo "$$2" > $2.log
if test ! "$$1" "$3" "$$2"; then
echo "bad '$1' against '$2' output"
fi
])
AT_TAR_CHECK([
AT_XATTRS_UTILS_PREREQ
AT_ACLS_PREREQ
AT_SORT_PREREQ
MYNAME=$( id -un )
MYGROUP=$( id -gn )
# Prepare directory structure with default ACLs
mkdir -p pure/d1/d2
genfile --file pure/d1/f2a
genfile --file pure/d1/f2b
genfile --file pure/d1/d2/f3a
genfile --file pure/d1/d2/f3b
setfacl -m g:$MYGROUP:r-x pure/d1
setfacl -d -m g:$MYGROUP:rwx pure/d1
setfacl -d -m u:$MYNAME:rwx pure/d1
# "*a" files have "some" additional ACLs
setfacl -m u:$MYNAME:--- pure/d1/d2/f3a
setfacl -m u:$MYNAME:--- pure/d1/f2a
# use default format (no acls stored)
tar -cf noacl.tar -C pure d1
# use posix format, acls stored
tar --acls -cf acl.tar -C pure d1
# Directory names are chosen based on "how the files were extracted from
# archive". Equivalent no* tags are used also:
# ^sacl_ — extracted archive has stored ACLs
# _def_ — target directory (-C) has default ACLs
# _optacl$ — extraction was done with --acls option
mkdir sacl_def_optacl
mkdir sacl_def_optnoacl
mkdir sacl_nodef_optacl
mkdir sacl_nodef_optnoacl
mkdir nosacl_def_optacl
mkdir nosacl_def_optnoacl
mkdir nosacl_nodef_optacl
mkdir nosacl_nodef_optnoacl
setfacl -d -m u:$MYNAME:--- nosacl_def_optnoacl sacl_def_optnoacl sacl_def_optacl nosacl_def_optacl
setfacl -d -m g:$MYGROUP:--- nosacl_def_optnoacl sacl_def_optnoacl sacl_def_optacl nosacl_def_optacl
tar -xf acl.tar -C sacl_nodef_optnoacl
tar --acls -xf acl.tar -C sacl_nodef_optacl
tar -xf acl.tar -C sacl_def_optnoacl
tar --acls -xf acl.tar -C sacl_def_optacl
tar -xf noacl.tar -C nosacl_def_optnoacl
# _NO_ ACLs in output
tar -xf noacl.tar -C nosacl_nodef_optnoacl
tar -xf noacl.tar -C nosacl_nodef_optacl
tar -cf noacl_repackaged.tar -C nosacl_nodef_optnoacl d1
# _NO_ ACLs in output (even when default ACLs exist)
tar --acls -xf noacl_repackaged.tar -C nosacl_def_optacl
ACL_LISTDIR(pure)
ACL_LISTDIR(sacl_def_optacl)
ACL_LISTDIR(sacl_def_optnoacl)
ACL_LISTDIR(sacl_nodef_optacl)
ACL_LISTDIR(sacl_nodef_optnoacl)
ACL_LISTDIR(nosacl_def_optacl)
ACL_LISTDIR(nosacl_def_optnoacl)
ACL_LISTDIR(nosacl_nodef_optacl)
ACL_LISTDIR(nosacl_nodef_optnoacl)
ACL_ASSERT(pure, sacl_def_optacl, =)
ACL_ASSERT(sacl_def_optacl, sacl_nodef_optacl, =)
ACL_ASSERT(sacl_def_optnoacl, nosacl_def_optnoacl, =)
ACL_ASSERT(sacl_nodef_optnoacl, nosacl_nodef_optnoacl, =)
ACL_ASSERT(nosacl_def_optacl, nosacl_nodef_optacl, =)
ACL_ASSERT(nosacl_def_optacl, nosacl_nodef_optnoacl, =)
ACL_ASSERT(sacl_def_optacl, sacl_def_optnoacl, !=)
ACL_ASSERT(sacl_def_optacl, nosacl_def_optnoacl, !=)
ACL_ASSERT(nosacl_def_optnoacl, nosacl_nodef_optnoacl, !=)
],
[0],
[],
[])
AT_CLEANUP

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
# Copyright 2004, 2006-2007, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([append])
AT_KEYWORDS([append append00])

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
# Copyright 2005-2007, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# When decoding a header tar was assigning 0 to oldgnu_header.isextended,
# which destroyed name prefix. When updating archive, modified prefix
@@ -29,7 +29,7 @@
AT_SETUP([appending files with long names])
AT_KEYWORDS([append append01])
m4_define([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_appending_long_file_names_that_run_into_a_limit_of_the_ustar_tarX])
m4_pushdef([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_appending_long_file_names_that_run_into_a_limit_of_the_ustar_tarX])
AT_TAR_CHECK([
mkdir PREFIX
@@ -44,4 +44,5 @@ PREFIX/file2
],
[],[],[],[oldgnu, ustar, posix, gnu])
m4_popdef([PREFIX])
AT_CLEANUP

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
# Copyright 2006-2007, 2009, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Using tar 1.15.x the following equivalent command sets:
#

45
tests/append03.at Normal file
View File

@@ -0,0 +1,45 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2010, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([append with name transformation])
AT_KEYWORDS([append append03])
# Description: Make sure filenames are transformed during append.
AT_TAR_CHECK([
genfile --file file.1
genfile --file file.2
tar -c -f archive --transform 's/file/plik/' file.*
echo Appending
tar -r -f archive --transform 's/file/plik/' -v --show-transformed-names file.1
echo Testing
tar tf archive
],
[0],
[Appending
plik.1
Testing
plik.1
plik.2
plik.1
])
AT_CLEANUP

60
tests/append04.at Normal file
View File

@@ -0,0 +1,60 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
# When called with --append and --verify options, tar would rewrite the
# archive instead of appending to it.
#
# Last-Affected-Version: 1.26
# Reported-by: Jivko Angelov <jivko@siteground.com>
# References: <51D6983C.3060404@siteground.com>,
# http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00003.html
AT_SETUP([append with verify])
AT_KEYWORDS([append append04 verify append-verify])
AT_TAR_CHECK([
# Create two empty files:
touch file1 file2
# Create an archive:
tar cpfW archive.tar file1 file2
# Verify created archive by listing its content:
tar -tf archive.tar
echo ==
# Create another empty file:
touch file3
# Append it to the already created archive:
tar rpfW archive.tar file3
# Verify content of the new archive:
tar -tf archive.tar
],
[0],
[file1
file2
==
file1
file2
file3
])
AT_CLEANUP

View File

@@ -1,6 +1,21 @@
# @configure_input@ -*- shell-script -*-
# Configurable variable values for tar test suite.
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
# Copyright 2004, 2006, 2013-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_srcdir@/build-aux:$top_srcdir:$srcdir:$PATH
@@ -34,3 +49,11 @@ decho() {
echo $*
echo >&2 $*
}
mkexcltest() {
mkdir $1 $1/subdir
genfile --file=$1/top-level-file
genfile --file=$1/subdir/excludeme
genfile --file=$1/subdir/subdir-file
}

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2009 Free Software Foundation, Inc.
# Copyright 2009-2010, 2013-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# 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.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Description:
# When extracting, tar (<1.22) sometimes renamed a backup back to the
@@ -34,6 +34,7 @@ AT_SETUP([extracting existing dir with --backup])
AT_KEYWORDS([extract backup backup01])
AT_TAR_CHECK([
unset VERSION_CONTROL
mkdir dir1 dir2
echo bla > dir1/file1
tar cf test.tar dir1 dir2
@@ -42,7 +43,7 @@ tar xfv test.tar --backup --warning=no-timestamp
[0],
[dir1/
dir1/file1
Renaming `dir1/file1' to `dir1/file1~'
Renaming 'dir1/file1' to 'dir1/file1~'
dir2/
])

53
tests/capabs_raw01.at Normal file
View File

@@ -0,0 +1,53 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2012-2014 Free Software Foundation, Inc.
# This file is part of GNU tar.
# 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# Test description: Test if file capabilities are archived/restored correctly
# using just the default xattr support (capabilities are stored/restored in
# binary format -> system dependant).
AT_SETUP([capabilities: binary store/restore])
AT_KEYWORDS([xattrs capabilities capabs_raw01])
AT_TAR_CHECK([
AT_PRIVILEGED_PREREQ
AT_XATTRS_PREREQ
AT_CAPABILITIES_UTILS_PREREQ
mkdir dir
genfile --file dir/file
setcap "= cap_chown=ei" dir/file
# archive whole directory including binary xattrs
tar --xattrs -cf archive.tar dir
# clear the directory
rm -rf dir
# restore _all_ xattrs (not just the user.* domain)
tar --xattrs --xattrs-include='*' -xf archive.tar
getcap dir/file
],
[0],
[dir/file = cap_chown+ei
])
AT_CLEANUP

Some files were not shown because too many files have changed in this diff Show More