202 Commits

Author SHA1 Message Date
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
265 changed files with 16264 additions and 5100 deletions

6
.gitignore vendored
View File

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

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

View File

@@ -1,28 +1,28 @@
# 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 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:
dist-hook:
$(MAKE) changelog_dir=$(distdir) ChangeLog
-rm -f $(distdir).cpio
find $(distdir) | cpio -Hcrc -o | \
@@ -36,5 +36,3 @@ include Make.rules
gen_start_date = 2009-03-06
prev_change_log = ChangeLog.CVS
changelog_dir = .

400
NEWS
View File

@@ -1,6 +1,233 @@
GNU tar NEWS - User visible changes. 2010-03-10
GNU tar NEWS - User visible changes. 2013-10-05
Please send GNU tar bug reports to <bug-tar@gnu.org>
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
@@ -15,28 +242,28 @@ to regular files and pipes).
When a read-only operation (e.g. --list or --extract) is requested
on a regular file, tar attemtps to speed up accesses by using lseek.
* New command line option `--warning'
* New command line option '--warning'
The `--warning' command line option allows to suppress or enable
particular warning messages during `tar' run. It takes a single
argument (a `keyword'), identifying the class of warning messages
to affect. If the argument is prefixed with `no-', such warning
The '--warning' command line option allows to suppress or enable
particular warning messages during 'tar' run. It takes a single
argument (a 'keyword'), identifying the class of warning messages
to affect. If the argument is prefixed with 'no-', such warning
messages are suppressed. For example,
tar --warning=no-alone-zero-block -x -f archive
suppresses the output of `A lone zero block' diagnostics, which is
normally issued if `archive' ends with a single block of zeros.
suppresses the output of "A lone zero block" diagnostics, which is
normally issued if 'archive' ends with a single block of zeros.
See Tar Manual, section 3.9 "Controlling Warning Messages", for a
detailed discussion.
* New command line option `--level'
* New command line option '--level'
The `--level=N' option sets the incremental dump level N. It
The '--level=N' option sets the incremental dump level N. It
is valid when used in conjunction with the -c and --listed-incremental
options. So far the only meaningful value for N is 0. The
`--level=0' option forces creating the level 0 dump, by truncating
'--level=0' option forces creating the level 0 dump, by truncating
the snapshot file if it exists.
* Files removed during incremental dumps
@@ -65,7 +292,7 @@ can be overridden by the
--pax-opion='exthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a `Time reference' (see below).
the Epoch or a "Time reference" (see below).
Modification times in ustar header blocks of global extended
headers are set to the time when tar was invoked.
@@ -75,15 +302,15 @@ This can be overridden by the
--pax-opion='globexthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a `Time reference' (see below).
the Epoch or a "Time reference" (see below).
* Time references in --pax-option argument.
Any value from the --pax-option argument that is enclosed in a pair
of curly braces represents a time reference. The string between the
of curly braces represents a time reference. The string between the
braces is understood either as a textual time representation, as described in
chapter 7, "Date input formats", of the Tar manual, or as a name of
an existing file, starting with `/' or `.'. In the latter
an existing file, starting with '/' or '.'. In the latter
case, it is replaced with the modification time of that file.
* Environment of --to-command script.
@@ -114,14 +341,14 @@ 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.
@@ -174,21 +401,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'
@@ -196,10 +423,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.
@@ -224,36 +451,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
@@ -280,8 +507,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
@@ -292,14 +519,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 '/.'.
@@ -332,7 +559,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
@@ -402,7 +629,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).
@@ -442,7 +669,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.
@@ -467,7 +694,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
@@ -478,7 +705,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.
@@ -492,7 +719,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.
@@ -565,7 +792,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
@@ -585,7 +812,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
@@ -595,11 +822,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).
@@ -653,12 +880,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
@@ -764,7 +991,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.
@@ -790,12 +1017,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.
@@ -812,12 +1039,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.
@@ -859,20 +1086,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
@@ -881,12 +1108,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.
@@ -903,40 +1130,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.
@@ -945,7 +1172,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.
@@ -1036,7 +1263,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
@@ -1115,7 +1342,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
@@ -1144,8 +1371,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.
@@ -1198,15 +1425,14 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Copyright 1994-2001, 2003-2010, 2013 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
@@ -1214,9 +1440,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-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
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,14 @@ some other value.
Copyright (C) 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Copyright 2001, 2003-2005, 2007, 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, 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 +77,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 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:

10
THANKS
View File

@@ -91,6 +91,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
@@ -133,7 +134,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@airbus.com
Denis Excoffier denis.excoffier@free.fr
Denis Fortin fortin@acm.org
Dennis Pixton dennis@math.binghamton.edu
Dick Streefland dicks@tasking.nl
@@ -241,6 +242,7 @@ Jim Clausing jac@postbox.acs.ohio-state.edu
Jim Farrell jwf@platinum.com
Jim Meyering meyering@na-net.ornl.gov
Jim Murray jjm@jjm.com
Jivko Angelov jivko@siteground.com
Joachim Holzfuss Joachim.Holzfuss@iap.physik.th-darmstadt.de
Joachim Seelig joachim@kruemel.han.de
Joe DeBattista joed@itsa.ucsf.edu
@@ -296,6 +298,7 @@ Kimmy Posey kimmyd@bnr.ca
Koji Kishi kis@rqa.sony.co.jp
Konno Hiroharu konno@pac.co.jp
Kurt Jaeger pi@lf.net
James Antill jantill@redhat.com
Larry Creech lcreech@lonestar.rcclub.org
Larry Schwimmer rosebud@cyclone.stanford.edu
Lasse Collin lasse.collin@tukaani.org
@@ -349,6 +352,7 @@ Michael P Urban urban@cobra.jpl.nasa.gov
Michael Schmidt michael@muc.de
Michael Schwingen m.schwingen@stochastik.rwth-aachen.de
Michael Smolsky fnsiguc@astro.weizmann.ac.il
Michal Žejdl zejdl@suas.cz
Mike Muuss mike@brl.mil
Mike Nolan nolan@lpl.arizona.edu
Mike Rogers mike@demon.net
@@ -357,7 +361,9 @@ 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
@@ -374,6 +380,7 @@ Oswald P. Backus IV backus@lks.csi.com
Pascal Meheut pascal@cnam.cnam.fr
Patrick Fulconis fulco@sig.uvsq.fr
Patrick Timmons timmons@electech.polymtl.ca
Pavel Raiskup praiskup@redhat.com
Paul Eggert eggert@twinsun.com
Paul Kanz paul@icx.com
Paul Mitchell P.Mitchell@surrey.ac.uk
@@ -395,6 +402,7 @@ Phil Proudman phil@proudman51.freeserve.co.uk
Philippe Defert defert@cern.ch
Piercarlo Grandi piercarl@sabi.demon.co.uk
Pierce Cantrell cantrell@ee.tamu.edu
Piotr Rotter piotr.rotter@active24.pl
R. Kent Dybvig dyb@cadence.bloomington.in.us
R. Scott Butler butler@prism.es.dupont.com
Rainer Orth ro@TechFak.Uni-Bielefeld.DE

26
TODO
View File

@@ -45,24 +45,22 @@ Suggestions for improving GNU tar.
* Copyright notice
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
Copyright 2003, 2004, 2007, 2013 Free Software Foundation, Inc.
This file is part of GNU tar.
This file is part of GNU tar.
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with tar; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Local variables:

View File

@@ -1,18 +1,21 @@
dnl Special Autoconf macros for GNU Tar -*- autoconf -*-
dnl Copyright (C) 2009 Free Software Foundation, Inc.
dnl Special Autoconf macros for GNU tar -*- autoconf -*-
dnl Copyright 2009, 2013 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU tar.
dnl
dnl GNU tar is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 3, or (at your option)
dnl any later version.
dnl the Free Software Foundation; either version 3 of the License, or
dnl (at your option) any later version.
dnl
dnl GNU tar is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License along
dnl with GNU tar. If not, see <http://www.gnu.org/licenses/>.
dnl You should have received a copy of the GNU General Public License
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_DEFUN([TAR_COMPR_PROGRAM],[
m4_pushdef([tar_compr_define],translit($1,[a-z+-],[A-ZX_])[_PROGRAM])
@@ -24,3 +27,28 @@ AC_DEFUN([TAR_COMPR_PROGRAM],[
[tar_compr_var=m4_if($2,,$1,$2)])
AC_DEFINE_UNQUOTED(tar_compr_define, "$tar_compr_var",
[Define to the program name of ]$1[ compressor program])])
# Provide <attr/xattr.h>, if necessary
AC_DEFUN([TAR_HEADERS_ATTR_XATTR_H],
[
AC_ARG_WITH([xattrs],
AS_HELP_STRING([--without-xattrs], [don't use linux extended attributes]),
[], [with_xattrs=maybe]
)
AC_CHECK_HEADERS([attr/xattr.h])
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_attr_xattr_h" = 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
])

508
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 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,46 +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
}
@@ -456,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
@@ -489,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
@@ -507,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
@@ -547,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
@@ -583,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
@@ -598,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
@@ -617,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`
@@ -661,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
@@ -704,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.
@@ -720,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 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,30 +1,28 @@
# Configure template for GNU tar. -*- autoconf -*-
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
# Software Foundation, Inc.
# Copyright 1991, 1994-2010, 2013 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.23], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.27], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_PREREQ([2.63])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-shar std-options silent-rules])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-xz dist-shar std-options silent-rules])
# Enable silent rules by default:
AM_SILENT_RULES([yes])
@@ -40,8 +38,8 @@ 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)
@@ -70,6 +68,28 @@ if test $diff_cv_st_fstype_string = yes; then
[Define if struct stat has a char st_fstype[] member.])
fi
# 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=no])
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; 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_SIGNAL
AC_TYPE_MODE_T
AC_TYPE_PID_T
@@ -90,13 +110,114 @@ 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])
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
AC_CHECK_DECLS([time],,, [#include <time.h>])
AC_REPLACE_FUNCS(waitpid)
AC_ARG_VAR([RSH], [Configure absolute path to default remote shell binary])
AC_CACHE_CHECK(for remote shell, tar_cv_path_RSH,
[if test -n "$RSH"; then
tar_cv_path_RSH=$RSH
@@ -157,7 +278,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 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>

2
doc/.gitignore vendored
View File

@@ -1,7 +1,7 @@
genfile.texi
getdate.texi
header.texi
manual
parse-datetime.texi
stamp-vti
tar.aux
tar.cp

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 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,9 +25,9 @@ tar_TEXINFOS = \
fdl.texi\
freemanuals.texi\
genfile.texi\
getdate.texi\
header.texi\
intern.texi\
parse-datetime.texi\
rendition.texi\
snapshot.texi\
sparse.texi\
@@ -34,7 +35,7 @@ tar_TEXINFOS = \
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
# Just call 'make RENDITION=PROOF [target]' if you want PROOF rendition.
RENDITION = DISTRIB
MAKEINFOFLAGS=-D$(RENDITION)
@@ -124,7 +125,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
#
@@ -144,4 +145,3 @@ manual:
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
$(GENDOCS) --texi2html tar 'GNU tar manual'

View File

@@ -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,12 @@
@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, 2001, 2002, 2007, 2008 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 +92,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 +111,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 +382,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 +423,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 +472,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 +481,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 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

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

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

View File

@@ -232,4 +232,3 @@ 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

@@ -6,24 +6,28 @@
@cindex Device numbers, changing
@cindex snapshot files, editing
@cindex snapshot files, fixing device numbers
Sometimes device numbers can change after upgrading your kernel
version or reconfiguring the hardware. Reportedly this is the case with
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
Various situations can cause device numbers to change: upgrading your
kernel version, reconfiguring your hardware, loading kernel modules in a
different order, using virtual volumes that are assembled dynamically
(such as with @acronym{LVM} or @acronym{RAID}), hot-plugging drives
(e.g. external USB or Firewire drives), etc. In the majority of
cases this change is unnoticed by the users. However, it influences
@command{tar} incremental backups: the device number is stored in tar
snapshot files (@pxref{Snapshot Files}) and is used to determine whether
the file has changed since the last backup. If the device numbers
change for some reason, the next backup you run will be a full backup.
change for some reason, by default the next backup you run will be a
full backup.
@pindex tar-snapshot-edit
To minimize the impact in these cases, GNU @command{tar} comes with
the @command{tar-snapshot-edit} utility for inspecting and updating
device numbers in snapshot files. The utility, written by
Dustin J.@: Mitchell, is available from
device numbers in snapshot files. (The utility, written by
Dustin J.@: Mitchell, is also available from the
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
@GNUTAR{} home page}.
@GNUTAR{} home page}.)
To obtain the device numbers used in the snapshot file, run
To obtain a summary of the device numbers found in the snapshot file, run
@smallexample
$ @kbd{tar-snapshot-edit @var{snapfile}}
@@ -31,10 +35,19 @@ $ @kbd{tar-snapshot-edit @var{snapfile}}
@noindent
where @var{snapfile} is the name of the snapshot file (you can supply as many
files as you wish in a single command line).
files as you wish in a single command line). You can then compare the
numbers across snapshot files, or against those currently in use on the
live filesystem (using @command{ls -l} or @command{stat}).
To update all occurrences of the given device number in the file, use
@option{-r} option. It takes a single argument of the form
Assuming the device numbers have indeed changed, it's often possible
to simply tell @GNUTAR{} to ignore the device number when processing the
incremental snapshot files for these backups, using the
@option{--no-check-device} option (@pxref{device numbers}).
Alternatively, you can use the @command{tar-edit-snapshot} script's
@option{-r} option to update all occurrences of the given device
number in the snapshot file(s). It takes a single argument
of the form
@samp{@var{olddev}-@var{newdev}}, where @var{olddev} is the device number
used in the snapshot file, and @var{newdev} is the corresponding new device
number. Both numbers may be specified in hex (e.g., @samp{0xfe01}),
@@ -49,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

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 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,5 @@
@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 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@macro GNUTAR
@@ -18,5 +17,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,24 +1,47 @@
# List of gnulib modules needed for GNU tar.
# A module name per line. Empty lines and comments are ignored.
# Copyright 2005-2010, 2012-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/>.
acl
alloca
argmatch
argp
argp-version-etc
backupfile
canonicalize
closeout
configmake
dirname
error
exclude
extern-inline
exitfail
fchmodat
fchownat
fcntl-h
fdopendir
fdutimensat
fileblocks
fnmatch-gnu
fseeko
ftruncate
fstatat
full-write
getdate
futimens
getline
getopt-gnu
getpagesize
@@ -27,20 +50,30 @@ gettime
gitlog-to-changelog
hash
human
inttostr
inttypes
lchown
linkat
localcharset
manywarnings
mkdirat
mkdtemp
mkfifoat
modechange
obstack
openat
parse-datetime
priv-set
progname
quote
quotearg
readlinkat
renameat
root-uid
rpmatch
safe-read
save-cwd
savedir
selinux-at
setenv
snprintf
stat-time
@@ -51,10 +84,12 @@ strdup-posix
strerror
strtol
strtoul
symlinkat
timespec
unlinkat
unlinkdir
unlocked-io
utimens
utimensat
version-etc-fsf
xalloc
xalloc-die

10
lib/.gitignore vendored Normal file
View File

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

View File

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

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

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

View File

@@ -1,5 +1,5 @@
/* Parse arguments from a string and prepend them to an argv.
Copyright 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
Copyright 1999-2001, 2007, 2013 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>. */

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

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

@@ -0,0 +1,66 @@
/* Prototypes for openat-style fd-relative functions for operating with
extended file attributes.
Copyright 2012-2013 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>
#include <attr/xattr.h>
/* 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 Free Software
# Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This file is part of GNU tar.
# This program is distributed in the hope that it will be useful,
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Library files
gnu/argmatch.c
@@ -37,7 +37,6 @@ gnu/version-etc.c
gnu/xalloc-die.c
lib/paxerror.c
lib/paxexit.c
lib/paxnames.c
lib/rtapelib.c

View File

@@ -1,19 +1,21 @@
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
# Make GNU tar scripts.
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3, or (at your option)
## any later version.
# Copyright 2004, 2006, 2007, 2013 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 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 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-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/>.
# 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 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 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 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,25 +1,27 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
Copyright 2006, 2007, 2010, 2013 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>
@@ -39,7 +41,7 @@
struct sp_array
{
off_t offset;
size_t numbytes;
off_t numbytes;
};
char *progname;
@@ -129,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);
@@ -163,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;
@@ -186,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)
@@ -226,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)
{
@@ -234,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
@@ -251,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)
@@ -267,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);
@@ -277,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);
}
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);
@@ -342,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 == '/')
@@ -358,7 +363,7 @@ guess_outname (char *name)
for (p--; p > name && *p != '/'; p--)
;
}
if (*p != '/')
{
if (s)
@@ -389,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)
{
@@ -408,7 +413,7 @@ main (int argc, char **argv)
case 'v':
verbose++;
break;
default:
exit (1);
}
@@ -429,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);
@@ -460,7 +465,7 @@ main (int argc, char **argv)
if (verbose)
printf ("Done\n");
if (outsize)
{
if (stat (outname, &st))
@@ -468,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,26 +1,26 @@
# Makefile for GNU tar sources.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007, 2009 Free Software Foundation, Inc.
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2009, 2013 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\
@@ -42,10 +42,12 @@ tar_SOURCES = \
unlink.c\
update.c\
utf8.c\
warning.c
warning.c\
xattrs.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)

View File

@@ -1,19 +1,20 @@
/* Long integers, for GNU tar.
Copyright 1999, 2007 Free Software Foundation, Inc.
Copyright 1999, 2007, 2013 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,19 +1,21 @@
/* Checkpoint management for tar.
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright 2007, 2013 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"
@@ -77,7 +79,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)
@@ -113,20 +115,20 @@ checkpoint_compile_action (const char *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 *
static char *
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
{
const char *opstr = do_write ? gettext ("write") : gettext ("read");
@@ -147,7 +149,7 @@ expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
case 'u':
outlen += cpslen - 2;
break;
case 's':
outlen += opstrlen - 2;
}
@@ -164,11 +166,11 @@ expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
case 'u':
op = stpcpy (op, cps);
break;
case 's':
op = stpcpy (op, opstr);
break;
default:
*op++ = '%';
*op++ = *ip;
@@ -188,7 +190,7 @@ 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,7 +209,7 @@ run_checkpoint_actions (bool do_write)
fflush (tty);
}
break;
case cop_echo:
{
char *tmp;
@@ -215,16 +217,16 @@ run_checkpoint_actions (bool do_write)
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'' */
/* 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'' */
/* 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);
@@ -232,7 +234,7 @@ run_checkpoint_actions (bool do_write)
free (tmp);
}
break;
case cop_ttyout:
if (!tty)
tty = fopen ("/dev/tty", "w");
@@ -245,11 +247,11 @@ run_checkpoint_actions (bool do_write)
free (tmp);
}
break;
case cop_sleep:
sleep (p->v.time);
break;
case cop_exec:
sys_exec_checkpoint_script (p->v.command,
archive_name_cursor[0],
@@ -266,5 +268,4 @@ checkpoint_run (bool do_write)
{
if (checkpoint_option && !(++checkpoint % checkpoint_option))
run_checkpoint_actions (do_write);
}
}

View File

@@ -1,22 +1,22 @@
/* Common declarations for the tar program.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
Inc.
Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2012-2013 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
This file is part of GNU tar.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Declare the GNU tar archive format. */
#include "tar.h"
@@ -70,6 +70,11 @@
#define LG_8 3
#define LG_64 6
#define LG_256 8
_GL_INLINE_HEADER_BEGIN
#ifndef COMMON_INLINE
# define COMMON_INLINE _GL_INLINE
#endif
/* Information gleaned from the command line. */
@@ -105,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.
@@ -136,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;
@@ -156,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;
@@ -180,10 +185,13 @@ enum old_files
OVERWRITE_OLD_FILES, /* --overwrite */
UNLINK_FIRST_OLD_FILES, /* --unlink-first */
KEEP_OLD_FILES, /* --keep-old-files */
SKIP_OLD_FILES, /* --skip-old-files */
KEEP_NEWER_FILES /* --keep-newer-files */
};
GLOBAL enum old_files old_files_option;
GLOBAL bool keep_directory_symlink_option;
/* Specified file name for incremental list. */
GLOBAL const char *listed_incremental_option;
/* Incremental dump level */
@@ -228,7 +236,8 @@ GLOBAL bool numeric_owner_option;
GLOBAL bool one_file_system_option;
/* 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;
@@ -237,9 +246,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;
@@ -251,6 +257,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;
@@ -311,11 +326,10 @@ GLOBAL struct timespec last_stat_time; /* when the statistics was last
GLOBAL struct tar_stat_info current_stat_info;
/* List of tape drive names, number of such tape drives, allocated number,
/* List of tape drive names, number of such tape drives,
and current cursor in list. */
GLOBAL const char **archive_name_array;
GLOBAL size_t archive_names;
GLOBAL size_t allocated_archive_names;
GLOBAL const char **archive_name_cursor;
/* Output index file name. */
@@ -335,12 +349,12 @@ struct 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 */
/* The following members are used for incremental dumps only,
if this struct name represents a directory;
see incremen.c */
@@ -355,6 +369,11 @@ struct name
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;
@@ -425,13 +444,17 @@ 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);
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
@@ -443,13 +466,14 @@ 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, bool 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);
@@ -459,33 +483,18 @@ union block * write_extended (bool global, struct tar_stat_info *st,
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 (const 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. */
@@ -507,18 +516,8 @@ 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 (char *dir, dev_t device, bool cmdline);
void name_fill_directory (struct name *name, dev_t device, bool cmdline);
struct directory *scan_directory (struct tar_stat_info *st);
const char *directory_contents (struct directory *dir);
const char *safe_directory_contents (struct directory *dir);
@@ -527,14 +526,16 @@ void rebase_directory (struct directory *dir,
const char *repl, size_t rlen);
void append_incremental_renames (struct directory *dir);
void show_snapshot_field_ranges (void);
void read_directory_file (void);
void write_directory_file (void);
void purge_directory (char const *directory_name);
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. */
@@ -566,27 +567,13 @@ 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, hbits) \
mode_from_header (where, sizeof (where), hbits)
#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, unsigned *hbits);
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);
void list_archive (void);
@@ -604,24 +591,65 @@ 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 (const char *name);
char *normalize_filename (int cdidx, const char *name);
void normalize_filename_x (char *name);
void replace_prefix (char **pname, const char *samp, size_t slen,
const char *repl, size_t rlen);
char *tar_savedir (const char *name, int must_exist);
typedef struct namebuf *namebuf_t;
namebuf_t namebuf_create (const char *dir);
void namebuf_free (namebuf_t buf);
char *namebuf_name (namebuf_t buf, const char *name);
void namebuf_add_dir (namebuf_t buf, const char *name);
char *namebuf_finish (namebuf_t buf);
const char *tar_getcdpath (int);
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
{
@@ -641,8 +669,13 @@ 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);
@@ -656,8 +689,6 @@ void seek_diag_details (char const *name, off_t offset);
void stat_diag (char const *name);
void file_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name));
void dir_removed_diag (char const *name, bool top_level,
void (*diagfn) (char const *name));
void write_error_details (char const *name, size_t status, size_t size);
void write_fatal (char const *name) __attribute__ ((noreturn));
void write_fatal_details (char const *name, ssize_t status, size_t size)
@@ -667,11 +698,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);
@@ -682,6 +714,7 @@ int uname_to_uid (char const *uname, uid_t *puid);
void name_init (void);
void name_add_name (const char *name, int matching_flags);
void name_add_dir (const char *name);
void name_add_file (const char *name, int term);
void name_term (void);
const char *name_next (int change_dirs);
void name_gather (void);
@@ -690,6 +723,7 @@ struct name *addname (char const *string, int change_dir,
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);
struct name const *name_from_list (void);
@@ -702,7 +736,6 @@ 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);
@@ -716,9 +749,9 @@ 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);
@@ -726,20 +759,25 @@ const char *archive_format_string (enum archive_format fmt);
const char *subcommand_string (enum subcommand c);
void set_exit_status (int val);
void request_stdin (const char *option);
void more_options (int argc, char **argv);
/* Module update.c. */
extern char *output_start;
void update_archive (void);
/* Module attrs.c. */
#include "xattrs.h"
/* Module xheader.c. */
void xheader_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_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);
@@ -753,6 +791,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 */
@@ -777,7 +821,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);
@@ -800,12 +845,12 @@ 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);
/* Module checkpoint.c */
void checkpoint_compile_action (const char *str);
@@ -832,11 +877,16 @@ void checkpoint_run (bool do_write);
#define WARN_UNKNOWN_CAST 0x00010000
#define WARN_UNKNOWN_KEYWORD 0x00020000
#define WARN_XDEV 0x00040000
#define WARN_DECOMPRESS_PROGRAM 0x00080000
#define WARN_EXISTING_FILE 0x00100000
#define WARN_XATTR_WRITE 0x00200000
#define WARN_RECORD_SIZE 0x00400000
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
in verbose mode */
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY)
#define WARN_ALL (0xffffffff & ~WARN_VERBOSE_WARNINGS)
/* 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);
@@ -857,3 +907,4 @@ void finish_deferred_unlinks (void);
/* Module exit.c */
extern void (*fatal_exit_hook) (void);
_GL_INLINE_HEADER_END

View File

@@ -1,23 +1,24 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2007,
2009-2010, 2012-2013 Free Software Foundation, Inc.
Written by John Gilmore, on 1987-04-30.
This file is part of GNU tar.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by John Gilmore, on 1987-04-30. */
#include <system.h>
#include <system-ioctl.h>
@@ -80,7 +81,7 @@ process_noop (size_t size __attribute__ ((unused)),
static int
process_rawdata (size_t bytes, char *buffer)
{
size_t status = safe_read (diff_handle, diff_buffer, bytes);
size_t status = blocking_read (diff_handle, diff_buffer, bytes);
if (status != bytes)
{
@@ -122,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 ();
@@ -151,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)
{
@@ -217,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)
{
@@ -239,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);
}
@@ -277,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)
{
@@ -331,7 +328,7 @@ static int
dumpdir_cmp (const char *a, const char *b)
{
size_t len;
while (*a)
switch (*a)
{
@@ -345,7 +342,7 @@ dumpdir_cmp (const char *a, const char *b)
a += len;
b += len;
break;
case 'D':
if (strcmp(a, b))
return 1;
@@ -353,7 +350,7 @@ dumpdir_cmp (const char *a, const char *b)
a += len;
b += len;
break;
case 'R':
case 'T':
case 'X':
@@ -363,32 +360,35 @@ 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;
else
stat_error (current_stat_info.file_name);
dir->fd = fd;
if (diag)
{
file_removed_diag (dir->orig_file_name, false, diag);
return;
}
}
else
dev = stat_data.st_dev;
dumpdir_buffer = directory_contents
(scan_directory (current_stat_info.file_name, dev, false));
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 +415,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)
{
@@ -452,7 +455,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. */
@@ -466,7 +468,7 @@ diff_archive (void)
switch (current_header->header.typeflag)
{
default:
ERROR ((0, 0, _("%s: Unknown file type `%c', diffed as normal file"),
ERROR ((0, 0, _("%s: Unknown file type '%c', diffed as normal file"),
quotearg_colon (current_stat_info.file_name),
current_header->header.typeflag));
/* Fall through. */
@@ -503,7 +505,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 +520,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,8 +591,8 @@ verify_volume (void)
flush_read ();
while (1)
{
enum read_header status = read_header (&current_header,
&current_stat_info,
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_auto);
if (status == HEADER_FAILURE)
@@ -609,7 +622,7 @@ verify_volume (void)
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (&current_header, &current_stat_info,
status = read_header (&current_header, &current_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
@@ -617,8 +630,10 @@ verify_volume (void)
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
}
continue;
}
decode_header (current_header, &current_stat_info, &current_format, 1);
diff_archive ();
tar_stat_destroy (&current_stat_info);
}

View File

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

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, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994, 1996-1997, 2000-2001, 2003-2006, 2010,
2013 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>
@@ -262,7 +263,7 @@ delete_archive_members (void)
if (current_block == record_end)
flush_archive ();
status = read_header (&current_header, &current_stat_info,
status = read_header (&current_header, &current_stat_info,
read_header_auto);
xheader_decode (&current_stat_info);
@@ -296,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,19 +1,21 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
/* Exit from GNU tar.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
Copyright 2009, 2013 Free Software Foundation, Inc.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
This file is part of GNU tar.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"

File diff suppressed because it is too large Load Diff

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, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2013
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,18 +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 */
union block *recent_global_header; /* Recent global header block */
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] =
@@ -61,6 +74,66 @@ 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);
}
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);
}
}
/* Main loop for reading an archive. */
void
read_and (void (*do_something) (void))
@@ -78,7 +151,7 @@ read_and (void (*do_something) (void))
prev_status = status;
tar_stat_destroy (&current_stat_info);
status = read_header (&current_header, &current_stat_info,
status = read_header (&current_header, &current_stat_info,
read_header_auto);
switch (status)
{
@@ -90,7 +163,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
@@ -116,13 +190,12 @@ 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;
@@ -140,7 +213,7 @@ read_and (void (*do_something) (void))
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (&current_header, &current_stat_info,
status = read_header (&current_header, &current_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
@@ -210,8 +283,6 @@ list_archive (void)
off_t block_ordinal = current_block_ordinal ();
/* Print the header block. */
decode_header (current_header, &current_stat_info, &current_format, 0);
if (verbose_option)
print_header (&current_stat_info, current_header, block_ordinal);
@@ -245,7 +316,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;
@@ -270,9 +341,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;
@@ -335,7 +405,11 @@ read_header (union block **return_block, struct tar_stat_info *info,
if (header->header.typeflag == LNKTYPE)
info->stat.st_size = 0; /* links 0 size on tape */
else
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
{
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
if (info->stat.st_size < 0)
return HEADER_FAILURE;
}
if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK
@@ -361,15 +435,13 @@ read_header (union block **return_block, struct tar_stat_info *info,
if (header->header.typeflag == GNUTYPE_LONGNAME)
{
if (next_long_name)
free (next_long_name);
free (next_long_name);
next_long_name = header_copy;
next_long_name_blocks = size / BLOCKSIZE;
}
else
{
if (next_long_link)
free (next_long_link);
free (next_long_link);
next_long_link = header_copy;
next_long_link_blocks = size / BLOCKSIZE;
}
@@ -428,8 +500,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
struct posix_header const *h = &header->header;
char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
if (recent_long_name)
free (recent_long_name);
free (recent_long_name);
if (next_long_name)
{
@@ -460,8 +531,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
assign_string (&info->file_name, name);
info->had_trailing_slash = strip_trailing_slashes (info->file_name);
if (recent_long_link)
free (recent_long_link);
free (recent_long_link);
if (next_long_link)
{
@@ -484,47 +554,6 @@ read_header (union block **return_block, struct tar_stat_info *info,
}
}
static char *
decode_xform (char *file_name, void *data)
{
int type = *(int*)data;
switch (type)
{
case XFORM_SYMLINK:
/* FIXME: It is not quite clear how and to which extent are the symbolic
links subject to filename transformation. In the absence of another
solution, symbolic links are exempt from component stripping and
name suffix normalization, but subject to filename transformation
proper. */
return file_name;
case XFORM_LINK:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case XFORM_REGFILE:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
prefix_len = strlen (file_name);
file_name += prefix_len;
}
return file_name;
}
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
@@ -545,9 +574,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group)
{
enum archive_format format;
unsigned hbits; /* high bits of the file mode. */
bool hbits;
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
if (strcmp (header->header.magic, TMAGIC) == 0)
{
if (header->star_header.prefix[130] == 0
@@ -561,7 +590,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
else
format = USTAR_FORMAT;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
else if (strcmp (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC)
== 0)
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
else
format = V7_FORMAT;
@@ -575,6 +606,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);
@@ -644,34 +677,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. */
@@ -699,14 +732,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;
}
@@ -730,7 +763,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++;
@@ -743,7 +776,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;
}
}
@@ -823,7 +856,7 @@ from_header (char const *where0, size_t digs, char const *type,
return -1;
}
}
negative = signbit;
negative = signbit != 0;
if (negative)
value = -value;
}
@@ -843,7 +876,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.) */
@@ -855,7 +888,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)
{
@@ -877,39 +910,38 @@ 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);
}
/* Convert P to the file mode, as understood by tar.
Store unrecognized mode bits (from 10th up) in HBITS. */
mode_t
mode_from_header (const char *p, size_t s, unsigned *hbits)
Set *HBITS if there are any unrecognized bits. */
static mode_t
mode_from_header (const char *p, size_t s, bool *hbits)
{
unsigned u = from_header (p, s, "mode_t",
- (uintmax_t) TYPE_MINIMUM (mode_t),
TYPE_MAXIMUM (uintmax_t), false, false);
intmax_t u = from_header (p, s, "mode_t",
INTMAX_MIN, UINTMAX_MAX,
false, false);
mode_t mode = ((u & TSUID ? S_ISUID : 0)
| (u & TSGID ? S_ISGID : 0)
| (u & TSVTX ? S_ISVTX : 0)
@@ -922,7 +954,7 @@ mode_from_header (const char *p, size_t s, unsigned *hbits)
| (u & TOREAD ? S_IROTH : 0)
| (u & TOWRITE ? S_IWOTH : 0)
| (u & TOEXEC ? S_IXOTH : 0));
*hbits = mode ^ u;
*hbits = (u & ~07777) != 0;
return mode;
}
@@ -931,38 +963,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);
}
@@ -1052,13 +1077,14 @@ static void
simple_print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal)
{
char modes[11];
char modes[12];
char const *time_stamp;
int time_stamp_len;
char *temp_name;
/* These hold formatted ints. */
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
char uform[max (INT_BUFSIZE_BOUND (intmax_t), UINTMAX_STRSIZE_BOUND)];
char gform[sizeof uform];
char *user, *group;
char size[2 * UINTMAX_STRSIZE_BOUND];
/* holds formatted size or major,minor */
@@ -1144,9 +1170,12 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
pax_decode_mode (st->stat.st_mode, modes + 1);
/* extended attributes: GNU `ls -l'-like preview */
xattrs_print_char (st, modes + 10);
/* Time stamp. */
time_stamp = tartime (st->mtime, false);
time_stamp = tartime (st->mtime, full_time_option);
time_stamp_len = strlen (time_stamp);
if (datewidth < time_stamp_len)
datewidth = time_stamp_len;
@@ -1165,17 +1194,11 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
ids that are too large to fit in a uid_t. */
uintmax_t u = from_header (blk->header.uid,
sizeof blk->header.uid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
0, UINTMAX_MAX,
false, false);
if (u != -1)
user = STRINGIFY_BIGINT (u, uform);
else
{
sprintf (uform, "%ld",
(long) UID_FROM_HEADER (blk->header.uid));
user = uform;
}
user = (u != -1
? STRINGIFY_BIGINT (u, uform)
: imaxtostr (UID_FROM_HEADER (blk->header.uid), uform));
}
if (st->gname
@@ -1190,17 +1213,11 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
ids that are too large to fit in a gid_t. */
uintmax_t g = from_header (blk->header.gid,
sizeof blk->header.gid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
0, UINTMAX_MAX,
false, false);
if (g != -1)
group = STRINGIFY_BIGINT (g, gform);
else
{
sprintf (gform, "%ld",
(long) GID_FROM_HEADER (blk->header.gid));
group = gform;
}
group = (g != -1
? STRINGIFY_BIGINT (g, gform)
: imaxtostr (GID_FROM_HEADER (blk->header.gid), gform));
}
/* Format the file size or major/minor device numbers. */
@@ -1289,11 +1306,12 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
}
}
fflush (stdlis);
xattrs_print (st);
}
void
print_volume_label ()
static void
print_volume_label (void)
{
struct tar_stat_info vstat;
union block vblk;
@@ -1345,8 +1363,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));
}
}
@@ -1356,7 +1374,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)
{
@@ -1391,7 +1409,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);
@@ -1403,7 +1421,7 @@ skip_member (void)
}
void
test_archive_label ()
test_archive_label (void)
{
base64_init ();
name_gather ();
@@ -1412,22 +1430,23 @@ test_archive_label ()
if (read_header (&current_header, &current_stat_info, read_header_auto)
== HEADER_SUCCESS)
{
char *s = NULL;
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
&& (name_match (volume_label)
|| (multi_volume_option
&& (s = drop_volume_label_suffix (volume_label))
&& name_match (s))))
if (verbose_option)
print_volume_label ();
free (s);
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 ();
names_notfound ();
label_notfound ();
}

View File

@@ -1,7 +1,7 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010,
2012-2013 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,24 +14,19 @@
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>
#include <canonicalize.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
@@ -42,11 +37,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
@@ -59,7 +56,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;
@@ -100,6 +97,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
@@ -107,7 +105,7 @@ quote_copy_string (const char *string)
completes the unquoting anyway.
This is used for reading the saved directory file in incremental
dumps. It is used for decoding old `N' records (demangling names).
dumps. It is used for decoding old 'N' records (demangling names).
But also, it is used for decoding file arguments, would they come
from the shell or a -T file, and for decoding the --exclude
argument. */
@@ -230,10 +228,82 @@ zap_slashes (char *name)
return name;
}
char *
normalize_filename (const char *name)
/* Normalize FILE_NAME by removing redundant slashes and "."
components, including redundant trailing slashes.
Leave ".." alone, as it may be significant in the presence
of symlinks and on platforms where "/.." != "/".
Destructive version: modifies its argument. */
void
normalize_filename_x (char *file_name)
{
return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
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? */
const char *cdpath = tar_getcdpath (cdidx);
size_t copylen;
bool need_separator;
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;
}
@@ -258,6 +328,76 @@ replace_prefix (char **pname, const char *samp, size_t slen,
/* Handling numbers. */
/* Convert VALUE, which is converted from a system integer type whose
minimum value is MINVAL and maximum MINVAL, to an decimal
integer string. Use the storage in BUF and return a pointer to the
converted string. If VALUE is converted from a negative integer in
the range MINVAL .. -1, represent it with a string representation
of the negative integer, using leading '-'. */
#if ! (INTMAX_MAX <= UINTMAX_MAX / 2)
# error "sysinttostr: uintmax_t cannot represent all intmax_t values"
#endif
char *
sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval,
char buf[SYSINT_BUFSIZE])
{
if (value <= maxval)
return umaxtostr (value, buf);
else
{
intmax_t i = value - minval;
return imaxtostr (i + minval, buf);
}
}
/* Convert a prefix of the string ARG to a system integer type whose
minimum value is MINVAL and maximum MAXVAL. If MINVAL is negative,
negative integers MINVAL .. -1 are assumed to be represented using
leading '-' in the usual way. If the represented value exceeds
INTMAX_MAX, return a negative integer V such that (uintmax_t) V
yields the represented value. If ARGLIM is nonnull, store into
*ARGLIM a pointer to the first character after the prefix.
This is the inverse of sysinttostr.
On a normal return, set errno = 0.
On conversion error, return 0 and set errno = EINVAL.
On overflow, return an extreme value and set errno = ERANGE. */
#if ! (INTMAX_MAX <= UINTMAX_MAX)
# error "strtosysint: nonnegative intmax_t does not fit in uintmax_t"
#endif
intmax_t
strtosysint (char const *arg, char **arglim, intmax_t minval, uintmax_t maxval)
{
errno = 0;
if (maxval <= INTMAX_MAX)
{
if (ISDIGIT (arg[*arg == '-']))
{
intmax_t i = strtoimax (arg, arglim, 10);
intmax_t imaxval = maxval;
if (minval <= i && i <= imaxval)
return i;
errno = ERANGE;
return i < minval ? minval : maxval;
}
}
else
{
if (ISDIGIT (*arg))
{
uintmax_t i = strtoumax (arg, arglim, 10);
if (i <= maxval)
return represent_uintmax (i);
errno = ERANGE;
return maxval;
}
}
errno = EINVAL;
return 0;
}
/* Output fraction and trailing digits appropriate for a nanoseconds
count equal to NS, but don't output unnecessary '.' or trailing
zeros. */
@@ -301,7 +441,7 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
/* ignore invalid values of ns */
if (BILLION <= ns || ns < 0)
ns = 0;
if (negative && ns != 0)
{
s++;
@@ -314,6 +454,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. */
@@ -322,7 +540,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);
@@ -363,7 +581,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,
@@ -383,7 +601,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
@@ -399,7 +617,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:
@@ -416,7 +634,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;
@@ -476,7 +694,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
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;
@@ -496,7 +714,8 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
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"),
@@ -523,7 +742,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"),
@@ -538,39 +758,90 @@ 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). */
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. */
@@ -582,8 +853,21 @@ 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 ()
chdir_count (void)
{
if (wd_count == 0)
return wd_count;
@@ -608,7 +892,8 @@ chdir_arg (char const *dir)
if (! wd_count)
{
wd[wd_count].name = ".";
wd[wd_count].saved = 0;
wd[wd_count].abspath = xgetcwd ();
wd[wd_count].fd = AT_FDCWD;
wd_count++;
}
}
@@ -625,67 +910,116 @@ chdir_arg (char const *dir)
}
wd[wd_count].name = dir;
wd[wd_count].saved = 0;
/* if the given name is an absolute path, then use that path
to represent this working directory; otherwise, construct
a path based on the previous -C option's absolute path */
if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name))
wd[wd_count].abspath = xstrdup (wd[wd_count].name);
else
{
namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
namebuf_add_dir (nbuf, wd[wd_count].name);
wd[wd_count].abspath = namebuf_finish (nbuf);
}
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.) */
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)
{
@@ -759,21 +1093,6 @@ file_removed_diag (const char *name, bool top_level,
(0, 0, _("%s: File removed before we read it"),
quotearg_colon (name)));
set_exit_status (TAREXIT_DIFFERS);
}
else
diagfn (name);
}
void
dir_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name))
{
if (!top_level && errno == ENOENT)
{
WARNOPT (WARN_FILE_REMOVED,
(0, 0, _("%s: Directory removed before we read it"),
quotearg_colon (name)));
set_exit_status (TAREXIT_DIFFERS);
}
else
diagfn (name);
@@ -835,7 +1154,7 @@ page_aligned_alloc (void **ptr, size_t size)
struct namebuf
{
char *buffer; /* directory, `/', and directory member */
char *buffer; /* directory, '/', and directory member */
size_t buffer_size; /* allocated size of name_buffer */
size_t dir_length; /* length of directory part in buffer */
};
@@ -870,5 +1189,54 @@ namebuf_name (namebuf_t buf, const char *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_error (name);
if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
savedir_error (name);
return ret;
}

View File

@@ -1,7 +1,7 @@
/* Various processing of names.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994, 1996-2001, 2003-2007, 2009, 2013 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,28 +14,20 @@
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <fnmatch.h>
#include <hash.h>
#include <quotearg.h>
#include <wordsplit.h>
#include <argp.h>
#include "common.h"
/* User and group names. */
struct group *getgrnam ();
struct passwd *getpwnam ();
#if ! HAVE_DECL_GETPWUID
struct passwd *getpwuid ();
#endif
#if ! HAVE_DECL_GETGRGID
struct group *getgrgid ();
#endif
/* Make sure you link with the proper libraries if you are running the
Yellow Peril (thanks for the good laugh, Ian J.!), or, euh... NIS.
This code should also be modified for non-UNIX systems to do something
@@ -56,8 +48,6 @@ static char *cached_no_such_gname;
static uid_t cached_no_such_uid;
static gid_t cached_no_such_gid;
static void register_individual_file (char const *name);
/* Given UID, find the corresponding UNAME. */
void
uid_to_uname (uid_t uid, char **uname)
@@ -179,7 +169,7 @@ gname_to_gid (char const *gname, gid_t *gidp)
}
struct name *
static struct name *
make_name (const char *file_name)
{
struct name *p = xzalloc (sizeof (*p));
@@ -190,7 +180,7 @@ make_name (const char *file_name)
return p;
}
void
static void
free_name (struct name *p)
{
if (p)
@@ -207,49 +197,83 @@ free_name (struct name *p)
static struct name *namelist; /* first name in list, if any */
static struct name *nametail; /* end of name list */
/* File name arguments are processed in two stages: first a
name_array (see below) is filled, then the names from it
/* File name arguments are processed in two stages: first a
name element list (see below) is filled, then the names from it
are moved into the namelist.
This awkward process is needed only to implement --same-order option,
which is meant to help process large archives on machines with
limited memory. With this option on, namelist contains at most one
entry, which diminishes the memory consumption.
However, I very much doubt if we still need this -- Sergey */
/* A name_array element contains entries of three types: */
/* A name_list element contains entries of three types: */
#define NELT_NAME 0 /* File name */
#define NELT_CHDIR 1 /* Change directory request */
#define NELT_FMASK 2 /* Change fnmatch options request */
#define NELT_FILE 3 /* Read file names from that file */
#define NELT_NOOP 4 /* No operation */
struct name_elt /* A name_array element. */
{
struct name_elt *next, *prev;
char type; /* Element type, see NELT_* constants above */
union
{
const char *name; /* File or directory name */
int matching_flags;/* fnmatch options if type == NELT_FMASK */
int matching_flags;/* fnmatch options if type == NELT_FMASK */
struct /* File, if type == NELT_FILE */
{
const char *name;/* File name */
int term; /* File name terminator in the list */
FILE *fp;
} file;
} v;
};
static struct name_elt *name_array; /* store an array of names */
static size_t allocated_names; /* how big is the array? */
static size_t names; /* how many entries does it have? */
static size_t name_index; /* how many of the entries have we scanned? */
static struct name_elt *name_head; /* store a list of names */
size_t name_count; /* how many of the entries are names? */
/* Check the size of name_array, reallocating it as necessary. */
static void
check_name_alloc ()
static struct name_elt *
name_elt_alloc (void)
{
if (names == allocated_names)
struct name_elt *elt;
elt = xmalloc (sizeof (*elt));
if (!name_head)
{
if (allocated_names == 0)
allocated_names = 10; /* Set initial allocation */
name_array = x2nrealloc (name_array, &allocated_names,
sizeof (name_array[0]));
name_head = elt;
name_head->prev = name_head->next = NULL;
name_head->type = NELT_NOOP;
elt = xmalloc (sizeof (*elt));
}
elt->prev = name_head->prev;
if (name_head->prev)
name_head->prev->next = elt;
elt->next = name_head;
name_head->prev = elt;
return elt;
}
static void
name_list_adjust (void)
{
if (name_head)
while (name_head->prev)
name_head = name_head->prev;
}
static void
name_list_advance (void)
{
struct name_elt *elt = name_head;
name_head = elt->next;
if (name_head)
name_head->prev = NULL;
free (elt);
}
/* Add to name_array the file NAME with fnmatch options MATCHING_FLAGS */
@@ -257,33 +281,38 @@ void
name_add_name (const char *name, int matching_flags)
{
static int prev_flags = 0; /* FIXME: Or EXCLUDE_ANCHORED? */
struct name_elt *ep;
struct name_elt *ep = name_elt_alloc ();
check_name_alloc ();
ep = &name_array[names++];
if (prev_flags != matching_flags)
{
ep->type = NELT_FMASK;
ep->v.matching_flags = matching_flags;
prev_flags = matching_flags;
check_name_alloc ();
ep = &name_array[names++];
ep = name_elt_alloc ();
}
ep->type = NELT_NAME;
ep->v.name = name;
name_count++;
}
/* Add to name_array a chdir request for the directory NAME */
void
name_add_dir (const char *name)
{
struct name_elt *ep;
check_name_alloc ();
ep = &name_array[names++];
struct name_elt *ep = name_elt_alloc ();
ep->type = NELT_CHDIR;
ep->v.name = name;
}
}
void
name_add_file (const char *name, int term)
{
struct name_elt *ep = name_elt_alloc ();
ep->type = NELT_FILE;
ep->v.file.name = name;
ep->v.file.term = term;
ep->v.file.fp = NULL;
}
/* Names from external name file. */
@@ -297,15 +326,222 @@ name_init (void)
{
name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
name_buffer_length = NAME_FIELD_SIZE;
name_list_adjust ();
}
void
name_term (void)
{
free (name_buffer);
free (name_array);
}
/* Prevent recursive inclusion of the same file */
struct file_id_list
{
struct file_id_list *next;
ino_t ino;
dev_t dev;
const char *from_file;
};
static struct file_id_list *file_id_list;
/* Return the name of the file from which the file names and options
are being read.
*/
static const char *
file_list_name (void)
{
struct name_elt *elt;
for (elt = name_head; elt; elt = elt->next)
if (elt->type == NELT_FILE && elt->v.file.fp)
return elt->v.file.name;
return _("command line");
}
static int
add_file_id (const char *filename)
{
struct file_id_list *p;
struct stat st;
const char *reading_from;
if (stat (filename, &st))
stat_fatal (filename);
reading_from = file_list_name ();
for (p = file_id_list; p; p = p->next)
if (p->ino == st.st_ino && p->dev == st.st_dev)
{
int oldc = set_char_quoting (NULL, ':', 1);
ERROR ((0, 0,
_("%s: file list requested from %s already read from %s"),
quotearg_n (0, filename),
reading_from, p->from_file));
set_char_quoting (NULL, ':', oldc);
return 1;
}
p = xmalloc (sizeof *p);
p->next = file_id_list;
p->ino = st.st_ino;
p->dev = st.st_dev;
p->from_file = reading_from;
file_id_list = p;
return 0;
}
enum read_file_list_state /* Result of reading file name from the list file */
{
file_list_success, /* OK, name read successfully */
file_list_end, /* End of list file */
file_list_zero, /* Zero separator encountered where it should not */
file_list_skip /* Empty (zero-length) entry encountered, skip it */
};
/* Read from FP a sequence of characters up to TERM and put them
into STK.
*/
static enum read_file_list_state
read_name_from_file (struct name_elt *ent)
{
int c;
size_t counter = 0;
FILE *fp = ent->v.file.fp;
int term = ent->v.file.term;
for (c = getc (fp); c != EOF && c != term; c = getc (fp))
{
if (counter == name_buffer_length)
name_buffer = x2realloc (name_buffer, &name_buffer_length);
name_buffer[counter++] = c;
if (c == 0)
{
/* We have read a zero separator. The file possibly is
zero-separated */
return file_list_zero;
}
}
if (counter == 0 && c != EOF)
return file_list_skip;
if (counter == name_buffer_length)
name_buffer = x2realloc (name_buffer, &name_buffer_length);
name_buffer[counter] = 0;
return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
}
static int
handle_option (const char *str)
{
struct wordsplit ws;
int i;
while (*str && isspace (*str))
;
if (*str != '-')
return 1;
ws.ws_offs = 1;
if (wordsplit (str, &ws, WRDSF_DEFFLAGS|WRDSF_DOOFFS))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
str, wordsplit_strerror (&ws)));
ws.ws_wordv[0] = program_invocation_short_name;
more_options (ws.ws_wordc+ws.ws_offs, ws.ws_wordv);
for (i = 0; i < ws.ws_wordc+ws.ws_offs; i++)
ws.ws_wordv[i] = NULL;
wordsplit_free (&ws);
return 0;
}
static int
read_next_name (struct name_elt *ent, struct name_elt *ret)
{
if (!ent->v.file.fp)
{
if (!strcmp (ent->v.file.name, "-"))
{
request_stdin ("-T");
ent->v.file.fp = stdin;
}
else
{
if (add_file_id (ent->v.file.name))
{
name_list_advance ();
return 1;
}
if ((ent->v.file.fp = fopen (ent->v.file.name, "r")) == NULL)
open_fatal (ent->v.file.name);
}
}
while (1)
{
switch (read_name_from_file (ent))
{
case file_list_skip:
continue;
case file_list_zero:
WARNOPT (WARN_FILENAME_WITH_NULS,
(0, 0, N_("%s: file name read contains nul character"),
quotearg_colon (ent->v.file.name)));
ent->v.file.term = 0;
/* fall through */
case file_list_success:
if (handle_option (name_buffer) == 0)
{
name_list_adjust ();
return 1;
}
ret->type = NELT_NAME;
ret->v.name = name_buffer;
return 0;
case file_list_end:
if (strcmp (ent->v.file.name, "-"))
fclose (ent->v.file.fp);
ent->v.file.fp = NULL;
name_list_advance ();
return 1;
}
}
}
static void
copy_name (struct name_elt *ep)
{
const char *source;
size_t source_len;
char *cursor;
source = ep->v.name;
source_len = strlen (source);
if (name_buffer_length < source_len)
{
do
{
name_buffer_length *= 2;
if (! name_buffer_length)
xalloc_die ();
}
while (name_buffer_length < source_len);
free (name_buffer);
name_buffer = xmalloc(name_buffer_length + 2);
}
strcpy (name_buffer, source);
/* Zap trailing slashes. */
cursor = name_buffer + strlen (name_buffer) - 1;
while (cursor > name_buffer && ISSLASH (*cursor))
*cursor-- = '\0';
}
static int matching_flags; /* exclude_fnmatch options */
/* Get the next NELT_NAME element from name_array. Result is in
@@ -313,64 +549,48 @@ static int matching_flags; /* exclude_fnmatch options */
If CHANGE_DIRS is true, treat any entries of type NELT_CHDIR as
the request to change to the given directory.
Entries of type NELT_FMASK cause updates of the matching_flags
value. */
struct name_elt *
static struct name_elt *
name_next_elt (int change_dirs)
{
static struct name_elt entry;
const char *source;
char *cursor;
struct name_elt *ep;
while (name_index != names)
while ((ep = name_head) != NULL)
{
struct name_elt *ep;
size_t source_len;
ep = &name_array[name_index++];
if (ep->type == NELT_FMASK)
switch (ep->type)
{
case NELT_NOOP:
name_list_advance ();
break;
case NELT_FMASK:
matching_flags = ep->v.matching_flags;
name_list_advance ();
continue;
}
source = ep->v.name;
source_len = strlen (source);
if (name_buffer_length < source_len)
{
do
case NELT_FILE:
if (read_next_name (ep, &entry) == 0)
return &entry;
continue;
case NELT_CHDIR:
if (change_dirs)
{
name_buffer_length *= 2;
if (! name_buffer_length)
xalloc_die ();
chdir_do (chdir_arg (xstrdup (ep->v.name)));
name_list_advance ();
break;
}
while (name_buffer_length < source_len);
free (name_buffer);
name_buffer = xmalloc (name_buffer_length + 2);
}
strcpy (name_buffer, source);
/* Zap trailing slashes. */
cursor = name_buffer + strlen (name_buffer) - 1;
while (cursor > name_buffer && ISSLASH (*cursor))
*cursor-- = '\0';
if (change_dirs && ep->type == NELT_CHDIR)
{
if (chdir (name_buffer) < 0)
chdir_fatal (name_buffer);
}
else
{
/* fall through */
case NELT_NAME:
copy_name (ep);
if (unquote_option)
unquote_string (name_buffer);
if (incremental_option)
register_individual_file (name_buffer);
entry.type = ep->type;
entry.v.name = name_buffer;
name_list_advance ();
return &entry;
}
}
@@ -421,7 +641,7 @@ name_gather (void)
buffer->directory = NULL;
buffer->parent = NULL;
buffer->cmdline = true;
namelist = nametail = buffer;
}
else if (change_dir)
@@ -519,7 +739,7 @@ name_match (const char *file_name)
if (!cursor)
return true;
if (cursor->name[0] == 0)
{
chdir_do (cursor->change_dir);
@@ -589,7 +809,7 @@ all_names_found (struct tar_stat_info *p)
return true;
}
static void
static int
regex_usage_warning (const char *name)
{
static int warned_once = 0;
@@ -603,6 +823,7 @@ regex_usage_warning (const char *name)
_("Use --wildcards to enable pattern matching,"
" or --no-wildcards to suppress this warning")));
}
return warned_once;
}
/* Print the names of things in the namelist that were not matched. */
@@ -615,12 +836,11 @@ names_notfound (void)
if (!WASFOUND (cursor) && cursor->name[0])
{
regex_usage_warning (cursor->name);
if (cursor->found_count == 0)
ERROR ((0, 0, _("%s: Not found in archive"),
quotearg_colon (cursor->name)));
else
ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
quotearg_colon (cursor->name)));
ERROR ((0, 0,
(cursor->found_count == 0) ?
_("%s: Not found in archive") :
_("%s: Required occurrence not found in archive"),
quotearg_colon (cursor->name)));
}
/* Don't bother freeing the name list; we're about to exit. */
@@ -639,14 +859,50 @@ names_notfound (void)
}
}
}
void
label_notfound (void)
{
struct name const *cursor;
if (!namelist)
return;
for (cursor = namelist; cursor; cursor = cursor->next)
if (WASFOUND (cursor))
return;
if (verbose_option)
error (0, 0, _("Archive label mismatch"));
set_exit_status (TAREXIT_DIFFERS);
for (cursor = namelist; cursor; cursor = cursor->next)
{
if (regex_usage_warning (cursor->name))
break;
}
/* Don't bother freeing the name list; we're about to exit. */
namelist = NULL;
nametail = NULL;
if (same_order_option)
{
const char *name;
while ((name = name_next (1)) != NULL
&& regex_usage_warning (name) == 0)
;
}
}
/* Sorting name lists. */
/* Sort *singly* linked LIST of names, of given LENGTH, using COMPARE
to order names. Return the sorted list. Note that after calling
this function, the `prev' links in list elements are messed up.
Apart from the type `struct name' and the definition of SUCCESSOR,
this function, the 'prev' links in list elements are messed up.
Apart from the type 'struct name' and the definition of SUCCESSOR,
this is a generic list-sorting function, but it's too painful to
make it both generic and portable
in C. */
@@ -752,17 +1008,15 @@ compare_names (struct name const *n1, struct name const *n2)
}
/* Add all the dirs under NAME, which names a directory, to the namelist.
If any of the files is a directory, recurse on the subdirectory.
DEVICE is the device not to leave, if the -l option is specified.
CMDLINE is true, if the NAME appeared on the command line. */
/* Add all the dirs under ST to the namelist NAME, descending the
directory hierarchy recursively. */
static void
add_hierarchy_to_namelist (struct name *name, dev_t device, bool cmdline)
add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
{
const char *buffer;
name_fill_directory (name, device, cmdline);
name->directory = scan_directory (st);
buffer = directory_contents (name->directory);
if (buffer)
{
@@ -790,6 +1044,8 @@ add_hierarchy_to_namelist (struct name *name, dev_t device, bool cmdline)
if (*string == 'D')
{
struct name *np;
struct tar_stat_info subdir;
int subfd;
if (allocated_length <= name_length + string_length)
{
@@ -810,7 +1066,38 @@ add_hierarchy_to_namelist (struct name *name, dev_t device, bool cmdline)
else
child_tail->sibling = np;
child_tail = np;
add_hierarchy_to_namelist (np, device, false);
tar_stat_init (&subdir);
subdir.parent = st;
if (st->fd < 0)
{
subfd = -1;
errno = - st->fd;
}
else
subfd = subfile_open (st, string + 1,
open_read_flags | O_DIRECTORY);
if (subfd < 0)
open_diag (namebuf);
else
{
subdir.fd = subfd;
if (fstat (subfd, &subdir.stat) != 0)
stat_diag (namebuf);
else if (! (O_DIRECTORY || S_ISDIR (subdir.stat.st_mode)))
{
errno = ENOTDIR;
open_diag (namebuf);
}
else
{
subdir.orig_file_name = xstrdup (namebuf);
add_hierarchy_to_namelist (&subdir, np);
restore_parent_fd (&subdir);
}
}
tar_stat_destroy (&subdir);
}
}
@@ -838,7 +1125,7 @@ name_compare (void const *entry1, void const *entry2)
}
/* Rebase `name' member of CHILD and all its siblings to
/* Rebase 'name' member of CHILD and all its siblings to
the new PARENT. */
static void
rebase_child_list (struct name *child, struct name *parent)
@@ -846,7 +1133,7 @@ rebase_child_list (struct name *child, struct name *parent)
size_t old_prefix_len = child->parent->length;
size_t new_prefix_len = parent->length;
char *new_prefix = parent->name;
for (; child; child = child->sibling)
{
size_t size = child->length - old_prefix_len + new_prefix_len;
@@ -858,7 +1145,7 @@ rebase_child_list (struct name *child, struct name *parent)
child->length = size;
rebase_directory (child->directory,
child->parent->name, old_prefix_len,
child->parent->name, old_prefix_len,
new_prefix, new_prefix_len);
}
}
@@ -871,11 +1158,10 @@ void
collect_and_sort_names (void)
{
struct name *name;
struct name *next_name, *prev_name;
struct name *next_name, *prev_name = NULL;
int num_names;
struct stat statbuf;
Hash_table *nametab;
name_gather ();
if (!namelist)
@@ -903,10 +1189,12 @@ collect_and_sort_names (void)
read_directory_file ();
}
num_names = 0;
for (name = namelist; name; name = name->next, num_names++)
{
struct tar_stat_info st;
if (name->found_count || name->directory)
continue;
if (name->matching_flags & EXCLUDE_WILDCARDS)
@@ -918,28 +1206,44 @@ collect_and_sort_names (void)
if (name->name[0] == 0)
continue;
if (deref_stat (dereference_option, name->name, &statbuf) != 0)
tar_stat_init (&st);
if (deref_stat (name->name, &st.stat) != 0)
{
stat_diag (name->name);
continue;
}
if (S_ISDIR (statbuf.st_mode))
if (S_ISDIR (st.stat.st_mode))
{
name->found_count++;
add_hierarchy_to_namelist (name, statbuf.st_dev, true);
int dir_fd = openat (chdir_fd, name->name,
open_read_flags | O_DIRECTORY);
if (dir_fd < 0)
open_diag (name->name);
else
{
st.fd = dir_fd;
if (fstat (dir_fd, &st.stat) != 0)
stat_diag (name->name);
else if (O_DIRECTORY || S_ISDIR (st.stat.st_mode))
{
st.orig_file_name = xstrdup (name->name);
name->found_count++;
add_hierarchy_to_namelist (&st, name);
}
}
}
tar_stat_destroy (&st);
}
namelist = merge_sort (namelist, num_names, compare_names);
num_names = 0;
nametab = hash_initialize (0, 0,
name_hash,
name_compare, NULL);
nametab = hash_initialize (0, 0, name_hash, name_compare, NULL);
for (name = namelist; name; name = next_name)
{
next_name = name->next;
name->caname = normalize_filename (name->name);
name->caname = normalize_filename (name->change_dir, name->name);
if (prev_name)
{
struct name *p = hash_lookup (nametab, name);
@@ -950,6 +1254,7 @@ collect_and_sort_names (void)
{
if (p->child)
rebase_child_list (p->child, name);
hash_delete (nametab, name);
/* FIXME: remove_directory (p->caname); ? */
remname (p);
free_name (p);
@@ -1024,7 +1329,7 @@ name_scan (const char *file_name)
struct name *gnu_list_name;
struct name const *
name_from_list ()
name_from_list (void)
{
if (!gnu_list_name)
gnu_list_name = namelist;
@@ -1071,28 +1376,6 @@ excluded_name (char const *name)
{
return excluded_file_name (excluded, name + FILE_SYSTEM_PREFIX_LEN (name));
}
static Hash_table *individual_file_table;
static void
register_individual_file (char const *name)
{
struct stat st;
if (deref_stat (dereference_option, name, &st) != 0)
return; /* Will be complained about later */
if (S_ISDIR (st.st_mode))
return;
hash_string_insert (&individual_file_table, name);
}
bool
is_individual_file (char const *name)
{
return hash_string_lookup (individual_file_table, name);
}
/* Return the size of the prefix of FILE_NAME that is removed after

View File

@@ -1,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 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 */
@@ -851,13 +853,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 +877,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 +917,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 +938,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 +978,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 +1003,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 +1015,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 +1030,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 +1085,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 +1131,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 +1140,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 +1151,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 +1172,7 @@ pax_decode_header (struct tar_sparse_file *file)
}
set_next_block_after (blk);
}
return true;
}
@@ -1168,7 +1182,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 Free Software Foundation, Inc.
Written by Sergey Poznyakoff.
@@ -27,7 +27,7 @@ struct compression_suffix
};
static struct compression_suffix compression_suffixes[] = {
#define __CAT2__(a,b) a ## b
#define __CAT2__(a,b) a ## b
#define S(s,p) #s, sizeof (#s) - 1, __CAT2__(p,_PROGRAM)
{ S(gz, GZIP) },
{ S(tgz, GZIP) },
@@ -43,6 +43,7 @@ static struct compression_suffix compression_suffixes[] = {
{ S(tlz, LZMA) },
{ S(lzo, LZOP) },
{ S(xz, XZ) },
{ S(txz, XZ) }, /* Slackware */
#undef S
#undef __CAT2__
};
@@ -54,7 +55,7 @@ static const char *
find_compression_program (const char *name, const char *defprog)
{
char *suf = strrchr (name, '.');
if (suf)
{
int i;
@@ -74,10 +75,9 @@ find_compression_program (const char *name, const char *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;
}

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 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
@@ -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,15 +297,15 @@ xdup2 (int from, int into)
}
}
void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
static void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
/* Propagate any failure of the grandchild back to the parent. */
void
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)
{
@@ -303,7 +317,7 @@ wait_for_grandchild (pid_t pid)
raise (WTERMSIG (wait_status));
else if (WEXITSTATUS (wait_status) != 0)
exit_code = WEXITSTATUS (wait_status);
exit (exit_code);
}
@@ -332,7 +346,7 @@ sys_child_open_for_compress (void)
set_program_name (_("tar (child)"));
signal (SIGPIPE, SIG_DFL);
xdup2 (parent_pipe[PREAD], STDIN_FILENO);
xclose (parent_pipe[PWRITE]);
@@ -362,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. */
@@ -379,9 +393,8 @@ sys_child_open_for_compress (void)
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! */
@@ -451,6 +464,42 @@ sys_child_open_for_compress (void)
wait_for_grandchild (grandchild_pid);
}
static void
run_decompress_program (void)
{
int i;
const char *p, *prog = NULL;
struct wordsplit ws;
int wsflags = (WRDSF_DEFFLAGS | WRDSF_ENV | WRDSF_DOOFFS) & ~WRDSF_NOVAR;
ws.ws_env = (const char **) environ;
ws.ws_offs = 1;
for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
{
if (prog)
{
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, errno, _("cannot run %s"), prog));
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, 0, _("trying %s"), p));
}
if (wordsplit (p, &ws, wsflags))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
p, wordsplit_strerror (&ws)));
wsflags |= WRDSF_REUSE;
memmove(ws.ws_wordv, ws.ws_wordv + ws.ws_offs,
sizeof(ws.ws_wordv[0])*ws.ws_wordc);
ws.ws_wordv[ws.ws_wordc] = (char *) "-d";
prog = p;
execvp (ws.ws_wordv[0], ws.ws_wordv);
ws.ws_wordv[ws.ws_wordc] = NULL;
}
if (!prog)
FATAL_ERROR ((0, 0, _("unable to run decompression program")));
exec_fatal (prog);
}
/* Set ARCHIVE for uncompressing, then reading an archive. */
pid_t
sys_child_open_for_uncompress (void)
@@ -476,7 +525,7 @@ sys_child_open_for_uncompress (void)
set_program_name (_("tar (child)"));
signal (SIGPIPE, SIG_DFL);
xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
xclose (parent_pipe[PREAD]);
@@ -496,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. */
@@ -514,9 +562,8 @@ sys_child_open_for_uncompress (void)
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! */
@@ -575,7 +622,7 @@ sys_child_open_for_uncompress (void)
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;
@@ -586,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)
@@ -594,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];
@@ -604,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)
{
@@ -616,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;
@@ -679,7 +726,6 @@ 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);
@@ -697,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
@@ -746,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);
xpipe (p);
saved_handler = signal (SIGPIPE, SIG_IGN);
@@ -783,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)
@@ -811,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
@@ -827,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 ();
@@ -858,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 */

955
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-2013
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,37 @@ 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;
};
union block

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 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;
@@ -432,16 +431,16 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
case ctl_upcase_next:
case_ctl_buffer[0] = toupper ((unsigned char) case_ctl_buffer[0]);
break;
case ctl_locase_next:
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 ((unsigned char) *p);
break;
case ctl_locase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = tolower ((unsigned char) *p);
@@ -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)
@@ -628,3 +627,9 @@ transform_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, NULL, NULL);
}
bool
transform_program_p (void)
{
return transform_head != NULL;
}

View File

@@ -1,19 +1,21 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
/* Unlink files.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
Copyright 2009, 2013 Free Software Foundation, Inc.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
This file is part of GNU tar.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"
@@ -22,7 +24,9 @@
struct deferred_unlink
{
struct deferred_unlink *next; /* Next unlink in the queue */
char *file_name; /* Absolute name of the file to unlink */
int dir_idx; /* Directory index in wd */
char *file_name; /* Name of the file to unlink, relative
to dir_idx */
bool is_dir; /* True if file_name is a directory */
off_t records_written; /* Number of records written when this
entry got added to the queue */
@@ -39,10 +43,10 @@ static struct deferred_unlink *dunlink_avail;
/* Delay (number of records written) between adding entry to the
list and its actual removal. */
size_t deferred_unlink_delay = 0;
static size_t deferred_unlink_delay = 0;
static struct deferred_unlink *
dunlink_alloc ()
dunlink_alloc (void)
{
struct deferred_unlink *p;
if (dunlink_avail)
@@ -68,16 +72,30 @@ static void
flush_deferred_unlinks (bool force)
{
struct deferred_unlink *p, *prev = NULL;
int saved_chdir = chdir_current;
for (p = dunlink_head; p; )
{
struct deferred_unlink *next = p->next;
if (force
|| records_written > p->records_written + deferred_unlink_delay)
{
chdir_do (p->dir_idx);
if (p->is_dir)
{
if (rmdir (p->file_name) != 0)
const char *fname;
if (p->file_name[0] == 0 ||
strcmp (p->file_name, ".") == 0)
{
fname = tar_dirname ();
chdir_do (p->dir_idx - 1);
}
else
fname = p->file_name;
if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
{
switch (errno)
{
@@ -95,13 +113,13 @@ flush_deferred_unlinks (bool force)
}
/* fall through */
default:
rmdir_error (p->file_name);
rmdir_error (fname);
}
}
}
else
{
if (unlink (p->file_name) != 0 && errno != ENOENT)
if (unlinkat (chdir_fd, p->file_name, 0) != 0 && errno != ENOENT)
unlink_error (p->file_name);
}
dunlink_reclaim (p);
@@ -116,14 +134,15 @@ flush_deferred_unlinks (bool force)
{
prev = p;
p = next;
}
}
}
if (!dunlink_head)
dunlink_tail = NULL;
chdir_do (saved_chdir);
}
void
finish_deferred_unlinks ()
finish_deferred_unlinks (void)
{
flush_deferred_unlinks (true);
while (dunlink_avail)
@@ -142,13 +161,15 @@ queue_deferred_unlink (const char *name, bool is_dir)
if (dunlink_head
&& records_written > dunlink_head->records_written + deferred_unlink_delay)
flush_deferred_unlinks (false);
p = dunlink_alloc ();
p->next = NULL;
p->file_name = normalize_filename (name);
p->dir_idx = chdir_current;
p->file_name = xstrdup (name);
normalize_filename_x (p->file_name);
p->is_dir = is_dir;
p->records_written = records_written;
if (dunlink_tail)
dunlink_tail->next = p;
else

View File

@@ -1,21 +1,22 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
2004, 2005, 2007, 2010 Free Software Foundation, Inc.
Copyright 1988, 1992, 1994, 1996-1997, 1999-2001, 2003-2005, 2007, 2010,
2013 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,8 +115,8 @@ update_archive (void)
while (!found_end)
{
enum read_header status = read_header (&current_header,
&current_stat_info,
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_auto);
switch (status)
@@ -130,6 +131,8 @@ update_archive (void)
decode_header (current_header, &current_stat_info,
&current_format, 0);
transform_stat_info (current_header->header.typeflag,
&current_stat_info);
archive_format = current_format;
if (subcommand_option == UPDATE_SUBCOMMAND
@@ -138,26 +141,22 @@ update_archive (void)
struct stat s;
chdir_do (name->change_dir);
if (deref_stat (dereference_option,
current_stat_info.file_name, &s) == 0)
if (deref_stat (current_stat_info.file_name, &s) == 0)
{
if (S_ISDIR (s.st_mode))
{
char *p, *dirp;
dirp = savedir (name->name);
if (!dirp)
savedir_error (name->name);
else
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);
}
}
@@ -167,7 +166,7 @@ update_archive (void)
remname (name);
}
}
skip_member ();
break;
}
@@ -224,11 +223,12 @@ update_archive (void)
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 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
This file is part of GNU tar.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <quotearg.h>

View File

@@ -1,19 +1,21 @@
/* This file is part of GNU tar.
/* Warnings for GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
Copyright 2009, 2012-2013 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
This file is part of GNU tar.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
GNU tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
GNU tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <argmatch.h>
@@ -41,6 +43,10 @@ static char const *const warning_args[] = {
"unknown-cast",
"unknown-keyword",
"xdev",
"decompress-program",
"existing-file",
"xattr-write",
"record-size",
NULL
};
@@ -64,7 +70,11 @@ static int warning_types[] = {
WARN_TIMESTAMP,
WARN_UNKNOWN_CAST,
WARN_UNKNOWN_KEYWORD,
WARN_XDEV
WARN_XDEV,
WARN_DECOMPRESS_PROGRAM,
WARN_EXISTING_FILE,
WARN_XATTR_WRITE,
WARN_RECORD_SIZE
};
ARGMATCH_VERIFY (warning_args, warning_types);
@@ -76,7 +86,7 @@ set_warning_option (const char *arg)
{
int negate = 0;
int option;
if (strcmp (arg, "none") == 0)
{
warning_option = 0;
@@ -88,11 +98,10 @@ set_warning_option (const char *arg)
arg += 3;
}
option = XARGMATCH ("--warning", arg,
option = XARGMATCH ("--warning", arg,
warning_args, warning_types);
if (negate)
warning_option &= ~option;
else
warning_option |= option;
}

734
src/xattrs.c Normal file
View File

@@ -0,0 +1,734 @@
/* Support for extended attributes.
Copyright (C) 2006-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/>.
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 *);
/* 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
/* 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;
}
/* "system.posix_acl_access" */
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);
acls_option = 1;
}
else if (acls_option > 0)
acl = perms2acl (st->stat.st_mode);
else
return; /* don't call acl functions unless we first hit an ACL, or
--acls was passed explicitly */
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 && (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 && st->cntx_name)
fprintf (stdlis, " s: %s\n", st->cntx_name);
/* acls */
if (acls_option && (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 && st->xattr_map_size)
{
int i;
for (i = 0; i < st->xattr_map_size; ++i)
{
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
fprintf (stdlis, " x: %lu %s\n",
(unsigned long) st->xattr_map[i].xval_len, keyword);
}
}
}

50
src/xattrs.h Normal file
View File

@@ -0,0 +1,50 @@
/* Support for extended attributes.
Copyright (C) 2006-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/>.
Written by James Antill, on 2006-07-27. */
#ifndef GUARD_XATTTRS_H
#define GUARD_XATTTRS_H
/* Add include/exclude fnmatch pattern for xattr key domain. Set INCL parameter
to true/false if you want to add include/exclude pattern */
extern void xattrs_mask_add (const char *mask, bool incl);
/* clear helping structures when tar finishes */
extern void xattrs_clear_setup (void);
extern void xattrs_acls_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd, int xisfile);
extern void xattrs_selinux_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd);
extern void xattrs_xattrs_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd);
extern void xattrs_acls_set (struct tar_stat_info const *st,
char const *file_name, char typeflag);
extern void xattrs_selinux_set (struct tar_stat_info const *st,
char const *file_name, char typeflag);
extern void xattrs_xattrs_set (struct tar_stat_info const *st,
char const *file_name, char typeflag,
int later_run);
extern void xattrs_print_char (struct tar_stat_info const *st, char *output);
extern void xattrs_print (struct tar_stat_info const *st);
#endif /* GUARD_XATTTRS_H */

View File

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

View File

@@ -1,25 +1,21 @@
# Makefile for GNU tar regression tests.
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
# 2006, 2007, 2009 Free Software Foundation, Inc.
# Copyright 1996-1997, 1999-2001, 2003-2007, 2009, 2012-2013 Free Software
# François Pinard <pinard@iro.umontreal.ca>, 1988.
# Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
# This file is part of GNU tar.
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3, or (at your option)
## any later version.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301, USA.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 star/README star/quicktest.sh
DISTCLEANFILES = atconfig $(check_SCRIPTS)
@@ -46,12 +42,20 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## ------------ ##
TESTSUITE_AT = \
T-cd.at\
T-empty.at\
T-null.at\
T-rec.at\
T-zfile.at\
T-nonl.at\
T-mult.at\
T-nest.at\
testsuite.at\
append.at\
append01.at\
append02.at\
append03.at\
append04.at\
backup01.at\
chtype.at\
comprec.at\
@@ -66,6 +70,17 @@ TESTSUITE_AT = \
exclude03.at\
exclude04.at\
exclude05.at\
exclude06.at\
exclude07.at\
exclude08.at\
exclude09.at\
exclude10.at\
exclude11.at\
exclude12.at\
exclude13.at\
exclude14.at\
exclude15.at\
exclude16.at\
extrac01.at\
extrac02.at\
extrac03.at\
@@ -74,6 +89,17 @@ TESTSUITE_AT = \
extrac06.at\
extrac07.at\
extrac08.at\
extrac09.at\
extrac10.at\
extrac11.at\
extrac12.at\
extrac13.at\
extrac14.at\
extrac15.at\
extrac16.at\
extrac17.at\
extrac18.at\
extrac19.at\
filerem01.at\
filerem02.at\
gzip.at\
@@ -85,15 +111,25 @@ TESTSUITE_AT = \
incr04.at\
incr05.at\
incr06.at\
incr07.at\
incr08.at\
incr09.at\
indexfile.at\
ignfail.at\
label01.at\
label02.at\
label03.at\
label04.at\
label05.at\
link01.at\
link02.at\
link03.at\
link04.at\
listed01.at\
listed02.at\
listed03.at\
listed04.at\
listed05.at\
long01.at\
longv7.at\
lustar01.at\
@@ -106,9 +142,17 @@ TESTSUITE_AT = \
multiv05.at\
multiv06.at\
multiv07.at\
multiv08.at\
old.at\
opcomp01.at\
opcomp02.at\
opcomp03.at\
opcomp04.at\
opcomp05.at\
opcomp06.at\
options.at\
options02.at\
owner.at\
pipe.at\
recurse.at\
rename01.at\
@@ -118,19 +162,41 @@ TESTSUITE_AT = \
rename05.at\
remfiles01.at\
remfiles02.at\
remfiles03.at\
remfiles04a.at\
remfiles04b.at\
remfiles04c.at\
remfiles05a.at\
remfiles05b.at\
remfiles05c.at\
remfiles06a.at\
remfiles06b.at\
remfiles06c.at\
remfiles07a.at\
remfiles07b.at\
remfiles07c.at\
remfiles08a.at\
remfiles08b.at\
remfiles08c.at\
remfiles09a.at\
remfiles09b.at\
remfiles09c.at\
same-order01.at\
same-order02.at\
shortfile.at\
shortupd.at\
shortrec.at\
sigpipe.at\
sparse01.at\
sparse02.at\
sparse03.at\
sparse04.at\
sparsemv.at\
sparsemvp.at\
spmvp00.at\
spmvp01.at\
spmvp10.at\
time01.at\
truncate.at\
update.at\
update01.at\
@@ -138,14 +204,26 @@ TESTSUITE_AT = \
volsize.at\
volume.at\
verbose.at\
verify.at\
version.at\
xform-h.at\
xform01.at\
star/gtarfail.at\
star/gtarfail2.at\
star/multi-fail.at\
star/ustar-big-2g.at\
star/ustar-big-8g.at\
star/pax-big-10g.at
star/pax-big-10g.at\
xattr01.at\
xattr02.at\
xattr03.at\
xattr04.at\
xattr05.at\
acls01.at\
acls02.at\
selnx01.at\
selacl01.at\
capabs_raw01.at
TESTSUITE = $(srcdir)/testsuite
@@ -182,6 +260,11 @@ check_PROGRAMS = genfile
genfile_SOURCES = genfile.c argcv.c argcv.h
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/gnu -I../gnu -I$(top_srcdir)/gnu -I$(top_srcdir)/lib
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
LDADD = ../gnu/libgnu.a $(LIBINTL) $(LIB_CLOCK_GETTIME)
AM_CPPFLAGS = \
-I$(top_srcdir)/gnu\
-I../gnu\
-I$(top_srcdir)/gnu\
-I$(top_srcdir)/lib\
-DLOCALEDIR=\"$(localedir)\"
LDADD = ../gnu/libgnu.a $(LIBINTL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)

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

@@ -0,0 +1,44 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([-C in file lists])
AT_KEYWORDS([files-from T-cd])
AT_TAR_CHECK([
AT_SORT_PREREQ
>file1
mkdir dir
>dir/file2
>dir/file3
AT_DATA([F1],[file1
-C dir
.
])
tar cf archive -T F1
tar tf archive | sort
],
[0],
[./
./file2
./file3
file1
],[],[],[],[ustar])
AT_CLEANUP

View File

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

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

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([multiple file lists])
AT_KEYWORDS([files-from T-mult])
AT_TAR_CHECK([
>file1
>file2
>file3
>file4
AT_DATA([F1],[file1
file2
])
AT_DATA([F2],[file3
file4
])
tar cf archive -T F1 -T F2
tar tf archive
],
[0],
[file1
file2
file3
file4
],[],[],[],[ustar])
AT_CLEANUP

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

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([nested file lists])
AT_KEYWORDS([files-from T-nest])
AT_TAR_CHECK([
>file1
>file2
>file3
>file4
AT_DATA([F1],[file1
-T F2
file2
])
AT_DATA([F2],[file3
file4
])
tar cf archive -T F1
tar tf archive
],
[0],
[file1
file3
file4
file2
],[],[],[],[ustar])
AT_CLEANUP

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

@@ -0,0 +1,62 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Tar malfunctioned when given a file list with the last line not ending
# in a newline.
#
# Reported by: Michal Žejdl <zejdl@suas.cz>
# References: <http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html>
AT_SETUP([entries with missing newlines])
AT_KEYWORDS([files-from nonewline nonl T-nonl])
AT_TAR_CHECK([
genfile --length=0 --file empty
AS_ECHO_N(c) > 1.nonl
echo d > 2.nonl
AS_ECHO_N(e) >> 2.nonl
touch a b c d e
AT_DATA([filelist],[a
b
])
tar cf archive -T empty -T 1.nonl -T 2.nonl -T filelist
tar tf archive
echo ==
tar cf archive -T 2.nonl -T empty -T filelist -T 1.nonl
tar tf archive
],
[0],
[c
d
e
a
b
==
d
e
a
b
c
],
[],[],[],[ustar])
AT_CLEANUP

View File

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

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

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([recursive file lists])
AT_KEYWORDS([files-from T-rec])
AT_TAR_CHECK([
>file1
>file2
AT_DATA([F1],[file1
-T F2
])
AT_DATA([F2],[file2
-T F1
])
tar cf archive -T F1
echo $?
tar tf archive
],
[0],
[2
file1
file2
],
[tar: F1: file list requested from F2 already read from command line
tar: Exiting with failure status due to previous errors
],[],[],[ustar])
AT_CLEANUP

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

@@ -0,0 +1,52 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Tar malfunctioned when given empty file as an argument to -T.
#
# Reported by: Michal Žejdl <zejdl@suas.cz>
# References: <http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html>
AT_SETUP([empty file])
AT_KEYWORDS([files-from empty-file])
AT_TAR_CHECK([
genfile --length=0 --file empty
genfile --file a
genfile --file b
AT_DATA([valid],[a
b
])
tar cf archive -T empty -T valid
tar tf archive
echo "=="
tar cf archive -T valid -T empty
tar tf archive
],
[0],
[a
b
==
a
b
],
[],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

55
tests/acls01.at Normal file
View File

@@ -0,0 +1,55 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2011, 2013 Free Software Foundation, Inc.
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Test description:
#
# This is basic test for acl support.
AT_SETUP([acls: basic functionality])
AT_KEYWORDS([xattrs acls acls01])
AT_TAR_CHECK([
AT_XATTRS_UTILS_PREREQ
AT_ACLS_PREREQ
mkdir dir
genfile --file dir/file
MYNAME=$( id -un )
setfacl -m u:$MYNAME:--x dir/file
setfacl -m u:$MYNAME:--x dir
getfattr -h -m. -d dir dir/file > before
tar --acls -cf archive.tar dir
rm -rf dir
tar --acls -xf archive.tar
getfattr -h -m. -d dir dir/file > after
diff before after
test "$?" = 0
],
[0],
[])
AT_CLEANUP

61
tests/acls02.at Normal file
View File

@@ -0,0 +1,61 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2011, 2013 Free Software Foundation, Inc.
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Test description:
#
# This is basic test for acl support.
AT_SETUP([acls: work with -C])
AT_KEYWORDS([xattrs acls acls02])
AT_TAR_CHECK([
AT_XATTRS_UTILS_PREREQ
AT_ACLS_PREREQ
mkdir dir
mkdir dir/subdir
genfile --file dir/subdir/file
MYNAME=$( id -un )
setfacl -m u:$MYNAME:--x dir/subdir
setfacl -m u:$MYNAME:--x dir/subdir/file
cd dir
getfattr -h -m. -d subdir subdir/file > ../before
cd ..
tar --acls -cf archive.tar -C dir subdir
rm -rf dir
mkdir dir
tar --acls -xf archive.tar -C dir
cd dir
getfattr -h -m. -d subdir subdir/file > ../after
cd ..
diff before after
test "$?" = 0
],
[0],
[])
AT_CLEANUP

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
# Copyright 2004, 2006-2007, 2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([append])
AT_KEYWORDS([append append00])

View File

@@ -1,35 +1,35 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
# Copyright 2005-2007, 2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# When decoding a header tar was assigning 0 to oldgnu_header.isextended,
# which destroyed name prefix. When updating archive, modified prefix
# could have been written to disk thus producing invalid archive member.
# Reported by Adye, TJ (Tim), <T.J.Adye@rl.ac.uk>
# Reported by Adye, TJ (Tim), <T.J.Adye@rl.ac.uk>
# References:
# <7231C15EAC2F164CA6DC326D97493C8B36C25D@exchange35.fed.cclrc.ac.uk>
# http://lists.gnu.org/archive/html/bug-tar/2005-02/msg00032.html
AT_SETUP([appending files with long names])
AT_KEYWORDS([append append01])
m4_define([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_appending_long_file_names_that_run_into_a_limit_of_the_ustar_tarX])
m4_pushdef([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_appending_long_file_names_that_run_into_a_limit_of_the_ustar_tarX])
AT_TAR_CHECK([
mkdir PREFIX
@@ -44,5 +44,5 @@ PREFIX/file2
],
[],[],[],[oldgnu, ustar, posix, gnu])
m4_popdef([PREFIX])
AT_CLEANUP

View File

@@ -1,26 +1,26 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
# Copyright 2006-2007, 2009, 2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Using tar 1.15.x the following equivalent command sets:
#
# 1. tar cf archive file1 file2
# 1. tar cf archive file1 file2
# and
# 2. tar cfT archive /dev/null
# tar rf archive file1
@@ -62,7 +62,7 @@ genfile --file file2
MTIME="--mtime=@0"
# For PAX archives, we need to make sure extended header names are
# reproducible and that their contents won't change with time
# reproducible and that their contents won't change with time
if test $[]TEST_TAR_FORMAT = posix; then
TAR_OPTIONS="$TAR_OPTIONS --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=mtime,delete=atime,delete=ctime"
fi

45
tests/append03.at Normal file
View File

@@ -0,0 +1,45 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2010, 2013 Free Software Foundation, Inc.
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([append with name transformation])
AT_KEYWORDS([append append03])
# Description: Make sure filenames are transformed during append.
AT_TAR_CHECK([
genfile --file file.1
genfile --file file.2
tar -c -f archive --transform 's/file/plik/' file.*
echo Appending
tar -r -f archive --transform 's/file/plik/' -v --show-transformed-names file.1
echo Testing
tar tf archive
],
[0],
[Appending
plik.1
Testing
plik.1
plik.2
plik.1
])
AT_CLEANUP

60
tests/append04.at Normal file
View File

@@ -0,0 +1,60 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# When called with --append and --verify options, tar would rewrite the
# archive instead of appending to it.
#
# Last-Affected-Version: 1.26
# Reported-by: Jivko Angelov <jivko@siteground.com>
# References: <51D6983C.3060404@siteground.com>,
# http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00003.html
AT_SETUP([append with verify])
AT_KEYWORDS([append append04 verify append-verify])
AT_TAR_CHECK([
# Create two empty files:
touch file1 file2
# Create an archive:
tar cpfW archive.tar file1 file2
# Verify created archive by listing its content:
tar -tf archive.tar
echo ==
# Create another empty file:
touch file3
# Append it to the already created archive:
tar rpfW archive.tar file3
# Verify content of the new archive:
tar -tf archive.tar
],
[0],
[file1
file2
==
file1
file2
file3
])
AT_CLEANUP

View File

@@ -1,6 +1,21 @@
# @configure_input@ -*- shell-script -*-
# Configurable variable values for tar test suite.
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
# Copyright 2004, 2006, 2013 Free Software Foundation, Inc.
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_srcdir@/build-aux:$top_srcdir:$srcdir:$PATH
@@ -16,17 +31,17 @@ fi
STAR_DATA_URL=ftp://ftp.berlios.de/pub/star/testscripts
if test -z "$STAR_TESTSCRIPTS"; then
STAR_TESTSCRIPTS=$TEST_DATA_DIR
fi
fi
# tarball_prereq file sum dir url
tarball_prereq() {
if test -d "$3"; then
if test -d "$3"; then
if test -r $3/$1; then
:
elif test -n "$FULL_TEST"; then
wget -q --directory-prefix=$3 $4/$1
fi
fi
fi
echo "$2 $3/$1" | md5sum --status --check - >/dev/null 2>&1
}
@@ -35,3 +50,10 @@ decho() {
echo >&2 $*
}
mkexcltest() {
mkdir $1 $1/subdir
genfile --file=$1/top-level-file
genfile --file=$1/subdir/excludeme
genfile --file=$1/subdir/subdir-file
}

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2009 Free Software Foundation, Inc.
# Copyright 2009-2010, 2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Description:
# When extracting, tar (<1.22) sometimes renamed a backup back to the
@@ -34,16 +34,17 @@ AT_SETUP([extracting existing dir with --backup])
AT_KEYWORDS([extract backup backup01])
AT_TAR_CHECK([
unset VERSION_CONTROL
mkdir dir1 dir2
echo bla > dir1/file1
tar cf test.tar dir1 dir2
tar xfv test.tar --backup
tar xfv test.tar --backup --warning=no-timestamp
],
[0],
[dir1/
dir1/file1
Renaming `dir1/file1' to `dir1/file1~'
Renaming 'dir1/file1' to 'dir1/file1~'
dir2/
])
AT_CLEANUP
AT_CLEANUP

53
tests/capabs_raw01.at Normal file
View File

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

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
# Copyright 2006-2007, 2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Description: Incremental restore malfunctions if an archive member
# changes type before restoration, e.g. from directory to file or vice
@@ -25,7 +25,7 @@
# References: <200605101232.25031.bugreport@wkleff.intergenia.de>
AT_SETUP([changed file types in incrementals])
AT_KEYWORDS([incremental chtype])
AT_KEYWORDS([incremental listed chtype])
AT_TAR_CHECK([
AT_SORT_PREREQ
@@ -51,9 +51,9 @@ tar --create --file=archive.2 --listed-incremental=db.2 directory
rm -r directory
echo Restore archive.1
tar -xf archive.1 --listed-incremental=/dev/null
tar -xf archive.1 --listed-incremental=/dev/null --warning=no-timestamp
echo Restore archive.2
tar -xf archive.2 --listed-incremental=/dev/null
tar -xf archive.2 --listed-incremental=/dev/null --warning=no-timestamp
find directory | sort
],
[0],

View File

@@ -1,22 +1,22 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
# Copyright 2004, 2006-2007, 2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# This file is part of GNU tar.
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# GNU tar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([compressed format recognition])
@@ -29,7 +29,7 @@ echo "separator"
tar cfz archive file1
echo "separator"
mv file1 orig
tar xfv archive
tar xfv archive --warning=no-timestamp
cmp orig file1
],
[0],

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