136 Commits

Author SHA1 Message Date
Sergey Poznyakoff
bf28f95b3a Version 1.34 2021-02-13 13:11:01 +02:00
Pavel Raiskup
beeb19f927 xattrs: fix capabilities root test
Related discussion in the Fedora pull-request:
https://src.fedoraproject.org/rpms/tar/pull-request/8

* tests/capabs_raw01.at: Newer systems (currently e.g. Fedora 34)
print getcap output in format CAP=VAL, not CAP+VAL.
2021-02-08 17:50:31 +02:00
Sergey Poznyakoff
553210d5ad Gracefully handle duplicate symlinks when extracting
If the archive being extracted contains multiple copies
of the same symlink, extract only the first of them and
skip the rest.  The use case is described in

https://lists.gnu.org/archive/html/bug-tar/2021-01/msg00026.html

The bug was introduced by 2d3396c3ea.

* src/extract.c (create_placeholder_file): If placeholder already
exists and is registered in the delayed_link list, return immediately.
2021-02-08 16:15:22 +02:00
Sergey Poznyakoff
ee2ec5ff19 Fix savannah bug #60002
Bug was introduced by commit 34d15af1.

* src/extract.c (prepare_to_extract): When extracting over pipe,
process only regular files.
* tests/extrac24.at: New test case.
* tests/Makefile.am: Add new test case.
* tests/testsuite.at: Likewise.
2021-02-04 16:51:38 +02:00
Sergey Poznyakoff
d9d4435692 Fix memory leak in read_header
Bug reported in https://savannah.gnu.org/bugs/?59897

* src/list.c (read_header): Don't return directly from the loop.
Instead set the status and break.  Return the status.  Free
next_long_name and next_long_link before returning.
2021-01-17 20:41:11 +02:00
Sergey Poznyakoff
2251317e3f Fix improper argument reference.
(bug introduced by 1ff0b63f)

* src/tar.c (parse_default_options): Pass args as is to the argp_parse.
2021-01-17 19:02:47 +02:00
Sergey Poznyakoff
972bebf07e Fix regression itroduced by 66162927.
* src/misc.c (chdir_arg): Initialize the abspath field to NULL.
(tar_getcdpath): Actually initialize the abspath field here.
2021-01-16 14:38:28 +02:00
Sergey Poznyakoff
8e2898ab11 Fixes in the delete_archive_members function
* src/delete.c (delete_archive_members): Clean-up the code. Avoid
entering the loop from the middle.  Free the memory allocated for
current_stat_info.
2021-01-14 09:00:12 +02:00
Sergey Poznyakoff
0b43ea2906 Use stdopen from gnulib
* gnulib.modules: Request stdopen
* lib/Makefile.am: Remove stdopen.c and stdopen.h
* lib/stdopen.c: Remove.
* lib/stdopen.h: Remove.
* src/tar.c: stdopen returns 0 on success.
2021-01-08 18:50:57 +02:00
Sergey Poznyakoff
e4d1edadef Actually prefer /dev/full over /dev/null as a replacement for stdin
* lib/stdopen.c (stdopen): Fix improper condition.
Avoid leaking extra file descriptor.
* src/tar.c (main): Set name of the stdout for diagnostics.
Bail out if stdopen fails.
2021-01-08 17:46:32 +02:00
Sergey Poznyakoff
0836a51147 Version 1.33
* NEWS: Update.
* configure.ac: Raise version number. Require automake 1.15 and
autoconf 2.64.
* gnulib: pull v0.1-4333-g30820c2
* src/names.c: Use hash_remove instead of the deprecated hash_delete.
2021-01-07 16:33:49 +02:00
Sergey Poznyakoff
afa743ac23 Update copyright years 2021-01-06 17:55:16 +02:00
Sergey Poznyakoff
01dd89c121 Fix typo in the manpage
* doc/tar.1: Fix description of the --newer option
2020-07-13 09:01:29 +03:00
Pavel Raiskup
1263f9bc1d Bugfix --sparse --diff mode
Originally reported in:
https://bugzilla.redhat.com/show_bug.cgi?id=1853469

* src/sparse.c (check_data_region): Only compare the part of buffer
really fed by safe_read(), not whole rdsize.
2020-07-10 09:06:42 +03:00
Sergey Poznyakoff
1ff0b63f48 Accept only position-sensitive (file-selection) options in file list files.
Using such options as -f, -z, etc. is senseless in the file list file
and bypasses the option consistency checks in decode_options.  Therefore,
only options related to file selection (a.k.a position-sensitive options)
are allowed in files.

* doc/tar.texi: Document changes.
* src/common.h (tar_args): Move from tar.c
(TAR_ARGS_INITIALIZER): New macro.
* src/names.c: Declare option group identifiers as an enum.
(names_parse_opt): Special handling for ARGP_KEY_ERROR.
(names_argp): Remove static qualifier.
(names_argp_children): Remove.
* src/tar.c: Declare option group identifiers as an enum.
(parse_opt): Special handling for ARGP_KEY_INIT.
(argp_children): New static variable.
(args): Remove static variable.
(more_options): Allow only options from names_argp.
(parse_default_options): Take a pointer to struct tar_args as argument.
Replace the loc member during the call to argp_parse and restore it
afterwards.
(decode_options): Use automatic variable for args.
2020-06-24 16:43:26 +03:00
Sergey Poznyakoff
34d15af170 Fix the logic of prepare_to_extract.
* src/extract.c (prepare_to_extract): Return true to proceed with
the extraction, and false to skip the current member.  If extracting
over a pipe, skip unlinking logic.
(extract_archive): Update accordingly.
2020-06-22 22:17:46 +03:00
Sergey Poznyakoff
63712973c7 Make sure link counting works for file names supplied with -T
* src/common.h (name_count): Remove extern.
(files_count): New enum.
(filename_args): New extern.
* src/names.c (name_count): Remove.
(files_count): New variable.
(name_add_name,name_add_file): Update filename_args.
* src/create.c (create_archive): Set trivial_link_count depending on
the filename_args.
2020-06-15 21:10:46 +03:00
Alfred M. Szmidt
d9ec6f04e2 Remove freemanuals.texi
* doc/Makefile.am (tar_TEXINFOS): Remove freemanuals.texi.
* doc/freemanuals.texi: Delete file.
* doc/tar.texi (Free Software Needs Free Documentation): Remove
appendix.
2020-06-10 21:56:54 +03:00
Sergey Poznyakoff
b5418cd393 Fix typo in docs 2020-06-03 10:55:51 +03:00
Sergey Poznyakoff
615732a804 Bugfix
* src/sparse.c (sparse_diff_file): Fix return value.
2020-06-03 09:31:41 +03:00
Paul Eggert
dd1a6bd37a tar: avoid read overrun
Problem reported by Timotej Kapus in:
https://lists.gnu.org/r/bug-tar/2020-05/msg00001.html
* src/transform.c (parse_transform_expr):
Diagnose ‘--transform='s'’ instead of continuing past '\0'.
2020-05-19 11:52:26 -07:00
Sergey Poznyakoff
41654f91f0 Fix handling of linked rename chains in incremental backups
* src/incremen.c: Change the meaning of the DIRF_RENAMED flag.  Now it
marks a directory which is the last one in a chain of renames.
Regular renamed directories are recognized by their orig member being
non-NULL.  Directories marked with DIRF_RENAMED start encoding of renames.
(procdir): Clear DIRF_RENAMED flag on directories which are origins for
renames.
(makedumpdir): Use the orig member to check if the directory is a
result of a rename.
(store_rename): Move the check for DIR_IS_RENAMED to the caller. Don't
clear the DIRF_RENAMED, it is not needed any more.

* tests/rename06.at: New test.
* tests/Makefile.am: Add rename06.at
* tests/testsuite.at: Likewise.
2020-02-15 11:09:18 +02:00
Sergey Poznyakoff
8d90723d30 Update copyright years 2020-02-08 13:21:13 +02:00
Sergey Poznyakoff
14d8fc718f Fix the --no-overwrite-dir option
Given this option, tar failed to preserve permissions of empty directories
and to create files under directories owned by the current user that did
not have the S_IWUSR bit set.

* src/extract.c (fd_chmod): Rename to fd_i_chmod.
(fd_chmod): New function.
(safe_dir_mode): New function.
(extract_dir): Special handling for existing directories in
--no-overwrite-dir mode.
* tests/extrac23.at: New file.
* tests/Makefile.am: Add new test case.
* tests/testsuite.at: Likewise.
2020-02-08 13:08:20 +02:00
Sergey Poznyakoff
883cc555df Wildcards in exclude-vcs-ignore mode should not match slash
* src/exclist.c (info_attach_exclist): Use the FNM_FILE_NAME flag.
2019-12-03 09:55:02 +02:00
Sergey Poznyakoff
e1005b385d Version 1.32.90 2019-11-27 18:51:58 +02:00
Sergey Poznyakoff
14f00a2c7a Testsuite fixes
* tests/sparse06.at: Skip the test if genfile is unable to create
sparse files.
* tests/sptrcreat.at: Likewise.
* tests/sptrdiff00.at: Likewise.
* tests/sptrdiff01.at: Likewise.
2019-11-25 08:01:04 +02:00
Sergey Poznyakoff
f122fc94a7 Another testsuite fix.
* tests/extrac11.at: Skip test if ulimit fails.
2019-11-14 07:58:17 +02:00
Sergey Poznyakoff
b31afe7cf0 Testsuite fix.
* tests/remfiles10.at: Don't expect EINVAL when trying to remove
CWD.
2019-11-13 08:37:41 +02:00
Sergey Poznyakoff
ea6f84dd40 Consistently use x2realloc for buffer reallocation
* src/create.c (create_archive): Use x2realloc
* src/names.c (copy_name)
(add_hierarchy_to_namelist): Use x2realloc
2019-08-25 14:41:17 +03:00
Sergey Poznyakoff
2d3396c3ea Fix extraction of symbolic links hardlinked to another symbolic links
* src/extract.c (create_placeholder_file): Take additional argument:
the delayed_link entry after which to the newly created one.
(extract_link): Create a placeholder file if the target link name
exists in the delayed_link list.
2019-08-18 23:40:54 +03:00
Sergey Poznyakoff
d70b8b3b39 Fix --delay-directory-restore on archives with reversed member ordering.
* src/extract.c (find_direct_ancestor): Remove useless test.
(delay_set_stat): If the file name being added is already in
the list, update stored data instead of creating a new entry.
This works for archives with reversed order of members.
* tests/extrac22.at: New testcase.
* tests/Makefile.am: Add new testcase.
* tests/testsuite.at: Include new testcase.
2019-04-11 13:45:32 +03:00
Sergey Poznyakoff
c445d99d4f Minor change
* scripts/backup.in: Fix typo
2019-03-28 14:01:58 +02:00
Sergey Poznyakoff
2c9730357f Typesetting fixes in the manpage
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2019-03-28 13:58:44 +02:00
Zachary Vance
ef0f882382 POSIX extended format headers do not include PID by default
The intent is to make binary-equivalent PAX archives easy to create.  If
POSIXLY_CORRECT is set, the POSIX standard default is used, which embeds
the pid.

* src/common.h (posixly_correct): New global.
* src/tar.c (decode_options): Detect the POSIXLY_CORRECT environment
variable.
* src/buffer.c (add_chunk_header): Change filenames of multipart files to
omit the pid.
* src/xheader.c (HEADER_TEMPLATE): New macro.
(xheader_xhdr_name, xheader_ghdr_name): Use HEADER_TEMPLATE to select
the template for the POSIX extended header name.
* doc/tar.texi: Document the change.

Signed-off-by: Zachary Vance <za3k@za3k.com>
2019-03-28 13:37:07 +02:00
Sergey Poznyakoff
66162927eb Check return value from xgetcwd
* src/misc.c (chdir_arg,tar_getcdpath): Check for non-NULL
return from xgetcwd. The function returns NULL for any
error originating from getcwd.
2019-03-03 09:02:20 +02:00
Sergey Poznyakoff
44cfdfb8b6 Version 1.32 2019-02-23 14:54:53 +02:00
Sergey Poznyakoff
97d8951536 Minor fixes in docs.
* doc/tar.1: Remove description of the --preserve option
Document verbosity levels.
* doc/tar.texi: Fix description of the -o option.
2019-02-04 21:30:00 +02:00
Daniel Le
bf5d66109c Fix typos in the documentation
Short option "t" was mistranslated to "--test" instead of "--list" in commit
67cad0792b.
2019-01-15 15:29:03 +02:00
Sergey Poznyakoff
bd1b0fc97c Fix build on AIX
* src/unlink.c (flush_deferred_unlinks): Avoid possible duplicate case
(if ENOTEMPTY==EEXIST)
2019-01-15 15:21:03 +02:00
Sergey Poznyakoff
a7289daf5c Version 1.31.90 2019-01-15 14:38:02 +02:00
Sergey Poznyakoff
72506bddee Ensure gnu format when running checkpoint tests 2019-01-14 23:32:15 +02:00
Sergey Poznyakoff
a311b908c0 Fix compression tests
Existing compression tests used tar with compiled-in defaults. However,
some of the defaults are sure to create archives that are not byte-to-byte
reproducible (e.g. DEFAULT_ARCHIVE_FORMAT=POSIX, because the name field
in posix extended headers uses PID of the creating process by default).
Moreover, some compressors (e.g. gzip) store current timestamp in
the file header when compressing from stdin, so that using cmp on the
two created archives as the tests did is error-prone. Another problem
is that the tests implicitly assumed that tar uses archive suffix to
recognize its format when extracting, which isn't the case. Finally,
there's hardly any reason in using sed to create m4 sources, when
everything can be achieved by m4 itself.

* tests/Makefile.am: Remove generation of compress-*.at files.
* tests/compress.at.in: Remove.
* tests/compress.m4: New file.
* tests/testsuite.at: Include compress.m4, use TAR_CHECK_COMPRESS to
check compression options.
2019-01-14 18:55:43 +02:00
Sergey Poznyakoff
cb07844454 Fix possible NULL dereference (savannah bug #55369)
* src/sparse.c (pax_decode_header): Check return from find_next_block.
2019-01-14 15:22:09 +02:00
Sergey Poznyakoff
2f5a57be4b Fix compilation without iconv. 2019-01-14 14:46:43 +02:00
Sergey Poznyakoff
3da8c2850d Fix iconv usage.
Patch by Christian Weisgerber.

* src/utf8.c (utf8_convert): non-zero return from iconv means failure.
2019-01-14 13:59:39 +02:00
Pavel Raiskup
c697d62598 tests: fix numeric.at for BSD
While creating file, BSD kernels inherit the group ownership from
parent directory.
http://lists.gnu.org/archive/html/bug-tar/2016-06/msg00000.html

* tests/numeric.at: Attempt to 'chown' the newly created directory
to proper group (at least on affected machines that command is
expected to succeed).
2019-01-14 12:54:29 +02:00
Sergey Poznyakoff
b0930da045 Fix typo in manpage. 2019-01-14 12:48:16 +02:00
Sergey Poznyakoff
f86722c34c Fix expected output in dirrem tests.
In both tests, the "file changed as we read it" warning might be
produced for dir/sub, depending on the ctime resolution and timing.
The problem was fixed by 64b43fdf70, but regressed
after e7cd377f78, which removed 1 second
delays between each pair of checkpoints. Since the presense or absense
of this warning is irrelevant for the test, it is now suppressed.

* tests/dirrem01.at: Suppress the file-changed warning.
* tests/dirrem02.at: Likewise.
2019-01-14 12:26:59 +02:00
Sergey Poznyakoff
aa0684ce90 Fix the use of --checkpoint without explicit --checkpoint-action
* src/checkpoint.c (checkpoint_finish_compile): Set default action,
if necessary.
* tests/checkpoint/defaults.at: New testcase.
* tests/checkpoint/dot-compat.at: New testcase.
* tests/checkpoint/dot-int.at: New testcase.
* tests/checkpoint/dot.at: New testcase.
* tests/checkpoint/interval.at: New testcase.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at Include new testcases.
2019-01-12 10:24:47 +02:00
Sergey Poznyakoff
85c005ee13 Remove erroneous abort() call
The call was introduced by commit ccef8581. It caused tar to abort
on perfectly normal operations, like untarring archives containing
./ with the -U option,

See http://lists.gnu.org/archive/html/bug-tar/2019-01/msg00019.html
for details.

* src/extract.c (maybe_recoverable): Remove misplaced call to abort().
2019-01-10 18:18:49 +02:00
Sergey Poznyakoff
2684c88a49 Version 1.31 2019-01-02 20:20:28 +02:00
Sergey Poznyakoff
1ed62596cf Fix the difflink test
Hardlinking a symlink produces hardlink on BSD and symlink
on GNU/Linux. Avoid the ambiguity.

* tests/difflink.at: Create hard link from a regular file.
2018-12-28 17:53:35 +02:00
Sergey Poznyakoff
9d1993f651 Work over a bug in gnulib error()
The error() function from glibc correctly prefixes each message it
prints with program_name as set by set_program_name. However, its
replacement from gnulib, which is linked in on systems where this
function is not available, prints the name returned by getprogname()
instead. Due to this messages output by tar subprocess (which sets its
program name to 'tar (child)') become indiscernible from those printed
by the main process. In particular, this breaks the remfiles01.at and
remfiles02.at test cases.

* configure.ac: Define ENABLE_ERROR_PRINT_PROGNAME if using
gnulib error().
* src/tar.c [ENABLE_ERROR_PRINT_PROGNAME] (tar_print_progname): New function.
(main) [ENABLE_ERROR_PRINT_PROGNAME]: Set error_print_progname.
2018-12-28 17:49:08 +02:00
Sergey Poznyakoff
e7cd377f78 Implement the "wait" checkpoint action.
This action instructs tar to pause until given signal is delivered.
The newer genfile tool uses this action for communication between
genfile and tar in exec mode. This eliminates race conitions and
speeds up the tests based on exec mode.

* doc/tar.texi: Document changes.
* paxutils: Upgrade.
* src/checkpoint.c: Implement the wait action.
* src/common.h (decode_signal): New proto.
* src/tar.c (decode_signal): New function.
(set_stat_signal): Rewrite.
* tests/dirrem01.at: Adjust genfile and tar command line arguments
to use the new feature.
* tests/dirrem02.at: Likewise.
* tests/filerem01.at: Likewise.
* tests/filerem02.at: Likewise.
* tests/grow.at: Likewise.
* tests/sptrcreat.at: Likewise.
* tests/sptrdiff00.at: Likewise.
* tests/sptrdiff01.at: Likewise.
* tests/truncate.at: Likewise.
2018-12-28 13:27:02 +02:00
Sergey Poznyakoff
c15c42ccd1 Fix CVE-2018-20482
* NEWS: Update.
* src/sparse.c (sparse_dump_region): Handle short read condition.
(sparse_extract_region,check_data_region): Fix dumped_size calculation.
Handle short read condition.
(pax_decode_header): Fix dumped_size calculation.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.

* tests/sptrcreat.at: New file.
* tests/sptrdiff00.at: New file.
* tests/sptrdiff01.at: New file.
2018-12-27 17:53:38 +02:00
Sergey Poznyakoff
3c2a2cd94d Disallow modifications to the global pax extended header in update mode.
Updating global headers in update mode is not possible, because:

1) If the original archive was not in PAX format, writing the
global header would overwrite first member header (and eventually
data blocks) in the archive.
2) Otherwise, using the --pax-option can make the updated header
occupy more blocks than the original one, which would lead to the
same effect as in 1.

This also fixes
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00007.html

* src/xheader.c (xheader_forbid_global): New function.
* src/common.h (xheader_forbid_global): New prototype.
* src/update.c (update_archive): Use xheader_forbid_global, instead
of trying to write global extended header record.
2018-12-21 14:39:49 +02:00
Sergey Poznyakoff
ea3aea06f1 Bugfix
Bug reported in
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00014.html

* src/names.c (collect_and_sort_names): Fix iteration over namelist.
2018-12-21 13:54:12 +02:00
Sergey Poznyakoff
983a82a376 Fix semantics of -K used together with explicit member names.
This also fixes the bug reported in
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00012.html

* src/common.h (starting_file_option): Describe the variable.
* src/names.c (add_starting_file): New function.
(name_match): Ignore everything before the member indicated by the
--starting-file option
* src/tar.c: Use add_starting_file to handle the -K option.
2018-12-21 13:54:11 +02:00
Sergey Poznyakoff
916fe62ae9 Fix error handling when reading incremental snapshots
Bug reported in
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00008.html

* incremen.c (read_incr_db_01): Don't try to continue after errors.
2018-12-21 13:54:11 +02:00
Sergey Poznyakoff
99d415e190 Reject pax options starting with equals sign
Bug reported in
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00010.html

* xheader.c (xheader_set_keyword_equal): Bail out if the keyword starts
with =
2018-12-21 13:54:11 +02:00
Sergey Poznyakoff
c7c59b57fa Fix buffer overflow
Bug reported in
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00011.html

* src/xheader.c (xheader_format_name): fix length calculation
2018-12-21 13:54:11 +02:00
Sergey Poznyakoff
eae48289c0 Fix improper memory access
Bug reported in
  http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00009.html

* src/transform.c (parse_transform_expr): Check if re is not empty
before accessing its last byte.
2018-12-21 13:54:11 +02:00
Sergey Poznyakoff
62c0c3a780 Fix parsing of ACLs
Text returned by acl_to_text can contain comments (introduced by #).
Strip comments and horizontal tabs prior to storing ACLs in PAX
headers.

* src/xattrs.c (xattrs_acls_cleanup): New function.
(xattrs__acls_get_a,xattrs__acls_get_d): Use xattrs_acls_cleanup.
2018-11-24 22:10:53 +02:00
Sergey Poznyakoff
ba472050da Don't try to read past the end of header string fields
* src/common.h (assign_string_n): New proto.
(ASSIGN_STRING_N): New macro.
* src/misc.c (assign_string_n): New function.
* gnulib.modules: Add strnlen.
* src/buffer.c: Use assign_string_n where appropriate.
* src/list.c: Likewise.
2018-11-24 17:57:32 +02:00
Sergey Poznyakoff
f6e2860e8a Fix verbose ACL listing
* src/xattrs.c (acls_one_line): Advance pos.
(xattrs_print): Insert a comma between ACL and default ACL if both
are non-empty.
2018-11-12 09:17:25 +02:00
Paul Eggert
2777a2bfd9 tar: fix numbered backup bug
* src/misc.c (maybe_backup_file): Pass chdir_fd, not AT_FDCWD,
to find_backup_file_name.  This fixes a bug whereby the wrong
backup file name was chosen for numbered backups.
2018-10-28 16:24:05 -07:00
Paul Eggert
9fc1cb40f9 * src/tar.c (expand_pax_option): Pacify recent GCC. 2018-10-28 16:08:59 -07:00
Paul Eggert
6238296458 build: update gnulib submodule to latest
* src/misc.c (maybe_backup_file): Adjust to Gnulib change.
2018-10-28 16:08:59 -07:00
Sergey Poznyakoff
9042dfc4b1 Minor fixes in wordsplit.c 2018-08-02 16:36:48 +03:00
Paul Eggert
016d6d27d1 build: update gnulib submodule to latest 2018-08-02 00:12:46 -07:00
Sergey Poznyakoff
e54741745c Silence gcc warnings in wordsplit 2018-07-31 16:05:28 +03:00
Sergey Poznyakoff
110e3bd7a6 Fix double-free introduced by 577dc345
* src/utf8.c (utf8_convert): Don't store freed value in *output
2018-07-31 15:57:11 +03:00
Pavel Raiskup
c1b569d9d6 Report race on systems without O_DIRECTORY
* src/names.c (collect_and_sort_names): Report ENOTDIR after
successful fstat() but !S_ISDIR.
2018-07-31 12:13:48 +03:00
Pavel Raiskup
577dc34565 Avoid some resource leaks
* src/incremen.c (store_rename): Free temp_name, leaked before for
each renamed directory with --listed-incremental.
* src/transform.c (add_literal_segment): Tighten arguments by
const.
(parse_transform_expr): Free 'str', leaked storage for each
--transform option before.
* src/utf8.c (utf8_convert): Deallocate buffer for failed iconv()
call so callers don't have to.
2018-07-31 12:06:09 +03:00
Sergey Poznyakoff
c7b3f0217f Sync wordsplit and paxutils with the most recent versions 2018-07-31 11:56:44 +03:00
Paul Eggert
e81c89ddd6 * doc/tar.1: Fix font typo noted by esr. 2018-06-13 15:07:32 -07:00
Paul Eggert
07b0026e5d * doc/tar.1: Don't refer to nonexistent tar(5). 2018-05-16 09:03:47 -07:00
Jim Meyering
b531801d6f --one-top-level: avoid a heap-buffer-overflow
* NEWS: Mention this.
* src/suffix.c (strip_compression_suffix): Fix string comparison guard.
Without this change, some ASAN-enabled test runs would fail with the
following.  Also, strip an additional .tar suffix only if the just-
stripped suffix did not match /^\.t/".

==30815==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000002ed at pc 0x00000049d1f4 bp 0x7ffeb5906d50 sp 0x7ffeb5906500
READ of size 1 at 0x6020000002ed thread T0
SCARINESS: 12 (1-byte-read-heap-buffer-overflow)
    #0 0x49d1f3 in __interceptor_strncmp /j/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:407
    #1 0x5670f3 in strip_compression_suffix /j/tar/src/suffix.c:107
    #2 0x575788 in decode_options /j/tar/src/tar.c:2545
    #3 0x5760c0 in main /j/tar/src/tar.c:2708
    #4 0x7f105090df29 in __libc_start_main ../csu/libc-start.c:308
    #5 0x408629 in _start (/j/tar/src/tar+0x408629)

0x6020000002ed is located 3 bytes to the left of 6-byte region [0x6020000002f0,0x6020000002f6)
allocated by thread T0 here:
    #0 0x4d0710 in __interceptor_malloc /j/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
    #1 0x4908ad in __interceptor_strndup /j/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:326
    #2 0x5cbcbd in xstrndup /j/tar/gnu/xstrndup.c:32
    #3 0x5a325b in base_name /j/tar/gnu/basename.c:57
    #4 0x575772 in decode_options /j/tar/src/tar.c:2544
    #5 0x5760c0 in main /j/tar/src/tar.c:2708
    #6 0x7f105090df29 in __libc_start_main ../csu/libc-start.c:308
2018-04-13 11:05:01 +03:00
Andrew Hounsell
f563b896cc Tiny fix
* doc/snapshot.texi: Fix a typo
* scripts/tar-snapshot-edit: Fix a typo
2018-04-07 11:07:57 +03:00
Jim Meyering
c90c6fee01 tests: avoid test failure with non-ancient autoconf
Running "make check" would fail with this:
  T-nonl.at:30: error: m4_divert_push: cannot change diversion
  to `GROW' inside m4_expand
* tests/T-nonl.at: Use printf in place of AS_ECHO_N.
These days, printf should work for everyone.
2018-04-07 10:58:00 +03:00
Jim Meyering
0a0242582f maint: avoid -Wstringop-truncation warnings from upcoming GCC8
* src/create.c (start_private_header, start_header): Convert
trivial uses of strncpy to memcpy, to avoid warnings like this:
In function 'strncpy',
    inlined from 'start_private_header' at create.c:522:3:
/usr/include/bits/string_fortified.h:106:10: warning: \
  '__builtin_strncpy' output truncated before terminating nul \
  copying 2 bytes from a string of the same length \
  [-Wstringop-truncation]
2018-04-07 10:38:31 +03:00
Jim Meyering
2baa531ce5 maint: avoid -Wstringop-truncation warnings upcoming GCC8
* src/buffer.c (gnu_add_multi_volume_header): Convert a use of
strncpy to memcpy, to avoid this warning:
In function 'strncpy',
    inlined from 'gnu_add_multi_volume_header' at buffer.c:1782:3,
    ...
/usr/include/bits/string_fortified.h:106:10: error: '__builtin_strncpy'\
   specified bound 100 equals destination size \
   [-Werror=stringop-truncation]
2018-04-07 10:37:16 +03:00
Jim Meyering
ccef8581b8 maint: avoid warnings from upcoming GCC8
* src/transform.c (_single_transform_name_to_obstack): Mark with
FALLTHROUGH statement rather than /* FALL THROUGH */ comment.
Only the former works with gcc-8.
* src/extract.c (maybe_recoverable): Call abort to tell gcc-8 that
this code is unreachable.
2018-04-07 10:36:23 +03:00
Sergey Poznyakoff
2d00d8b321 Rewrite struct tm formatting
* src/list.c (tartime): Use strftime instead of manually formatting
fields of the struct tm. This should also suppress some gcc warnings.
2018-04-07 10:33:27 +03:00
Jim Meyering
e8c3f4860d tests: add coverage for new --zstd and all other compression tools
* tests/compress.at.in: New file: template from which each
per-compression-tool test is derived.
* tests/Makefile.am (TESTSUITE_AT): Add it.
(EXTRA_DIST): Add compress.at.in.
(compress-*.at): New rules to generate a file/tests for each compression tool.
* tests/testsuite.at (Compression): Add each of these generated
files in a new section.
* tests/.gitignore: Ignore the new generated files.
2018-04-07 10:32:38 +03:00
Aaron Schrab
00f03498a9 Fix typo 2018-03-18 12:06:36 +02:00
Sergey Poznyakoff
688924d2a8 Version 1.30.90
* NEWS: Update.
* configure.ac: Update.
* THANKS: Add Adam Borowski.
2018-03-18 10:38:16 +02:00
Adam Borowski
3d45373d3b Add support for zstd compression
* configure.ac (zstd): Register compression program.
* doc/tar.1: Mention --zstd.
* doc/tar.texi: Document zstd support.
* src/buffer.c: Register zstd compression.
* src/suffix.c: Add suffixes zst and tzst.
* src/tar.c: New compression option --zstd.
2018-03-18 10:24:13 +02:00
Pavel Raiskup
64b43fdf70 tests: fix race in dirrem01 and dirrem02
Previously the '--checkpoint-action=echo' was triggered after
'--checkpoint-action=sleep=1' - so the order of events *usually*
was (for --format='gnu'):

  ...
  1. checkpoint handler before write of 'dir/sub' member
  2. one-second delay
  3. stderr write: 'tar: Write checkpoint 3'
  4. write the member 'dir/sub' into the archive
  5. check that the member's ctime has not been changed
  6. genfile's detecting 'Write checkpoint', doing unlink
  ...

But sometimes, the genfile was fast enough to win the race and
unlinked the directory before the member was written into the
archive (IOW, the order was 1-2-3-6-4-5).  This led to the
occasional warning 'tar: dir/sub: file changed as we read it'.

Swap the order of 'sleep=1' and 'echo' actions so the genfile
utility has (hopefully) enough time to do the unlink before
writing the file into the archive (enforce 1-2-3-6-4-5 order).

* tests/dirrem01.at: Swap 'sleep=1' and 'echo' actions.
* tests/dirrem02.at: Likewise.
2018-03-18 08:33:03 +02:00
Sergey Poznyakoff
7b8efcc7cb Fix typos in the docs 2018-03-13 22:20:53 +02:00
Sergey Poznyakoff
c13401c0a7 Provide a way to skip tests that create very large files
Define environment variable TARTEST_SKIP_LARGE_FILES=1 in order
to skip tests that require lots of disk space.

* tests/testsuite.at (AT_SKIP_LARGE_FILES): New macro.
* tests/sparse03.at: Mark test with AT_SKIP_LARGE_FILES.
* tests/sparse05.at: Likewise.
* tests/star/pax-big-10g.at: Likewise.
* tests/star/ustar-big-2g.at: Likewise.
* tests/star/ustar-big-8g.at: Likewise.
2018-03-13 21:58:37 +02:00
Sergey Poznyakoff
847a36f064 Testsuite bugfix
* tests/difflink.at: Define order of files within tested archive.
2018-03-13 09:59:11 +02:00
Sergey Poznyakoff
2b7fc4aee9 testsuite: account for absolute file names starting with double slash
* tests/incr08.at: Absolute file names can start with //
* tests/xform03.at: Likewise.
2018-03-13 08:08:44 +02:00
Sergey Poznyakoff
f8459cf838 Version 1.30
* configure.ac: Set version 1.30
* NEWS: Update.
2017-12-17 12:28:30 +02:00
Paul Eggert
22b5645879 Fix "concatenating" typo.
Problem reported by Rodrigo Queiro in:
https://lists.gnu.org/r/bug-tar/2017-11/msg00021.html
* doc/intern.texi (Extensions): Fix typo.
2017-11-20 11:10:25 -08:00
Paul Eggert
d44d592013 Port to gcc -Wimplicit-fallthrough=5
* src/common.h (FALLTHROUGH): New macro, for use with gcc
-Wimplicit-fallthrough=5, which is now the default when used with
Gnulib after commit 2017-05-16T16:23:52!eggert@cs.ucla.edu
and with --enable-gcc-warnings
2017-11-18 08:42:23 -08:00
Paul Eggert
0c8e7bad3e Port to Texinfo 6.4
* doc/tar.texi (Sparse Recovery): Omit ‘.’ from anchor name,
as ‘makeinfo’ now complains about it.  All uses changed.
2017-11-18 08:42:23 -08:00
Paul Eggert
37d7ce16c5 Document base-256 representation in GNU format
Problem reported by Rodrigo Queiro in:
https://lists.gnu.org/r/bug-tar/2017-11/msg00018.html
* doc/intern.texi (Standard, Extensions):
Document base-256 representations.
2017-11-18 08:42:23 -08:00
Paul Eggert
9ed0a6ba35 build: update gnulib submodule to latest 2017-11-18 08:42:23 -08:00
Paul Eggert
35008b75e4 Fix typo caught by GCC 7.2.1
* lib/wordsplit.c (wordsplit_perror): Add missing "break;".
2017-11-18 08:42:23 -08:00
Sergey Poznyakoff
9855bc011e Update docs
* doc/Makefile.am: Add recipes.texi
* doc/recipes.texi: New file.
* doc/tar.texi: New appendix "Recipes"
2017-11-16 18:12:36 +02:00
Pavel Raiskup
22093ad2b6 tests: more deterministic xattr07
* tests/xattr07.at: Define order of files within tested archive.
2017-11-16 14:45:01 +02:00
Sergey Poznyakoff
ee0508f01c Minor improvements in the docs. 2017-11-16 14:31:53 +02:00
Sergey Poznyakoff
32e51de2af New option --warning=failed-read
* NEWS: Document the --warning=failed-read option.
* doc/tar.texi: Likewise.
* doc/tar.1: Likewise.
* src/common.h (WARN_FAILED_READ): New constant.
(WARNING_ENABLED): New macro.
* src/misc.c (close_diag, open_diag)
(read_diag_details, readlink_diag)
(savedir_diag, seek_diag_details)
(stat_diag): Suppress warnings if WARN_FAILED_READ is set.
* src/warning.c (failed-read): New keyword.
2017-11-16 14:22:48 +02:00
Sergey Poznyakoff
560f67c9f0 Fix docs
* doc/tar.texi: Fix description of the argument to --xattrs-exclude
and --xattrs-include option. It is a globbing pattern, not a regex.

Fix a typo (LZOP)
2017-11-16 12:24:45 +02:00
Sergey Poznyakoff
3ae075a51a Fix the --delay-directory-restore option
* src/extract.c (find_direct_ancestor): New function.
(create_placeholder_file): Set after_links member on delayed_set_stat
entries starting from the direct ancestor of the placeholder file.

* tests/extrac21.at: New testcase.
* tests/testsuite.at: Add extrac21
* tests/Makefile.am: Likewise.

* NEWS: Update.
2017-11-16 11:34:13 +02:00
Sergey Poznyakoff
1bf590ab2d Fix reporting of hardlink mismatch during compare
* src/common.h (quote_n_colon): New prototype.
* src/misc.c (quote_n_colon): New function.
* src/compare.c (report_difference, diff_link): Use quote_n_colon.

* tests/difflink.at: New file.
* tests/Makefile.am: Add difflink.at
* tests/testsuite.at: Likewise.
2017-11-09 09:55:43 +02:00
Sergey Poznyakoff
dee7e3f16e Fix --verbatim-files-from
* src/names.c (read_next_name): Don't unquote name read from the
file, if --verbatim-files-from option is in effect.
(names_options): improve description of --verbatim-files-from
* tests/T-null2.at: Test the change.
2017-11-09 09:06:26 +02:00
Sergey Poznyakoff
13edc746f6 Fix typo
* doc/tar.texi
2017-11-09 09:06:18 +02:00
Sergey Poznyakoff
1e6d2c0488 Fix the effect of --transform over hard link targets without the --absolute-names
* src/create.c (file_count_links): Apply safer_name_suffix to the
hard link name prior to transforming it.
* tests/xform03.at: New test case.
* tests/Makefile.am: Add xform03.at
* tests/testsuite.at: Likewise.
2017-09-30 10:26:56 +03:00
Sergey Poznyakoff
228d83ed24 Bugfix
* src/tar.c (tar_help_filter): Add missing break statement
2017-08-24 22:18:39 +03:00
Troels Thomsen
ede0d1b42d Fix typo 2017-06-29 14:23:15 +03:00
Pavel Raiskup
1e8b786e65 Fix non-deterministic archive type detection
Due to analysis of partly uninitialized read-ahead buffer
(short_read call), we sometimes mistakenly classified very small
compressed archives as non-compressed; which in turn caused
extraction failure.

* src/buffer.c (check_compressed_archive): Don't assume that
archives smaller than BLOCKSIZE could be non-compressed, as tar
header always has at least one block.
2017-05-29 16:12:48 +03:00
Jonas Julino
8b9026f3ae Fix handling of directories removed during incremental tar run
Co-authored-by: Sergey Poznyakoff <gray@gnu.org.ua>
* paxutils: Upgrade
* src/create.c (create_archive): Use file_removed_diag
instead of calling the corresponding *_diag function
directly.
* tests/dirrem01.at: New testcase.
* tests/dirrem02.at: New testcase.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Likewise.
2017-05-29 15:59:53 +03:00
Sergey Poznyakoff
795877532e Fix a bug in multi-volume archive creation.
When creating multivolume archives, the bufmap code in buffer.c
implicitly assumed that the members are stored in the archive
contiguously, ignoring the member (and eventual extended) headers
between them.  This worked until the member header happened to be
at the very beginning of the volume, in which case its length was
included in the calculation of the stored size and size left to
store.  Due to this, the GNUFileParts extended header contained
invalid GNU.volume.offset value, and the resulting archive failed
to extract properly.

This patch also eliminates improper listing of file part headers
as regular files, when creating multivolume posix archives with -v.

* src/buffer.c (bufmap): New member nblocks.  Counts number of blocks
of file data written since reset.
(bufmap_reset): Reset nblocks to 0.
(_flush_write): Update nblocks.  When computing offset difference for
bufmap_reset, count only data blocks, not headers.
(close_archive): Flush archive until all blocks are written.
(add_chunk_header): Use simple_finish_header instead of finish_header
to avoid listing chunk header as regular file in verbose mode.
* tests/multiv10.at: New test case.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Add new test.
2017-05-29 11:31:12 +03:00
Paul Eggert
da8d0659a6 --numeric-owner now affects private headers too
Problem reported by Daniel Peebles in:
http://lists.gnu.org/archive/html/bug-tar/2017-04/msg00004.html
* NEWS: Document this.
* src/create.c (write_gnu_long_link): If --numeric-owner,
leave the user and group empty in a private header.  Cache the
names for 0.
2017-04-06 18:18:12 -07:00
Pavel Raiskup
d06126f814 Test and document --keep-directory-symlink
* doc/tar.1: Document the option.
* tests/extrac20.at: New testcase.
* tests/Makefile.am: Mention extrac20.
* tests/testsuite.at: Likewise.
2017-02-28 12:59:17 +02:00
Paul Eggert
2be02a7c9a Fix incompatibility with PGI 16.10
* src/tar.c (options): Fix incompatibility with the C standard,
which says that arguments to macro calls cannot contain # directives.
2017-02-14 08:55:28 -08:00
Sergey Poznyakoff
30fe67226a Update copyright years 2017-01-02 14:49:55 +02:00
Sergey Poznyakoff
2bfacfe3d0 Fix description of the "escape" quoting style 2016-11-12 12:49:10 +02:00
Sergey Poznyakoff
76dad6d1fb Better error checking in the backup script.
* scripts/backup.in: Check exit code of MT_BEGIN
* scripts/backup.sh.in (backup_host): Return meaningful code
in case of remote execution.  See the comment, though.
2016-11-12 12:31:24 +02:00
Sergey Poznyakoff
a2fd82f622 Minor documentation fix
* doc/tar.texi: Fix example about use of --no-recursion with -T
2016-11-12 11:46:43 +02:00
Sergey Poznyakoff
3a283cfe9f Fix the --add-file option.
* src/common.h (name_more_files): New proto.
(files_from_option): Remove.
* src/names.c (name_more_files): New file.
(names_options): Fix declaration of the
add-file option.
(names_parse_opt): Handle --add-file.
* src/tar.c (struct tar_args): Remove the input_files member.
Change all uses: use name_more_files() instead.
* tests/Makefile.am: Add new test.
* tests/add-file.at: New testcase.
* tests/testsuite.at: Add new test.
2016-11-12 11:27:08 +02:00
Sergey Poznyakoff
ca9399d4ee Add missing files 2016-11-11 13:29:55 +02:00
Pavel Raiskup
597b0ae509 don't set xattrs when --skip-old-files is used
* src/extract.c (set_xattr): Properly handle maybe_recoverable()
output.  Throw warnings to not complicate caller.
(extract_file): Don't handle set_xattr's error.
* tests/xattr07.at: New testcase.
* tests/Makefile.am: Mention new testcase.
* tests/testsuite.at: Likewise.
* THANKS: Dawid.
2016-11-11 12:31:40 +02:00
Sergey Poznyakoff
21c1c29592 Minor fix
* src/tar.h (tar_stat_info): Change type of real_size_set to bool
2016-11-11 12:22:03 +02:00
Pavel Raiskup
00f928642f sparse: fix pax extraction for unicode filenames
Make sure that 'GNU.sparse.name' header has higher priority than
(for sparse-purposes artificially modified) 'path' pax header.

Historically, the 'GNU.sparse.name' header comes before 'path';
this caused that modified 'path' header won and that is not what
we want in sparse "capable" tar implementation.

* src/tar.h (tar_stat_info): New argument sparse_name_done.
* src/xheader.c (raw_path_decoder): Move here the unconditional
code from path_decoder.
(path_decoder): Apply raw_path_decoder only if sparse_path_decoder
was not yet called.
(sparse_path_decoder): New wrapper around raw_path_decoder.
* tests/sparse07.at: New testcase.
* tests/testsuite.at: Mention new testcase.
* tests/Makefile.am: Likewise.
2016-11-11 11:18:32 +02:00
Pavel Raiskup
c81a0853bb * tests/xattr06.at: Test include/exclude during archive/exctract. 2016-11-10 10:02:44 +02:00
Ian McLeod
bb6ddd8e04 Bugfix - fix xattr exclude/include for archive create
This makes archive create behavior consistent with the
documentation.  Without this change xattr include/exclude options
are accepted when creating an archive but are silently ignored.

* src/xattrs.c (xattrs_xattrs_get): Apply exclude/include mask
when fetching extended attributes
* tests/Makefile.am: Add new test case.
* tests/testsuite.at: Likewise.
2016-11-10 10:02:31 +02:00
Paul Eggert
7340f67b98 When extracting, skip ".." members
* NEWS: Document this.
* src/extract.c (extract_archive): Skip members whose names
contain "..".
2016-10-29 21:05:35 -07:00
Sergey Poznyakoff
1d2674bacc Mark all tests related to -C option with the "chdir" keyword 2016-09-26 14:00:12 +03:00
Sergey Poznyakoff
e1b7e40ff0 Fix interaction of -u with -C
* src/update.c (update_archive): Pass correct change_dir
value for addname
* tests/update03.at: New file.
* tests/Makefile.am: Add update03.at
* tests/testsuite.at: Include update03.at
2016-09-26 13:53:50 +03:00
Sergey Poznyakoff
c2886473a8 Fix passing string values via TAR_OPTIONS
* src/tar.c (parse_default_options): Don't free parsed words.
* tests/options03.at: New testcase.
* tests/Makefile.am: Add options03.at
* tests/testsuite.at: Include options03.at
2016-09-21 08:58:10 +03:00
Sergey Poznyakoff
ac065c57fd Tiny bugfix 2016-05-28 01:05:07 +03:00
Sergey Poznyakoff
9a33077a7b Report positional options that were used but had no effect during archive creation
* src/names.c (file_selection_option)
(file_selection_option_name): New functions.
(unconsumed_option_push, unconsumed_option_free)
(unconsumed_option_report): New functions.
(name_list_advance): Maintain a list
of eventually unconsumed options during archive creation.
Report unconsumed options, if any.

* tests/positional01.at: New test case.
* tests/positional02.at: New test case.
* tests/positional03.at: New test case.
* tests/Makefile.am: Add new test cases.
* tests/testsuite.at: Likewise.

* NEWS: Document the changes.
* configure.ac: Version 1.29.90
* doc/tar.texi: Document the changes.
2016-05-27 11:50:19 +03:00
322 changed files with 5858 additions and 2303 deletions

2
.gitignore vendored
View File

@@ -8,6 +8,7 @@
.deps
.emacs*
.libs
.gdbinit
ABOUT-NLS
ChangeLog
INSTALL
@@ -28,3 +29,4 @@ libtool
m4
rmt
stamp-h1
TAGS

View File

@@ -1,7 +1,6 @@
# Main Makefile for GNU tar.
# Copyright 1994-1997, 1999-2001, 2003, 2007, 2009, 2013-2014, 2016 Free
# Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

163
NEWS
View File

@@ -1,5 +1,152 @@
GNU tar NEWS - User visible changes. 2016-05-16
GNU tar NEWS - User visible changes. 2021-02-13
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.34 - Sergey Poznyakoff, 2021-02-13
* Fix extraction over pipe (savannah bug #60002)
* Fix memory leak in read_header (savannah bug #59897)
* Fix extraction when . and .. are unreadable
See https://lists.gnu.org/archive/html/bug-tar/2021-01/msg00012.html
* Gracefully handle duplicate symlinks when extracting
See https://lists.gnu.org/archive/html/bug-tar/2021-01/msg00026.html
* Re-initialize supplementary groups when switching to user privileges
version 1.33 - Sergey Poznyakoff, 2021-01-07
* POSIX extended format headers do not include PID by default
The intent is to make binary-equivalent PAX archives easy to create. If
POSIXLY_CORRECT is set, the POSIX standard default is used, which embeds
the pid.
* --delay-directory-restore works for archives with reversed member ordering
* Fix extraction of a symbolic link hardlinked to another symbolic link
* Wildcards in exclude-vcs-ignore mode don't match slash
* Fix the --no-overwrite-dir option
Given this option, previous versions of tar failed to preserve
permissions of empty directories and to create files under directories
owned by the current user that did not have the S_IWUSR bit set.
* Fix handling of chained renames in incremental backups
* Link counting works for file names supplied with -T
* Accept only position-sensitive (file-selection) options in file list files.
Using such options as -f, -z, etc. is senseless in a file list file and
bypasses option consistency checks in decode_options. Therefore,
only options related to file selection (a.k.a position-sensitive options)
are allowed in file list files.
version 1.32 - Sergey Poznyakoff, 2019-02-23
* Fix the use of --checkpoint without explicit --checkpoint-action
* Fix extraction with the -U option
See http://lists.gnu.org/archive/html/bug-tar/2019-01/msg00015.html,
for details
* Fix iconv usage on BSD-based systems
* Fix possible NULL dereference (savannah bug #55369)
* Improve the testsuite
version 1.31 - Sergey Poznyakoff, 2019-01-02
* Fix heap-buffer-overrun with --one-top-level.
Bug introduced with the addition of that option in 1.28.
* Support for zstd compression
New option '--zstd' instructs tar to use zstd as compression program.
When listing, extractng and comparing, zstd compressed archives are
recognized automatically.
When '-a' option is in effect, zstd compression is selected if the
destination archive name ends in '.zst' or '.tzst'.
* The -K option interacts properly with member names given in the command line
Names of members to extract can be specified along with the "-K NAME"
option. In this case, tar will extract NAME and those of named members
that appear in the archive after it, which is consistent with the
semantics of the option.
Previous versions of tar extracted NAME, those of named members that
appeared before it, and everything after it.
* Fix CVE-2018-20482
When creating archives with the --sparse option, previous versions of
tar would loop endlessly if a sparse file had been truncated while
being archived.
version 1.30 - Sergey Poznyakoff, 2017-12-17
* Member names containing '..' components are now skipped when extracting.
This fixes tar's behavior to match its documentation, and is a bit
safer when extracting untrusted archives over old files (an unsafe
practice that the tar manual has long recommended against).
* Report erroneous use of position-sensitive options.
During archive creation or update, tar keeps track of positional
options (see the manual, subsection 3.4.4 "Position-Sensitive
Options"), and reports those that had no effect. For example, when
invoked as
tar -cf a.tar . --exclude '*.o'
tar will create the archive, but will exit with status 2, having
issued the following error message
tar: The following options were used after non-optional
arguments in archive create or update mode. These options are
positional and affect only arguments that follow them. Please,
rearrange them properly.
tar: --exclude '*.o' has no effect
tar: Exiting with failure status due to previous errors
* --numeric-owner now affects private headers too.
This helps the output of 'tar' to be more deterministic.
* Fixed the --delay-directory-restore option
In some cases tar would restore the directory permissions too early,
causing subsequent link extractions in that directory to fail.
* The --warnings=failed-read option
This new warning control option suppresses warning messages about
unreadable files and directories. It has effect only if used together
with the --ignore-failed-read option.
* The --warnings=none option now suppresses all warnings
This includes warnings about unreadable files produced when
--ignore-failed-read is in effect. To output these, use
--warnings=none --warnings=no-failed-read.
* Fix reporting of hardlink mismatches during compare
Tar reported incorrect target file name in the 'Not linked to'
diagnostic message.
version 1.29 - Sergey Poznyakoff, 2016-05-16
@@ -24,7 +171,7 @@ the command line. Its effect is reverted by the
* --null option reads file names verbatim
The --null option implies --verbatim-files-from. I.e. each line
The --null option implies --verbatim-files-from. I.e. each line
read from null-delimited file lists is treated as a file name.
This restores the documented behavior, which was broken in version
@@ -55,7 +202,7 @@ use the time specified if the file mtime is newer than the given time.
The --clamp-mtime option can only be used together with --mtime.
Typical use case is to make builds reproducible: to loose less
information, it's better to keep the original date of an archive,
information, it's better to keep the original date of an archive,
except for files modified during the build process. In that case, using
reference (and thus reproducible) timestamps for the latter is good
enough.
@@ -103,7 +250,7 @@ sign and the specifier letter.
deleted, correspondingly.
%{FMT}t - Current local time using FMT as strftime(3) format.
If {FMT} is omitted, use %c.
%{N}* - Pad output with spaces to the Nth column, or to the
%{N}* - Pad output with spaces to the Nth column, or to the
current screen width, if {N} is not given.
%c - A shortcut for "%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r"
@@ -142,7 +289,7 @@ speed up archivation.
--exclude-vcs-ignores Read exclude tags from VCS ignore files,
where such files exist. Supported VCS's
are: CVS, Git, Bazaar, Mercurial.
* Tar refuses to read input from and write output to a tty device.
@@ -151,7 +298,7 @@ speed up archivation.
This release includes official tar(1) and rmt(8) manpages.
Distribution maintainers are kindly asked to use these instead of the
home-made pages they have been providing so far.
version 1.27.1 - Sergey Poznyakoff, 2013-11-17
@@ -244,7 +391,7 @@ 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.
symlinks to directories when extracting from the archive.
It is mainly intended to provide compatibility with the Slackware
installation scripts.
@@ -1587,7 +1734,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
Copyright 1994-2001, 2003-2010, 2013-2016 Free Software Foundation, Inc.
Copyright 1994-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

3
README
View File

@@ -221,8 +221,7 @@ and share your findings by writing to <bug-tar@gnu.org>.
* Copying
Copyright 1990-1992, 1994, 1997-2001, 2003-2004, 2007, 2012-2014, 2016
Free Software Foundation, Inc.
Copyright 1990-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -35,8 +35,7 @@ behavior. Run 'bootstrap --help' for a list.
Copyright 2001, 2003-2005, 2007, 2013-2016 Free Software Foundation,
Inc.
Copyright 2001-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -39,7 +39,7 @@ See 'bootstrap --help' for a detailed list.
* Copyright information
Copyright 2007-2009, 2013-2016 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

3
THANKS
View File

@@ -8,6 +8,7 @@ list of these people. Help me keep it complete and exempt of errors.
See various ChangeLogs for a detailed description of contributions.
Aage Robeck aagero@ifi.uio.no
Adam Borowski kilobyte@angband.pl
Adye, TJ (Tim) T.J.Adye@rl.ac.uk
Akiko Matsushita matusita@sra.co.jp
Alan Bawden Alan@lcs.mit.edu
@@ -94,6 +95,7 @@ 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
Christian Weisgerber naddy@mips.inka.de
Christoph Litauer litauer@mailhost.uni-koblenz.de
Christophe Colle colle@krtkg1.rug.ac.be
Christophe Kalt Christophe.Kalt@kbcfp.com
@@ -138,6 +140,7 @@ David Nugent davidn@blaze.net.au
David Shaw david.shaw@alcatel.com.au
David Steiner dsteiner@ispa.uni-osnabrueck.de
David Taylor taylor@think.com
Dawid dpc@dpc.pw
Dean Gaudet dgaudet@watdragon.uwaterloo.ca
Demizu Noritoshi nori-d@is.aist-nara.ac.jp
Denis Excoffier denis.excoffier@free.fr

3
TODO
View File

@@ -45,8 +45,7 @@ Suggestions for improving GNU tar.
* Copyright notice
Copyright 2003-2004, 2007, 2013-2014, 2016 Free Software Foundation,
Inc.
Copyright 2003-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
dnl Special Autoconf macros for GNU tar -*- autoconf -*-
dnl Copyright 2009, 2013-2014, 2016 Free Software Foundation, Inc.
dnl Copyright 2009-2021 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU tar.
dnl

View File

@@ -4,7 +4,7 @@ scriptversion=2015-08-24.08; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2016 Free Software Foundation, Inc.
# Copyright (C) 2003-2021 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

View File

@@ -1,6 +1,6 @@
# Bootstrap configuration for GNU tar.
# Copyright 2006-2009, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
# Configure template for GNU tar. -*- autoconf -*-
# Copyright 1991, 1994-2010, 2013-2016 Free Software Foundation, Inc.
# Copyright 1991, 1994-2010, 2013-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -17,12 +17,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_INIT([GNU tar], [1.29], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.34], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_PREREQ([2.63])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-xz std-options silent-rules])
AC_PREREQ([2.64])
AM_INIT_AUTOMAKE([1.15 gnits tar-ustar dist-bzip2 dist-xz std-options silent-rules])
# Enable silent rules by default:
AM_SILENT_RULES([yes])
@@ -102,6 +102,18 @@ gt_TYPE_SSIZE_T
# gnulib modules
gl_INIT
if test $ac_cv_lib_error_at_line = no; then
# This means that the error() function is not present in libc, so
# the one from gnulib will be used instead. This function precedes
# error messages it prints with the program name as returned by getprogname()
# call, instead of using the name set by set_program_name.
# Install workaround.
AC_DEFINE([ENABLE_ERROR_PRINT_PROGNAME],[1],
[Enable the use of error_print_progname to print program name with error messages.
See comment to function tar_print_progname in src/tar.c])
fi
# paxutils modules
tar_PAXUTILS
@@ -250,6 +262,7 @@ TAR_COMPR_PROGRAM(lzip)
TAR_COMPR_PROGRAM(lzma)
TAR_COMPR_PROGRAM(lzop)
TAR_COMPR_PROGRAM(xz)
TAR_COMPR_PROGRAM(zstd)
AC_MSG_CHECKING(for default archive format)

View File

@@ -1,5 +1,5 @@
%%comments:
Copyright 2004, 2013-2014 Free Software Foundation, Inc.
Copyright 2004-2021 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.3 or

1
doc/.gitignore vendored
View File

@@ -24,3 +24,4 @@ tar.tp
tar.vr
version.texi
/parse-datetime.texi
/rmt.8

View File

@@ -1,7 +1,6 @@
# Makefile for GNU tar documentation.
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2013-2014, 2016 Free
# Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -23,11 +22,11 @@ tar_TEXINFOS = \
dumpdir.texi\
tar-snapshot-edit.texi\
fdl.texi\
freemanuals.texi\
genfile.texi\
header.texi\
intern.texi\
parse-datetime.texi\
recipes.texi\
rendition.texi\
snapshot.texi\
sparse.texi\

View File

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

View File

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

View File

@@ -1,89 +0,0 @@
@cindex free documentation
The biggest deficiency in the free software community today is not in
the software---it is the lack of good free documentation that we can
include with the free software. Many of our most important
programs do not come with free reference manuals and free introductory
texts. Documentation is an essential part of any software package;
when an important free software package does not come with a free
manual and a free tutorial, that is a major gap. We have many such
gaps today.
Consider Perl, for instance. The tutorial manuals that people
normally use are non-free. How did this come about? Because the
authors of those manuals published them with restrictive terms---no
copying, no modification, source files not available---which exclude
them from the free software world.
That wasn't the first time this sort of thing happened, and it was far
from the last. Many times we have heard a GNU user eagerly describe a
manual that he is writing, his intended contribution to the community,
only to learn that he had ruined everything by signing a publication
contract to make it non-free.
Free documentation, like free software, is a matter of freedom, not
price. The problem with the non-free manual is not that publishers
charge a price for printed copies---that in itself is fine. (The Free
Software Foundation sells printed copies of manuals, too.) The
problem is the restrictions on the use of the manual. Free manuals
are available in source code form, and give you permission to copy and
modify. Non-free manuals do not allow this.
The criteria of freedom for a free manual are roughly the same as for
free software. Redistribution (including the normal kinds of
commercial redistribution) must be permitted, so that the manual can
accompany every copy of the program, both on-line and on paper.
Permission for modification of the technical content is crucial too.
When people modify the software, adding or changing features, if they
are conscientious they will change the manual too---so they can
provide accurate and clear documentation for the modified program. A
manual that leaves you no choice but to write a new manual to document
a changed version of the program is not really available to our
community.
Some kinds of limits on the way modification is handled are
acceptable. For example, requirements to preserve the original
author's copyright notice, the distribution terms, or the list of
authors, are ok. It is also no problem to require modified versions
to include notice that they were modified. Even entire sections that
may not be deleted or changed are acceptable, as long as they deal
with nontechnical topics (like this one). These kinds of restrictions
are acceptable because they don't obstruct the community's normal use
of the manual.
However, it must be possible to modify all the @emph{technical}
content of the manual, and then distribute the result in all the usual
media, through all the usual channels. Otherwise, the restrictions
obstruct the use of the manual, it is not free, and we need another
manual to replace it.
Please spread the word about this issue. Our community continues to
lose manuals to proprietary publishing. If we spread the word that
free software needs free reference manuals and free tutorials, perhaps
the next person who wants to contribute by writing documentation will
realize, before it is too late, that only free manuals contribute to
the free software community.
If you are writing documentation, please insist on publishing it under
the GNU Free Documentation License or another free documentation
license. Remember that this decision requires your approval---you
don't have to let the publisher decide. Some commercial publishers
will use a free license if you insist, but they will not propose the
option; it is up to you to raise the issue and say firmly that this is
what you want. If the publisher you are dealing with refuses, please
try other publishers. If you're not sure whether a proposed license
is free, write to @email{licensing@@gnu.org}.
You can encourage commercial publishers to sell more free, copylefted
manuals and tutorials by buying them, and particularly by buying
copies from the publishers that paid for their writing or for major
improvements. Meanwhile, try to avoid buying non-free documentation
at all. Check the distribution terms of a manual before you buy it,
and insist that whoever seeks your business must respect your freedom.
Check the history of the book, and try reward the publishers that have
paid or pay the authors to work on it.
The Free Software Foundation maintains a list of free documentation
published by other publishers, at
@url{http://www.fsf.org/doc/other-free-books.html}.

View File

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

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006, 2014, 2016 Free Software Foundation, Inc.
@c Copyright (C) 2006--2021 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@@ -87,6 +87,8 @@ The @code{name}, @code{linkname}, @code{magic}, @code{uname}, and
@code{gname} are null-terminated character strings. All other fields
are zero-filled octal numbers in ASCII. Each numeric field of width
@var{w} contains @var{w} minus 1 digits, and a null.
(In the extended @acronym{GNU} format, the numeric fields can take
other forms.)
The @code{name} field is the file name of the file, with directory names
(if any) preceding the file name, separated by slashes.
@@ -112,14 +114,12 @@ be ignored.
The @code{size} field is the size of the file in bytes; linked files
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
value of the last time the file's contents were modified, represented
as an integer number of
The @code{mtime} field represents the data modification time of the file at
the time it was archived. It represents the integer number of
seconds since January 1, 1970, 00:00 Coordinated Universal Time.
The @code{chksum} field is the ASCII representation of the octal value
of the simple sum of all bytes in the header block. Each 8-bit
The @code{chksum} field represents
the simple sum of all bytes in the header block. Each 8-bit
byte in the header is added to an unsigned integer, initialized to
zero, the precision of which shall be no less than seventeen bits.
When calculating the checksum, the @code{chksum} field is treated as
@@ -310,6 +310,18 @@ of an archive should have this type.
@end table
For fields containing numbers or timestamps that are out of range for
the basic format, the @acronym{GNU} format uses a base-256
representation instead of an ASCII octal number. If the leading byte
is 0xff (255), all the bytes of the field (including the leading byte)
are concatenated in big-endian order, with the result being a negative
number expressed in two's complement form. If the leading byte is
0x80 (128), the non-leading bytes of the field are concatenated in
big-endian order, with the result being a positive number expressed in
binary form. Leading bytes other than 0xff, 0x80 and ASCII octal
digits are reserved for future use, as are base-256 representations of
values that would be in range for the basic format.
You may have trouble reading a @acronym{GNU} format archive on a
non-@acronym{GNU} system if the options @option{--incremental} (@option{-G}),
@option{--multi-volume} (@option{-M}), @option{--sparse} (@option{-S}), or @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) were

View File

@@ -1,6 +1,6 @@
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
;; Copyright 2006-2007, 2013-2014, 2016 Free Software Foundation, Inc.
;; Copyright 2006-2021 Free Software Foundation, Inc.
;; Author: Sergey Poznyakoff
;; Maintainer: bug-tar@gnu.org

134
doc/recipes.texi Normal file
View File

@@ -0,0 +1,134 @@
@c This is part of the GNU tar manual.
@c Copyright (C) 2017--2021 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.3 or any later version
@c published by the Free Software Foundation.
This appendix provides several recipes for performing common tasks
using @GNUTAR{}.
@menu
* copy directory hierarchy::
* intermediate directories::
@end menu
@node copy directory hierarchy
@appendixsec Copying directory hierarchies
This is a traditional way to copy a directory hierarchy preserving
the dates, modes, owners and link-structure of all the files therein.
It was used back when the @command{cp} command lacked the @option{-a}
option:
@smallexample
$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xf -)}
@end smallexample
@noindent
You can avoid subshells by using @option{-C} option:
@smallexample
$ @kbd{tar -C sourcedir -cf - . | tar -C targetdir -xf -}
@end smallexample
@noindent
The same command using long option forms:
@smallexample
@group
$ @kbd{(cd sourcedir; tar --create --file=- . ) \
| (cd targetdir; tar --extract --file=-)}
@end group
@end smallexample
@noindent
or
@smallexample
@group
$ @kbd{tar --directory sourcedir --create --file=- . \
| tar --directory targetdir --extract --file=-}
@end group
@end smallexample
@node intermediate directories
@appendixsec Restoring Intermediate Directories
A common concern is how to extract permissions and ownerships of
intermediate directories when extracting only selected members from
the archive. To illustrate this, consider the following archive:
@example
@group
# tar tvf A.tar
drwxr-xr-x root/root 0 2017-11-16 14:39 foo/
dr-xr-x--- gray/user 0 2017-11-16 14:39 foo/bar/
-rw-r--r-- gray/user 10 2017-11-16 14:40 foo/bar/file
@end group
@end example
Suppose you extract only the file @file{foo/bar/file}, while being
@samp{root}:
@example
# @kbd{tar xvf A.tar foo/bar/file}
foo/bar/file
@end example
Now, let's inspect the content of the created directories:
@example
@group
# find foo -ls
427257 0 drwxr-xr-x 3 root root 16 Nov 17 16:10 foo
427258 0 drwxr-xr-x 2 root root 17 Nov 17 16:10 foo/bar
427259 0 -rw-r--r-- 1 gray user 10 Nov 6 14:40 foo/bar/file
@end group
@end example
The requested file is restored, including its ownership and
permissions. The intermediate directories, however, are created with
the default permissions, current timestamp and owned by the current
user. This is because by the time @command{tar} has reached the requested file,
it had already skipped the entries for its parent directories, so it
has no iformation about their ownership and modes.
To restore meta information about the intermediate directories,
you'll need to specify them explicitly in the command line and use the
@option{--no-recursive} option (@pxref{recurse}) to avoid extracting
their content.
To automate this process, @cite{Neal P. Murphy} proposed the following
shell script@footnote{The original version of the script can be
seen at @uref{http://lists.gnu.org/archive/html/bug-tar/2016-11/msg00024.html}}:
@example
@group
#! /bin/sh
(while read path
do
path=`dirname $path`
while [ -n "$path" -a "$path" != "." ]
do
echo $path
path=`dirname $path`
done
done < $2 | sort | uniq) |
tar -x --no-recursion -v -f $1 -T - -T $2
@end group
@end example
The script takes two arguments: the name of the archive file, and the
name of the file list file.
To complete our example, the file list will contain single line:
@example
foo/bar/file
@end example
Supposing its name is @file{file.list} and the script is named
@file{restore.sh}, you can invoke it as follows:
@example
# @kbd{sh restore.sh A.tar file.list}
@end example

View File

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

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2005, 2007, 2014, 2016 Free Software Foundation, Inc.
@c Copyright (C) 2005--2021 Free Software Foundation, Inc.
@c Written by Sergey Poznyakoff
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@@ -146,7 +146,7 @@ is compiled. To see the specific ranges allowed for a particular
@option{--show-snapshot-field-ranges} option:
@smallexample
$ @kbd{tar --show-shapshot-field-ranges}
$ @kbd{tar --show-snapshot-field-ranges}
This tar's snapshot file field ranges are
(field name => [ min, max ]):

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006, 2014, 2016 Free Software Foundation, Inc.
@c Copyright (C) 2006--2021 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@@ -143,7 +143,7 @@ format, it will also extract a file containing extension header
attributes. This file can be used to expand the file to its original
state. However, posix-aware @command{tar}s will usually ignore the
unknown variables, which makes restoring the file more
difficult. @xref{extracting sparse v.0.x, Extraction of sparse
difficult. @xref{extracting sparse v0x, Extraction of sparse
members in v.0.0 format}, for the detailed description of how to
restore such members using non-GNU @command{tar}s.
@end enumerate
@@ -175,7 +175,7 @@ The real name of the sparse file is stored in the variable
@code{GNU.sparse.name}. Thus, those @command{tar} implementations
that are not aware of GNU extensions will at least extract the files
into separate directories, giving the user a possibility to expand it
afterwards. @xref{extracting sparse v.0.x, Extraction of sparse
afterwards. @xref{extracting sparse v0x, Extraction of sparse
members in v.0.1 format}, for the detailed description of how to
restore such members using non-GNU @command{tar}s.
@@ -218,12 +218,12 @@ The real name of the sparse file is stored in the variable
variable @code{GNU.sparse.realsize}.
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length, delimited
file data. It consists of a series of decimal numbers delimited
by newlines. The map is padded with nulls to the nearest block boundary.
The first number gives the number of entries in the map. Following are map entries,
each one consisting of two numbers giving the offset and size of the
data block it describes.
The first number gives the number of entries in the map. Following are
map entries, each one consisting of two numbers giving the offset and
size of the data block it describes.
The format is designed in such a way that non-posix aware @command{tar}s and @command{tar}s not
supporting @code{GNU.sparse.*} keywords will extract each sparse file

View File

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

View File

@@ -1,5 +1,5 @@
.\" This file is part of GNU tar. -*- nroff -*-
.\" Copyright 2013-2014, 2016 Free Software Foundation, Inc.
.\" Copyright 2013-2021 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
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
.TH TAR 1 "March 23, 2016" "TAR" "GNU TAR Manual"
.TH TAR 1 "July 13, 2020" "TAR" "GNU TAR Manual"
.SH NAME
tar \- an archiving utility
.SH SYNOPSIS
@@ -111,7 +111,7 @@ into the archive file
verbosely listing the files being archived:
.PP
.EX
.B tar cfv a.tar /etc
tar cfv etc.tar /etc
.EE
.PP
In
@@ -133,9 +133,11 @@ The example command above written in the
could look like:
.PP
.EX
.B tar -cvf a.tar /etc
tar -cvf etc.tar /etc
.EE
or
.B tar -c -v -f a.tar /etc
.EX
tar -c -v -f etc.tar /etc
.EE
.PP
In
@@ -152,11 +154,11 @@ method.
Here are several ways of writing the example command in this style:
.PP
.EX
.B tar --create --file a.tar --verbose /etc
tar --create --file etc.tar --verbose /etc
.EE
or (abbreviating some options):
.EX
.B tar --cre --file=a.tar --verb /etc
tar --cre --file=etc.tar --verb /etc
.EE
.PP
The options in all three styles can be intermixed, although doing so
@@ -219,7 +221,10 @@ There is no short option equivalent for this option.
\fB\-u\fR, \fB\-\-update\fR
Append files which are newer than the corresponding copy in the
archive. Arguments have the same meaning as with \fB\-c\fR and
\fB\-r\fR options.
\fB\-r\fR options. Notice, that newer files don't replace their
old archive copies, but instead are appended to the end of archive.
The resulting archive can thus contain several members of the
same name, corresponding to various versions of the same file.
.TP
\fB\-x\fR, \fB\-\-extract\fR, \fB\-\-get\fR
Extract files from an archive. Arguments are optional. When given,
@@ -253,7 +258,7 @@ exist when creating an archive, it will be created and all files will
be added to the resulting archive (the \fBlevel 0\fR dump). To create
incremental archives of non-zero level \fBN\fR, create a copy of the
snapshot file created during the level \fBN-1\fR, and use it as
\fIFILE\fR.
\fIFILE\fR.
When listing or extracting, the actual contents of \fIFILE\fR is not
inspected, it is needed only due to syntactical requirements. It is
@@ -284,7 +289,7 @@ effect only if the archive is open for reading (e.g. with
.B \-\-list
or
.B \-\-extract
options).
options).
.TP
\fB\-\-no\-check\-device\fR
Do not check device numbers when creating incremental archives.
@@ -333,6 +338,9 @@ Don't replace existing files when extracting.
\fB\-\-keep\-newer\-files\fR
Don't replace existing files that are newer than their archive copies.
.TP
\fB\-\-keep\-directory\-symlink\fR
Don't replace existing symlinks to directories when extracting.
.TP
\fB\-\-no\-overwrite\-dir\fR
Preserve metadata of existing directories.
.TP
@@ -377,7 +385,7 @@ Extract files to standard output.
Pipe extracted files to \fICOMMAND\fR. The argument is the pathname
of an external program, optionally with command line arguments. The
program will be invoked and the contents of the file being extracted
supplied to it on its standard output. Additional data will be
supplied to it on its standard input. Additional data will be
supplied via the following environment variables:
.RS
.TP
@@ -457,9 +465,10 @@ Format of the archive being processed. One of:
.BR posix ,
.BR ustar ,
.BR v7 .
.TP
.B TAR_SUBCOMMAND
A short option (with a leading dash) describing the operation \fBtar\fR is
executing.
executing.
.RE
.SS Handling of file attributes
.TP
@@ -556,9 +565,6 @@ stored in archive with owner name \fINEWUSR\fR and UID \fINEWUID\fR.
\fB\-p\fR, \fB\-\-preserve\-permissions\fR, \fB\-\-same\-permissions\fR
extract information about file permissions (default for superuser)
.TP
\fB\-\-preserve\fR
Same as both \fB\-p\fR and \fB\-s\fR.
.TP
\fB\-\-same\-owner\fR
Try extracting files with the same ownership as exists in the archive
(default for superuser).
@@ -688,7 +694,7 @@ executing.
.B TAR_FD
File descriptor which can be used to communicate the new volume name
to
.BR tar .
.BR tar .
.RE
.RS
@@ -726,7 +732,7 @@ When this option is used in conjunction with
.BR \-\-multi\-volume ,
.B tar
will keep track of which volume of a multi-volume archive it is
working in \fIFILE\fR.
working in \fIFILE\fR.
.SS Device blocking
.TP
\fB\-b\fR, \fB\-\-blocking\-factor\fR=\fIBLOCKS\fR
@@ -734,7 +740,7 @@ Set record size to \fIBLOCKS\fRx\fB512\fR bytes.
.TP
\fB\-B\fR, \fB\-\-read\-full\-records\fR
When listing or extracting, accept incomplete input records after
end-of-file marker.
end-of-file marker.
.TP
\fB\-i\fR, \fB\-\-ignore\-zeros\fR
Ignore zeroed blocks in archive. Normally two consecutive 512-blocks
@@ -777,7 +783,8 @@ Same as \fB\-\-format=v7\fR.
\fB\-\-pax\-option\fR=\fIkeyword\fR[[:]=\fIvalue\fR][,\fIkeyword\fR[[:]=\fIvalue\fR]]...
Control pax keywords when creating \fBPAX\fR archives (\fB\-H
pax\fR). This option is equivalent to the \fB\-o\fR option of the
.BR pax (1) utility.
.BR pax (1)
utility.
.TP
\fB\-\-posix\fR
Same as \fB\-\-format=posix\fR.
@@ -825,6 +832,10 @@ Filter the archive through
\fB\-Z\fR, \fB\-\-compress\fR, \fB\-\-uncompress\fR
Filter the archive through
.BR compress (1).
.TP
\fB\-\-zstd\fR
Filter the archive through
.BR zstd (1).
.SS Local file selection
.TP
\fB\-\-add\-file\fR=\fIFILE\fR
@@ -953,7 +964,7 @@ See also \fB\-\-verbatim\-files\-from\fR.
.TP
\fB\-N\fR, \fB\-\-newer\fR=\fIDATE\fR, \fB\-\-after\-date\fR=\fIDATE\fR
Only store files newer than DATE. If \fIDATE\fR starts with \fB/\fR
or \fB.\fR it is taken to be a file name; the ctime of that file is
or \fB.\fR it is taken to be a file name; the mtime of that file is
used as the date.
.TP
\fB\-\-one\-file\-system\fR
@@ -1096,7 +1107,7 @@ Show file or archive names after transformation by \fB\-\-strip\fR and
Print total bytes after processing the archive. If \fISIGNAL\fR is
given, print total bytes when this signal is delivered. Allowed
signals are:
.BR SIGHUP ,
.BR SIGHUP ,
.BR SIGQUIT ,
.BR SIGINT ,
.BR SIGUSR1 ", and"
@@ -1107,7 +1118,11 @@ The \fBSIG\fR prefix can be omitted.
Print file modification times in UTC.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
Verbosely list files processed.
Verbosely list files processed. Each instance of this option on the
command line increases the verbosity level by one. The maximum
verbosity level is 3. For a detailed discussion of how various
verbosity levels affect tar's output, please refer to \fBGNU Tar
Manual\fR, subsection 2.5.1 "\fBThe \-\-verbose Option\fR".
.TP
\fB\-\-warning\fR=\fIKEYWORD\fR
Enable or disable warning messages identified by \fIKEYWORD\fR. The
@@ -1160,6 +1175,12 @@ Keywords applicable for \fBtar --create\fR:
.TP
.B file-changed
"%s: file changed as we read it"
.TP
.B failed-read
Suppresses warnings about unreadable files or directories. This
keyword applies only if used together with the
.B \-\-ignore\-failed\-read
option.
.HP
Keywords applicable for \fBtar --extract\fR:
.TP
@@ -1193,7 +1214,7 @@ default (unless \fB\-\-verbose\fR is used). A common example of what
you can get when using this warning is:
.EX
$ \fBtar --warning=decompress-program -x -f archive.Z
$ tar --warning=decompress-program -x -f archive.Z
tar (child): cannot run compress: No such file or directory
tar (child): trying gzip
.EE
@@ -1284,8 +1305,8 @@ failure during backup to a remote device.
.BR lzop (1),
.BR rmt (8),
.BR symlink (7),
.BR tar (5),
.BR xz (1).
.BR xz (1),
.BR zstd (1).
.PP
Complete \fBtar\fR manual: run
.B info tar
@@ -1301,7 +1322,7 @@ found at:
.SH "BUG REPORTS"
Report bugs to <bug\-tar@gnu.org>.
.SH COPYRIGHT
Copyright \(co 2013 Free Software Foundation, Inc.
Copyright \(co 2013-2019 Free Software Foundation, Inc.
.br
.na
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
@@ -1316,4 +1337,3 @@ There is NO WARRANTY, to the extent permitted by law.
.\" time-stamp-end: "\""
.\" time-stamp-line-limit: 20
.\" end:

View File

@@ -36,8 +36,8 @@ This manual is for @acronym{GNU} @command{tar} (version
@value{VERSION}, @value{UPDATED}), which creates and extracts files
from archives.
Copyright @copyright{} 1992, 1994--1997, 1999--2001, 2003--2016 Free
Software Foundation, Inc.
Copyright @copyright{} 1992, 1994--1997, 1999--2001, 2003--2017, 2021
Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -111,11 +111,11 @@ document. The rest of the menu lists all the lower level nodes.
Appendices
* Changes::
* Recipes:: Frequently used tar recipes
* Configuring Help Summary::
* Fixing Snapshot Files::
* Tar Internals::
* Genfile::
* Free Software Needs Free Documentation::
* GNU Free Documentation License::
* Index of Command Line Options::
* Index::
@@ -204,7 +204,6 @@ All @command{tar} Options
* create options::
* extract options::
* backup::
* Applications::
* looking ahead::
Advanced @GNUTAR{} Operations
@@ -1464,7 +1463,7 @@ tar: Removing leading '/' from member names
/home/myself/practice/folk
/home/myself/practice/jazz
/home/myself/practice/collection.tar
$ @kbd{tar --test --file practice.tar}
$ @kbd{tar --list --file practice.tar}
home/myself/practice/
home/myself/practice/blues
home/myself/practice/folk
@@ -1495,7 +1494,7 @@ home/myself/practice/blues
home/myself/practice/folk
home/myself/practice/jazz
home/myself/practice/collection.tar
$ @kbd{tar --test --file practice.tar}
$ @kbd{tar --list --file practice.tar}
home/myself/practice/
home/myself/practice/blues
home/myself/practice/folk
@@ -1521,7 +1520,7 @@ the error message is produced because there is no member named
@file{folk}, only one named @file{home/myself/folk}.
If you are not sure of the exact file name, use @dfn{globbing
patterns}, for example:
patterns}, for example:
@smallexample
$ @kbd{tar --list --file=practice.tar --wildcards '*/folk'}
@@ -2553,6 +2552,12 @@ Wait for @var{time} seconds.
@item ttyout=@var{string}
Output @var{string} on the current console (@file{/dev/tty}).
@item totals
Print statistics (see @pxref{totals}).
@item wait=@var{signo}
Wait for signal @var{signo}.
@end table
Several @option{--checkpoint-action} options can be specified. The
@@ -3155,7 +3160,7 @@ Disable extended attributes support. @xref{Extended File Attributes, xattrs}.
When @command{tar} is using the @option{--files-from} option, this option
instructs @command{tar} to expect file names terminated with
@acronym{NUL}, and to process file names verbatim.
@acronym{NUL}, and to process file names verbatim.
This means that @command{tar} correctly works with file names that
contain newlines or begin with a dash.
@@ -3703,8 +3708,8 @@ Specify exclude pattern for xattr keys.
@opsummary{xattrs-include}
@item --xattrs-include=@var{pattern}.
Specify include pattern for xattr keys. @var{pattern} is a POSIX
regular expression, e.g. @samp{--xattrs-exclude='^user\.'} to include
Specify include pattern for xattr keys. @var{pattern} is a globbing
pattern, e.g. @samp{--xattrs-include='user.*'} to include
only attributes from the user namespace.
@xref{Extended File Attributes, xattrs-include}.
@@ -3713,6 +3718,9 @@ only attributes from the user namespace.
@itemx -J
Use @command{xz} for compressing or decompressing the archives. @xref{gzip}.
@item --zstd
Use @command{zstd} for compressing or decompressing the archives. @xref{gzip}.
@end table
@node Short Option Summary
@@ -3786,8 +3794,8 @@ them with the equivalent long option.
@item -m @tab @ref{--touch}.
@item -o @tab When creating, @ref{--no-same-owner}, when extracting ---
@ref{--portability}.
@item -o @tab When extracting, same as @ref{--no-same-owner}. When creating,
-- @ref{--old-archive}.
The latter usage is deprecated. It is retained for compatibility with
the earlier versions of @GNUTAR{}. In future releases
@@ -3879,7 +3887,24 @@ tar -cf a.tar /usr --no-recursion /var/*
tar -cf a.tar --recursion /usr --no-recursion /var/*
@end example
The following table summarizes all position-sensitive options.
During archive creation, @GNUTAR{} keeps track of positional options
used and arguments affected by them. If it finds out that any such
options are used in an obviously erroneous way, the fact is reported
and exit code is set to 2. E.g.:
@example
@group
$ @kbd{tar -cf a.tar . --exclude '*.o'}
tar: The following options were used after any non-optional
arguments in archive create or update mode. These options are
positional and affect only arguments that follow them. Please,
rearrange them properly.
tar: --exclude '*.o' has no effect
tar: Exiting with failure status due to previous errors
@end group
@end example
The following table summarizes all position-sensitive options.
@table @option
@item --directory=@var{dir}
@@ -3898,24 +3923,24 @@ The following table summarizes all position-sensitive options.
@itemx --no-verbatim-files-from
@xref{verbatim-files-from}.
@item --recursion
@item --recursion
@itemx --no-recursion
@xref{recurse}.
@item --anchored
@itemx --no-anchored
@item --anchored
@itemx --no-anchored
@xref{anchored patterns}.
@item --ignore-case
@itemx --no-ignore-case
@item --ignore-case
@itemx --no-ignore-case
@xref{case-insensitive matches}.
@item --wildcards
@itemx --no-wildcards
@xref{controlling pattern-matching}.
@item --wildcards-match-slash
@itemx --no-wildcards-match-slash
@item --wildcards-match-slash
@itemx --no-wildcards-match-slash
@xref{controlling pattern-matching}.
@item --exclude
@@ -3951,7 +3976,7 @@ successfully. For example, @w{@samp{tar --version}} might print:
@smallexample
tar (GNU tar) @value{VERSION}
Copyright (C) 2013-2016 Free Software Foundation, Inc.
Copyright (C) 2013-2020 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.
@@ -4432,6 +4457,25 @@ checkpoint:
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=sleep=30}
@end smallexample
@anchor{checkpoint wait}
@cindex @code{wait}, checkpoint action
The @code{wait=@var{signo}} action stops further execution until the
signal @var{signo} is delivered. Valid values for @var{signo} are:
@code{SIGHUP}, @code{SIGQUIT}, @code{SIGINT}, @code{SIGUSR1} and
@code{SIGUSR2}. The @samp{SIG} prefix is optional. For example:
@example
$ @kbd{tar -c -f arc --checkpoint=1000 --checkpoint-action wait=USR1 .}
@end example
In this example, @GNUTAR{} will stop archivation at each 1000th
checkpoint. wait until the @samp{SIGUSR1} signal is delivered,
and resume processing.
This action is used by the @command{genfile} utility to perform
modifications on the input files upon hitting certain checkpoints
(@pxref{Exec Mode, genfile}).
@anchor{checkpoint exec}
@cindex @code{exec}, checkpoint action
Finally, the @code{exec} action executes a given external command.
@@ -4593,6 +4637,10 @@ Disable all warning messages.
@cindex @samp{file changed as we read it}, warning message
@item file-changed
@samp{%s: file changed as we read it}
@item failed-read
Suppresses warnings about unreadable files or directories. This
keyword applies only if used together with the @option{--ignore-failed-read}
option. @xref{Ignore Failed Read}.
@end table
@subheading Keywords applicable for @command{tar --extract}
@@ -4756,7 +4804,6 @@ expanded by the shell when invoking @command{tar}.
* create options::
* extract options::
* backup::
* Applications::
* looking ahead::
@end menu
@@ -5174,7 +5221,7 @@ the one at the end will be newer and larger, since you added text before
updating it.
The reason @command{tar} does not overwrite the older file when updating
it is because writing to the middle of a section of tape is a difficult
it is that writing to the middle of a section of tape is a difficult
process. Tapes are not designed to go backward. @xref{Media}, for more
information about tapes.
@@ -5457,7 +5504,7 @@ reproducible archives given a common timestamp for generated files
while still retaining the original timestamps of untouched files.
@smallexample
$ @kbd{tar -c -f archive.tar --clamp-mtime --mtime=@atchar{}$SOURCE_DATE_EPOCH .}
$ @kbd{tar -c -f archive.tar --clamp-mtime --mtime=@@$SOURCE_DATE_EPOCH .}
@end smallexample
@item --owner=@var{user}
@@ -5576,7 +5623,7 @@ map file.
@subsection Extended File Attributes
Extended file attributes are name-value pairs that can be
associated with each node in a file system. Despite the fact that
associated with each node in a file system. Despite the fact that
POSIX.1e draft which proposed them has been withdrawn, the extended
file attributes are supported by many file systems. @GNUTAR{} can
store extended file attributes along with the files. This feature is
@@ -5612,11 +5659,11 @@ Specify exclude pattern for extended attributes.
Specify include pattern for extended attributes.
@end table
Here, the @var{pattern} is POSIX regular expression. For example, the
Here, the @var{pattern} is a globbing pattern. For example, the
following command:
@example
$ @kbd{tar --xattrs --xattrs-exclude='^user\.' -c a.tar .}
$ @kbd{tar --xattrs --xattrs-exclude='user.*' -c a.tar .}
@end example
will include in the archive @file{a.tar} all attributes, except those
@@ -5625,11 +5672,11 @@ from the @samp{user} namespace.
Any number of these options can be given, thereby creating lists of
include and exclude patterns.
When both options are used, first @option{--xattrs-inlcude} is applied
When both options are used, first @option{--xattrs-include} is applied
to select the set of attribute names to keep, and then
@option{--xattrs-exclude} is applied to the resulting set. In other
words, only those attributes will be stored, whose names match one
of the regexps in @option{--xattrs-inlcude} and don't match any of
of the regexps in @option{--xattrs-include} and don't match any of
the regexps from @option{--xattrs-exclude}.
When listing the archive, if both @option{--xattrs} and
@@ -5678,7 +5725,7 @@ Disable POSIX ACLs support. This is the default.
When listing the archive, if both @option{--acls} and
@option{--verbose} options are given, files that have ACLs are marked
with a plus sing following their permission mask. For example:
with a plus sign following their permission mask. For example:
@example
-rw-r--r--+ smith/users 110 2016-03-16 16:07 file
@@ -5691,7 +5738,7 @@ listing of ACL is printed after each file entry:
@group
-rw-r--r--+ smith/users 110 2016-03-16 16:07 file
a: user::rw-,user:gray:-w-,group::r--,mask::rw-,other::r--
@end group
@end group
@end example
@dfn{Security-Enhanced Linux} (@dfn{SELinux} for short) is a Linux
@@ -5709,7 +5756,7 @@ Disable SELinux context support.
@end table
@node Ignore Failed Read
@subsection Ignore Fail Read
@subsection Ignore Failed Read
@table @option
@item --ignore-failed-read
@@ -5717,6 +5764,13 @@ Disable SELinux context support.
Do not exit with nonzero on unreadable files or directories.
@end table
This option has effect only during creation. It instructs tar to
treat as mild conditions any missing or unreadable files (directories).
Such failures don't affect the program exit code, and the
corresponding diagnostic messages are marked as warnings, not errors.
These warnings can be suppressed using the
@option{--warning=failed-read} option (@pxref{warnings}).
@node extract options
@section Options Used by @option{--extract}
@cindex options for use with @option{--extract}
@@ -6473,65 +6527,6 @@ set, the default is @samp{~}, just as in Emacs.
@end table
@node Applications
@section Notable @command{tar} Usages
@UNREVISED
@FIXME{Using Unix file linking capability to recreate directory
structures---linking files into one subdirectory and then
@command{tar}ring that directory.}
@FIXME{Nice hairy example using absolute-names, newer, etc.}
@findex uuencode
You can easily use archive files to transport a group of files from
one system to another: put all relevant files into an archive on one
computer system, transfer the archive to another system, and extract
the contents there. The basic transfer medium might be magnetic tape,
Internet FTP, or even electronic mail (though you must encode the
archive with @command{uuencode} in order to transport it properly by
mail). Both machines do not have to use the same operating system, as
long as they both support the @command{tar} program.
For example, here is how you might copy a directory's contents from
one disk to another, while preserving the dates, modes, owners and
link-structure of all the files therein. In this case, the transfer
medium is a @dfn{pipe}:
@smallexample
$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xf -)}
@end smallexample
@noindent
You can avoid subshells by using @option{-C} option:
@smallexample
$ @kbd{tar -C sourcedir -cf - . | tar -C targetdir -xf -}
@end smallexample
@noindent
The command also works using long option forms:
@smallexample
@group
$ @kbd{(cd sourcedir; tar --create --file=- . ) \
| (cd targetdir; tar --extract --file=-)}
@end group
@end smallexample
@noindent
or
@smallexample
@group
$ @kbd{tar --directory sourcedir --create --file=- . \
| tar --directory targetdir --extract --file=-}
@end group
@end smallexample
@noindent
This is one of the easiest methods to transfer a @command{tar} archive.
@node looking ahead
@section Looking Ahead: The Rest of this Manual
@@ -7735,9 +7730,12 @@ any leading and trailing whitespace. If the resulting string begins
with @samp{-} character, it is considered a @command{tar} option and is
processed accordingly@footnote{Versions of @GNUTAR{} up to 1.15.1
recognized only @option{-C} option in file lists, and only if the
option and its argument occupied two consecutive lines.}. For example,
the common use of this feature is to change to another directory by
specifying @option{-C} option:
option and its argument occupied two consecutive lines.}. Only a
subset of @GNUTAR{} options is allowed for use in file lists. For
a list of such options, @ref{Position-Sensitive Options}.
For example, the common use of this feature is to change to another
directory by specifying @option{-C} option:
@smallexample
@group
@@ -8474,9 +8472,7 @@ quoting}. The characters in question are:
The exact way @command{tar} uses to quote these characters depends on
the @dfn{quoting style}. The default quoting style, called
@dfn{escape} (see below), uses backslash notation to represent control
characters, space and backslash. Using this quoting style, control
characters are represented as listed in column @samp{Character} in the
above table, a space is printed as @samp{\ } and a backslash as @samp{\\}.
characters and backslash.
@GNUTAR{} offers seven distinct quoting styles, which can be selected
using @option{--quoting-style} option:
@@ -8607,10 +8603,9 @@ $ @kbd{tar tf arch.tar --quoting-style=c}
@end smallexample
@item escape
Control characters are printed using backslash notation, a space is
printed as @samp{\ } and a backslash as @samp{\\}. This is the
default quoting style, unless it was changed when configured the
package.
Control characters are printed using backslash notation, and a
backslash as @samp{\\}. This is the default quoting style, unless it
was changed when configured the package.
@smallexample
@group
@@ -8964,7 +8959,7 @@ is used, which excludes symbolic link targets from filename
transformations. The result is:
@smallexample
$ @kbd{tar --transform 's,^,/usr/local/,S', -c -v -f arch.tar \
$ @kbd{tar --transform 's,^,/usr/local/,S' -c -v -f arch.tar \
--show-transformed /lib}
drwxr-xr-x root/root 0 2008-07-08 16:20 /usr/local/lib/
-rwxr-xr-x root/root 1250840 2008-05-25 07:44 /usr/local/lib/libc-2.3.2.so
@@ -9157,7 +9152,7 @@ create a list of files to be stored in an archive, use it as follows:
@smallexample
@group
$ @kbd{find @var{dir} @var{tests} | \
tar -cf @var{archive} -T - --no-recursion}
tar -cf @var{archive} --no-recursion -T -}
@end group
@end smallexample
@@ -9555,24 +9550,32 @@ switch to @samp{posix}.
@cindex lzma
@cindex lzop
@cindex compress
@cindex zstd
@GNUTAR{} is able to create and read compressed archives. It supports
a wide variety of compression programs, namely: @command{gzip},
@command{bzip2}, @command{lzip}, @command{lzma}, @command{lzop},
@command{xz} and traditional @command{compress}. The latter is
supported mostly for backward compatibility, and we recommend
@command{zstd}, @command{xz} and traditional @command{compress}. The
latter is supported mostly for backward compatibility, and we recommend
against using it, because it is by far less effective than the other
compression programs@footnote{It also had patent problems in the past.}.
Creating a compressed archive is simple: you just specify a
@dfn{compression option} along with the usual archive creation
commands. The compression option is @option{-z} (@option{--gzip}) to
create a @command{gzip} compressed archive, @option{-j}
(@option{--bzip2}) to create a @command{bzip2} compressed archive,
@option{--lzip} to create an @asis{lzip} compressed archive,
@option{-J} (@option{--xz}) to create an @asis{XZ} archive,
@option{--lzma} to create an @asis{LZMA} compressed
archive, @option{--lzop} to create an @asis{LSOP} archive, and
@option{-Z} (@option{--compress}) to use @command{compress} program.
commands. Available compression options are summarized in the
table below:
@multitable @columnfractions 0.4 0.2 0.4
@headitem Long @tab Short @tab Archive format
@item @option{--gzip} @tab @option{-z} @tab @command{gzip}
@item @option{--bzip2} @tab @option{-j} @tab @command{bzip2}
@item @option{--xz} @tab @option{-J} @tab @command{xz}
@item @option{--lzip} @tab @tab @command{lzip}
@item @option{--lzma} @tab @tab @command{lzma}
@item @option{--lzop} @tab @tab @command{lzop}
@item @option{--zstd} @tab @tab @command{zstd}
@item @option{--compress} @tab @option{-Z} @tab @command{compress}
@end multitable
For example:
@smallexample
@@ -9693,6 +9696,10 @@ Filter the archive through @command{lzma}.
@item --lzop
Filter the archive through @command{lzop}.
@opindex zstd
@item --zstd
Filter the archive through @command{zstd}.
@opindex compress
@opindex uncompress
@item -Z
@@ -9765,6 +9772,8 @@ suffix. The following suffixes are recognized:
@item @samp{.tlz} @tab @command{lzma}
@item @samp{.lzo} @tab @command{lzop}
@item @samp{.xz} @tab @command{xz}
@item @samp{.zst} @tab @command{zstd}
@item @samp{.tzst} @tab @command{zstd}
@end multitable
@anchor{use-compress-program}
@@ -10451,9 +10460,16 @@ If no option @samp{exthdr.name=string} is specified, @command{tar}
will use the following default value:
@smallexample
%d/PaxHeaders.%p/%f
%d/PaxHeaders/%f
@end smallexample
This default is selected to ensure the reproducibility of the
archive. @acronym{POSIX} standard recommends to use
@samp{%d/PaxHeaders.%p/%f} instead, which means the two archives
created with the same set of options and containing the same set
of files will be byte-to-byte different. This default will be used
if the environment variable @env{POSIXLY_CORRECT} is set.
@item exthdr.mtime=@var{value}
This keyword defines the value of the @samp{mtime} field that
@@ -10482,12 +10498,18 @@ Any other @samp{%} characters in @var{string} produce undefined results.
If no option @samp{globexthdr.name=string} is specified, @command{tar}
will use the following default value:
@smallexample
$TMPDIR/GlobalHead.%n
@end smallexample
If the environment variable @env{POSIXLY_CORRECT} is set, the
following value is used instead:
@smallexample
$TMPDIR/GlobalHead.%p.%n
@end smallexample
@noindent
where @samp{$TMPDIR} represents the value of the @var{TMPDIR}
In both cases, @samp{$TMPDIR} stands for the value of the @var{TMPDIR}
environment variable. If @var{TMPDIR} is not set, @command{tar}
uses @samp{/tmp}.
@@ -10550,7 +10572,7 @@ archives created using it, will be binary equivalent if they have the
same contents:
@smallexample
--pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0
--pax-option=atime:=0
@end smallexample
@noindent
@@ -10559,14 +10581,27 @@ from them, you will also need to eliminate changes due to ctime, as
shown in examples below:
@smallexample
--pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0
--pax-option=atime:=0,ctime:=0
@end smallexample
@noindent
or
@smallexample
--pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,delete=ctime
--pax-option=atime:=0,delete=ctime
@end smallexample
Notice, that if you create an archive in POSIX format (@pxref{posix})
and the environment variable @env{POSIXLY_CORRECT} is set, then the
two archives created using the same options on the same set of files
will not be byte-to-byte equivalent even with the above option. This
is because the posix default for extended header names includes the
PID of the tar process, which is different at each run. To produce
byte-to-byte equivalent archives in this case, either unset
@env{POSIXLY_CORRECT}, or use the following option:
@smallexample
---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0
@end smallexample
@node Checksumming
@@ -10692,7 +10727,7 @@ GNU extensions. More specifically, the very first part retains its
original name, and all subsequent parts are named using the pattern:
@smallexample
%d/GNUFileParts.%p/%f.%n
%d/GNUFileParts/%f.%n
@end smallexample
@noindent
@@ -10711,13 +10746,12 @@ created the archive.
@end multitable
For example, if the file @file{var/longfile} was split during archive
creation between three volumes, and the creator @command{tar} process
had process @acronym{ID} @samp{27962}, then the member names will be:
creation between three volumes, then the member names will be:
@smallexample
var/longfile
var/GNUFileParts.27962/longfile.1
var/GNUFileParts.27962/longfile.2
var/GNUFileParts/longfile.1
var/GNUFileParts/longfile.2
@end smallexample
When you extract your archive using a third-party @command{tar}, these
@@ -10728,9 +10762,9 @@ the proper order, for example:
@smallexample
@group
$ @kbd{cd var}
$ @kbd{cat GNUFileParts.27962/longfile.1 \
GNUFileParts.27962/longfile.2 >> longfile}
$ rm -f GNUFileParts.27962
$ @kbd{cat GNUFileParts/longfile.1 \
GNUFileParts/longfile.2 >> longfile}
$ rm -f GNUFileParts
@end group
@end smallexample
@@ -10756,12 +10790,12 @@ more warnings and more files generated on your disk, e.g.:
@smallexample
@group
$ @kbd{tar xf vol-1.tar}
var/PaxHeaders.27962/longfile: Unknown file type 'x', extracted as
var/PaxHeaders/longfile: Unknown file type 'x', extracted as
normal file
Unexpected EOF in archive
$ @kbd{tar xf vol-2.tar}
tmp/GlobalHead.27962.1: Unknown file type 'g', extracted as normal file
GNUFileParts.27962/PaxHeaders.27962/sparsefile.1: Unknown file type
tmp/GlobalHead.1: Unknown file type 'g', extracted as normal file
GNUFileParts/PaxHeaders/sparsefile.1: Unknown file type
'x', extracted as normal file
@end group
@end smallexample
@@ -10877,8 +10911,8 @@ use. Continuing our example:
@smallexample
@group
$ @kbd{xsparse -v -x /home/gray/PaxHeaders.6058/sparsefile \
/home/gray/GNUSparseFile.6058/sparsefile}
$ @kbd{xsparse -v -x /home/gray/PaxHeaders/sparsefile \
/home/gray/GNUSparseFile/sparsefile}
Reading extended header file
Found variable GNU.sparse.major = 1
Found variable GNU.sparse.minor = 0
@@ -10891,7 +10925,7 @@ Done
@end group
@end smallexample
@anchor{extracting sparse v.0.x}
@anchor{extracting sparse v0x}
@cindex sparse files v.0.1, extracting with non-GNU tars
@cindex sparse files v.0.0, extracting with non-GNU tars
An @dfn{extended header} is a special @command{tar} archive header
@@ -10908,8 +10942,7 @@ If you use a @command{tar} implementation that does not support PAX
format, extended headers for each member will be extracted as a
separate file. If we represent the member name as
@file{@var{dir}/@var{name}}, then the extended header file will be
named @file{@var{dir}/@/PaxHeaders.@var{n}/@/@var{name}}, where
@var{n} is an integer number.
named @file{@var{dir}/@/PaxHeaders/@/@var{name}}.
Things become more difficult if your @command{tar} implementation
does support PAX headers, because in this case you will have to
@@ -12907,8 +12940,8 @@ understand their security implications.
@appendix Changes
This appendix lists some important user-visible changes between
version @GNUTAR{} @value{VERSION} and previous versions. An up-to-date
version of this document is available at
various versions of @GNUTAR{}. An up-to-date version of this document
is available at
@uref{http://www.gnu.org/@/software/@/tar/manual/changes.html,the
@GNUTAR{} documentation page}.
@@ -12994,6 +13027,10 @@ These options are deprecated. Please use @option{--format=v7} instead.
This option is deprecated. Please use @option{--format=posix} instead.
@end table
@node Recipes
@appendix Recipes
@include recipes.texi
@node Configuring Help Summary
@appendix Configuring Help Summary
@@ -13219,10 +13256,6 @@ Right margin of the text output. Used for wrapping.
@appendix Genfile
@include genfile.texi
@node Free Software Needs Free Documentation
@appendix Free Software Needs Free Documentation
@include freemanuals.texi
@node GNU Free Documentation License
@appendix GNU Free Documentation License

View File

@@ -1,4 +1,4 @@
# Copyright 2006-2007, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,6 +1,5 @@
@c This is part of GNU tar manual.
@c Copyright 1992, 1994-1997, 1999-2006, 2013-2014, 2016 Free Software
@c Foundation, Inc.
@c Copyright 1992--2021 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@macro GNUTAR

2
gnulib

Submodule gnulib updated: 1029a81122...30820c2d7c

View File

@@ -1,7 +1,7 @@
# List of gnulib modules needed for GNU tar.
# A module name per line. Empty lines and comments are ignored.
# Copyright 2005-2010, 2012-2014 Free Software Foundation, Inc.
# Copyright 2005-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -83,8 +83,10 @@ stat-time
stdbool
stdint
stpcpy
stdopen
strdup-posix
strerror
strnlen
strtoimax
strtol
strtoul

View File

@@ -1,7 +1,6 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright 1994-1997, 1999-2001, 2003-2007, 2009-2010, 2013-2014, 2016
# Free Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -33,7 +32,6 @@ AM_CFLAGS = $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)
noinst_HEADERS = \
paxlib.h\
rmt.h\
stdopen.h\
system.h\
system-ioctl.h\
wordsplit.h\
@@ -43,7 +41,6 @@ libtar_a_SOURCES = \
paxerror.c paxexit-status.c paxlib.h paxnames.c \
rtapelib.c \
rmt.h \
stdopen.c stdopen.h \
system.h system-ioctl.h \
wordsplit.c\
xattr-at.c

View File

@@ -1,5 +1,5 @@
/* Replacement <attr/xattr.h> for platforms that lack it.
Copyright 2012-2014, 2016 Free Software Foundation, Inc.
Copyright 2012-2021 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

View File

@@ -1,76 +0,0 @@
/* stdopen.c - ensure that the three standard file descriptors are in use
Copyright 2005, 2007, 2013-2014, 2016 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Paul Eggert and Jim Meyering. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "stdopen.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
/* Try to ensure that all of the standard file numbers (0, 1, 2)
are in use. Without this, each application would have to guard
every call to open, dup, fopen, etc. with tests to ensure they
don't use one of the special file numbers when opening a file.
Return false if at least one of the file descriptors is initially
closed and an attempt to reopen it fails. Otherwise, return true. */
bool
stdopen (void)
{
int fd;
bool ok = true;
for (fd = 0; fd <= 2; fd++)
{
if (fcntl (fd, F_GETFD) < 0)
{
if (errno != EBADF)
ok = false;
else
{
static const int contrary_mode[]
= { O_WRONLY, O_RDONLY, O_RDONLY };
int mode = contrary_mode[fd];
int new_fd;
/* Open /dev/null with the contrary mode so that the typical
read (stdin) or write (stdout, stderr) operation will fail.
With descriptor 0, we can do even better on systems that
have /dev/full, by opening that write-only instead of
/dev/null. The only drawback is that a write-provoked
failure comes with a misleading errno value, ENOSPC. */
if (mode == O_RDONLY
|| (new_fd = open ("/dev/full", mode) != fd))
new_fd = open ("/dev/null", mode);
if (new_fd != fd)
{
if (0 <= new_fd)
close (new_fd);
ok = false;
}
}
}
}
return ok;
}

View File

@@ -1,16 +0,0 @@
#ifndef STDOPEN_H
# define STDOPEN_H 1
# include <stdbool.h>
# ifdef __cplusplus
extern "C" {
# endif
bool stdopen (void);
# ifdef __cplusplus
}
# endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* wordsplit - a word splitter
Copyright (C) 2009-2014, 2016 Free Software Foundation, Inc.
Copyright (C) 2009-2018 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
@@ -12,10 +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, see <http://www.gnu.org/licenses/>.
Written by Sergey Poznyakoff
*/
with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef __WORDSPLIT_H
#define __WORDSPLIT_H
@@ -28,42 +25,106 @@
# define __WORDSPLIT_ATTRIBUTE_FORMAT(spec) /* empty */
#endif
struct wordsplit
typedef struct wordsplit wordsplit_t;
/* Structure used to direct the splitting. Members marked with [Input]
can be defined before calling wordsplit(), those marked with [Output]
provide return values when the function returns. If neither mark is
used, the member is internal and must not be used by the caller.
In the comments below, the identifiers in parentheses indicate bits that
must be set (or unset, if starting with !) in ws_flags (if starting with
WRDSF_) or ws_options (if starting with WRDSO_) to initialize or use the
given member.
If not redefined explicitly, most of them are set to some reasonable
default value upon entry to wordsplit(). */
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);
size_t ws_wordc; /* [Output] Number of words in ws_wordv. */
char **ws_wordv; /* [Output] Array of parsed out words. */
size_t ws_offs; /* [Input] (WRDSF_DOOFFS) Number of initial
elements in ws_wordv to fill with NULLs. */
size_t ws_wordn; /* Number of elements ws_wordv can accomodate. */
unsigned ws_flags; /* [Input] Flags passed to wordsplit. */
unsigned ws_options; /* [Input] (WRDSF_OPTIONS)
Additional options. */
size_t ws_maxwords; /* [Input] (WRDSO_MAXWORDS) Return at most that
many words */
size_t ws_wordi; /* [Output] (WRDSF_INCREMENTAL) Total number of
words returned so far */
const char *ws_delim; /* [Input] (WRDSF_DELIM) Word delimiters. */
const char *ws_comment; /* [Input] (WRDSF_COMMENT) Comment characters. */
const char *ws_escape[2]; /* [Input] (WRDSF_ESCAPE) Characters to be escaped
with backslash. */
void (*ws_alloc_die) (wordsplit_t *wsp);
/* [Input] (WRDSF_ALLOC_DIE) Function called when
out of memory. Must not return. */
void (*ws_error) (const char *, ...)
__WORDSPLIT_ATTRIBUTE_FORMAT ((__printf__, 1, 2));
__attribute__ ((__format__ (__printf__, 1, 2)));
/* [Input] (WRDSF_ERROR) Function used for error
reporting */
void (*ws_debug) (const char *, ...)
__WORDSPLIT_ATTRIBUTE_FORMAT ((__printf__, 1, 2));
__attribute__ ((__format__ (__printf__, 1, 2)));
/* [Input] (WRDSF_DEBUG) Function used for debug
output. */
const char **ws_env; /* [Input] (WRDSF_ENV, !WRDSF_NOVAR) Array of
environment variables. */
const char **ws_env;
const char *(*ws_getvar) (const char *, size_t, void *);
void *ws_closure;
char **ws_envbuf;
size_t ws_envidx;
size_t ws_envsiz;
int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos);
/* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up
the name VAR (LEN bytes long) in the table of
variables and if found returns in memory
location pointed to by RET the value of that
variable. Returns WRDSE_OK (0) on success,
and an error code (see WRDSE_* defines below)
on error. User-specific errors can be returned
by storing the error diagnostic string in RET
and returning WRDSE_USERERR.
Whatever is stored in RET, it must be allocated
using malloc(3). */
void *ws_closure; /* [Input] (WRDSF_CLOSURE) Passed as the CLOS
argument to ws_getvar and ws_command. */
int (*ws_command) (char **ret, const char *cmd, size_t len, char **argv,
void *clos);
/* [Input] (!WRDSF_NOCMD) Returns in the memory
location pointed to by RET the expansion of
the command CMD (LEN bytes long). If WRDSO_ARGV
option is set, ARGV contains CMD split out to
words. Otherwise ARGV is NULL.
const char *ws_input;
size_t ws_len;
size_t ws_endp;
int ws_errno;
See ws_getvar for a discussion of possible
return values. */
const char *ws_input; /* Input string (the S argument to wordsplit. */
size_t ws_len; /* Length of ws_input. */
size_t ws_endp; /* Points past the last processed byte in
ws_input. */
int ws_errno; /* [Output] Error code, if an error occurred. */
char *ws_usererr; /* Points to textual description of
the error, if ws_errno is WRDSE_USERERR. Must
be allocated with malloc(3). */
struct wordsplit_node *ws_head, *ws_tail;
/* Doubly-linked list of parsed out nodes. */
int ws_lvl; /* Invocation nesting level. */
};
/* Wordsplit flags. Only 2 bits of a 32-bit word remain unused.
It is getting crowded... */
/* Initial size for ws_env, if allocated automatically */
#define WORDSPLIT_ENV_INIT 16
/* Wordsplit flags. */
/* 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.
/* Insert ws_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. */
/* Don't do command substitution. */
#define WRDSF_NOCMD 0x00000004
/* The parameter p resulted from a previous call to
wordsplit(), and wordsplit_free() was not called. Reuse the
@@ -71,10 +132,8 @@ struct wordsplit
#define WRDSF_REUSE 0x00000008
/* Print errors */
#define WRDSF_SHOWERR 0x00000010
/* Consider it an error if an undefined shell variable
is expanded. */
/* Consider it an error if an undefined variable is expanded. */
#define WRDSF_UNDEF 0x00000020
/* Don't do variable expansion. */
#define WRDSF_NOVAR 0x00000040
/* Abort on ENOMEM error */
@@ -85,7 +144,7 @@ struct wordsplit
#define WRDSF_SQUOTE 0x00000200
/* Handle double quotes */
#define WRDSF_DQUOTE 0x00000400
/* Handle quotes and escape directives */
/* Handle single and double quotes */
#define WRDSF_QUOTE (WRDSF_SQUOTE|WRDSF_DQUOTE)
/* Replace each input sequence of repeated delimiters with a single
delimiter */
@@ -113,56 +172,106 @@ struct wordsplit
/* 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 */
empty strings. */
#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
/* Perform pathname and tilde expansion */
#define WRDSF_PATHEXPAND 0x40000000
/* ws_options is initialized */
#define WRDSF_OPTIONS 0x80000000
#define WRDSF_DEFFLAGS \
(WRDSF_NOVAR | WRDSF_NOCMD | \
WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_CESCAPES)
#define WRDSE_EOF 0
/* Remove the word that produces empty string after path expansion */
#define WRDSO_NULLGLOB 0x00000001
/* Print error message if path expansion produces empty string */
#define WRDSO_FAILGLOB 0x00000002
/* Allow a leading period to be matched by metacharacters. */
#define WRDSO_DOTGLOB 0x00000004
/* ws_command needs argv parameter */
#define WRDSO_ARGV 0x00000008
/* Keep backslash in unrecognized escape sequences in words */
#define WRDSO_BSKEEP_WORD 0x00000010
/* Handle octal escapes in words */
#define WRDSO_OESC_WORD 0x00000020
/* Handle hex escapes in words */
#define WRDSO_XESC_WORD 0x00000040
/* ws_maxwords field is initialized */
#define WRDSO_MAXWORDS 0x00000080
/* Keep backslash in unrecognized escape sequences in quoted strings */
#define WRDSO_BSKEEP_QUOTE 0x00000100
/* Handle octal escapes in quoted strings */
#define WRDSO_OESC_QUOTE 0x00000200
/* Handle hex escapes in quoted strings */
#define WRDSO_XESC_QUOTE 0x00000400
#define WRDSO_BSKEEP WRDSO_BSKEEP_WORD
#define WRDSO_OESC WRDSO_OESC_WORD
#define WRDSO_XESC WRDSO_XESC_WORD
/* Indices into ws_escape */
#define WRDSX_WORD 0
#define WRDSX_QUOTE 1
/* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */
#define WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q)))
/* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */
#define WRDSO_ESC_TEST(ws,q,f) ((ws)->ws_options & ((f) << 4*(q)))
#define WRDSE_OK 0
#define WRDSE_EOF WRDSE_OK
#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
#define WRDSE_USAGE 3
#define WRDSE_CBRACE 4
#define WRDSE_UNDEF 5
#define WRDSE_NOINPUT 6
#define WRDSE_PAREN 7
#define WRDSE_GLOBERR 8
#define WRDSE_USERERR 9
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 (const char *s, wordsplit_t *ws, unsigned flags);
int wordsplit_len (const char *s, size_t len, wordsplit_t *ws, unsigned flags);
void wordsplit_free (wordsplit_t *ws);
void wordsplit_free_words (wordsplit_t *ws);
void wordsplit_free_envbuf (wordsplit_t *ws);
int wordsplit_get_words (wordsplit_t *ws, size_t *wordc, char ***wordv);
static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
__attribute__ ((deprecated));
static inline void
wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
{
wordsplit_get_words (ws, wordc, wordv);
}
int wordsplit_append (wordsplit_t *wsp, int argc, char **argv);
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);
size_t wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote);
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);
void wordsplit_perror (wordsplit_t *ws);
const char *wordsplit_strerror (wordsplit_t *ws);
void wordsplit_clearerr (wordsplit_t *ws);
#endif

View File

@@ -1,7 +1,7 @@
/* openat-style fd-relative functions for operating with extended file
attributes.
Copyright 2012-2014, 2016 Free Software Foundation, Inc.
Copyright 2012-2021 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

View File

@@ -1,7 +1,7 @@
/* Prototypes for openat-style fd-relative functions for operating with
extended file attributes.
Copyright 2012-2014, 2016 Free Software Foundation, Inc.
Copyright 2012-2021 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

1
po/.gitignore vendored
View File

@@ -1,3 +1,4 @@
/Makefile.in.in
/Makevars.template~
/Makefile.in.in~
*.gmo

View File

@@ -1,7 +1,6 @@
# List of files which contain translatable strings.
# Copyright 1996, 1999-2000, 2003-2005, 2007, 2013-2014, 2016 Free
# Software Foundation, Inc.
# Copyright 1996-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,6 @@
# Make GNU tar scripts.
# Copyright 2004, 2006-2007, 2013-2014, 2016 Free Software Foundation,
# Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -82,7 +82,7 @@ SLEEP_MESSAGE="`awk '
}' /dev/null`"
# Copyright 2004, 2007, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
#! /bin/sh
# Make backups.
# Copyright 2004-2006, 2013 Free Software Foundation
# Copyright 2004-2006, 2013, 2019 Free Software Foundation
# This file is part of GNU tar.
@@ -149,13 +149,16 @@ message 20 "Variables:"
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
# The bunch of commands below is run in a subshell for which all output is
# 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.
(
message 1 "preparing tapes"
$MT_BEGIN "${TAPE_FILE}"
if ! $MT_BEGIN "${TAPE_FILE}"; then
echo >&2 "$0: tape initialization failed"
exit 1
fi
rm -f "${VOLNO_FILE}"
message 1 "processing backup directories"
@@ -191,7 +194,7 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
# '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
echo "$0: backup of ${1} failed." 1>&2
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
@@ -238,17 +241,17 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
else
echo "No miscellaneous files specified"
fi
message 1 "final cleanup"
$MT_REWIND "${TAPE_FILE}"
$MT_OFFLINE "${TAPE_FILE}"
echo "."
) 2>&1 | tee -a "${LOGFILE}"
RC=$?
if test "${ADMINISTRATOR}" != NONE; then
echo "Sending the dump log to ${ADMINISTRATOR}"
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
fi
exit $RC
# EOF

View File

@@ -1,7 +1,7 @@
#! /bin/sh
# Make backups.
# Copyright 2004-2006, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -311,7 +311,9 @@ backup_host() {
CMD="exec ${TAR_PART1} -f \"${TAPE_FILE}\" $@"
message 10 "CMD: $CMD"
sh -c "$CMD"
message 10 "RC: $?"
RC=$?
message 10 "RC: $RC"
return $RC
fi
}

View File

@@ -8,8 +8,7 @@
# interested parties that a tape for the next volume of the backup needs to
# be put in the tape drive.
# Copyright 2004-2005, 2010, 2012-2014, 2016 Free Software Foundation,
# Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
#! /bin/sh
# Restore backups.
# Copyright 2004, 2006, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
#! /usr/bin/perl -w
# Display and edit the 'dev' field in tar's snapshots
# Copyright 2007, 2011, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2007-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -408,7 +408,7 @@ sub check_field_values ($) {
}
if ( $msg ne "" ) {
$error_found = 1;
print "\n shapshot file header:\n";
print "\n snapshot file header:\n";
print $msg;
}

View File

@@ -3,8 +3,7 @@
# concatenates a GNU tar multi-volume archive into a single tar archive.
# Author: Bruno Haible <bruno@clisp.org>, Sergey Poznyakoff <gray@gnu.org.ua>
# Copyright 2004-2005, 2010, 2013-2014, 2016 Free Software Foundation,
# Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,8 +1,7 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright 2006-2007, 2010, 2013-2014, 2016 Free Software Foundation,
Inc.
Copyright 2006-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,7 +1,6 @@
# Makefile for GNU tar sources.
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2009, 2013-2014, 2016
# Free Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,5 +1,5 @@
/* Long integers, for GNU tar.
Copyright 1999, 2007, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 1999-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,7 +1,6 @@
/* Buffer management for tar.
Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2013-2014, 2016 Free
Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -105,13 +104,20 @@ bool write_archive_to_stdout;
/* When creating a multi-volume archive, each 'bufmap' represents
a member stored (perhaps partly) in the current record buffer.
Bufmaps are form a single-linked list in chronological order.
After flushing the record to the output media, all bufmaps that
represent fully written members are removed from the list, then
the sizeleft and start numbers in the remaining bufmaps are updated.
represent fully written members are removed from the list, the
nblocks and sizeleft values in the bufmap_head and start values
in all remaining bufmaps are updated. The information stored
in bufmap_head is used to form the volume header.
When reading from a multi-volume archive, the list degrades to a
single element, which keeps information about the member currently
being read.
being read. In that case the sizeleft member is updated explicitly
from the extractor code by calling the mv_size_left function. The
information from bufmap_head is compared with the volume header data
to ensure that subsequent volumes are fed in the right order.
*/
struct bufmap
@@ -121,6 +127,7 @@ struct bufmap
char *file_name; /* Name of the stored file */
off_t sizetotal; /* Size of the stored file */
off_t sizeleft; /* Size left to read/write */
size_t nblocks; /* Number of blocks written since reset */
};
static struct bufmap *bufmap_head, *bufmap_tail;
@@ -145,6 +152,7 @@ mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft)
bp->file_name = xstrdup (file_name);
bp->sizetotal = totsize;
bp->sizeleft = sizeleft;
bp->nblocks = 0;
}
}
@@ -155,8 +163,7 @@ bufmap_locate (size_t off)
for (map = bufmap_head; map; map = map->next)
{
if (!map->next
|| off < map->next->start * BLOCKSIZE)
if (!map->next || off < map->next->start * BLOCKSIZE)
break;
}
return map;
@@ -185,7 +192,10 @@ bufmap_reset (struct bufmap *map, ssize_t fixup)
if (map)
{
for (; map; map = map->next)
map->start += fixup;
{
map->start += fixup;
map->nblocks = 0;
}
}
}
@@ -270,7 +280,8 @@ enum compress_type {
ct_lzip,
ct_lzma,
ct_lzop,
ct_xz
ct_xz,
ct_zstd
};
static enum compress_type archive_compression_type = ct_none;
@@ -299,6 +310,7 @@ static struct zip_magic const magic[] = {
{ ct_lzma, 6, "\xFFLZMA" },
{ ct_lzop, 4, "\211LZO" },
{ ct_xz, 6, "\xFD" "7zXZ" },
{ ct_zstd, 4, "\x28\xB5\x2F\xFD" },
};
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
@@ -314,6 +326,7 @@ static struct zip_program zip_program[] = {
{ ct_lzma, XZ_PROGRAM, "-J" },
{ ct_lzop, LZOP_PROGRAM, "--lzop" },
{ ct_xz, XZ_PROGRAM, "-J" },
{ ct_zstd, ZSTD_PROGRAM, "--zstd" },
{ ct_none }
};
@@ -391,10 +404,12 @@ check_compressed_archive (bool *pshort)
/* Restore global values */
read_full_records = sfr;
if ((strcmp (record_start->header.magic, TMAGIC) == 0 ||
strcmp (record_start->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC) == 0) &&
tar_checksum (record_start, true) == HEADER_SUCCESS)
if (record_start != record_end /* no files smaller than BLOCKSIZE */
&& (strcmp (record_start->header.magic, TMAGIC) == 0
|| strcmp (record_start->buffer + offsetof (struct posix_header,
magic),
OLDGNU_MAGIC) == 0)
&& tar_checksum (record_start, true) == HEADER_SUCCESS)
/* Probably a valid header */
return ct_tar;
@@ -868,12 +883,19 @@ _flush_write (void)
if (map)
{
size_t delta = status - map->start * BLOCKSIZE;
ssize_t diff;
map->nblocks += delta / BLOCKSIZE;
if (delta > map->sizeleft)
delta = map->sizeleft;
map->sizeleft -= delta;
if (map->sizeleft == 0)
map = map->next;
bufmap_reset (map, map ? (- map->start) : 0);
{
diff = map->start + map->nblocks;
map = map->next;
}
else
diff = map->start;
bufmap_reset (map, - diff);
}
}
return status;
@@ -984,7 +1006,7 @@ void
flush_archive (void)
{
size_t buffer_level;
if (access_mode == ACCESS_READ && time_to_start_writing)
{
access_mode = ACCESS_WRITE;
@@ -1105,9 +1127,9 @@ close_archive (void)
{
if (time_to_start_writing || access_mode == ACCESS_WRITE)
{
flush_archive ();
if (current_block > record_start)
flush_archive ();
do
flush_archive ();
while (current_block > record_start);
}
compute_duration ();
@@ -1276,8 +1298,7 @@ change_tape_menu (FILE *read_file)
sys_spawn_shell ();
break;
}
/* FALL THROUGH */
FALLTHROUGH;
default:
fprintf (stderr, _("Invalid input. Type ? for help.\n"));
}
@@ -1481,18 +1502,17 @@ try_new_volume (void)
if (!read_header0 (&dummy))
return false;
tar_stat_destroy (&dummy);
assign_string (&volume_label, current_header->header.name);
ASSIGN_STRING_N (&volume_label, current_header->header.name);
set_next_block_after (header);
header = find_next_block ();
if (header->header.typeflag != GNUTYPE_MULTIVOL)
break;
/* FALL THROUGH */
FALLTHROUGH;
case GNUTYPE_MULTIVOL:
if (!read_header0 (&dummy))
return false;
tar_stat_destroy (&dummy);
assign_string (&continued_file_name, current_header->header.name);
ASSIGN_STRING_N (&continued_file_name, current_header->header.name);
continued_file_size =
UINTMAX_FROM_HEADER (current_header->header.size);
continued_file_offset =
@@ -1512,7 +1532,7 @@ try_new_volume (void)
quote (bufmap_head->file_name)));
return false;
}
if (strcmp (continued_file_name, bufmap_head->file_name))
{
if ((archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
@@ -1635,15 +1655,7 @@ match_volume_label (void)
quote (volume_label_option)));
if (label->header.typeflag == GNUTYPE_VOLHDR)
{
if (memchr (label->header.name, '\0', sizeof label->header.name))
assign_string (&volume_label, label->header.name);
else
{
volume_label = xmalloc (sizeof (label->header.name) + 1);
memcpy (volume_label, label->header.name,
sizeof (label->header.name));
volume_label[sizeof (label->header.name)] = 0;
}
ASSIGN_STRING_N (&volume_label, label->header.name);
}
else if (label->header.typeflag == XGLTYPE)
{
@@ -1679,8 +1691,7 @@ _write_volume_label (const char *str)
memset (label, 0, BLOCKSIZE);
strcpy (label->header.name, str);
assign_string (&current_stat_info.file_name,
label->header.name);
assign_string (&current_stat_info.file_name, label->header.name);
current_stat_info.had_trailing_slash =
strip_trailing_slashes (current_stat_info.file_name);
@@ -1711,7 +1722,6 @@ add_chunk_header (struct bufmap *map)
{
if (archive_format == POSIX_FORMAT)
{
off_t block_ordinal;
union block *blk;
struct tar_stat_info st;
@@ -1721,16 +1731,15 @@ add_chunk_header (struct bufmap *map)
st.stat.st_uid = getuid ();
st.stat.st_gid = getgid ();
st.orig_file_name = xheader_format_name (&st,
"%d/GNUFileParts.%p/%f.%n",
"%d/GNUFileParts/%f.%n",
volno);
st.file_name = st.orig_file_name;
st.archive_file_size = st.stat.st_size = map->sizeleft;
block_ordinal = current_block_ordinal ();
blk = start_header (&st);
if (!blk)
abort (); /* FIXME */
finish_header (&st, blk, block_ordinal);
simple_finish_header (write_extended (false, &st, blk));
free (st.orig_file_name);
}
}
@@ -1752,15 +1761,19 @@ gnu_add_multi_volume_header (struct bufmap *map)
{
int tmp;
union block *block = find_next_block ();
size_t len = strlen (map->file_name);
if (strlen (map->file_name) > NAME_FIELD_SIZE)
WARN ((0, 0,
_("%s: file name too long to be stored in a GNU multivolume header, truncated"),
quotearg_colon (map->file_name)));
if (len > NAME_FIELD_SIZE)
{
WARN ((0, 0,
_("%s: file name too long to be stored in a GNU multivolume header, truncated"),
quotearg_colon (map->file_name)));
len = NAME_FIELD_SIZE;
}
memset (block, 0, BLOCKSIZE);
strncpy (block->header.name, map->file_name, NAME_FIELD_SIZE);
memcpy (block->header.name, map->file_name, len);
block->header.typeflag = GNUTYPE_MULTIVOL;
OFF_TO_CHARS (map->sizeleft, block->header.size);

View File

@@ -1,6 +1,6 @@
/* Checkpoint management for tar.
Copyright 2007, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -23,6 +23,7 @@
#include <sys/ioctl.h>
#include <termios.h>
#include "fprintftime.h"
#include <signal.h>
enum checkpoint_opcode
{
@@ -32,7 +33,8 @@ enum checkpoint_opcode
cop_ttyout,
cop_sleep,
cop_exec,
cop_totals
cop_totals,
cop_wait
};
struct checkpoint_action
@@ -43,6 +45,7 @@ struct checkpoint_action
{
time_t time;
char *command;
int signal;
} v;
};
@@ -52,6 +55,16 @@ static unsigned checkpoint;
/* List of checkpoint actions */
static struct checkpoint_action *checkpoint_action, *checkpoint_action_tail;
/* State of the checkpoint system */
enum {
CHKP_INIT, /* Needs initialization */
CHKP_COMPILE, /* Actions are being compiled */
CHKP_RUN /* Actions are being run */
};
static int checkpoint_state;
/* Blocked signals */
static sigset_t sigs;
static struct checkpoint_action *
alloc_action (enum checkpoint_opcode opcode)
{
@@ -85,6 +98,12 @@ checkpoint_compile_action (const char *str)
{
struct checkpoint_action *act;
if (checkpoint_state == CHKP_INIT)
{
sigemptyset (&sigs);
checkpoint_state = CHKP_COMPILE;
}
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
alloc_action (cop_dot);
else if (strcmp (str, "bell") == 0)
@@ -117,6 +136,12 @@ checkpoint_compile_action (const char *str)
}
else if (strcmp (str, "totals") == 0)
alloc_action (cop_totals);
else if (strncmp (str, "wait=", 5) == 0)
{
act = alloc_action (cop_wait);
act->v.signal = decode_signal (str + 5);
sigaddset (&sigs, act->v.signal);
}
else
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
}
@@ -124,15 +149,24 @@ checkpoint_compile_action (const char *str)
void
checkpoint_finish_compile (void)
{
if (checkpoint_option)
if (checkpoint_state == CHKP_INIT
&& checkpoint_option
&& !checkpoint_action)
{
if (!checkpoint_action)
/* Provide a historical default */
checkpoint_compile_action ("echo");
/* Provide a historical default */
checkpoint_compile_action ("echo");
}
if (checkpoint_state == CHKP_COMPILE)
{
sigprocmask (SIG_BLOCK, &sigs, NULL);
if (!checkpoint_option)
/* set default checkpoint rate */
checkpoint_option = DEFAULT_CHECKPOINT;
checkpoint_state = CHKP_RUN;
}
else if (checkpoint_action)
/* Otherwise, set default checkpoint rate */
checkpoint_option = DEFAULT_CHECKPOINT;
}
static const char *checkpoint_total_format[] = {
@@ -390,6 +424,13 @@ run_checkpoint_actions (bool do_write)
case cop_totals:
compute_duration ();
print_total_stats ();
break;
case cop_wait:
{
int n;
sigwait (&sigs, &n);
}
}
}
}

View File

@@ -1,7 +1,6 @@
/* Common declarations for the tar program.
Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2012-2016 Free
Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -44,6 +43,12 @@
# define GLOBAL extern
#endif
#if 7 <= __GNUC__
# define FALLTHROUGH __attribute__ ((__fallthrough__))
#else
# define FALLTHROUGH ((void) 0)
#endif
#define TAREXIT_SUCCESS PAXEXIT_SUCCESS
#define TAREXIT_DIFFERS PAXEXIT_DIFFERS
#define TAREXIT_FAILURE PAXEXIT_FAILURE
@@ -296,6 +301,10 @@ enum hole_detection_method
GLOBAL enum hole_detection_method hole_detection;
/* The first entry in names.c:namelist specifies the member name to
start extracting from. Set by add_starting_file() upon seeing the
-K option.
*/
GLOBAL bool starting_file_option;
/* Specified maximum byte length of each tape volume (multiple of 1024). */
@@ -331,6 +340,9 @@ GLOBAL const char *volume_label_option;
/* Other global variables. */
/* Force POSIX-compliance */
GLOBAL bool posixly_correct;
/* File descriptor for archive file. */
GLOBAL int archive;
@@ -414,9 +426,6 @@ GLOBAL bool show_transformed_names_option;
timestamps from archives with an unusual member order. It is automatically
set for incremental archives. */
GLOBAL bool delay_directory_restore_option;
/* When set, tar will not refuse to create empty archives */
GLOBAL bool files_from_option;
/* Declarations for each module. */
@@ -622,7 +631,11 @@ void skip_member (void);
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) < (b) ? (b) : (a))
char const *quote_n_colon (int n, char const *arg);
void assign_string (char **dest, const char *src);
void assign_string_n (char **string, const char *value, size_t n);
#define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v))
int unquote_string (char *str);
char *zap_slashes (char *name);
char *normalize_filename (int cdidx, const char *name);
@@ -729,7 +742,21 @@ int set_file_atime (int fd, int parentfd, char const *file,
/* Module names.c. */
extern size_t name_count;
enum files_count
{
FILES_NONE,
FILES_ONE,
FILES_MANY
};
extern enum files_count filename_args;
/* Return true if there are file names in the list */
static inline bool
name_more_files (void)
{
return filename_args != FILES_NONE;
}
extern struct name *gnu_list_name;
void gid_to_gname (gid_t gid, char **gname);
@@ -738,12 +765,14 @@ void uid_to_uname (uid_t uid, char **uname);
int uname_to_uid (char const *uname, uid_t *puid);
void name_init (void);
bool name_more_files (void);
void name_add_name (const char *name);
void name_term (void);
const char *name_next (int change_dirs);
void name_gather (void);
struct name *addname (char const *string, int change_dir,
bool cmdline, struct name *parent);
void add_starting_file (char const *file_name);
void remname (struct name *name);
bool name_match (const char *name);
void names_notfound (void);
@@ -785,6 +814,8 @@ void set_exit_status (int val);
void request_stdin (const char *option);
int decode_signal (const char *);
/* Where an option comes from: */
enum option_source
{
@@ -803,6 +834,24 @@ struct option_locus
class */
};
struct tar_args /* Variables used during option parsing */
{
struct option_locus *loc;
struct textual_date *textual_date; /* Keeps the arguments to --newer-mtime
and/or --date option if they are
textual dates */
bool o_option; /* True if -o option was given */
bool pax_option; /* True if --pax-option was given */
bool compress_autodetect; /* True if compression autodetection should
be attempted when creating archives */
char const *backup_suffix_string; /* --suffix option argument */
char const *version_control_string; /* --backup option argument */
};
#define TAR_ARGS_INITIALIZER(loc) \
{ loc, NULL, false, false, false, NULL, NULL }
void more_options (int argc, char **argv, struct option_locus *loc);
/* Module update.c. */
@@ -823,6 +872,7 @@ void xheader_store (char const *keyword, struct tar_stat_info *st,
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_forbid_global (void);
void xheader_finish (struct xheader *hdr);
void xheader_destroy (struct xheader *hdr);
char *xheader_xhdr_name (struct tar_stat_info *st);
@@ -927,6 +977,7 @@ void checkpoint_flush_actions (void);
#define WARN_EXISTING_FILE 0x00100000
#define WARN_XATTR_WRITE 0x00200000
#define WARN_RECORD_SIZE 0x00400000
#define WARN_FAILED_READ 0x00800000
/* These warnings are enabled by default in verbose mode: */
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
@@ -938,10 +989,12 @@ void set_warning_option (const char *arg);
extern int warning_option;
#define WARNING_ENABLED(opt) (warning_option & (opt))
#define WARNOPT(opt,args) \
do \
{ \
if (warning_option & opt) WARN (args); \
if (WARNING_ENABLED(opt)) WARN (args); \
} \
while (0)

View File

@@ -1,7 +1,6 @@
/* Diff files from a tar archive.
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2007,
2009-2010, 2012-2014, 2016 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -51,6 +50,8 @@ diff_init (void)
read_directory_file ();
}
enum { QUOTE_ARG, QUOTE_NAME };
/* Sigh about something that differs by writing a MESSAGE to stdlis,
given MESSAGE is nonzero. Also set the exit status if not already. */
void
@@ -60,7 +61,7 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
{
va_list ap;
fprintf (stdlis, "%s: ", quotearg_colon (st->file_name));
fprintf (stdlis, "%s: ", quote_n_colon (QUOTE_NAME, st->file_name));
va_start (ap, fmt);
vfprintf (stdlis, fmt, ap);
va_end (ap);
@@ -263,7 +264,8 @@ diff_link (void)
&& !sys_compare_links (&file_data, &link_data))
report_difference (&current_stat_info,
_("Not linked to %s"),
quote (current_stat_info.link_name));
quote_n_colon (QUOTE_ARG,
current_stat_info.link_name));
}
#ifdef HAVE_READLINK
@@ -477,8 +479,7 @@ diff_archive (void)
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. */
FALLTHROUGH;
case AREGTYPE:
case REGTYPE:
case GNUTYPE_SPARSE:

View File

@@ -1,7 +1,6 @@
/* Create a tar archive.
Copyright 1985, 1992-1994, 1996-1997, 1999-2001, 2003-2007,
2009-2010, 2012-2014, 2016 Free Software Foundation, Inc.
Copyright 1985-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -202,8 +201,8 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
#define MODE_TO_CHARS(val, where) mode_to_chars (val, where, sizeof (where))
#define UID_TO_CHARS(val, where) uid_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))
#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))
static bool
to_chars (int negative, uintmax_t value, size_t valsize,
@@ -518,8 +517,8 @@ start_private_header (const char *name, size_t size, time_t t)
MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
UID_TO_CHARS (0, header->header.uid);
GID_TO_CHARS (0, header->header.gid);
strncpy (header->header.magic, TMAGIC, TMAGLEN);
strncpy (header->header.version, TVERSION, TVERSLEN);
memcpy (header->header.magic, TMAGIC, TMAGLEN);
memcpy (header->header.version, TVERSION, TVERSLEN);
return header;
}
@@ -542,15 +541,19 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
size_t size = strlen (p) + 1;
size_t bufsize;
union block *header;
char *tmpname;
header = start_private_header ("././@LongLink", size, 0);
uid_to_uname (0, &tmpname);
UNAME_TO_CHARS (tmpname, header->header.uname);
free (tmpname);
gid_to_gname (0, &tmpname);
GNAME_TO_CHARS (tmpname, header->header.gname);
free (tmpname);
if (! numeric_owner_option)
{
static char *uname, *gname;
if (!uname)
{
uid_to_uname (0, &uname);
gid_to_gname (0, &gname);
}
UNAME_TO_CHARS (uname, header->header.uname);
GNAME_TO_CHARS (gname, header->header.gname);
}
strcpy (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC);
@@ -743,7 +746,7 @@ start_header (struct tar_stat_info *st)
union block *header;
char const *uname = NULL;
char const *gname = NULL;
header = write_header_name (st);
if (!header)
return NULL;
@@ -830,11 +833,11 @@ start_header (struct tar_stat_info *st)
case USE_FILE_MTIME:
mtime = st->mtime;
break;
case FORCE_MTIME:
mtime = mtime_option;
break;
case CLAMP_MTIME:
mtime = timespec_cmp (st->mtime, mtime_option) > 0
? mtime_option : st->mtime;
@@ -913,8 +916,8 @@ start_header (struct tar_stat_info *st)
case POSIX_FORMAT:
case USTAR_FORMAT:
strncpy (header->header.magic, TMAGIC, TMAGLEN);
strncpy (header->header.version, TVERSION, TVERSLEN);
memcpy (header->header.magic, TMAGIC, TMAGLEN);
memcpy (header->header.version, TVERSION, TVERSLEN);
break;
default:
@@ -1345,15 +1348,15 @@ create_archive (void)
{
struct name const *p;
trivial_link_count = name_count <= 1 && ! dereference_option;
trivial_link_count = filename_args != FILES_MANY && ! dereference_option;
open_archive (ACCESS_WRITE);
buffer_write_global_xheader ();
if (incremental_option)
{
size_t buffer_size = 1000;
char *buffer = xmalloc (buffer_size);
size_t buffer_size = 0;
char *buffer = NULL;
const char *q;
collect_and_sort_names ();
@@ -1368,12 +1371,8 @@ create_archive (void)
{
struct tar_stat_info st;
size_t plen = strlen (p->name);
if (buffer_size <= plen)
{
while ((buffer_size *= 2) <= plen)
continue;
buffer = xrealloc (buffer, buffer_size);
}
while (buffer_size <= plen)
buffer = x2realloc (buffer, &buffer_size);
memcpy (buffer, p->name, plen);
if (! ISSLASH (buffer[plen - 1]))
buffer[plen++] = DIRECTORY_SEPARATOR;
@@ -1391,23 +1390,21 @@ create_archive (void)
open_searchdir_flags);
if (fd < 0)
{
open_diag (p->name);
file_removed_diag (p->name, !p->parent,
open_diag);
break;
}
st.fd = fd;
if (fstat (fd, &st.stat) != 0)
{
stat_diag (p->name);
file_removed_diag (p->name, !p->parent,
stat_diag);
break;
}
st.orig_file_name = xstrdup (p->name);
}
if (buffer_size < plen + qlen)
{
while ((buffer_size *=2 ) < plen + qlen)
continue;
buffer = xrealloc (buffer, buffer_size);
}
while (buffer_size < plen + qlen)
buffer = x2realloc (buffer, &buffer_size);
strcpy (buffer + plen, q + 1);
dump_file (&st, q + 1, buffer);
}
@@ -1528,7 +1525,8 @@ file_count_links (struct tar_stat_info *st)
char *linkname = NULL;
struct link *lp;
assign_string (&linkname, st->orig_file_name);
assign_string (&linkname, safer_name_suffix (st->orig_file_name, true,
absolute_names_option));
transform_name (&linkname, XFORM_LINK);
lp = xmalloc (offsetof (struct link, name)

View File

@@ -1,7 +1,6 @@
/* Delete entries from a tar archive.
Copyright 1988, 1992, 1994, 1996-1997, 2000-2001, 2003-2006, 2010,
2013-2014, 2016 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -148,6 +147,23 @@ write_recent_bytes (char *data, size_t bytes)
write_record (1);
}
static inline void
flush_file (void)
{
off_t blocks_to_skip;
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);
flush_archive ();
}
current_block += blocks_to_skip;
}
void
delete_archive_members (void)
{
@@ -156,7 +172,6 @@ delete_archive_members (void)
/* FIXME: Should clean the routine before cleaning these variables :-( */
struct name *name;
off_t blocks_to_skip = 0;
off_t blocks_to_keep = 0;
int kept_blocks_in_record;
@@ -164,11 +179,12 @@ delete_archive_members (void)
open_archive (ACCESS_UPDATE);
acting_as_filter = strcmp (archive_name_array[0], "-") == 0;
/* Skip to the first member that matches the name list. */
do
{
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_x_raw);
&current_stat_info,
read_header_x_raw);
switch (status)
{
@@ -182,13 +198,12 @@ delete_archive_members (void)
break;
}
name->found_count++;
if (!ISFOUND(name))
if (!ISFOUND (name))
{
skip_member ();
break;
}
/* Fall through. */
FALLTHROUGH;
case HEADER_SUCCESS_EXTENDED:
logical_status = status;
break;
@@ -199,7 +214,7 @@ delete_archive_members (void)
set_next_block_after (current_header);
break;
}
/* Fall through. */
FALLTHROUGH;
case HEADER_END_OF_FILE:
logical_status = HEADER_END_OF_FILE;
break;
@@ -210,14 +225,12 @@ delete_archive_members (void)
{
case HEADER_STILL_UNREAD:
WARN ((0, 0, _("This does not look like a tar archive")));
/* Fall through. */
FALLTHROUGH;
case HEADER_SUCCESS:
case HEADER_SUCCESS_EXTENDED:
case HEADER_ZERO_BLOCK:
ERROR ((0, 0, _("Skipping to next header")));
/* Fall through. */
FALLTHROUGH;
case HEADER_FAILURE:
break;
@@ -247,15 +260,12 @@ delete_archive_members (void)
if (logical_status == HEADER_SUCCESS)
{
/* FIXME: Pheew! This is crufty code! */
logical_status = HEADER_STILL_UNREAD;
goto flush_file;
flush_file ();
}
/* FIXME: Solaris 2.4 Sun cc (the ANSI one, not the old K&R) says:
"delete.c", line 223: warning: loop not entered at top
Reported by Bruno Haible. */
while (1)
/* Skip matching members and move the rest up the archive. */
while (logical_status != HEADER_END_OF_FILE)
{
enum read_header status;
@@ -263,105 +273,108 @@ delete_archive_members (void)
if (current_block == record_end)
flush_archive ();
status = read_header (&current_header, &current_stat_info,
read_header_auto);
read_header_auto);
xheader_decode (&current_stat_info);
if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
switch (status)
{
set_next_block_after (current_header);
continue;
}
if (status == HEADER_END_OF_FILE || status == HEADER_ZERO_BLOCK)
{
logical_status = HEADER_END_OF_FILE;
break;
}
case HEADER_STILL_UNREAD:
case HEADER_SUCCESS_EXTENDED:
abort ();
if (status == HEADER_FAILURE)
{
ERROR ((0, 0, _("Deleting non-header from archive")));
set_next_block_after (current_header);
continue;
}
case HEADER_SUCCESS:
/* Found another header. */
xheader_decode (&current_stat_info);
/* Found another header. */
if ((name = name_scan (current_stat_info.file_name)) != NULL)
{
name->found_count++;
if (ISFOUND(name))
if ((name = name_scan (current_stat_info.file_name)) != NULL)
{
flush_file:
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)
name->found_count++;
if (ISFOUND (name))
{
blocks_to_skip -= (record_end - current_block);
flush_archive ();
flush_file ();
break;
}
current_block += blocks_to_skip;
blocks_to_skip = 0;
continue;
}
}
/* Copy header. */
/* Copy header. */
if (current_stat_info.xhdr.size)
{
write_recent_bytes (current_stat_info.xhdr.buffer,
current_stat_info.xhdr.size);
}
else
{
write_recent_blocks (recent_long_name, recent_long_name_blocks);
write_recent_blocks (recent_long_link, recent_long_link_blocks);
}
new_record[new_blocks] = *current_header;
new_blocks++;
blocks_to_keep
= (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
set_next_block_after (current_header);
if (new_blocks == blocking_factor)
write_record (1);
/* Copy data. */
kept_blocks_in_record = record_end - current_block;
if (kept_blocks_in_record > blocks_to_keep)
kept_blocks_in_record = blocks_to_keep;
while (blocks_to_keep)
{
int count;
if (current_block == record_end)
if (current_stat_info.xhdr.size)
{
flush_read ();
current_block = record_start;
kept_blocks_in_record = blocking_factor;
if (kept_blocks_in_record > blocks_to_keep)
kept_blocks_in_record = blocks_to_keep;
write_recent_bytes (current_stat_info.xhdr.buffer,
current_stat_info.xhdr.size);
}
count = kept_blocks_in_record;
if (blocking_factor - new_blocks < count)
count = blocking_factor - new_blocks;
if (! count)
abort ();
memcpy (new_record + new_blocks, current_block, count * BLOCKSIZE);
new_blocks += count;
current_block += count;
blocks_to_keep -= count;
kept_blocks_in_record -= count;
else
{
write_recent_blocks (recent_long_name,
recent_long_name_blocks);
write_recent_blocks (recent_long_link,
recent_long_link_blocks);
}
new_record[new_blocks] = *current_header;
new_blocks++;
blocks_to_keep
= (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
set_next_block_after (current_header);
if (new_blocks == blocking_factor)
write_record (1);
/* Copy data. */
kept_blocks_in_record = record_end - current_block;
if (kept_blocks_in_record > blocks_to_keep)
kept_blocks_in_record = blocks_to_keep;
while (blocks_to_keep)
{
int count;
if (current_block == record_end)
{
flush_read ();
current_block = record_start;
kept_blocks_in_record = blocking_factor;
if (kept_blocks_in_record > blocks_to_keep)
kept_blocks_in_record = blocks_to_keep;
}
count = kept_blocks_in_record;
if (blocking_factor - new_blocks < count)
count = blocking_factor - new_blocks;
if (! count)
abort ();
memcpy (new_record + new_blocks, current_block,
count * BLOCKSIZE);
new_blocks += count;
current_block += count;
blocks_to_keep -= count;
kept_blocks_in_record -= count;
if (new_blocks == blocking_factor)
write_record (1);
}
break;
case HEADER_ZERO_BLOCK:
if (ignore_zeros_option)
set_next_block_after (current_header);
else
logical_status = HEADER_END_OF_FILE;
break;
case HEADER_END_OF_FILE:
logical_status = HEADER_END_OF_FILE;
break;
case HEADER_FAILURE:
ERROR ((0, 0, _("Deleting non-header from archive")));
set_next_block_after (current_header);
break;
default:
abort ();
}
tar_stat_destroy (&current_stat_info);
}
if (logical_status == HEADER_END_OF_FILE)

View File

@@ -1,6 +1,6 @@
/* Per-directory exclusion files for tar.
Copyright 2014, 2016 Free Software Foundation, Inc.
Copyright 2014-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -104,7 +104,8 @@ info_attach_exclist (struct tar_stat_info *dir)
vcsfile->data = vcsfile->initfn (vcsfile->data);
if (add_exclude_fp (vcsfile->addfn, ex, fp,
EXCLUDE_WILDCARDS|EXCLUDE_ANCHORED, '\n',
FNM_FILE_NAME|EXCLUDE_WILDCARDS|EXCLUDE_ANCHORED,
'\n',
vcsfile->data))
{
int e = errno;

View File

@@ -1,6 +1,6 @@
/* Exit from GNU tar.
Copyright 2009, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,7 +1,6 @@
/* Extract files from a tar archive.
Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014,
2016 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -195,7 +194,7 @@ extr_init (void)
/* Use fchmod if possible, fchmodat otherwise. */
static int
fd_chmod (int fd, char const *file, mode_t mode, int atflag)
fd_i_chmod (int fd, char const *file, mode_t mode, int atflag)
{
if (0 <= fd)
{
@@ -206,6 +205,42 @@ fd_chmod (int fd, char const *file, mode_t mode, int atflag)
return fchmodat (chdir_fd, file, mode, atflag);
}
/* A version of fd_i_chmod which gracefully handles several common error
conditions. Additional argument TYPEFLAG is the type of file in tar
notation.
*/
static int
fd_chmod(int fd, char const *file_name, int mode, int atflag, int typeflag)
{
int chmod_errno = fd_i_chmod (fd, file_name, mode, atflag) == 0 ? 0 : errno;
/* On Solaris, chmod may fail if we don't have PRIV_ALL, because
setuid-root files would otherwise be a backdoor. See
http://opensolaris.org/jive/thread.jspa?threadID=95826
(2009-09-03). */
if (chmod_errno == EPERM && (mode & S_ISUID)
&& priv_set_restore_linkdir () == 0)
{
chmod_errno = fd_i_chmod (fd, file_name, mode, atflag) == 0 ? 0 : errno;
priv_set_remove_linkdir ();
}
/* Linux fchmodat does not support AT_SYMLINK_NOFOLLOW, and
returns ENOTSUP even when operating on non-symlinks, try
again with the flag disabled if it does not appear to be
supported and if the file is not a symlink. This
introduces a race, alas. */
if (atflag && typeflag != SYMTYPE && ! implemented (chmod_errno))
chmod_errno = fd_i_chmod (fd, file_name, mode, 0) == 0 ? 0 : errno;
if (chmod_errno && (typeflag != SYMTYPE || implemented (chmod_errno)))
{
errno = chmod_errno;
return -1;
}
return 0;
}
/* Use fchown if possible, fchownat otherwise. */
static int
fd_chown (int fd, char const *file, uid_t uid, gid_t gid, int atflag)
@@ -260,35 +295,8 @@ set_mode (char const *file_name,
if (current_mode != mode)
{
int chmod_errno =
fd_chmod (fd, file_name, mode, atflag) == 0 ? 0 : errno;
/* On Solaris, chmod may fail if we don't have PRIV_ALL, because
setuid-root files would otherwise be a backdoor. See
http://opensolaris.org/jive/thread.jspa?threadID=95826
(2009-09-03). */
if (chmod_errno == EPERM && (mode & S_ISUID)
&& priv_set_restore_linkdir () == 0)
{
chmod_errno =
fd_chmod (fd, file_name, mode, atflag) == 0 ? 0 : errno;
priv_set_remove_linkdir ();
}
/* Linux fchmodat does not support AT_SYMLINK_NOFOLLOW, and
returns ENOTSUP even when operating on non-symlinks, try
again with the flag disabled if it does not appear to be
supported and if the file is not a symlink. This
introduces a race, alas. */
if (atflag && typeflag != SYMTYPE && ! implemented (chmod_errno))
chmod_errno = fd_chmod (fd, file_name, mode, 0) == 0 ? 0 : errno;
if (chmod_errno
&& (typeflag != SYMTYPE || implemented (chmod_errno)))
{
errno = chmod_errno;
chmod_error_details (file_name, mode);
}
if (fd_chmod (fd, file_name, mode, atflag, typeflag))
chmod_error_details (file_name, mode);
}
}
}
@@ -393,6 +401,24 @@ set_stat (char const *file_name,
xattrs_selinux_set (st, file_name, typeflag);
}
/* Find the direct ancestor of FILE_NAME in the delayed_set_stat list.
*/
static struct delayed_set_stat *
find_direct_ancestor (char const *file_name)
{
struct delayed_set_stat *h = delayed_set_stat_head;
while (h)
{
if (! h->after_links
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
&& ISSLASH (file_name[h->file_name_len])
&& (last_component (file_name) == file_name + h->file_name_len + 1))
break;
h = h->next;
}
return h;
}
/* For each entry H in the leading prefix of entries in HEAD that do
not have after_links marked, mark H and fill in its dev and ino
members. Assume HEAD && ! HEAD->after_links. */
@@ -441,25 +467,56 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
mode_t mode, int atflag)
{
size_t file_name_len = strlen (file_name);
struct delayed_set_stat *data = xmalloc (sizeof (*data));
data->next = delayed_set_stat_head;
struct delayed_set_stat *data;
for (data = delayed_set_stat_head; data; data = data->next)
if (strcmp (data->file_name, file_name) == 0)
break;
if (data)
{
if (data->interdir)
{
struct stat real_st;
if (fstatat (chdir_fd, data->file_name,
&real_st, data->atflag) != 0)
{
stat_error (data->file_name);
}
else
{
data->dev = real_st.st_dev;
data->ino = real_st.st_ino;
}
}
}
else
{
data = xmalloc (sizeof (*data));
data->next = delayed_set_stat_head;
delayed_set_stat_head = data;
data->file_name_len = file_name_len;
data->file_name = xstrdup (file_name);
data->after_links = false;
if (st)
{
data->dev = st->stat.st_dev;
data->ino = st->stat.st_ino;
}
}
data->mode = mode;
if (st)
{
data->dev = st->stat.st_dev;
data->ino = st->stat.st_ino;
data->uid = st->stat.st_uid;
data->gid = st->stat.st_gid;
data->atime = st->atime;
data->mtime = st->mtime;
}
data->file_name_len = file_name_len;
data->file_name = xstrdup (file_name);
data->current_mode = current_mode;
data->current_mode_mask = current_mode_mask;
data->interdir = ! st;
data->atflag = atflag;
data->after_links = 0;
data->change_dir = chdir_current;
data->cntx_name = NULL;
if (st)
@@ -491,8 +548,6 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->xattr_map = NULL;
data->xattr_map_size = 0;
}
strcpy (data->file_name, file_name);
delayed_set_stat_head = data;
if (must_be_dot_or_slash (file_name))
mark_after_links (data);
}
@@ -506,7 +561,7 @@ repair_delayed_set_stat (char const *dir,
struct stat const *dir_stat_info)
{
struct delayed_set_stat *data;
for (data = delayed_set_stat_head; data; data = data->next)
for (data = delayed_set_stat_head; data; data = data->next)
{
struct stat st;
if (fstatat (chdir_fd, data->file_name, &st, data->atflag) != 0)
@@ -740,10 +795,9 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
break;
stp = &st;
}
/* The caller tried to open a symbolic link with O_NOFOLLOW.
Fall through, treating it as an already-existing file. */
FALLTHROUGH;
case EEXIST:
/* Remove an old file, if the options allow this. */
@@ -760,8 +814,7 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, stp, &current_stat_info))
break;
/* FALL THROUGH */
FALLTHROUGH;
case DEFAULT_OLD_FILES:
case NO_OVERWRITE_DIR_OLD_FILES:
case OVERWRITE_OLD_FILES:
@@ -772,6 +825,7 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
case UNLINK_FIRST_OLD_FILES:
break;
}
FALLTHROUGH;
case ENOENT:
/* Attempt creating missing intermediate directories. */
@@ -795,13 +849,13 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
in advance dramatically improves the following performance of reading and
writing a file). If not restoring permissions, invert the INVERT_PERMISSIONS
bits from the file's current permissions. TYPEFLAG specifies the type of the
file. FILE_CREATED indicates set_xattr has created the file */
file. Returns non-zero when error occurs (while un-available xattrs is not
an error, rather no-op). Non-zero FILE_CREATED indicates set_xattr has
created the file. */
static int
set_xattr (char const *file_name, struct tar_stat_info const *st,
mode_t invert_permissions, char typeflag, int *file_created)
{
int status = 0;
#ifdef HAVE_XATTRS
bool interdir_made = false;
@@ -809,17 +863,32 @@ set_xattr (char const *file_name, struct tar_stat_info const *st,
{
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
do
status = mknodat (chdir_fd, file_name, mode ^ invert_permissions, 0);
while (status && maybe_recoverable ((char *)file_name, false,
&interdir_made));
for (;;)
{
if (!mknodat (chdir_fd, file_name, mode ^ invert_permissions, 0))
{
/* Successfully created file */
xattrs_xattrs_set (st, file_name, typeflag, 0);
*file_created = 1;
return 0;
}
xattrs_xattrs_set (st, file_name, typeflag, 0);
*file_created = 1;
switch (maybe_recoverable ((char *)file_name, false, &interdir_made))
{
case RECOVER_OK:
continue;
case RECOVER_NO:
skip_member ();
open_error (file_name);
return 1;
case RECOVER_SKIP:
return 0;
}
}
}
#endif
return(status);
return 0;
}
/* Fix the statuses of all directories whose statuses need fixing, and
@@ -906,7 +975,7 @@ is_directory_link (const char *file_name)
struct stat st;
int e = errno;
int res;
res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
S_ISLNK (st.st_mode) &&
fstatat (chdir_fd, file_name, &st, 0) == 0 &&
@@ -915,6 +984,26 @@ is_directory_link (const char *file_name)
return res;
}
/* Given struct stat of a directory (or directory member) whose ownership
or permissions of will be restored later, return the temporary permissions
for that directory, sufficiently restrictive so that in the meantime
processes owned by other users do not inadvertently create files under this
directory that inherit the wrong owner, group, or permissions from the
directory.
If not root, though, make the directory writeable and searchable at first,
so that files can be created under it.
*/
static inline int
safe_dir_mode (struct stat const *st)
{
return ((st->st_mode
& (0 < same_owner_option || 0 < same_permissions_option
? S_IRWXU
: MODE_RWX))
| (we_are_root ? 0 : MODE_WXUSR));
}
/* Extractor functions for various member types */
static int
@@ -944,18 +1033,7 @@ extract_dir (char *file_name, int typeflag)
else if (typeflag == GNUTYPE_DUMPDIR)
skip_member ();
/* If ownership or permissions will be restored later, create the
directory with restrictive permissions at first, so that in the
meantime processes owned by other users do not inadvertently
create files under this directory that inherit the wrong owner,
group, or permissions from the directory. If not root, though,
make the directory writeable and searchable at first, so that
files can be created under it. */
mode = ((current_stat_info.stat.st_mode
& (0 < same_owner_option || 0 < same_permissions_option
? S_IRWXU
: MODE_RWX))
| (we_are_root ? 0 : MODE_WXUSR));
mode = safe_dir_mode (&current_stat_info.stat);
for (;;)
{
@@ -971,6 +1049,7 @@ extract_dir (char *file_name, int typeflag)
if (errno == EEXIST
&& (interdir_made
|| keep_directory_symlink_option
|| old_files_option == NO_OVERWRITE_DIR_OLD_FILES
|| old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES))
{
@@ -978,7 +1057,7 @@ extract_dir (char *file_name, int typeflag)
if (keep_directory_symlink_option && is_directory_link (file_name))
return 0;
if (deref_stat (file_name, &st) == 0)
{
current_mode = st.st_mode;
@@ -991,6 +1070,31 @@ extract_dir (char *file_name, int typeflag)
repair_delayed_set_stat (file_name, &st);
return 0;
}
else if (old_files_option == NO_OVERWRITE_DIR_OLD_FILES)
{
/* Temporarily change the directory mode to a safe
value, to be able to create files in it, should
the need be.
*/
mode = safe_dir_mode (&st);
status = fd_chmod(-1, file_name, mode,
AT_SYMLINK_NOFOLLOW, DIRTYPE);
if (status == 0)
{
/* Store the actual directory mode, to be restored
later.
*/
current_stat_info.stat = st;
current_mode = mode & ~ current_umask;
current_mode_mask = MODE_RWX;
atflag = AT_SYMLINK_NOFOLLOW;
break;
}
else
{
chmod_error_details (file_name, mode);
}
}
break;
}
}
@@ -1136,11 +1240,7 @@ extract_file (char *file_name, int typeflag)
int file_created = 0;
if (set_xattr (file_name, &current_stat_info, invert_permissions,
typeflag, &file_created))
{
skip_member ();
open_error (file_name);
return 1;
}
return 1;
while ((fd = open_output_file (file_name, typeflag, mode,
file_created, &current_mode,
@@ -1223,20 +1323,69 @@ extract_file (char *file_name, int typeflag)
return status;
}
/* Find a delayed_link structure corresponding to the source NAME.
Such a structure exists in the delayed link list only if the link
placeholder file has been created. Therefore, try to stat the NAME
first. If it doesn't exist, there is no matching entry in the list.
Otherwise, look for the entry in list which has the matching dev
and ino numbers.
This approach avoids scanning the singly-linked list in obvious cases
and does not rely on comparing file names, which may differ for
various reasons (e.g. relative vs. absolute file names).
*/
static struct delayed_link *
find_delayed_link_source (char const *name)
{
struct delayed_link *dl;
struct stat st;
if (!delayed_link_head)
return NULL;
if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW))
{
if (errno != ENOENT)
stat_error (name);
return NULL;
}
for (dl = delayed_link_head; dl; dl = dl->next)
{
if (dl->dev == st.st_dev && dl->ino == st.st_ino)
break;
}
return dl;
}
/* Create a placeholder file with name FILE_NAME, which will be
replaced after other extraction is done by a symbolic link if
IS_SYMLINK is true, and by a hard link otherwise. Set
*INTERDIR_MADE if an intermediate directory is made in the
process. */
process.
Install the created struct delayed_link after PREV, unless the
latter is NULL, in which case insert it at the head of the delayed
link list.
*/
static int
create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made,
struct delayed_link *prev)
{
int fd;
struct stat st;
while ((fd = openat (chdir_fd, file_name, O_WRONLY | O_CREAT | O_EXCL, 0)) < 0)
{
if (errno == EEXIST && find_delayed_link_source (file_name))
{
/* The placeholder file has already been created. This means
that the link being extracted is a duplicate of an already
processed one. Skip it.
*/
return 0;
}
switch (maybe_recoverable (file_name, false, interdir_made))
{
case RECOVER_OK:
@@ -1265,8 +1414,16 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
xmalloc (offsetof (struct delayed_link, target)
+ strlen (current_stat_info.link_name)
+ 1);
p->next = delayed_link_head;
delayed_link_head = p;
if (prev)
{
p->next = prev->next;
prev->next = p;
}
else
{
p->next = delayed_link_head;
delayed_link_head = p;
}
p->dev = st.st_dev;
p->ino = st.st_ino;
p->birthtime = get_stat_birthtime (&st);
@@ -1281,7 +1438,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
}
p->change_dir = chdir_current;
p->sources = xmalloc (offsetof (struct string_list, string)
+ strlen (file_name) + 1);
+ strlen (file_name) + 1);
p->sources->next = 0;
strcpy (p->sources->string, file_name);
p->cntx_name = NULL;
@@ -1290,14 +1447,11 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
p->acls_a_len = 0;
p->acls_d_ptr = NULL;
p->acls_d_len = 0;
xheader_xattr_copy (&current_stat_info, &p->xattr_map, &p->xattr_map_size);
xheader_xattr_copy (&current_stat_info, &p->xattr_map,
&p->xattr_map_size);
strcpy (p->target, current_stat_info.link_name);
h = delayed_set_stat_head;
if (h && ! h->after_links
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
&& ISSLASH (file_name[h->file_name_len])
&& (last_component (file_name) == file_name + h->file_name_len + 1))
if ((h = find_direct_ancestor (file_name)) != NULL)
mark_after_links (h);
return 0;
@@ -1312,12 +1466,16 @@ extract_link (char *file_name, int typeflag)
bool interdir_made = false;
char const *link_name;
int rc;
struct delayed_link *dl;
link_name = current_stat_info.link_name;
if (! absolute_names_option && contains_dot_dot (link_name))
return create_placeholder_file (file_name, false, &interdir_made);
return create_placeholder_file (file_name, false, &interdir_made, NULL);
dl = find_delayed_link_source (link_name);
if (dl)
return create_placeholder_file (file_name, false, &interdir_made, dl);
do
{
struct stat st1, st2;
@@ -1379,7 +1537,7 @@ extract_symlink (char *file_name, int typeflag)
if (! absolute_names_option
&& (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
|| contains_dot_dot (current_stat_info.link_name)))
return create_placeholder_file (file_name, true, &interdir_made);
return create_placeholder_file (file_name, true, &interdir_made, NULL);
while (symlinkat (current_stat_info.link_name, chdir_fd, file_name) != 0)
switch (maybe_recoverable (file_name, false, &interdir_made))
@@ -1472,47 +1630,23 @@ extract_fifo (char *file_name, int typeflag)
}
#endif
static int
extract_volhdr (char *file_name, int typeflag)
{
skip_member ();
return 0;
}
static int
extract_failure (char *file_name, int typeflag)
{
return 1;
}
static int
extract_skip (char *file_name, int typeflag)
{
skip_member ();
return 0;
}
typedef int (*tar_extractor_t) (char *file_name, int typeflag);
/* Prepare to extract a file. Find extractor function.
Return zero if extraction should not proceed. */
Return true to proceed with the extraction, false to skip the current
member. */
static int
static bool
prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
{
int rc = 1;
if (EXTRACT_OVER_PIPE)
rc = 0;
tar_extractor_t extractor = NULL;
/* Select the extractor */
switch (typeflag)
{
case GNUTYPE_SPARSE:
*fun = extract_file;
rc = 1;
extractor = extract_file;
break;
case AREGTYPE:
@@ -1521,106 +1655,106 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
/* Appears to be a file. But BSD tar uses the convention that a slash
suffix means a directory. */
if (current_stat_info.had_trailing_slash)
*fun = extract_dir;
extractor = extract_dir;
else
{
*fun = extract_file;
rc = 1;
}
extractor = extract_file;
break;
case SYMTYPE:
*fun = extract_symlink;
extractor = extract_symlink;
break;
case LNKTYPE:
*fun = extract_link;
extractor = extract_link;
break;
#if S_IFCHR
case CHRTYPE:
current_stat_info.stat.st_mode |= S_IFCHR;
*fun = extract_node;
extractor = extract_node;
break;
#endif
#if S_IFBLK
case BLKTYPE:
current_stat_info.stat.st_mode |= S_IFBLK;
*fun = extract_node;
extractor = extract_node;
break;
#endif
#if HAVE_MKFIFO || defined mkfifo
case FIFOTYPE:
*fun = extract_fifo;
extractor = extract_fifo;
break;
#endif
case DIRTYPE:
case GNUTYPE_DUMPDIR:
*fun = extract_dir;
extractor = extract_dir;
if (current_stat_info.is_dumpdir)
delay_directory_restore_option = true;
break;
case GNUTYPE_VOLHDR:
*fun = extract_volhdr;
break;
return false;
case GNUTYPE_MULTIVOL:
ERROR ((0, 0,
_("%s: Cannot extract -- file is continued from another volume"),
quotearg_colon (current_stat_info.file_name)));
*fun = extract_skip;
break;
return false;
case GNUTYPE_LONGNAME:
case GNUTYPE_LONGLINK:
ERROR ((0, 0, _("Unexpected long name header")));
*fun = extract_failure;
break;
return false;
default:
WARNOPT (WARN_UNKNOWN_CAST,
(0, 0,
_("%s: Unknown file type '%c', extracted as normal file"),
quotearg_colon (file_name), typeflag));
*fun = extract_file;
extractor = extract_file;
}
/* Determine whether the extraction should proceed */
if (rc == 0)
return 0;
switch (old_files_option)
if (EXTRACT_OVER_PIPE)
{
case UNLINK_FIRST_OLD_FILES:
if (!remove_any_file (file_name,
recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
: ORDINARY_REMOVE_OPTION)
&& errno && errno != ENOENT)
{
unlink_error (file_name);
return 0;
}
break;
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, 0, &current_stat_info))
{
WARNOPT (WARN_IGNORE_NEWER,
(0, 0, _("Current %s is newer or same age"),
quote (file_name)));
return 0;
}
break;
default:
break;
if (extractor != extract_file)
return false;
}
else
{
switch (old_files_option)
{
case UNLINK_FIRST_OLD_FILES:
if (!remove_any_file (file_name,
recursive_unlink_option
? RECURSIVE_REMOVE_OPTION
: ORDINARY_REMOVE_OPTION)
&& errno && errno != ENOENT)
{
unlink_error (file_name);
return false;
}
break;
return 1;
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, 0, &current_stat_info))
{
WARNOPT (WARN_IGNORE_NEWER,
(0, 0, _("Current %s is newer or same age"),
quote (file_name)));
return false;
}
break;
default:
break;
}
}
*fun = extractor;
return true;
}
/* Extract a file from the archive. */
@@ -1629,12 +1763,20 @@ extract_archive (void)
{
char typeflag;
tar_extractor_t fun;
bool skip_dotdot_name;
fatal_exit_hook = extract_finish;
set_next_block_after (current_header);
skip_dotdot_name = (!absolute_names_option
&& contains_dot_dot (current_stat_info.orig_file_name));
if (skip_dotdot_name)
ERROR ((0, 0, _("%s: Member name contains '..'"),
quotearg_colon (current_stat_info.orig_file_name)));
if (!current_stat_info.file_name[0]
|| skip_dotdot_name
|| (interactive_option
&& !confirm ("extract", current_stat_info.file_name)))
{
@@ -1675,13 +1817,14 @@ extract_archive (void)
if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun))
{
if (fun && (*fun) (current_stat_info.file_name, typeflag)
&& backup_option)
undo_last_backup ();
if (fun (current_stat_info.file_name, typeflag) == 0)
return;
}
else
skip_member ();
if (backup_option)
undo_last_backup ();
}
/* Extract the links whose final extraction were delayed. */
@@ -1754,8 +1897,8 @@ apply_delayed_links (void)
sources = next;
}
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
free (ds->cntx_name);
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
free (ds->cntx_name);
{
struct delayed_link *next = ds->next;

View File

@@ -1,7 +1,6 @@
/* GNU dump extensions to tar.
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2009,
2013-2014, 2016 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -39,7 +38,15 @@ enum children
#define DIRF_FOUND 0x0004 /* directory is found on fs */
#define DIRF_NEW 0x0008 /* directory is new (not found
in the previous dump) */
#define DIRF_RENAMED 0x0010 /* directory is renamed */
#define DIRF_RENAMED 0x0010 /* Last target in a chain of renames */
/* A directory which is renamed from another one is recognized by its
orig member, which is not-NULL. This directory may eventually be
the source for another rename, in which case it will be pointed to by
the orig member of another directory structure. The last directory
in such a chain of renames (the one which is not pointed to by any
other orig) is marked with the DIRF_RENAMED flag. This marks a starting
point from which append_incremental_renames starts encoding renames for
this chain. */
#define DIR_IS_INITED(d) ((d)->flags & DIRF_INIT)
#define DIR_IS_NFS(d) ((d)->flags & DIRF_NFS)
@@ -496,6 +503,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
quote_n (1, d->name)));
directory->orig = d;
DIR_SET_FLAG (directory, DIRF_RENAMED);
DIR_CLEAR_FLAG (d, DIRF_RENAMED);
dirlist_replace_prefix (d->name, name_buffer);
}
directory->children = CHANGED_CHILDREN;
@@ -538,6 +546,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
quote_n (1, d->name)));
directory->orig = d;
DIR_SET_FLAG (directory, DIRF_RENAMED);
DIR_CLEAR_FLAG (d, DIRF_RENAMED);
dirlist_replace_prefix (d->name, name_buffer);
}
directory->children = CHANGED_CHILDREN;
@@ -650,7 +659,7 @@ makedumpdir (struct directory *directory, const char *dir)
if (directory->children == ALL_CHILDREN)
dump = NULL;
else if (DIR_IS_RENAMED (directory))
else if (directory->orig)
dump = directory->orig->idump ?
directory->orig->idump : directory->orig->dump;
else
@@ -879,43 +888,36 @@ obstack_code_rename (struct obstack *stk, char const *from, char const *to)
static void
store_rename (struct directory *dir, struct obstack *stk)
{
if (DIR_IS_RENAMED (dir))
struct directory *prev, *p;
/* Detect eventual cycles. If the chain forms a cycle, prev points to
the entry DIR is renamed from.*/
for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
;
if (prev == NULL)
{
struct directory *prev, *p;
/* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries
are ignored when hit by this function next time.
If the chain forms a cycle, prev points to the entry DIR is renamed
from. In this case it still retains DIRF_RENAMED flag, which will be
cleared in the 'else' branch below */
for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
if (prev == NULL)
{
for (p = dir; p && p->orig; p = p->orig)
obstack_code_rename (stk, p->orig->name, p->name);
}
else
{
char *temp_name;
DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
/* Break the cycle by using a temporary name for one of its
elements.
First, create a temp name stub entry. */
temp_name = dir_name (dir->name);
obstack_1grow (stk, 'X');
obstack_grow (stk, temp_name, strlen (temp_name) + 1);
obstack_code_rename (stk, dir->name, "");
for (p = dir; p != prev; p = p->orig)
obstack_code_rename (stk, p->orig->name, p->name);
obstack_code_rename (stk, "", prev->name);
}
for (p = dir; p && p->orig; p = p->orig)
obstack_code_rename (stk, p->orig->name, p->name);
}
else
{
char *temp_name;
/* Break the cycle by using a temporary name for one of its
elements.
First, create a temp name stub entry. */
temp_name = dir_name (dir->name);
obstack_1grow (stk, 'X');
obstack_grow (stk, temp_name, strlen (temp_name) + 1);
obstack_code_rename (stk, dir->name, "");
for (p = dir; p != prev; p = p->orig)
obstack_code_rename (stk, p->orig->name, p->name);
obstack_code_rename (stk, "", prev->name);
free (temp_name);
}
}
@@ -941,7 +943,8 @@ append_incremental_renames (struct directory *dir)
size = 0;
for (dp = dirhead; dp; dp = dp->next)
store_rename (dp, &stk);
if (DIR_IS_RENAMED (dp))
store_rename (dp, &stk);
/* FIXME: Is this the right thing to do when DIR is null? */
if (dir && obstack_object_size (&stk) != size)
@@ -997,10 +1000,10 @@ read_incr_db_01 (int version, const char *initbuf)
newer_mtime_option = decode_timespec (buf, &ebuf, false);
if (! valid_timespec (newer_mtime_option))
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option),
lineno,
_("Invalid time stamp")));
FATAL_ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option),
lineno,
_("Invalid time stamp")));
else
{
if (version == 1 && *ebuf)
@@ -1042,9 +1045,9 @@ read_incr_db_01 (int version, const char *initbuf)
mtime = decode_timespec (strp, &ebuf, false);
strp = ebuf;
if (!valid_timespec (mtime) || *strp != ' ')
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time")));
FATAL_ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time")));
errno = 0;
u = strtoumax (strp, &ebuf, 10);
@@ -1052,9 +1055,9 @@ read_incr_db_01 (int version, const char *initbuf)
errno = ERANGE;
if (errno || strp == ebuf || *ebuf != ' ')
{
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time (nanoseconds)")));
FATAL_ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid modification time (nanoseconds)")));
mtime.tv_nsec = -1;
}
else
@@ -1068,17 +1071,17 @@ read_incr_db_01 (int version, const char *initbuf)
TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t));
strp = ebuf;
if (errno || *strp != ' ')
ERROR ((0, errno, "%s:%ld: %s",
FATAL_ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid device number")));
_("Invalid device number")));
ino = strtosysint (strp, &ebuf,
TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t));
strp = ebuf;
if (errno || *strp != ' ')
ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid inode number")));
FATAL_ERROR ((0, errno, "%s:%ld: %s",
quotearg_colon (listed_incremental_option), lineno,
_("Invalid inode number")));
strp++;
unquote_string (strp);

View File

@@ -1,7 +1,6 @@
/* List a tar archive, with support routines for reading a tar archive.
Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2016 Free
Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -23,7 +22,7 @@
#include <system.h>
#include <inttostr.h>
#include <quotearg.h>
#include <time.h>
#include "common.h"
union block *current_header; /* points to current archive header */
@@ -120,7 +119,7 @@ enforce_one_top_level (char **pfile_name)
{
char *file_name = *pfile_name;
char *p;
for (p = file_name; *p && (ISSLASH (*p) || *p == '.'); p++)
;
@@ -132,7 +131,7 @@ enforce_one_top_level (char **pfile_name)
if (ISSLASH (p[pos]) || p[pos] == 0)
return;
}
*pfile_name = make_file_name (one_top_level_dir, file_name);
normalize_filename_x (*pfile_name);
}
@@ -218,7 +217,7 @@ read_and (void (*do_something) (void))
if (show_omitted_dirs_option)
WARN ((0, 0, _("%s: Omitting"),
quotearg_colon (current_stat_info.file_name)));
/* Fall through. */
FALLTHROUGH;
default:
skip_member ();
continue;
@@ -273,8 +272,7 @@ read_and (void (*do_something) (void))
{
case HEADER_STILL_UNREAD:
ERROR ((0, 0, _("This does not look like a tar archive")));
/* Fall through. */
FALLTHROUGH;
case HEADER_ZERO_BLOCK:
case HEADER_SUCCESS:
if (block_number_option)
@@ -410,26 +408,27 @@ read_header (union block **return_block, struct tar_stat_info *info,
enum read_header_mode mode)
{
union block *header;
union block *header_copy;
char *bp;
union block *data_block;
size_t size, written;
union block *next_long_name = 0;
union block *next_long_link = 0;
union block *next_long_name = NULL;
union block *next_long_link = NULL;
size_t next_long_name_blocks = 0;
size_t next_long_link_blocks = 0;
enum read_header status = HEADER_SUCCESS;
while (1)
{
enum read_header status;
header = find_next_block ();
*return_block = header;
if (!header)
return HEADER_END_OF_FILE;
{
status = HEADER_END_OF_FILE;
break;
}
if ((status = tar_checksum (header, false)) != HEADER_SUCCESS)
return status;
break;
/* Good block. Decode file size and return. */
@@ -439,7 +438,10 @@ read_header (union block **return_block, struct tar_stat_info *info,
{
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
if (info->stat.st_size < 0)
return HEADER_FAILURE;
{
status = HEADER_FAILURE;
break;
}
}
if (header->header.typeflag == GNUTYPE_LONGNAME
@@ -449,10 +451,14 @@ read_header (union block **return_block, struct tar_stat_info *info,
|| header->header.typeflag == SOLARIS_XHDTYPE)
{
if (mode == read_header_x_raw)
return HEADER_SUCCESS_EXTENDED;
{
status = HEADER_SUCCESS_EXTENDED;
break;
}
else if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK)
{
union block *header_copy;
size_t name_size = info->stat.st_size;
size_t n = name_size % BLOCKSIZE;
size = name_size + BLOCKSIZE;
@@ -519,7 +525,10 @@ read_header (union block **return_block, struct tar_stat_info *info,
xheader_decode_global (&xhdr);
xheader_destroy (&xhdr);
if (mode == read_header_x_global)
return HEADER_SUCCESS_EXTENDED;
{
status = HEADER_SUCCESS_EXTENDED;
break;
}
}
/* Loop! */
@@ -538,6 +547,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
name = next_long_name->buffer + BLOCKSIZE;
recent_long_name = next_long_name;
recent_long_name_blocks = next_long_name_blocks;
next_long_name = NULL;
}
else
{
@@ -569,6 +579,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
name = next_long_link->buffer + BLOCKSIZE;
recent_long_link = next_long_link;
recent_long_link_blocks = next_long_link_blocks;
next_long_link = NULL;
}
else
{
@@ -580,9 +591,12 @@ read_header (union block **return_block, struct tar_stat_info *info,
}
assign_string (&info->link_name, name);
return HEADER_SUCCESS;
break;
}
}
free (next_long_name);
free (next_long_link);
return status;
}
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
@@ -632,10 +646,12 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
stat_info->stat.st_mode = mode;
stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
stat_info->mtime.tv_nsec = 0;
assign_string (&stat_info->uname,
header->header.uname[0] ? header->header.uname : NULL);
assign_string (&stat_info->gname,
header->header.gname[0] ? header->header.gname : NULL);
assign_string_n (&stat_info->uname,
header->header.uname[0] ? header->header.uname : NULL,
sizeof (header->header.uname));
assign_string_n (&stat_info->gname,
header->header.gname[0] ? header->header.gname : NULL,
sizeof (header->header.gname));
xheader_xattr_init (stat_info);
@@ -1050,15 +1066,11 @@ tartime (struct timespec t, bool full_time)
{
if (full_time)
{
sprintf (buffer, "%04ld-%02d-%02d %02d:%02d:%02d",
tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
strftime (buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", tm);
code_ns_fraction (ns, buffer + strlen (buffer));
}
else
sprintf (buffer, "%04ld-%02d-%02d %02d:%02d",
tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min);
strftime (buffer, sizeof buffer, "%Y-%m-%d %H:%M", tm);
return buffer;
}
@@ -1444,7 +1456,7 @@ test_archive_label (void)
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);
ASSIGN_STRING_N (&volume_label, current_header->header.name);
if (volume_label)
{

View File

@@ -1,6 +1,6 @@
/* Owner/group mapping for tar
Copyright 2015-2016 Free Software Foundation, Inc.
Copyright 2015-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,7 +1,6 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010,
2012-2014, 2016 Free Software Foundation, Inc.
Copyright 1988-2021 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
@@ -33,6 +32,11 @@ static void namebuf_add_dir (namebuf_t, char const *);
static char *namebuf_finish (namebuf_t);
static const char *tar_getcdpath (int);
char const *
quote_n_colon (int n, char const *arg)
{
return quotearg_n_style_colon (n, get_quoting_style (NULL), arg);
}
/* Handling strings. */
@@ -45,6 +49,20 @@ assign_string (char **string, const char *value)
*string = value ? xstrdup (value) : 0;
}
void
assign_string_n (char **string, const char *value, size_t n)
{
free (*string);
if (value)
{
size_t l = strnlen (value, n);
char *p = xmalloc (l + 1);
memcpy (p, value, l);
p[l] = 0;
*string = p;
}
}
#if 0
/* This function is currently unused; perhaps it should be removed? */
@@ -296,8 +314,6 @@ normalize_filename (int cdidx, const char *name)
size_t copylen;
bool need_separator;
if (!cdpath)
call_arg_fatal ("getcwd", ".");
copylen = strlen (cdpath);
need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& copylen == 2 && ISSLASH (cdpath[1]));
@@ -722,7 +738,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
return true;
after_backup_name = find_backup_file_name (file_name, backup_type);
after_backup_name = find_backup_file_name (chdir_fd, file_name, backup_type);
if (! after_backup_name)
xalloc_die ();
@@ -892,8 +908,6 @@ chdir_count (void)
int
chdir_arg (char const *dir)
{
char *absdir;
if (wd_count == wd_alloc)
{
if (wd_alloc == 0)
@@ -903,7 +917,7 @@ chdir_arg (char const *dir)
if (! wd_count)
{
wd[wd_count].name = ".";
wd[wd_count].abspath = xgetcwd ();
wd[wd_count].abspath = NULL;
wd[wd_count].fd = AT_FDCWD;
wd_count++;
}
@@ -920,22 +934,8 @@ chdir_arg (char const *dir)
return wd_count - 1;
}
/* If the given name is absolute, use it to represent this directory;
otherwise, construct a name based on the previous -C option. */
if (IS_ABSOLUTE_FILE_NAME (dir))
absdir = xstrdup (dir);
else if (wd[wd_count - 1].abspath)
{
namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
namebuf_add_dir (nbuf, dir);
absdir = namebuf_finish (nbuf);
}
else
absdir = 0;
wd[wd_count].name = dir;
wd[wd_count].abspath = absdir;
wd[wd_count].abspath = NULL;
wd[wd_count].fd = 0;
return wd_count++;
}
@@ -1029,9 +1029,47 @@ tar_getcdpath (int idx)
{
static char *cwd;
if (!cwd)
cwd = xgetcwd ();
{
cwd = xgetcwd ();
if (!cwd)
call_arg_fatal ("getcwd", ".");
}
return cwd;
}
if (!wd[idx].abspath)
{
int i;
int save_cwdi = chdir_current;
for (i = idx; i >= 0; i--)
if (wd[i].abspath)
break;
while (++i <= idx)
{
chdir_do (i);
if (i == 0)
{
if ((wd[i].abspath = xgetcwd ()) == NULL)
call_arg_fatal ("getcwd", ".");
}
else if (IS_ABSOLUTE_FILE_NAME (wd[i].name))
/* If the given name is absolute, use it to represent this
directory; otherwise, construct a name based on the
previous -C option. */
wd[i].abspath = xstrdup (wd[i].name);
else
{
namebuf_t nbuf = namebuf_create (wd[i - 1].abspath);
namebuf_add_dir (nbuf, wd[i].name);
wd[i].abspath = namebuf_finish (nbuf);
}
}
chdir_do (save_cwdi);
}
return wd[idx].abspath;
}
@@ -1039,7 +1077,10 @@ void
close_diag (char const *name)
{
if (ignore_failed_read_option)
close_warn (name);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
close_warn (name);
}
else
close_error (name);
}
@@ -1048,7 +1089,10 @@ void
open_diag (char const *name)
{
if (ignore_failed_read_option)
open_warn (name);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
open_warn (name);
}
else
open_error (name);
}
@@ -1057,7 +1101,10 @@ void
read_diag_details (char const *name, off_t offset, size_t size)
{
if (ignore_failed_read_option)
read_warn_details (name, offset, size);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
read_warn_details (name, offset, size);
}
else
read_error_details (name, offset, size);
}
@@ -1066,7 +1113,10 @@ void
readlink_diag (char const *name)
{
if (ignore_failed_read_option)
readlink_warn (name);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
readlink_warn (name);
}
else
readlink_error (name);
}
@@ -1075,7 +1125,10 @@ void
savedir_diag (char const *name)
{
if (ignore_failed_read_option)
savedir_warn (name);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
savedir_warn (name);
}
else
savedir_error (name);
}
@@ -1084,7 +1137,10 @@ void
seek_diag_details (char const *name, off_t offset)
{
if (ignore_failed_read_option)
seek_warn_details (name, offset);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
seek_warn_details (name, offset);
}
else
seek_error_details (name, offset);
}
@@ -1093,7 +1149,10 @@ void
stat_diag (char const *name)
{
if (ignore_failed_read_option)
stat_warn (name);
{
if (WARNING_ENABLED(WARN_FAILED_READ))
stat_warn (name);
}
else
stat_error (name);
}

View File

@@ -1,7 +1,6 @@
/* Various processing of names.
Copyright 1988, 1992, 1994, 1996-2001, 2003-2007, 2009, 2013-2016
Free Software Foundation, Inc.
Copyright 1988-2021 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
@@ -32,7 +31,8 @@ static void name_add_file (const char *name);
enum
{
EXCLUDE_BACKUPS_OPTION = 256,
ADD_FILE_OPTION = 256,
EXCLUDE_BACKUPS_OPTION,
EXCLUDE_CACHES_OPTION,
EXCLUDE_CACHES_UNDER_OPTION,
EXCLUDE_CACHES_ALL_OPTION,
@@ -62,104 +62,121 @@ enum
WILDCARDS_OPTION
};
static struct argp_option names_options[] = {
#define GRID 100
{NULL, 0, NULL, 0,
N_("Local file name selection:"), GRID },
enum
{
GRH_LOCAL,
GRID_LOCAL,
GRH_MATCH,
GRID_MATCH,
};
{"add-file", ARGP_KEY_ARG, N_("FILE"), 0,
N_("add given FILE to the archive (useful if its name starts with a dash)"), GRID+1 },
static struct argp_option names_options[] = {
{NULL, 0, NULL, 0,
N_("Local file name selection:"), GRH_LOCAL },
{"add-file", ADD_FILE_OPTION, N_("FILE"), 0,
N_("add given FILE to the archive (useful if its name starts with a dash)"), GRID_LOCAL },
{"directory", 'C', N_("DIR"), 0,
N_("change to directory DIR"), GRID+1 },
N_("change to directory DIR"), GRID_LOCAL },
{"files-from", 'T', N_("FILE"), 0,
N_("get names to extract or create from FILE"), GRID+1 },
N_("get names to extract or create from FILE"), GRID_LOCAL },
{"null", NULL_OPTION, 0, 0,
N_("-T reads null-terminated names; implies --verbatim-files-from"),
GRID+1 },
GRID_LOCAL },
{"no-null", NO_NULL_OPTION, 0, 0,
N_("disable the effect of the previous --null option"), GRID+1 },
N_("disable the effect of the previous --null option"), GRID_LOCAL },
{"unquote", UNQUOTE_OPTION, 0, 0,
N_("unquote input file or member names (default)"), GRID+1 },
N_("unquote input file or member names (default)"), GRID_LOCAL },
{"no-unquote", NO_UNQUOTE_OPTION, 0, 0,
N_("do not unquote input file or member names"), GRID+1 },
N_("do not unquote input file or member names"), GRID_LOCAL },
{"verbatim-files-from", VERBATIM_FILES_FROM_OPTION, 0, 0,
N_("-T reads file names verbatim (no option handling)"), GRID+1 },
N_("-T reads file names verbatim (no escape or option handling)"), GRID_LOCAL },
{"no-verbatim-files-from", NO_VERBATIM_FILES_FROM_OPTION, 0, 0,
N_("-T treats file names starting with dash as options (default)"),
GRID+1 },
GRID_LOCAL },
{"exclude", EXCLUDE_OPTION, N_("PATTERN"), 0,
N_("exclude files, given as a PATTERN"), GRID+1 },
N_("exclude files, given as a PATTERN"), GRID_LOCAL },
{"exclude-from", 'X', N_("FILE"), 0,
N_("exclude patterns listed in FILE"), GRID+1 },
N_("exclude patterns listed in FILE"), GRID_LOCAL },
{"exclude-caches", EXCLUDE_CACHES_OPTION, 0, 0,
N_("exclude contents of directories containing CACHEDIR.TAG, "
"except for the tag file itself"), GRID+1 },
"except for the tag file itself"), GRID_LOCAL },
{"exclude-caches-under", EXCLUDE_CACHES_UNDER_OPTION, 0, 0,
N_("exclude everything under directories containing CACHEDIR.TAG"),
GRID+1 },
GRID_LOCAL },
{"exclude-caches-all", EXCLUDE_CACHES_ALL_OPTION, 0, 0,
N_("exclude directories containing CACHEDIR.TAG"), GRID+1 },
N_("exclude directories containing CACHEDIR.TAG"), GRID_LOCAL },
{"exclude-tag", EXCLUDE_TAG_OPTION, N_("FILE"), 0,
N_("exclude contents of directories containing FILE, except"
" for FILE itself"), GRID+1 },
" for FILE itself"), GRID_LOCAL },
{"exclude-ignore", EXCLUDE_IGNORE_OPTION, N_("FILE"), 0,
N_("read exclude patterns for each directory from FILE, if it exists"),
GRID+1 },
GRID_LOCAL },
{"exclude-ignore-recursive", EXCLUDE_IGNORE_RECURSIVE_OPTION, N_("FILE"), 0,
N_("read exclude patterns for each directory and its subdirectories "
"from FILE, if it exists"), GRID+1 },
"from FILE, if it exists"), GRID_LOCAL },
{"exclude-tag-under", EXCLUDE_TAG_UNDER_OPTION, N_("FILE"), 0,
N_("exclude everything under directories containing FILE"), GRID+1 },
N_("exclude everything under directories containing FILE"), GRID_LOCAL },
{"exclude-tag-all", EXCLUDE_TAG_ALL_OPTION, N_("FILE"), 0,
N_("exclude directories containing FILE"), GRID+1 },
N_("exclude directories containing FILE"), GRID_LOCAL },
{"exclude-vcs", EXCLUDE_VCS_OPTION, NULL, 0,
N_("exclude version control system directories"), GRID+1 },
N_("exclude version control system directories"), GRID_LOCAL },
{"exclude-vcs-ignores", EXCLUDE_VCS_IGNORES_OPTION, NULL, 0,
N_("read exclude patterns from the VCS ignore files"), GRID+1 },
N_("read exclude patterns from the VCS ignore files"), GRID_LOCAL },
{"exclude-backups", EXCLUDE_BACKUPS_OPTION, NULL, 0,
N_("exclude backup and lock files"), GRID+1 },
N_("exclude backup and lock files"), GRID_LOCAL },
{"recursion", RECURSION_OPTION, 0, 0,
N_("recurse into directories (default)"), GRID+1 },
N_("recurse into directories (default)"), GRID_LOCAL },
{"no-recursion", NO_RECURSION_OPTION, 0, 0,
N_("avoid descending automatically in directories"), GRID+1 },
#undef GRID
N_("avoid descending automatically in directories"), GRID_LOCAL },
#define GRID 120
{NULL, 0, NULL, 0,
N_("File name matching options (affect both exclude and include patterns):"),
GRID },
GRH_MATCH },
{"anchored", ANCHORED_OPTION, 0, 0,
N_("patterns match file name start"), GRID+1 },
N_("patterns match file name start"), GRID_MATCH },
{"no-anchored", NO_ANCHORED_OPTION, 0, 0,
N_("patterns match after any '/' (default for exclusion)"), GRID+1 },
N_("patterns match after any '/' (default for exclusion)"), GRID_MATCH },
{"ignore-case", IGNORE_CASE_OPTION, 0, 0,
N_("ignore case"), GRID+1 },
N_("ignore case"), GRID_MATCH },
{"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0,
N_("case sensitive matching (default)"), GRID+1 },
N_("case sensitive matching (default)"), GRID_MATCH },
{"wildcards", WILDCARDS_OPTION, 0, 0,
N_("use wildcards (default for exclusion)"), GRID+1 },
N_("use wildcards (default for exclusion)"), GRID_MATCH },
{"no-wildcards", NO_WILDCARDS_OPTION, 0, 0,
N_("verbatim string matching"), GRID+1 },
N_("verbatim string matching"), GRID_MATCH },
{"wildcards-match-slash", WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
N_("wildcards match '/' (default for exclusion)"), GRID+1 },
N_("wildcards match '/' (default for exclusion)"), GRID_MATCH },
{"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
N_("wildcards do not match '/'"), GRID+1 },
#undef GRID
N_("wildcards do not match '/'"), GRID_MATCH },
{NULL}
};
static bool
is_file_selection_option (int key)
static struct argp_option const *
file_selection_option (int key)
{
struct argp_option *p;
for (p = names_options;
!(p->name == NULL && p->key == 0 && p->doc == NULL); p++)
if (p->key == key)
return true;
return false;
}
return p;
return NULL;
}
static char const *
file_selection_option_name (int key)
{
struct argp_option const *opt = file_selection_option (key);
return opt ? opt->name : NULL;
}
static bool
is_file_selection_option (int key)
{
return file_selection_option (key) != NULL;
}
/* Either NL or NUL, as decided by the --null option. */
static char filename_terminator = '\n';
@@ -177,17 +194,30 @@ names_parse_opt (int key, char *arg, struct argp_state *state)
case 'T':
name_add_file (arg);
/* Indicate we've been given -T option. This is for backward
compatibility only, so that `tar cfT archive /dev/null will
succeed */
files_from_option = true;
break;
case ADD_FILE_OPTION:
name_add_name (arg);
break;
case ARGP_KEY_ERROR:
{
struct tar_args *args = state->input;
if (args->loc->source == OPTS_FILE)
{
error (0, 0, _("%s:%lu: unrecognized option"), args->loc->name,
(unsigned long) args->loc->line);
set_exit_status (TAREXIT_FAILURE);
}
return ARGP_ERR_UNKNOWN;
}
default:
if (is_file_selection_option (key))
name_add_option (key, arg);
else
return ARGP_ERR_UNKNOWN;
}
return 0;
}
@@ -207,7 +237,7 @@ static int matching_flags = 0;
/* exclude_fnmatch options */
static int include_anchored = EXCLUDE_ANCHORED;
/* Pattern anchoring options used for file inclusion */
#define EXCLUDE_OPTIONS \
(((wildcards != disable_wildcards) ? EXCLUDE_WILDCARDS : 0) \
| matching_flags \
@@ -406,7 +436,7 @@ handle_file_selection_option (int key, const char *arg)
}
}
static struct argp names_argp = {
struct argp names_argp = {
names_options,
names_parse_opt,
NULL,
@@ -416,10 +446,6 @@ static struct argp names_argp = {
NULL
};
struct argp_child names_argp_children[] = {
{ &names_argp, 0, "", 0 },
{ NULL }
};
/* User and group names. */
@@ -638,8 +664,10 @@ struct name_elt /* A name_array element. */
} v;
};
static struct name_elt *name_head; /* store a list of names */
size_t name_count; /* how many of the entries are names? */
static struct name_elt *name_head; /* store a list of names */
/* how many of the entries are file names? */
enum files_count filename_args = FILES_NONE;
static struct name_elt *
name_elt_alloc (void)
@@ -670,7 +698,86 @@ name_list_adjust (void)
while (name_head->prev)
name_head = name_head->prev;
}
/* For error-reporting purposes, keep a doubly-linked list of unconsumed file
selection options. The option is deemed unconsumed unless followed by one
or more file/member name arguments. When archive creation is requested,
each file selection option encountered is pushed into the list. The list
is cleared upon encountering a file name argument.
If the list is not empty when all arguments have been processed, an error
message is issued reporting the options that had no effect.
For simplicity, only a tail pointer of the list is maintained.
*/
struct name_elt *unconsumed_option_tail;
/* Push an option to the list */
static void
unconsumed_option_push (struct name_elt *elt)
{
elt->next = NULL;
elt->prev = unconsumed_option_tail;
if (unconsumed_option_tail)
unconsumed_option_tail->next = elt;
unconsumed_option_tail = elt;
}
/* Clear the unconsumed option list */
static void
unconsumed_option_free (void)
{
while (unconsumed_option_tail)
{
struct name_elt *elt = unconsumed_option_tail;
unconsumed_option_tail = unconsumed_option_tail->prev;
free (elt);
}
}
/* Report any options that have not been consumed */
static void
unconsumed_option_report (void)
{
if (unconsumed_option_tail)
{
struct name_elt *elt;
ERROR ((0, 0, _("The following options were used after any non-optional arguments in archive create or update mode. These options are positional and affect only arguments that follow them. Please, rearrange them properly.")));
elt = unconsumed_option_tail;
while (elt->prev)
elt = elt->prev;
while (elt)
{
switch (elt->type)
{
case NELT_CHDIR:
ERROR ((0, 0, _("-C %s has no effect"), quote (elt->v.name)));
break;
case NELT_OPTION:
if (elt->v.opt.arg)
ERROR ((0, 0, _("--%s %s has no effect"),
file_selection_option_name (elt->v.opt.option),
quote (elt->v.opt.arg)));
else
ERROR ((0, 0, _("--%s has no effect"),
file_selection_option_name (elt->v.opt.option)));
break;
default:
break;
}
elt = elt->next;
}
unconsumed_option_free ();
}
}
static void
name_list_advance (void)
{
@@ -678,10 +785,20 @@ name_list_advance (void)
name_head = elt->next;
if (name_head)
name_head->prev = NULL;
free (elt);
if (elt->type == NELT_OPTION || elt->type == NELT_CHDIR)
{
if (subcommand_option == CREATE_SUBCOMMAND
|| subcommand_option == UPDATE_SUBCOMMAND)
unconsumed_option_push (elt);
}
else
{
if (elt->type != NELT_NOOP)
unconsumed_option_free ();
free (elt);
}
}
/* Add to name_array the file NAME with fnmatch options MATFLAGS */
void
name_add_name (const char *name)
@@ -690,7 +807,20 @@ name_add_name (const char *name)
ep->type = NELT_NAME;
ep->v.name = name;
name_count++;
switch (filename_args)
{
case FILES_NONE:
filename_args = FILES_ONE;
break;
case FILES_ONE:
filename_args = FILES_MANY;
break;
default:
break;
}
}
static void
@@ -720,6 +850,10 @@ name_add_file (const char *name)
ep->v.file.name = name;
ep->v.file.line = 0;
ep->v.file.fp = NULL;
/* We don't know beforehand how many files are listed.
Assume more than one. */
filename_args = FILES_MANY;
}
/* Names from external name file. */
@@ -856,7 +990,7 @@ handle_option (const char *str, struct name_elt const *ent)
struct wordsplit ws;
int i;
struct option_locus loc;
while (*str && isspace (*str))
++str;
if (*str != '-')
@@ -914,14 +1048,17 @@ read_next_name (struct name_elt *ent, struct name_elt *ret)
(0, 0, N_("%s: file name read contains nul character"),
quotearg_colon (ent->v.file.name)));
ent->v.file.term = 0;
/* fall through */
FALLTHROUGH;
case file_list_success:
if (unquote_option)
unquote_string (name_buffer);
if (!ent->v.file.verbatim && handle_option (name_buffer, ent) == 0)
if (!ent->v.file.verbatim)
{
name_list_adjust ();
return 1;
if (unquote_option)
unquote_string (name_buffer);
if (handle_option (name_buffer, ent) == 0)
{
name_list_adjust ();
return 1;
}
}
ret->type = NELT_NAME;
ret->v.name = name_buffer;
@@ -945,19 +1082,8 @@ copy_name (struct name_elt *ep)
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);
}
while (name_buffer_length <= source_len)
name_buffer = x2realloc(name_buffer, &name_buffer_length);
strcpy (name_buffer, source);
chopslash (name_buffer);
}
@@ -996,7 +1122,7 @@ name_next_elt (int change_dirs)
name_list_advance ();
break;
}
/* fall through */
FALLTHROUGH;
case NELT_NAME:
copy_name (ep);
if (unquote_option)
@@ -1013,6 +1139,8 @@ name_next_elt (int change_dirs)
}
}
unconsumed_option_report ();
return NULL;
}
@@ -1111,6 +1239,34 @@ addname (char const *string, int change_dir, bool cmdline, struct name *parent)
return name;
}
void
add_starting_file (char const *file_name)
{
struct name *name = make_name (file_name);
if (starting_file_option)
{
struct name *head = namelist;
remname (head);
free_name (head);
}
name->prev = NULL;
name->next = namelist;
namelist = name;
if (!nametail)
nametail = namelist;
name->found_count = 0;
name->matching_flags = INCLUDE_OPTIONS;
name->change_dir = 0;
name->directory = NULL;
name->parent = NULL;
name->cmdline = true;
starting_file_option = true;
}
/* Find a match for FILE_NAME (whose string length is LENGTH) in the name
list. */
static struct name *
@@ -1167,19 +1323,22 @@ name_match (const char *file_name)
}
cursor = namelist_match (file_name, length);
if (starting_file_option)
{
/* If starting_file_option is set, the head of the list is the name
of the member to start extraction from. Skip the match unless it
is head. */
if (cursor == namelist)
starting_file_option = false;
else
cursor = NULL;
}
if (cursor)
{
if (!(ISSLASH (file_name[cursor->length]) && recursion_option)
|| cursor->found_count == 0)
cursor->found_count++; /* remember it matched */
if (starting_file_option)
{
free (namelist);
namelist = NULL;
nametail = NULL;
}
chdir_do (cursor->change_dir);
/* We got a match. */
return ISFOUND (cursor);
}
@@ -1445,9 +1604,8 @@ add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
size_t name_length = name->length;
size_t allocated_length = (name_length >= NAME_FIELD_SIZE
? name_length + NAME_FIELD_SIZE
: NAME_FIELD_SIZE);
char *namebuf = xmalloc (allocated_length + 1);
/* FIXME: + 2 above? */
: NAME_FIELD_SIZE) + 2;
char *namebuf = xmalloc (allocated_length);
const char *string;
size_t string_length;
int change_dir = name->change_dir;
@@ -1468,18 +1626,10 @@ add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
struct tar_stat_info subdir;
int subfd;
if (allocated_length <= name_length + string_length)
{
do
{
allocated_length *= 2;
if (! allocated_length)
xalloc_die ();
}
while (allocated_length <= name_length + string_length);
namebuf = xrealloc (namebuf, allocated_length + 1);
}
/* need to have at least string_length bytes above the
name_length, this includes the trailing null character */
while (allocated_length < name_length + string_length)
namebuf = x2realloc (namebuf, &allocated_length);
strcpy (namebuf + name_length, string + 1);
np = addname (namebuf, change_dir, false, name);
if (!child_head)
@@ -1651,6 +1801,11 @@ collect_and_sort_names (void)
name->found_count++;
add_hierarchy_to_namelist (&st, name);
}
else
{
errno = ENOTDIR;
open_diag (name->name);
}
}
}
@@ -1675,7 +1830,7 @@ collect_and_sort_names (void)
{
if (p->child)
rebase_child_list (p->child, name);
hash_delete (nametab, name);
hash_remove (nametab, name);
/* FIXME: remove_directory (p->caname); ? */
remname (p);
free_name (p);
@@ -1705,7 +1860,7 @@ collect_and_sort_names (void)
if (listed_incremental_option)
{
for (name = namelist; name && name->name[0] == 0; name++)
for (name = namelist; name && name->name[0] == 0; name = name->next)
;
if (name)
append_incremental_renames (name->directory);

View File

@@ -1,6 +1,6 @@
/* Functions for dealing with sparse files
Copyright 2003-2007, 2010, 2013-2016 Free Software Foundation, Inc.
Copyright 2003-2021 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
@@ -361,11 +361,12 @@ sparse_scan_file (struct tar_sparse_file *file)
/* fall back to "raw" for this and all other files */
hole_detection = HOLE_DETECTION_RAW;
#endif
FALLTHROUGH;
case HOLE_DETECTION_RAW:
if (sparse_scan_file_raw (file))
return true;
}
return false;
}
@@ -426,6 +427,30 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
bufsize);
return false;
}
else if (bytes_read == 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
struct stat st;
size_t n;
if (fstat (file->fd, &st) == 0)
n = file->stat_info->stat.st_size - st.st_size;
else
n = file->stat_info->stat.st_size
- (file->stat_info->sparse_map[i].offset
+ file->stat_info->sparse_map[i].numbytes
- bytes_left);
WARNOPT (WARN_FILE_SHRANK,
(0, 0,
ngettext ("%s: File shrank by %s byte; padding with zeros",
"%s: File shrank by %s bytes; padding with zeros",
n),
quotearg_colon (file->stat_info->orig_file_name),
STRINGIFY_BIGINT (n, buf)));
if (! ignore_failed_read_option)
set_exit_status (TAREXIT_DIFFERS);
return false;
}
memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
bytes_left -= bytes_read;
@@ -463,9 +488,9 @@ sparse_extract_region (struct tar_sparse_file *file, size_t i)
return false;
}
set_next_block_after (blk);
file->dumped_size += BLOCKSIZE;
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);
file->offset += count;
if (count != wrbytes)
@@ -597,6 +622,12 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
rdsize);
return false;
}
else if (bytes_read == 0)
{
report_difference (file->stat_info, _("Size differs"));
return false;
}
if (!zero_block_p (diff_buffer, bytes_read))
{
char begbuf[INT_BUFSIZE_BOUND (off_t)];
@@ -608,6 +639,7 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
beg += bytes_read;
}
return true;
}
@@ -634,6 +666,7 @@ check_data_region (struct tar_sparse_file *file, size_t i)
return false;
}
set_next_block_after (blk);
file->dumped_size += BLOCKSIZE;
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
if (bytes_read == SAFE_READ_ERROR)
{
@@ -644,10 +677,14 @@ check_data_region (struct tar_sparse_file *file, size_t i)
rdsize);
return false;
}
file->dumped_size += bytes_read;
else if (bytes_read == 0)
{
report_difference (&current_stat_info, _("Size differs"));
return false;
}
size_left -= bytes_read;
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
if (memcmp (blk->buffer, diff_buffer, rdsize))
if (memcmp (blk->buffer, diff_buffer, bytes_read))
{
report_difference (file->stat_info, _("Contents differ"));
return false;
@@ -665,7 +702,7 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
off_t offset = 0;
if (!tar_sparse_init (&file))
return dump_status_not_implemented;
return false;
file.stat_info = st;
file.fd = fd;
@@ -1212,7 +1249,8 @@ pax_decode_header (struct tar_sparse_file *file)
union block *blk;
char *p;
size_t i;
off_t start;
#define COPY_BUF(b,buf,src) do \
{ \
char *endp = b->buffer + BLOCKSIZE; \
@@ -1228,8 +1266,9 @@ pax_decode_header (struct tar_sparse_file *file)
if (src == endp) \
{ \
set_next_block_after (b); \
file->dumped_size += BLOCKSIZE; \
b = find_next_block (); \
if (!b) \
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive"))); \
src = b->buffer; \
endp = b->buffer + BLOCKSIZE; \
} \
@@ -1239,9 +1278,11 @@ pax_decode_header (struct tar_sparse_file *file)
dst[-1] = 0; \
} while (0)
start = current_block_ordinal ();
set_next_block_after (current_header);
file->dumped_size += BLOCKSIZE;
blk = find_next_block ();
if (!blk)
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
p = blk->buffer;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
@@ -1277,6 +1318,8 @@ pax_decode_header (struct tar_sparse_file *file)
sparse_add_map (file->stat_info, &sp);
}
set_next_block_after (blk);
file->dumped_size += BLOCKSIZE * (current_block_ordinal () - start);
}
return true;

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright 2007, 2009, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
Written by Sergey Poznyakoff.
@@ -45,6 +45,8 @@ static struct compression_suffix compression_suffixes[] = {
{ S(lzo, LZOP) },
{ S(xz, XZ) },
{ S(txz, XZ) }, /* Slackware */
{ S(zst, ZSTD) },
{ S(tzst, ZSTD) },
{ NULL }
#undef S
#undef __CAT2__
@@ -59,7 +61,7 @@ find_compression_suffix (const char *name, size_t *ret_len)
{
size_t len;
struct compression_suffix *p;
suf++;
len = strlen (suf);
@@ -98,10 +100,14 @@ strip_compression_suffix (const char *name)
{
char *s = NULL;
size_t len;
struct compression_suffix const *p = find_compression_suffix (name, &len);
if (find_compression_suffix (name, &len))
if (p)
{
if (strncmp (name + len - 4, ".tar", 4) == 0)
/* Strip an additional ".tar" suffix, but only if the just-stripped
"outer" suffix did not begin with "t". */
if (len > 4 && strncmp (name + len - 4, ".tar", 4) == 0
&& p->suffix[0] != 't')
len -= 4;
if (len == 0)
return NULL;
@@ -111,4 +117,3 @@ strip_compression_suffix (const char *name)
}
return s;
}

View File

@@ -1,7 +1,6 @@
/* System-dependent calls for tar.
Copyright 2003-2008, 2010, 2013-2014, 2016 Free Software Foundation,
Inc.
Copyright 2003-2021 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

798
src/tar.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
/* GNU tar Archive Format description.
Copyright 1988-1989, 1991-1997, 2000-2001, 2003-2007, 2012-2014, 2016
Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -328,9 +327,13 @@ struct tar_stat_info
struct sp_array *sparse_map;
off_t real_size; /* The real size of sparse file */
int real_size_set; /* True when GNU.sparse.realsize is set in
bool real_size_set; /* True when GNU.sparse.realsize is set in
archived file */
bool sparse_name_done; /* Set to true if 'GNU.sparse.name' header was
processed pax header parsing. Following 'path'
header (lower priority) will be ignored. */
size_t xattr_map_size; /* Size of the xattr map */
struct xattr_array *xattr_map;

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright 2006-2008, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 2006-2021 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
@@ -100,7 +100,7 @@ add_segment (struct transform *tf)
}
static void
add_literal_segment (struct transform *tf, char *str, char *end)
add_literal_segment (struct transform *tf, const char *str, const char *end)
{
size_t len = end - str;
if (len)
@@ -208,6 +208,8 @@ parse_transform_expr (const char *expr)
}
delim = expr[1];
if (!delim)
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
/* Scan regular expression */
for (i = 2; expr[i] && expr[i] != delim; i++)
@@ -272,7 +274,7 @@ parse_transform_expr (const char *expr)
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
}
if (str[0] == '^' || str[strlen (str) - 1] == '$')
if (str[0] == '^' || (i > 2 && str[i - 3] == '$'))
tf->transform_type = transform_first;
free (str);
@@ -402,6 +404,7 @@ parse_transform_expr (const char *expr)
cur++;
}
add_literal_segment (tf, beg, cur);
free(str);
return p;
}
@@ -549,7 +552,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
default:
break;
}
/*FALL THROUGH*/
FALLTHROUGH;
case ctl_upcase:
case ctl_locase:

View File

@@ -1,6 +1,6 @@
/* Unlink files.
Copyright 2009, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -127,7 +127,9 @@ flush_deferred_unlinks (bool force)
case EEXIST:
/* OpenSolaris >=10 sets EEXIST instead of ENOTEMPTY
if trying to remove a non-empty directory */
#if defined ENOTEMPTY && ENOTEMPTY != EEXIST
case ENOTEMPTY:
#endif
/* Keep the record in list, in the hope we'll
be able to remove it later */
prev = p;

View File

@@ -1,7 +1,6 @@
/* Update a tar archive.
Copyright 1988, 1992, 1994, 1996-1997, 1999-2001, 2003-2005, 2007,
2010, 2013-2014, 2016 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -111,7 +110,7 @@ update_archive (void)
name_gather ();
open_archive (ACCESS_UPDATE);
buffer_write_global_xheader ();
xheader_forbid_global ();
while (!found_end)
{
@@ -152,7 +151,7 @@ update_archive (void)
for (p = dirp; *p; p += strlen (p) + 1)
addname (namebuf_name (nbuf, p),
0, false, NULL);
name->change_dir, false, NULL);
namebuf_free (nbuf);
free (dirp);
@@ -186,13 +185,11 @@ update_archive (void)
{
case HEADER_STILL_UNREAD:
WARN ((0, 0, _("This does not look like a tar archive")));
/* Fall through. */
FALLTHROUGH;
case HEADER_SUCCESS:
case HEADER_ZERO_BLOCK:
ERROR ((0, 0, _("Skipping to next header")));
/* Fall through. */
FALLTHROUGH;
case HEADER_FAILURE:
break;

View File

@@ -1,7 +1,6 @@
/* Charset handling for GNU tar.
Copyright 2004, 2006-2007, 2013-2014, 2016 Free Software Foundation,
Inc.
Copyright 2004-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -36,11 +35,14 @@
# define iconv_open(tocode, fromcode) ((iconv_t) -1)
# undef iconv
# define iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) ((size_t) 0)
# define iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) (errno = ENOSYS, (size_t) -1)
# undef iconv_close
# define iconv_close(cd) 0
# undef iconv_t
# define iconv_t int
#endif
@@ -65,10 +67,9 @@ bool
utf8_convert (bool to_utf, char const *input, char **output)
{
char ICONV_CONST *ib;
char *ob;
char *ob, *ret;
size_t inlen;
size_t outlen;
size_t rc;
iconv_t cd = utf8_init (to_utf);
if (cd == 0)
@@ -81,11 +82,27 @@ utf8_convert (bool to_utf, char const *input, char **output)
inlen = strlen (input) + 1;
outlen = inlen * MB_LEN_MAX + 1;
ob = *output = xmalloc (outlen);
ob = ret = xmalloc (outlen);
ib = (char ICONV_CONST *) input;
rc = iconv (cd, &ib, &inlen, &ob, &outlen);
/* According to POSIX, "if iconv() encounters a character in the input
buffer that is valid, but for which an identical character does not
exist in the target codeset, iconv() shall perform an
implementation-defined conversion on this character." It will "update
the variables pointed to by the arguments to reflect the extent of the
conversion and return the number of non-identical conversions performed".
On error, it returns -1.
In other words, non-zero return always indicates failure, either because
the input was not fully converted, or because it was converted in a
non-reversible way.
*/
if (iconv (cd, &ib, &inlen, &ob, &outlen) != 0)
{
free (ret);
return false;
}
*ob = 0;
return rc != -1;
*output = ret;
return true;
}

View File

@@ -1,6 +1,6 @@
/* Warnings for GNU tar.
Copyright 2009, 2012-2014, 2016 Free Software Foundation, Inc.
Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -47,6 +47,7 @@ static char const *const warning_args[] = {
"existing-file",
"xattr-write",
"record-size",
"failed-read",
NULL
};
@@ -74,7 +75,8 @@ static int warning_types[] = {
WARN_DECOMPRESS_PROGRAM,
WARN_EXISTING_FILE,
WARN_XATTR_WRITE,
WARN_RECORD_SIZE
WARN_RECORD_SIZE,
WARN_FAILED_READ
};
ARGMATCH_VERIFY (warning_args, warning_types);

View File

@@ -1,6 +1,6 @@
/* Support for extended attributes.
Copyright (C) 2006-2014, 2016 Free Software Foundation, Inc.
Copyright (C) 2006-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -246,13 +246,36 @@ xattrs__acls_set (struct tar_stat_info const *st,
acl_free (acl);
}
/* Cleanup textual representation of the ACL in VAL by eliminating tab
characters and comments */
static void
xattrs_acls_cleanup (char *val, size_t *plen)
{
char *p, *q;
p = q = val + strcspn (val, "#\t");
while (*q)
{
if (*q == '\t')
q++;
else if (*q == '#')
{
while (*q != '\n')
q++;
}
else
*p++ = *q++;
}
*plen = p - val;
*p++ = 0;
}
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)))
@@ -262,7 +285,7 @@ xattrs__acls_get_a (int parentfd, const char *file_name,
return;
}
val = acl_to_text (acl, &len);
val = acl_to_text (acl, NULL);
acl_free (acl);
if (!val)
@@ -272,8 +295,7 @@ xattrs__acls_get_a (int parentfd, const char *file_name,
}
*ret_ptr = xstrdup (val);
*ret_len = len;
xattrs_acls_cleanup (*ret_ptr, ret_len);
acl_free (val);
}
@@ -284,7 +306,6 @@ xattrs__acls_get_d (int parentfd, char const *file_name,
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)))
@@ -294,7 +315,7 @@ xattrs__acls_get_d (int parentfd, char const *file_name,
return;
}
val = acl_to_text (acl, &len);
val = acl_to_text (acl, NULL);
acl_free (acl);
if (!val)
@@ -304,8 +325,7 @@ xattrs__acls_get_d (int parentfd, char const *file_name,
}
*ret_ptr = xstrdup (val);
*ret_len = len;
xattrs_acls_cleanup (*ret_ptr, ret_len);
acl_free (val);
}
#endif /* HAVE_POSIX_ACLS */
@@ -336,6 +356,7 @@ acls_one_line (const char *prefix, char delim,
obstack_grow (&stk, prefix, pref_len);
obstack_grow (&stk, aclstring, move);
pos += move + 1;
aclstring += move + 1;
}
@@ -434,8 +455,12 @@ xattrs_clear_setup (void)
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 */
static bool xattrs_masked_out (const char *kw, bool archiving);
/* get xattrs from file given by FILE_NAME or FD (when non-zero)
xattrs are checked against the user supplied include/exclude mask
if no mask is given 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)
@@ -480,8 +505,6 @@ xattrs_xattrs_get (int parentfd, char const *file_name,
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)
@@ -492,7 +515,10 @@ xattrs_xattrs_get (int parentfd, char const *file_name,
}
if (aret != -1)
xheader_xattr_add (st, attr, val, aret);
{
if (!xattrs_masked_out (attr, true))
xheader_xattr_add (st, attr, val, aret);
}
else if (errno != ENOATTR)
call_arg_warn ((fd == 0) ? "lgetxattrat"
: "fgetxattr", file_name);
@@ -735,6 +761,8 @@ xattrs_print (struct tar_stat_info const *st)
{
fprintf (stdlis, " a: ");
acls_one_line ("", ',', st->acls_a_ptr, st->acls_a_len);
if (st->acls_a_len && st->acls_d_len)
fprintf (stdlis, ",");
acls_one_line ("default:", ',', st->acls_d_ptr, st->acls_d_len);
fprintf (stdlis, "\n");
}

View File

@@ -1,6 +1,6 @@
/* Support for extended attributes.
Copyright (C) 2006-2014, 2016 Free Software Foundation, Inc.
Copyright (C) 2006-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,7 +1,6 @@
/* POSIX extended headers for tar.
Copyright (C) 2003-2007, 2009-2010, 2012-2014, 2016 Free Software
Foundation, Inc.
Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -185,6 +184,9 @@ xheader_set_keyword_equal (char *kw, char *eq)
bool global = true;
char *p = eq;
if (eq == kw)
USAGE_ERROR ((0, 0, _("Malformed pax option: %s"), quote (kw)));
if (eq[-1] == ':')
{
p--;
@@ -255,7 +257,7 @@ char *
xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
{
char *buf;
size_t len = strlen (fmt);
size_t len;
char *q;
const char *p;
char *dirp = NULL;
@@ -266,43 +268,51 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
char nbuf[UINTMAX_STRSIZE_BOUND];
char const *nptr = NULL;
for (p = fmt; *p && (p = strchr (p, '%')); )
len = 0;
for (p = fmt; *p; p++)
{
switch (p[1])
if (*p == '%' && p[1])
{
case '%':
len--;
break;
case 'd':
if (st)
switch (*++p)
{
if (!dirp)
dirp = dir_name (st->orig_file_name);
dir = safer_name_suffix (dirp, false, absolute_names_option);
len += strlen (dir) - 2;
case '%':
len++;
break;
case 'd':
if (st)
{
if (!dirp)
dirp = dir_name (st->orig_file_name);
dir = safer_name_suffix (dirp, false, absolute_names_option);
len += strlen (dir);
}
break;
case 'f':
if (st)
{
base = last_component (st->orig_file_name);
len += strlen (base);
}
break;
case 'p':
pptr = umaxtostr (getpid (), pidbuf);
len += pidbuf + sizeof pidbuf - 1 - pptr;
break;
case 'n':
nptr = umaxtostr (n, nbuf);
len += nbuf + sizeof nbuf - 1 - nptr;
break;
default:
len += 2;
}
break;
case 'f':
if (st)
{
base = last_component (st->orig_file_name);
len += strlen (base) - 2;
}
break;
case 'p':
pptr = umaxtostr (getpid (), pidbuf);
len += pidbuf + sizeof pidbuf - 1 - pptr - 2;
break;
case 'n':
nptr = umaxtostr (n, nbuf);
len += nbuf + sizeof nbuf - 1 - nptr - 2;
break;
}
p++;
else
len++;
}
buf = xmalloc (len + 1);
@@ -359,29 +369,46 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
return buf;
}
/* Table of templates for the names of POSIX extended headers.
Indexed by the the type of the header (per-file or global)
and POSIX compliance mode (0 or q depending on whether
POSIXLY_CORRECT environment variable is set. */
static const char *header_template[][2] = {
/* Individual header templates: */
{ "%d/PaxHeaders/%f", "%d/PaxHeaders.%p/%f" },
/* Global header templates: */
{ "/GlobalHead.%n", "/GlobalHead.%p.%n" }
};
/* Indices to the above table */
enum {
pax_file_header,
pax_global_header
};
/* Return the name for the POSIX extended header T */
#define HEADER_TEMPLATE(t) header_template[t][posixly_correct]
char *
xheader_xhdr_name (struct tar_stat_info *st)
{
if (!exthdr_name)
assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
assign_string (&exthdr_name, HEADER_TEMPLATE (pax_file_header));
return xheader_format_name (st, exthdr_name, 0);
}
#define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
char *
xheader_ghdr_name (void)
{
if (!globexthdr_name)
{
size_t len;
const char *global_header_template = HEADER_TEMPLATE (pax_global_header);
const char *tmp = getenv ("TMPDIR");
if (!tmp)
tmp = "/tmp";
len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */
len = strlen (tmp) + strlen (global_header_template) + 1;
globexthdr_name = xmalloc (len);
strcpy(globexthdr_name, tmp);
strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
strcat(globexthdr_name, global_header_template);
}
return xheader_format_name (NULL, globexthdr_name, global_header_count + 1);
@@ -458,6 +485,14 @@ xheader_write_global (struct xheader *xhdr)
}
}
/* Forbid modifications of the global extended header */
void
xheader_forbid_global (void)
{
if (keyword_global_override_list)
USAGE_ERROR ((0, 0, _("can't update global extended header record")));
}
void
xheader_xattr_init (struct tar_stat_info *st)
{
@@ -1290,15 +1325,33 @@ path_coder (struct tar_stat_info const *st, char const *keyword,
code_string (st->file_name, keyword, xhdr);
}
static void
raw_path_decoder (struct tar_stat_info *st, char const *arg)
{
decode_string (&st->orig_file_name, arg);
decode_string (&st->file_name, arg);
st->had_trailing_slash = strip_trailing_slashes (st->file_name);
}
static void
path_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&st->orig_file_name, arg);
decode_string (&st->file_name, arg);
st->had_trailing_slash = strip_trailing_slashes (st->file_name);
if (! st->sparse_name_done)
raw_path_decoder (st, arg);
}
static void
sparse_path_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
st->sparse_name_done = true;
raw_path_decoder (st, arg);
}
static void
@@ -1371,7 +1424,7 @@ sparse_size_decoder (struct tar_stat_info *st,
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
{
st->real_size_set = 1;
st->real_size_set = true;
st->real_size = u;
}
}
@@ -1730,7 +1783,7 @@ struct xhdr_tab const xhdr_tab[] = {
{ "uname", uname_coder, uname_decoder, 0, false },
/* Sparse file handling */
{ "GNU.sparse.name", path_coder, path_decoder,
{ "GNU.sparse.name", path_coder, sparse_path_decoder,
XHDR_PROTECTED, false },
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
XHDR_PROTECTED, false },

1
tests/.gitignore vendored
View File

@@ -12,3 +12,4 @@ download
ttyemu
checkseekhole
ckmtime
/compress-*.at

View File

@@ -1,6 +1,6 @@
# Makefile for GNU tar regression tests.
# Copyright 1996-1997, 1999-2001, 2003-2007, 2009, 2012-2015 Free Software
# Copyright 1996-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -17,9 +17,13 @@
# 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
EXTRA_DIST = $(TESTSUITE_AT) \
testsuite package.m4 star/README star/quicktest.sh \
compress.m4
DISTCLEANFILES = atconfig $(check_SCRIPTS)
MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
CLEANFILES =
## ------------ ##
## package.m4. ##
@@ -42,6 +46,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## ------------ ##
TESTSUITE_AT = \
testsuite.at\
compress.m4\
T-cd.at\
T-dir00.at\
T-dir01.at\
@@ -54,7 +60,7 @@ TESTSUITE_AT = \
T-nonl.at\
T-mult.at\
T-nest.at\
testsuite.at\
add-file.at\
append.at\
append01.at\
append02.at\
@@ -65,11 +71,17 @@ TESTSUITE_AT = \
chtype.at\
comprec.at\
comperr.at\
checkpoint/defaults.at\
checkpoint/interval.at\
checkpoint/dot.at\
checkpoint/dot-compat.at\
checkpoint/dot-int.at\
delete01.at\
delete02.at\
delete03.at\
delete04.at\
delete05.at\
difflink.at\
exclude.at\
exclude01.at\
exclude02.at\
@@ -106,8 +118,15 @@ TESTSUITE_AT = \
extrac17.at\
extrac18.at\
extrac19.at\
extrac20.at\
extrac21.at\
extrac22.at\
extrac23.at\
extrac24.at\
filerem01.at\
filerem02.at\
dirrem01.at\
dirrem02.at\
gzip.at\
grow.at\
incremental.at\
@@ -153,6 +172,7 @@ TESTSUITE_AT = \
multiv07.at\
multiv08.at\
multiv09.at\
multiv10.at\
numeric.at\
old.at\
onetop01.at\
@@ -166,8 +186,12 @@ TESTSUITE_AT = \
opcomp04.at\
opcomp05.at\
opcomp06.at\
positional01.at\
positional02.at\
positional03.at\
options.at\
options02.at\
options03.at\
owner.at\
pipe.at\
recurse.at\
@@ -177,6 +201,7 @@ TESTSUITE_AT = \
rename03.at\
rename04.at\
rename05.at\
rename06.at\
remfiles01.at\
remfiles02.at\
remfiles03.at\
@@ -211,17 +236,22 @@ TESTSUITE_AT = \
sparse04.at\
sparse05.at\
sparse06.at\
sparse07.at\
sparsemv.at\
sparsemvp.at\
spmvp00.at\
spmvp01.at\
spmvp10.at\
sptrcreat.at\
sptrdiff00.at\
sptrdiff01.at\
time01.at\
time02.at\
truncate.at\
update.at\
update01.at\
update02.at\
update03.at\
volsize.at\
volume.at\
verbose.at\
@@ -230,6 +260,7 @@ TESTSUITE_AT = \
xform-h.at\
xform01.at\
xform02.at\
xform03.at\
star/gtarfail.at\
star/gtarfail2.at\
star/multi-fail.at\
@@ -241,6 +272,8 @@ TESTSUITE_AT = \
xattr03.at\
xattr04.at\
xattr05.at\
xattr06.at\
xattr07.at\
acls01.at\
acls02.at\
acls03.at\

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
@@ -19,7 +19,7 @@
# 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_KEYWORDS([files-from T-cd chdir])
AT_TAR_CHECK([
AT_SORT_PREREQ

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2014, 2016 Free Software Foundation, Inc.
# Copyright 2014-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2014, 2016 Free Software Foundation, Inc.
# Copyright 2014-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright 2006-2007, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
@@ -29,9 +29,8 @@ 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
printf c > 1.nonl
printf 'd\ne' > 2.nonl
touch a b c d e
AT_DATA([filelist],[a
b
@@ -59,4 +58,3 @@ c
[],[],[],[ustar])
AT_CLEANUP

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright 2006-2007, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,5 +1,5 @@
# This file is part of test suite for GNU tar. -*- Autotest -*-
# Copyright 2015-2016 Free Software Foundation, Inc.
# Copyright 2015-2021 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
@@ -25,11 +25,13 @@ AT_TAR_CHECK([
AT_DATA([file-list],[a
-b
--c d
:\\.jpg
])
genfile -f a
genfile -f -b
genfile -f '--c d'
genfile -f ':\\.jpg'
cat file-list | tr '\n' '\0' | tar -c -f archive -v --null -T -
],
@@ -37,6 +39,7 @@ cat file-list | tr '\n' '\0' | tar -c -f archive -v --null -T -
[a
-b
--c d
:\\\\.jpg
],
[],[],[],[ustar]) # Testing one format is enough

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright 2015-2016 Free Software Foundation, Inc.
# Copyright 2015-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2011, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2011-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2011, 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2011-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -23,7 +23,7 @@
# This is basic test for acl support.
AT_SETUP([acls: work with -C])
AT_KEYWORDS([xattrs acls acls02])
AT_KEYWORDS([xattrs acls acls02 chdir])
AT_TAR_CHECK([
AT_XATTRS_UTILS_PREREQ

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014, 2016 Free Software Foundation, Inc.
# Copyright 2013-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -28,7 +28,7 @@
# http://www.mail-archive.com/bug-tar@gnu.org/msg04355.html
AT_SETUP([acls: default ACLs])
AT_KEYWORDS([xattrs acls acls03])
AT_KEYWORDS([xattrs acls acls03 chdir])
m4_define([ACL_LISTDIR], [
cd $1

67
tests/add-file.at Normal file
View File

@@ -0,0 +1,67 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2016-2021 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([The --add-file option])
AT_KEYWORDS([add-file])
# Version 1.29 would give "tar: Cowardly refusing to create an empty archive"
# if only --add-file arguments were used, and would give "tar: unhandled
# positional option 0" when handling the --add-file if at least one file was
# also given normally.
#
# Reported by: James Clarke <jrtc27@jrtc27.com>
# References: <20161112000246.77013-1-jrtc27@jrtc27.com>,
# http://lists.gnu.org/archive/html/bug-tar/2016-11/msg00013.html
AT_TAR_CHECK([
genfile --file -File
genfile --file foo
genfile --file bar
echo 1:
tar -cvf arc.tar --add-file foo --add-file -File
echo 2:
tar -cvf arc.tar foo --add-file -File bar
AT_DATA([input],[foo
--add-file=-File
bar
])
echo 3:
tar -cvf arc.tar -T input
],
[0],
[1:
foo
-File
2:
foo
-File
bar
3:
foo
-File
bar
])
AT_CLEANUP

View File

@@ -1,8 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright 2004, 2006-2007, 2013-2014, 2016 Free Software Foundation,
# Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

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