318 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
Sergey Poznyakoff
983113b140 Version 1.24
* configure.ac, NEWS: Version 1.24
* bootstrap: Restore tar-specific code lost during last
sync from gnulib (241b72ffad).
* src/misc.c (chdir_do): Remove unused automatic variable.
2010-10-25 00:35:50 +03:00
Paul Eggert
9447e799ab tar: use more-accurate diagnostic when intermediate mkdir fails
Without this change, if tar tried to extract a file A/B/C, noticed
that A/B didn't exist, attempted to mkdir A/B, and the mkdir
failed, it did not diagnose the mkdir failure, but simply reported
the failure to open A/B/C.  This sometimes led to confusion
because it wasn't clear what tar was trying to do, in particular
that tar tried to mkdir A/B.  With this patch, tar issues two
diagnostics in this case: one for A/B and the other for A/B/C.
Problem reported by Hauke Laging in
<http://lists.gnu.org/archive/html/bug-tar/2010-10/msg00020.html>.
* gnulib.modules: Remove faccessat.
* src/extract.c (make_directories): New arg INTERDIR_MADE.
Diagnose mkdir failure.  Return 0 on success, nonzero on failure,
as opposed to nonzero iff some directory was created.  All callers
changed.  Simplify the code when mkdir fails, by checking whether
the desired file exists unless errno==EEXIST: this is more robust.
* tests/extrac15.at: New test, to check this.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2010-10-15 22:26:43 -07:00
Paul Eggert
502abd93bd tests: port to NFS file servers with clock skew
Several of the tests assumed that a newly created file cannot
have a time stamp dated in the future.  This assumption is not
true when files are served by a remote host whose clock is
slightly in advance of ours.  Fix the problems that I observed
when running "make check" a couple of times on such a server.

* tests/backup01.at: Use --warning=no-timestamp to suppress
clock-skew warnings.
* tests/chtype.at, tests/comprec.at, tests/exclude06.at:
* tests/extrac01.at, tests/extrac03.at, tests/extrac05.at:
* tests/extrac06.at, tests/extrac08.at, tests/extrac13.at:
* tests/extrac14.at, tests/incr01.at, tests/incr03.at, tests/link01.at:
* tests/multiv01.at, tests/multiv02.at, tests/multiv03.at:
* tests/pipe.at, tests/rename02.at, tests/rename03.at:
* tests/rename05.at, tests/same-order01.at, tests/same-order02.at:
* tests/sparse01.at:
Likewise.
2010-10-15 21:53:37 -07:00
Paul Eggert
241b72ffad gnulib: sync from latest gnulib, notably bootstrap and parse-datetime
* bootstrap: Sync from gnulib.
* doc/.gitignore: Rename getdate.texi to parse-datetime.texi.
* doc/Makefile.am (tar_TEXINFOS): Likewise.
* doc/tar.texi (Top): Adjust to renaming of getdate to parse-datetime.
* gnulib.modules: Likewise.  Also, remove ftruncate (now obsolete).
And add inttostr (we missed this dependency).
* src/tar.c: Include parse-datetime.h, not getdate.h.  All calls
to get_date replaced with parse_datetime.
2010-10-11 16:25:32 -07:00
Paul Eggert
c5c196310e tar: -x -C symlink fix
* src/misc.c (chdir_do): Don't use O_NOFOLLOW when opening the
argument to -C.  This is for consistency with "tar -c -C FOO", and
matches the new documentation.
* tests/extrac14.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2010-09-24 13:13:47 -07:00
Paul Eggert
14efeb9f95 tar: --dereference consistency
This closes another race condition, that occurs when overwriting a
symlink with a regular file.
* NEWS (--dereference consistency): New section.
* doc/tar.texi (Option Summary): Describe new --deference behavior.
(dereference): Likewise.  Remove discussion that I didn't follow,
even before --dereference was changed.
* src/common.h (deref_stat, set_file_atime): Adjust signatures.
* src/compare.c (diff_file, diff_multivol): Respect open_read_flags
instead of rolling our own flags.  This implements the new behavior
for --dereference.
(diff_file, diff_dumpdir): Likewise, for fstatat_flags.
* src/create.c: Adjust to set_file_atime signature change.
* src/extract.c (mark_after_links, file_newer_p, extract_dir):
Likewise.
* src/incremen.c (try_purge_directory): Likewise.
* src/misc.c (maybe_backup_file): Likewise.
* src/extract.c (file_newer_p): New arg STP.  All callers changed.
(maybe_recoverable): New arg REGULAR.  All callers changed.
Handle the case of overwriting a symlink with a regular file,
when --overwrite is specified but --dereference is not.
(open_output_file): Add O_CLOEXEC, O_NOCTTY, O_NONBLOCK for
consistency with file creation.  Add O_NOFOLLOW if
overwriting_old_files && ! dereference_option.
* src/incremen.c (update_parent_directory): Use fstat, not fstatat;
there's less to go wrong.
* src/misc.c (deref_stat): Remove DEREF arg.  All callers changed.
Instead, use fstatat_flags.
(set_file_atime): Remove ATFLAG arg.  All callers changed.
Instead, use fstatat_flags.
* src/names.c, src/update.c: Adjust to deref_stat signature change.
* src/tar.c (get_date_or_file): Use stat, not deref_stat, as this
is not a file to be archived.
* tests/Makefile.am (TESTSUITE_AT): Add extrac13.at.
* tests/extrac13.at: New file.
* tests/testsuite.at: Include it.
2010-09-23 19:41:47 -07:00
Paul Eggert
efe26f98ec tar: do not crash with --listed-incremental
Problem reported by Frantisek Hanzlik in
<https://bugzilla.redhat.com/635318> via Kamil Dudka in
<http://lists.gnu.org/archive/html/bug-tar/2010-09/msg00066.html>.
I don't understand this code either, but Sergey can take a look at
this patch, and perhaps install a better one, when he has the time.
* src/incremen.c (append_incremental_renames): Don't actually append
anything to DIR if DIR is null.
2010-09-20 11:35:04 -07:00
Paul Eggert
4bde4f39d0 tar: prefer openat-style functions
This change replaces traditional functions like 'open' with the
POSIX.1-2008 functions like 'openat'.  Mostly this is an internal
refactoring change, in preparation for further changes to close
some races.
* gnulib.modules: Add faccessat, linkat, mkfifoat, renameat, symlinkat.
Remove save-cwd.
* src/Makefile.am (tar_LDADD): Add $(LIB_EACCESS).
* tests/Makefile.am (LDADD): Likewise.
* src/common.h (chdir_fd): New extern var.
* src/compare.c (diff_file, diff_multivol): Use openat instead of open.
* src/create.c (create_archive, restore_parent_fd): Likewise.
* src/extract.c (create_placeholder_file): Likewise.
* src/names.c (collect_and_sort_names): Likewise.
* src/update.c (append_file): Likewise.
* src/compare.c (diff_symlink): Use readlinkat instead of readlink.
* src/compare.c (diff_file): Use chdir_fd instead of AT_FDCWD.
* src/create.c (subfile_open, dump_file0): Likewise.
* src/extract.c (fd_chmod, fd_chown, fd_stat, set_stat):
(repair_delayed_set_stat, apply_nonancestor_delayed_set_stat):
Likewise.
* src/extract.c (mark_after_links, file_newer_p, extract_dir):
(extract_link, apply_delayed_links):
Use fstatat rather than stat or lstat.
* src/misc.c (maybe_backup_file, deref_stat): Likewise.
* src/extract.c (make_directories): Use mkdirat rather than mkdir.
Use faccessat rather than access.  This fixes a minor permissions
bug when tar is running setuid (who would want to do that?!).
(open_output_file): Use openat rather than open.
In the process, this removes support for Masscomp's O_CTG files,
which aren't compatible with openat's signature.  Masscomp!  Wow!
That's a blast from the past.  As far as I know, that operating
system hasn't been supported for more than 20 years.
(extract_link, apply_delayed_links):
Use linkat rather than link.
(extract_symlink, apply_delayed_links):
Use symlinkat rather than symlink.
(extract_node): Use mknodat rather than mknod.
(extract_fifo): Use mkfifoat rather than mkfifo.
(apply_delayed_links): Use unlinkat rather than unlink or rmdir.
* src/misc.c (safer_rmdir, remove_any_file): Likewise.
* src/unlink.c (flush_deferred_unlinks): Likewise.
* src/extract.c (rename_directory): Use renameat rather than rename.
* src/misc.c (maybe_backup_file, undo_last_backup): Likewise.
* src/misc.c: Don't include <save-cwd.h>; no longer needed now
that we're using openat etc.
(struct wd): Add member fd.  Remove members err and fd.  All uses
changed.
(CHDIR_CACHE_SIZE): New constant.
(wdcache, wdcache_count, chdir_fd): New vars.
(chdir_do): Use openat rather than save_cwd.  Keep the cache up
to date.  This code won't scale well, but is good enough for now.
* src/update.c (update_archive): Use openat + fdopendir +
streamsavedir rather than savedir.

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-09-18 23:42:54 -07:00
Paul Eggert
fc5e44c99c tar: add utimens.h includes
* src/extract.c: Include <utimens.h>, needed for fdutimens prototype.
* src/misc.c: Likewise.
2010-09-18 00:40:16 -07:00
Paul Eggert
098ad10c71 tar: switch to gnulib fdutimensat module
* gnulib.modules: Add fdutimensat.
* src/common.h (fd_utimensat): Remove decl.
* src/extract.c (set_stat): Call fdutimensat, not fd_utimensat.
* src/misc.c (set_file_atime): Likewise.
(fd_utimensat): Remove.
2010-09-17 14:24:04 -07:00
Paul Eggert
6e08ab7694 tar: extract permissions for . last
* src/common.h (must_be_dot_or_slash): New decl.
* src/extract.c (mark_after_links): New function, taking code
that used to be in create_placeholder_file.
(create_placeholder_file): Use it.
(delay_set_stat): Always delay setting status for . and /.
* src/misc.c (must_be_dot_or_slash): Now extern.
* tests/extrac12.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Likewise.
2010-09-17 12:28:25 -07:00
Paul Eggert
cecb7ac8e6 tar: don't check for getdtablesize; use AC_CHECK_FUNCS_ONCE
* configure.ac: Don't check for getdtablesize; no longer needed.
Use AC_CHECK_FUNCS_ONCE rather than AC_CHECK_FUNCS, for efficiency.
2010-09-17 10:48:03 -07:00
Paul Eggert
ea964cce81 tar: extract symlink attributes, close some symlink-related races
* NEWS: Describe symlink-extraction improvements.
* src/extract.c (enum permstatus): Remove.
(fchmod, fchown): Define dummy replacement macros if the system
does not supply them.
(implemented): New function.
(struct delayed_set_stat): Remove members invert_permissions,
permstatus.  They were too confusing, and tried to do too much
in too-little space.  Instead, add members current_mode,
current_mode_mask, interdir, atflag.  All users changed.
(struct delayed_link): Add members mode, atime, mtime, to support
platforms such as BSD where symlinks have these attributes.
All users changed.
(fd_chmod): Renamed from fdchmod.  New argument atflag.  Check for
operation not supported at run-time, not at configure-time.  Put
fd argument first.  All callers changed.
(fd_chown): Likewise, renaming from fdchown.
(fd_stat): Likewise, renaming from fdstat.
(set_mode): Remove args stat_info, cur_info, invert_permissions,
permstatus.  Add args mode, mode_mask, current_mode, current_mode_mask,
atflag.  All callers changed.  Close some races.  Use an easier-to
understand method for computing permissions.  Work around POSIX
incompatibility in Linux fchmodat.  Support extraction of symlink
modes, if the OS allows it.
(set_stat): Remove args cur_info, invert_permissions, permstatus.
Add args current_mode, current_mode_mask, interdir, atflag.
All callers changed.  Close some races.  Support extraction of
attributes on symlinks, if the OS allows it.
(delay_set_stat): Remove args invert_permissions, permstatus.
Add args current_mode, current_mode_mask, mode, atflag.
The ST arg can be null now, indicating that it's an intermediate
directory.  All callers changed.
(repair_delayed_set_stat, apply_nonancestor_delayed_set_stat):
Close some races.
(extract_dir): Also be paranoid if only --same-permissions, due
to semantics of setgid and setuid directories on some hosts.
This closes a race on those hosts.  Simplify calculation of
delay_set_stat arguments; the old code was truly strange and
probably wrong in some border cases.
(extract_dir, extract_file, extract_node, extract_fifo): Don't rely on
unspecified behavior in mode arg of open, mknod, etc.  Instead,
mask out those bits when creating the file, and add them later via
fchmod or chmodat.
(open_output_file): file_name is now const.  Add arg current_mode,
current_mode_mask.  All callers changed.  When overwriting old files,
refuse to overwrite something that is not a regular file, since
we're extracting a regular file.
(extract_file): Remove the FIXME comment.  Whatever the protection
issues were, they should be fixed now.  As a result of all the other
API changes, we now use fchmod etc. rather than chmod etc., closing
some races.
(create_placeholder_file, apply_delayed_links): Record desired
mode and times for symlinks, for OSes that support that.
2010-09-17 10:44:13 -07:00
Paul Eggert
e3fdb78d4b tar: tar -x without --incremental no longer sets atime again
* src/extract.c (set_stat): Use UTIME_OMIT rather than UTIME_NOW.
The UTIME_NOW was there only to emulate the previous behavior of
using the current time, and the previous behavior was there only
because before we started assuming POSIX.1-2008 there was no
portable way to get the effect of UTIME_NOW.
2010-09-16 11:02:26 -07:00
Paul Eggert
d945888643 tar: another --atime-preserve race fix
* src/common.h (set_file_atime): Add parentfd arg.
* src/compare.c (diff_file): Use it.
* src/create.c (dump_file0): Likewise.  This closes yet another
race condition with symbolic links.
* src/misc.c (set_file_atime): Add parentfd arg.
2010-09-16 10:47:07 -07:00
Paul Eggert
ecbcb7b6d7 tar: --atime-preserve fixes for races etc.
This patch fixes a race condition in the --atime-preserve=replace
option, which might cause tar to improperly follow a symbolic link.

It also drops the use of the _FIOSATIME ioctl of Solaris 2.x
and later, which loses resolution on time stamps.  Modern Solaris
systems support full-resolution time stamps in the kernel, and
it's not worth the hassle of testing this call, useful only in
no-longer-supported Solaris variants.

Also, it undoes a change I recently introduced to the --compare
option, which caused it to not follow symbolic links unless the
--dereference option was also used.  Quite possibly this change is
a good idea, but the old behavior was documented and the change
should not have been installed casually.

* configure.ac: Don't check for stropts.h and sys/filio.h.
* gnulib.modules: Add futimens, utimensat.  Remove futimens.
* src/common.h (fd_utimensat): New decl.
* src/compare.c (diff_file, diff_multivol):
Don't use open_read_flags: those are for --create only.
* src/create.c (dump_file0): Adjust to set_file_atime changes.
Pass fstatat_flags to set_file_atime, so that symbolic links are
not followed inadvertantly.
* src/extract.c: Don't include utimens.h.
(set_stat): Use fd_utimensat ant UTIME_NOW rather than fdutimens.
* src/misc.c: Don't include utimens.h, stropts.h, sys/filio.h.
(fd_utimensat): New function.
(set_file_atime): Use it.  New arg atflag, controlling symlink
handling.  All callers changed.
2010-09-16 10:17:04 -07:00
Paul Eggert
59146768ef * configure.ac: tar: close some race conditions when extracting
* configure.ac: Check for fchmod and fchown.  Don't check for utimes.
* src/extract.c (fdchmod, fdchown, fdstat): New functions.
(set_mode, set_stat): New arg FD.  All callers changed.
This avoids some race conditions between closing a regular file
and setting its metadata, and it's a bit faster.
2010-09-14 13:34:25 -07:00
Paul Eggert
0fb3020da0 tar: don't worry about fdopendir closing its argument
* NEWS: Don't mention dirfd; no longer needed.
* gnulib.modules: Remove dirfd.
* src/create.c (get_directory_entries): Remove the code dealing
with dirfd failures, as the new fdopendir replacement doesn't
close its argument so we don't need to call dirfd.  See
<http://lists.gnu.org/archive/html/bug-gnulib/2010-09/msg00208.html>
and gnulib commit 970c9038e4cca46e1b037ae0a6d574dfae6a7327.
2010-09-13 13:13:08 -07:00
Paul Eggert
d7db30d0e8 * NEWS: Fix wording typo in previous change.
Reported by Jim Meyering.
2010-09-13 00:22:53 -07:00
Paul Eggert
8da503cad6 tar: live within system-supplied limits on file descriptors
* NEWS: Note the change.  Mention dirfd and fdopendir.
* gnulib.modules: Add dirfd and fdopendir.  The code was already
using fdopendir; dirfd is a new need.
* src/common.h (open_searchdir_flags, get_directory_entries):
(subfile_open, restore_parent_fd, tar_stat_close): New decls.
(check_exclusion_tags): Adjust signature to match code change.
* src/create.c (IMPOSTOR_ERRNO): New constant.
(check_exclusion_tags): First arg is now a struct tar_stat_info
const *, not an fd.  All callers changed.
(dump_regular_file, dump_file0): A zero fd represents an unused
slot, so play it safe if the fd member is zero here.  A negative
fd represents the negation of an errno value, so play it safe and
do not assign -1 to fd merely because an open fails.
(open_failure_recover, get_directory_entries, restore_parent_fd):
(subfile_open): New functions.  These help to recover from file
descriptor exhaustion.
(dump_dir, dump_file0): Use them.
(dump_file0): Use tar_stat_close instead of rolling our own close.
* src/incremen.c (scan_directory): Use get_directory_entries,
subfile_open, etc., to recover from file descriptor exhaustion.
* src/names.c (add_hierarchy_to_namelist): Likewise.
(collect_and_sort_names): A negative fd represents the negation
of an errno value, so play it safe and do not assign -1 to fd.
* src/tar.c (decode_options): Set open_searchdir_flags.
Add O_CLOEXEC to all the open flags.
(tar_stat_close): New function, which knows how to deal with
new convention for directory streams and file descriptors.
Diagnose 'close' failures.
(tar_stat_destroy): Use it.
* src/tar.h (struct tar_stat_info): New member dirstream.
fd now has the negative of an errno value, not merely -1, if
the file could not be opened, so that failures to reopen directories
are better-diagnosed later.
* tests/Makefile.am (TESTSUITE_AT): Add extrac11.at.
* tests/testsuite.at: Likewise.
* tests/extrac11.at: New file.
2010-09-12 14:27:13 -07:00
Paul Eggert
c743301494 tar: improve documentation of reliability and security issues
* doc/tar.texi (Reliability and security, Reliability):
(Permissions problems, Data corruption and repair, Race conditions):
(Security, Privacy, Integrity, Live untrusted data):
(Security rules of thumb): New nodes.
2010-09-08 13:40:27 -07:00
Paul Eggert
de328a580a tar: more reliable directory traversal when creating archives
* NEWS: Document this.
* gnulib.modules: Add openat, readlinkat.
* src/common.h (open_read_flags, fstatat_flags): New global variables.
(cachedir_file_p, dump_file, check_exclusion_tags, scan_directory):
Adjust to new signatures, described below.
(name_fill_directory): Remove.
* src/compare.c (diff_file, diff_multivol): Use open_read_flags.
* src/create.c (struct exclusion_tag): Exclusion predicates now take
a file descriptor, not a file name.
(add_exclusion_tag): Likewise.  All uses changed.
(cachedir_file_p): Likewise.
(check_exclusion_tags): The directory is now a file descriptor,
not a file name.  All uses changed.  Use openat for better traversal.
(file_dumpable_p): Arg is now a struct stat, not a struct
tar_stat_info.  All uses changed.  Check the arg's file types too.
(dump_dir0, dump_dir, dump_file0, dump_file): Omit top_level and
parent_device args, since st->parent tells us that now.  All uses
changed.
(dump_dir): Likewise.  Also, omit fd arg for similar reasons.
Apply fdsavedir to a dup of the file descriptor, since we need a
file descriptor for openat etc. as well, and fdsavedir (perhaps
unwisely) consumes its file descriptor when successful.
Do not consume st->fd when successful; this simplifies the caller.
(create_archive): Allocate a file descriptor when retraversing
a directory, during incremental dumps.
(dump_file0): Use fstatat, openat, and readlinkat for better traversal.
When opening a file, use the result of fstat on the file descriptor
rather than the fstatat on the directory entry, to avoid some race
conditions.  No need to reopen the directory since we now no longer
close it.  Change "did we open the file?" test from 0 <= fd to
0 < fd since fd == 0 now represents uninitialized.
(dump_file): Now accepts struct tar_stat_info describing parent,
not parent_device.  Also, accept basename and fullname of entry.
All uses changed.
* src/incremen.c (update_parent_directory): Accept struct
tar_stat_info for parent, not name.  All callers changed.
Use fstatat for safer directory traversal.
(procdir): Accept struct tar_stat_info, not struct stat and
dev_t, for info about directory.  All callers changed.
(scan_directory): Accept struct tar_stat_info, not name,
device, and cmdline, for info about directory.  All callers
changed.  Do not consume the file descriptor, since caller
might need it.  Use fstatat and openat for safer directory
traversal; also, use fstat after opening to double-check.
(name_fill_directory): Remove.
* src/names.c (add_hierarchy_to_namelist): Accept struct
tar_stat_info instead of device and cmdline.  All callers changed.
When descending into a subdirectory, use openat and fstat for
safer directory traversal.
(collect_and_sort_names): Use open and fstat for safer directory
traversal.  Set up struct tar_stat_info for callee's new API.
* src/tar.c (decode_options): Initialize open_read_flags
and fstatat_flags.
(tar_stat_destroy): Close st->fd if it is positive (not zero!).
* src/tar.h (struct tar_stat_info): New members parent, fd.
* src/update.c (update_archive): Adjust to dump_file's API change.
* tests/filerem02.at: Ignore stderr since its contents now depend
on the file system implementation.
2010-09-06 13:39:21 -07:00
Paul Eggert
bad4b0006c tar: remove lint discovered by Sun C compiler
* src/common.h (WARN_ALL): Don't mask with 0xffffffff; on a 32-bit
host, 0xffffffff is of type 'unsigned int', which makes WARN_ALL
an unsigned int value that is too large to fit into an int, and
the C standard says that this has undefined behavior.  The mask is
not needed, so omit it.
2010-09-04 23:53:23 -07:00
Paul Eggert
e985feb292 tar: restore macros that are used in some cases
* src/tar.c (LOW_DENSITY_NUM, MID_DENSITY_NUM, HIGH_DENSITY_NUM):
Restore these macros, undoing the previous change to this file.
The macros are used after all, in some cases.  Sorry about that.
2010-09-04 00:09:30 -07:00
Paul Eggert
fbc54fa337 tar: remove unused macros
* src/create.c (UINTMAX_TO_CHARS): Remove; no longer used.
* src/tar.c (LOW_DENSITY_NUM, MID_DENSITY_NUM, HIGH_DENSITY_NUM):
Likewise.
* src/incremen.c (DIR_IS_NEW): Comment out; not used.
Mark this with a FIXME, since it looks like it should be used.
2010-09-02 20:46:25 -07:00
Sergey Poznyakoff
45a574151a Fix --remove-files in update/append mode.
* src/update.c (update_archive): Call finish_deferred_unlinks when
done.
2010-08-27 15:36:24 +03:00
Paul Eggert
0adf4027f5 tar: avoid assumptions about root access and chmod -w in test cases
* tests/extrac07.at, tests/extrac09.at, tests/listed03.at: Use
AT_UNPRIVILEGED_PREREQ, since this test requires non-root
privileges.
* tests/extrac07.at: Don't use "chmod -w", as POSIX says it's not
portable to start a chmod permissions-list with "-" as it may be
confused with an option.  Use "chmod a-w" instead.
2010-08-26 10:23:06 -07:00
Paul Eggert
fce1c1c8cb tar: fix bug with -C and delayed setting of metadata
* src/common.h (chdir_current): New decl.
* src/extract.c (struct delayed_set_stat, struct delayed_link):
New member change_dir.
(delay_set_stat, create_placeholder_file): Set it.
(apply_nonancestor_delayed_set_stat, apply_delayed_links): Use it.
(extract_link): Check that the links are all relative to the same
directory.
(extract_archive): Restore the current directory after
apply_nonancestor_delayed_set_stat has possibly changed it.
* src/misc.c (chdir_current): New external var; this used to
be the private static variable 'previous' inside chdir_dir.
All uses changed.
* tests/Makefile.am (TESTSUITE_AT): New test extrac10.at.
* tests/extrac10.at: New file.
* tests/testsuite.at: Include it.
2010-08-25 17:09:59 -07:00
Sergey Poznyakoff
372ac37d01 Don't apply file transformations to volume names.
* src/list.c (decode_header): Don't apply file transformations to volume names.
* tests/xform01.at: New testcase.
* tests/xform-h.at (xform): Rename macro to xformtest. Use pushdef/popdef.
* tests/Makefile.am, tests/testsuite.at: Add xform01.at
2010-08-25 10:54:45 +03:00
Paul Eggert
a9895fd20c tar: optimize -c --sparse when file is entirely sparse
* src/sparse.c (sparse_scan_file): If the file is entirely sparse,
that is, if ST_NBLOCKS is zero, don't bother scanning for nonzero
blocks.  Idea by Kit Westneat, communicated by Bernd Schubert in
<http://lists.gnu.org/archive/html/bug-tar/2010-08/msg00038.html>.
Also, omit unnecessary lseek at start of file.
2010-08-24 17:29:06 -07:00
Paul Eggert
a59c819beb tar: don't assume size of a sparse file chunk fits in size_t
* src/tar.h (struct sp_array): Change numbytes from size_t to off_t.
All uses changed.
* scripts/xsparse.c (struct sp_array): Likewise.
Include <stdint.h>, for SIZE_MAX.
(expand_sparse): Don't try to allocate a buffer bigger than
SIZE_MAX bytes.
* src/common.h (SIZE_TO_CHARS, size_to_chars, SIZE_FROM_HEADER):
(size_from_header): Remove decls.
* src/create.c (size_to_chars): Remove.
* src/list.c (size_from_header): Remove.
* src/sparse.c (sparse_extract_region, check_data_region):
(oldgnu_add_sparse, oldgnu_store_sparse_info, pax_decode_header):
Don't assume chunk sizes fit in size_t.
(oldgnu_add_sparse): Check for off_t overflow.
* src/xheader.c (sparse_numbytes_decoder, sparse_map_decoder):
Likewise.
2010-08-24 16:50:49 -07:00
Paul Eggert
57b11473b0 tar: use ctime, not mtime, when checking placeholders
* src/extract.c (struct delayed_link): Rename member mtime to ctime.
All uses changed to use ctime rather than mtime.
2010-08-24 15:44:25 -07:00
Paul Eggert
fbcadc9592 tar: add comment to link04.at test
* tests/link04.at: Add explanatory comment at head.
2010-08-24 08:18:37 -07:00
Paul Eggert
3b219f943e tar: fix 1.23 Solaris regression related to PRIV_SYS_LINKDIR
The idea was suggested by Petr Sumbera in the thread starting here:
http://lists.gnu.org/archive/html/bug-tar/2010-08/msg00000.html
* src/extract.c (set_mode): Save the errno of the chmod that
failed, for the benefit of chmod_error_details.  Do not bother
retrying chmod unless the mode suggests setuid is the issue.
(extract_archive): Remove redundant call to priv_set_remove_linkdir.
* src/system.c: Include priv-set.h.
(sys_spawn_shell, sys_child_open_for_compress):
(sys_child_open_for_uncompress, sys_exec_command):
(sys_exec_info_script, sys_exec_checkpoint_script):
Invoke priv_set_restore_linkdir before execv or execlp, so that
the subprocess has the same privileges that tar originally did.
2010-08-24 00:07:50 -07:00
Paul Eggert
37ddfb0b7e tar: handle files that occur multiple times but have link count 1
This patch was inspired by the following patch that addressed a
similar problem in GNU coreutils du:
http://git.savannah.gnu.org/gitweb/?p=coreutils.git;h=efe53cc72b599979ea292754ecfe8abf7c839d22
* src/common.h (name_count): New decl.
* src/create.c (trivial_link_count): New static var.
(create_archive): Initialize it.
(dump_hard_link, file_count_links): Use it, so that files with
link count 1 are handled correctly when they are found multiple times.
* src/names.c (allocated_entries): Renamed from allocated_names,
since the identifier's name was misleading.  All uses changed.
(entries): Renamed from names.  All uses changed.
(scanned): Renamed from name_index.  All uses changed.
(name_count): New var.
(name_add_name): Increment it.
* tests/link04.at: New file.
* tests/testsuite.at: Add it.
* tests/Makefile.am (TESTSUITE_AT): Likewise.
2010-08-23 19:13:12 -07:00
Paul Eggert
09f039050e tar: use nlink_t for link counts
* src/create.c (struct link): nlink is now of type nlink_t, not size_t.
2010-08-23 13:49:49 -07:00
Paul Eggert
34795cedb7 tar: don't export names that aren't used elsewhere
* src/common.h (file_dumpable_p, gid_to_chars, major_to_chars):
(minor_to_chars, mode_to_chars, uid_to_chars, uintmax_to_chars):
(string_to_chars, dumpdir_creat0, dumpdir_create, dumpdir_free):
(dumpdir_locate, dumpdir_next, dumpdir_first, gid_from_header):
(major_from_header, minor_from_header, mode_from_header):
(time_from_header, uid_from_header, quote_copy_string, request_stdin):
(xheader_init, transform_header_name):
Remove declarations; these are no longer exported from their modules.
(GID_TO_CHARS, MAJOR_TO_CHARS, MINOR_TO_CHARS, MODE_TO_CHARS):
(UID_TO_CHARS, UINTMAX_TO_CHARS, UNAME_TO_CHARS, GNAME_TO_CHARS):
Move to src/create.c, since no other module uses these.
(GID_FROM_HEADER, MAJOR_FROM_HEADER, MINOR_FROM_HEADER):
(MODE_FROM_HEADER, TIME_FROM_HEADER, UID_FROM_HEADER):
Move to src/extract.c, since no other module uses these.
(dumpdir_t, dumpdir_iter_t): Remove; no longer used.
* src/create.c (gid_to_chars, major_to_chars, minor_to_chars):
(mode_to_chars, uid_to_chars, uintmax_to_chars, string_to_chars):
(file_dumpable_p): Now static.
* src/incremen.c (dumpdir_create0, dumpdir_create, dumpdir_free):
(dumpdir_locate, dumpdir_next, dumpdir_first): Now static.
(scan_directory, write_directory_file_entry):
Use struct dumpdir_iter * rather than dumpdir_iter_t.
* src/list.c (gid_from_header, major_from_header, minor_from_header):
(mode_from_header, time_from_header, uid_from_header):
(transform_member_name): Now static.
* src/misc.c (quote_copy_string): #if 0 out, as it's not used
anywhere.
* src/system.c (wait_for_grandchild): Now static.
* src/tar.c (request_stdin): Now static.
* src/xheader.c (xheader_init): Now static.
2010-08-23 13:27:36 -07:00
Paul Eggert
9764a6b1d3 tar: fix misspelled identifier "set_comression_program_by_suffix"
* src/suffix.c (set_compression_program_by_suffix): Renamed from
set_comression_program_by_suffix.
* src/buffer.c, src/common.h, src/tar.c: All uses changed.
2010-08-23 11:37:19 -07:00
Paul Eggert
a1a15e3202 tar: change interdir_made from int to bool
* src/extract.c (maybe_recoverable, create_placeholder_file):
Change interdir_made from int * to bool *, since the flag has just
two values 0 and 1.  All uses changed.  This does not affect tar's
behavior.
2010-08-20 01:09:17 -07:00
Paul Eggert
0ab5e64ac0 tar: remove trailing white space from source files
* ChangeLog.1, ChangeLog.CVS, Makefile.am, NEWS, README:
* README-hacking, directory, doc/Makefile.am, doc/dumpdir.texi:
* doc/gendocs_template, doc/intern.texi, doc/mastermenu.el:
* doc/snapshot.texi, doc/sparse.texi, doc/tar-snapshot-edit.texi:
* doc/value.texi, lib/Makefile.am, scripts/backup-specs:
* scripts/dump-remind.in, scripts/tar-snapshot-edit, scripts/tarcat:
* scripts/xsparse.c, src/arith.h, src/buffer.c, src/compare.c:
* src/create.c, src/delete.c, src/exit.c, src/suffix.c, src/tar.c:
* src/tar.h, src/update.c, src/warning.c, src/xheader.c:
* tests/append01.at, tests/append02.at, tests/atlocal.in:
* tests/delete03.at, tests/exclude.at, tests/exclude06.at:
* tests/extrac04.at, tests/extrac05.at, tests/extrac06.at:
* tests/extrac07.at, tests/filerem01.at, tests/filerem02.at:
* tests/incr01.at, tests/incr02.at, tests/incr03.at, tests/incr06.at:
* tests/label02.at, tests/label03.at, tests/label04.at:
* tests/label05.at, tests/link02.at, tests/link03.at:
* tests/listed01.at, tests/listed02.at, tests/long01.at:
* tests/longv7.at, tests/multiv01.at, tests/multiv02.at:
* tests/multiv03.at, tests/multiv05.at, tests/multiv06.at:
* tests/multiv07.at, tests/multiv08.at, tests/options.at:
* tests/options02.at, tests/remfiles03.at, tests/rename01.at:
* tests/rename02.at, tests/rename03.at, tests/rename04.at:
* tests/rename05.at, tests/same-order01.at, tests/same-order02.at:
* tests/shortfile.at, tests/shortupd.at, tests/sparse01.at:
* tests/sparse02.at, tests/sparsemv.at, tests/sparsemvp.at:
* tests/star/README, tests/star/gtarfail2.at:
* tests/star/multi-fail.at:
* tests/star/pax-big-10g.at, tests/star/quicktest.sh:
* tests/star/ustar-big-2g.at, tests/star/ustar-big-8g.at:
* tests/update01.at, tests/update02.at, tests/volsize.at:
* tests/volume.at:
Remove trailing spaces and tabs from lines, and remove
trailing empty lines from files.  This makes it a bit easier
to share code among coreutils and other projects that do this.
2010-08-19 15:50:07 -07:00
Paul Eggert
0a694a16e5 tar: update licenses to latest versions from www.gnu.org
* COPYING: Update to latest version; this is just minor formatting.
* doc/fdl.texi: Update from GFDL 1.2 to 1.3.
* doc/tar.texi: Adjust to new format of fdl.texi.  Omit trailing
white space.
2010-08-19 04:15:42 -07:00
Paul Eggert
b3b15f7cbc * src/misc.c (struct wd): Fix comment to match code. 2010-07-18 12:34:13 -07:00
Paul R. Eggert
8c662c9f29 tar: no need to report getcwd error if never using the result
* src/misc.c (struct wd): Rename 'saved' to 'err', with new semantics.
(chdir_arg, chdir_do): Adjust to new semantics.  Do not report an
error merely because save_cwd fails; report an error only if
save_cwd's result is needed later.
* tests/extrac09.at: New file, to test for bug that was fixed.
* tests/testsuite.at: Include it.
* tests/Makefile.am (TESTSUITE_AT): Add it.
2010-07-18 12:20:47 -07:00
Paul R. Eggert
427b3b8c79 tar: go back to absolutifying filenames in normalize_filename for now
* src/misc.c (normalize_filename): For now, go back to making
filenames absolute, even though this causes 'tar' to fail when
getcwd fails.  However, do not attempt to resolve ".." as this
does not work with symlinks.  Also, do the right thing with
leading file system prefixes and on hosts where // != /.
2010-07-17 15:47:46 -07:00
Sergey Poznyakoff
c1b30c268f Allow for size suffixes in -L and --record-size options.
* src/tar.c (TAR_SIZE_SUFFIXES): New define.
(parse_opt): Allow for size suffixes in arguments to
-L and --record-size options.
* NEWS, doc/tar.texi: Update.
2010-07-17 11:38:08 +03:00
Paul R. Eggert
cc40c57a37 tar: don't crash if getcwd fails
* src/extract.c: Don't include xgetcwd.h.
(extract_dir): stat "." rather than statting getcwd's output.
* src/misc.c (normalize_filename_x): Rewrite so as not to resolve
/../, which can't be done reliably in the presence of symlinks.
Don't reject valid names such as ".".
(normalize_filename): Don't make it absolute; that way, we don't
have to invoke xgetcwd which might fail.  Don't bother to realloc
at the end, since that uses time and now saves little space.
(chdir_do): Don't crash if xgetcwd fails.
* tests/Makefile.am (TESTSUITE_AT): Add listed03.at.
* tests/listed03.at: New file.
* tests/testsuite.at: Include listed03.at.
2010-07-15 11:25:15 -07:00
Sergey Poznyakoff
ab6dd4948d Keep a detailed map of archive members stored in the record buffer.
A separate map (bufmap) provides information for creating
multi-volume continuation headers.

* src/buffer.c (bufmap): New struct.
(bufmap_head, bufmap_tail, inhibit_map): New variables.
(mv_begin_write): New function.
(mv_begin): Rename to mv_begin_read. Rewrite using mv_begin_write.
All callers changed.
(mv_total_size): Remove.
(bufmap_locate, bufmap_free, bufmap_reset): New functions.
(_flush_write): Update bufmap.
(close_archive): Free bufmap.
(add_chunk_header): Take a bufmap argument.
(gnu_add_multi_volume_header): Likewise.
(add_multi_volume_header): Likewise.
(_gnu_flush_write): Rewrite using bufmap.
(real_s_name, real_s_totsize)
(real_s_sizeleft)
(save_name, save_totsize, save_sizeleft): Removed. All
uses updated.
(mv_size_left): Update bufmap_head.
(mv_end): Rewrite.
(multi_volume_sync): Remove.

* src/common.h (mv_begin_write): New prototype.
(mv_begin): Rename to mv_begin_read.
* src/create.c: Use mv_begin_write instead of mv_begin.
Remove calls to mv_size_left and mv_end.
* src/sparse.c: Likewise.

* tests/multiv07.at: Close stdin.
* tests/spmvp00.at: Update AT_KEYWORDS.
* tests/spmvp10.at: Likewise.

* tests/multiv08.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add multiv08.at.
2010-07-11 22:57:17 +03:00
Sergey Poznyakoff
b4bcb97e38 Version 1.23.90
* NEWS, configure.ac: Version 1.23.90
* doc/tar.texi: Document the use of lbzip2.
2010-07-11 19:36:43 +03:00
Sergey Poznyakoff
9c194c9942 Fix exclusion of long file names when extracting from pax format archives.
* src/list.c (read_and): Call decode_header before attempting
name_match.
(list_archive): Remove call to decode_header.

* src/compare.c (diff_archive): Remove call to decode_header.
* src/extract.c (extract_archive): Likewise.

* test/exclude06.at: New test case.
* tests/testsuite.at: Include exclude06.at.
* tests/Makefile.am (TESTSUITE_AT): Add exclude06.at.
2010-06-28 16:56:54 +03:00
Sergey Poznyakoff
80a6ef7d94 Minor fix.
* src/buffer.c (magic): Split the character constant to help
cc recognize character boundaries (7 is a valid hex character).
2010-06-28 00:04:49 +03:00
Sergey Poznyakoff
9b31db388e Minor fix.
* src/buffer.c (magic): Fix xz magic.
2010-06-27 23:47:20 +03:00
Paul Eggert
f6edb92580 Remove some lint, found by gcc -W etc.
* src/common.h (label_notfound): New decl.
* src/buffer.c (set_volume_start_time, compress_type):
(guess_seekable_archive, open_compressed_archive, init_buffer):
(_flush_write, archive_is-dev, increase_volume_number):
(change_tape_menu, try_new_volume, add_chunk_header):
(multi_volume_sync):
Declare as 'static' if it's not exported.
Use function prototype (void) rather than old-style ().
* src/checkpoint.c (expand_checkpoint_string): Likewise.
* src/incremen.c (dirlist_replace_prefix, makedumpdir, read_incr_db_2):
Likewise.
* src/list.c (print_volume_label): Likewise.
* src/misc.c (normalize_filename_x): Likewise.
* src/names.c (make_name, free_name, check_name_alloc, name_next_elt):
Likewise.
* src/tar.c (tar_list_quoting_style, add_exclude_array):
(set_stat_signal): Likewise.
* src/transform.c (new_transform, _single_transform_name_to_obstack):
(_transform_name_to_obstack): Likewise.
* src/unlink.c (dunlink_alloc): Likewise.

* src/buffer.c (struct zip_magic): Use const when appropriate.
* src/incremen.c (obstack_code_rename, write_directory_file_entry):
Likewise.
* src/sparse.c (COPY_STRING): Likewise.
* src/system.c (dec_to_env, time_to_env, oct_to_env, str_to_env):
(chr_to_env): Likewise.
* src/tar.c (tar_list_quoting_style, set_stat_signal): Likewise.

* src/extract.c (extract_node): Don't return garbage.

* src/names.c: Remove old-style declarations of getgrnam etc.
All modern systems declare these, and it's not worth the hassle
of ignoring the warnings on modern systems for old-style decls.
2010-06-16 13:04:12 -07:00
Sergey Poznyakoff
e21d54e8cd Bugfix.
* src/incremen.c (make_directory): Retain the slash if it is the
only character in a filename.
2010-05-17 20:22:16 +03:00
Sergey Poznyakoff
c79f0d06bc Recode NEWS back to UTF-8 2010-04-02 14:24:58 +03:00
Sergey Poznyakoff
2c97cb7ea2 Fix the gzip.at test case.
* tests/gzip.at: Suppress gzip error output, as it can differ
depending on its version etc. Bug reported by Ludovic Courtès.
2010-04-01 00:03:51 +03:00
Sergey Poznyakoff
fc61c17410 New option --full-time.
* src/common.h (full_time_option): New global.
* src/tar.c (FULL_TIME_OPTION): New constant.
(options): New option --full-time.
(parse_opt): Handle the --full-time option.
* src/list.c (simple_print_header): Pass full_time_option
as the 2nd argument to tartime.
* doc/tar.texi: Update.
* NEWS: Update.
2010-03-28 12:26:37 +03:00
Sergey Poznyakoff
2981fcc5cb Minor fixes in the testsuite.
* tests/extrac07.at: Fix a typo (invalid number
of arguments before format list).
* tests/link02.at: Use `ln' instead of `link'.
* tests/link03.at: Likewise.
2010-03-27 22:46:18 +02:00
Sergey Poznyakoff
40dea1ae7f Fix coredump.
* src/names.c (collect_and_sort_names): Remove
entry from the table before freeing it.
2010-03-27 22:24:19 +02:00
Sergey Poznyakoff
b60e56fdb6 Fix dead loop on extracting existing symlinks with the -k option.
* src/extract.c (create_placeholder_file)
(extract_link, extract_symlink)
(extract_node, extract_fifo): Handle all possible
return values from maybe_recoverable. This complements
8f390db92f. Reported by Ico Doornekamp <bug-tar@zevv.nl>.
* NEWS: Update.
2010-03-27 22:02:28 +02:00
Sergey Poznyakoff
340dbf5aab Fix undesired error exit on receiving SIGPIPE.
* src/tar.c: Do not ignore SIGPIPE.
* tests/sigpipe.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add sigpipe.at
* tests/remfiles01.at: Fix error code expectation.
* NEWS: Update.
2010-03-20 13:20:30 +02:00
Sergey Poznyakoff
c1d3d13493 Fix --remove-files.
Tar --remove-files relied on canonicalize_file_name,
which replaces symlinks in file name components with
the directories they point to. Due to this, tar
effectively ignored existence of symbolic links and
was unable to remove a directory that contained any
(Alexander Kozlov <akozlov@nada.kth.se>, 2010-03-15).

* gnulib.modules: Remove canonicalize.
* src/misc.c (normalize_filename): Rewrite
from scratch. The function operates only on
its input string, it makes no attempt to test
components for existence or to resolve symbolic
links.
* tests/Makefile.am (TESTSUITE_AT): Add remfiles03.at.
* tests/testsuite.at: Likewise.
* tests/remfiles03.at: New test case.
* NEWS: Update.
2010-03-17 11:52:40 +02:00
Sergey Poznyakoff
67b4f3519d Bugfixes.
* src/buffer.c (check_label_pattern): Initialize result.
* tests/remfiles01.at: Skip if run with root privileges.
2010-03-12 09:48:46 +02:00
Sergey Poznyakoff
0ba8bdf5f3 Fix --test-label' and --label -r' behavior.
* doc/tar.texi (Including a Label in the Archive): Revise
the section.
* NEWS: Update

* src/buffer.c (open_archive): Check volume label on
ACCESS_UPDATE as well.
* src/list.c (test_archive_label): Rewrite to match the
documentation.
* src/names.c (regex_usage_warning): Return int.
(names_notfound): Rewrite the conditional.
(label_notfound): New function.

* tests/label03.at: New testcase.
* tests/label04.at: New testcase.
* tests/label05.at: New testcase.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
2010-03-11 17:41:23 +02:00
Sergey Poznyakoff
8d3cc6c3cf Doc fixes.
* doc/tar.texi: Consistently use lowercase `see' within sentences.
More fixes spotted by Denis Excoffier.
* THANKS: Update.
2010-03-11 15:06:18 +02:00
Sergey Poznyakoff
3f4a6d83f0 Shut up a gcc warning message.
* src/tar.c (tar_help_filter): Use a separate const
variable to hold returns from gettext. Reported by
Peter Breitenlohner.
2010-03-11 15:05:57 +02:00
Sergey Poznyakoff
a3f1d933cc Bugfix.
* src/names.c (collect_and_sort_names): Initialize prev_name.
Reported by Dmitry V. Levin.
2010-03-11 12:19:32 +02:00
Sergey Poznyakoff
e8e0b6cb7a Version 1.23
* configure.ac, NEWS: Update version number.
2010-03-10 13:53:15 +02:00
Sergey Poznyakoff
338add8d10 Doc changes.
* NEWS: Update.
* THANKS: Update.
* doc/snapshot.texi, doc/snapshot.texi,
doc/sparse.texi, doc/tar-snapshot-edit.texi,
doc/tar.texi: Spellchecked and proof-read. Thanks
to Denis Excoffier.
* gnulib.modules: Remove utime.
2010-03-10 13:22:49 +02:00
Kamil Dudka
46b07a52f9 Fix possible overflow in code_timespec (tiny change)
* src/misc.c (code_timespec): ignore invalid values of ns
2010-03-08 12:34:58 +02:00
Sergey Poznyakoff
a06b3a29fb Minor fix in the testsuite.
* tests/extrac05.at: Skip test if creating
sparse file fails.
2010-03-08 12:31:59 +02:00
Sergey Poznyakoff
6f02669c7b Fix eventual memory override and fd exhaustion in create.c
Both bugs reported by Kamil Dudka.

* src/create.c (check_exclusion_tags): Do not keep
pointer to a location within tagname: it may change
after xrealloc. Use byte offset instead.
(dump_file0): Close fd before returning without
dumping the directory.
2010-03-08 12:27:23 +02:00
Sergey Poznyakoff
e1e1f87eb4 Minor change.
* doc/tar.texi: Improve some wording.
2010-03-02 18:48:20 +02:00
Antonio Diaz Diaz
bffe1074aa Add Lzip support
* configure.ac: Add TAR_COMPR_PROGRAM(lzip)
* doc/tar.texi: Reflect lzip support.
* src/buffer.c (compress_type) <ct_lzip>: New constant.
(magic): Add magic for lzip.
* src/suffix.c (compression_suffixes): Add lz.
* src/tar.c: New option --lzip.
2010-03-02 18:44:25 +02:00
Sergey Poznyakoff
9a3e8a6f43 Minor fix.
* tests/exclude05.at: Rewrite awk invocation to avoid
overflowing awk's file table on Solaris.
2010-03-02 18:39:40 +02:00
Eric Blake
a0fd0d95e2 Fix large file support.
* scripts/xsparse.c (read_map): Use fseeko.
* src/incremen.c (write_directory_file): Likewise.
2010-03-02 18:08:07 +02:00
Sergey Poznyakoff
3925776b41 Bugfix
* src/buffer.c (seek_archive): Rewrite size computation
to prevent it from reaching negative values. Based on
report by Denis Excoffier <Denis.Excoffier@free.fr>.
2010-03-02 11:20:20 +02:00
Sergey Poznyakoff
762be4f2bd Supply more information to the --to-command script.
* src/system.c (stat_to_env): Pass information about the current
volume in variables TAR_ARCHIVE, TAR_VOLUME, TAR_BLOCKING_FACTOR,
TAR_FORMAT.
* doc/tar.texi: Document new environment variables.
* NEWS: Likewise.
* configure.ac: Version number 1.22.91.
2010-02-25 10:41:18 +02:00
Sergey Poznyakoff
b7899bb121 Minor change.
* src/names.c (regex_usage_warning): Fix warning message.
2010-02-17 16:48:34 +02:00
Sergey Poznyakoff
6e196273a4 Update THANKS 2010-02-05 18:41:15 +02:00
Ondřej Vašík
bdb9de4b1e Bugfix (tiny change)
* src/xheader.c (xheader_read): Remove unnecessary call
to xheader_init.
2010-02-05 18:39:53 +02:00
Sergey Poznyakoff
c4acbdaa97 Enable silent build mode.
* configure.ac: Require automake 1.11, autoconf 2.63. Enable silent rules.
* NEWS: Update.
* lib/Makefile.am (rmt-command.h): Silent the rule.
2010-01-26 13:42:48 +02:00
Sergey Poznyakoff
c3fa22fc80 Read POSIX multivolume archives split at the header boundary.
* src/common.h (read_header_mode): New enum.
(read_header): Change type of the 3rd argument.
* src/list.c (read_header): Change type of the 3rd argument.
All callers updated.
* src/buffer.c (try_new_volume): Allow for volumes split at the
extended/ustar header boundary. This is against POSIX specs, but
we must be able to read such archives anyway.

* tests/multiv07.at: New test case.
* tests/Makefile.am: Add multiv07.at
* tests/testsuite.at: Likewise.

* src/compare.c: Update calls to read_header.
* src/delete.c: Likewise.
* src/update.c: Likewise.
2010-01-25 17:03:28 +02:00
Sergey Poznyakoff
706bd01915 Minor change.
* NEWS: Update.
* doc/tar.texi: Update.
* src/create.c (finish_header): Minor change.
2010-01-24 22:45:57 +02:00
Rob Vermaas
0057cd6803 Bugfix (tiny change).
* src/tar.c (format_default_settings)[REMOTE_SHELL]: Fix
misplaced comma.
2010-01-24 22:24:49 +02:00
Sergey Poznyakoff
45cf3a7426 Minor fix.
* src/incremen.c (read_incr_db_01)
(read_directory_file): Initialize bufsize to 0.
Suggested by noordsij@cs.helsinki.fi.
2010-01-24 18:09:31 +02:00
Sergey Poznyakoff
28f2669b15 Improve handling of --test-label.
* src/list.c (print_volume_label): New function.
(print_header): Call print_volume_label.
(test_archive_label): New function.
* src/buffer.c (VOLUME_LABEL_APPEND): Remove.
(VOLUME_TEXT, VOLUME_TEXT_LEN): New macros
(drop_volume_label_suffix): New function.
(check_label_pattern): Use drop_volume_label_suffix.
* src/common.h (subcommand): New constant TEST_LABEL_SUBCOMMAND.
(test_label_option): Remove.
(drop_volume_label_suffix): New proto.
(test_archive_label): New proto.
* src/names.c (all_names_found): Remove test for test_label_option.
* src/tar.c (subcommand_string): Handle TEST_LABEL_SUBCOMMAND.
(set_subcommand_option): Improve diagnostics.
(parse_opt): Set subcommand if --test-label is given.
(main): Handle TEST_LABEL_SUBCOMMAND.
2010-01-24 16:58:04 +02:00
Sergey Poznyakoff
166b7c7d02 Fix listing of volume labels (in particular in PAX archives).
* src/buffer.c (match_volume_label): Call set_volume_label.
(check_label_pattern): Get label string
as argument.
(match_volume_label): Handle volume labels stored in
global PAX headers.
* src/common.c (print_header,read_header): Change signature.
(read_header_primitive): Remove prototype.
* src/list.c (recent_global_header): New static.
(list_archive): Always print volume labels.
(read_header_primitive): Remove.
(read_header): Change the signature (all callers updated)
Save the recent global header.
(volume_label_printed): New static.
(simple_print_header): New function (ex-print_header).
(print_header): Change the signature (all callers updated).
For POSIX formats, print first volume header (if set).
* src/xheader.c (xheader_write_global): Write the data
accumulated in xhdr->stk even if keyword_global_override_list
is empty.
(xheader_read): On unexpected EOF, report error instead of
coredumping.
(XHDR_PROTECTED, XHDR_GLOBAL): New defines.
(struct xhdr_tab): Remove `protected' with `flags'. All uses updated.
(decg): If XHDR_GLOBAL bit is set, call the keyword's decode
method instead of adding it to `kwl'.

* src/compare.c: Update calls to read_header.
* src/create.c: Likewise.
* src/delete.c: Likewise.
* src/update.c: Likewise.
* src/extract.c: Likewise.
(extract_volhdr): Do not print "Reading <label>" statement, because
it is inconsistent: it is not printed if the volume begins with a
member continued from the previous volume.

* tests/label01.at: New testcase.
* tests/label02.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add new testcases.
2010-01-24 15:52:22 +02:00
Sergey Poznyakoff
cd91cd3c62 Fix prefix length calculation in ustar mode.
* src/create.c (split_long_name): Fix prefix length
calculation.
(write_ustar_long_name): Improve ustar mode compatibility
with the Sun version.
2010-01-22 17:52:42 +02:00
Sergey Poznyakoff
cac45fffc5 Rewrite update algorithm.
* src/common.h (namebuf_t): New typedef.
(namebuf_create, namebuf_free)
(namebuf_name): New prototypes.
(remname): New prototype.
* src/misc.c (struct namebuf): New structure.
(namebuf_create, namebuf_free)
(namebuf_name): New functions.
* src/create.c (dup_dir0): Remove is_avoided_name
checks. This is taken care of in update_archive.
* src/incremen.c (scan_directory): Use namebuf
to produce full file names.
* src/names.c (nametail): Remove extra level of
indirection. All uses updated.
(avoided_name_table, add_avoided_name)
(is_avoided_name): Remove.
* src/update.c (update_archive): Change algorithm.
Instead of adding unmodified files to the avoided_name
table, create namelist so that it contains only
modified files.

* tests/Makefile.am: Add update01.at, update02.at
* tests/testsuite.at: Likewise.
* tests/update.at (AT_KEYWORDS): Add update00.
2009-10-14 23:26:52 +03:00
Sergey Poznyakoff
0c6c288b53 Minor changes.
* src/tar.c (main): Ignore SIGPIPE.
* src/system.c (sys_child_open_for_compress)
(sys_child_open_for_uncompress): Reset SIGPIPE
in child to default.
* tests/remfiles01.at: Avoid race conditions.
* tests/remfiles02.at: Likewise.
2009-10-14 17:55:15 +03:00
Sergey Poznyakoff
87240ee7c4 Bugfix.
* src/buffer.c (_open_archive): Call guess_seekable_archive
only if the call to open_compressed_archive succeeded.
2009-10-14 17:51:19 +03:00
Sergey Poznyakoff
84a55f12e5 Improve previous changes.
* acinclude.m4: Fix typos.
* gnulib.modules: Add xvasprintf.
* src/common.h: Include xvasprintf.h.
* src/tar.c (options): Remove docstrings for --gzip, --bzip2,
--compress, --lzop, --lzma and --xz.
(tar_help_filter): Generate these using actual values of
*_PROGRAM constants.
(format_default_settings): Use xasprintf.
(parse_opt): Use *_PROGRAM defines instead of hardcoded
program names.
2009-10-10 19:49:38 +03:00
Sergey Poznyakoff
a7e9b6a17b Allow installers to specify alternative program names for compression programs.
This adds --with-gzip, --with-bzip2 etc. switches to the configure, so that
one can do, e.g. ./configure --with-bzip2=lbzip2 and have lbzip2 executed
whenever user calls `tar --bzip2'.

* acinclude.m4: New file.
* configure.ac: Add TAR_COMPR_PROGRAM invocations for
the supported compressors.
* src/buffer.c (magic): Use *_COMPRESSOR defines instead
of hardcoded program names.
* src/suffix.c (compression_suffixes): Likewise.
2009-10-10 17:30:53 +03:00
Sergey Poznyakoff
f0ceef8596 Minor fix.
* src/buffer.c (magic): Fix `xz' entry: add the name of the program.
* src/suffix.c (compression_suffixes, nsuffixes): Mark as static.
2009-10-09 11:49:26 +03:00
Sergey Poznyakoff
63e092548a Provide a way to explicitly set mtime for extended header ustar blocks.
* src/tar.c (struct textual_date): ts is a copy of the structure,
not a pointer to it. Date is a copy as well, hence the `const' is
taken away.
(get_date_or_file): Return 0/1 depending on success/failure.
Copy timestamp to the `ts' member. Store a copy of the string
in `date'.
(report_textual_dates): Report only if verbose_option is set,
but always free the list.
(expand_pax_option): New function.
(parse_opt): Preprocess the argument to xheader_set_option with
expand_pax_option.
(decode_options): Call report_textual_dates unconditionally.
* src/xheader.c (exthdr_mtime_option, exthdr_mtime)
(globexthdr_mtime_option, globexthdr_mtime): New statics.
(xheader_set_keyword_equal): handle exthdr.mtime and globexthdr.mtime.
(xheader_write): Override `t' argument if a corresponding
exthdr.mtime or globexthdr.mtime option is set.
* NEWS: Update
* doc/tar.texi: Document the changes.
2009-10-07 21:08:29 +03:00
Sergey Poznyakoff
7cb84c25ee Use file's mtime as mtime for its extended header.
This makes two pax archives binary equivalent if they
have the same contents and care is taken to make extended
headers otherwise reproducible, e.g. by using:

  --pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0

Proposed by Michael D. Adams <mdmkolbe@gmail.com>.

* src/common.h (start_private_header): Take time_t as 3rd param.
(xheader_write): Likewise.
* src/create.c (start_private_header): Take time_t as 3rd param.
All callers updated.
(write_extended): Use file's mtime as mtime for its extended header,
Use current time stamp as mtime for global headers.
(xheader_write): Take time_t as 3rd param.
2009-10-07 18:40:07 +03:00
Sergey Poznyakoff
4dfcd6c054 Fix bugs in handling the --remove-files option.
Make sure the files are deleted only if they were succesfully stored
to the archive.

* src/exit.c: New file.
* src/unlink.c: New file.
* src/Makefile.am (tar_SOURCES): Add exit.c and unlink.c.
* src/common.h: Include progname.h
(program_name): Remove global.
(records_written): New extern.
(queue_deferred_unlink, finish_deferred_unlinks): New prototypes.
(fatal_exit_hook): New extern.
* src/create.c (create_archive): Call finish_deferred_unlinks.
(dump_hard_link, dump_file0): Don't actually unlink the file,
queue it to deferred_unlinks instead.
* src/delete.c (records_written): Remove extern: declared in
common.h.
* src/extract.c (extract_archive): Set fatal_exit_hook.
(fatal_exit, xalloc_die): Move to exit.c
* src/system.c (sys_wait_for_child): Exit immediately
if the child dies or exits with a non-zero status.
(sys_child_open_for_compress)
(sys_child_open_for_uncompress): Use set_program_name,
instead of setting program_name directly.
* src/tar.c (main): Use set_program_name,
instead of setting program_name directly.

* tests/Makefile.am (TESTSUITE_AT): Add remfiles01.at
and remfiles02.at.
* tests/testsuite.at: Likewise.
* tests/gzip.at: Reflect the above changes.
2009-10-07 16:42:06 +03:00
Sergey Poznyakoff
2947023d27 Fix bug in OLDGNU format creation.
See tests/append02.at for a detailed description

* src/common.h (MODE_FROM_HEADER): Take additional argument.
(mode_from_header): Likewise.
* src/create.c (mode_to_chars): Store all mode bits if
using OLDGNU_FORMAT. This reverses f4e4adea80.
* src/list.c (decode_header): Use header mode field
to discern between GNU and OLDGNU formats.
(mode_from_header): Store unrecognized mode bits (from 10th up)
in the location pointed to by the third parameter.
* tests/append02.at: Update documentation and references.
2009-10-04 23:38:34 +03:00
Sergey Poznyakoff
92773d860f Restore extra help output.
* src/tar.c (tar_list_quoting_styles): Change first argument to
struct obstack.
(format_default_settings): New function.
(show_default_settings)
(show_default_settings_fs): Removed.
(tar_help): Removed.
(tar_help_filter): New function.
(argp): Set help_filter.
(parse_opt): Fix error message.
2009-09-16 11:52:34 +03:00
Sergey Poznyakoff
dccb3806a6 Improve command line option handling.
* gnulib.modules: Add argp-version-etc and progname,
use getopt-gnu instead of getopt.
* src/tar.c (HANG_OPTION, USAGE_OPTION)
(VERSION_OPTION): Remove.
(options): Remove corresponding options. Let argp
handle them.
(parse_opt): Likewise.
(_argp_hang): Removed.
(tar_authors): New variable.
(decode_options): Call argp_version_setup.
Do not use ARGP_NO_HELP flag in the call to argp_parse.
2009-09-08 11:08:49 +03:00
Sergey Poznyakoff
0d8e324912 Avoid overwriting exit_status with a value indicating less important condition.
* src/tar.c (set_exit_status): New function.
* src/common.h (set_exit_status): New prototype.
* src/compare.c: Use set_exit_status instead of
exit_status assignments.
* src/create.c: Likewise.
* src/misc.c: Likewise.

* src/system.c (wait_for_grandchild): Use auto variable
instead of the global exit_status.
* src/incremen.c (scan_directory): Use file_removed_diag
instead of stat_diag.
2009-09-08 11:04:48 +03:00
Sergey Poznyakoff
cef4d5e838 Automatic detection of seekable archives.
* src/buffer.c (guess_seekable_archive): New function.
(_open_archive): Call guess_seekable_archive for archives
open for reading.
(new_volume): Likewise.
* src/common.h (seek_option): New global.
* src/tar.c (options): New option --no-seek.
(parse_opt): --seek and --no-seek set seek_option,
not seekable_archive.
(decode_options): Initialize seek_option to -1.

* NEWS: Update.
* doc/tar.texi: Update.
2009-09-08 10:27:57 +03:00
Sergey Poznyakoff
ba954ea1e1 Fix testcases.
* tests/extrac08.at: Ensure a predictable umask value.
* tests/xform-h.at (xform): do not depend on file name
ordering.
2009-08-27 20:12:14 +03:00
Sergey Poznyakoff
006c1efbe8 Fix interaction between --listed-incremental and -C
* src/incremen.c (read_directory_file): Execute eventual -C dir
after opening the snapshot file.
(collect_and_sort_names): Remove call to chdir_do
* tests/incr05.at, tests/incr06.at: Use relative file names for
snapshot files.
2009-08-13 16:45:49 +03:00
Sergey Poznyakoff
aeffa4f266 Update for new exclude module from gnulib. Add testcases by Phil Proudman.
* src/names.c (is_pattern): Remove.
(regex_usage_warning): Use fnmatch_pattern_has_wildcards instead of
is_pattern.
* src/tar.c: New option --exclude-backups.
(vcs_file_table, backup_file_table): New globals.
(add_exclude_array): New function.
* tests/exclude01.at, tests/exclude02.at,
tests/exclude03.at, tests/exclude04.at,
tests/exclude05.at: New testcases. Supplied by Phil Proudman.
* tests/Makefile.am (TESTSUITE_AT): Add new tests.
* tests/testsuite.at: Add new tests.
* THANKS: Update.
2009-08-12 19:25:29 +03:00
Sergey Poznyakoff
829b3feb26 Remove src/version.c (reappeared after migration to Git) 2009-08-10 01:03:31 +03:00
Sergey Poznyakoff
88347995b2 Minor fixes.
* src/misc.c (file_removed_diag): Set exit code to TAREXIT_DIFFERS.
2009-08-09 11:20:52 +03:00
Sergey Poznyakoff
acd833fb98 Minor fixes 2009-08-08 22:33:16 +03:00
Sergey Poznyakoff
51aee274e8 Fix handling of files removed during incremental dumps.
Changes to src/create.c and src/incremen.c are partially
based on patch from Alexander Peslyak <solar at openwall.com>.

The new testcases require paxutils commit f653a2b or later.

* src/common.h (struct name): New member `cmdline'.
(dump_file): Change type of the 2nd argument to bool.
(file_removed_diag, dir_removed_diag): New prototypes.
(addname): New argument `cmdline'.
(name_from_list): Change return value.
* src/create.c (dump_dir0, dump_dir): top_level is bool.
(create_archive): Update calls to name_from_list.
Take advantage of the name->cmdline to set top_level argument
during incremental backups.
(dump_file0): top_level is bool.
Do not bail out if a no-top-level file disappears during incremental
backup, use file_removed_diag instead.
(dump_filed): top_level is bool.
* src/incremen.c (update_parent_directory): Silently ignore
ENOENT.  It should have already been reported elsewhere.
(scan_directory): Use dir_removed_diag to report missing directories.
* src/misc.c (file_removed_diag, dir_removed_diag): New functions.
* src/names.c (name_gather): Set ->cmdname.
(addname): Likewise. All uses updated.
(name_from_list): Return struct name const *. All uses updated.

* tests/filerem01.at: New testcase.
* tests/filerem02.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add filerem01.at, filerem02.at
* tests/grow.at, test/truncate.at: Use new syntax for genfile --run.

* NEWS: Update.
* doc/tar.texi: Minor fix.
2009-08-08 19:53:54 +03:00
Sergey Poznyakoff
2b1bffbad6 Optimize searches for directory structures by keeping a pointer to struct directory in struct name.
* src/common.h (struct name): New member `directory' replaces
dir_contents. Rearrange members.
(rebase_directory): Change signature.
(scan_directory): Change signature.
(name_fill_directory)
(directory_contents, safe_directory_contents): New prototypes.
(append_incremental_renames): Change signature.
(replace_prefix): New proto.
* src/compare.c (diff_dumpdir): Use directory_contents + scan_directory.
* src/create.c
* src/incremen.c (replace_prefix): Move to misc.c
(rebase_directory): Rewrite.
(scan_directory): Return pointer to struct directory.
(directory_contents, safe_directory_contents): New functions.
(get_directory_contents): Remove.
(name_fill_directory): New function.
(append_incremental_renames): Rewrite. This also fixes a memory leak.
* src/names.c (name_gather, addname): Reflect changes in struct name.
(add_hierarchy_to_namelist): Rewrite using name_fill_directory and
directory_contents.
(rebase_child_list): Update call to rebase_directory.
(collect_and_sort_names): Optimize

* src/misc.c (replace_prefix): New function.
* src/names.c (add_hierarchy_to_namelist): Use new get_directory_contents.

* tests/incr05.at: New test case.
* tests/incr06.at: New test case.
* tests/Makefile.am, test/testsuite.at: Add incr05.at and incr06.at.

* doc/Makefile.am (check-options): Improve rule.
* doc/tar.texi, NEWS: Update.
2009-08-08 15:29:19 +03:00
Sergey Poznyakoff
df59690240 Minor fixes.
* src/common.h (rebase_directory): New prototype.
* src/incremen.c (rebase_directory): Use replace_prefix.
* src/names.c (collect_and_sort_names): Abort if
hash_insert fails.
2009-08-07 23:07:01 +03:00
Sergey Poznyakoff
1bcbbcf1ff Improve listed incremental dumps.
The modified algorithm tries to avoid dumping the same
directory twice and ensures the order of the directories
in the resulting archive is the same, whatever their order
on the command line.  It also fixes the operation of
--listed-incremental -C.

* gnulib.modules: Add canonicalize
* src/common.h (incremental_level): New global.
(check_exclusion_tags): first argument is const.
(get_directory_contents): Add third argument.
(zap_slashes, normalize_filename): New prototypes.
(chdir_count): New prototype.
(WARN_VERBOSE_WARNINGS): New define.
(WARN_ALL): Exclude WARN_VERBOSE_WARNINGS.
* src/compare.c (diff_dumpdir): Update the call to get_directory_contents.
* src/create.c (check_exclusion_tags): First argument is const.
Use ISSLASH and DIRECTORY_SEPARATOR instead of referring to '/'.

* src/incremen.c (struct directory): New member `caname'.
(hash_directory_name): Rename to hash_directory_canonical_name. Operate
on the canonical name.
(compare_directory_names): Rename to compare_directory_canonical_names.
Operate on the canonical name.
(make_directory): Take two arguments.
(free_directory): Free caname.
(attach_directory): Create caname.
(find_directory): Use caname for lookups.
(PD_VERBOSE): Remove.
(PD_FORCE_INIT): New define.
(procdir): First argument is const.
Reinitialize directory if PD_FORCE_INIT bit is set.
Do not use PD_VERBOSE or verbose_option for issuing warnings.
Rely on WARNOPT instead.
Always set *entry.
(scan_directory): Take three arguments. The third one is a boolean
which is true if the directory is explicitly mentioned on the command
line.
(get_directory_contents): Remove.  Use scan_directory instead.
All callers updated.
(read_directory_file): Truncate the file if --level=0 is given.
* src/misc.c: Include canonicalize.h
(zap_slashes, normalize_filename): New functions.
(chdir_count): New function.
* src/names.c (add_hierarchy_to_namelist): Take three arguments, as
get_directory_contents and scan_directory.
(collect_and_sort_names): Allow at most one -C, before file name
arguments.
Read directory file after eventual changing to another directory.
Avoid adding the same directory under different pathnames to
the list.
* src/tar.c: New option --level.

* tests/incr03.at, tests/incr04.at, tests/listed01.at,
tests/listed02.at, tests/rename01.at, tests/rename02.at,
tests/rename03.at: Update for new tar behavior.
* tests/multiv01.at: Do not use --listed-incremental.
2009-08-07 14:52:55 +03:00
Sergey Poznyakoff
ac5288c1ac Forgotten to push src/warning.c 2009-08-05 22:18:33 +03:00
Sergey Poznyakoff
67a1a0eac5 Implement the --warning option.
* src/warning.c: New file.
* src/Makefile.am: Add warning.c
* src/common.h: Provide definitions for warning classes.
(warning_option): New global.
(WARNOPT): New define.
(set_warning_option): New prototype.
* src/tar.c: New option `--warning'.
* src/compare.c: When applicable WARNOPT instead of WARN.
* src/create.c: Likewise.
* src/extract.c: Likewise.
* src/incremen.c: Likewise.
* src/list.c: Likewise.

* NEWS, doc/tar.texi: Update.
2009-08-05 13:52:38 +03:00
Carl Worth
471c0f76cd Fix descriptions of some options (tiny change) 2009-08-05 10:42:42 +03:00
Sergey Poznyakoff
755c246588 Fix backup handling and restoring file modes of existing directories
* NEWS, THANKS: Update
* src/extract.c (extract_dir): reset status to 0 if the
directory already exists.
* src/misc.c (maybe_backup_file): Assign before_backup_name
and clear after_backup_name before checking if we really need
to backup the file.
* tests/backup01.at: New testcase.
* tests/extrac08.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add extrac08.at and
backup01.at
2009-08-05 10:38:50 +03:00
Sergey Poznyakoff
5944f452b0 Fix hard links recognition with -c --remove-files
* src/create.c (dump_hard_link): Always look up in the link table
if remove_files_option is set. Patch suggested by Theodore Ts'o
<tytso@mit.edu>.
(check_links): Remove extra newline from the warning message.
* tests/link02.at, tests/link03.at: New testcases.
* tests/Makefile.am (TESTSUITE_AT): Add link02.at and link03.at
* tests/testsuite.at: Include link02.at and link03.at
2009-07-30 23:49:32 +03:00
Sergey Poznyakoff
f74cab3a93 Fix handling of hard link targets by -c --transform
* src/create.c (file_count_links): Transform link target
before the look up.
* tests/xform-h.at: New test case.
* tests/Makefile.am (TESTSUITE_AT): Add xform-h.at.
* tests/testsuite.at: Add xform-h.at
2009-07-30 11:43:16 +03:00
Sergey Poznyakoff
01c4475b17 Minor fix.
* src/extract.c (file_newer_p): Do not report error on ENOENT
2009-06-23 16:52:33 +03:00
Sergey Poznyakoff
b7d206cb1e Remove rebox.el (reappeared after migration to Git) 2009-06-19 15:49:17 +03:00
Sergey Poznyakoff
c30c4ffb9f Remove files that were removed in CVS, but reappeared after migration to Git 2009-06-18 14:24:50 +03:00
David Bartley
b216fed634 Fix Solaris bug where chmod fails if we don't have PRIV_SYS_LINKDIR
* gnulib.modules: Add priv-set.
* src/extract.c (set_mode, extract_archive): Restore
PRIV_SYS_LINKDIR on chmod failure.
* src/tar.c (main): Drop PRIV_SYS_LINKDIR on startup.
2009-06-18 13:57:10 +03:00
Sergey Poznyakoff
0d6720288b Ensure default behavior for SIGPIPE
* src/tar.c (main): Install default handler for SIGPIPE.
Proposed by Bastian Blank.
2009-06-18 13:05:48 +03:00
Eric Blake
da760e3faa Follow autoconf recommendation for TESTSUITEFLAGS.
* tests/Makefile.am (check-local, installcheck-local): Honor
TESTSUITEFLAGS.
2009-06-18 12:30:04 +03:00
Sergey Poznyakoff
af30244849 Fix handling of sub-subprocess returns.
* src/system.c (wait_for_grandchild): New function.
(sys_child_open_for_compress)
(sys_child_open_for_uncompress): Use wait_for_grandchild
to manage grandchild return.
2009-06-18 12:22:47 +03:00
Sergey Poznyakoff
be34933b63 Report record size only if the archive refers to a device.
* Makefile.am (INCLUDES): Add ../lib, for rmt-command.h
* src/buffer.c (short_read): Report the actual record size
only if the archive descriptor refers to a device.
* tests/pipe.at, tests/shortrec.at,
tests/sparsemvp.at: Reflect the above change.
* NEWS, configure.ac: Version 1.22.90
2009-05-25 10:18:59 +03:00
Sergey Poznyakoff
8f390db92f Do not issue errors on existing files when given the -k option
* Makefile.am (dist-hook): Fix rule.
* src/extract.c (maybe_recoverable): Return three-state value.
(extract_dir): Skip extraction if maybe_recoverable indicates so.
(extract_file): Likewise.
2009-05-14 11:28:41 +03:00
Eric Blake
705fab49eb Avoid undefined behavior
* src/xheader.c (xheader_set_keyword_equal): Pass correct type to
ctype macros.
* src/transform.c (run_case_conv): Likewise.
2009-05-12 12:12:15 +03:00
Sergey Poznyakoff
f14558de94 Remove src/Makefile.in 2009-05-12 12:11:17 +03:00
Sergey Poznyakoff
67cad0792b Bugfixes.
* bootstrap (symlink_to_dir): Fix symlink calculation.
* doc/tar.texi: Minor fixes by Victor Villa and Stepan Kasal.
2009-03-12 16:15:06 +02:00
297 changed files with 23191 additions and 12895 deletions

12
.gitignore vendored
View File

@@ -11,21 +11,25 @@
ABOUT-NLS
ChangeLog
INSTALL
Make.rules
Makefile
Makefile.in
Make.rules
aclocal.m4
autom4te.cache
build-aux
build-aux/
config.h
config.h.in
config.log
config.status
configure
gnu/*.h
gnu/*/
gnu/.gitignore
gnu/charset.alias
gnulib
libtool
m4
paxutils
rmt
stamp-h1
build-aux/
gnu

18
COPYING
View File

@@ -1,12 +1,11 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
@@ -69,7 +68,7 @@ patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
TERMS AND CONDITIONS
0. Definitions.
@@ -77,7 +76,7 @@ modification follow.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
@@ -510,7 +509,7 @@ actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
@@ -619,9 +618,9 @@ an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -673,4 +672,3 @@ may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -1,26 +1,23 @@
Currently there is just one ChangeLog file for tar, but
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.
@@ -5,7 +26,7 @@
2009-03-04 Sergey Poznyakoff <gray@gnu.org.ua>
Add xz support.
* src/buffer.c, src/suffix.c: Add support for xz compression.
* src/tar.c: New option --xz, for compression/decompression using xz.
Re-assign -J as a short equivalent of --xz.
@@ -34,8 +55,8 @@
2008-11-25 Sergey Poznyakoff <gray@gnu.org.ua>
Do not try to drain the input pipe before closing the
archive.
archive.
* src/buffer.c (close_archive): Remove call to
sys_drain_input_pipe. Pass hit_eof as the second
argument to sys_wait_for_child.
@@ -63,7 +84,7 @@
* src/extract.c (extract_link, extract_symlink): Remove calls to
transform_member_name. It is done in read_header.
* src/list.c (decode_xform): Reflect change in data type of 2nd
argument.
argument.
(transform_member_name): 2nd arg is int.
(decode_header): Transform file name and link target names.
* src/tar.c: Remove --transform-symlinks.
@@ -73,7 +94,7 @@
set global flags using `flags=' syntax.
(_transform_name_to_obstack, transform_name_fp)
(transform_name): Take an additional argument, specifying scope
flags.
flags.
2008-10-19 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -86,7 +107,7 @@
* tests/sparsemvp.at: Likewise.
* tests/volsize.at: Likewise.
* NEWS: Update.
2008-10-16 Sergey Poznyakoff <gray@gnu.org.ua>
* src/common.h (transform_symlinks_option): New global.
@@ -99,11 +120,11 @@
* doc/tar.texi: Document --transform-symlinks
* NEWS: Update.
* THANKS: Update.
* src/names.c (name_gather): Use xzalloc.
* src/buffer.c (short_read): Move record size detection before
the loop.
2008-10-07 Sergey Poznyakoff <gray@gnu.org.ua>
* src/tar.c (options): Add --lzop option.
@@ -111,7 +132,7 @@
2008-10-05 Xavier Hienne <xavier.hienne@free.fr> (tiny change)
* src/checkpoint.c (checkpoint_compile_action): Add missing
`else'.
`else'.
2008-09-24 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -157,7 +178,7 @@
* tests/atlocal.in (decho): New function.
* tests/multiv06.at: Use decho instead of echo2.
* tests/incremental.at: Raise wait interval to 2 seconds.
2008-07-24 Sergey Poznyakoff <gray@gnu.org.ua>
* src/tar.c (decode_options): Do not allow volume length less
@@ -193,21 +214,21 @@
tests/longv7.at, tests/lustar01.at, tests/lustar02.at,
tests/shortfile.at: Update to match new diagnostic wording
(see 2008-05-06).
* NEWS: Update.
2008-06-14 Sergey Poznyakoff <gray@gnu.org.ua>
* doc/tar.texi (exclude): Document support for new VCS.
* THANKS: Update.
* NEWS: Update.
* NEWS: Update.
* tests/multiv05.at: Fix typos.
* tests/volsize.at: Remove a TZ dependency.
2008-06-14 Dan Drake <dan@dandrake.org> (tiny change)
* src/tar.c (exclude_vcs_files): Support for Bazaar, Mercurial and
Darcs.
Darcs.
2008-05-06 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -231,23 +252,23 @@
* tests/incr03.at, tests/incr04.at, tests/rename02.at,
tests/rename03.at: Insert calls to sleep between creation of files
and adding them to the archive.
2008-03-31 Sergey Poznyakoff <gray@gnu.org.ua>
* src/create.c (dump_file0): Count links only for actually dumped
files.
files.
2008-03-27 Sergey Poznyakoff <gray@gnu.org.ua>
* NEWS: Document --no-check-device and --check-device.
* doc/rendition.texi: Change the way FIXME-*refs are handled in
!PROOF.
!PROOF.
* doc/intern.texi, doc/tar.texi: Update.
* doc/untabify.el: New file.
* doc/Makefile.am (EXTRA_DIST): Add untabify.el
(untabify, final, check-format, check-refs, check-fixmes)
(check-unrevised, all-check-docs, check-docs): New rules.
* src/common.h (check_device_option): New global.
* src/incremen.c (procdir): Use boolean and instead of bitwise
one. Patch by Jean-Louis Martineau.
@@ -256,7 +277,7 @@
--check-device. Proposed by Jean-Louis Martineau.
(parse_opt): Hanlde new options.
(decode_options): Initialize check_device_option to true.
* THANKS: Update
2008-03-06 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -267,7 +288,7 @@
* po/.cvsignore: Update
* src/system.c: Remove include setenv.h.
* tests/atlocal.in (STAR_DATA_URL): Update.
* tests/star/README: Update URL.
* tests/star/README: Update URL.
2008-02-09 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -303,7 +324,7 @@
Exit with nonzero status if a close fails on an archive.
Problem (and initial trivial fix)
* src/buffer.c (close_archive, new_volume): close_error, not
close_warn.
close_warn.
2007-12-05 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -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,29 +1,29 @@
# 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
SUBDIRS = doc gnu lib rmt src scripts po tests
dist-hook:
$(MAKE) changelog_dir=$(distdir) make-ChangeLog
dist-hook:
$(MAKE) changelog_dir=$(distdir) ChangeLog
-rm -f $(distdir).cpio
find $(distdir) | cpio -Hcrc -o | \
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
@@ -36,5 +36,4 @@ include Make.rules
gen_start_date = 2009-03-06
prev_change_log = ChangeLog.CVS
changelog_dir = .
changelog_amend_file=ChangeLog.amend

560
NEWS
View File

@@ -1,19 +1,434 @@
GNU tar NEWS - User visible changes. 2009-03-05
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
time stamps to the full resolution.
* Bugfixes.
** More reliable directory traversal when creating archives
Tar now checks for inconsistencies caused when a file system is
modified while tar is creating an archive. In the new approach, tar
maintains a cache of file descriptors to directories, so it uses more
file descriptors than before, but it adjusts to system limits on
the number of file descriptors. Tar also takes more care when
a file system is modified while tar is extracting from an archive.
The new checks are implemented via the openat and related calls
standardized by POSIX.1-2008. On an older system where these calls do
not exist or do not return useful results, tar emulates the calls at
some cost in efficiency and reliability.
** Symbolic link attributes
When extracting symbolic links, tar now restores attributes such as
last-modified time and link permissions, if the operating system
supports this. For example, recent versions of the Linux kernel
support setting times on symlinks, and some BSD kernels also support
symlink permissions.
** --dereference consistency
The --dereference (-h) option now applies to files that are copied
into or out of archives, independently of other options. For example,
if F is a symbolic link and archive.tar contains a regular-file member
also named F, "tar --overwrite -x -f archive.tar F" now overwrites F
itself, rather than the file that F points to. (To overwrite the file
that F points to, add the --dereference (-h) option.) Formerly,
--dereference was intended to apply only when using the -c option, but
the implementation was not consistent.
Also, the --dereference option no longer affects accesses to other
files, such as archives and time stamp files. Symbolic links to these
files are always followed. Previously, the links were usually but not
always followed.
** Spurious error diagnostics on broken pipe.
When receiving SIGPIPE, tar would exit with error status and
"write error" diagnostics. In particular, this occurred if
invoked as in the example below:
tar tf archive.tar | head -n 1
** --remove-files
'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,
not 2 as it did in previous versions.
The '--verbose' option used with '--test-label' provides additional
diagnostics.
Several volume labels may be specified in a command line, e.g.:
tar --test-label -f archive 'My volume' 'New volume' 'Test volume'
In this case, tar exits with code 0 if any one of the arguments
matches the actual volume label.
** --label used with --update
The '--label' option can be used with '--update' to prevent accidental
update of an archive:
tar -rf archive --label 'My volume' .
This did not work in previous versions, in spite of what the docs said.
** --record-size and --tape-length (-L) options
Usual size suffixes are allowed for these options. For example,
-L10k stands for a 10 kilobyte tape length.
** Fix dead loop on extracting existing symlinks with the -k option.
version 1.23 - Sergey Poznyakoff, 2010-03-10
* Record size autodetection
When listing or extracting archives, the actual record size is
reported only if the archive is read from a device (as opposed
to regular files and pipes).
* Seekable archives
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'
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.
See Tar Manual, section 3.9 "Controlling Warning Messages", for a
detailed discussion.
* New command line option '--level'
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
the snapshot file if it exists.
* Files removed during incremental dumps
If a file or directory is removed while incremental dump is
in progress, tar exact actions depend on whether this file
was explicitly listed in the command line, or was found
during file system scan.
If the file was explicitly listed in the command line, tar
issues error message and exits with the code 2, meaning
fatal error.
Otherwise, if the file was found during the file system scan,
tar issues a warning, saying "File removed before we read it",
and sets exit code to 1, which means "some files differ".
If the --warning=no-file-removed option is given, no warning
is issued and exit code remains 0.
* Modification times of PAX extended headers.
Modification times in ustar header blocks of extended headers
are set to mtimes of the corresponding archive members. This
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).
Modification times in ustar header blocks of global extended
headers are set to the time when tar was invoked.
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).
* Time references in --pax-option argument.
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
case, it is replaced with the modification time of that file.
* Environment of --to-command script.
The environment passed to the --to-command script is extended with
the following variables:
TAR_VERSION GNU tar version number
TAR_ARCHIVE The name of the archive
TAR_VOLUME Ordinal number of the volume
TAR_FORMAT Format of the archive
TAR_BLOCKING_FACTOR Current blocking factor
* Bugfixes
** Fix handling of hard link targets by -c --transform.
** Fix hard links recognition with -c --remove-files.
** Fix restoring files from backup (debian bug #508199).
** Correctly restore modes and permissions on existing directories.
** The --remove-files option removes files only if they were
succesfully stored in the archive.
** Fix storing and listing of the volume labels in POSIX format.
** Improve algorithm for splitting long file names (ustar
format).
** Fix possible memory overflow in the rmt client code (CVE-2010-0624).
version 1.22 - Sergey Poznyakoff, 2009-03-05
* Support for xz compression
Tar uses xz for compression if one of the following conditions is met:
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:
Xz is used for decompression if one of the following conditions is met:
1. The option --xz or -J is used.
2. The xz binary is set as compressor using --use-compress-program option.
@@ -66,21 +481,21 @@ control type of archive members affected by them. The flags are:
- s
Apply transformation to symbolic link targets.
- h
- h
Apply transformation to hard link targets.
Corresponding upper-case letters negate the meaning, so that
`H' means ``do not apply transformation to hard link targets.''
'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'
@@ -88,10 +503,10 @@ can be changed using `flags=' statement before the expressions, e.g.:
** The --null option disabled handling of tar options in list files. This
is fixed.
** Fixed record size autodetection. If detected record size differs from
the expected value (either default, or set on the command line), tar
always prints a warning if verbosity level is set to 1 or greater,
i.e. if either -t or -v option is given.
** Fixed record size autodetection. If the detected record size differs from
the expected value (either default one, or the one set from the
command line), tar always prints a warning if verbosity level is set
to 1 or greater, i.e. if either -t or -v option is given.
@@ -116,36 +531,36 @@ 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
during extraction.
For a detailed description, see chapter 6.7 "Modifying File and Member
Names".
Names".
* Info (end-of-volume) scripts
@@ -172,8 +587,8 @@ control systems, e.g. "CVS/", ".svn/", etc.
The following options now work with incremental archives as well:
--exclude-caches
--exclude-caches-all
--exclude-caches
--exclude-caches-all
--exclude-tag
--exclude-tag-all
--exclude-tag-under
@@ -184,14 +599,14 @@ Previous versions always stored absolute file names in rename
records, even if -P was not used. This is fixed: rename records
contain file names processed in accordance with the command line
settings.
* Fix --version output.
* Recognition of broken archives.
When supplied an archive smaller than 512 bytes in reading mode (-x,
-t), the previous version of tar silently ignored it, exiting with
code 0. It is fixed. Tar now issues the following diagnostic message:
code 0. It is fixed. Tar now issues the following diagnostic message:
'This does not look like a tar archive', and exits with code 2.
* Fix double-dot recognition in archive member names in case of duplicate '/.'.
@@ -224,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
@@ -294,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).
@@ -334,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.
@@ -359,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
@@ -370,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.
@@ -384,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.
@@ -457,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
@@ -477,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
@@ -487,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).
@@ -545,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
@@ -656,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.
@@ -682,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.
@@ -704,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.
@@ -751,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
@@ -773,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.
@@ -795,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.
@@ -837,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.
@@ -928,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
@@ -1007,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
@@ -1036,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.
@@ -1090,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 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
@@ -1106,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

135
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-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.
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,36 +216,39 @@ 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
paragraph-separate: "[ ]*$"
version-control: never
End:

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

@@ -6,20 +6,20 @@ this package.
You need the following packages to build the Git version of GNU
tar. We do not make any efforts to accommodate older versions of
these packages, so please make sure that you have the latest stable
version.
version.
- Automake <http://www.gnu.org/software/automake/>
- Autoconf <http://www.gnu.org/software/autoconf/>
- M4 <http://www.gnu.org/software/m4/>
- Texinfo <http://www.gnu.org/software/texinfo>
- Gnulib <http://www.gnu.org/software/gnulib>
- Gnulib <http://www.gnu.org/software/gnulib>
- Git <http://git.or.cz>
* Bootstrapping
Obviously, if you are reading these notes, you did manage to clone
tar from Git. The next step is to get other files needed to build,
which are extracted from other source packages:
which are extracted from other source packages:
1. Change to the source tree directory
@@ -27,7 +27,7 @@ which are extracted from other source packages:
2. Run
./bootstrap
./bootstrap
Once done, proceed as described in the file README (section
INSTALLATION).
@@ -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:
@@ -67,5 +72,3 @@ mode: outline
paragraph-separate: "[ ^L]*$"
version-control: never
End:

16
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
@@ -70,6 +71,7 @@ Burkhard Plache plache@krusty.optimax.ns.ca
Calvin Cliff cliff@trifid.astro.ucla.edu
Cameron Elliott cam@mvbms.mvbms.com
Carl Streeter streeter@cae.wisc.edu
Carl Worth cworth@cworth.org
Carsten Heyl heyl@nads.de
Catrin Urbanneck cur@gppc.de
Cesar Romani romani@ifm.uni-hamburg.de
@@ -90,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
@@ -99,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
@@ -117,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
@@ -132,6 +137,7 @@ David Steiner dsteiner@ispa.uni-osnabrueck.de
David Taylor taylor@think.com
Dean Gaudet dgaudet@watdragon.uwaterloo.ca
Demizu Noritoshi nori-d@is.aist-nara.ac.jp
Denis Excoffier denis.excoffier@free.fr
Denis Fortin fortin@acm.org
Dennis Pixton dennis@math.binghamton.edu
Dick Streefland dicks@tasking.nl
@@ -239,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
@@ -294,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
@@ -347,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
@@ -355,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
@@ -367,10 +379,12 @@ Olaf Schlueter olaf@toppoint.de
Olaf Wucknitz owucknitz@hs.uni-hamburg.de
Oliver Trepte oliver@fysik4.kth.se
Olivier Roussel roussel@lifl.fr
Ondřej Vašík ovasik@redhat.com
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
@@ -388,9 +402,11 @@ Peter Fox fox@gec-mi-at.co.uk
Peter Kutschera peter@zditr1.arcs.ac.at
Peter Seebach seebs@taniemarie.solon.com
Phil Hands phil@hands.com
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:

76
acinclude.m4 Normal file
View File

@@ -0,0 +1,76 @@
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 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
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])
m4_pushdef([tar_compr_var],[tar_cv_compressor_]translit($1,[+-],[x_]))
AC_ARG_WITH($1,
AC_HELP_STRING([--with-]$1[=PROG],
[use PROG as ]$1[ compressor program]),
[tar_compr_var=${withval}],
[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
])

507
bootstrap
View File

@@ -1,8 +1,10 @@
#! /bin/sh
# Print a version string.
scriptversion=2012-12-31.16; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2008, 2009 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
@@ -17,7 +19,15 @@
# 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 Paul Eggert and Sergey Poznyakoff.
# Originally written by Paul Eggert. The canonical version of this
# script is maintained as build-aux/bootstrap in gnulib, however, to
# be useful to your project, you should place a copy of it under
# version control in the top-level directory of your project. The
# intent is that all customization can be done with a bootstrap.conf
# file also maintained in your version control; gnulib comes with a
# template build-aux/bootstrap.conf to get you started.
# Please report bugs or propose patches to bug-gnulib@gnu.org.
nl='
'
@@ -34,7 +44,7 @@ bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
bt2=${bt}2
usage() {
echo >&2 "\
cat <<EOF
Usage: $0 [OPTION]...
Bootstrap this package from the checked-out sources.
@@ -48,7 +58,7 @@ Options:
sources reside. Use this if you already
have gnulib sources on your machine, and
do not want to waste your bandwidth downloading
them again.
them again. Defaults to \$GNULIB_SRCDIR.
--copy Copy files instead of creating symbolic links.
--force Attempt to bootstrap even if the sources seem
not to have been checked out.
@@ -57,8 +67,11 @@ Options:
If the file $0.conf exists in the same directory as this script, its
contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Running without arguments will suffice in most cases.
"
EOF
}
# Configuration.
@@ -72,13 +85,22 @@ gnulib_modules=
# Any gnulib files needed that are not in modules.
gnulib_files=
# A function to be called to edit gnulib.mk right after it's created.
# Override it via your own definition in bootstrap.conf.
gnulib_mk_hook() { :; }
# A function to be called after everything else in this script.
# Override it via your own definition in bootstrap.conf.
bootstrap_epilogue() { :; }
# The command to download all .po files for a specified domain into
# a specified directory. Fill in the first %s is the domain name, and
# the second with the destination directory. Use rsync's -L and -r
# options because the latest/%s directory and the .po files within are
# all symlinks.
po_download_command_format=\
"rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
"rsync --delete --exclude '*.s1' -Lrtvz \
'translationproject.org::tp/latest/%s/' '%s'"
extract_package_name='
/^AC_INIT(/{
@@ -108,14 +130,13 @@ 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
$build_aux/config.guess
$build_aux/config.sub
doc/INSTALL
$build_aux/install-sh
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
$build_aux/config.guess
$build_aux/config.sub
doc/INSTALL
"
# Additional gnulib-tool options to use. Use "\newline" to break lines.
@@ -131,7 +152,8 @@ XGETTEXT_OPTIONS='\\\
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
'
# Package bug report address for gettext files
# Package bug report address and copyright holder for gettext files
COPYRIGHT_HOLDER='Free Software Foundation, Inc.'
MSGID_BUGS_ADDRESS=bug-$package@gnu.org
# Files we don't want to import.
@@ -150,6 +172,44 @@ copy=false
# on which version control system (if any) is used in the source directory.
vc_ignore=auto
# find_tool ENVVAR NAMES...
# -------------------------
# Search for a required program. Use the value of ENVVAR, if set,
# otherwise find the first of the NAMES that can be run (i.e.,
# supports --version). If found, set ENVVAR to the program name,
# die otherwise.
find_tool ()
{
find_tool_envvar=$1
shift
find_tool_names=$@
eval "find_tool_res=\$$find_tool_envvar"
if test x"$find_tool_res" = x; then
for i
do
if ($i --version </dev/null) >/dev/null 2>&1; then
find_tool_res=$i
break
fi
done
else
find_tool_error_prefix="\$$find_tool_envvar: "
fi
if test x"$find_tool_res" = x; then
echo >&2 "$0: one of these is required: $find_tool_names"
exit 1
fi
($find_tool_res --version </dev/null) >/dev/null 2>&1 || {
echo >&2 "$0: ${find_tool_error_prefix}cannot run $find_tool_res --version"
exit 1
}
eval "$find_tool_envvar=\$find_tool_res"
eval "export $find_tool_envvar"
}
# Find sha1sum, named gsha1sum on MacPorts, and shasum on MacOS 10.6.
find_tool SHA1SUM sha1sum gsha1sum shasum
# Override the default configuration, if necessary.
# Make sure that bootstrap.conf is sourced from the current directory
# if we were invoked as "sh bootstrap".
@@ -202,7 +262,7 @@ insert_sorted_if_absent() {
file=$1
str=$2
test -f $file || touch $file
echo "$str" | sort -u - $file | cmp -s - $file \
echo "$str" | sort -u - $file | cmp - $file > /dev/null \
|| echo "$str" | sort -u - $file -o $file \
|| exit 1
}
@@ -229,6 +289,128 @@ if test ! -d $build_aux; then
done
fi
# Note this deviates from the version comparison in automake
# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
# but this should suffice as we won't be specifying old
# version formats or redundant trailing .0 in bootstrap.conf.
# If we did want full compatibility then we should probably
# use m4_version_compare from autoconf.
sort_ver() { # sort -V is not generally available
ver1="$1"
ver2="$2"
# split on '.' and compare each component
i=1
while : ; do
p1=$(echo "$ver1" | cut -d. -f$i)
p2=$(echo "$ver2" | cut -d. -f$i)
if [ ! "$p1" ]; then
echo "$1 $2"
break
elif [ ! "$p2" ]; then
echo "$2 $1"
break
elif [ ! "$p1" = "$p2" ]; then
if [ "$p1" -gt "$p2" ] 2>/dev/null; then # numeric comparison
echo "$2 $1"
elif [ "$p2" -gt "$p1" ] 2>/dev/null; then # numeric comparison
echo "$1 $2"
else # numeric, then lexicographic comparison
lp=$(printf "$p1\n$p2\n" | LANG=C sort -n | tail -n1)
if [ "$lp" = "$p2" ]; then
echo "$1 $2"
else
echo "$2 $1"
fi
fi
break
fi
i=$(($i+1))
done
}
get_version() {
app=$1
$app --version >/dev/null 2>&1 || return 1
$app --version 2>&1 |
sed -n '# extract version within line
s/.*[v ]\{1,\}\([0-9]\{1,\}\.[.a-z0-9-]*\).*/\1/
t done
# extract version at start of line
s/^\([0-9]\{1,\}\.[.a-z0-9-]*\).*/\1/
t done
d
:done
#the following essentially does s/5.005/5.5/
s/\.0*\([1-9]\)/.\1/g
p
q'
}
check_versions() {
ret=0
while read app req_ver; do
# We only need libtoolize from the libtool package.
if test "$app" = libtool; then
app=libtoolize
fi
# Honor $APP variables ($TAR, $AUTOCONF, etc.)
appvar=`echo $app | tr '[a-z]-' '[A-Z]_'`
test "$appvar" = TAR && appvar=AMTAR
eval "app=\${$appvar-$app}"
inst_ver=$(get_version $app)
if [ ! "$inst_ver" ]; then
echo "Error: '$app' not found" >&2
ret=1
elif [ ! "$req_ver" = "-" ]; then
latest_ver=$(sort_ver $req_ver $inst_ver | cut -d' ' -f2)
if [ ! "$latest_ver" = "$inst_ver" ]; then
echo "Error: '$app' version == $inst_ver is too old" >&2
echo " '$app' version >= $req_ver is required" >&2
ret=1
fi
fi
done
return $ret
}
print_versions() {
echo "Program Min_version"
echo "----------------------"
printf %s "$buildreq"
echo "----------------------"
# can't depend on column -t
}
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
# but that's not portable enough (e.g., for Solaris).
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
&& use_libtool=1
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
&& use_libtool=1
if test $use_libtool = 1; then
find_tool LIBTOOLIZE glibtoolize libtoolize
fi
if ! printf "$buildreq" | check_versions; then
echo >&2
if test -f README-prereq; then
echo "See README-prereq for how to get the prerequisite programs" >&2
else
echo "Please install the prerequisite programs" >&2
fi
exit 1
fi
echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver.
@@ -245,13 +427,13 @@ if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
fi
cleanup() {
status=$?
rm -fr $1
exit $status
status=$?
rm -fr $1
exit $status
}
git_modules_config () {
GIT_CONFIG_LOCAL=.gitmodules git config "$@"
cleanup_gnulib() {
cleanup "$gnulib_path"
}
# Get paxutils files.
@@ -276,6 +458,12 @@ if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
`
fi
git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@"
}
gnulib_path=`git_modules_config submodule.gnulib.path`
: ${gnulib_path:=gnulib}
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
@@ -285,30 +473,44 @@ case ${GNULIB_SRCDIR--} in
git submodule init || exit $?
git submodule update || exit $?
elif [ ! -d gnulib ]; then
elif [ ! -d "$gnulib_path" ]; then
echo "$0: getting gnulib files..."
trap cleanup_gnulib 1 2 13 15
git clone --help|grep depth > /dev/null && shallow='--depth 2' || shallow=
git clone $shallow git://git.sv.gnu.org/gnulib ||
"cleanup $1"
shallow=
git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2'
git clone $shallow git://git.sv.gnu.org/gnulib "$gnulib_path" ||
cleanup_gnulib
trap - 1 2 13 15
fi
GNULIB_SRCDIR=gnulib
GNULIB_SRCDIR=$gnulib_path
;;
*)
# Redirect the gnulib submodule to the directory on the command line
# if possible.
# Use GNULIB_SRCDIR as a reference.
if test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then
git submodule init
GNULIB_SRCDIR=`cd $GNULIB_SRCDIR && pwd`
git config --replace-all submodule.gnulib.url $GNULIB_SRCDIR
git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
git submodule update || exit $?
GNULIB_SRCDIR=gnulib
if git submodule -h|grep -- --reference > /dev/null; then
# Prefer the one-liner available in git 1.6.4 or newer.
git submodule update --init --reference "$GNULIB_SRCDIR" \
"$gnulib_path" || exit $?
else
# This fallback allows at least git 1.5.5.
if test -f "$gnulib_path"/gnulib-tool; then
# Since file already exists, assume submodule init already complete.
git submodule update || exit $?
else
# Older git can't clone into an empty directory.
rmdir "$gnulib_path" 2>/dev/null
git clone --reference "$GNULIB_SRCDIR" \
"$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
&& git submodule init && git submodule update \
|| exit $?
fi
fi
GNULIB_SRCDIR=$gnulib_path
fi
;;
esac
@@ -326,22 +528,24 @@ download_po_files() {
eval "$cmd"
}
# Download .po files to $po_dir/.reference and copy only the new
# Mirror .po files to $po_dir/.reference and copy only the new
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
# Note po files that exist locally only are left in $po_dir but will
# not be included in LINGUAS and hence will not be distributed.
update_po_files() {
# Directory containing primary .po files.
# Overwrite them only when we're sure a .po file is new.
po_dir=$1
domain=$2
# Download *.po files into this dir.
# Mirror *.po files into this dir.
# Usually contains *.s1 checksum files.
ref_po_dir="$po_dir/.reference"
test -d $ref_po_dir || mkdir $ref_po_dir || return
download_po_files $ref_po_dir $domain \
&& ls "$ref_po_dir"/*.po 2>/dev/null |
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS" || return
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
test "$langs" = '*' && langs=x
@@ -350,10 +554,12 @@ update_po_files() {
new_po="$ref_po_dir/$po.po"
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
! test -f "$po_dir/$po.po" ||
! $SHA1SUM -c --status "$cksum_file" \
< "$new_po" > /dev/null; then
echo "updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
cp "$new_po" "$po_dir/$po.po" \
&& $SHA1SUM < "$new_po" > "$cksum_file"
fi
done
}
@@ -387,45 +593,46 @@ symlink_to_dir()
# FIXME: for now, this does only one level
parent=`dirname "$dst_dir"`
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
done
fi
if $copy; then
{
test ! -h "$dst" || {
echo "$0: rm -f $dst" &&
rm -f "$dst"
}
test ! -h "$dst" || {
echo "$0: rm -f $dst" &&
rm -f "$dst"
}
} &&
test -f "$dst" &&
cmp -s "$src" "$dst" || {
echo "$0: cp -fp $src $dst" &&
cp -fp "$src" "$dst"
echo "$0: cp -fp $src $dst" &&
cp -fp "$src" "$dst"
}
else
test -h "$dst" &&
src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
test "$src_i" = "$dst_i" || {
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
*//* | */../* | */./* | /*/*/*/*/*/)
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
exit 1;;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
/./*) ;;
*//* | */../* | */./* | /*/*/*/*/*/)
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
exit 1;;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
echo "$0: ln -fs $dot_dots$src $dst" &&
ln -fs "$dot_dots$src" "$dst"
echo "$0: ln -fs $dot_dots$src $dst" &&
ln -fs "$dot_dots$src" "$dst"
}
fi
}
@@ -455,28 +662,28 @@ cp_mark_as_generated()
if test -z "$c1"; then
cmp -s "$cp_src" "$cp_dst" || {
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
echo "$0: cp -f $cp_src $cp_dst" &&
rm -f "$cp_dst" &&
cp "$cp_src" "$cp_dst-t" &&
sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" &&
mv -f "$cp_dst-t" "$cp_dst"
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
echo "$0: cp -f $cp_src $cp_dst" &&
rm -f "$cp_dst" &&
cp "$cp_src" "$cp_dst-t" &&
sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" &&
mv -f "$cp_dst-t" "$cp_dst"
}
else
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
cp "$cp_src" "$cp_dst-t" &&
(
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
sed "s!$bt_regex/!!g" "$cp_src"
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
sed "s!$bt_regex/!!g" "$cp_src"
) > $cp_dst-t &&
if cmp -s "$cp_dst-t" "$cp_dst"; then
rm -f "$cp_dst-t"
rm -f "$cp_dst-t"
else
echo "$0: cp $cp_src $cp_dst # with edits" &&
mv -f "$cp_dst-t" "$cp_dst"
echo "$0: cp $cp_src $cp_dst # with edits" &&
mv -f "$cp_dst-t" "$cp_dst"
fi
fi
fi
@@ -488,7 +695,7 @@ version_controlled_file() {
found=no
if test -d CVS; then
grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
elif test -d .git; then
git rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
elif test -d .svn; then
@@ -506,39 +713,42 @@ slurp() {
for file in `ls -a $1/$dir`; do
case $file in
.|..) continue;;
.*) continue;; # FIXME: should all file names starting with "." be ignored?
# FIXME: should all file names starting with "." be ignored?
.*) continue;;
esac
test -d $1/$dir/$file && continue
for excluded_file in $excluded_files; do
test "$dir/$file" = "$excluded_file" && continue 2
test "$dir/$file" = "$excluded_file" && continue 2
done
if test $file = Makefile.am; then
if test $file = Makefile.am && test "X$gnulib_mk" != XMakefile.am; then
copied=$copied${sep}$gnulib_mk; sep=$nl
remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/$gnulib_mk || {
echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
rm -f $dir/$gnulib_mk &&
sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk
}
remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
sed "$remove_intl" $1/$dir/$file |
cmp - $dir/$gnulib_mk > /dev/null || {
echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
rm -f $dir/$gnulib_mk &&
sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk &&
gnulib_mk_hook $dir/$gnulib_mk
}
elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
version_controlled_file $dir $file; then
echo "$0: $dir/$file overrides $1/$dir/$file"
version_controlled_file $dir $file; then
echo "$0: $dir/$file overrides $1/$dir/$file"
else
copied=$copied$sep$file; sep=$nl
if test $file = gettext.m4; then
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
rm -f $dir/$file
sed '
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
AC_DEFUN([AM_INTL_SUBDIR], [
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
$a\
AC_DEFUN([gl_LOCK_EARLY], [])
' $1/$dir/$file >$dir/$file
else
cp_mark_as_generated $1/$dir/$file $dir/$file
fi
copied=$copied$sep$file; sep=$nl
if test $file = gettext.m4; then
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
rm -f $dir/$file
sed '
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
AC_DEFUN([AM_INTL_SUBDIR], [])
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
$a\
AC_DEFUN([gl_LOCK_EARLY], [])
' $1/$dir/$file >$dir/$file
else
cp_mark_as_generated $1/$dir/$file $dir/$file
fi
fi || exit
done
@@ -546,18 +756,25 @@ slurp() {
test $dot_ig = x && continue
ig=$dir/$dot_ig
if test -n "$copied"; then
insert_sorted_if_absent $ig "$copied"
# If an ignored file name ends with .in.h, then also add
# the name with just ".h". Many gnulib headers are generated,
# e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc.
# Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
f=`echo "$copied"|sed 's/\.in\.h$/.h/;s/\.sin$/.sed/;s/\.y$/.c/;s/\.gperf$/.h/'`
insert_sorted_if_absent $ig "$f"
insert_sorted_if_absent $ig "$copied"
# If an ignored file name ends with .in.h, then also add
# the name with just ".h". Many gnulib headers are generated,
# e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc.
# Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
f=`echo "$copied" |
sed '
s/\.in\.h$/.h/
s/\.sin$/.sed/
s/\.y$/.c/
s/\.gperf$/.h/
'
`
insert_sorted_if_absent $ig "$f"
# For files like sys_stat.in.h and sys_time.in.h, record as
# ignorable the directory we might eventually create: sys/.
f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'`
insert_sorted_if_absent $ig "$f"
# For files like sys_stat.in.h and sys_time.in.h, record as
# ignorable the directory we might eventually create: sys/.
f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'`
insert_sorted_if_absent $ig "$f"
fi
done
done
@@ -582,6 +799,12 @@ gnulib_tool_options="\
--local-dir $local_gl_dir\
$gnulib_tool_option_extras\
"
if test $use_libtool = 1; then
case "$gnulib_tool_options " in
*' --libtool '*) ;;
*) gnulib_tool_options="$gnulib_tool_options --libtool" ;;
esac
fi
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
slurp $bt || exit
@@ -597,9 +820,9 @@ grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
with_gettext=no
if test $with_gettext = yes; then
echo "$0: (cd $bt2; autopoint) ..."
echo "$0: (cd $bt2; ${AUTOPOINT-autopoint}) ..."
cp configure.ac $bt2 &&
(cd $bt2 && autopoint && rm configure.ac) &&
(cd $bt2 && ${AUTOPOINT-autopoint} && rm configure.ac) &&
slurp $bt2 $bt || exit
fi
rm -fr $bt $bt2 || exit
@@ -616,6 +839,8 @@ find "$m4_base" "$source_base" \
-depth \( -name '*.m4' -o -name '*.[ch]' \) \
-type l -xtype l -delete > /dev/null 2>&1
# Reconfigure, getting other files.
# copy_files srcdir dstdir
copy_files() {
for file in `cat $1/DISTFILES`
@@ -660,27 +885,22 @@ done
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
# Reconfigure, getting other files.
# Skip autoheader if it's not needed.
grep -E '^[ ]*AC_CONFIG_HEADERS?\>' configure.ac >/dev/null ||
AUTOHEADER=true
for command in \
libtool \
'aclocal --force -I m4' \
'autoconf --force' \
'autoheader --force' \
'automake --add-missing --copy --force-missing';
"${ACLOCAL-aclocal} --force -I m4 $ACLOCAL_FLAGS" \
"${AUTOCONF-autoconf} --force" \
"${AUTOHEADER-autoheader} --force" \
"${AUTOMAKE-automake} --add-missing --copy --force-missing"
do
if test "$command" = libtool; then
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
# but that's not portable enough (e.g., for Solaris).
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
&& use_libtool=1
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
&& use_libtool=1
test $use_libtool = 0 \
&& continue
command='libtoolize -c -f'
command="${LIBTOOLIZE-libtoolize} -c -f"
fi
echo "$0: $command ..."
$command || exit
@@ -703,13 +923,14 @@ if test $with_gettext = yes; then
rm -f po/Makevars
sed '
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= '"$MSGID_BUGS_ADDRESS"'/
/^COPYRIGHT_HOLDER *=/s/=.*/= '"$COPYRIGHT_HOLDER"'/
/^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$MSGID_BUGS_ADDRESS"'|
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' po/Makevars.template >po/Makevars
' po/Makevars.template >po/Makevars || exit 1
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
@@ -719,15 +940,25 @@ if test $with_gettext = yes; then
/^subdir *=.*/s/=.*/= runtime-po/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
}
' <po/Makevars.template >runtime-po/Makevars
' po/Makevars.template >runtime-po/Makevars || exit 1
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
fi
fi
bootstrap_epilogue
echo "$0: done. Now you can run './configure'."
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

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,43 +1,45 @@
# 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 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.22], [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.60])
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
AC_PREREQ([2.63])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-xz std-options silent-rules])
AC_PROG_CC
# Enable silent rules by default:
AM_SILENT_RULES([yes])
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 \
sgtty.h string.h stropts.h \
sys/param.h sys/device.h sys/filio.h sys/gentape.h \
sgtty.h string.h \
sys/param.h sys/device.h sys/gentape.h \
sys/inet.h sys/io/trioctl.h \
sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \
unistd.h locale.h)
@@ -47,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,
@@ -66,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.]))
@@ -86,13 +105,115 @@ gl_INIT
# paxutils modules
tar_PAXUTILS
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
# 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
@@ -121,6 +242,14 @@ else
[Define to the full path of your rsh, if any.])
fi
TAR_COMPR_PROGRAM(compress)
TAR_COMPR_PROGRAM(gzip)
TAR_COMPR_PROGRAM(bzip2)
TAR_COMPR_PROGRAM(lzip)
TAR_COMPR_PROGRAM(lzma)
TAR_COMPR_PROGRAM(lzop)
TAR_COMPR_PROGRAM(xz)
AC_MSG_CHECKING(for default archive format)
AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],
@@ -145,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
@@ -65,7 +65,7 @@ programs (using pipes); tar can even access remote devices or files
%%contributors: Jay Fenlason,
Joy Kendall,
Francois Pinard <pinard@iro.umontreal.ca>
%%source-tarball: ftp://ftp.gnu.org/pub/gnu/tar/tar-1.15.1.tar.gz
%%source-info: http://savannah.gnu.org/projects/tar
@@ -84,4 +84,3 @@ programs (using pipes); tar can even access remote devices or files
%%bug-list: bug-tar@gnu.org bug-tar@gnu.org http://mail.gnu.org/mailman/listinfo/bug-tar
%%entry-written-by: Sergey Poznyakoff <gray@gnu.org>

6
doc/.gitignore vendored
View File

@@ -1,5 +1,7 @@
getdate.texi
genfile.texi
header.texi
manual
parse-datetime.texi
stamp-vti
tar.aux
tar.cp
@@ -22,5 +24,3 @@ tar.toc
tar.tp
tar.vr
version.texi
genfile.texi
header.texi

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 = \
@@ -24,17 +25,23 @@ tar_TEXINFOS = \
fdl.texi\
freemanuals.texi\
genfile.texi\
getdate.texi\
header.texi\
intern.texi\
parse-datetime.texi\
rendition.texi\
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)
@@ -59,25 +66,28 @@ check-format:
fi
check-options:
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
$(top_builddir)/src/tar --usage | \
sed -n 's/^\[--\([^]\=\[]*\).*/\1/p' | sort | uniq > opts.$$$$;\
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS) | \
sed -n '/^@macro/,/^@end macro/d;s/@opindex *\([^@,]*\).*/\1/p' \
| sort | uniq > docs.$$$$;\
(echo 'Not documented options:';\
join -v1 opts.$$$$ docs.$$$$;\
echo 'Non-existing options:';\
join -v2 opts.$$$$ docs.$$$$) > report.$$$$;\
rm opts.$$$$ docs.$$$$;\
if [ -n "`sed '1,2d' report.$$$$`" ]; then \
cat report.$$$$;\
rm report.$$$$;\
exit 1;\
fi;\
rm report.$$$$
status=0;\
join -v1 opts.$$$$ docs.$$$$ > report.$$$$;\
if test -s report.$$$$; then \
echo 'Not documented options:'; \
cat report.$$$$; \
status=1; \
fi; \
join -v2 opts.$$$$ docs.$$$$ > report.$$$$;\
if test -s report.$$$$; then \
echo 'Non-existing options:';\
cat report.$$$$; \
status=1; \
fi; \
rm opts.$$$$ docs.$$$$ report.$$$$;\
test $$status -ne 0 && exit $$status
check-refs:
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
@@ -121,7 +131,7 @@ check-unrevised:
all-check-docs: check-format check-options check-refs check-fixmes check-unrevised
check-docs:
check-docs:
$(MAKE) -k all-check-docs
#
@@ -141,4 +151,3 @@ manual:
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
$(GENDOCS) --texi2html tar 'GNU tar manual'

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.
@@ -16,7 +16,7 @@ dumped directory in special data blocks called @dfn{dumpdirs}.
@noindent
where @var{C} is one of the @dfn{control codes} described below,
@var{filename} is the name of the file @var{C} operates upon, and
@samp{\0} represents a nul character (ASCII 0). The white space
@samp{\0} represents a nul character (ASCII 0). The white space
characters were added for readability, real dumpdirs do not contain
them.
@@ -68,7 +68,7 @@ directory}. For example, consider the following scenario:
@enumerate 1
@item
Previous run dumped a directory @file{foo} which contained the
following three directories:
following three directories:
@smallexample
a
@@ -93,7 +93,7 @@ New incremental dump was made.
renaming @file{a} to @file{b} will destroy the existing directory.
To correctly process it, @GNUTAR{} needs a temporary directory, so
it creates the following dumpdir (newlines have been added for
readability):
readability):
@smallexample
@group
@@ -114,7 +114,7 @@ work as usual, and, finally, the last command, @samp{R\0Tfoo/a\0}
tells tar to rename the temporary directory to @file{foo/a}.
The exact placement of a dumpdir in the archive depends on the
archive format (@pxref{Formats}):
archive format (@pxref{Formats}):
@itemize
@item PAX archives

View File

@@ -1,13 +1,13 @@
@c The GNU Free Documentation License.
@center Version 1.3, 3 November 2008
@node GNU Free Documentation License
@appendixsec GNU Free Documentation License
@cindex FDL, GNU Free Documentation License
@center Version 1.2, November 2002
@c This file is intended to be included within another document,
@c hence no sectioning command or @node.
@display
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Copyright @copyright{} 2000-2002, 2007-2008, 2014 Free Software
Foundation, Inc.
@uref{http://fsf.org/}
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -93,16 +93,16 @@ An image format is not Transparent if used for any substantial amount
of text. A copy that is not ``Transparent'' is called ``Opaque''.
Examples of suitable formats for Transparent copies include plain
@sc{ascii} without markup, Texinfo input format, La@TeX{} input
format, @acronym{SGML} or @acronym{XML} using a publicly available
@acronym{DTD}, and standard-conforming simple @acronym{HTML},
PostScript or @acronym{PDF} designed for human modification. Examples
of transparent image formats include @acronym{PNG}, @acronym{XCF} and
@acronym{JPG}. Opaque formats include proprietary formats that can be
read and edited only by proprietary word processors, @acronym{SGML} or
@acronym{XML} for which the @acronym{DTD} and/or processing tools are
not generally available, and the machine-generated @acronym{HTML},
PostScript or @acronym{PDF} produced by some word processors for
ASCII without markup, Texinfo input format, La@TeX{} input
format, SGML or XML using a publicly available
DTD, and standard-conforming simple HTML,
PostScript or PDF designed for human modification. Examples
of transparent image formats include PNG, XCF and
JPG. Opaque formats include proprietary formats that can be
read and edited only by proprietary word processors, SGML or
XML for which the DTD and/or processing tools are
not generally available, and the machine-generated HTML,
PostScript or PDF produced by some word processors for
output purposes only.
The ``Title Page'' means, for a printed book, the title page itself,
@@ -112,6 +112,9 @@ formats which do not have any title page as such, ``Title Page'' means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
The ``publisher'' means any person or entity that distributes copies
of the Document to the public.
A section ``Entitled XYZ'' means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
@@ -380,13 +383,30 @@ title.
@item
TERMINATION
You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
You may not copy, modify, sublicense, or distribute the Document
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, or distribute it is void, and
will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, receipt of a copy of some or all of the same material does
not give you any rights to use it.
@item
FUTURE REVISIONS OF THIS LICENSE
@@ -404,11 +424,46 @@ following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.
as a draft) by the Free Software Foundation. If the Document
specifies that a proxy can decide which future versions of this
License can be used, that proxy's public statement of acceptance of a
version permanently authorizes you to choose that version for the
Document.
@item
RELICENSING
``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any
World Wide Web server that publishes copyrightable works and also
provides prominent facilities for anybody to edit those works. A
public wiki that anybody can edit is an example of such a server. A
``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the
site means any set of copyrightable works thus published on the MMC
site.
``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0
license published by Creative Commons Corporation, a not-for-profit
corporation with a principal place of business in San Francisco,
California, as well as future copyleft versions of that license
published by that same organization.
``Incorporate'' means to publish or republish a Document, in whole or
in part, as part of another Document.
An MMC is ``eligible for relicensing'' if it is licensed under this
License, and if all works that were first published under this License
somewhere other than this MMC, and subsequently incorporated in whole
or in part into the MMC, (1) had no cover texts or invariant sections,
and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site
under CC-BY-SA on the same site at any time before August 1, 2009,
provided the MMC is eligible for relicensing.
@end enumerate
@page
@appendixsubsec ADDENDUM: How to use this License for your documents
@heading ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
@@ -418,7 +473,7 @@ license notices just after the title page:
@group
Copyright (C) @var{year} @var{your name}.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
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, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled ``GNU
@@ -427,7 +482,7 @@ license notices just after the title page:
@end smallexample
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the ``with...Texts.'' line with this:
replace the ``with@dots{}Texts.'' line with this:
@smallexample
@group

View File

@@ -36,7 +36,7 @@
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
<ul>
<li><a href="%%PACKAGE%%.html">HTML
<li><a href="%%PACKAGE%%.html">HTML
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
<li><a href="html_node/index.html">HTML</a> - with one web page per
node.</li>
@@ -49,7 +49,7 @@
chapter.</li>
%%ENDIF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
one web page.</li>
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
@@ -96,9 +96,9 @@ Return to the <a href="/home.html">GNU Project home page</a>.
</p>
<p>
Please send FSF &amp; GNU inquiries to
Please send FSF &amp; GNU inquiries to
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
the FSF.
<br />
Please send broken links and other corrections (or suggestions) to
@@ -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.
@@ -107,10 +107,10 @@ group permission could be copied from the @emph{other} permission.
The @code{uid} and @code{gid} fields are the numeric user and group
@acronym{ID} of the file owners, respectively. If the operating system does
not support numeric user or group @acronym{ID}s, these fields should
be ignored.
be ignored.
The @code{size} field is the size of the file in bytes; linked files
are archived with this field specified as zero.
are archived with this field specified as zero.
The @code{mtime} field is the data modification time of the file at
the time it was archived. It is the ASCII representation of the octal
@@ -330,4 +330,3 @@ checksum error.
@node Dumpdir
@unnumberedsec Dumpdir
@include dumpdir.texi

View File

@@ -1,37 +1,36 @@
;;; 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:
;; This file redefines texinfo-master-menu-list so that it takes into
;; account included files.
;; Known bugs: @menu without previous sectioning command will inherit
;; Known bugs: @menu without previous sectioning command will inherit
;; documentation string from the previous menu. However, since such a
;; menu is illegal in a texinfo file, we can live with it.
(require 'texinfo)
(require 'texinfo)
(require 'texnfo-upd)
(defun texinfo-master-menu-list-recursive (title)

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.
@@ -23,17 +23,17 @@ snapshots only in format 2.
This appendix describes all three formats in detail.
@enumerate 0
@cindex format 0, snapshot file
@cindex format 0, snapshot file
@cindex snapshot file, format 0
@item
@item
@samp{Format 0} snapshot file begins with a line containing a
decimal number that represents a @acronym{UNIX} timestamp of the
beginning of the last archivation. This line is followed by directory
metadata descriptions, one per line. Each description has the
following format:
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;
@@ -55,9 +58,9 @@ Name of the directory. Any special characters (white-space,
backslashes, etc.) are quoted.
@end table
@cindex format 1, snapshot file
@cindex format 1, snapshot file
@cindex snapshot file, format 1
@item
@item
@samp{Format 1} snapshot file begins with a line specifying the
format of the file. This line has the following structure:
@@ -69,7 +72,7 @@ format of the file. This line has the following structure:
where @var{tar-version} is the version number of @GNUTAR{}
implementation that created this snapshot, and
@var{incr-format-version} is the version number of the snapshot format
(in this case @samp{1}).
(in this case @samp{1}).
Next line contains two decimal numbers, representing the
time of the last backup. First number is the number of seconds, the
@@ -89,11 +92,10 @@ modification time of this directory with nanosecond precision;
@var{nfs}, @var{dev}, @var{inode} and @var{name} have the same meaning
as with @samp{format 0}.
@cindex format 2, snapshot file
@cindex format 2, snapshot file
@cindex snapshot file, format 2
@item
@FIXME{}
A snapshot file begins with a format identifier, as described for
@samp{Format 2} snapshot file begins with a format identifier, as described for
version 1, e.g.:
@smallexample
@@ -105,37 +107,58 @@ 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.
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 name @tab String @tab Directory name; In contrast to the
previous versions it is not quoted.
@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;
@xref{Dumpdir}, for a description of its format.
@item
@item
@end multitable
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.
@@ -14,12 +14,12 @@ The support for sparse files in @GNUTAR{} has a long history. The
earliest version featuring this support that I was able to find was 1.09,
released in November, 1990. The format introduced back then is called
@dfn{old GNU} sparse format and in spite of the fact that its design
contained many flaws, it was the only format @GNUTAR{} supported
contained many flaws, it was the only format @GNUTAR{} supported
until version 1.14 (May, 2004), which introduced initial support for
sparse archives in @acronym{PAX} archives (@pxref{posix}). This
format was not free from design flows, either and it was subsequently
format was not free from design flaws, either and it was subsequently
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
2006).
2006).
In addition to GNU sparse format, @GNUTAR{} is able to read and
extract sparse files archived by @command{star}.
@@ -37,7 +37,7 @@ The following subsections describe each format in detail.
@cindex sparse formats, Old GNU
@cindex Old GNU sparse format
The format introduced some time around 1990 (v. 1.09). It was
The format introduced in November 1990 (v. 1.09) was
designed on top of standard @code{ustar} headers in such an
unfortunate way that some of its fields overwrote fields required by
POSIX.
@@ -61,7 +61,7 @@ extension sparse header follows, @code{0} otherwise.
@end multitable
Each of @code{sparse_header} object at offset 386 describes a single
data chunk. It has the following structure:
data chunk. It has the following structure:
@multitable @columnfractions 0.10 0.10 0.20 0.60
@headitem Offset @tab Size @tab Data type @tab Contents
@@ -78,7 +78,7 @@ the following structure:
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
@item 0 @tab 21 @tab sp @tab @code{sparse_header} @tab
(21 entires) File map.
(21 entries) File map.
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
extension sparse header follows, or @code{0} otherwise.
@end multitable
@@ -97,19 +97,19 @@ versions 1.14--1.15.1. The sparse file map is kept in extended
@table @code
@vrindex GNU.sparse.size, extended header variable
@item GNU.sparse.size
Real size of the stored file
Real size of the stored file;
@item GNU.sparse.numblocks
@vrindex GNU.sparse.numblocks, extended header variable
Number of blocks in the sparse map
Number of blocks in the sparse map;
@item GNU.sparse.offset
@vrindex GNU.sparse.offset, extended header variable
Offset of the data block
Offset of the data block;
@item GNU.sparse.numbytes
@vrindex GNU.sparse.numbytes, extended header variable
Size of the data block
Size of the data block.
@end table
The latter two variables repeat for each data block, so the overall
@@ -117,11 +117,11 @@ structure is like this:
@smallexample
@group
GNU.sparse.size=@var{size}
GNU.sparse.numblocks=@var{numblocks}
GNU.sparse.size=@var{size}
GNU.sparse.numblocks=@var{numblocks}
repeat @var{numblocks} times
GNU.sparse.offset=@var{offset}
GNU.sparse.numbytes=@var{numbytes}
GNU.sparse.offset=@var{offset}
GNU.sparse.numbytes=@var{numbytes}
end repeat
@end group
@end smallexample
@@ -136,8 +136,8 @@ meaningful. Thus, multiple occurrences of @code{GNU.sparse.offset} and
@code{GNU.sparse.numbytes} are conflicting with the POSIX specs.
@item
Attempting to extract such archives using a third-party @command{tar}s
results in extraction of sparse files in @emph{compressed form}. If
Attempting to extract such archives using a third-party's @command{tar}
results in extraction of sparse files in @emph{condensed form}. If
the @command{tar} implementation in question does not support POSIX
format, it will also extract a file containing extension header
attributes. This file can be used to expand the file to its original
@@ -160,7 +160,7 @@ it uses a single variable:
@item GNU.sparse.map
@vrindex GNU.sparse.map, extended header variable
Map of non-null data chunks. It is a string consisting of
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
@end table
To address the 2nd problem, the @code{name} field in @code{ustar}
@@ -181,7 +181,7 @@ restore such members using non-GNU @command{tar}s.
The resulting @code{GNU.sparse.map} string can be @emph{very} long.
Although POSIX does not impose any limit on the length of a @code{x}
header variable, this possibly can confuse some tars.
header variable, this possibly can confuse some @command{tar}s.
@node PAX 1
@appendixsubsec PAX Format, Version 1.0
@@ -218,18 +218,17 @@ The real name of the sparse file is stored in the variable
variable @code{GNU.sparse.realsize}.
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length, delimited
file data. It consists of a series of octal numbers of arbitrary length, delimited
by newlines. The map is padded with nulls to the nearest block boundary.
The first number gives the number of entries in the map. Following are map entries,
each one consisting of two numbers giving the offset and size of the
data block it describes.
The format is designed in such a way that non-posix aware tars and tars not
The format is designed in such a way that non-posix aware @command{tar}s and @command{tar}s not
supporting @code{GNU.sparse.*} keywords will extract each sparse file
in its condensed form with the file map prepended and will place it
into a separate directory. Then, using a simple program it would be
possible to expand the file to its original form even without @GNUTAR{}.
@xref{Sparse Recovery}, for the detailed information on how to extract
sparse members without @GNUTAR{}.

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 recofiguring the harvare. 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,10 +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
@end smallexample
$ @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
@@ -18,5 +18,3 @@
@end ifclear
@xopindex{\option\, summary}
@end macro

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,42 +1,83 @@
# 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
argp-version-etc
backupfile
closeout
configmake
dirname
error
exclude
extern-inline
exitfail
faccessat
fchmodat
fchownat
fcntl-h
fdopendir
fdutimensat
fileblocks
fnmatch-gnu
fprintftime
fseeko
ftruncate
fstatat
full-write
getdate
futimens
getline
getopt
getopt-gnu
getpagesize
gettext
gettime
gitlog-to-changelog
hash
human
inttostr
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
save-cwd
savedir
selinux-at
setenv
snprintf
stat-time
@@ -45,15 +86,20 @@ stdint
stpcpy
strdup-posix
strerror
strtoimax
strtol
strtoul
strtoumax
symlinkat
timespec
unlinkat
unlinkdir
unlocked-io
utime
utimens
unlockpt
utimensat
version-etc-fsf
xalloc
xalloc-die
xgetcwd
xstrtoumax
xvasprintf

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,39 +1,62 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
# 2005, 2006, 2007, 2009 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
rm -f $@-t $@
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
echo "#endif" >> $@-t
mv $@-t $@
$(AM_V_GEN)rm -f $@-t $@
$(AM_V_at)echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
$(AM_V_at)echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
$(AM_V_at)echo "#endif" >> $@-t
$(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,445 +0,0 @@
/* modechange.c -- file mode manipulation
Copyright (C) 1989, 1990, 1997, 1998, 1999 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 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@ai.mit.edu> */
/* The ASCII mode string is compiled into a linked list of `struct
modechange', which can then be applied to each file to be changed.
We do this instead of re-parsing the ASCII string for each file
because the compiled form requires less computation to use; when
changing the mode of many files, this probably results in a
performance gain. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "modechange.h"
#include <sys/stat.h>
#include "xstrtol.h"
#if STDC_HEADERS
# include <stdlib.h>
#else
char *malloc ();
#endif
#ifndef NULL
# define NULL 0
#endif
#if STAT_MACROS_BROKEN
# undef S_ISDIR
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISUID
# define S_ISUID 04000
#endif
#ifndef S_ISGID
# define S_ISGID 04000
#endif
#ifndef S_ISVTX
# define S_ISVTX 01000
#endif
#ifndef S_IRUSR
# define S_IRUSR 0400
#endif
#ifndef S_IWUSR
# define S_IWUSR 0200
#endif
#ifndef S_IXUSR
# define S_IXUSR 0100
#endif
#ifndef S_IRGRP
# define S_IRGRP 0040
#endif
#ifndef S_IWGRP
# define S_IWGRP 0020
#endif
#ifndef S_IXGRP
# define S_IXGRP 0010
#endif
#ifndef S_IROTH
# define S_IROTH 0004
#endif
#ifndef S_IWOTH
# define S_IWOTH 0002
#endif
#ifndef S_IXOTH
# define S_IXOTH 0001
#endif
#ifndef S_IRWXU
# define S_IRWXU 0700
#endif
#ifndef S_IRWXG
# define S_IRWXG 0070
#endif
#ifndef S_IRWXO
# define S_IRWXO 0007
#endif
/* All the mode bits that can be affected by chmod. */
#define CHMOD_MODE_BITS \
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
/* Return newly allocated memory to hold one element of type TYPE. */
#define talloc(type) ((type *) malloc (sizeof (type)))
/* Create a mode_change entry with the specified `=ddd'-style
mode change operation, where NEW_MODE is `ddd'. Return the
new entry, or NULL upon failure. */
static struct mode_change *
make_node_op_equals (mode_t new_mode)
{
struct mode_change *p;
p = talloc (struct mode_change);
if (p == NULL)
return p;
p->next = NULL;
p->op = '=';
p->flags = 0;
p->value = new_mode;
p->affected = CHMOD_MODE_BITS; /* Affect all permissions. */
return p;
}
/* Append entry E to the end of the link list with the specified
HEAD and TAIL. */
static void
mode_append_entry (struct mode_change **head,
struct mode_change **tail,
struct mode_change *e)
{
if (*head == NULL)
*head = *tail = e;
else
{
(*tail)->next = e;
*tail = e;
}
}
/* Return a linked list of file mode change operations created from
MODE_STRING, an ASCII string that contains either an octal number
specifying an absolute mode, or symbolic mode change operations with
the form:
[ugoa...][[+-=][rwxXstugo...]...][,...]
MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-)
should not affect bits set in the umask when no users are given.
Operators not selected in MASKED_OPS ignore the umask.
Return MODE_INVALID if `mode_string' does not contain a valid
representation of file mode change operations;
return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */
struct mode_change *
mode_compile (const char *mode_string, unsigned int masked_ops)
{
struct mode_change *head; /* First element of the linked list. */
struct mode_change *tail; /* An element of the linked list. */
uintmax_t mode_value; /* The mode value, if octal. */
char *string_end; /* Pointer to end of parsed value. */
mode_t umask_value; /* The umask value (surprise). */
head = NULL;
#ifdef lint
tail = NULL;
#endif
if (xstrtoumax (mode_string, &string_end, 8, &mode_value, "") == LONGINT_OK)
{
struct mode_change *p;
if (mode_value != (mode_value & CHMOD_MODE_BITS))
return MODE_INVALID;
p = make_node_op_equals ((mode_t) mode_value);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
return head;
}
umask_value = umask (0);
umask (umask_value); /* Restore the old value. */
--mode_string;
/* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
do
{
/* Which bits in the mode are operated on. */
mode_t affected_bits = 0;
/* `affected_bits' modified by umask. */
mode_t affected_masked;
/* Operators to actually use umask on. */
unsigned ops_to_mask = 0;
int who_specified_p;
affected_bits = 0;
ops_to_mask = 0;
/* Turn on all the bits in `affected_bits' for each group given. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
case 'u':
affected_bits |= S_ISUID | S_IRWXU;
break;
case 'g':
affected_bits |= S_ISGID | S_IRWXG;
break;
case 'o':
affected_bits |= S_ISVTX | S_IRWXO;
break;
case 'a':
affected_bits |= CHMOD_MODE_BITS;
break;
default:
goto no_more_affected;
}
no_more_affected:
/* If none specified, affect all bits, except perhaps those
set in the umask. */
if (affected_bits)
who_specified_p = 1;
else
{
who_specified_p = 0;
affected_bits = CHMOD_MODE_BITS;
ops_to_mask = masked_ops;
}
while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')
{
struct mode_change *change = talloc (struct mode_change);
if (change == NULL)
{
mode_free (head);
return MODE_MEMORY_EXHAUSTED;
}
change->next = NULL;
change->op = *mode_string; /* One of "=+-". */
affected_masked = affected_bits;
/* Per the Single Unix Spec, if `who' is not specified and the
`=' operator is used, then clear all the bits first. */
if (!who_specified_p &&
ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS : 0))
{
struct mode_change *p = make_node_op_equals (0);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
}
if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
: *mode_string == '+' ? MODE_MASK_PLUS
: MODE_MASK_MINUS))
affected_masked &= ~umask_value;
change->affected = affected_masked;
change->value = 0;
change->flags = 0;
/* Add the element to the tail of the list, so the operations
are performed in the correct order. */
mode_append_entry (&head, &tail, change);
/* Set `value' according to the bits set in `affected_masked'. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
case 'r':
change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
& affected_masked);
break;
case 'w':
change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
& affected_masked);
break;
case 'X':
change->flags |= MODE_X_IF_ANY_X;
/* Fall through. */
case 'x':
change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
& affected_masked);
break;
case 's':
/* Set the setuid/gid bits if `u' or `g' is selected. */
change->value |= (S_ISUID | S_ISGID) & affected_masked;
break;
case 't':
/* Set the "save text image" bit if `o' is selected. */
change->value |= S_ISVTX & affected_masked;
break;
case 'u':
/* Set the affected bits to the value of the `u' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXU;
change->flags |= MODE_COPY_EXISTING;
break;
case 'g':
/* Set the affected bits to the value of the `g' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXG;
change->flags |= MODE_COPY_EXISTING;
break;
case 'o':
/* Set the affected bits to the value of the `o' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXO;
change->flags |= MODE_COPY_EXISTING;
break;
default:
goto no_more_values;
}
no_more_values:;
}
} while (*mode_string == ',');
if (*mode_string == 0)
return head;
invalid:
mode_free (head);
return MODE_INVALID;
}
/* Return a file mode change operation that sets permissions to match those
of REF_FILE. Return MODE_BAD_REFERENCE if REF_FILE can't be accessed. */
struct mode_change *
mode_create_from_ref (const char *ref_file)
{
struct mode_change *change; /* the only change element */
struct stat ref_stats;
if (stat (ref_file, &ref_stats))
return MODE_BAD_REFERENCE;
change = talloc (struct mode_change);
if (change == NULL)
return MODE_MEMORY_EXHAUSTED;
change->op = '=';
change->flags = 0;
change->affected = CHMOD_MODE_BITS;
change->value = ref_stats.st_mode;
change->next = NULL;
return change;
}
/* Return file mode OLDMODE, adjusted as indicated by the list of change
operations CHANGES. If OLDMODE is a directory, the type `X'
change affects it even if no execute bits were set in OLDMODE.
The returned value has the S_IFMT bits cleared. */
mode_t
mode_adjust (mode_t oldmode, const struct mode_change *changes)
{
mode_t newmode; /* The adjusted mode and one operand. */
mode_t value; /* The other operand. */
newmode = oldmode & CHMOD_MODE_BITS;
for (; changes; changes = changes->next)
{
if (changes->flags & MODE_COPY_EXISTING)
{
/* Isolate in `value' the bits in `newmode' to copy, given in
the mask `changes->value'. */
value = newmode & changes->value;
if (changes->value & S_IRWXU)
/* Copy `u' permissions onto `g' and `o'. */
value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
| (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
| (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
else if (changes->value & S_IRWXG)
/* Copy `g' permissions onto `u' and `o'. */
value |= ((value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
| (value & S_IWGRP ? S_IWUSR | S_IROTH : 0)
| (value & S_IXGRP ? S_IXUSR | S_IXOTH : 0));
else
/* Copy `o' permissions onto `u' and `g'. */
value |= ((value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
| (value & S_IWOTH ? S_IWUSR | S_IRGRP : 0)
| (value & S_IXOTH ? S_IXUSR | S_IXGRP : 0));
/* In order to change only `u', `g', or `o' permissions,
or some combination thereof, clear unselected bits.
This can not be done in mode_compile because the value
to which the `changes->affected' mask is applied depends
on the old mode of each file. */
value &= changes->affected;
}
else
{
value = changes->value;
/* If `X', do not affect the execute bits if the file is not a
directory and no execute bits are already set. */
if ((changes->flags & MODE_X_IF_ANY_X)
&& !S_ISDIR (oldmode)
&& (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
/* Clear the execute bits. */
value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
}
switch (changes->op)
{
case '=':
/* Preserve the previous values in `newmode' of bits that are
not affected by this change operation. */
newmode = (newmode & ~changes->affected) | value;
break;
case '+':
newmode |= value;
break;
case '-':
newmode &= ~value;
break;
}
}
return newmode;
}
/* Free the memory used by the list of file mode change operations
CHANGES. */
void
mode_free (register struct mode_change *changes)
{
register struct mode_change *next;
while (changes)
{
next = changes->next;
free (changes);
changes = next;
}
}

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

852
rebox.el
View File

@@ -1,852 +0,0 @@
;;; Handling of comment boxes.
;;; Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
;;; Fran<61>ois Pinard <pinard@iro.umontreal.ca>, April 1991.
;;; I first observed rounded corners, as in style 223 boxes, in code from
;;; Warren Tucker <wht@n4hgf.mt-park.ga.us>, a previous shar maintainer.
;;; Refilling paragraphs inside comments, stretching or shrinking the
;;; surrounding box as needed, is a pain to do "by hand". This GNU Emacs
;;; LISP code eases my life on this and I find it fair, giving all sources
;;; for a package, to also give the means for nicely modifying comments.
;;; The function rebox-comment discovers the extent of the boxed comments
;;; near the cursor, possibly refills the text, then adjusts the comment
;;; box style. The function rebox-region does the same, except that it
;;; takes the current region as a boxed comment. Numeric prefixes are
;;; used to add or remove a box, change its style (language, quality or
;;; type), or to prevent refilling of its text. A minus sign alone as
;;; prefix asks for interactive style selection.
;;; For most Emacs language editing modes, refilling does not make sense
;;; outside comments, so you may redefine the M-q command and link it to
;;; this file. For example, I use this in my .emacs file:
;;; (setq c-mode-hook
;;; '(lambda ()
;;; (define-key c-mode-map "\M-q" 'rebox-comment)))
;;; (autoload 'rebox-comment "rebox" nil t)
;;; (autoload 'rebox-region "rebox" nil t)
;;; The cursor should be within a comment before any of these commands,
;;; or else it should be between two comments, in which case the command
;;; applies to the next comment. When the command is given without prefix,
;;; the current comment box style is recognized from the comment itself
;;; as far as possible, and preserved. A prefix may be used to force
;;; a particular box style. A style is made up of three attributes: a
;;; language (the hundreds digit), a quality (the tens digit) and a type
;;; (the units digit). A zero or negative flag value changes the default
;;; box style to its absolute value. Zero digits in default style,
;;; when not overriden in flag, asks for recognition of corresponding
;;; attributes from the current box. `C-u' avoids refilling the text,
;;; using the default box style. `C-u -' defines the style interactively.
;;; Box language is associated with comment delimiters. Values are 100
;;; for none or unknown, 200 for `/*' and `*/' as in plain C, 300 for
;;; '//' as in C++, 400 for `#' as in most scripting languages, 500 for
;;; `;' as in LISP or assembler and 600 for `%' as in TeX or PostScript.
;;; Box quality differs according to language. For unknown languages (100)
;;; or for the C language (200), values are 10 for simple, 20 or 30 for
;;; rounded, and 40 for starred. For all others, box quality indicates
;;; the thickness in characters of the left and right sides of the box:
;;; values are 10, 20, 30 or 40 for 1, 2, 3 or 4 characters wide. C++
;;; quality 10 is always promoted to 20. Roughly said, simple quality
;;; boxes (10) use comment delimiters to left and right of each comment
;;; line, and also for the top or bottom line when applicable. Rounded
;;; quality boxes (20 or 30) try to suggest rounded corners in boxes.
;;; Starred quality boxes (40) mostly use a left margin of asterisks or
;;; X'es, and use them also in box surroundings. Experiment a little to
;;; see what happens.
;;; Box type values are 1 for fully opened boxes for which boxing is done
;;; only for the left and right but not for top or bottom, 2 for half
;;; single lined boxes for which boxing is done on all sides except top,
;;; 3 for fully single lined boxes for which boxing is done on all sides,
;;; 4 for half double lined boxes which is like type 2 but more bold,
;;; or 5 for fully double lined boxes which is like type 3 but more bold.
;;; The special style 221 or 231 is worth a note, because it is fairly
;;; common: the whole C comment stays between a single opening `/*'
;;; and a single closing `*/'. The special style 111 deletes a box.
;;; The initial default style is 023 so, unless overriden, comments are
;;; put in single lined boxes, C comments are of rounded quality.
(defvar rebox-default-style 0 "*Preferred style for box comments.")
;;; Help strings for prompting or error messages.
(defconst REBOX_HELP_FOR_LANGUAGE
"Box language is 100-none, 200-/*, 300-//, 400-#, 500-;, 600-%%")
(defconst REBOX_LANGUAGE_NONE 100)
(defconst REBOX_LANGUAGE_C 200)
(defconst REBOX_LANGUAGE_C++ 300)
(defconst REBOX_LANGUAGE_AWK 400)
(defconst REBOX_LANGUAGE_LISP 500)
(defconst REBOX_LANGUAGE_TEX 600)
(defun rebox-help-string-for-language (language)
(cond ((= language 0) "default language")
((= language REBOX_LANGUAGE_NONE) "no language")
((= language REBOX_LANGUAGE_C) "plain C")
((= language REBOX_LANGUAGE_C++) "C++")
((= language REBOX_LANGUAGE_AWK) "sh/Perl/make")
((= language REBOX_LANGUAGE_LISP) "LISP/assembler")
((= language REBOX_LANGUAGE_TEX) "TeX/PostScript")
(t "<Unknown Language>")))
(defconst REBOX_HELP_FOR_QUALITY
"Box quality/width is 10-simple, 20-rounded, 30-rounded or 40-starred")
(defconst REBOX_QUALITY_SIMPLE_ONE 10)
(defconst REBOX_QUALITY_ROUNDED_TWO 20)
(defconst REBOX_QUALITY_ROUNDED_THREE 30)
(defconst REBOX_QUALITY_STARRED_FOUR 40)
(defun rebox-help-string-for-quality (quality)
(cond ((= quality 0) "default quality")
((= quality REBOX_QUALITY_SIMPLE_ONE) "square or 1-wide")
((= quality REBOX_QUALITY_ROUNDED_TWO) "rounded or 2-wide")
((= quality REBOX_QUALITY_ROUNDED_THREE) "rounded or 3-wide")
((= quality REBOX_QUALITY_STARRED_FOUR) "starred or 4-wide")
(t "<Unknown Quality>")))
(defconst REBOX_HELP_FOR_TYPE
"Box type is 1-open, 2-half-single, 3-single, 4-half-double or 5-double")
(defconst REBOX_TYPE_OPEN 1)
(defconst REBOX_TYPE_HALF_SINGLE 2)
(defconst REBOX_TYPE_SINGLE 3)
(defconst REBOX_TYPE_HALF_DOUBLE 4)
(defconst REBOX_TYPE_DOUBLE 5)
(defun rebox-help-string-for-type (type)
(cond ((= type 0) "default type")
((= type REBOX_TYPE_OPEN) "opened box")
((= type REBOX_TYPE_HALF_SINGLE) "half normal")
((= type REBOX_TYPE_SINGLE) "full normal")
((= type REBOX_TYPE_HALF_DOUBLE) "half bold")
((= type REBOX_TYPE_DOUBLE) "full bold")
(t "<Unknown Type>")))
(defconst REBOX_MAX_LANGUAGE 6)
(defconst REBOX_MAX_QUALITY 4)
(defconst REBOX_MAX_TYPE 5)
;;; Request the style interactively, using the minibuffer.
(defun rebox-ask-for-style ()
(let (key language quality type)
(while (not language)
(message REBOX_HELP_FOR_LANGUAGE)
(setq key (read-char))
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_LANGUAGE)))
(setq language (- key ?0))))
(while (not quality)
(message REBOX_HELP_FOR_QUALITY)
(setq key (read-char))
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_QUALITY)))
(setq quality (- key ?0))))
(while (not type)
(message REBOX_HELP_FOR_TYPE)
(setq key (read-char))
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_TYPE)))
(setq type (- key ?0))))
(+ (* 100 language) (* 10 quality) type)))
;;; Write some TEXT followed by an edited STYLE value into the minibuffer.
(defun rebox-show-style (text style)
(message
(concat text (format " (%03d)" style)
": " (rebox-help-string-for-language (* (/ style 100) 100))
", " (rebox-help-string-for-quality (* (% (/ style 10) 10) 10))
", " (rebox-help-string-for-type (% style 10)))))
;;; Validate FLAG and usually return t if not interrupted by errors.
;;; But if FLAG is zero or negative, then change default box style and
;;; return nil.
(defun rebox-validate-flag (flag)
;; Validate flag.
(if (numberp flag)
(let ((value (if (< flag 0) (- flag) flag)))
(if (> (/ value 100) REBOX_MAX_LANGUAGE)
(error REBOX_HELP_FOR_LANGUAGE))
(if (> (% (/ value 10) 10) REBOX_MAX_QUALITY)
(error REBOX_HELP_FOR_QUALITY))
(if (> (% value 10) REBOX_MAX_TYPE)
(error REBOX_HELP_FOR_TYPE))))
;; Change default box style if requested.
(if (and (numberp flag) (<= flag 0))
(progn
(setq flag (- flag))
(if (not (zerop (/ flag 100)))
(setq rebox-default-style
(+ (* (/ flag 100) 100)
(% rebox-default-style 100))))
(if (not (zerop (% (/ flag 10) 10)))
(setq rebox-default-style
(+ (* (/ rebox-default-style 100) 100)
(* (% (/ flag 10) 10) 10)
(% rebox-default-style 10))))
(if (not (zerop (% flag 10)))
(setq rebox-default-style
(+ (* (/ rebox-default-style 10) 10)
(% flag 10))))
(rebox-show-style "Default style" rebox-default-style)
nil)
t))
;;; Return the minimum value of the left margin of all lines, or -1 if
;;; all lines are empty.
(defun rebox-left-margin ()
(let ((margin -1))
(goto-char (point-min))
(while (not (eobp))
(skip-chars-forward " \t")
(if (not (looking-at "\n"))
(setq margin
(if (< margin 0)
(current-column)
(min margin (current-column)))))
(forward-line 1))
margin))
;;; Return the maximum value of the right margin of all lines. Any
;;; sentence ending a line has a space guaranteed before the margin.
(defun rebox-right-margin ()
(let ((margin 0) period)
(goto-char (point-min))
(while (not (eobp))
(end-of-line)
(if (bobp)
(setq period 0)
(backward-char 1)
(setq period (if (looking-at "[.?!]") 1 0))
(forward-char 1))
(setq margin (max margin (+ (current-column) period)))
(forward-char 1))
margin))
;;; Return a regexp to match the start or end of a comment for some
;;; LANGUAGE, leaving the comment marks themselves available in \1.
;; FIXME: Recognize style 1** boxes.
(defun rebox-regexp-start (language)
(cond ((= language 0) "^[ \t]*\\(/\\*\\|//+\\|#+\\|;+\\|%+\\)")
((= language REBOX_LANGUAGE_NONE) "^\\(\\)")
((= language REBOX_LANGUAGE_C) "^[ \t]*\\(/\\*\\)")
((= language REBOX_LANGUAGE_C++) "^[ \t]*\\(//+\\)")
((= language REBOX_LANGUAGE_AWK) "^[ \t]*\\(#+\\)")
((= language REBOX_LANGUAGE_LISP) "^[ \t]*\\(;+\\)")
((= language REBOX_LANGUAGE_TEX) "^[ \t]*\\(%+\\)")))
(defun rebox-regexp-end (language)
(cond ((= language 0) "\\(\\*/\\|//+\\|#+\\|;+\\|%+\\)[ \t]*$")
((= language REBOX_LANGUAGE_NONE) "\\(\\)$")
((= language REBOX_LANGUAGE_C) "\\(\\*/\\)[ \t]*$")
((= language REBOX_LANGUAGE_C++) "\\(//+\\)[ \t]*$")
((= language REBOX_LANGUAGE_AWK) "\\(#+\\)[ \t]*$")
((= language REBOX_LANGUAGE_LISP) "\\(;+\\)[ \t]*$")
((= language REBOX_LANGUAGE_TEX) "\\(%+\\)[ \t]*$")))
;;; By looking at the text starting at the cursor position, guess the
;;; language in use, and return it.
(defun rebox-guess-language ()
(let ((language REBOX_LANGUAGE_NONE)
(value (* 100 REBOX_MAX_LANGUAGE)))
(while (not (zerop value))
(if (looking-at (rebox-regexp-start value))
(progn
(setq language value)
(setq value 0))
(setq value (- value 100))))
language))
;;; Find the limits of the block of comments following or enclosing
;;; the cursor, or return an error if the cursor is not within such a
;;; block of comments. Extend it as far as possible in both
;;; directions, then narrow the buffer around it.
(defun rebox-find-and-narrow ()
(save-excursion
(let (start end temp language)
;; Find the start of the current or immediately following comment.
(beginning-of-line)
(skip-chars-forward " \t\n")
(beginning-of-line)
(if (not (looking-at (rebox-regexp-start 0)))
(progn
(setq temp (point))
(if (re-search-forward "\\*/" nil t)
(progn
(re-search-backward "/\\*")
(if (> (point) temp)
(error "outside any comment block"))
(setq temp (point))
(beginning-of-line)
(skip-chars-forward " \t")
(if (not (= (point) temp))
(error "text before start of comment"))
(beginning-of-line))
(error "outside any comment block"))))
(setq start (point))
(setq language (rebox-guess-language))
;; - find the end of this comment
(if (= language REBOX_LANGUAGE_C)
(progn
(search-forward "*/")
(if (not (looking-at "[ \t]*$"))
(error "text after end of comment"))))
(end-of-line)
(if (eobp)
(insert "\n")
(forward-char 1))
(setq end (point))
;; - try to extend the comment block backwards
(goto-char start)
(while (and (not (bobp))
(if (= language REBOX_LANGUAGE_C)
(progn
(skip-chars-backward " \t\n")
(if (and (looking-at "[ \t]*\n[ \t]*/\\*")
(> (point) 2))
(progn
(backward-char 2)
(if (looking-at "\\*/")
(progn
(re-search-backward "/\\*")
(setq temp (point))
(beginning-of-line)
(skip-chars-forward " \t")
(if (= (point) temp)
(progn (beginning-of-line) t)))))))
(previous-line 1)
(looking-at (rebox-regexp-start language))))
(setq start (point)))
;; - try to extend the comment block forward
(goto-char end)
(while (looking-at (rebox-regexp-start language))
(if (= language REBOX_LANGUAGE_C)
(progn
(re-search-forward "[ \t]*/\\*")
(re-search-forward "\\*/")
(if (looking-at "[ \t]*$")
(progn
(beginning-of-line)
(forward-line 1)
(setq end (point)))))
(forward-line 1)
(setq end (point))))
;; - narrow to the whole block of comments
(narrow-to-region start end))))
;;; After refilling it if REFILL is not nil, while respecting a left
;;; MARGIN, put the narrowed buffer back into a boxed LANGUAGE comment
;;; box of a given QUALITY and TYPE.
(defun rebox-reconstruct (refill margin language quality type)
(rebox-show-style "Style" (+ language quality type))
(let (right-margin nw nn ne ww ee sw ss se x xx)
;; - decide the elements of the box being produced
(cond ((= language REBOX_LANGUAGE_NONE)
;; - planify a comment for no language in particular
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
;; - planify a simple box
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "| ") (setq ee " |")
(setq sw "+-") (setq ss ?-) (setq se "-+"))
((= type REBOX_TYPE_SINGLE)
(setq nw "+-") (setq nn ?-) (setq ne "-+")
(setq ww "| ") (setq ee " |")
(setq sw "+-") (setq ss ?-) (setq se "-+"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "| ") (setq ee " |")
(setq sw "*=") (setq ss ?=) (setq se "=*"))
((= type REBOX_TYPE_DOUBLE)
(setq nw "*=") (setq nn ?=) (setq ne "=*")
(setq ww "| ") (setq ee " |")
(setq sw "*=") (setq ss ?=) (setq se "=*"))))
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
(= quality REBOX_QUALITY_ROUNDED_THREE))
;; - planify a rounded box
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "| ") (setq ee " |"))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "-'"))
((= type REBOX_TYPE_SINGLE)
(setq nw ".-") (setq nn ?-) (setq ne "-.")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "-'"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/=" ) (setq nn ?=) (setq ne "=\\")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))))
((= quality REBOX_QUALITY_STARRED_FOUR)
;; - planify a starred box
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "| ") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "* ") (setq ee " *")
(setq sw "**") (setq ss ?*) (setq se "**"))
((= type REBOX_TYPE_SINGLE)
(setq nw "**") (setq nn ?*) (setq ne "**")
(setq ww "* ") (setq ee " *")
(setq sw "**") (setq ss ?*) (setq se "**"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "X ") (setq ee " X")
(setq sw "XX") (setq ss ?X) (setq se "XX"))
((= type REBOX_TYPE_DOUBLE)
(setq nw "XX") (setq nn ?X) (setq ne "XX")
(setq ww "X ") (setq ee " X")
(setq sw "XX") (setq ss ?X) (setq se "XX"))))))
((= language REBOX_LANGUAGE_C)
;; - planify a comment for C
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
;; - planify a simple C comment
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "/* ") (setq ee " */"))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?-) (setq se " */"))
((= type REBOX_TYPE_SINGLE)
(setq nw "/* ") (setq nn ?-) (setq ne " */")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?-) (setq se " */"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?=) (setq se " */"))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/* ") (setq nn ?=) (setq ne " */")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?=) (setq se " */"))))
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
(= quality REBOX_QUALITY_ROUNDED_THREE))
;; - planify a rounded C comment
(cond ((= type REBOX_TYPE_OPEN)
;; ``open rounded'' is a special case
(setq nw "") (setq sw "")
(setq ww " ") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "/*") (setq nn ? ) (setq ne " .")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "*/"))
((= type REBOX_TYPE_SINGLE)
(setq nw "/*") (setq nn ?-) (setq ne "-.")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "*/"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "/*" ) (setq nn ? ) (setq ne " \\")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/*" ) (setq nn ?=) (setq ne "=\\")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))))
((= quality REBOX_QUALITY_STARRED_FOUR)
;; - planify a starred C comment
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "/* ") (setq nn ? ) (setq ne "")
(setq ww " * ") (setq ee "")
(setq sw " */") (setq ss ? ) (setq se ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "/* ") (setq nn ? ) (setq ne " *")
(setq ww " * ") (setq ee " *")
(setq sw " **") (setq ss ?*) (setq se "**/"))
((= type REBOX_TYPE_SINGLE)
(setq nw "/**") (setq nn ?*) (setq ne "**")
(setq ww " * ") (setq ee " *")
(setq sw " **") (setq ss ?*) (setq se "**/"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "/* " ) (setq nn ? ) (setq ne " *\\")
(setq ww "|* " ) (setq ee " *|" )
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/**" ) (setq nn ?*) (setq ne "**\\")
(setq ww "|* " ) (setq ee " *|" )
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))))))
(t
;; - planify a comment for all other things
(if (and (= language REBOX_LANGUAGE_C++)
(= quality REBOX_QUALITY_SIMPLE_ONE))
(setq quality REBOX_QUALITY_ROUNDED_TWO))
(setq x (cond ((= language REBOX_LANGUAGE_C++) ?/)
((= language REBOX_LANGUAGE_AWK) ?#)
((= language REBOX_LANGUAGE_LISP) ?\;)
((= language REBOX_LANGUAGE_TEX) ?%)))
(setq xx (make-string (/ quality 10) x))
(setq ww (concat xx " "))
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq ee (concat " " xx))
(setq nw "")
(setq sw ww) (setq ss ?-) (setq se ee))
((= type REBOX_TYPE_SINGLE)
(setq ee (concat " " xx))
(setq nw ww) (setq nn ?-) (setq ne ee)
(setq sw ww) (setq ss ?-) (setq se ee))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq ee (concat " " xx))
(setq xx (make-string (1+ (/ quality 10)) x))
(setq nw "")
(setq sw xx) (setq ss x) (setq se xx))
((= type REBOX_TYPE_DOUBLE)
(setq ee (concat " " xx))
(setq xx (make-string (1+ (/ quality 10)) x))
(setq nw xx) (setq nn x) (setq ne xx)
(setq sw xx) (setq ss x) (setq se xx)))))
;; - possibly refill, and adjust margins to account for left inserts
(if (not (and flag (listp flag)))
(let ((fill-prefix (make-string margin ? ))
(fill-column (- fill-column (+ (length ww) (length ee)))))
(fill-region (point-min) (point-max))))
(setq right-margin (+ (rebox-right-margin) (length ww)))
;; - construct the box comment, from top to bottom
(goto-char (point-min))
(if (and (= language REBOX_LANGUAGE_C)
(or (= quality REBOX_QUALITY_ROUNDED_TWO)
(= quality REBOX_QUALITY_ROUNDED_THREE))
(= type REBOX_TYPE_OPEN))
(progn
;; - construct an 33 style comment
(skip-chars-forward " " (+ (point) margin))
(insert (make-string (- margin (current-column)) ? )
"/* ")
(end-of-line)
(forward-char 1)
(while (not (eobp))
(skip-chars-forward " " (+ (point) margin))
(insert (make-string (- margin (current-column)) ? )
ww)
(beginning-of-line)
(forward-line 1))
(backward-char 1)
(insert " */"))
;; - construct all other comment styles
;; construct one top line
(if (not (zerop (length nw)))
(progn
(indent-to margin)
(insert nw)
(if (or (not (eq nn ? )) (not (zerop (length ne))))
(insert (make-string (- right-margin (current-column)) nn)
ne))
(insert "\n")))
;; construct one middle line
(while (not (eobp))
(skip-chars-forward " " (+ (point) margin))
(insert (make-string (- margin (current-column)) ? )
ww)
(end-of-line)
(if (not (zerop (length ee)))
(progn
(indent-to right-margin)
(insert ee)))
(beginning-of-line)
(forward-line 1))
;; construct one bottom line
(if (not (zerop (length sw)))
(progn
(indent-to margin)
(insert sw)
(if (or (not (eq ss ? )) (not (zerop (length se))))
(insert (make-string (- right-margin (current-column)) ss)
se "\n")))))))
;;; Add, delete or adjust a comment box in the narrowed buffer.
;;; Various FLAG values are explained at beginning of this file.
(defun rebox-engine (flag)
(let ((undo-list buffer-undo-list)
(marked-point (point-marker))
(language (progn (goto-char (point-min)) (rebox-guess-language)))
(quality 0)
(type 0))
(untabify (point-min) (point-max))
;; Remove all the comment marks, and move all the text rigidly to the
;; left for insuring that the left margin stays at the same place.
;; At the same time, try recognizing the box style, saving its quality
;; in QUALITY and its type in TYPE. (LANGUAGE is already guessed.)
(let ((indent-tabs-mode nil)
(previous-margin (rebox-left-margin))
actual-margin)
;; FIXME: Cleanup style 1** boxes.
;; FIXME: Recognize really all cases of type and quality.
;; - remove all comment marks
(if (= language REBOX_LANGUAGE_NONE)
nil
(goto-char (point-min))
(while (re-search-forward (rebox-regexp-start language) nil t)
(goto-char (match-beginning 1))
(delete-region (point) (match-end 1))
(insert (make-string (- (match-end 1) (point)) ? )))
(goto-char (point-min))
(while (re-search-forward (rebox-regexp-end language) nil t)
(replace-match "" t t)))
(if (= language REBOX_LANGUAGE_C)
(progn
(goto-char (point-min))
(while (re-search-forward "\\*/ */\\*" nil t)
(replace-match " " t t))
(goto-char (point-min))
(while (re-search-forward "^\\( *\\)|\\*\\(.*\\)\\*| *$" nil t)
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_DOUBLE)
(replace-match "\\1 \\2" t))
(goto-char (point-min))
(while (re-search-forward "^\\( *\\)\\*\\(.*\\)\\* *$" nil t)
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_SINGLE)
(replace-match "\\1 \\2" t))
(goto-char (point-min))
(while (re-search-forward "^\\( *\\)|\\(.*\\)| *$" nil t)
(setq quality REBOX_QUALITY_ROUNDED_TWO)
(replace-match "\\1 \\2" t))
(goto-char (point-min))
(if (zerop quality)
(while (re-search-forward "^\\( +\\)\\* " nil t)
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_OPEN)
(replace-match "\\1 " t)))))
;; - remove the first dashed or starred line
(goto-char (point-min))
(if (looking-at "^ *\\(--+\\|\\*\\*+\\)[.\+\\]? *\n")
(progn
(setq type REBOX_TYPE_SINGLE)
(replace-match "" t t))
(if (looking-at "^ *\\(==\\|XX+\\|##+\\|;;+\\)[.\+\\]? *\n")
(progn
(setq type REBOX_TYPE_DOUBLE)
(replace-match "" t t))))
;; - remove the last dashed or starred line
(goto-char (point-max))
(previous-line 1)
(if (looking-at "^ *[`\+\\]?*--+ *\n")
(progn
(if (= type REBOX_TYPE_OPEN)
(setq type REBOX_TYPE_HALF_SINGLE))
(replace-match "" t t))
(if (looking-at "^ *[`\+\\]?*\\(==+\\|##+\\|;;+\\) *\n")
(progn
(if (= type REBOX_TYPE_OPEN)
(setq type REBOX_TYPE_HALF_DOUBLE))
(replace-match "" t t))
(if (looking-at "^ *\\*\\*+[.\+\\]? *\n")
(progn
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_HALF_SINGLE)
(replace-match "" t t))
(if (looking-at "^ *XX+[.\+\\]? *\n")
(progn
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_HALF_DOUBLE)
(replace-match "" t t))))))
;; - remove all spurious whitespace
(goto-char (point-min))
(while (re-search-forward " +$" nil t)
(replace-match "" t t))
(goto-char (point-min))
(if (looking-at "\n+")
(replace-match "" t t))
(goto-char (point-max))
(skip-chars-backward "\n")
(if (looking-at "\n\n+")
(replace-match "\n" t t))
(goto-char (point-min))
(while (re-search-forward "\n\n\n+" nil t)
(replace-match "\n\n" t t))
;; - move the text left is adequate
(setq actual-margin (rebox-left-margin))
(if (not (= previous-margin actual-margin))
(indent-rigidly (point-min) (point-max)
(- previous-margin actual-margin))))
;; Override box style according to FLAG or chosen default style.
;; Else, use either recognized style elements or built-in defaults.
(cond ((and (numberp flag) (not (zerop (/ flag 100))))
(setq language (* (/ flag 100) 100)))
((not (zerop (/ rebox-default-style 100)))
(setq language (* (/ rebox-default-style 100) 100))))
(cond ((and (numberp flag) (not (zerop (% (/ flag 10) 10))))
(setq quality (* (% (/ flag 10) 10) 10)))
((not (zerop (% (/ rebox-default-style 10) 10)))
(setq quality (* (% (/ rebox-default-style 10) 10) 10)))
((zerop quality)
(setq quality REBOX_QUALITY_ROUNDED_TWO)))
(cond ((and (numberp flag) (not (zerop (% flag 10))))
(setq type (% flag 10)))
((not (zerop (% rebox-default-style 10)))
(setq type (% rebox-default-style 10)))
((zerop type)
(setq type 1)))
;; Possibly refill, then reconstruct the comment box.
(let ((indent-tabs-mode nil))
(rebox-reconstruct (not (and flag (listp flag)))
(rebox-left-margin)
language quality type))
;; Retabify to the left only (adapted from tabify.el).
(if indent-tabs-mode
(progn
(goto-char (point-min))
(while (re-search-forward "^[ \t][ \t]+" nil t)
(let ((column (current-column)))
(delete-region (match-beginning 0) (point))
(indent-to column)))))
;; Restore the point position.
(goto-char (marker-position marked-point))
;; Remove all intermediate boundaries from the undo list.
(if (not (eq buffer-undo-list undo-list))
(let ((cursor buffer-undo-list))
(while (not (eq (cdr cursor) undo-list))
(if (car (cdr cursor))
(setq cursor (cdr cursor))
(rplacd cursor (cdr (cdr cursor)))))))))
;;; Set or reset the Taarna team's own way for a C style. You do not
;;; really want to know about this.
(defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.")
(defun taarna-mode ()
(interactive)
(if c-mode-taarna-style
(progn
(setq c-mode-taarna-style nil)
(setq c-indent-level 2)
(setq c-continued-statement-offset 2)
(setq c-brace-offset 0)
(setq c-argdecl-indent 5)
(setq c-label-offset -2)
(setq c-tab-always-indent t)
(setq rebox-default-style REBOX_QUALITY_ROUNDED_TWO)
(message "C mode: GNU style"))
(setq c-mode-taarna-style t)
(setq c-indent-level 4)
(setq c-continued-statement-offset 4)
(setq c-brace-offset -4)
(setq c-argdecl-indent 4)
(setq c-label-offset -4)
(setq c-tab-always-indent t)
(setq rebox-default-style
(+ REBOX_QUALITY_SIMPLE_ONE REBOX_TYPE_HALF_SINGLE))
(message "C mode: Taarna style")))
;;; Rebox the current region.
(defun rebox-region (flag)
(interactive "P")
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
(if (rebox-validate-flag flag)
(save-restriction
(narrow-to-region (region-beginning) (region-end))
(rebox-engine flag))))
;;; Rebox the surrounding comment.
(defun rebox-comment (flag)
(interactive "P")
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
(if (rebox-validate-flag flag)
(save-restriction
(rebox-find-and-narrow)
(rebox-engine flag))))

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

@@ -65,9 +65,9 @@ XLIST=exclude_files
SLEEP_TIME=15
# Script to be run when it's time to insert a new tape in for the next
# volume. Administrators may want to tailor this script for their site.
# volume. Administrators may want to tailor this script for their site.
# If this variable isn't set, tar will use some default behavior which is
# probably defined in the manual.
# probably defined in the manual.
#DUMP_REMIND_SCRIPT='rsh apple-gunkies /home/gd2/dump/dump-remind'
# Message to display on the terminal while waiting for dump time. Usually
@@ -75,26 +75,26 @@ SLEEP_TIME=15
# entertaining than this. The awk script here saves some redundant
# repetition, but is not really all that desirable.
SLEEP_MESSAGE="`awk '
BEGIN {
BEGIN {
for (i = 0; i < 30; i++)
print \" \" \
\"D O N O T T O U C H T H I S T E R M I N A L !!!!!\"
}' /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

@@ -2,14 +2,30 @@
# This file is included in the GNU tar distribution as an example. It is
# not used by default unless the proper line is uncommented in backup-specs.
# System administrators will probably want to customize this and
# backup-specs for their site.
# backup-specs for their site.
#
# 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.
#
# 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,9 +41,9 @@ 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
# just test accounts.
# 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 \
| sed -ne '
@@ -69,8 +85,8 @@ Cc: ${ADMINISTRATOR}
Subject: Backup needs new tape for volume ${TAR_VOLUME}
Reply-To: ${ADMINISTRATOR}
This is an automated report from the backup script running on
`hostname`.
This is an automated report from the backup script running on
`hostname`.
Volume ${TAR_VOLUME} of the backup needs to be put in the tape drive.
Usually whoever prepared the backup leaves labeled tapes on top of the
@@ -92,8 +108,8 @@ Cc: ${ADMINISTRATOR}
Subject: Volume ${TAR_VOLUME} for backup has been added
Reply-To: ${ADMINISTRATOR}
This is an automated report from the backup script running on
`hostname`.
This is an automated report from the backup script running on
`hostname`.
The backup has been continued, so for now no further attention is required.
__EOF__

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
@@ -211,14 +482,17 @@ sub write_incr_db ($$) {
sub write_incr_db_0 ($$) {
my $info = shift;
my $file = shift;
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";
}
}
@@ -226,19 +500,22 @@ sub write_incr_db_0 ($$) {
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";
}
}
@@ -246,22 +523,22 @@ sub write_incr_db_1 ($$) {
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() {
@@ -35,8 +52,7 @@ do
fi
if [ "$T" = "M" ]; then
SKIP=$(($SKIP + 1))
fi
fi
fi
dd skip=$SKIP if="$f"
dd skip=$SKIP if="$f"
done

View File

@@ -1,27 +1,30 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
Copyright 2006-2007, 2010, 2013-2014 Free Software Foundation, Inc.
Written by Sergey Poznyakoff
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/>.
Written by Sergey Poznyakoff */
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -38,7 +41,7 @@
struct sp_array
{
off_t offset;
size_t numbytes;
off_t numbytes;
};
char *progname;
@@ -128,12 +131,12 @@ get_var (FILE *fp, char **name, char **value)
static char *buffer;
static size_t bufsize = OFF_T_STRSIZE_BOUND;
char *p, *q;
buffer = emalloc (bufsize);
do
{
size_t len, s;
if (!fgets (buffer, bufsize, fp))
return 0;
len = strlen (buffer);
@@ -162,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;
@@ -185,14 +188,14 @@ read_xheader (char *name)
if (verbose)
printf ("Reading extended header file\n");
while (get_var (fp, &kw, &val))
{
if (verbose)
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)
@@ -225,7 +228,7 @@ read_xheader (char *name)
}
else if (strcmp (kw, "numbytes") == 0)
{
sparse_map[i++].numbytes = string_to_size (val, NULL);
sparse_map[i++].numbytes = string_to_off (val, NULL);
}
else if (strcmp (kw, "map") == 0)
{
@@ -233,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_size (val+1, &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
@@ -250,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)
@@ -266,7 +269,7 @@ read_map (FILE *ifp)
if (verbose)
printf ("Reading v.1.0 sparse map\n");
get_line (nbuf, sizeof nbuf, ifp);
sparse_map_size = string_to_size (nbuf, NULL);
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
@@ -276,31 +279,34 @@ read_map (FILE *ifp)
get_line (nbuf, sizeof nbuf, ifp);
sparse_map[i].offset = string_to_off (nbuf, NULL);
get_line (nbuf, sizeof nbuf, ifp);
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
sparse_map[i].numbytes = string_to_off (nbuf, NULL);
}
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
SEEK_SET);
}
fseeko (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
SEEK_SET);
}
void
expand_sparse (FILE *sfp, int ofd)
{
size_t i;
size_t maxbytes = 0;
off_t max_numbytes = 0;
size_t maxbytes;
char *buffer;
for (i = 0; i < sparse_map_size; i++)
if (maxbytes < sparse_map[i].numbytes)
maxbytes = sparse_map[i].numbytes;
if (max_numbytes < sparse_map[i].numbytes)
max_numbytes = sparse_map[i].numbytes;
maxbytes = max_numbytes < SIZE_MAX ? max_numbytes : SIZE_MAX;
for (buffer = malloc (maxbytes); !buffer; maxbytes /= 2)
if (maxbytes == 0)
die (1, "not enough memory");
for (i = 0; i < sparse_map_size; i++)
{
size_t size = sparse_map[i].numbytes;
off_t size = sparse_map[i].numbytes;
if (size == 0)
ftruncate (ofd, sparse_map[i].offset);
@@ -341,13 +347,13 @@ guess_outname (char *name)
{
char *p;
char *s;
if (name[0] == '.' && name[1] == '/')
name += 2;
p = name + strlen (name) - 1;
s = NULL;
for (; p > name && *p != '/'; p--)
;
if (*p == '/')
@@ -357,7 +363,7 @@ guess_outname (char *name)
for (p--; p > name && *p != '/'; p--)
;
}
if (*p != '/')
{
if (s)
@@ -388,7 +394,7 @@ main (int argc, char **argv)
FILE *ifp;
struct stat st;
int ofd;
progname = argv[0];
while ((c = getopt (argc, argv, "hnvx:")) != EOF)
{
@@ -407,7 +413,7 @@ main (int argc, char **argv)
case 'v':
verbose++;
break;
default:
exit (1);
}
@@ -428,30 +434,30 @@ main (int argc, char **argv)
if (stat (inname, &st))
die (1, "cannot stat %s (%d)", inname, errno);
ifp = fopen (inname, "r");
if (ifp == NULL)
die (1, "cannot open file %s (%d)", inname, errno);
if (!xheader_file || version_major == 1)
read_map (ifp);
if (!outname)
guess_outname (inname);
ofd = open (outname, O_RDWR|O_CREAT|O_TRUNC, st.st_mode);
if (ofd == -1)
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)
{
printf ("Finished dry run\n");
return 0;
}
expand_sparse (ifp, ofd);
fclose (ifp);
@@ -459,7 +465,7 @@ main (int argc, char **argv)
if (verbose)
printf ("Done\n");
if (outsize)
{
if (stat (outname, &st))
@@ -467,7 +473,6 @@ main (int argc, char **argv)
if (st.st_size != outsize)
die (1, "expanded file has wrong size");
}
return 0;
}

View File

@@ -1,32 +1,34 @@
# 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\
compare.c\
create.c\
delete.c\
exit.c\
exclist.c\
extract.c\
xheader.c\
incremen.c\
@@ -38,11 +40,19 @@ tar_SOURCES = \
system.c\
tar.c\
transform.c\
unlink.c\
update.c\
utf8.c
utf8.c\
warning.c\
xattrs.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/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)
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)
if TAR_LIB_ATTR
tar_LDADD += -lattr
endif

View File

@@ -1,973 +0,0 @@
# Makefile.in generated by automake 1.10.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Makefile for GNU tar sources.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007, 2009 Free Software Foundation, Inc.
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = tar$(EXEEXT)
subdir = src
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in ansi2knr.1 ansi2knr.c
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
$(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/argmatch.m4 \
$(top_srcdir)/m4/argp.m4 $(top_srcdir)/m4/backupfile.m4 \
$(top_srcdir)/m4/bison.m4 $(top_srcdir)/m4/btowc.m4 \
$(top_srcdir)/m4/canonicalize-lgpl.m4 \
$(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/chown.m4 \
$(top_srcdir)/m4/clock_time.m4 \
$(top_srcdir)/m4/close-stream.m4 $(top_srcdir)/m4/close.m4 \
$(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \
$(top_srcdir)/m4/d-ino.m4 $(top_srcdir)/m4/dirent_h.m4 \
$(top_srcdir)/m4/dirfd.m4 $(top_srcdir)/m4/dirname.m4 \
$(top_srcdir)/m4/dos.m4 $(top_srcdir)/m4/double-slash-root.m4 \
$(top_srcdir)/m4/dup2.m4 $(top_srcdir)/m4/eealloc.m4 \
$(top_srcdir)/m4/environ.m4 $(top_srcdir)/m4/errno_h.m4 \
$(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exclude.m4 \
$(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \
$(top_srcdir)/m4/fchdir.m4 $(top_srcdir)/m4/fclose.m4 \
$(top_srcdir)/m4/fcntl-safer.m4 $(top_srcdir)/m4/fcntl_h.m4 \
$(top_srcdir)/m4/fileblocks.m4 $(top_srcdir)/m4/float_h.m4 \
$(top_srcdir)/m4/fnmatch.m4 $(top_srcdir)/m4/fpending.m4 \
$(top_srcdir)/m4/fseeko.m4 $(top_srcdir)/m4/ftruncate.m4 \
$(top_srcdir)/m4/getcwd-abort-bug.m4 \
$(top_srcdir)/m4/getcwd-path-max.m4 $(top_srcdir)/m4/getcwd.m4 \
$(top_srcdir)/m4/getdate.m4 $(top_srcdir)/m4/getdelim.m4 \
$(top_srcdir)/m4/getline.m4 $(top_srcdir)/m4/getopt.m4 \
$(top_srcdir)/m4/getpagesize.m4 $(top_srcdir)/m4/gettext.m4 \
$(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \
$(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/hash.m4 \
$(top_srcdir)/m4/human.m4 $(top_srcdir)/m4/iconv.m4 \
$(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inline.m4 \
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \
$(top_srcdir)/m4/inttostr.m4 $(top_srcdir)/m4/inttypes-pri.m4 \
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
$(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/lib-ld.m4 \
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
$(top_srcdir)/m4/localcharset.m4 $(top_srcdir)/m4/locale-fr.m4 \
$(top_srcdir)/m4/locale-ja.m4 $(top_srcdir)/m4/locale-zh.m4 \
$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/lseek.m4 \
$(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/malloc.m4 \
$(top_srcdir)/m4/malloca.m4 $(top_srcdir)/m4/mbchar.m4 \
$(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \
$(top_srcdir)/m4/mbscasecmp.m4 $(top_srcdir)/m4/mbsinit.m4 \
$(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/mempcpy.m4 \
$(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mkdtemp.m4 \
$(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/modechange.m4 \
$(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/open.m4 $(top_srcdir)/m4/openat.m4 \
$(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/paxutils.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/quote.m4 \
$(top_srcdir)/m4/quotearg.m4 $(top_srcdir)/m4/rawmemchr.m4 \
$(top_srcdir)/m4/readlink.m4 $(top_srcdir)/m4/realloc.m4 \
$(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/rmt.m4 \
$(top_srcdir)/m4/rpmatch.m4 $(top_srcdir)/m4/rtapelib.m4 \
$(top_srcdir)/m4/safe-read.m4 $(top_srcdir)/m4/safe-write.m4 \
$(top_srcdir)/m4/save-cwd.m4 $(top_srcdir)/m4/savedir.m4 \
$(top_srcdir)/m4/setenv.m4 $(top_srcdir)/m4/size_max.m4 \
$(top_srcdir)/m4/sleep.m4 $(top_srcdir)/m4/snprintf.m4 \
$(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \
$(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \
$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \
$(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strcase.m4 \
$(top_srcdir)/m4/strchrnul.m4 $(top_srcdir)/m4/strdup.m4 \
$(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/string_h.m4 \
$(top_srcdir)/m4/strings_h.m4 $(top_srcdir)/m4/strndup.m4 \
$(top_srcdir)/m4/strnlen.m4 $(top_srcdir)/m4/strtoimax.m4 \
$(top_srcdir)/m4/strtol.m4 $(top_srcdir)/m4/strtoll.m4 \
$(top_srcdir)/m4/strtoul.m4 $(top_srcdir)/m4/strtoull.m4 \
$(top_srcdir)/m4/strtoumax.m4 $(top_srcdir)/m4/sys_stat_h.m4 \
$(top_srcdir)/m4/sys_time_h.m4 $(top_srcdir)/m4/sysexits.m4 \
$(top_srcdir)/m4/system.m4 $(top_srcdir)/m4/tempname.m4 \
$(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \
$(top_srcdir)/m4/timespec.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \
$(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \
$(top_srcdir)/m4/unlinkdir.m4 $(top_srcdir)/m4/unlocked-io.m4 \
$(top_srcdir)/m4/utimbuf.m4 $(top_srcdir)/m4/utime.m4 \
$(top_srcdir)/m4/utimens.m4 $(top_srcdir)/m4/utimes-null.m4 \
$(top_srcdir)/m4/utimes.m4 $(top_srcdir)/m4/vasnprintf.m4 \
$(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/wchar.m4 \
$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wcrtomb.m4 \
$(top_srcdir)/m4/wctype.m4 $(top_srcdir)/m4/wcwidth.m4 \
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/write.m4 \
$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xgetcwd.m4 \
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/xstrndup.m4 \
$(top_srcdir)/m4/xstrtol.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
am_tar_OBJECTS = buffer.$(OBJEXT) checkpoint.$(OBJEXT) \
compare.$(OBJEXT) create.$(OBJEXT) delete.$(OBJEXT) \
extract.$(OBJEXT) xheader.$(OBJEXT) incremen.$(OBJEXT) \
list.$(OBJEXT) misc.$(OBJEXT) names.$(OBJEXT) sparse.$(OBJEXT) \
suffix.$(OBJEXT) system.$(OBJEXT) tar.$(OBJEXT) \
transform.$(OBJEXT) update.$(OBJEXT) utf8.$(OBJEXT)
tar_OBJECTS = $(am_tar_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = ../lib/libtar.a ../gnu/libgnu.a \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
tar_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(tar_SOURCES)
DIST_SOURCES = $(tar_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
ALLOCA_H = @ALLOCA_H@
AMTAR = @AMTAR@
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOM4TE = @AUTOM4TE@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BACKUP_LIBEXEC_SCRIPTS = @BACKUP_LIBEXEC_SCRIPTS@
BACKUP_SBIN_SCRIPTS = @BACKUP_SBIN_SCRIPTS@
BACKUP_SED_COND = @BACKUP_SED_COND@
BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@
BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@
BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFAULT_ARCHIVE = @DEFAULT_ARCHIVE@
DEFAULT_ARCHIVE_FORMAT = @DEFAULT_ARCHIVE_FORMAT@
DEFAULT_BLOCKING = @DEFAULT_BLOCKING@
DEFAULT_QUOTING_STYLE = @DEFAULT_QUOTING_STYLE@
DEFAULT_RMT_COMMAND = @DEFAULT_RMT_COMMAND@
DEFAULT_RMT_DIR = @DEFAULT_RMT_DIR@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIRENT_H = @DIRENT_H@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
EMULTIHOP_VALUE = @EMULTIHOP_VALUE@
ENOLINK_HIDDEN = @ENOLINK_HIDDEN@
ENOLINK_VALUE = @ENOLINK_VALUE@
EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
ERRNO_H = @ERRNO_H@
EXEEXT = @EXEEXT@
FCNTL_H = @FCNTL_H@
FLOAT_H = @FLOAT_H@
FNMATCH_H = @FNMATCH_H@
GETOPT_H = @GETOPT_H@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
GNULIB_ATOLL = @GNULIB_ATOLL@
GNULIB_BTOWC = @GNULIB_BTOWC@
GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
GNULIB_CHOWN = @GNULIB_CHOWN@
GNULIB_CLOSE = @GNULIB_CLOSE@
GNULIB_DIRFD = @GNULIB_DIRFD@
GNULIB_DPRINTF = @GNULIB_DPRINTF@
GNULIB_DUP2 = @GNULIB_DUP2@
GNULIB_ENVIRON = @GNULIB_ENVIRON@
GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
GNULIB_FCHDIR = @GNULIB_FCHDIR@
GNULIB_FCLOSE = @GNULIB_FCLOSE@
GNULIB_FFLUSH = @GNULIB_FFLUSH@
GNULIB_FOPEN = @GNULIB_FOPEN@
GNULIB_FPRINTF = @GNULIB_FPRINTF@
GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
GNULIB_FPUTC = @GNULIB_FPUTC@
GNULIB_FPUTS = @GNULIB_FPUTS@
GNULIB_FREOPEN = @GNULIB_FREOPEN@
GNULIB_FSEEK = @GNULIB_FSEEK@
GNULIB_FSEEKO = @GNULIB_FSEEKO@
GNULIB_FSYNC = @GNULIB_FSYNC@
GNULIB_FTELL = @GNULIB_FTELL@
GNULIB_FTELLO = @GNULIB_FTELLO@
GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
GNULIB_FWRITE = @GNULIB_FWRITE@
GNULIB_GETCWD = @GNULIB_GETCWD@
GNULIB_GETDELIM = @GNULIB_GETDELIM@
GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
GNULIB_GETLINE = @GNULIB_GETLINE@
GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
GNULIB_IMAXABS = @GNULIB_IMAXABS@
GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
GNULIB_LCHMOD = @GNULIB_LCHMOD@
GNULIB_LCHOWN = @GNULIB_LCHOWN@
GNULIB_LINK = @GNULIB_LINK@
GNULIB_LSEEK = @GNULIB_LSEEK@
GNULIB_LSTAT = @GNULIB_LSTAT@
GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
GNULIB_MBRLEN = @GNULIB_MBRLEN@
GNULIB_MBRTOWC = @GNULIB_MBRTOWC@
GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
GNULIB_MBSCHR = @GNULIB_MBSCHR@
GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
GNULIB_MBSINIT = @GNULIB_MBSINIT@
GNULIB_MBSLEN = @GNULIB_MBSLEN@
GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@
GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@
GNULIB_MBSSEP = @GNULIB_MBSSEP@
GNULIB_MBSSPN = @GNULIB_MBSSPN@
GNULIB_MBSSTR = @GNULIB_MBSSTR@
GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
GNULIB_MEMMEM = @GNULIB_MEMMEM@
GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
GNULIB_OPEN = @GNULIB_OPEN@
GNULIB_PERROR = @GNULIB_PERROR@
GNULIB_PRINTF = @GNULIB_PRINTF@
GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
GNULIB_PUTC = @GNULIB_PUTC@
GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
GNULIB_PUTENV = @GNULIB_PUTENV@
GNULIB_PUTS = @GNULIB_PUTS@
GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
GNULIB_READLINK = @GNULIB_READLINK@
GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
GNULIB_RPMATCH = @GNULIB_RPMATCH@
GNULIB_SCANDIR = @GNULIB_SCANDIR@
GNULIB_SETENV = @GNULIB_SETENV@
GNULIB_SLEEP = @GNULIB_SLEEP@
GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
GNULIB_STPCPY = @GNULIB_STPCPY@
GNULIB_STPNCPY = @GNULIB_STPNCPY@
GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
GNULIB_STRDUP = @GNULIB_STRDUP@
GNULIB_STRERROR = @GNULIB_STRERROR@
GNULIB_STRNDUP = @GNULIB_STRNDUP@
GNULIB_STRNLEN = @GNULIB_STRNLEN@
GNULIB_STRPBRK = @GNULIB_STRPBRK@
GNULIB_STRSEP = @GNULIB_STRSEP@
GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
GNULIB_STRSTR = @GNULIB_STRSTR@
GNULIB_STRTOD = @GNULIB_STRTOD@
GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
GNULIB_STRTOLL = @GNULIB_STRTOLL@
GNULIB_STRTOULL = @GNULIB_STRTOULL@
GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
GNULIB_UNSETENV = @GNULIB_UNSETENV@
GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
GNULIB_VPRINTF = @GNULIB_VPRINTF@
GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
GNULIB_WCRTOMB = @GNULIB_WCRTOMB@
GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@
GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@
GNULIB_WCTOB = @GNULIB_WCTOB@
GNULIB_WCWIDTH = @GNULIB_WCWIDTH@
GNULIB_WRITE = @GNULIB_WRITE@
GREP = @GREP@
HAVE_ALPHASORT = @HAVE_ALPHASORT@
HAVE_ATOLL = @HAVE_ATOLL@
HAVE_BTOWC = @HAVE_BTOWC@
HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@
HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@
HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@
HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@
HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
HAVE_DECL_STRERROR = @HAVE_DECL_STRERROR@
HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@
HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@
HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@
HAVE_DPRINTF = @HAVE_DPRINTF@
HAVE_DUP2 = @HAVE_DUP2@
HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
HAVE_FSEEKO = @HAVE_FSEEKO@
HAVE_FSYNC = @HAVE_FSYNC@
HAVE_FTELLO = @HAVE_FTELLO@
HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
HAVE_GETDOMAINNAME = @HAVE_GETDOMAINNAME@
HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
HAVE_GETUSERSHELL = @HAVE_GETUSERSHELL@
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
HAVE_ISWCNTRL = @HAVE_ISWCNTRL@
HAVE_LCHMOD = @HAVE_LCHMOD@
HAVE_LINK = @HAVE_LINK@
HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
HAVE_LSTAT = @HAVE_LSTAT@
HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@
HAVE_MBRLEN = @HAVE_MBRLEN@
HAVE_MBRTOWC = @HAVE_MBRTOWC@
HAVE_MBSINIT = @HAVE_MBSINIT@
HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@
HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
HAVE_OS_H = @HAVE_OS_H@
HAVE_RANDOM_H = @HAVE_RANDOM_H@
HAVE_RANDOM_R = @HAVE_RANDOM_R@
HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@
HAVE_READLINK = @HAVE_READLINK@
HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@
HAVE_RPMATCH = @HAVE_RPMATCH@
HAVE_SCANDIR = @HAVE_SCANDIR@
HAVE_SETENV = @HAVE_SETENV@
HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
HAVE_SLEEP = @HAVE_SLEEP@
HAVE_STDINT_H = @HAVE_STDINT_H@
HAVE_STPCPY = @HAVE_STPCPY@
HAVE_STPNCPY = @HAVE_STPNCPY@
HAVE_STRCASECMP = @HAVE_STRCASECMP@
HAVE_STRCASESTR = @HAVE_STRCASESTR@
HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
HAVE_STRNDUP = @HAVE_STRNDUP@
HAVE_STRPBRK = @HAVE_STRPBRK@
HAVE_STRSEP = @HAVE_STRSEP@
HAVE_STRTOD = @HAVE_STRTOD@
HAVE_STRTOLL = @HAVE_STRTOLL@
HAVE_STRTOULL = @HAVE_STRTOULL@
HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@
HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
HAVE_SYSEXITS_H = @HAVE_SYSEXITS_H@
HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
HAVE_UNISTD_H = @HAVE_UNISTD_H@
HAVE_UNSETENV = @HAVE_UNSETENV@
HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
HAVE_VASPRINTF = @HAVE_VASPRINTF@
HAVE_VDPRINTF = @HAVE_VDPRINTF@
HAVE_WCHAR_H = @HAVE_WCHAR_H@
HAVE_WCRTOMB = @HAVE_WCRTOMB@
HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@
HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@
HAVE_WCTYPE_H = @HAVE_WCTYPE_H@
HAVE_WINT_T = @HAVE_WINT_T@
HAVE__BOOL = @HAVE__BOOL@
INCLUDE_NEXT = @INCLUDE_NEXT@
INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@
INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
INTTYPES_H = @INTTYPES_H@
LDFLAGS = @LDFLAGS@
LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
LIB_CLOSE = @LIB_CLOSE@
LIB_SETSOCKOPT = @LIB_SETSOCKOPT@
LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@
LOCALE_FR = @LOCALE_FR@
LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
LOCALE_JA = @LOCALE_JA@
LOCALE_ZH_CN = @LOCALE_ZH_CN@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
NEXT_DIRENT_H = @NEXT_DIRENT_H@
NEXT_ERRNO_H = @NEXT_ERRNO_H@
NEXT_FCNTL_H = @NEXT_FCNTL_H@
NEXT_FLOAT_H = @NEXT_FLOAT_H@
NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
NEXT_STDARG_H = @NEXT_STDARG_H@
NEXT_STDINT_H = @NEXT_STDINT_H@
NEXT_STDIO_H = @NEXT_STDIO_H@
NEXT_STDLIB_H = @NEXT_STDLIB_H@
NEXT_STRINGS_H = @NEXT_STRINGS_H@
NEXT_STRING_H = @NEXT_STRING_H@
NEXT_SYSEXITS_H = @NEXT_SYSEXITS_H@
NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@
NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@
NEXT_TIME_H = @NEXT_TIME_H@
NEXT_UNISTD_H = @NEXT_UNISTD_H@
NEXT_WCHAR_H = @NEXT_WCHAR_H@
NEXT_WCTYPE_H = @NEXT_WCTYPE_H@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POSUB = @POSUB@
PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
PRIPTR_PREFIX = @PRIPTR_PREFIX@
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
PU_RMT_PROG = @PU_RMT_PROG@
RANLIB = @RANLIB@
REPLACE_BTOWC = @REPLACE_BTOWC@
REPLACE_CHOWN = @REPLACE_CHOWN@
REPLACE_CLOSE = @REPLACE_CLOSE@
REPLACE_DPRINTF = @REPLACE_DPRINTF@
REPLACE_FCHDIR = @REPLACE_FCHDIR@
REPLACE_FCLOSE = @REPLACE_FCLOSE@
REPLACE_FFLUSH = @REPLACE_FFLUSH@
REPLACE_FOPEN = @REPLACE_FOPEN@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
REPLACE_FREOPEN = @REPLACE_FREOPEN@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
REPLACE_FTELL = @REPLACE_FTELL@
REPLACE_FTELLO = @REPLACE_FTELLO@
REPLACE_GETCWD = @REPLACE_GETCWD@
REPLACE_GETLINE = @REPLACE_GETLINE@
REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@
REPLACE_LCHOWN = @REPLACE_LCHOWN@
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
REPLACE_LSEEK = @REPLACE_LSEEK@
REPLACE_LSTAT = @REPLACE_LSTAT@
REPLACE_MBRLEN = @REPLACE_MBRLEN@
REPLACE_MBRTOWC = @REPLACE_MBRTOWC@
REPLACE_MBSINIT = @REPLACE_MBSINIT@
REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@
REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@
REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@
REPLACE_MEMMEM = @REPLACE_MEMMEM@
REPLACE_MKDIR = @REPLACE_MKDIR@
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@
REPLACE_OPEN = @REPLACE_OPEN@
REPLACE_PERROR = @REPLACE_PERROR@
REPLACE_PRINTF = @REPLACE_PRINTF@
REPLACE_PUTENV = @REPLACE_PUTENV@
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
REPLACE_SPRINTF = @REPLACE_SPRINTF@
REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
REPLACE_STRDUP = @REPLACE_STRDUP@
REPLACE_STRERROR = @REPLACE_STRERROR@
REPLACE_STRPTIME = @REPLACE_STRPTIME@
REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
REPLACE_STRSTR = @REPLACE_STRSTR@
REPLACE_STRTOD = @REPLACE_STRTOD@
REPLACE_TIMEGM = @REPLACE_TIMEGM@
REPLACE_VASPRINTF = @REPLACE_VASPRINTF@
REPLACE_VDPRINTF = @REPLACE_VDPRINTF@
REPLACE_VFPRINTF = @REPLACE_VFPRINTF@
REPLACE_VPRINTF = @REPLACE_VPRINTF@
REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
REPLACE_WCRTOMB = @REPLACE_WCRTOMB@
REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@
REPLACE_WCTOB = @REPLACE_WCTOB@
REPLACE_WCWIDTH = @REPLACE_WCWIDTH@
REPLACE_WRITE = @REPLACE_WRITE@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
STDARG_H = @STDARG_H@
STDBOOL_H = @STDBOOL_H@
STDINT_H = @STDINT_H@
STRIP = @STRIP@
SYSEXITS_H = @SYSEXITS_H@
SYS_STAT_H = @SYS_STAT_H@
SYS_TIME_H = @SYS_TIME_H@
SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
VOID_UNSETENV = @VOID_UNSETENV@
WCHAR_H = @WCHAR_H@
WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
WCTYPE_H = @WCTYPE_H@
WINT_T_SUFFIX = @WINT_T_SUFFIX@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
gltests_LIBOBJS = @gltests_LIBOBJS@
gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_HEADERS = arith.h common.h tar.h
tar_SOURCES = \
buffer.c\
checkpoint.c\
compare.c\
create.c\
delete.c\
extract.c\
xheader.c\
incremen.c\
list.c\
misc.c\
names.c\
sparse.c\
suffix.c\
system.c\
tar.c\
transform.c\
update.c\
utf8.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnits src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
rm -f "$(DESTDIR)$(bindir)/$$f"; \
done
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
installcheck-binPROGRAMS: $(bin_PROGRAMS)
bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
*" $$p "* | *" $(srcdir)/$$p "*) continue;; \
esac; \
f=`echo "$$p" | \
sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
for opt in --help --version; do \
if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \
2>c$${pid}_.err </dev/null \
&& test -n "`cat c$${pid}_.out`" \
&& test -z "`cat c$${pid}_.err`"; then :; \
else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
done; \
done; rm -f c$${pid}_.???; exit $$bad
tar$(EXEEXT): $(tar_OBJECTS) $(tar_DEPENDENCIES)
@rm -f tar$(EXEEXT)
$(LINK) $(tar_OBJECTS) $(tar_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkpoint.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compare.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sparse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suffix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xheader.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(bindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-exec-am: install-binPROGRAMS
install-html: install-html-am
install-info: install-info-am
install-man:
install-pdf: install-pdf-am
install-ps: install-ps-am
installcheck-am: installcheck-binPROGRAMS
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-binPROGRAMS \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installcheck-binPROGRAMS \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -1,42 +0,0 @@
.\" $Id: ansi2knr.1 $
.TH ANSI2KNR 1 "9 September 1998" \" -*- nroff -*-
.SH NAME
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
.SH SYNOPSIS
\fBansi2knr\fR [\fB--filename\fR \fIfilename\fR] [\fIinput_file\fR [\fIoutput_file\fR]]
.br
.SH DESCRIPTION
\fB--filename\fR provides the file name for the #line directive in the output,
overriding \fIinput_file\fR (if present).
.sp
If no \fIinput_file\fR is supplied, input is read from stdin.
.sp
If no \fIoutput_file\fR is supplied, output goes to stdout.
.sp
There are no error messages.
.sp
\fBansi2knr\fR
recognizes function definitions by seeing a non-keyword identifier at the left
margin, followed by a left parenthesis, with a right parenthesis as the last
character on the line, and with a left brace as the first token on the
following line (ignoring possible intervening comments). It will recognize a
multi-line header provided that no intervening line ends with a left or right
brace or a semicolon. These algorithms ignore whitespace and comments, except
that the function name must be the first thing on the line.
.sp
The following constructs will confuse it:
.br
- Any other construct that starts at the left margin and follows the
above syntax (such as a macro or function call).
.br
- Some macros that tinker with the syntax of the function header.
.sp
The --varargs switch is obsolete, and is recognized only for
backwards compatibility. The present version of
\fBansi2knr\fR
will always attempt to convert a ... argument to va_alist and va_dcl.
.SH AUTHOR
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
continues to maintain the current version; most of the code in the current
version is his work. ansi2knr also includes contributions by Francois
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.

View File

@@ -1,720 +0,0 @@
/* Copyright (C) 1989, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved. */
/*$Id: ansi2knr.c $*/
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
/*
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone for the
consequences of using it or for whether it serves any particular purpose or
works at all, unless he says so in writing. Refer to the GNU General Public
License (the "GPL") for full details.
Everyone is granted permission to copy, modify and redistribute ansi2knr,
but only under the conditions described in the GPL. A copy of this license
is supposed to have been given to you along with ansi2knr so you can know
your rights and responsibilities. It should be in a file named COPYLEFT,
or, if there is no file named COPYLEFT, a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies.
We explicitly state here what we believe is already implied by the GPL: if
the ansi2knr program is distributed as a separate set of sources and a
separate executable file which are aggregated on a storage medium together
with another program, this in itself does not bring the other program under
the GPL, nor does the mere fact that such a program or the procedures for
constructing it invoke the ansi2knr executable bring any other part of the
program under the GPL.
*/
/*
* Usage:
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
* --filename provides the file name for the #line directive in the output,
* overriding input_file (if present).
* If no input_file is supplied, input is read from stdin.
* If no output_file is supplied, output goes to stdout.
* There are no error messages.
*
* ansi2knr recognizes function definitions by seeing a non-keyword
* identifier at the left margin, followed by a left parenthesis, with a
* right parenthesis as the last character on the line, and with a left
* brace as the first token on the following line (ignoring possible
* intervening comments and/or preprocessor directives), except that a line
* consisting of only
* identifier1(identifier2)
* will not be considered a function definition unless identifier2 is
* the word "void", and a line consisting of
* identifier1(identifier2, <<arbitrary>>)
* will not be considered a function definition.
* ansi2knr will recognize a multi-line header provided that no intervening
* line ends with a left or right brace or a semicolon. These algorithms
* ignore whitespace, comments, and preprocessor directives, except that
* the function name must be the first thing on the line. The following
* constructs will confuse it:
* - Any other construct that starts at the left margin and
* follows the above syntax (such as a macro or function call).
* - Some macros that tinker with the syntax of function headers.
*/
/*
* The original and principal author of ansi2knr is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history
* that follows (in reverse chronological order):
lpd 1999-08-17 added code to allow preprocessor directives
wherever comments are allowed
lpd 1999-04-12 added minor fixes from Pavel Roskin
<pavel_roskin@geocities.com> for clean compilation with
gcc -W -Wall
lpd 1999-03-22 added hack to recognize lines consisting of
identifier1(identifier2, xxx) as *not* being procedures
lpd 1999-02-03 made indentation of preprocessor commands consistent
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
endless loop; quoted strings within an argument list
confused the parser
lpd 1999-01-24 added a check for write errors on the output,
suggested by Jim Meyering <meyering@ascend.com>
lpd 1998-11-09 added further hack to recognize identifier(void)
as being a procedure
lpd 1998-10-23 added hack to recognize lines consisting of
identifier1(identifier2) as *not* being procedures
lpd 1997-12-08 made input_file optional; only closes input and/or
output file if not stdin or stdout respectively; prints
usage message on stderr rather than stdout; adds
--filename switch (changes suggested by
<ceder@lysator.liu.se>)
lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
compilers that don't understand void, as suggested by
Tom Lane
lpd 1996-01-15 changed to require that the first non-comment token
on the line following a function header be a left brace,
to reduce sensitivity to macros, as suggested by Tom Lane
<tgl@sss.pgh.pa.us>
lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
undefined preprocessor symbols as 0; changed all #ifdefs
for configuration symbols to #ifs
lpd 1995-04-05 changed copyright notice to make it clear that
including ansi2knr in a program does not bring the entire
program under the GPL
lpd 1994-12-18 added conditionals for systems where ctype macros
don't handle 8-bit characters properly, suggested by
Francois Pinard <pinard@iro.umontreal.ca>;
removed --varargs switch (this is now the default)
lpd 1994-10-10 removed CONFIG_BROKETS conditional
lpd 1994-07-16 added some conditionals to help GNU `configure',
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
properly erase prototype args in function parameters,
contributed by Jim Avera <jima@netcom.com>;
correct error in writeblanks (it shouldn't erase EOLs)
lpd 1989-xx-xx original version
*/
/* Most of the conditionals here are to make ansi2knr work with */
/* or without the GNU configure machinery. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#if HAVE_CONFIG_H
/*
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
This will define HAVE_CONFIG_H and so, activate the following lines.
*/
# if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
#else /* not HAVE_CONFIG_H */
/* Otherwise do it the hard way */
# ifdef BSD
# include <strings.h>
# else
# ifdef VMS
extern int strlen(), strncmp();
# else
# include <string.h>
# endif
# endif
#endif /* not HAVE_CONFIG_H */
#if STDC_HEADERS
# include <stdlib.h>
#else
/*
malloc and free should be declared in stdlib.h,
but if you've got a K&R compiler, they probably aren't.
*/
# ifdef MSDOS
# include <malloc.h>
# else
# ifdef VMS
extern char *malloc();
extern void free();
# else
extern char *malloc();
extern int free();
# endif
# endif
#endif
/* Define NULL (for *very* old compilers). */
#ifndef NULL
# define NULL (0)
#endif
/*
* The ctype macros don't always handle 8-bit characters correctly.
* Compensate for this here.
*/
#ifdef isascii
# undef HAVE_ISASCII /* just in case */
# define HAVE_ISASCII 1
#else
#endif
#if STDC_HEADERS || !HAVE_ISASCII
# define is_ascii(c) 1
#else
# define is_ascii(c) isascii(c)
#endif
#define is_space(c) (is_ascii(c) && isspace(c))
#define is_alpha(c) (is_ascii(c) && isalpha(c))
#define is_alnum(c) (is_ascii(c) && isalnum(c))
/* Scanning macros */
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
/* Forward references */
char *ppdirforward();
char *ppdirbackward();
char *skipspace();
char *scanstring();
int writeblanks();
int test1();
int convert1();
/* The main program */
int
main(argc, argv)
int argc;
char *argv[];
{ FILE *in = stdin;
FILE *out = stdout;
char *filename = 0;
char *program_name = argv[0];
char *output_name = 0;
#define bufsize 5000 /* arbitrary size */
char *buf;
char *line;
char *more;
char *usage =
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
/*
* In previous versions, ansi2knr recognized a --varargs switch.
* If this switch was supplied, ansi2knr would attempt to convert
* a ... argument to va_alist and va_dcl; if this switch was not
* supplied, ansi2knr would simply drop any such arguments.
* Now, ansi2knr always does this conversion, and we only
* check for this switch for backward compatibility.
*/
int convert_varargs = 1;
int output_error;
while ( argc > 1 && argv[1][0] == '-' ) {
if ( !strcmp(argv[1], "--varargs") ) {
convert_varargs = 1;
argc--;
argv++;
continue;
}
if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
filename = argv[2];
argc -= 2;
argv += 2;
continue;
}
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
argv[1]);
fprintf(stderr, usage);
exit(1);
}
switch ( argc )
{
default:
fprintf(stderr, usage);
exit(0);
case 3:
output_name = argv[2];
out = fopen(output_name, "w");
if ( out == NULL ) {
fprintf(stderr, "%s: Cannot open output file %s\n",
program_name, output_name);
exit(1);
}
/* falls through */
case 2:
in = fopen(argv[1], "r");
if ( in == NULL ) {
fprintf(stderr, "%s: Cannot open input file %s\n",
program_name, argv[1]);
exit(1);
}
if ( filename == 0 )
filename = argv[1];
/* falls through */
case 1:
break;
}
if ( filename )
fprintf(out, "#line 1 \"%s\"\n", filename);
buf = malloc(bufsize);
if ( buf == NULL )
{
fprintf(stderr, "Unable to allocate read buffer!\n");
exit(1);
}
line = buf;
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
{
test: line += strlen(line);
switch ( test1(buf) )
{
case 2: /* a function header */
convert1(buf, out, 1, convert_varargs);
break;
case 1: /* a function */
/* Check for a { at the start of the next line. */
more = ++line;
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
goto wl;
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
goto wl;
switch ( *skipspace(ppdirforward(more), 1) )
{
case '{':
/* Definitely a function header. */
convert1(buf, out, 0, convert_varargs);
fputs(more, out);
break;
case 0:
/* The next line was blank or a comment: */
/* keep scanning for a non-comment. */
line += strlen(line);
goto f;
default:
/* buf isn't a function header, but */
/* more might be. */
fputs(buf, out);
strcpy(buf, more);
line = buf;
goto test;
}
break;
case -1: /* maybe the start of a function */
if ( line != buf + (bufsize - 1) ) /* overflow check */
continue;
/* falls through */
default: /* not a function */
wl: fputs(buf, out);
break;
}
line = buf;
}
if ( line != buf )
fputs(buf, out);
free(buf);
if ( output_name ) {
output_error = ferror(out);
output_error |= fclose(out);
} else { /* out == stdout */
fflush(out);
output_error = ferror(out);
}
if ( output_error ) {
fprintf(stderr, "%s: error writing to %s\n", program_name,
(output_name ? output_name : "stdout"));
exit(1);
}
if ( in != stdin )
fclose(in);
return 0;
}
/*
* Skip forward or backward over one or more preprocessor directives.
*/
char *
ppdirforward(p)
char *p;
{
for (; *p == '#'; ++p) {
for (; *p != '\r' && *p != '\n'; ++p)
if (*p == 0)
return p;
if (*p == '\r' && p[1] == '\n')
++p;
}
return p;
}
char *
ppdirbackward(p, limit)
char *p;
char *limit;
{
char *np = p;
for (;; p = --np) {
if (*np == '\n' && np[-1] == '\r')
--np;
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
if (np[-1] == 0)
return np;
if (*np != '#')
return p;
}
}
/*
* Skip over whitespace, comments, and preprocessor directives,
* in either direction.
*/
char *
skipspace(p, dir)
char *p;
int dir; /* 1 for forward, -1 for backward */
{
for ( ; ; ) {
while ( is_space(*p) )
p += dir;
if ( !(*p == '/' && p[dir] == '*') )
break;
p += dir; p += dir;
while ( !(*p == '*' && p[dir] == '/') ) {
if ( *p == 0 )
return p; /* multi-line comment?? */
p += dir;
}
p += dir; p += dir;
}
return p;
}
/* Scan over a quoted string, in either direction. */
char *
scanstring(p, dir)
char *p;
int dir;
{
for (p += dir; ; p += dir)
if (*p == '"' && p[-dir] != '\\')
return p + dir;
}
/*
* Write blanks over part of a string.
* Don't overwrite end-of-line characters.
*/
int
writeblanks(start, end)
char *start;
char *end;
{ char *p;
for ( p = start; p < end; p++ )
if ( *p != '\r' && *p != '\n' )
*p = ' ';
return 0;
}
/*
* Test whether the string in buf is a function definition.
* The string may contain and/or end with a newline.
* Return as follows:
* 0 - definitely not a function definition;
* 1 - definitely a function definition;
* 2 - definitely a function prototype (NOT USED);
* -1 - may be the beginning of a function definition,
* append another line and look again.
* The reason we don't attempt to convert function prototypes is that
* Ghostscript's declaration-generating macros look too much like
* prototypes, and confuse the algorithms.
*/
int
test1(buf)
char *buf;
{ char *p = buf;
char *bend;
char *endfn;
int contin;
if ( !isidfirstchar(*p) )
return 0; /* no name at left margin */
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
switch ( *bend )
{
case ';': contin = 0 /*2*/; break;
case ')': contin = 1; break;
case '{': return 0; /* not a function */
case '}': return 0; /* not a function */
default: contin = -1;
}
while ( isidchar(*p) )
p++;
endfn = p;
p = skipspace(p, 1);
if ( *p++ != '(' )
return 0; /* not a function */
p = skipspace(p, 1);
if ( *p == ')' )
return 0; /* no parameters */
/* Check that the apparent function name isn't a keyword. */
/* We only need to check for keywords that could be followed */
/* by a left parenthesis (which, unfortunately, is most of them). */
{ static char *words[] =
{ "asm", "auto", "case", "char", "const", "double",
"extern", "float", "for", "if", "int", "long",
"register", "return", "short", "signed", "sizeof",
"static", "switch", "typedef", "unsigned",
"void", "volatile", "while", 0
};
char **key = words;
char *kp;
unsigned len = endfn - buf;
while ( (kp = *key) != 0 )
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
return 0; /* name is a keyword */
key++;
}
}
{
char *id = p;
int len;
/*
* Check for identifier1(identifier2) and not
* identifier1(void), or identifier1(identifier2, xxxx).
*/
while ( isidchar(*p) )
p++;
len = p - id;
p = skipspace(p, 1);
if (*p == ',' ||
(*p == ')' && (len != 4 || strncmp(id, "void", 4)))
)
return 0; /* not a function */
}
/*
* If the last significant character was a ), we need to count
* parentheses, because it might be part of a formal parameter
* that is a procedure.
*/
if (contin > 0) {
int level = 0;
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
if (level > 0)
contin = -1;
}
return contin;
}
/* Convert a recognized function definition or header to K&R syntax. */
int
convert1(buf, out, header, convert_varargs)
char *buf;
FILE *out;
int header; /* Boolean */
int convert_varargs; /* Boolean */
{ char *endfn;
char *p;
/*
* The breaks table contains pointers to the beginning and end
* of each argument.
*/
char **breaks;
unsigned num_breaks = 2; /* for testing */
char **btop;
char **bp;
char **ap;
char *vararg = 0;
/* Pre-ANSI implementations don't agree on whether strchr */
/* is called strchr or index, so we open-code it here. */
for ( endfn = buf; *(endfn++) != '('; )
;
top: p = endfn;
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
if ( breaks == NULL )
{ /* Couldn't allocate break table, give up */
fprintf(stderr, "Unable to allocate break table!\n");
fputs(buf, out);
return -1;
}
btop = breaks + num_breaks * 2 - 2;
bp = breaks;
/* Parse the argument list */
do
{ int level = 0;
char *lp = NULL;
char *rp = NULL;
char *end = NULL;
if ( bp >= btop )
{ /* Filled up break table. */
/* Allocate a bigger one and start over. */
free((char *)breaks);
num_breaks <<= 1;
goto top;
}
*bp++ = p;
/* Find the end of the argument */
for ( ; end == NULL; p++ )
{ switch(*p)
{
case ',':
if ( !level ) end = p;
break;
case '(':
if ( !level ) lp = p;
level++;
break;
case ')':
if ( --level < 0 ) end = p;
else rp = p;
break;
case '/':
if (p[1] == '*')
p = skipspace(p, 1) - 1;
break;
case '"':
p = scanstring(p, 1) - 1;
break;
default:
;
}
}
/* Erase any embedded prototype parameters. */
if ( lp && rp )
writeblanks(lp + 1, rp);
p--; /* back up over terminator */
/* Find the name being declared. */
/* This is complicated because of procedure and */
/* array modifiers. */
for ( ; ; )
{ p = skipspace(p - 1, -1);
switch ( *p )
{
case ']': /* skip array dimension(s) */
case ')': /* skip procedure args OR name */
{ int level = 1;
while ( level )
switch ( *--p )
{
case ']': case ')':
level++;
break;
case '[': case '(':
level--;
break;
case '/':
if (p > buf && p[-1] == '*')
p = skipspace(p, -1) + 1;
break;
case '"':
p = scanstring(p, -1) + 1;
break;
default: ;
}
}
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
{ /* We found the name being declared */
while ( !isidfirstchar(*p) )
p = skipspace(p, 1) + 1;
goto found;
}
break;
default:
goto found;
}
}
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
{ if ( convert_varargs )
{ *bp++ = "va_alist";
vararg = p-2;
}
else
{ p++;
if ( bp == breaks + 1 ) /* sole argument */
writeblanks(breaks[0], p);
else
writeblanks(bp[-1] - 1, p);
bp--;
}
}
else
{ while ( isidchar(*p) ) p--;
*bp++ = p+1;
}
p = end;
}
while ( *p++ == ',' );
*bp = p;
/* Make a special check for 'void' arglist */
if ( bp == breaks+2 )
{ p = skipspace(breaks[0], 1);
if ( !strncmp(p, "void", 4) )
{ p = skipspace(p+4, 1);
if ( p == breaks[2] - 1 )
{ bp = breaks; /* yup, pretend arglist is empty */
writeblanks(breaks[0], p + 1);
}
}
}
/* Put out the function name and left parenthesis. */
p = buf;
while ( p != endfn ) putc(*p, out), p++;
/* Put out the declaration. */
if ( header )
{ fputs(");", out);
for ( p = breaks[0]; *p; p++ )
if ( *p == '\r' || *p == '\n' )
putc(*p, out);
}
else
{ for ( ap = breaks+1; ap < bp; ap += 2 )
{ p = *ap;
while ( isidchar(*p) )
putc(*p, out), p++;
if ( ap < bp - 1 )
fputs(", ", out);
}
fputs(") ", out);
/* Put out the argument declarations */
for ( ap = breaks+2; ap <= bp; ap += 2 )
(*ap)[-1] = ';';
if ( vararg != 0 )
{ *vararg = 0;
fputs(breaks[0], out); /* any prior args */
fputs("va_dcl", out); /* the final arg */
fputs(bp[0], out);
}
else
fputs(breaks[0], out);
}
free((char *)breaks);
return 0;
}

View File

@@ -1,163 +0,0 @@
/* Arithmetic for numbers greater than a long int, for GNU tar.
Copyright (C) 1996, 1997 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 2, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */
#include "common.h"
/* GNU tar needs handling numbers exceeding 32 bits, which is the size of
unsigned long ints for many C compilers. This module should provide
machinery for handling at least BITS_PER_TARLONG bits per number. If
`long long' ints are available and are sufficient for the task, they will
be used preferrably.
Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on
Ampex drives), so requiring 38 bits for the tape length in bytes. He
also reports breaking the terabyte limit with a single file (using SGI
xFS file system over 37 28GB disk arrays attached to a Power Challenge
XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a
little more than 40 bits for the file size in bytes. The POSIX header
structure allows for 12 octal digits to represent file lengths, that is,
up to 36 bits for the byte size of files.
If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be
set to zero by configure. In this case, or if `long long' ints does not
have enough bits, then huge numbers are rather represented by an array of
longs, with the least significant super-digit at position 0. For making
multiplication and decimal input/output easy, the base of a super-digit
is an exact exponent of 10, and is such that base*base fits in a long. */
#if SUPERDIGIT
/*-------------------------------.
| Check if ACCUMULATOR is zero. |
`-------------------------------*/
int
zerop_tarlong_helper (unsigned long *accumulator)
{
int counter;
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
if (accumulator[counter])
return 0;
return 1;
}
/*----------------------------------------------.
| Check if FIRST is strictly less than SECOND. |
`----------------------------------------------*/
int
lessp_tarlong_helper (unsigned long *first, unsigned long *second)
{
int counter;
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
if (first[counter] != second[counter])
return first[counter] < second[counter];
return 0;
}
/*----------------------------.
| Reset ACCUMULATOR to zero. |
`----------------------------*/
void
clear_tarlong_helper (unsigned long *accumulator)
{
int counter;
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
accumulator[counter] = 0;
}
/*----------------------------.
| To ACCUMULATOR, add VALUE. |
`----------------------------*/
void
add_to_tarlong_helper (unsigned long *accumulator, int value)
{
int counter;
if (value < 0)
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
if (accumulator[counter] >= -value)
{
accumulator[counter] += value;
return;
}
accumulator[counter] += value + SUPERDIGIT;
value = -1;
}
else
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
if (accumulator[counter] + value < SUPERDIGIT)
{
accumulator[counter] += value;
return;
}
accumulator[counter] += value - SUPERDIGIT;
value = 1;
}
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
}
/*--------------------------------.
| Multiply ACCUMULATOR by VALUE. |
`--------------------------------*/
void
mult_tarlong_helper (unsigned long *accumulator, int value)
{
int carry = 0;
int counter;
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
carry += accumulator[counter] * value;
accumulator[counter] = carry % SUPERDIGIT;
carry /= SUPERDIGIT;
}
if (carry)
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
}
/*----------------------------------------------------------.
| Print the decimal representation of ACCUMULATOR on FILE. |
`----------------------------------------------------------*/
void
print_tarlong_helper (unsigned long *accumulator, FILE *file)
{
int counter = LONGS_PER_TARLONG - 1;
while (counter > 0 && accumulator[counter] == 0)
counter--;
fprintf (file, "%uld", accumulator[counter]);
while (counter > 0)
fprintf (file, TARLONG_FORMAT, accumulator[--counter]);
}
#endif /* SUPERDIGIT */

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
@@ -22,6 +23,6 @@
blocked in 1 kB boundaries. We'll need arbitrary precision
arithmetic anyway once we get into the 2**64 range, so there's no
point doing anything fancy before then. */
#define TARLONG_FORMAT "%.0f"
typedef double tarlong;

File diff suppressed because it is too large Load Diff

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
@@ -77,7 +84,7 @@ void
checkpoint_compile_action (const char *str)
{
struct checkpoint_action *act;
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
alloc_action (cop_dot);
else if (strcmp (str, "bell") == 0)
@@ -108,87 +115,232 @@ 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)
{
if (!checkpoint_action)
/* Provide a historical default */
checkpoint_compile_action ("echo");
checkpoint_compile_action ("echo");
}
else if (checkpoint_action)
/* Otherwise, set default checkpoint rate */
checkpoint_option = DEFAULT_CHECKPOINT;
}
char *
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
{
const char *opstr = do_write ? gettext ("write") : gettext ("read");
size_t opstrlen = strlen (opstr);
char uintbuf[UINTMAX_STRSIZE_BOUND];
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
size_t cpslen = strlen (cps);
const char *ip;
char *op;
char *output;
size_t outlen = strlen (input); /* Initial guess */
static const char *checkpoint_total_format[] = {
"R",
"W",
"D"
};
/* Fix the initial length guess */
for (ip = input; (ip = strchr (ip, '%')) != NULL; )
static long
getwidth (FILE *fp)
{
char const *columns;
#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)
{
switch (p->opcode)
@@ -207,58 +359,64 @@ run_checkpoint_actions (bool do_write)
fflush (tty);
}
break;
case cop_echo:
{
char *tmp;
const char *str = p->v.command;
if (!str)
{
if (do_write)
/* TRANSLATORS: This is a ``checkpoint of write operation'',
*not* ``Writing a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
*not* ``Escribiendo un punto de comprobaci@'on'' */
str = gettext ("Write checkpoint %u");
else
/* TRANSLATORS: This is a ``checkpoint of read operation'',
*not* ``Reading a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
*not* ``Leyendo un punto de comprobaci@'on'' */
str = gettext ("Read checkpoint %u");
}
tmp = expand_checkpoint_string (str, do_write, checkpoint);
WARN ((0, 0, "%s", tmp));
free (tmp);
int n = fprintf (stderr, "%s: ", program_name);
format_checkpoint_string (stderr, n, p->v.command, do_write,
checkpoint);
fputc ('\n', stderr);
}
break;
case cop_ttyout:
if (!tty)
tty = fopen ("/dev/tty", "w");
if (tty)
{
char *tmp = expand_checkpoint_string (p->v.command, do_write,
checkpoint);
fprintf (tty, "%s", tmp);
fflush (tty);
free (tmp);
}
format_checkpoint_string (tty, 0, p->v.command, do_write,
checkpoint);
break;
case cop_sleep:
sleep (p->v.time);
break;
case cop_exec:
sys_exec_checkpoint_script (p->v.command,
archive_name_cursor[0],
checkpoint);
break;
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
@@ -266,5 +424,15 @@ 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,21 +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 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"
@@ -60,6 +61,8 @@
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
#include <obstack.h>
#include <progname.h>
#include <xvasprintf.h>
#include <paxlib.h>
@@ -67,12 +70,14 @@
#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. */
/* Name of this program. */
GLOBAL const char *program_name;
/* Main command option. */
enum subcommand
@@ -85,7 +90,8 @@ enum subcommand
DIFF_SUBCOMMAND, /* -d */
EXTRACT_SUBCOMMAND, /* -x */
LIST_SUBCOMMAND, /* -t */
UPDATE_SUBCOMMAND /* -u */
UPDATE_SUBCOMMAND, /* -u */
TEST_LABEL_SUBCOMMAND, /* --test-label */
};
GLOBAL enum subcommand subcommand_option;
@@ -104,6 +110,8 @@ GLOBAL bool absolute_names_option;
/* Display file times in UTC */
GLOBAL bool utc_option;
/* Output file timestamps to the full resolution */
GLOBAL bool full_time_option;
/* This variable tells how to interpret newer_mtime_option, below. If zero,
files get archived if their mtime is not less than newer_mtime_option.
@@ -135,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;
@@ -155,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;
@@ -179,12 +185,17 @@ 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 */
GLOBAL int incremental_level;
/* Check device numbers when doing incremental dumps. */
GLOBAL bool check_device_option;
@@ -224,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;
@@ -234,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;
@@ -248,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;
@@ -308,35 +330,55 @@ 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. */
GLOBAL char const *index_file_name;
/* Opaque structure for keeping directory meta-data */
struct directory;
/* Structure for keeping track of filenames and lists thereof. */
struct name
{
struct name *next; /* Link to the next element */
struct name *prev; /* Link to the previous element */
char *name; /* File name or globbing pattern */
size_t length; /* cached strlen (name) */
int matching_flags; /* wildcard flags if name is a pattern */
bool cmdline; /* true if this name was given in the
command line */
int change_dir; /* Number of the directory to change to.
Set with the -C option. */
uintmax_t found_count; /* number of times a matching file has
been found */
int matching_flags; /* this name is a regexp, not literal */
char const *dir_contents; /* for incremental_option */
size_t length; /* cached strlen(name) */
char name[1];
/* The following members are used for incremental dumps only,
if this struct name represents a directory;
see incremen.c */
struct directory *directory;/* directory meta-data and contents */
struct name *parent; /* pointer to the parent hierarchy */
struct name *child; /* pointer to the first child */
struct name *sibling; /* pointer to the next sibling */
char *caname; /* canonical name */
};
/* Obnoxious test to see if dimwit is trying to dump the archive. */
GLOBAL dev_t ar_dev;
GLOBAL ino_t ar_ino;
/* Flags for reading, searching, and fstatatting files. */
GLOBAL int open_read_flags;
GLOBAL int open_searchdir_flags;
GLOBAL int fstatat_flags;
GLOBAL int seek_option;
GLOBAL bool seekable_archive;
GLOBAL dev_t root_device;
@@ -344,7 +386,7 @@ GLOBAL dev_t root_device;
/* Unquote filenames */
GLOBAL bool unquote_option;
GLOBAL bool test_label_option; /* Test archive volume label and exit */
GLOBAL int savedir_sort_order;
/* Show file or archive names after transformation.
In particular, when creating archive in verbose mode, list member names
@@ -379,15 +421,19 @@ extern enum access_mode access_mode;
extern FILE *stdlis;
extern bool write_archive_to_stdout;
extern char *volume_label;
extern size_t volume_label_count;
extern char *continued_file_name;
extern uintmax_t continued_file_size;
extern uintmax_t continued_file_offset;
extern off_t records_written;
char *drop_volume_label_suffix (const char *label);
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);
@@ -404,13 +450,23 @@ void archive_read_error (void);
off_t seek_archive (off_t size);
void set_start_time (void);
void mv_begin (struct tar_stat_info *st);
#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);
void mv_end (void);
void mv_total_size (off_t size);
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
@@ -422,49 +478,35 @@ enum dump_status
};
void add_exclusion_tag (const char *name, enum exclusion_tag_type type,
bool (*)(const char*));
bool cachedir_file_p (const char *name);
bool (*predicate) (int));
bool cachedir_file_p (int fd);
char *get_directory_entries (struct tar_stat_info *st);
bool file_dumpable_p (struct tar_stat_info *st);
void create_archive (void);
void pad_archive (off_t size_left);
void dump_file (const char *st, int top_level, dev_t parent_device);
void dump_file (struct tar_stat_info *parent, char const *name,
char const *fullname);
union block *start_header (struct tar_stat_info *st);
void finish_header (struct tar_stat_info *st, union block *header,
off_t block_ordinal);
void simple_finish_header (union block *header);
union block * write_extended (bool global, struct tar_stat_info *st,
union block *old_header);
union block *start_private_header (const char *name, size_t size);
union block *start_private_header (const char *name, size_t size, time_t t);
void write_eot (void);
void check_links (void);
int subfile_open (struct tar_stat_info const *dir, char const *file, int flags);
void restore_parent_fd (struct tar_stat_info const *st);
void exclusion_tag_warning (const char *dirname, const char *tagname,
const char *message);
enum exclusion_tag_type check_exclusion_tags (char *dirname,
enum exclusion_tag_type check_exclusion_tags (struct tar_stat_info const *st,
const char **tag_file_name);
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
#define MAJOR_TO_CHARS(val, where) major_to_chars (val, where, sizeof (where))
#define MINOR_TO_CHARS(val, where) minor_to_chars (val, where, sizeof (where))
#define MODE_TO_CHARS(val, where) mode_to_chars (val, where, sizeof (where))
#define OFF_TO_CHARS(val, where) off_to_chars (val, where, sizeof (where))
#define SIZE_TO_CHARS(val, where) size_to_chars (val, where, sizeof (where))
#define TIME_TO_CHARS(val, where) time_to_chars (val, where, sizeof (where))
#define UID_TO_CHARS(val, where) uid_to_chars (val, where, sizeof (where))
#define UINTMAX_TO_CHARS(val, where) uintmax_to_chars (val, where, sizeof (where))
#define UNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
#define GNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
bool gid_to_chars (gid_t gid, char *buf, size_t size);
bool major_to_chars (major_t m, char *buf, size_t size);
bool minor_to_chars (minor_t m, char *buf, size_t size);
bool mode_to_chars (mode_t m, char *buf, size_t size);
#define OFF_TO_CHARS(val, where) off_to_chars (val, where, sizeof (where))
#define TIME_TO_CHARS(val, where) time_to_chars (val, where, sizeof (where))
bool off_to_chars (off_t off, char *buf, size_t size);
bool size_to_chars (size_t v, char *buf, size_t size);
bool time_to_chars (time_t t, char *buf, size_t size);
bool uid_to_chars (uid_t uid, char *buf, size_t size);
bool uintmax_to_chars (uintmax_t v, char *buf, size_t size);
void string_to_chars (char const *s, char *buf, size_t size);
/* Module diffarch.c. */
@@ -486,27 +528,26 @@ bool rename_directory (char *src, char *dst);
void delete_archive_members (void);
/* Module incremen.c. */
typedef struct dumpdir *dumpdir_t;
typedef struct dumpdir_iter *dumpdir_iter_t;
dumpdir_t dumpdir_create0 (const char *contents, const char *cmask);
dumpdir_t dumpdir_create (const char *contents);
void dumpdir_free (dumpdir_t);
char *dumpdir_locate (dumpdir_t dump, const char *name);
char *dumpdir_next (dumpdir_iter_t itr);
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
struct directory *scan_directory (struct tar_stat_info *st);
const char *directory_contents (struct directory *dir);
const char *safe_directory_contents (struct directory *dir);
void rebase_directory (struct directory *dir,
const char *samp, size_t slen,
const char *repl, size_t rlen);
const char *get_directory_contents (char *dir_name, dev_t device);
const char *append_incremental_renames (const char *dump);
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);
void list_dumpdir (char *buffer, size_t size);
void update_parent_directory (const char *name);
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. */
@@ -520,6 +561,17 @@ enum read_header
HEADER_FAILURE /* ill-formed header, or bad checksum */
};
/* Operation mode for read_header: */
enum read_header_mode
{
read_header_auto, /* process extended headers automatically */
read_header_x_raw, /* return raw extended headers (return
HEADER_SUCCESS_EXTENDED) */
read_header_x_global /* when POSIX global extended header is read,
decode it and return
HEADER_SUCCESS_EXTENDED */
};
extern union block *current_header;
extern enum archive_format current_format;
extern size_t recent_long_name_blocks;
@@ -527,50 +579,88 @@ 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 GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
#define MODE_FROM_HEADER(where) mode_from_header (where, sizeof (where))
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
#define SIZE_FROM_HEADER(where) size_from_header (where, sizeof (where))
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
#define UINTMAX_FROM_HEADER(where) uintmax_from_header (where, sizeof (where))
gid_t gid_from_header (const char *buf, size_t size);
major_t major_from_header (const char *buf, size_t size);
minor_t minor_from_header (const char *buf, size_t size);
mode_t mode_from_header (const char *buf, size_t size);
off_t off_from_header (const char *buf, size_t size);
size_t size_from_header (const char *buf, size_t size);
time_t time_from_header (const char *buf, size_t size);
uid_t uid_from_header (const char *buf, size_t size);
uintmax_t uintmax_from_header (const char * buf, size_t size);
uintmax_t uintmax_from_header (const char *buf, size_t size);
void list_archive (void);
void test_archive_label (void);
void print_for_mkdir (char *dirname, int length, mode_t mode);
void print_header (struct tar_stat_info *st, off_t block_ordinal);
void print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal);
void read_and (void (*do_something) (void));
enum read_header read_header_primitive (bool raw_extended_headers,
struct tar_stat_info *info);
enum read_header read_header (bool raw_extended_headers);
enum read_header read_header (union block **return_block,
struct tar_stat_info *info,
enum read_header_mode m);
enum read_header tar_checksum (union block *header, bool silent);
void skip_file (off_t size);
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);
char *quote_copy_string (const char *str);
int unquote_string (char *str);
char *zap_slashes (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 *);
enum remove_option
{
@@ -590,10 +680,16 @@ int remove_any_file (const char *file_name, enum remove_option option);
bool maybe_backup_file (const char *file_name, bool this_is_the_archive);
void undo_last_backup (void);
int deref_stat (bool deref, char const *name, struct stat *buf);
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);
void chdir_do (int dir);
int chdir_count (void);
void close_diag (char const *name);
void open_diag (char const *name);
@@ -602,6 +698,8 @@ void readlink_diag (char const *name);
void savedir_diag (char const *name);
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 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)
@@ -611,11 +709,12 @@ pid_t xfork (void);
void xpipe (int fd[2]);
void *page_aligned_alloc (void **ptr, size_t size);
int set_file_atime (int fd, char const *file,
struct timespec const timespec[2]);
int set_file_atime (int fd, int parentfd, char const *file,
struct timespec atime);
/* Module names.c. */
extern size_t name_count;
extern struct name *gnu_list_name;
void gid_to_gname (gid_t gid, char **gname);
@@ -626,25 +725,26 @@ 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);
struct name *addname (char const *string, int change_dir);
struct name *addname (char const *string, int change_dir,
bool cmdline, struct name *parent);
void remname (struct name *name);
bool name_match (const char *name);
void names_notfound (void);
void label_notfound (void);
void collect_and_sort_names (void);
struct name *name_scan (const char *name);
char *name_from_list (void);
struct name const *name_from_list (void);
void blank_name_list (void);
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);
@@ -658,14 +758,18 @@ bool contains_dot_dot (char const *name);
void usage (int);
int confirm (const char *message_action, const char *name);
void request_stdin (const char *option);
void tar_stat_init (struct tar_stat_info *st);
bool tar_stat_close (struct tar_stat_info *st);
void tar_stat_destroy (struct tar_stat_info *st);
void usage (int) __attribute__ ((noreturn));
int tar_timespec_cmp (struct timespec a, struct timespec b);
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. */
@@ -673,15 +777,17 @@ extern char *output_start;
void update_archive (void);
/* Module attrs.c. */
#include "xattrs.h"
/* Module xheader.c. */
void xheader_init (struct xheader *xhdr);
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_write (char type, char *name, struct xheader *xhdr);
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);
void xheader_destroy (struct xheader *hdr);
@@ -694,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 */
@@ -718,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);
@@ -741,14 +854,81 @@ bool utf8_convert (bool to_utf, char const *input, char **output);
void set_transform_expr (const char *expr);
bool transform_name (char **pinput, int type);
bool transform_member_name (char **pinput, int type);
bool transform_name_fp (char **pinput, int type,
char *(*fun)(char *, void *), void *);
bool transform_program_p (void);
/* Module suffix.c */
void set_comression_program_by_suffix (const char *name, const char *defprog);
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
#define WARN_BAD_DUMPDIR 0x00000002
#define WARN_CACHEDIR 0x00000004
#define WARN_CONTIGUOUS_CAST 0x00000008
#define WARN_FILE_CHANGED 0x00000010
#define WARN_FILE_IGNORED 0x00000020
#define WARN_FILE_REMOVED 0x00000040
#define WARN_FILE_SHRANK 0x00000080
#define WARN_FILE_UNCHANGED 0x00000100
#define WARN_FILENAME_WITH_NULS 0x00000200
#define WARN_IGNORE_ARCHIVE 0x00000400
#define WARN_IGNORE_NEWER 0x00000800
#define WARN_NEW_DIRECTORY 0x00001000
#define WARN_RENAME_DIRECTORY 0x00002000
#define WARN_SYMLINK_CAST 0x00004000
#define WARN_TIMESTAMP 0x00008000
#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
/* 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);
extern int warning_option;
#define WARNOPT(opt,args) \
do \
{ \
if (warning_option & opt) WARN (args); \
} \
while (0)
/* Module unlink.c */
void queue_deferred_unlink (const char *name, bool is_dir);
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 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>
@@ -66,8 +67,7 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
fprintf (stdlis, "\n");
}
if (exit_status == TAREXIT_SUCCESS)
exit_status = TAREXIT_DIFFERS;
set_exit_status (TAREXIT_DIFFERS);
}
/* Take a buffer returned by read_and_process and do nothing with it. */
@@ -81,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)
{
@@ -123,7 +123,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
size_t data_size;
off_t size = st->stat.st_size;
mv_begin (st);
mv_begin_read (st);
while (size)
{
data_block = find_next_block ();
@@ -152,7 +152,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
static int
get_stat_data (char const *file_name, struct stat *stat_data)
{
int status = deref_stat (dereference_option, file_name, stat_data);
int status = deref_stat (file_name, stat_data);
if (status != 0)
{
@@ -218,12 +218,7 @@ diff_file (void)
}
else
{
int atime_flag =
(atime_preserve_option == system_atime_preserve
? O_NOATIME
: 0);
diff_handle = open (file_name, O_RDONLY | O_BINARY | atime_flag);
diff_handle = openat (chdir_fd, file_name, open_read_flags);
if (diff_handle < 0)
{
@@ -240,12 +235,12 @@ 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 ts[2];
ts[0] = get_stat_atime (&stat_data);
ts[1] = get_stat_mtime (&stat_data);
if (set_file_atime (diff_handle, file_name, ts) != 0)
struct timespec atime = get_stat_atime (&stat_data);
if (set_file_atime (diff_handle, chdir_fd, file_name, atime)
!= 0)
utime_error (file_name);
}
@@ -278,7 +273,8 @@ diff_symlink (void)
size_t len = strlen (current_stat_info.link_name);
char *linkbuf = alloca (len + 1);
int status = readlink (current_stat_info.file_name, linkbuf, len + 1);
int status = readlinkat (chdir_fd, current_stat_info.file_name,
linkbuf, len + 1);
if (status < 0)
{
@@ -332,7 +328,7 @@ static int
dumpdir_cmp (const char *a, const char *b)
{
size_t len;
while (*a)
switch (*a)
{
@@ -346,7 +342,7 @@ dumpdir_cmp (const char *a, const char *b)
a += len;
b += len;
break;
case 'D':
if (strcmp(a, b))
return 1;
@@ -354,7 +350,7 @@ dumpdir_cmp (const char *a, const char *b)
a += len;
b += len;
break;
case 'R':
case 'T':
case 'X':
@@ -364,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 (true, current_stat_info.file_name, &stat_data))
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 = get_directory_contents (current_stat_info.file_name, dev);
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
@@ -415,14 +418,17 @@ 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 ();
return;
}
fd = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
fd = openat (chdir_fd, current_stat_info.file_name, open_read_flags);
if (fd < 0)
{
@@ -436,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)
@@ -452,7 +457,6 @@ diff_archive (void)
{
set_next_block_after (current_header);
decode_header (current_header, &current_stat_info, &current_format, 1);
/* Print the block from current_header and current_stat_info. */
@@ -460,13 +464,13 @@ diff_archive (void)
{
if (now_verifying)
fprintf (stdlis, _("Verify "));
print_header (&current_stat_info, -1);
print_header (&current_stat_info, current_header, -1);
}
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. */
@@ -503,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;
@@ -518,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 ();
@@ -578,7 +593,9 @@ verify_volume (void)
flush_read ();
while (1)
{
enum read_header status = read_header (false);
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_auto);
if (status == HEADER_FAILURE)
{
@@ -588,7 +605,8 @@ verify_volume (void)
{
counter++;
set_next_block_after (current_header);
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
}
while (status == HEADER_FAILURE);
@@ -606,14 +624,18 @@ verify_volume (void)
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(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)

File diff suppressed because it is too large Load Diff

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 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>
@@ -35,7 +36,6 @@ extern union block *current_block;
extern union block *recent_long_name;
extern union block *recent_long_link;
extern off_t records_read;
extern off_t records_written;
/* The number of records skipped at the start of the archive, when
passing over members that are not deleted. */
@@ -166,7 +166,9 @@ delete_archive_members (void)
do
{
enum read_header status = read_header (true);
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_x_raw);
switch (status)
{
@@ -261,7 +263,8 @@ delete_archive_members (void)
if (current_block == record_end)
flush_archive ();
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
xheader_decode (&current_stat_info);
@@ -294,7 +297,7 @@ delete_archive_members (void)
set_next_block_after (current_header);
blocks_to_skip = (current_stat_info.stat.st_size
+ BLOCKSIZE - 1) / BLOCKSIZE;
while (record_end - current_block <= blocks_to_skip)
{
blocks_to_skip -= (record_end - current_block);

View File

@@ -1,759 +0,0 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993 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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Diff files from a tar archive.
*
* Written 30 April 1987 by John Gilmore, ihnp4!hoptoad!gnu.
*/
#include <stdio.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <sys/types.h>
#ifdef BSD42
#include <sys/file.h>
#else
#ifndef V7
#include <fcntl.h>
#endif
#endif
#ifdef HAVE_SYS_MTIO_H
#include <sys/ioctl.h>
#include <sys/mtio.h>
#endif
#include "tar.h"
#include "port.h"
#include "rmt.h"
#ifndef S_ISLNK
#define lstat stat
#endif
extern void *valloc ();
extern union record *head; /* Points to current tape header */
extern struct stat hstat; /* Stat struct corresponding */
extern int head_standard; /* Tape header is in ANSI format */
void decode_header ();
void diff_sparse_files ();
void fill_in_sparse_array ();
void fl_read ();
long from_oct ();
int do_stat ();
extern void print_header ();
int read_header ();
void saverec ();
void sigh ();
extern void skip_file ();
extern void skip_extended_headers ();
int wantbytes ();
extern FILE *msg_file;
int now_verifying = 0; /* Are we verifying at the moment? */
int diff_fd; /* Descriptor of file we're diffing */
char *diff_buf = 0; /* Pointer to area for reading
file contents into */
char *diff_dir; /* Directory contents for LF_DUMPDIR */
int different = 0;
/*struct sp_array *sparsearray;
int sp_ar_size = 10;*/
/*
* Initialize for a diff operation
*/
void
diff_init ()
{
/*NOSTRICT*/
diff_buf = (char *) valloc ((unsigned) blocksize);
if (!diff_buf)
{
msg ("could not allocate memory for diff buffer of %d bytes",
blocksize);
exit (EX_ARGSBAD);
}
}
/*
* Diff a file against the archive.
*/
void
diff_archive ()
{
register char *data;
int check, namelen;
int err;
long offset;
struct stat filestat;
int compare_chunk ();
int compare_dir ();
int no_op ();
#ifndef __MSDOS__
dev_t dev;
ino_t ino;
#endif
char *get_dir_contents ();
long from_oct ();
errno = EPIPE; /* FIXME, remove perrors */
saverec (&head); /* Make sure it sticks around */
userec (head); /* And go past it in the archive */
decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
/* Print the record from 'head' and 'hstat' */
if (f_verbose)
{
if (now_verifying)
fprintf (msg_file, "Verify ");
print_header ();
}
switch (head->header.linkflag)
{
default:
msg ("Unknown file type '%c' for %s, diffed as normal file",
head->header.linkflag, current_file_name);
/* FALL THRU */
case LF_OLDNORMAL:
case LF_NORMAL:
case LF_SPARSE:
case LF_CONTIG:
/*
* Appears to be a file.
* See if it's really a directory.
*/
namelen = strlen (current_file_name) - 1;
if (current_file_name[namelen] == '/')
goto really_dir;
if (do_stat (&filestat))
{
if (head->header.isextended)
skip_extended_headers ();
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
if (!S_ISREG (filestat.st_mode))
{
fprintf (msg_file, "%s: not a regular file\n",
current_file_name);
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
filestat.st_mode &= 07777;
if (filestat.st_mode != hstat.st_mode)
sigh ("mode");
if (filestat.st_uid != hstat.st_uid)
sigh ("uid");
if (filestat.st_gid != hstat.st_gid)
sigh ("gid");
if (filestat.st_mtime != hstat.st_mtime)
sigh ("mod time");
if (head->header.linkflag != LF_SPARSE &&
filestat.st_size != hstat.st_size)
{
sigh ("size");
skip_file ((long) hstat.st_size);
goto quit;
}
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
if (diff_fd < 0 && !f_absolute_paths)
{
char tmpbuf[NAMSIZ + 2];
tmpbuf[0] = '/';
strcpy (&tmpbuf[1], current_file_name);
diff_fd = open (tmpbuf, O_NDELAY | O_RDONLY);
}
if (diff_fd < 0)
{
msg_perror ("cannot open %s", current_file_name);
if (head->header.isextended)
skip_extended_headers ();
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
/*
* Need to treat sparse files completely differently here.
*/
if (head->header.linkflag == LF_SPARSE)
diff_sparse_files (hstat.st_size);
else
wantbytes ((long) (hstat.st_size), compare_chunk);
check = close (diff_fd);
if (check < 0)
msg_perror ("Error while closing %s", current_file_name);
quit:
break;
#ifndef __MSDOS__
case LF_LINK:
if (do_stat (&filestat))
break;
dev = filestat.st_dev;
ino = filestat.st_ino;
err = stat (current_link_name, &filestat);
if (err < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file, "%s: does not exist\n", current_file_name);
}
else
{
msg_perror ("cannot stat file %s", current_file_name);
}
different++;
break;
}
if (filestat.st_dev != dev || filestat.st_ino != ino)
{
fprintf (msg_file, "%s not linked to %s\n", current_file_name, current_link_name);
break;
}
break;
#endif
#ifdef S_ISLNK
case LF_SYMLINK:
{
char linkbuf[NAMSIZ + 3];
check = readlink (current_file_name, linkbuf,
(sizeof linkbuf) - 1);
if (check < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file,
"%s: no such file or directory\n",
current_file_name);
}
else
{
msg_perror ("cannot read link %s", current_file_name);
}
different++;
break;
}
linkbuf[check] = '\0'; /* Null-terminate it */
if (strncmp (current_link_name, linkbuf, check) != 0)
{
fprintf (msg_file, "%s: symlink differs\n",
current_link_name);
different++;
}
}
break;
#endif
#ifdef S_IFCHR
case LF_CHR:
hstat.st_mode |= S_IFCHR;
goto check_node;
#endif
#ifdef S_IFBLK
/* If local system doesn't support block devices, use default case */
case LF_BLK:
hstat.st_mode |= S_IFBLK;
goto check_node;
#endif
#ifdef S_ISFIFO
/* If local system doesn't support FIFOs, use default case */
case LF_FIFO:
#ifdef S_IFIFO
hstat.st_mode |= S_IFIFO;
#endif
hstat.st_rdev = 0; /* FIXME, do we need this? */
goto check_node;
#endif
check_node:
/* FIXME, deal with umask */
if (do_stat (&filestat))
break;
if (hstat.st_rdev != filestat.st_rdev)
{
fprintf (msg_file, "%s: device numbers changed\n", current_file_name);
different++;
break;
}
#ifdef S_IFMT
if (hstat.st_mode != filestat.st_mode)
#else /* POSIX lossage */
if ((hstat.st_mode & 07777) != (filestat.st_mode & 07777))
#endif
{
fprintf (msg_file, "%s: mode or device-type changed\n", current_file_name);
different++;
break;
}
break;
case LF_DUMPDIR:
data = diff_dir = get_dir_contents (current_file_name, 0);
if (data)
{
wantbytes ((long) (hstat.st_size), compare_dir);
free (data);
}
else
wantbytes ((long) (hstat.st_size), no_op);
/* FALL THROUGH */
case LF_DIR:
/* Check for trailing / */
namelen = strlen (current_file_name) - 1;
really_dir:
while (namelen && current_file_name[namelen] == '/')
current_file_name[namelen--] = '\0'; /* Zap / */
if (do_stat (&filestat))
break;
if (!S_ISDIR (filestat.st_mode))
{
fprintf (msg_file, "%s is no longer a directory\n", current_file_name);
different++;
break;
}
if ((filestat.st_mode & 07777) != (hstat.st_mode & 07777))
sigh ("mode");
break;
case LF_VOLHDR:
break;
case LF_MULTIVOL:
namelen = strlen (current_file_name) - 1;
if (current_file_name[namelen] == '/')
goto really_dir;
if (do_stat (&filestat))
break;
if (!S_ISREG (filestat.st_mode))
{
fprintf (msg_file, "%s: not a regular file\n",
current_file_name);
skip_file ((long) hstat.st_size);
different++;
break;
}
filestat.st_mode &= 07777;
offset = from_oct (1 + 12, head->header.offset);
if (filestat.st_size != hstat.st_size + offset)
{
sigh ("size");
skip_file ((long) hstat.st_size);
different++;
break;
}
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
if (diff_fd < 0)
{
msg_perror ("cannot open file %s", current_file_name);
skip_file ((long) hstat.st_size);
different++;
break;
}
err = lseek (diff_fd, offset, 0);
if (err != offset)
{
msg_perror ("cannot seek to %ld in file %s", offset, current_file_name);
different++;
break;
}
wantbytes ((long) (hstat.st_size), compare_chunk);
check = close (diff_fd);
if (check < 0)
{
msg_perror ("Error while closing %s", current_file_name);
}
break;
}
/* We don't need to save it any longer. */
saverec ((union record **) 0);/* Unsave it */
}
int
compare_chunk (bytes, buffer)
long bytes;
char *buffer;
{
int err;
err = read (diff_fd, diff_buf, bytes);
if (err != bytes)
{
if (err < 0)
{
msg_perror ("can't read %s", current_file_name);
}
else
{
fprintf (msg_file, "%s: could only read %d of %d bytes\n", current_file_name, err, bytes);
}
different++;
return -1;
}
if (bcmp (buffer, diff_buf, bytes))
{
fprintf (msg_file, "%s: data differs\n", current_file_name);
different++;
return -1;
}
return 0;
}
int
compare_dir (bytes, buffer)
long bytes;
char *buffer;
{
if (bcmp (buffer, diff_dir, bytes))
{
fprintf (msg_file, "%s: data differs\n", current_file_name);
different++;
return -1;
}
diff_dir += bytes;
return 0;
}
/*
* Sigh about something that differs.
*/
void
sigh (what)
char *what;
{
fprintf (msg_file, "%s: %s differs\n",
current_file_name, what);
}
void
verify_volume ()
{
int status;
#ifdef MTIOCTOP
struct mtop t;
int er;
#endif
if (!diff_buf)
diff_init ();
#ifdef MTIOCTOP
t.mt_op = MTBSF;
t.mt_count = 1;
if ((er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
{
if (errno != EIO || (er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
{
#endif
if (rmtlseek (archive, 0L, 0) != 0)
{
/* Lseek failed. Try a different method */
msg_perror ("Couldn't rewind archive file for verify");
return;
}
#ifdef MTIOCTOP
}
}
#endif
ar_reading = 1;
now_verifying = 1;
fl_read ();
for (;;)
{
status = read_header ();
if (status == 0)
{
unsigned n;
n = 0;
do
{
n++;
status = read_header ();
}
while (status == 0);
msg ("VERIFY FAILURE: %d invalid header%s detected!", n, n == 1 ? "" : "s");
}
if (status == 2 || status == EOF)
break;
diff_archive ();
}
ar_reading = 0;
now_verifying = 0;
}
int
do_stat (statp)
struct stat *statp;
{
int err;
err = f_follow_links ? stat (current_file_name, statp) : lstat (current_file_name, statp);
if (err < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file, "%s: does not exist\n", current_file_name);
}
else
msg_perror ("can't stat file %s", current_file_name);
/* skip_file((long)hstat.st_size);
different++;*/
return 1;
}
else
return 0;
}
/*
* JK
* Diff'ing a sparse file with its counterpart on the tar file is a
* bit of a different story than a normal file. First, we must know
* what areas of the file to skip through, i.e., we need to contruct
* a sparsearray, which will hold all the information we need. We must
* compare small amounts of data at a time as we find it.
*/
void
diff_sparse_files (filesize)
int filesize;
{
int sparse_ind = 0;
char *buf;
int buf_size = RECORDSIZE;
union record *datarec;
int err;
long numbytes;
/* int amt_read = 0;*/
int size = filesize;
buf = (char *) ck_malloc (buf_size * sizeof (char));
fill_in_sparse_array ();
while (size > 0)
{
datarec = findrec ();
if (!sparsearray[sparse_ind].numbytes)
break;
/*
* 'numbytes' is nicer to write than
* 'sparsearray[sparse_ind].numbytes' all the time ...
*/
numbytes = sparsearray[sparse_ind].numbytes;
lseek (diff_fd, sparsearray[sparse_ind].offset, 0);
/*
* take care to not run out of room in our buffer
*/
while (buf_size < numbytes)
{
buf = (char *) ck_realloc (buf, buf_size * 2 * sizeof (char));
buf_size *= 2;
}
while (numbytes > RECORDSIZE)
{
if ((err = read (diff_fd, buf, RECORDSIZE)) != RECORDSIZE)
{
if (err < 0)
msg_perror ("can't read %s", current_file_name);
else
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
current_file_name, err, numbytes);
break;
}
if (bcmp (buf, datarec->charptr, RECORDSIZE))
{
different++;
break;
}
numbytes -= err;
size -= err;
userec (datarec);
datarec = findrec ();
}
if ((err = read (diff_fd, buf, numbytes)) != numbytes)
{
if (err < 0)
msg_perror ("can't read %s", current_file_name);
else
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
current_file_name, err, numbytes);
break;
}
if (bcmp (buf, datarec->charptr, numbytes))
{
different++;
break;
}
/* amt_read += numbytes;
if (amt_read >= RECORDSIZE) {
amt_read = 0;
userec(datarec);
datarec = findrec();
}*/
userec (datarec);
sparse_ind++;
size -= numbytes;
}
/*
* if the number of bytes read isn't the
* number of bytes supposedly in the file,
* they're different
*/
/* if (amt_read != filesize)
different++;*/
userec (datarec);
free (sparsearray);
if (different)
fprintf (msg_file, "%s: data differs\n", current_file_name);
}
/*
* JK
* This routine should be used more often than it is ... look into
* that. Anyhow, what it does is translate the sparse information
* on the header, and in any subsequent extended headers, into an
* array of structures with true numbers, as opposed to character
* strings. It simply makes our life much easier, doing so many
* comparisong and such.
*/
void
fill_in_sparse_array ()
{
int ind;
/*
* allocate space for our scratch space; it's initially
* 10 elements long, but can change in this routine if
* necessary
*/
sp_array_size = 10;
sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
/*
* there are at most five of these structures in the header
* itself; read these in first
*/
for (ind = 0; ind < SPARSE_IN_HDR; ind++)
{
if (!head->header.sp[ind].numbytes)
break;
sparsearray[ind].offset =
from_oct (1 + 12, head->header.sp[ind].offset);
sparsearray[ind].numbytes =
from_oct (1 + 12, head->header.sp[ind].numbytes);
}
/*
* if the header's extended, we gotta read in exhdr's till
* we're done
*/
if (head->header.isextended)
{
/* how far into the sparsearray we are 'so far' */
static int so_far_ind = SPARSE_IN_HDR;
union record *exhdr;
for (;;)
{
exhdr = findrec ();
for (ind = 0; ind < SPARSE_EXT_HDR; ind++)
{
if (ind + so_far_ind > sp_array_size - 1)
{
/*
* we just ran out of room in our
* scratch area - realloc it
*/
sparsearray = (struct sp_array *)
ck_realloc (sparsearray,
sp_array_size * 2 * sizeof (struct sp_array));
sp_array_size *= 2;
}
/*
* convert the character strings into longs
*/
sparsearray[ind + so_far_ind].offset =
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset);
sparsearray[ind + so_far_ind].numbytes =
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes);
}
/*
* if this is the last extended header for this
* file, we can stop
*/
if (!exhdr->ext_hdr.isextended)
break;
else
{
so_far_ind += SPARSE_EXT_HDR;
userec (exhdr);
}
}
/* be sure to skip past the last one */
userec (exhdr);
}
}

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

39
src/exit.c Normal file
View File

@@ -0,0 +1,39 @@
/* Exit from GNU tar.
Copyright 2009, 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/>. */
#include <system.h>
#include "common.h"
void (*fatal_exit_hook) (void);
void
fatal_exit (void)
{
if (fatal_exit_hook)
fatal_exit_hook ();
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
abort ();
}
void
xalloc_die (void)
{
error (0, 0, "%s", _("memory exhausted"));
fatal_exit ();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,96 +0,0 @@
/* Replacement for getopt() that can be used by tar.
Copyright (C) 1988 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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Plug-compatible replacement for getopt() for parsing tar-like
* arguments. If the first argument begins with "-", it uses getopt;
* otherwise, it uses the old rules used by tar, dump, and ps.
*
* Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu)
*/
#include <stdio.h>
#include "getopt.h"
#include "tar.h" /* For msg() declaration if STDC_MSG. */
#include <sys/types.h>
#include "port.h"
int
getoldopt (argc, argv, optstring, long_options, opt_index)
int argc;
char **argv;
char *optstring;
struct option *long_options;
int *opt_index;
{
extern char *optarg; /* Points to next arg */
extern int optind; /* Global argv index */
static char *key; /* Points to next keyletter */
static char use_getopt; /* !=0 if argv[1][0] was '-' */
char c;
char *place;
optarg = NULL;
if (key == NULL)
{ /* First time */
if (argc < 2)
return EOF;
key = argv[1];
if ((*key == '-') || (*key == '+'))
use_getopt++;
else
optind = 2;
}
if (use_getopt)
return getopt_long (argc, argv, optstring,
long_options, opt_index);
c = *key++;
if (c == '\0')
{
key--;
return EOF;
}
place = index (optstring, c);
if (place == NULL || c == ':')
{
msg ("unknown option %c", c);
return ('?');
}
place++;
if (*place == ':')
{
if (optind < argc)
{
optarg = argv[optind];
optind++;
}
else
{
msg ("%c argument missing", c);
return ('?');
}
}
return (c);
}

677
src/gnu.c
View File

@@ -1,677 +0,0 @@
/* GNU dump extensions to tar.
Copyright (C) 1988, 1992, 1993 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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <time.h>
time_t time ();
#include "tar.h"
#include "port.h"
#ifndef S_ISLNK
#define lstat stat
#endif
extern time_t new_time;
extern FILE *msg_file;
void addname ();
int check_exclude ();
extern PTR ck_malloc ();
extern PTR ck_realloc ();
int confirm ();
extern PTR init_buffer ();
extern char *get_buffer ();
int is_dot_or_dotdot ();
extern void add_buffer ();
extern void flush_buffer ();
void name_gather ();
int recursively_delete ();
void skip_file ();
char *un_quote_string ();
extern char *new_name ();
static void add_dir_name ();
struct dirname
{
struct dirname *next;
char *name;
char *dir_text;
int dev;
int ino;
int allnew;
};
static struct dirname *dir_list;
static time_t this_time;
void
add_dir (name, dev, ino, text)
char *name;
char *text;
dev_t dev;
ino_t ino;
{
struct dirname *dp;
dp = (struct dirname *) ck_malloc (sizeof (struct dirname));
if (!dp)
abort ();
dp->next = dir_list;
dir_list = dp;
dp->dev = dev;
dp->ino = ino;
dp->name = ck_malloc (strlen (name) + 1);
strcpy (dp->name, name);
dp->dir_text = text;
dp->allnew = 0;
}
void
read_dir_file ()
{
int dev;
int ino;
char *strp;
FILE *fp;
char buf[512];
static char *path = 0;
if (path == 0)
path = ck_malloc (PATH_MAX);
time (&this_time);
if (gnu_dumpfile[0] != '/')
{
#if defined(__MSDOS__) || defined(HAVE_GETCWD) || defined(_POSIX_VERSION)
if (!getcwd (path, PATH_MAX))
{
msg ("Couldn't get current directory.");
exit (EX_SYSTEM);
}
#else
char *getwd ();
if (!getwd (path))
{
msg ("Couldn't get current directory: %s", path);
exit (EX_SYSTEM);
}
#endif
/* If this doesn't fit, we're in serious trouble */
strcat (path, "/");
strcat (path, gnu_dumpfile);
gnu_dumpfile = path;
}
fp = fopen (gnu_dumpfile, "r");
if (fp == 0 && errno != ENOENT)
{
msg_perror ("Can't open %s", gnu_dumpfile);
return;
}
if (!fp)
return;
fgets (buf, sizeof (buf), fp);
if (!f_new_files)
{
f_new_files++;
new_time = atol (buf);
}
while (fgets (buf, sizeof (buf), fp))
{
strp = &buf[strlen (buf)];
if (strp[-1] == '\n')
strp[-1] = '\0';
strp = buf;
dev = atol (strp);
while (isdigit (*strp))
strp++;
ino = atol (strp);
while (isspace (*strp))
strp++;
while (isdigit (*strp))
strp++;
strp++;
add_dir (un_quote_string (strp), dev, ino, (char *) 0);
}
fclose (fp);
}
void
write_dir_file ()
{
FILE *fp;
struct dirname *dp;
char *str;
extern char *quote_copy_string ();
fp = fopen (gnu_dumpfile, "w");
if (fp == 0)
{
msg_perror ("Can't write to %s", gnu_dumpfile);
return;
}
fprintf (fp, "%lu\n", this_time);
for (dp = dir_list; dp; dp = dp->next)
{
if (!dp->dir_text)
continue;
str = quote_copy_string (dp->name);
if (str)
{
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, str);
free (str);
}
else
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, dp->name);
}
fclose (fp);
}
struct dirname *
get_dir (name)
char *name;
{
struct dirname *dp;
for (dp = dir_list; dp; dp = dp->next)
{
if (!strcmp (dp->name, name))
return dp;
}
return 0;
}
/* Collect all the names from argv[] (or whatever), then expand them into
a directory tree, and put all the directories at the beginning. */
void
collect_and_sort_names ()
{
struct name *n, *n_next;
int num_names;
struct stat statbuf;
int name_cmp ();
char *merge_sort ();
name_gather ();
if (gnu_dumpfile)
read_dir_file ();
if (!namelist)
addname (".");
for (n = namelist; n; n = n_next)
{
n_next = n->next;
if (n->found || n->dir_contents)
continue;
if (n->regexp) /* FIXME just skip regexps for now */
continue;
if (n->change_dir)
if (chdir (n->change_dir) < 0)
{
msg_perror ("can't chdir to %s", n->change_dir);
continue;
}
#ifdef AIX
if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK))
#else
if (lstat (n->name, &statbuf) < 0)
#endif /* AIX */
{
msg_perror ("can't stat %s", n->name);
continue;
}
if (S_ISDIR (statbuf.st_mode))
{
n->found++;
add_dir_name (n->name, statbuf.st_dev);
}
}
num_names = 0;
for (n = namelist; n; n = n->next)
num_names++;
namelist = (struct name *) merge_sort ((PTR) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, name_cmp);
for (n = namelist; n; n = n->next)
{
n->found = 0;
}
if (gnu_dumpfile)
write_dir_file ();
}
int
name_cmp (n1, n2)
struct name *n1, *n2;
{
if (n1->found)
{
if (n2->found)
return strcmp (n1->name, n2->name);
else
return -1;
}
else if (n2->found)
return 1;
else
return strcmp (n1->name, n2->name);
}
int
dirent_cmp (p1, p2)
const PTR p1;
const PTR p2;
{
char *frst, *scnd;
frst = (*(char **) p1) + 1;
scnd = (*(char **) p2) + 1;
return strcmp (frst, scnd);
}
char *
get_dir_contents (p, device)
char *p;
int device;
{
DIR *dirp;
register struct dirent *d;
char *new_buf;
char *namebuf;
int bufsiz;
int len;
PTR the_buffer;
char *buf;
size_t n_strs;
/* int n_size;*/
char *p_buf;
char **vec, **p_vec;
extern int errno;
errno = 0;
dirp = opendir (p);
bufsiz = strlen (p) + NAMSIZ;
namebuf = ck_malloc (bufsiz + 2);
if (!dirp)
{
if (errno)
msg_perror ("can't open directory %s", p);
else
msg ("error opening directory %s", p);
new_buf = NULL;
}
else
{
struct dirname *dp;
int all_children;
dp = get_dir (p);
all_children = dp ? dp->allnew : 0;
(void) strcpy (namebuf, p);
if (p[strlen (p) - 1] != '/')
(void) strcat (namebuf, "/");
len = strlen (namebuf);
the_buffer = init_buffer ();
while (d = readdir (dirp))
{
struct stat hs;
/* Skip . and .. */
if (is_dot_or_dotdot (d->d_name))
continue;
if (NLENGTH (d) + len >= bufsiz)
{
bufsiz += NAMSIZ;
namebuf = ck_realloc (namebuf, bufsiz + 2);
}
(void) strcpy (namebuf + len, d->d_name);
#ifdef AIX
if (0 != f_follow_links ?
statx (namebuf, &hs, STATSIZE, STX_HIDDEN) :
statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
#else
if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
#endif
{
msg_perror ("can't stat %s", namebuf);
continue;
}
if ((f_local_filesys && device != hs.st_dev)
|| (f_exclude && check_exclude (namebuf)))
add_buffer (the_buffer, "N", 1);
#ifdef AIX
else if (S_ISHIDDEN (hs.st_mode))
{
add_buffer (the_buffer, "D", 1);
strcat (d->d_name, "A");
d->d_namlen++;
}
#endif /* AIX */
else if (S_ISDIR (hs.st_mode))
{
if (dp = get_dir (namebuf))
{
if (dp->dev != hs.st_dev
|| dp->ino != hs.st_ino)
{
if (f_verbose)
msg ("directory %s has been renamed.", namebuf);
dp->allnew = 1;
dp->dev = hs.st_dev;
dp->ino = hs.st_ino;
}
dp->dir_text = "";
}
else
{
if (f_verbose)
msg ("Directory %s is new", namebuf);
add_dir (namebuf, hs.st_dev, hs.st_ino, "");
dp = get_dir (namebuf);
dp->allnew = 1;
}
if (all_children)
dp->allnew = 1;
add_buffer (the_buffer, "D", 1);
}
else if (!all_children
&& f_new_files
&& new_time > hs.st_mtime
&& (f_new_files > 1
|| new_time > hs.st_ctime))
add_buffer (the_buffer, "N", 1);
else
add_buffer (the_buffer, "Y", 1);
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
}
add_buffer (the_buffer, "\000\000", 2);
closedir (dirp);
/* Well, we've read in the contents of the dir, now sort them */
buf = get_buffer (the_buffer);
if (buf[0] == '\0')
{
flush_buffer (the_buffer);
new_buf = NULL;
}
else
{
n_strs = 0;
for (p_buf = buf; *p_buf;)
{
int tmp;
tmp = strlen (p_buf) + 1;
n_strs++;
p_buf += tmp;
}
vec = (char **) ck_malloc (sizeof (char *) * (n_strs + 1));
for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
*p_vec++ = p_buf;
*p_vec = 0;
qsort ((PTR) vec, n_strs, sizeof (char *), dirent_cmp);
new_buf = (char *) ck_malloc (p_buf - buf + 2);
for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
{
char *p_tmp;
for (p_tmp = *p_vec; *p_buf++ = *p_tmp++;)
;
}
*p_buf++ = '\0';
free (vec);
flush_buffer (the_buffer);
}
}
free (namebuf);
return new_buf;
}
/* p is a directory. Add all the files in P to the namelist. If any of the
files is a directory, recurse on the subdirectory. . . */
static void
add_dir_name (p, device)
char *p;
int device;
{
char *new_buf;
char *p_buf;
char *namebuf;
int buflen;
register int len;
int sublen;
/* PTR the_buffer;*/
/* char *buf;*/
/* char **vec,**p_vec;*/
/* int n_strs,n_size;*/
struct name *n;
int dirent_cmp ();
new_buf = get_dir_contents (p, device);
for (n = namelist; n; n = n->next)
{
if (!strcmp (n->name, p))
{
n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
break;
}
}
if (new_buf)
{
len = strlen (p);
buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
namebuf = ck_malloc (buflen + 1);
(void) strcpy (namebuf, p);
if (namebuf[len - 1] != '/')
{
namebuf[len++] = '/';
namebuf[len] = '\0';
}
for (p_buf = new_buf; *p_buf; p_buf += sublen + 1)
{
sublen = strlen (p_buf);
if (*p_buf == 'D')
{
if (len + sublen >= buflen)
{
buflen += NAMSIZ;
namebuf = ck_realloc (namebuf, buflen + 1);
}
(void) strcpy (namebuf + len, p_buf + 1);
addname (namebuf);
add_dir_name (namebuf, device);
}
}
free (namebuf);
}
}
/* Returns non-zero if p is . or .. This could be a macro for speed. */
int
is_dot_or_dotdot (p)
char *p;
{
return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')));
}
void
gnu_restore (skipcrud)
int skipcrud;
{
char *current_dir;
/* int current_dir_length; */
char *archive_dir;
/* int archive_dir_length; */
PTR the_buffer;
char *p;
DIR *dirp;
struct dirent *d;
char *cur, *arc;
extern struct stat hstat; /* Stat struct corresponding */
long size, copied;
char *from, *to;
extern union record *head;
dirp = opendir (skipcrud + current_file_name);
if (!dirp)
{
/* The directory doesn't exist now. It'll be created.
In any case, we don't have to delete any files out
of it */
skip_file ((long) hstat.st_size);
return;
}
the_buffer = init_buffer ();
while (d = readdir (dirp))
{
if (is_dot_or_dotdot (d->d_name))
continue;
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
}
closedir (dirp);
add_buffer (the_buffer, "", 1);
current_dir = get_buffer (the_buffer);
archive_dir = (char *) ck_malloc (hstat.st_size);
if (archive_dir == 0)
{
msg ("Can't allocate %d bytes for restore", hstat.st_size);
skip_file ((long) hstat.st_size);
return;
}
to = archive_dir;
for (size = hstat.st_size; size > 0; size -= copied)
{
from = findrec ()->charptr;
if (!from)
{
msg ("Unexpected EOF in archive\n");
break;
}
copied = endofrecs ()->charptr - from;
if (copied > size)
copied = size;
bcopy ((PTR) from, (PTR) to, (int) copied);
to += copied;
userec ((union record *) (from + copied - 1));
}
for (cur = current_dir; *cur; cur += strlen (cur) + 1)
{
for (arc = archive_dir; *arc; arc += strlen (arc) + 1)
{
arc++;
if (!strcmp (arc, cur))
break;
}
if (*arc == '\0')
{
p = new_name (skipcrud + current_file_name, cur);
if (f_confirm && !confirm ("delete", p))
{
free (p);
continue;
}
if (f_verbose)
fprintf (msg_file, "%s: deleting %s\n", tar, p);
if (recursively_delete (p))
{
msg ("%s: Error while deleting %s\n", tar, p);
}
free (p);
}
}
flush_buffer (the_buffer);
free (archive_dir);
}
int
recursively_delete (path)
char *path;
{
struct stat sbuf;
DIR *dirp;
struct dirent *dp;
char *path_buf;
/* int path_len; */
if (lstat (path, &sbuf) < 0)
return 1;
if (S_ISDIR (sbuf.st_mode))
{
/* path_len=strlen(path); */
dirp = opendir (path);
if (dirp == 0)
return 1;
while (dp = readdir (dirp))
{
if (is_dot_or_dotdot (dp->d_name))
continue;
path_buf = new_name (path, dp->d_name);
if (recursively_delete (path_buf))
{
free (path_buf);
closedir (dirp);
return 1;
}
free (path_buf);
}
closedir (dirp);
if (rmdir (path) < 0)
return 1;
return 0;
}
if (unlink (path) < 0)
return 1;
return 0;
}

File diff suppressed because it is too large Load Diff

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 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,17 +26,30 @@
#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 */
static union block *recent_global_header; /* Recent global header block */
static uintmax_t from_header (const char *, size_t, const char *,
uintmax_t, uintmax_t, bool, bool);
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
#define MODE_FROM_HEADER(where, hbits) \
mode_from_header (where, sizeof (where), hbits)
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
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, 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 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] =
@@ -60,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))
@@ -77,7 +178,8 @@ read_and (void (*do_something) (void))
prev_status = status;
tar_stat_destroy (&current_stat_info);
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
switch (status)
{
case HEADER_STILL_UNREAD:
@@ -88,7 +190,8 @@ read_and (void (*do_something) (void))
/* Valid header. We should decode next field (mode) first.
Ensure incoming names are null terminated. */
decode_header (current_header, &current_stat_info,
&current_format, 1);
if (! name_match (current_stat_info.file_name)
|| (NEWER_OPTION_INITIALIZED (newer_mtime_option)
/* FIXME: We get mtime now, and again later; this causes
@@ -100,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)
{
@@ -114,13 +218,13 @@ read_and (void (*do_something) (void))
quotearg_colon (current_stat_info.file_name)));
/* Fall through. */
default:
decode_header (current_header,
&current_stat_info, &current_format, 0);
skip_member ();
continue;
}
}
transform_stat_info (current_header->header.typeflag,
&current_stat_info);
(*do_something) ();
continue;
@@ -138,11 +242,13 @@ read_and (void (*do_something) (void))
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
break;
}
status = prev_status;
@@ -204,11 +310,10 @@ void
list_archive (void)
{
off_t block_ordinal = current_block_ordinal ();
/* Print the header block. */
decode_header (current_header, &current_stat_info, &current_format, 0);
/* Print the header block. */
if (verbose_option)
print_header (&current_stat_info, block_ordinal);
print_header (&current_stat_info, current_header, block_ordinal);
if (incremental_option)
{
@@ -240,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;
@@ -265,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;
@@ -279,20 +383,29 @@ tar_checksum (union block *header, bool silent)
}
/* Read a block that's supposed to be a header block. Return its
address in "current_header", and if it is good, the file's size
and names (file name, link name) in *info.
address in *RETURN_BLOCK, and if it is good, the file's size
and names (file name, link name) in *INFO.
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
block full of zeros (EOF marker).
Return one of enum read_header describing the status of the
operation.
If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the
GNU long name and link headers into later headers.
The MODE parameter instructs read_header what to do with special
header blocks, i.e.: extended POSIX, GNU long name or long link,
etc.:
You must always set_next_block_after(current_header) to skip past
read_header_auto process them automatically,
read_header_x_raw when a special header is read, return
HEADER_SUCCESS_EXTENDED without actually
processing the header,
read_header_x_global when a POSIX global header is read,
decode it and return HEADER_SUCCESS_EXTENDED.
You must always set_next_block_after(*return_block) to skip past
the header which this routine reads. */
enum read_header
read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
read_header (union block **return_block, struct tar_stat_info *info,
enum read_header_mode mode)
{
union block *header;
union block *header_copy;
@@ -309,7 +422,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
enum read_header status;
header = find_next_block ();
current_header = header;
*return_block = header;
if (!header)
return HEADER_END_OF_FILE;
@@ -321,7 +434,11 @@ read_header_primitive (bool raw_extended_headers, 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
@@ -329,7 +446,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|| header->header.typeflag == XGLTYPE
|| header->header.typeflag == SOLARIS_XHDTYPE)
{
if (raw_extended_headers)
if (mode == read_header_x_raw)
return HEADER_SUCCESS_EXTENDED;
else if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK)
@@ -347,15 +464,13 @@ read_header_primitive (bool raw_extended_headers, 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;
}
@@ -391,11 +506,18 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
else if (header->header.typeflag == XGLTYPE)
{
struct xheader xhdr;
if (!recent_global_header)
recent_global_header = xmalloc (sizeof *recent_global_header);
memcpy (recent_global_header, header,
sizeof *recent_global_header);
memset (&xhdr, 0, sizeof xhdr);
xheader_read (&xhdr, header,
OFF_FROM_HEADER (header->header.size));
xheader_decode_global (&xhdr);
xheader_destroy (&xhdr);
if (mode == read_header_x_global)
return HEADER_SUCCESS_EXTENDED;
}
/* Loop! */
@@ -404,11 +526,10 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
else
{
char const *name;
struct posix_header const *h = &current_header->header;
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)
{
@@ -439,8 +560,7 @@ read_header_primitive (bool raw_extended_headers, 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)
{
@@ -463,53 +583,6 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
}
}
enum read_header
read_header (bool raw_extended_headers)
{
return read_header_primitive (raw_extended_headers, &current_stat_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;
}
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
@@ -530,6 +603,8 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group)
{
enum archive_format format;
bool hbits;
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
if (strcmp (header->header.magic, TMAGIC) == 0)
{
@@ -544,13 +619,15 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
else
format = USTAR_FORMAT;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
format = OLDGNU_FORMAT;
else if (strcmp (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC)
== 0)
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
else
format = V7_FORMAT;
*format_pointer = format;
stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
stat_info->stat.st_mode = mode;
stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
stat_info->mtime.tv_nsec = 0;
assign_string (&stat_info->uname,
@@ -558,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);
@@ -627,34 +706,34 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|| stat_info->dumpdir)
stat_info->is_dumpdir = true;
}
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. */
@@ -667,12 +746,13 @@ from_header (char const *where0, size_t digs, char const *type,
{
if (type && !silent)
ERROR ((0, 0,
/* TRANSLATORS: %s is type of the value (gid_t, uid_t, etc.) */
/* TRANSLATORS: %s is type of the value (gid_t, uid_t,
etc.) */
_("Blanks in header where numeric %s value expected"),
type));
return -1;
}
if (!ISSPACE ((unsigned char) *where))
if (!isspace ((unsigned char) *where))
break;
where++;
}
@@ -681,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;
}
@@ -712,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++;
@@ -725,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;
}
}
@@ -805,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)
{
@@ -825,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.) */
@@ -837,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)
{
@@ -859,50 +939,52 @@ from_header (char const *where0, size_t digs, char const *type,
return -1;
}
gid_t
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);
}
major_t
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);
}
minor_t
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);
}
mode_t
mode_from_header (const char *p, size_t s)
/* Convert P to the file mode, as understood by tar.
Set *HBITS if there are any unrecognized bits. */
static mode_t
mode_from_header (const char *p, size_t s, bool *hbits)
{
/* Do not complain about unrecognized mode bits. */
unsigned u = from_header (p, s, "mode_t",
- (uintmax_t) TYPE_MINIMUM (mode_t),
TYPE_MAXIMUM (uintmax_t), false, false);
return ((u & TSUID ? S_ISUID : 0)
| (u & TSGID ? S_ISGID : 0)
| (u & TSVTX ? S_ISVTX : 0)
| (u & TUREAD ? S_IRUSR : 0)
| (u & TUWRITE ? S_IWUSR : 0)
| (u & TUEXEC ? S_IXUSR : 0)
| (u & TGREAD ? S_IRGRP : 0)
| (u & TGWRITE ? S_IWGRP : 0)
| (u & TGEXEC ? S_IXGRP : 0)
| (u & TOREAD ? S_IROTH : 0)
| (u & TOWRITE ? S_IWOTH : 0)
| (u & TOEXEC ? S_IXOTH : 0));
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)
| (u & TUREAD ? S_IRUSR : 0)
| (u & TUWRITE ? S_IWUSR : 0)
| (u & TUEXEC ? S_IXUSR : 0)
| (u & TGREAD ? S_IRGRP : 0)
| (u & TGWRITE ? S_IWGRP : 0)
| (u & TGEXEC ? S_IXGRP : 0)
| (u & TOREAD ? S_IROTH : 0)
| (u & TOWRITE ? S_IWOTH : 0)
| (u & TOEXEC ? S_IXOTH : 0));
*hbits = (u & ~07777) != 0;
return mode;
}
off_t
@@ -910,38 +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);
}
size_t
size_from_header (const char *p, size_t s)
{
return from_header (p, s, "size_t", (uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (size_t), false, false);
}
time_t
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);
}
uid_t
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);
}
@@ -1013,9 +1088,6 @@ tartime (struct timespec t, bool full_time)
they shouldn't. Unix tar is pretty random here anyway. */
/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
HEAD_STANDARD, which must be set up in advance. Not very clean.. */
/* Width of "user/group size", with initial value chosen
heuristically. This grows as needed, though this may cause some
stairstepping in the output. Make it too small and the output will
@@ -1028,16 +1100,20 @@ static int ugswidth = 19;
USGWIDTH, some stairstepping may occur. */
static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;
void
print_header (struct tar_stat_info *st, off_t block_ordinal)
static bool volume_label_printed = false;
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 */
@@ -1045,9 +1121,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
int pad;
int sizelen;
if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR)
return;
if (show_transformed_names_option)
temp_name = st->file_name ? st->file_name : st->orig_file_name;
else
@@ -1067,16 +1140,20 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
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
{
/* File type and modes. */
modes[0] = '?';
switch (current_header->header.typeflag)
switch (blk->header.typeflag)
{
case GNUTYPE_VOLHDR:
volume_label_printed = true;
modes[0] = 'V';
break;
@@ -1093,9 +1170,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
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';
@@ -1125,9 +1200,12 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
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, false);
time_stamp = tartime (st->mtime, full_time_option);
time_stamp_len = strlen (time_stamp);
if (datewidth < time_stamp_len)
datewidth = time_stamp_len;
@@ -1144,19 +1222,13 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Try parsing it as an unsigned integer first, and as a
uid_t if that fails. This method can list positive user
ids that are too large to fit in a uid_t. */
uintmax_t u = from_header (current_header->header.uid,
sizeof current_header->header.uid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
uintmax_t u = from_header (blk->header.uid,
sizeof blk->header.uid, 0,
0, UINTMAX_MAX,
false, false);
if (u != -1)
user = STRINGIFY_BIGINT (u, uform);
else
{
sprintf (uform, "%ld",
(long) UID_FROM_HEADER (current_header->header.uid));
user = uform;
}
user = (u != -1
? STRINGIFY_BIGINT (u, uform)
: imaxtostr (UID_FROM_HEADER (blk->header.uid), uform));
}
if (st->gname
@@ -1169,24 +1241,18 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Try parsing it as an unsigned integer first, and as a
gid_t if that fails. This method can list positive group
ids that are too large to fit in a gid_t. */
uintmax_t g = from_header (current_header->header.gid,
sizeof current_header->header.gid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
uintmax_t g = from_header (blk->header.gid,
sizeof blk->header.gid, 0,
0, UINTMAX_MAX,
false, false);
if (g != -1)
group = STRINGIFY_BIGINT (g, gform);
else
{
sprintf (gform, "%ld",
(long) GID_FROM_HEADER (current_header->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. */
switch (current_header->header.typeflag)
switch (blk->header.typeflag)
{
case CHRTYPE:
case BLKTYPE:
@@ -1215,8 +1281,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
datewidth, time_stamp);
fprintf (stdlis, " %s", quotearg (temp_name));
if (show_transformed_names_option && st->had_trailing_slash)
fputc ('/', stdlis);
switch (current_header->header.typeflag)
switch (blk->header.typeflag)
{
case SYMTYPE:
fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
@@ -1229,7 +1297,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
default:
{
char type_string[2];
type_string[0] = current_header->header.typeflag;
type_string[0] = blk->header.typeflag;
type_string[1] = '\0';
fprintf (stdlis, _(" unknown file type %s\n"),
quote (type_string));
@@ -1263,13 +1331,48 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
case GNUTYPE_MULTIVOL:
strcpy (size,
STRINGIFY_BIGINT
(UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset),
(UINTMAX_FROM_HEADER (blk->oldgnu_header.offset),
uintbuf));
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
break;
}
}
fflush (stdlis);
xattrs_print (st);
}
static void
print_volume_label (void)
{
struct tar_stat_info vstat;
union block vblk;
enum archive_format dummy;
memset (&vblk, 0, sizeof (vblk));
vblk.header.typeflag = GNUTYPE_VOLHDR;
if (recent_global_header)
memcpy (vblk.header.mtime, recent_global_header->header.mtime,
sizeof vblk.header.mtime);
tar_stat_init (&vstat);
assign_string (&vstat.file_name, ".");
decode_header (&vblk, &vstat, &dummy, 0);
assign_string (&vstat.file_name, volume_label);
simple_print_header (&vstat, &vblk, 0);
tar_stat_destroy (&vstat);
}
void
print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal)
{
if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
{
print_volume_label ();
volume_label_printed = true;
}
simple_print_header (st, blk, block_ordinal);
}
/* Print a similar line when we make a directory automatically. */
@@ -1292,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));
}
}
@@ -1303,7 +1406,7 @@ skip_file (off_t size)
{
union block *x;
/* FIXME: Make sure mv_begin is always called before it */
/* FIXME: Make sure mv_begin_read is always called before it */
if (seekable_archive)
{
@@ -1338,7 +1441,7 @@ skip_member (void)
char save_typeflag = current_header->header.typeflag;
set_next_block_after (current_header);
mv_begin (&current_stat_info);
mv_begin_read (&current_stat_info);
if (current_stat_info.is_sparse)
sparse_skip_file (&current_stat_info);
@@ -1348,3 +1451,34 @@ skip_member (void)
mv_end ();
}
}
void
test_archive_label (void)
{
base64_init ();
name_gather ();
open_archive (ACCESS_READ);
if (read_header (&current_header, &current_stat_info, read_header_auto)
== HEADER_SUCCESS)
{
decode_header (current_header,
&current_stat_info, &current_format, 0);
if (current_header->header.typeflag == GNUTYPE_VOLHDR)
assign_string (&volume_label, current_header->header.name);
if (volume_label)
{
if (verbose_option)
print_volume_label ();
if (!name_match (volume_label) && multi_volume_option)
{
char *s = drop_volume_label_suffix (volume_label);
name_match (s);
free (s);
}
}
}
close_archive ();
label_notfound ();
}

View File

@@ -1,57 +0,0 @@
# Makefile for GNU tar on MS-DOS using Turbo C 2.0.
# Copyright (C) 1991 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 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
CC = tcc
RM = rm -f
MODEL = m
DEFS = -DNONAMES -DNO_REMOTE -DNO_MTIO -DSTDC_HEADERS -m$(MODEL) -Dmain=_main
LIBS =
DEF_AR_FILE = tar.out
DEFBLOCKING = 20
CFLAGS = -I. $(DEFS) \
-DDEF_AR_FILE="$(DEF_AR_FILE)" \
-DDEFBLOCKING=$(DEFBLOCKING)
LDFLAGS = -m$(MODEL)
OBJ1 = tar.obj create.obj extract.obj buffer.obj getoldopt.obj update.obj gnu.obj mangle.obj
OBJ2 = version.obj list.obj names.obj diffarch.obj port.obj wildmat.obj getopt.obj
OBJ3 = getopt1.obj regex.obj getdate.obj alloca.obj tcexparg.obj msd_dir.obj
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
all: tar
tar: testpad.h getdate.c $(OBJS)
$(RM) testpad.obj
$(CC) $(LDFLAGS) -etar *.obj $(LIBS)
.c.obj:
$(CC) -c $(CFLAGS) $<
testpad.h: testpad.exe
testpad
testpad.exe: testpad.c
$(CC) $(LDFLAGS) -etestpad testpad.c $(LIBS)
clean:
$(RM) errs *.obj tar testpad testpad.h
distclean: clean
realclean: clean

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 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,25 +14,23 @@
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"
#include <quotearg.h>
#include <save-cwd.h>
#include <xgetcwd.h>
#include <unlinkdir.h>
#include <utimens.h>
#if HAVE_STROPTS_H
# include <stropts.h>
#endif
#if HAVE_SYS_FILIO_H
# include <sys/filio.h>
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
#endif
static const char *tar_getcdpath (int);
/* Handling strings. */
@@ -41,11 +39,13 @@
void
assign_string (char **string, const char *value)
{
if (*string)
free (*string);
free (*string);
*string = value ? xstrdup (value) : 0;
}
#if 0
/* This function is currently unused; perhaps it should be removed? */
/* Allocate a copy of the string quoted as in C, and returns that. If
the string does not have to be quoted, it returns a null pointer.
The allocated copy should normally be freed with free() after the
@@ -58,7 +58,7 @@ assign_string (char **string, const char *value)
when reading directory files. This means that we can't use
quotearg, as quotearg is locale-dependent and is meant for human
consumption. */
char *
static char *
quote_copy_string (const char *string)
{
const char *source = string;
@@ -99,6 +99,7 @@ quote_copy_string (const char *string)
}
return 0;
}
#endif
/* Takes a quoted C string (like those produced by quote_copy_string)
and turns it back into the un-quoted original. This is done in
@@ -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. */
@@ -214,9 +215,194 @@ unquote_string (char *string)
*destination = '\0';
return result;
}
/* Zap trailing slashes. */
char *
zap_slashes (char *name)
{
char *q;
if (!name || *name == 0)
return name;
q = name + strlen (name) - 1;
while (q > name && ISSLASH (*q))
*q-- = '\0';
return 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. */
void
normalize_filename_x (char *file_name)
{
char *name = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
char *p;
char const *q;
char c;
/* Don't squeeze leading "//" to "/", on hosts where they're distinct. */
name += (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& ISSLASH (*name) && ISSLASH (name[1]) && ! ISSLASH (name[2]));
/* Omit redundant leading "." components. */
for (q = p = name; (*p = *q) == '.' && ISSLASH (q[1]); p += !*q)
for (q += 2; ISSLASH (*q); q++)
continue;
/* Copy components from Q to P, omitting redundant slashes and
internal "." components. */
while ((*p++ = c = *q++) != '\0')
if (ISSLASH (c))
while (ISSLASH (q[*q == '.']))
q += (*q == '.') + 1;
/* Omit redundant trailing "." component and slash. */
if (2 < p - name)
{
p -= p[-2] == '.' && ISSLASH (p[-3]);
p -= 2 < p - name && ISSLASH (p[-2]);
p[-1] = '\0';
}
}
/* Normalize NAME by removing redundant slashes and "." components,
including redundant trailing slashes.
Return a normalized newly-allocated copy. */
char *
normalize_filename (int cdidx, const char *name)
{
char *copy = NULL;
if (IS_RELATIVE_FILE_NAME (name))
{
/* Set COPY to the absolute path for this name.
FIXME: There should be no need to get the absolute file name.
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)
copy = xstrdup (name);
normalize_filename_x (copy);
return copy;
}
void
replace_prefix (char **pname, const char *samp, size_t slen,
const char *repl, size_t rlen)
{
char *name = *pname;
size_t nlen = strlen (name);
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
{
if (rlen > slen)
{
name = xrealloc (name, nlen - slen + rlen + 1);
*pname = name;
}
memmove (name + rlen, name + slen, nlen - slen + 1);
memcpy (name, repl, rlen);
}
}
/* 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. */
@@ -257,6 +443,10 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
char *np;
bool negative = s < 0;
/* ignore invalid values of ns */
if (BILLION <= ns || ns < 0)
ns = 0;
if (negative && ns != 0)
{
s++;
@@ -269,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. */
@@ -277,7 +545,7 @@ static char *before_backup_name;
static char *after_backup_name;
/* Return 1 if FILE_NAME is obviously "." or "/". */
static bool
bool
must_be_dot_or_slash (char const *file_name)
{
file_name += FILE_SYSTEM_PREFIX_LEN (file_name);
@@ -318,7 +586,7 @@ safer_rmdir (const char *file_name)
return -1;
}
return rmdir (file_name);
return unlinkat (chdir_fd, file_name, AT_REMOVEDIR);
}
/* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory,
@@ -338,7 +606,7 @@ remove_any_file (const char *file_name, enum remove_option option)
if (try_unlink_first)
{
if (unlink (file_name) == 0)
if (unlinkat (chdir_fd, file_name, 0) == 0)
return 1;
/* POSIX 1003.1-2001 requires EPERM when attempting to unlink a
@@ -354,7 +622,7 @@ remove_any_file (const char *file_name, enum remove_option option)
switch (errno)
{
case ENOTDIR:
return !try_unlink_first && unlink (file_name) == 0;
return !try_unlink_first && unlinkat (chdir_fd, file_name, 0) == 0;
case 0:
case EEXIST:
@@ -371,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;
@@ -417,12 +685,21 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
{
struct stat file_stat;
assign_string (&before_backup_name, file_name);
/* A run situation may exist between Emacs or other GNU programs trying to
make a backup for the same file simultaneously. If theoretically
possible, real problems are unlikely. Doing any better would require a
convention, GNU-wide, for all programs doing backups. */
assign_string (&after_backup_name, 0);
/* Check if we really need to backup the file. */
if (this_is_the_archive && _remdev (file_name))
return true;
if (stat (file_name, &file_stat))
if (deref_stat (file_name, &file_stat) != 0)
{
if (errno == ENOENT)
return true;
@@ -438,19 +715,12 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
return true;
assign_string (&before_backup_name, file_name);
/* A run situation may exist between Emacs or other GNU programs trying to
make a backup for the same file simultaneously. If theoretically
possible, real problems are unlikely. Doing any better would require a
convention, GNU-wide, for all programs doing backups. */
assign_string (&after_backup_name, 0);
after_backup_name = find_backup_file_name (file_name, backup_type);
if (! after_backup_name)
xalloc_die ();
if (rename (before_backup_name, after_backup_name) == 0)
if (renameat (chdir_fd, before_backup_name, chdir_fd, after_backup_name)
== 0)
{
if (verbose_option)
fprintf (stdlis, _("Renaming %s to %s\n"),
@@ -477,7 +747,8 @@ undo_last_backup (void)
{
if (after_backup_name)
{
if (rename (after_backup_name, before_backup_name) != 0)
if (renameat (chdir_fd, after_backup_name, chdir_fd, before_backup_name)
!= 0)
{
int e = errno;
ERROR ((0, e, _("%s: Cannot rename to %s"),
@@ -492,70 +763,142 @@ undo_last_backup (void)
}
}
/* Depending on DEREF, apply either stat or lstat to (NAME, BUF). */
/* Apply either stat or lstat to (NAME, BUF), depending on the
presence of the --dereference option. NAME is relative to the
most-recent argument to chdir_do. */
int
deref_stat (bool deref, char const *name, struct stat *buf)
deref_stat (char const *name, struct stat *buf)
{
return deref ? stat (name, buf) : lstat (name, buf);
return fstatat (chdir_fd, name, buf, fstatat_flags);
}
/* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not
possible to do by itself, set its access and data modification
times to TIMESPEC[0] and TIMESPEC[1], respectively. */
int
set_file_atime (int fd, char const *file, struct timespec const timespec[2])
/* 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)
{
#ifdef _FIOSATIME
if (0 <= fd)
size_t bytes = safe_read (fd, buf, count);
#if defined F_SETFL && O_NONBLOCK
if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
{
struct timeval timeval;
timeval.tv_sec = timespec[0].tv_sec;
timeval.tv_usec = timespec[0].tv_nsec / 1000;
if (ioctl (fd, _FIOSATIME, &timeval) == 0)
return 0;
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 gl_futimens (fd, file, timespec);
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
set_file_atime (int fd, int parentfd, char const *file, struct timespec atime)
{
struct timespec ts[2];
ts[0] = atime;
ts[1].tv_nsec = UTIME_OMIT;
return fdutimensat (fd, parentfd, file, ts, fstatat_flags);
}
/* A description of a working directory. */
struct wd
{
/* The directory's name. */
char const *name;
int saved;
struct saved_cwd saved_cwd;
/* "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. */
int fd;
};
/* A vector of chdir targets. wd[0] is the initial working directory. */
static struct wd *wd;
/* The number of working directories in the vector. */
static size_t wds;
static size_t wd_count;
/* The allocated size of the vector. */
static size_t wd_alloc;
/* The maximum number of chdir targets with open directories.
Don't make it too large, as many operating systems have a small
limit on the number of open file descriptors. Also, the current
implementation does not scale well. */
enum { CHDIR_CACHE_SIZE = 16 };
/* Indexes into WD of chdir targets with open file descriptors, sorted
most-recently used first. Zero indexes are unused. */
static int wdcache[CHDIR_CACHE_SIZE];
/* Number of nonzero entries in WDCACHE. */
static size_t wdcache_count;
int
chdir_count (void)
{
if (wd_count == 0)
return wd_count;
return wd_count - 1;
}
/* DIR is the operand of a -C option; add it to vector of chdir targets,
and return the index of its location. */
int
chdir_arg (char const *dir)
{
if (wds == wd_alloc)
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 (! wds)
if (! wd_count)
{
wd[wds].name = ".";
wd[wds].saved = 0;
wds++;
wd[wd_count].name = ".";
wd[wd_count].abspath = xgetcwd ();
wd[wd_count].fd = AT_FDCWD;
wd_count++;
}
}
@@ -567,71 +910,124 @@ chdir_arg (char const *dir)
for (dir += 2; ISSLASH (*dir); dir++)
continue;
if (! dir[dir[0] == '.'])
return wds - 1;
return wd_count - 1;
}
wd[wds].name = dir;
wd[wds].saved = 0;
return wds++;
/* 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++;
}
/* Change to directory I. If I is 0, change to the initial working
directory; otherwise, I must be a value returned by chdir_arg. */
/* Index of current directory. */
int chdir_current;
/* Value suitable for use as the first argument to openat, and in
similar locations for fstatat, etc. This is an open file
descriptor, or AT_FDCWD if the working directory is current. It is
valid until the next invocation of chdir_do. */
int chdir_fd = AT_FDCWD;
/* Change to directory I, in a virtual way. This does not actually
invoke chdir; it merely sets chdir_fd to an int suitable as the
first argument for openat, etc. If I is 0, change to the initial
working directory; otherwise, I must be a value returned by
chdir_arg. */
void
chdir_do (int i)
{
static int previous;
if (previous != i)
if (chdir_current != i)
{
struct wd *prev = &wd[previous];
struct wd *curr = &wd[i];
int fd = curr->fd;
if (! prev->saved)
if (! fd)
{
int err = 0;
prev->saved = 1;
if (save_cwd (&prev->saved_cwd) != 0)
err = errno;
else if (0 <= prev->saved_cwd.desc)
{
/* Make sure we still have at least one descriptor available. */
int fd1 = prev->saved_cwd.desc;
int fd2 = dup (fd1);
if (0 <= fd2)
close (fd2);
else if (errno == EMFILE)
{
/* Force restore_cwd to use chdir_long. */
close (fd1);
prev->saved_cwd.desc = -1;
prev->saved_cwd.name = xgetcwd ();
}
else
err = errno;
}
if (err)
FATAL_ERROR ((0, err, _("Cannot save working directory")));
}
if (curr->saved)
{
if (restore_cwd (&curr->saved_cwd))
FATAL_ERROR ((0, 0, _("Cannot change working directory")));
}
else
{
if (i && ! ISSLASH (curr->name[0]))
if (! IS_ABSOLUTE_FILE_NAME (curr->name))
chdir_do (i - 1);
if (chdir (curr->name) != 0)
chdir_fatal (curr->name);
fd = openat (chdir_fd, curr->name,
open_searchdir_flags & ~ O_NOFOLLOW);
if (fd < 0)
open_fatal (curr->name);
curr->fd = fd;
/* Add I to the cache, tossing out the lowest-ranking entry if the
cache is full. */
if (wdcache_count < CHDIR_CACHE_SIZE)
wdcache[wdcache_count++] = i;
else
{
struct wd *stale = &wd[wdcache[CHDIR_CACHE_SIZE - 1]];
if (close (stale->fd) != 0)
close_diag (stale->name);
stale->fd = 0;
wdcache[CHDIR_CACHE_SIZE - 1] = i;
}
}
previous = i;
if (0 < fd)
{
/* Move the i value to the front of the cache. This is
O(CHDIR_CACHE_SIZE), but the cache is small. */
size_t ci;
int prev = wdcache[0];
for (ci = 1; prev != i; ci++)
{
int cur = wdcache[ci];
wdcache[ci] = prev;
if (cur == i)
break;
prev = cur;
}
wdcache[0] = i;
}
chdir_current = i;
chdir_fd = fd;
}
}
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)
{
@@ -695,6 +1091,21 @@ stat_diag (char const *name)
stat_error (name);
}
void
file_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: File 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)
{
@@ -746,3 +1157,94 @@ page_aligned_alloc (void **ptr, size_t size)
*ptr = xmalloc (size1);
return ptr_align (*ptr, alignment);
}
struct namebuf
{
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 */
};
namebuf_t
namebuf_create (const char *dir)
{
namebuf_t buf = xmalloc (sizeof (*buf));
buf->buffer_size = strlen (dir) + 2;
buf->buffer = xmalloc (buf->buffer_size);
strcpy (buf->buffer, dir);
buf->dir_length = strlen (buf->buffer);
if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
buf->buffer[buf->dir_length++] = DIRECTORY_SEPARATOR;
return buf;
}
void
namebuf_free (namebuf_t buf)
{
free (buf->buffer);
free (buf);
}
char *
namebuf_name (namebuf_t buf, const char *name)
{
size_t len = strlen (name);
while (buf->dir_length + len + 1 >= buf->buffer_size)
buf->buffer = x2realloc (buf->buffer, &buf->buffer_size);
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,218 +0,0 @@
/*
* @(#)msd_dir.c 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*/
#include <sys/types.h>
#include <sys/stat.h>
#include "msd_dir.h"
#ifndef __TURBOC__
#include <malloc.h>
#endif
#include <string.h>
#include <dos.h>
#ifndef NULL
# define NULL 0
#endif /* NULL */
#ifndef MAXPATHLEN
# define MAXPATHLEN 255
#endif /* MAXPATHLEN */
/* attribute stuff */
#define A_RONLY 0x01
#define A_HIDDEN 0x02
#define A_SYSTEM 0x04
#define A_LABEL 0x08
#define A_DIR 0x10
#define A_ARCHIVE 0x20
/* dos call values */
#define DOSI_FINDF 0x4e
#define DOSI_FINDN 0x4f
#define DOSI_SDTA 0x1a
#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
/* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */
#define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR)
/* what find first/next calls look use */
typedef struct {
char d_buf[21];
char d_attribute;
unsigned short d_time;
unsigned short d_date;
long d_size;
char d_name[13];
} Dta_buf;
static char *getdirent();
static void mysetdta();
static void free_dircontents();
static Dta_buf dtabuf;
static Dta_buf *dtapnt = &dtabuf;
static union REGS reg, nreg;
#if defined(M_I86LM)
static struct SREGS sreg;
#endif
DIR *
opendir(name)
char *name;
{
struct stat statb;
DIR *dirp;
char c;
char *s;
struct _dircontents *dp;
char nbuf[MAXPATHLEN + 1];
if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
return (DIR *) NULL;
if (Newisnull(dirp, DIR))
return (DIR *) NULL;
if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
(void) strcat(strcpy(nbuf, name), "\\*.*");
else
(void) strcat(strcpy(nbuf, name), "*.*");
dirp->dd_loc = 0;
mysetdta();
dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
if ((s = getdirent(nbuf)) == (char *) NULL)
return dirp;
do {
if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
{
if (dp)
free((char *) dp);
free_dircontents(dirp->dd_contents);
return (DIR *) NULL;
}
if (dirp->dd_contents)
dirp->dd_cp = dirp->dd_cp->_d_next = dp;
else
dirp->dd_contents = dirp->dd_cp = dp;
(void) strcpy(dp->_d_entry, s);
dp->_d_next = (struct _dircontents *) NULL;
} while ((s = getdirent((char *) NULL)) != (char *) NULL);
dirp->dd_cp = dirp->dd_contents;
return dirp;
}
void
closedir(dirp)
DIR *dirp;
{
free_dircontents(dirp->dd_contents);
free((char *) dirp);
}
struct dirent *
readdir(dirp)
DIR *dirp;
{
static struct dirent dp;
if (dirp->dd_cp == (struct _dircontents *) NULL)
return (struct dirent *) NULL;
dp.d_namlen = dp.d_reclen =
strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
strlwr(dp.d_name); /* JF */
dp.d_ino = 0;
dirp->dd_cp = dirp->dd_cp->_d_next;
dirp->dd_loc++;
return &dp;
}
void
seekdir(dirp, off)
DIR *dirp;
long off;
{
long i = off;
struct _dircontents *dp;
if (off < 0)
return;
for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
;
dirp->dd_loc = off - (i + 1);
dirp->dd_cp = dp;
}
long
telldir(dirp)
DIR *dirp;
{
return dirp->dd_loc;
}
static void
free_dircontents(dp)
struct _dircontents *dp;
{
struct _dircontents *odp;
while (dp) {
if (dp->_d_entry)
free(dp->_d_entry);
dp = (odp = dp)->_d_next;
free((char *) odp);
}
}
static char *
getdirent(dir)
char *dir;
{
if (dir != (char *) NULL) { /* get first entry */
reg.h.ah = DOSI_FINDF;
reg.h.cl = ATTRIBUTES;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dir);
sreg.ds = FP_SEG(dir);
#else
reg.x.dx = (unsigned) dir;
#endif
} else { /* get next entry */
reg.h.ah = DOSI_FINDN;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dtapnt);
sreg.ds = FP_SEG(dtapnt);
#else
reg.x.dx = (unsigned) dtapnt;
#endif
}
#if defined(M_I86LM)
intdosx(&reg, &nreg, &sreg);
#else
intdos(&reg, &nreg);
#endif
if (nreg.x.cflag)
return (char *) NULL;
return dtabuf.d_name;
}
static void
mysetdta()
{
reg.h.ah = DOSI_SDTA;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dtapnt);
sreg.ds = FP_SEG(dtapnt);
intdosx(&reg, &nreg, &sreg);
#else
reg.x.dx = (int) dtapnt;
intdos(&reg, &nreg);
#endif
}

View File

@@ -1,41 +0,0 @@
/*
* @(#)msd_dir.h 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*/
#define rewinddir(dirp) seekdir(dirp, 0L)
#define MAXNAMLEN 12
#ifdef __TURBOC__
typedef int ino_t;
typedef int dev_t;
#endif
struct direct {
ino_t d_ino; /* a bit of a farce */
int d_reclen; /* more farce */
int d_namlen; /* length of d_name */
char d_name[MAXNAMLEN + 1]; /* garentee null termination */
};
struct _dircontents {
char *_d_entry;
struct _dircontents *_d_next;
};
typedef struct _dirdesc {
int dd_id; /* uniquely identify each open directory */
long dd_loc; /* where we are in directory entry is this */
struct _dircontents *dd_contents; /* pointer to contents of dir */
struct _dircontents *dd_cp; /* pointer to current position */
} DIR;
extern DIR *opendir();
extern struct direct *readdir();
extern void seekdir();
extern long telldir();
extern void closedir();

File diff suppressed because it is too large Load Diff

View File

@@ -1,178 +0,0 @@
/* Defines for Sys V style 3-argument open call.
Copyright (C) 1988, 1994, 1995, 1996 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 2, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#if EMUL_OPEN3
/* open3.h -- #defines for the various flags for the Sys V style 3-argument
open() call. On BSD or System 5, the system already has this in an
include file. This file is needed for V7 and MINIX systems for the
benefit of open3() in port.c, a routine that emulates the 3-argument call
using system calls available on V7/MINIX.
Written 1987-06-10 by Richard Todd.
The names have been changed by John Gilmore, 1987-07-31, since Richard
called it "bsdopen", and really this change was introduced in AT&T Unix
systems before BSD picked it up. */
/*-----------------------------------------------------------------------.
| open3 -- routine to emulate the 3-argument open system. |
| |
| open3 (path, flag, mode); |
| |
| Attempts to open the file specified by the given pathname. The |
| following flag bits specify options to the routine. Needless to say, |
| you should only specify one of the first three. Function returns file |
| descriptor if successful, -1 and errno if not. |
`-----------------------------------------------------------------------*/
/* The routine obeys the following mode arguments:
O_RDONLY file open for read only
O_WRONLY file open for write only
O_RDWR file open for both read & write
O_CREAT file is created with specified mode if it needs to be
O_TRUNC if file exists, it is truncated to 0 bytes
O_EXCL used with O_CREAT--routine returns error if file exists */
/* Call that if present in most modern Unix systems. This version attempts
to support all the flag bits except for O_NDELAY and O_APPEND, which are
silently ignored. The emulation is not as efficient as the real thing
(at worst, 4 system calls instead of one), but there's not much I can do
about that. */
/* Array to give arguments to access for various modes FIXME, this table
depends on the specific integer values of O_*, and also contains
integers (args to 'access') that should be #define's. */
static int modes[] =
{
04, /* O_RDONLY */
02, /* O_WRONLY */
06, /* O_RDWR */
06, /* invalid, just cope: O_WRONLY+O_RDWR */
};
/* Shut off the automatic emulation of open(), we'll need it. */
#undef open
int
open3 (char *path, int flags, int mode)
{
int exists = 1;
int call_creat = 0;
/* We actually do the work by calling the open() or creat() system
call, depending on the flags. Call_creat is true if we will use
creat(), false if we will use open(). */
/* See if the file exists and is accessible in the requested mode.
Strictly speaking we shouldn't be using access, since access checks
against real uid, and the open call should check against euid. Most
cases real uid == euid, so it won't matter. FIXME. FIXME, the
construction "flags & 3" and the modes table depends on the specific
integer values of the O_* #define's. Foo! */
if (access (path, modes[flags & 3]) < 0)
{
if (errno == ENOENT)
{
/* The file does not exist. */
exists = 0;
}
else
{
/* Probably permission violation. */
if (flags & O_EXCL)
{
/* Oops, the file exists, we didn't want it. No matter
what the error, claim EEXIST. */
errno = EEXIST; /* FIXME: errno should be read-only */
}
return -1;
}
}
/* If we have the O_CREAT bit set, check for O_EXCL. */
if (flags & O_CREAT)
{
if ((flags & O_EXCL) && exists)
{
/* Oops, the file exists and we didn't want it to. */
errno = EEXIST; /* FIXME: errno should be read-only */
return -1;
}
/* If the file doesn't exist, be sure to call creat() so that it
will be created with the proper mode. */
if (!exists)
call_creat = 1;
}
else
{
/* If O_CREAT isn't set and the file doesn't exist, error. */
if (!exists)
{
errno = ENOENT; /* FIXME: errno should be read-only */
return -1;
}
}
/* If the O_TRUNC flag is set and the file exists, we want to call
creat() anyway, since creat() guarantees that the file will be
truncated and open()-for-writing doesn't. (If the file doesn't
exist, we're calling creat() anyway and the file will be created
with zero length.) */
if ((flags & O_TRUNC) && exists)
call_creat = 1;
/* Actually do the call. */
if (call_creat)
/* Call creat. May have to close and reopen the file if we want
O_RDONLY or O_RDWR access -- creat() only gives O_WRONLY. */
{
int fd = creat (path, mode);
if (fd < 0 || (flags & O_WRONLY))
return fd;
if (close (fd) < 0)
return -1;
/* Fall out to reopen the file we've created. */
}
/* Calling old open, we strip most of the new flags just in case. */
return open (path, flags & (O_RDONLY | O_WRONLY | O_RDWR | O_BINARY));
}
#endif /* EMUL_OPEN3 */

View File

@@ -1,69 +0,0 @@
/* Defines for Sys V style 3-argument open call.
Copyright (C) 1988 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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* @(#)open3.h 1.4 87/11/11
*
* open3.h -- #defines for the various flags for the Sys V style 3-argument
* open() call. On BSD or System 5, the system already has this in an
* include file. This file is needed for V7 and MINIX systems for the
* benefit of open3() in port.c, a routine that emulates the 3-argument
* call using system calls available on V7/MINIX.
*
* This file is needed by PD tar even if we aren't using the
* emulator, since the #defines for O_WRONLY, etc. are used in
* a couple of places besides the open() calls, (e.g. in the assignment
* to openflag in extract.c). We just #include this rather than
* #ifdef them out.
*
* Written 6/10/87 by rmtodd@uokmax (Richard Todd).
*
* The names have been changed by John Gilmore, 31 July 1987, since
* Richard called it "bsdopen", and really this change was introduced in
* AT&T Unix systems before BSD picked it up.
*/
/* Only one of the next three should be specified */
#define O_RDONLY 0 /* only allow read */
#define O_WRONLY 1 /* only allow write */
#define O_RDWR 2 /* both are allowed */
/* The rest of these can be OR-ed in to the above. */
/*
* O_NDELAY isn't implemented by the emulator. It's only useful (to tar) on
* systems that have named pipes anyway; it prevents tar's hanging by
* opening a named pipe. We #ifndef it because some systems already have
* it defined.
*/
#ifndef O_NDELAY
#define O_NDELAY 4 /* don't block on opening devices that would
* block on open -- ignored by emulator. */
#endif
#define O_CREAT 8 /* create file if needed */
#define O_EXCL 16 /* file cannot already exist */
#define O_TRUNC 32 /* truncate file on open */
#define O_APPEND 64 /* always write at end of file -- ignored by emul */
#ifdef EMUL_OPEN3
/*
* make emulation transparent to rest of file -- redirect all open() calls
* to our routine
*/
#define open open3
#endif

1256
src/port.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,215 +0,0 @@
/* Portability declarations. Requires sys/types.h.
Copyright (C) 1988, 1992 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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#if HAVE_ALLOCA_H
#include <alloca.h>
#else /* not HAVE_ALLOCA_H */
#ifdef _AIX
#pragma alloca
#else /* not _AIX */
char *alloca ();
#endif /* not _AIX */
#endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
#include "pathmax.h"
#ifdef _POSIX_VERSION
#include <sys/wait.h>
#else /* !_POSIX_VERSION */
#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
#define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0)
#define WIFEXITED(w) (((w) & 0xff) == 0)
#define WSTOPSIG(w) (((w) >> 8) & 0xff)
#define WTERMSIG(w) ((w) & 0x7f)
#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
#endif /* _POSIX_VERSION */
/* nonstandard */
#ifndef WIFCOREDUMPED
#define WIFCOREDUMPED(w) (((w) & 0x80) != 0)
#endif
#ifdef __MSDOS__
/* missing things from sys/stat.h */
#define S_ISUID 0
#define S_ISGID 0
#define S_ISVTX 0
/* device stuff */
#define makedev(ma, mi) ((ma << 8) | mi)
#define major(dev) (dev)
#define minor(dev) (dev)
typedef long off_t;
#endif /* __MSDOS__ */
#if defined(__STDC__) || defined(__TURBOC__)
#define PTR void *
#else
#define PTR char *
#define const
#endif
/* Since major is a function on SVR4, we can't just use `ifndef major'. */
#ifdef major /* Might be defined in sys/types.h. */
#define HAVE_MAJOR
#endif
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_MKDEV)
#include <sys/mkdev.h>
#define HAVE_MAJOR
#endif
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_SYSMACROS)
#include <sys/sysmacros.h>
#define HAVE_MAJOR
#endif
#ifndef HAVE_MAJOR
#define major(dev) (((dev) >> 8) & 0xff)
#define minor(dev) ((dev) & 0xff)
#define makedev(maj, min) (((maj) << 8) | (min))
#endif
#undef HAVE_MAJOR
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#if !defined(__MSDOS__) && !defined(STDC_HEADERS)
#include <memory.h>
#endif
#ifdef index
#undef index
#endif
#ifdef rindex
#undef rindex
#endif
#define index strchr
#define rindex strrchr
#define bcopy(s, d, n) memcpy(d, s, n)
#define bzero(s, n) memset(s, 0, n)
#define bcmp memcmp
#else
#include <strings.h>
#endif
#if defined(STDC_HEADERS)
#include <stdlib.h>
#else
char *malloc (), *realloc ();
char *getenv ();
#endif
#ifndef _POSIX_VERSION
#ifdef __MSDOS__
#include <io.h>
#else /* !__MSDOS__ */
off_t lseek ();
#endif /* !__MSDOS__ */
char *getcwd ();
#endif /* !_POSIX_VERSION */
#ifndef NULL
#define NULL 0
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CREAT
#define O_CREAT 0
#endif
#ifndef O_NDELAY
#define O_NDELAY 0
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#include <sys/stat.h>
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
#define mode_t unsigned short
#endif
#if !defined(S_ISBLK) && defined(S_IFBLK)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
#if !defined(S_ISCHR) && defined(S_IFCHR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISREG) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISFIFO) && defined(S_IFIFO)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
#endif
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif
#if !defined(S_ISCTG) && defined(S_IFCTG) /* contiguous file */
#define S_ISCTG(m) (((m) & S_IFMT) == S_IFCTG)
#endif
#if !defined(S_ISVTX)
#define S_ISVTX 0001000
#endif
#ifdef __MSDOS__
#include "msd_dir.h"
#define NLENGTH(direct) ((direct)->d_namlen)
#else /* not __MSDOS__ */
#if defined(DIRENT) || defined(_POSIX_VERSION)
#include <dirent.h>
#define NLENGTH(direct) (strlen((direct)->d_name))
#else /* not (DIRENT or _POSIX_VERSION) */
#define dirent direct
#define NLENGTH(direct) ((direct)->d_namlen)
#ifdef SYSNDIR
#include <sys/ndir.h>
#endif /* SYSNDIR */
#ifdef SYSDIR
#include <sys/dir.h>
#endif /* SYSDIR */
#ifdef NDIR
#include <ndir.h>
#endif /* NDIR */
#endif /* DIRENT or _POSIX_VERSION */
#endif /* not __MSDOS__ */

View File

@@ -1,22 +0,0 @@
/* Read files directly from the fast file system
Copyright (C) 1992 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 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */

View File

@@ -1,6 +1,6 @@
/* Functions for dealing with sparse files
Copyright (C) 2003, 2004, 2005, 2006, 2007 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
@@ -13,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>
@@ -216,43 +215,45 @@ sparse_scan_file (struct tar_sparse_file *file)
struct tar_stat_info *st = file->stat_info;
int fd = file->fd;
char buffer[BLOCKSIZE];
size_t count;
size_t count = 0;
off_t offset = 0;
struct sp_array sp = {0, 0};
if (!lseek_or_error (file, 0))
return false;
st->archive_file_size = 0;
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
if (ST_NBLOCKS (st->stat) == 0)
offset = st->stat.st_size;
else
{
/* Analyze the block. */
if (zero_block_p (buffer, count))
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = blocking_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
{
if (sp.numbytes)
/* Analyze the block. */
if (zero_block_p (buffer, count))
{
sparse_add_map (st, &sp);
sp.numbytes = 0;
if (!tar_sparse_scan (file, scan_block, NULL))
if (sp.numbytes)
{
sparse_add_map (st, &sp);
sp.numbytes = 0;
if (!tar_sparse_scan (file, scan_block, NULL))
return false;
}
}
else
{
if (sp.numbytes == 0)
sp.offset = offset;
sp.numbytes += count;
st->archive_file_size += count;
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
}
else
{
if (sp.numbytes == 0)
sp.offset = offset;
sp.numbytes += count;
st->archive_file_size += count;
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
offset += count;
offset += count;
}
}
if (sp.numbytes == 0)
@@ -324,7 +325,6 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
bytes_left -= bytes_read;
file->dumped_size += bytes_read;
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
set_next_block_after (blk);
}
@@ -334,7 +334,7 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
static bool
sparse_extract_region (struct tar_sparse_file *file, size_t i)
{
size_t write_size;
off_t write_size;
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
@@ -358,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);
@@ -398,10 +398,11 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
{
size_t i;
mv_begin (file.stat_info);
mv_begin_write (file.stat_info->file_name,
file.stat_info->stat.st_size,
file.stat_info->archive_file_size - file.dumped_size);
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
rc = tar_sparse_dump_region (&file, i);
mv_end ();
}
}
@@ -508,13 +509,13 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
static bool
check_data_region (struct tar_sparse_file *file, size_t i)
{
size_t size_left;
off_t size_left;
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
size_left = file->stat_info->sparse_map[i].numbytes;
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
while (size_left > 0)
{
size_t bytes_read;
@@ -564,9 +565,9 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
file.stat_info = st;
file.fd = fd;
file.seekable = true; /* File *must* be seekable for compare to work */
rc = tar_sparse_decode_header (&file);
mv_begin (st);
mv_begin_read (st);
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
{
rc = check_sparse_region (&file,
@@ -579,7 +580,7 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
if (!rc)
skip_file (file.stat_info->archive_file_size - file.dumped_size);
mv_end ();
tar_sparse_done (&file);
return rc;
}
@@ -588,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... */
@@ -625,8 +626,9 @@ oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
if (s->numbytes[0] == '\0')
return add_finish;
sp.offset = OFF_FROM_HEADER (s->offset);
sp.numbytes = SIZE_FROM_HEADER (s->numbytes);
if (sp.offset < 0
sp.numbytes = OFF_FROM_HEADER (s->numbytes);
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;
@@ -640,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 */
@@ -695,8 +697,8 @@ oldgnu_store_sparse_info (struct tar_sparse_file *file, size_t *pindex,
{
OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].offset,
sp->offset);
SIZE_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,
sp->numbytes);
OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,
sp->numbytes);
}
}
@@ -764,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 */
@@ -807,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)
@@ -851,13 +854,13 @@ static struct tar_sparse_optab const star_optab = {
instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
POSIX requires the latest occurrence of the variable to override all
previous occurrences.
To avoid this incompatibility two following versions were introduced.
* 0.1
Used by tar 1.15.2 -- 1.15.91 (alpha releases).
The sparse file map is stored in
x header:
@@ -875,18 +878,18 @@ static struct tar_sparse_optab const star_optab = {
Starting from this version, the exact sparse format version is specified
explicitely in the header using the following variables:
GNU.sparse.major Major version
GNU.sparse.major Major version
GNU.sparse.minor Minor version
X header keeps the following variables:
GNU.sparse.name Real file name of the sparse file
GNU.sparse.realsize Real size of the stored file (corresponds to the old
GNU.sparse.size variable)
The name field of the ustar header is constructed using the pattern
"%d/GNUSparseFile.%p/%f".
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length,
delimited by newlines. The map is padded with nulls to the nearest block
@@ -915,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)
{
@@ -924,11 +939,11 @@ pax_dump_header_0 (struct tar_sparse_file *file)
char nbuf[UINTMAX_STRSIZE_BOUND];
struct sp_array *map = file->stat_info->sparse_map;
char *save_file_name = NULL;
/* Store the real file size */
xheader_store ("GNU.sparse.size", file->stat_info, NULL);
xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
if (xheader_keyword_deleted_p ("GNU.sparse.map")
|| tar_sparse_minor == 0)
{
@@ -964,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)
{
@@ -991,7 +1004,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
#define COPY_STRING(b,dst,src) do \
{ \
char *endp = b->buffer + BLOCKSIZE; \
char *srcp = src; \
char const *srcp = src; \
while (*srcp) \
{ \
if (dst == endp) \
@@ -1003,7 +1016,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
} \
*dst++ = *srcp++; \
} \
} while (0)
} while (0)
/* Compute stored file size */
p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
@@ -1018,19 +1031,20 @@ pax_dump_header_1 (struct tar_sparse_file *file)
size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
file->stat_info->archive_file_size += size * BLOCKSIZE;
file->dumped_size += size * BLOCKSIZE;
/* Store sparse file identification */
xheader_store ("GNU.sparse.major", file->stat_info, NULL);
xheader_store ("GNU.sparse.minor", file->stat_info, NULL);
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);
blk = start_header (file->stat_info);
/* Store the effective (shrunken) file size */
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
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 = 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;
@@ -1072,12 +1086,13 @@ 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)
return false;
*num = u;
return true;
}
@@ -1117,7 +1132,7 @@ pax_decode_header (struct tar_sparse_file *file)
} \
while (*dst++ != '\n'); \
dst[-1] = 0; \
} while (0)
} while (0)
set_next_block_after (current_header);
file->dumped_size += BLOCKSIZE;
@@ -1126,7 +1141,7 @@ pax_decode_header (struct tar_sparse_file *file)
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
@@ -1137,19 +1152,19 @@ pax_decode_header (struct tar_sparse_file *file)
for (i = 0; i < file->stat_info->sparse_map_size; i++)
{
struct sp_array sp;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
sp.offset = u;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
@@ -1158,7 +1173,7 @@ pax_decode_header (struct tar_sparse_file *file)
}
set_next_block_after (blk);
}
return true;
}
@@ -1168,7 +1183,7 @@ static struct tar_sparse_optab const pax_optab = {
pax_sparse_member_p,
pax_dump_header,
NULL,
pax_decode_header,
pax_decode_header,
NULL, /* No scan_block function */
sparse_dump_region,
sparse_extract_region,

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.
@@ -26,55 +26,89 @@ struct compression_suffix
const char *program;
};
struct compression_suffix compression_suffixes[] = {
#define S(s,p) #s, sizeof (#s) - 1, #p
{ S(gz, gzip) },
{ S(tgz, gzip) },
{ S(taz, gzip) },
{ S(Z, compress) },
{ S(taZ, compress) },
{ S(bz2, bzip2) },
{ S(tbz, bzip2) },
{ S(tbz2, bzip2) },
{ S(tz2, bzip2) },
{ S(lzma, lzma) },
{ S(tlz, lzma) },
{ S(lzo, lzop) },
{ S(xz, xz) },
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) },
{ S(Z, COMPRESS) },
{ S(taZ, COMPRESS) },
{ S(bz2, BZIP2) },
{ S(tbz, BZIP2) },
{ S(tbz2, BZIP2) },
{ S(tz2, BZIP2) },
{ S(lz, LZIP) },
{ S(lzma, LZMA) },
{ S(tlz, LZMA) },
{ S(lzo, LZOP) },
{ S(xz, XZ) },
{ S(txz, XZ) }, /* Slackware */
{ NULL }
#undef S
#undef __CAT2__
};
int nsuffixes = sizeof (compression_suffixes) /
sizeof (compression_suffixes[0]);
static struct compression_suffix const *
find_compression_suffix (const char *name, size_t *ret_len)
{
char *suf = strrchr (name, '.');
if (suf)
{
size_t len;
struct compression_suffix *p;
suf++;
len = strlen (suf);
for (p = compression_suffixes; p->suffix; p++)
{
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)
{
char *suf = strrchr (name, '.');
if (suf)
{
int i;
size_t len;
suf++;
len = strlen (suf);
for (i = 0; i < nsuffixes; i++)
{
if (compression_suffixes[i].length == len
&& memcmp (compression_suffixes[i].suffix, suf, len) == 0)
return compression_suffixes[i].program;
}
}
struct compression_suffix const *p = find_compression_suffix (name, NULL);
if (p)
return p->program;
return defprog;
}
void
set_comression_program_by_suffix (const char *name, const char *defprog)
set_compression_program_by_suffix (const char *name, const char *defprog)
{
const char *program = find_compression_program (name, 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 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,14 +13,28 @@
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 "common.h"
#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
@@ -174,11 +187,11 @@ sys_wait_for_child (pid_t child_pid, bool eof)
{
int sig = WTERMSIG (wait_status);
if (!(!eof && sig == SIGPIPE))
ERROR ((0, 0, _("Child died with signal %d"), sig));
FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig));
}
else if (WEXITSTATUS (wait_status) != 0)
ERROR ((0, 0, _("Child returned status %d"),
WEXITSTATUS (wait_status)));
FATAL_ERROR ((0, 0, _("Child returned status %d"),
WEXITSTATUS (wait_status)));
}
}
@@ -192,7 +205,8 @@ sys_spawn_shell (void)
child = xfork ();
if (child == 0)
{
execlp (shell, "-sh", "-i", (char *) 0);
priv_set_restore_linkdir ();
execlp (shell, "-sh", "-i", NULL);
exec_fatal (shell);
}
else
@@ -283,6 +297,30 @@ xdup2 (int from, int into)
}
}
static void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
/* Propagate any failure of the grandchild back to the parent. */
static void
wait_for_grandchild (pid_t pid)
{
int wait_status;
int exit_code = 0;
while (waitpid (pid, &wait_status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (use_compress_program_option);
break;
}
if (WIFSIGNALED (wait_status))
raise (WTERMSIG (wait_status));
else if (WEXITSTATUS (wait_status) != 0)
exit_code = WEXITSTATUS (wait_status);
exit (exit_code);
}
/* Set ARCHIVE for writing, then compressing an archive. */
pid_t
sys_child_open_for_compress (void)
@@ -291,7 +329,6 @@ sys_child_open_for_compress (void)
int child_pipe[2];
pid_t grandchild_pid;
pid_t child_pid;
int wait_status;
xpipe (parent_pipe);
child_pid = xfork ();
@@ -307,7 +344,8 @@ sys_child_open_for_compress (void)
/* The new born child tar is here! */
program_name = _("tar (child)");
set_program_name (_("tar (child)"));
signal (SIGPIPE, SIG_DFL);
xdup2 (parent_pipe[PREAD], STDIN_FILENO);
xclose (parent_pipe[PWRITE]);
@@ -338,8 +376,8 @@ sys_child_open_for_compress (void)
}
xdup2 (archive, STDOUT_FILENO);
}
execlp (use_compress_program_option, use_compress_program_option, NULL);
exec_fatal (use_compress_program_option);
priv_set_restore_linkdir ();
xexec (use_compress_program_option);
}
/* We do need a grandchild tar. */
@@ -351,13 +389,12 @@ sys_child_open_for_compress (void)
{
/* The newborn grandchild tar is here! Launch the compressor. */
program_name = _("tar (grandchild)");
set_program_name (_("tar (grandchild)"));
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
xclose (child_pipe[PREAD]);
execlp (use_compress_program_option, use_compress_program_option,
(char *) 0);
exec_fatal (use_compress_program_option);
priv_set_restore_linkdir ();
xexec (use_compress_program_option);
}
/* The child tar is still here! */
@@ -424,24 +461,43 @@ sys_child_open_for_compress (void)
archive_write_error (status);
}
/* Propagate any failure of the grandchild back to the parent. */
wait_for_grandchild (grandchild_pid);
}
while (waitpid (grandchild_pid, &wait_status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (use_compress_program_option);
break;
}
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;
if (WIFSIGNALED (wait_status))
ws.ws_env = (const char **) environ;
ws.ws_offs = 1;
for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
{
kill (child_pid, WTERMSIG (wait_status));
exit_status = TAREXIT_FAILURE;
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;
}
else if (WEXITSTATUS (wait_status) != 0)
exit_status = WEXITSTATUS (wait_status);
exit (exit_status);
if (!prog)
FATAL_ERROR ((0, 0, _("unable to run decompression program")));
exec_fatal (prog);
}
/* Set ARCHIVE for uncompressing, then reading an archive. */
@@ -452,7 +508,6 @@ sys_child_open_for_uncompress (void)
int child_pipe[2];
pid_t grandchild_pid;
pid_t child_pid;
int wait_status;
xpipe (parent_pipe);
child_pid = xfork ();
@@ -468,7 +523,8 @@ sys_child_open_for_uncompress (void)
/* The newborn child tar is here! */
program_name = _("tar (child)");
set_program_name (_("tar (child)"));
signal (SIGPIPE, SIG_DFL);
xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
xclose (parent_pipe[PREAD]);
@@ -489,9 +545,8 @@ sys_child_open_for_uncompress (void)
if (archive < 0)
open_fatal (archive_name_array[0]);
xdup2 (archive, STDIN_FILENO);
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
exec_fatal (use_compress_program_option);
priv_set_restore_linkdir ();
run_decompress_program ();
}
/* We do need a grandchild tar. */
@@ -503,13 +558,12 @@ sys_child_open_for_uncompress (void)
{
/* The newborn grandchild tar is here! Launch the uncompressor. */
program_name = _("tar (grandchild)");
set_program_name (_("tar (grandchild)"));
xdup2 (child_pipe[PREAD], STDIN_FILENO);
xclose (child_pipe[PWRITE]);
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
exec_fatal (use_compress_program_option);
priv_set_restore_linkdir ();
run_decompress_program ();
}
/* The child tar is still here! */
@@ -562,30 +616,13 @@ sys_child_open_for_uncompress (void)
xclose (STDOUT_FILENO);
/* Propagate any failure of the grandchild back to the parent. */
while (waitpid (grandchild_pid, &wait_status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (use_compress_program_option);
break;
}
if (WIFSIGNALED (wait_status))
{
kill (child_pid, WTERMSIG (wait_status));
exit_status = TAREXIT_FAILURE;
}
else if (WEXITSTATUS (wait_status) != 0)
exit_status = WEXITSTATUS (wait_status);
exit (exit_status);
wait_for_grandchild (grandchild_pid);
}
static void
dec_to_env (char *envar, uintmax_t num)
dec_to_env (char const *envar, uintmax_t num)
{
char buf[UINTMAX_STRSIZE_BOUND];
char *numstr;
@@ -596,7 +633,7 @@ dec_to_env (char *envar, uintmax_t num)
}
static void
time_to_env (char *envar, struct timespec t)
time_to_env (char const *envar, struct timespec t)
{
char buf[TIMESPEC_STRSIZE_BOUND];
if (setenv (envar, code_timespec (t, buf), 1) != 0)
@@ -604,7 +641,7 @@ time_to_env (char *envar, struct timespec t)
}
static void
oct_to_env (char *envar, unsigned long num)
oct_to_env (char const *envar, unsigned long num)
{
char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
@@ -614,7 +651,7 @@ oct_to_env (char *envar, unsigned long num)
}
static void
str_to_env (char *envar, char const *str)
str_to_env (char const *envar, char const *str)
{
if (str)
{
@@ -626,7 +663,7 @@ str_to_env (char *envar, char const *str)
}
static void
chr_to_env (char *envar, char c)
chr_to_env (char const *envar, char c)
{
char buf[2];
buf[0] = c;
@@ -639,6 +676,12 @@ static void
stat_to_env (char *name, char type, struct tar_stat_info *st)
{
str_to_env ("TAR_VERSION", PACKAGE_VERSION);
str_to_env ("TAR_ARCHIVE", *archive_name_cursor);
dec_to_env ("TAR_VOLUME", archive_name_cursor - archive_name_array + 1);
dec_to_env ("TAR_BLOCKING_FACTOR", blocking_factor);
str_to_env ("TAR_FORMAT",
archive_format_string (current_format == DEFAULT_FORMAT ?
archive_format : current_format));
chr_to_env ("TAR_FILETYPE", type);
oct_to_env ("TAR_MODE", st->stat.st_mode);
str_to_env ("TAR_FILENAME", name);
@@ -677,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);
@@ -701,14 +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;
execv ("/bin/sh", argv);
exec_fatal (file_name);
priv_set_restore_linkdir ();
xexec (to_command_option);
}
void
@@ -750,11 +786,10 @@ 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);
@@ -787,7 +822,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
}
signal (SIGPIPE, saved_handler);
if (WIFEXITED (status))
{
if (WEXITSTATUS (status) == 0 && rc > 0)
@@ -815,14 +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;
execv (argv[0], argv);
exec_fatal (info_script_option);
priv_set_restore_linkdir ();
xexec (info_script_option);
}
void
@@ -831,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 ();
@@ -862,14 +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;
execv (argv[0], argv);
exec_fatal (script_name);
priv_set_restore_linkdir ();
xexec (script_name);
}
#endif /* not MSDOS */

1290
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
@@ -265,7 +266,7 @@ enum archive_format
struct sp_array
{
off_t offset;
size_t numbytes;
off_t numbytes;
};
struct xheader
@@ -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,14 +327,40 @@ 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;
/* For dumpdirs */
bool is_dumpdir; /* Is the member a dumpdir? */
bool skipped; /* The member contents is already read
(for GNUTYPE_DUMPDIR) */
char *dumpdir; /* Contents of the dump directory */
/* Parent directory, if creating an archive. This is null if the
file is at the top level. */
struct tar_stat_info *parent;
/* Directory stream. If this is not null, it is in control of FD,
and should be closed instead of FD. */
DIR *dirstream;
/* File descriptor, if creating an archive, and if a directory or a
regular file or a contiguous file.
It is zero if no file descriptor is available, either because it
was never needed or because it was open and then closed to
conserve on file descriptors. (Standard input is never used
here, so zero cannot be a valid file descriptor.)
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,240 +0,0 @@
/* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0
This file is in the public domain.
Compile your main program with -Dmain=_main and link with this file.
After that, it is just as if the operating system had expanded the
arguments, except that they are not sorted. The program name and all
arguments that are expanded from wildcards are lowercased.
Syntax for wildcards:
* Matches zero or more of any character (except a '.' at
the beginning of a name).
? Matches any single character.
[r3z] Matches 'r', '3', or 'z'.
[a-d] Matches a single character in the range 'a' through 'd'.
[!a-d] Matches any single character except a character in the
range 'a' through 'd'.
The period between the filename root and its extension need not be
given explicitly. Thus, the pattern `a*e' will match 'abacus.exe'
and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive.
Authors:
The expargs code is a modification of wildcard expansion code
written for Turbo C 1.0 by
Richard Hargrove
Texas Instruments, Inc.
P.O. Box 869305, m/s 8473
Plano, Texas 75086
214/575-4128
and posted to USENET in September, 1987.
The wild_match code was written by Rich Salz, rsalz@bbn.com,
posted to net.sources in November, 1986.
The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2,
posted to comp.sys.ibm.pc in November, 1988.
Major performance enhancements and bug fixes, and source cleanup,
by David MacKenzie, djm@gnu.ai.mit.edu. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <dir.h>
/* Number of new arguments to allocate space for at a time. */
#define ARGS_INCREMENT 10
/* The name this program was run with, for error messages. */
static char *program_name;
static char **grow_argv (char **new_argv, int new_argc);
static void fatal_error (const char *message);
int wild_match (char *string, char *pattern);
char *basename (char *path);
char **expargs (int *, char **);
#ifdef main
#undef main
#endif
int
main (int argc, char **argv, char **envp)
{
argv = expargs (&argc, argv);
return _main (argc, argv, envp);
}
char **
expargs (int *pargc, char **argv)
{
char path[MAXPATH + 1];
char **new_argv;
struct ffblk block;
char *path_base;
char *arg_base;
int argind;
int new_argc;
int path_length;
int matched;
program_name = argv[0];
if (program_name && *program_name)
strlwr (program_name);
new_argv = grow_argv (NULL, 0);
new_argv[0] = argv[0];
new_argc = 1;
for (argind = 1; argind < *pargc; ++argind)
{
matched = 0;
if (strpbrk (argv[argind], "?*[") != NULL)
{
strncpy (path, argv[argind], MAXPATH - 3);
path_base = basename (path);
strcpy (path_base, "*.*");
arg_base = argv[argind] + (path_base - path);
if (!findfirst (path, &block, FA_DIREC))
{
strlwr (path);
do
{
/* Only match "." and ".." explicitly. */
if (*block.ff_name == '.' && *arg_base != '.')
continue;
path_length = stpcpy (path_base, block.ff_name) - path + 1;
strlwr (path_base);
if (wild_match (path, argv[argind]))
{
matched = 1;
new_argv[new_argc] = (char *) malloc (path_length);
if (new_argv[new_argc] == NULL)
fatal_error ("memory exhausted");
strcpy (new_argv[new_argc++], path);
new_argv = grow_argv (new_argv, new_argc);
}
} while (!findnext (&block));
}
}
if (matched == 0)
new_argv[new_argc++] = argv[argind];
new_argv = grow_argv (new_argv, new_argc);
}
*pargc = new_argc;
new_argv[new_argc] = NULL;
return &new_argv[0];
}
/* Return a pointer to the last element of PATH. */
char *
basename (char *path)
{
char *tail;
for (tail = path; *path; ++path)
if (*path == ':' || *path == '\\')
tail = path + 1;
return tail;
}
static char **
grow_argv (char **new_argv, int new_argc)
{
if (new_argc % ARGS_INCREMENT == 0)
{
new_argv = (char **) realloc
(new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT));
if (new_argv == NULL)
fatal_error ("memory exhausted");
}
return new_argv;
}
static void
fatal_error (const char *message)
{
putc ('\n', stderr);
if (program_name && *program_name)
{
fputs (program_name, stderr);
fputs (": ", stderr);
}
fputs (message, stderr);
putc ('\n', stderr);
exit (1);
}
/* Shell-style pattern matching for ?, \, [], and * characters.
I'm putting this replacement in the public domain.
Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */
/* The character that inverts a character class; '!' or '^'. */
#define INVERT '!'
static int star (char *string, char *pattern);
/* Return nonzero if `string' matches Unix-style wildcard pattern
`pattern'; zero if not. */
int
wild_match (char *string, char *pattern)
{
int prev; /* Previous character in character class. */
int matched; /* If 1, character class has been matched. */
int reverse; /* If 1, character class is inverted. */
for (; *pattern; string++, pattern++)
switch (*pattern)
{
case '\\':
/* Literal match with following character; fall through. */
pattern++;
default:
if (*string != *pattern)
return 0;
continue;
case '?':
/* Match anything. */
if (*string == '\0')
return 0;
continue;
case '*':
/* Trailing star matches everything. */
return *++pattern ? star (string, pattern) : 1;
case '[':
/* Check for inverse character class. */
reverse = pattern[1] == INVERT;
if (reverse)
pattern++;
for (prev = 256, matched = 0; *++pattern && *pattern != ']';
prev = *pattern)
if (*pattern == '-'
? *string <= *++pattern && *string >= prev
: *string == *pattern)
matched = 1;
if (matched == reverse)
return 0;
continue;
}
return *string == '\0';
}
static int
star (char *string, char *pattern)
{
while (wild_match (string, pattern) == 0)
if (*++string == '\0')
return 0;
return 1;
}

View File

@@ -1,67 +0,0 @@
/* Find out if we need the pad field in the header for this machine
Copyright (C) 1991 Free Software Foundation
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 2, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
struct inc
{
char a[20];
char b[20];
};
struct test1
{
char a;
struct inc in[5];
};
struct test2
{
char a;
char b;
struct inc in[5];
};
void
main ()
{
struct test1 t1;
struct test2 t2;
int t1diff, t2diff;
FILE *fp = fopen ("testpad.h", "w");
if (fp == 0)
{
fprintf (stderr, "testpad: cannot open ");
fflush (stderr);
perror ("testpad.h");
exit (1);
}
t1diff = (char *) &t1.in[0] - (char *) &t1;
t2diff = (char *) &t2.in[0] - (char *) &t2;
if (t2diff == t1diff + 1)
fprintf (fp, "#define NEEDPAD\n");
else if (t1diff != t2diff)
fprintf (stderr, "Cannot determine padding for tar struct, \n\
will try with none.\n");
fclose (fp);
exit (0);
}

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
/* This file is part of GNU tar.
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>
@@ -34,8 +33,8 @@ enum replace_segm_type
enum case_ctl_type
{
ctl_stop, /* Stop case conversion */
ctl_upcase_next,/* Turn the next character to uppercase */
ctl_stop, /* Stop case conversion */
ctl_upcase_next,/* Turn the next character to uppercase */
ctl_locase_next,/* Turn the next character to lowercase */
ctl_upcase, /* Turn the replacement to uppercase until ctl_stop */
ctl_locase /* Turn the replacement to lowercase until ctl_stop */
@@ -51,9 +50,9 @@ struct replace_segm
{
char *ptr;
size_t size;
} literal; /* type == segm_literal */
} literal; /* type == segm_literal */
size_t ref; /* type == segm_backref */
enum case_ctl_type ctl; /* type == segm_case_ctl */
enum case_ctl_type ctl; /* type == segm_case_ctl */
} v;
};
@@ -71,11 +70,11 @@ struct transform
int transform_flags = XFORM_ALL;
static int transform_flags = XFORM_ALL;
static struct transform *transform_head, *transform_tail;
static struct transform *
new_transform ()
new_transform (void)
{
struct transform *p = xzalloc (sizeof *p);
if (transform_tail)
@@ -146,7 +145,7 @@ parse_xform_flags (int *pflags, int c)
case 'R':
*pflags &= ~XFORM_REGFILE;
break;
case 'h':
*pflags |= XFORM_LINK;
break;
@@ -154,7 +153,7 @@ parse_xform_flags (int *pflags, int c)
case 'H':
*pflags &= ~XFORM_LINK;
break;
case 's':
*pflags |= XFORM_SYMLINK;
break;
@@ -204,10 +203,10 @@ parse_transform_expr (const char *expr)
*expr));
}
return expr;
}
}
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
}
delim = expr[1];
/* Scan regular expression */
@@ -258,14 +257,14 @@ parse_transform_expr (const char *expr)
if (*p == ';')
p++;
/* Extract and compile regex */
str = xmalloc (i - 1);
memcpy (str, expr + 2, i - 2);
str[i - 2] = 0;
rc = regcomp (&tf->regex, str, cflags);
if (rc)
{
char errbuf[512];
@@ -275,7 +274,7 @@ parse_transform_expr (const char *expr)
if (str[0] == '^' || str[strlen (str) - 1] == '$')
tf->transform_type = transform_first;
free (str);
/* Extract and compile replacement expr */
@@ -289,7 +288,7 @@ parse_transform_expr (const char *expr)
if (*cur == '\\')
{
size_t n;
add_literal_segment (tf, beg, cur);
switch (*++cur)
{
@@ -310,32 +309,32 @@ parse_transform_expr (const char *expr)
add_char_segment (tf, '\a');
cur++;
break;
case 'b':
add_char_segment (tf, '\b');
cur++;
break;
case 'f':
add_char_segment (tf, '\f');
cur++;
break;
case 'n':
add_char_segment (tf, '\n');
cur++;
break;
case 'r':
add_char_segment (tf, '\r');
cur++;
break;
case 't':
add_char_segment (tf, '\t');
cur++;
break;
case 'v':
add_char_segment (tf, '\v');
cur++;
@@ -345,39 +344,39 @@ parse_transform_expr (const char *expr)
add_char_segment (tf, '&');
cur++;
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++;
break;
case 'l':
/* Turn the next character to lowercase, */
add_case_ctl_segment (tf, ctl_locase_next);
cur++;
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++;
break;
case 'u':
/* Turn the next character to uppercase, */
add_case_ctl_segment (tf, ctl_upcase_next);
cur++;
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;
default:
/* Try to be nice */
{
@@ -420,7 +419,7 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
static char *case_ctl_buffer;
static size_t case_ctl_bufsize;
char *p;
if (case_ctl_bufsize < size)
{
case_ctl_bufsize = size;
@@ -430,21 +429,21 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
switch (case_ctl)
{
case ctl_upcase_next:
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
case_ctl_buffer[0] = toupper ((unsigned char) case_ctl_buffer[0]);
break;
case ctl_locase_next:
case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
case_ctl_buffer[0] = tolower ((unsigned char) case_ctl_buffer[0]);
break;
case ctl_upcase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = toupper (*p);
*p = toupper ((unsigned char) *p);
break;
case ctl_locase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = tolower (*p);
*p = tolower ((unsigned char) *p);
break;
case ctl_stop:
@@ -457,7 +456,7 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
static struct obstack stk;
static bool stk_init;
void
static void
_single_transform_name_to_obstack (struct transform *tf, char *input)
{
regmatch_t *rmp;
@@ -465,7 +464,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
size_t nmatches = 0;
enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
save_ctl = ctl_stop; /* Saved case_ctl for \u and \l */
/* Reset case conversion after a single-char operation */
#define CASE_CTL_RESET() if (case_ctl == ctl_upcase_next \
|| case_ctl == ctl_locase_next) \
@@ -473,20 +472,20 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
case_ctl = save_ctl; \
save_ctl = ctl_stop; \
}
rmp = xmalloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
while (*input)
{
size_t disp;
char *ptr;
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
if (rc == 0)
{
struct replace_segm *segm;
disp = rmp[0].rm_eo;
if (rmp[0].rm_so)
@@ -516,7 +515,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
}
obstack_grow (&stk, ptr, segm->v.literal.size);
break;
case segm_backref: /* Back-reference segment */
if (rmp[segm->v.ref].rm_so != -1
&& rmp[segm->v.ref].rm_eo != -1)
@@ -529,7 +528,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
ptr = run_case_conv (case_ctl, ptr, size);
CASE_CTL_RESET();
}
obstack_grow (&stk, ptr, size);
}
break;
@@ -549,7 +548,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
break;
}
/*FALL THROUGH*/
case ctl_upcase:
case ctl_locase:
case ctl_stop:
@@ -577,18 +576,18 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
free (rmp);
}
bool
static bool
_transform_name_to_obstack (int flags, char *input, char **output)
{
struct transform *tf;
bool alloced = false;
if (!stk_init)
{
obstack_init (&stk);
stk_init = true;
}
for (tf = transform_head; tf; tf = tf->next)
{
if (tf->flags & flags)
@@ -601,7 +600,7 @@ _transform_name_to_obstack (int flags, char *input, char **output)
*output = input;
return alloced;
}
bool
transform_name_fp (char **pinput, int flags,
char *(*fun)(char *, void *), void *dat)
@@ -629,3 +628,8 @@ transform_name (char **pinput, int type)
return transform_name_fp (pinput, type, NULL, NULL);
}
bool
transform_program_p (void)
{
return transform_head != NULL;
}

180
src/unlink.c Normal file
View File

@@ -0,0 +1,180 @@
/* Unlink files.
Copyright 2009, 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/>. */
#include <system.h>
#include "common.h"
#include <quotearg.h>
struct deferred_unlink
{
struct deferred_unlink *next; /* Next unlink in the queue */
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 */
};
/* The unlink queue */
static struct deferred_unlink *dunlink_head, *dunlink_tail;
/* Number of entries in the queue */
static size_t dunlink_count;
/* List of entries available for allocation */
static struct deferred_unlink *dunlink_avail;
/* Delay (number of records written) between adding entry to the
list and its actual removal. */
static size_t deferred_unlink_delay = 0;
static struct deferred_unlink *
dunlink_alloc (void)
{
struct deferred_unlink *p;
if (dunlink_avail)
{
p = dunlink_avail;
dunlink_avail = p->next;
p->next = NULL;
}
else
p = xmalloc (sizeof (*p));
return p;
}
static void
dunlink_reclaim (struct deferred_unlink *p)
{
free (p->file_name);
p->next = dunlink_avail;
dunlink_avail = p;
}
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)
{
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)
{
case ENOENT:
/* nothing to worry about */
break;
case ENOTEMPTY:
if (!force)
{
/* Keep the record in list, in the hope we'll
be able to remove it later */
prev = p;
p = next;
continue;
}
/* fall through */
default:
rmdir_error (fname);
}
}
}
else
{
if (unlinkat (chdir_fd, p->file_name, 0) != 0 && errno != ENOENT)
unlink_error (p->file_name);
}
dunlink_reclaim (p);
dunlink_count--;
p = next;
if (prev)
prev->next = p;
else
dunlink_head = p;
}
else
{
prev = p;
p = next;
}
}
if (!dunlink_head)
dunlink_tail = NULL;
chdir_do (saved_chdir);
}
void
finish_deferred_unlinks (void)
{
flush_deferred_unlinks (true);
while (dunlink_avail)
{
struct deferred_unlink *next = dunlink_avail->next;
free (dunlink_avail);
dunlink_avail = next;
}
}
void
queue_deferred_unlink (const char *name, bool is_dir)
{
struct deferred_unlink *p;
if (dunlink_head
&& records_written > dunlink_head->records_written + deferred_unlink_delay)
flush_deferred_unlinks (false);
p = dunlink_alloc ();
p->next = NULL;
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;
if (dunlink_tail)
dunlink_tail->next = p;
else
dunlink_head = p;
dunlink_tail = p;
dunlink_count++;
}

View File

@@ -1,21 +1,22 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
2004, 2005, 2007 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
@@ -47,7 +48,7 @@ char *output_start;
static void
append_file (char *file_name)
{
int handle = open (file_name, O_RDONLY | O_BINARY);
int handle = openat (chdir_fd, file_name, O_RDONLY | O_BINARY);
struct stat stat_data;
if (handle < 0)
@@ -114,7 +115,9 @@ update_archive (void)
while (!found_end)
{
enum read_header status = read_header (false);
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_auto);
switch (status)
{
@@ -128,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
@@ -136,12 +141,30 @@ update_archive (void)
struct stat s;
chdir_do (name->change_dir);
if (deref_stat (dereference_option,
current_stat_info.file_name, &s) == 0
&& (tar_timespec_cmp (get_stat_mtime (&s),
current_stat_info.mtime)
<= 0))
add_avoided_name (current_stat_info.file_name);
if (deref_stat (current_stat_info.file_name, &s) == 0)
{
if (S_ISDIR (s.st_mode))
{
char *p, *dirp = tar_savedir (name->name, 1);
if (dirp)
{
namebuf_t nbuf = namebuf_create (name->name);
for (p = dirp; *p; p += strlen (p) + 1)
addname (namebuf_name (nbuf, p),
0, false, NULL);
namebuf_free (nbuf);
free (dirp);
remname (name);
}
}
else if (tar_timespec_cmp (get_stat_mtime (&s),
current_stat_info.mtime)
<= 0)
remname (name);
}
}
skip_member ();
@@ -189,22 +212,23 @@ update_archive (void)
output_start = current_block->buffer;
{
char *file_name;
while ((file_name = name_from_list ()) != NULL)
struct name const *p;
while ((p = name_from_list ()) != NULL)
{
if (excluded_name (file_name))
char *file_name = p->name;
if (excluded_name (file_name, NULL))
continue;
if (interactive_option && !confirm ("add", file_name))
continue;
if (subcommand_option == CAT_SUBCOMMAND)
append_file (file_name);
else
dump_file (file_name, 1, (dev_t) 0);
dump_file (0, file_name, file_name);
}
}
write_eot ();
close_archive ();
finish_deferred_unlinks ();
names_notfound ();
}

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,20 +0,0 @@
/* Version info for tar.
Copyright (C) 1989, 1992, 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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
char version_string[] = "GNU tar version 1.11";

107
src/warning.c Normal file
View File

@@ -0,0 +1,107 @@
/* Warnings for GNU tar.
Copyright 2009, 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 <system.h>
#include <argmatch.h>
#include "common.h"
static char const *const warning_args[] = {
"all",
"alone-zero-block",
"bad-dumpdir",
"cachedir",
"contiguous-cast",
"file-changed",
"file-ignored",
"file-removed",
"file-shrank",
"file-unchanged",
"filename-with-nuls",
"ignore-archive",
"ignore-newer",
"new-directory",
"rename-directory",
"symlink-cast",
"timestamp",
"unknown-cast",
"unknown-keyword",
"xdev",
"decompress-program",
"existing-file",
"xattr-write",
"record-size",
NULL
};
static int warning_types[] = {
WARN_ALL,
WARN_ALONE_ZERO_BLOCK,
WARN_BAD_DUMPDIR,
WARN_CACHEDIR,
WARN_CONTIGUOUS_CAST,
WARN_FILE_CHANGED,
WARN_FILE_IGNORED,
WARN_FILE_REMOVED,
WARN_FILE_SHRANK,
WARN_FILE_UNCHANGED,
WARN_FILENAME_WITH_NULS,
WARN_IGNORE_ARCHIVE,
WARN_IGNORE_NEWER,
WARN_NEW_DIRECTORY,
WARN_RENAME_DIRECTORY,
WARN_SYMLINK_CAST,
WARN_TIMESTAMP,
WARN_UNKNOWN_CAST,
WARN_UNKNOWN_KEYWORD,
WARN_XDEV,
WARN_DECOMPRESS_PROGRAM,
WARN_EXISTING_FILE,
WARN_XATTR_WRITE,
WARN_RECORD_SIZE
};
ARGMATCH_VERIFY (warning_args, warning_types);
int warning_option = WARN_ALL;
void
set_warning_option (const char *arg)
{
int negate = 0;
int option;
if (strcmp (arg, "none") == 0)
{
warning_option = 0;
return;
}
if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
{
negate = 1;
arg += 3;
}
option = XARGMATCH ("--warning", arg,
warning_args, warning_types);
if (negate)
warning_option &= ~option;
else
warning_option |= option;
}

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

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