211 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
Sergey Poznyakoff
20b55f0679 Version 1.29 2016-05-16 11:51:12 +03:00
Sergey Poznyakoff
35b292ac4b Minor fix
* src/names.c (new_name): rename to make_file_name. All uses changed.
2016-05-16 11:50:19 +03:00
Sergey Poznyakoff
61cd3fd268 Fix argument handling when running external commands.
* src/system.c (xexec): Use sh -c to run the command.  This fixed
bug introduced by 7b5e80396 (tar 1.27)
* doc/tar.texi: Fix checkpoint examples: (1) $TAR_FILENAME
is not available when creating archive and (2) --checkpoint
can't be used as abbreviation of --checkpoint-action
2016-04-14 11:51:38 +03:00
Sergey Poznyakoff
3010818f36 Remove iotty test
The auxiliary utility ttyemu proved to be unreliable.  Given existing
differences between pty implementations and termios ioctls on various
platforms, writing it in a portable way requires effort disproportional
to its actual purpose.

* configure.ac: Remove check for grantpt
* gnulib.modules: Remove posix_openpt, ptsname, and unlockpt
* tests/Makefile.am (TESTSUITE_AT): Remove iotty.at
(check_PROGRAMS): Remove ttyemu.
* tests/testsuite.at: Remove iotty.at
* tests/iotty.at: Remove.
* tests/ttyemu.c: Remove.
2016-04-06 08:34:55 +03:00
Pavel Raiskup
733e2741b1 xattrs: fix build on Darwin
Be careful to define HAVE_XATTRS when not all needed xattr-related
functions are properly defined either in libc or libattr.

Reported independently by Denis Excoffier and Dominyk Tille.

* acinclude.m4 (TAR_HEADERS_ATTR_XATTR_H): Check for each xattr
function separately.  Don't AC_CHECK_LIB (LIBS is filled by
AC_SEARCH_LIBS when necessary).
* src/Makefile.am: The LDADD -lattr was redundant.
2016-04-05 17:55:19 +03:00
Sergey Poznyakoff
195a25316c Remove --preserve option
* src/tar.c: Remove --preserve option
* NEWS: Update.
* doc/tar.texi: Update.
2016-03-24 08:39:52 +02:00
Sergey Poznyakoff
74e3b497c4 Fix testcase
* tests/time02.at: Sort tar -d output
2016-03-24 08:38:38 +02:00
Sergey Poznyakoff
29f652871e Update THANKS file 2016-03-24 07:30:16 +02:00
Jeremy Bobbio
13d04fe6ae New option --clamp-mtime
The new `--clamp-mtime` option will change the behavior of `--mtime` to only
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, except for
files modified during the build process. In that case, using a reference
(and thus reproducible) timestamps for the latter is good enough. See
<https://wiki.debian.org/ReproducibleBuilds> for more information.

Patch submitted by Jeremy Bobbio and
Daniel Kahn Gillmor <dkg@fifthhorseman.net>

* doc/tar.1: Document --clamp-mtime
* doc/tar.texi: Likewise.

* src/common.h (set_mtime_option_mode): New enum
(set_mtime_option): Change type to enum set_mtime_option_mode.
(NEWER_OPTION_INITIALIZED): Rename to NEWER_OPTION_INITIALIZED.
* src/create.c (start_header): Set mtime depending on set_mtime_option.
* src/tar.c (options,parse_opt): New option --clamp-mtime
(decode_options): Initialize mtime_option

* tests/time02.at: New testcase.
* tests/Makefile.am: Add new testcase
* tests/testsuite.at: Likewise.
2016-03-24 07:26:27 +02:00
Sergey Poznyakoff
8d31493c99 Acknowledgments
* THANKS: Add Dagobert Michelsen
2016-03-21 20:46:19 +02:00
Sergey Poznyakoff
752b447f3e Fix the testsuite
* tests/sparse06.at: Don't use timeout: depending on the filesystem
mounted, current LA and lots of other factors, creation of archive can
take much more time than the expected 2 seconds.
2016-03-21 20:33:26 +02:00
Sergey Poznyakoff
a3aa7003ea Fix ckmtime
* gnulib.modules: Use timespec-sub
* tests/ckmtime.c: Use second resolution.
2016-03-21 13:35:32 +02:00
Sergey Poznyakoff
143dc63ffa Fix the testsuite
* tests/sparse05.at: Use autom4te magic to generate mapfile,
instead of the shell command seq, which is not always available.
* tests/listed03.at: Skip the test if xgetcwd fails.
* tests/ckmtime.c: New file.
* tests/Makefile.am: Build ckmtime
* tests/testsuite.at (AT_CHECK_TIMESTAMP): Check whether newly created
files have timestamps consistent with the creation time.  Skip the test
if not.
* tests/incr01.at: Use AT_CHECK_TIMESTAMP
* tests/incr02.at: Likewise.
* tests/incr03.at: Likewise.
* tests/incr04.at: Likewise.
* tests/incr05.at: Likewise.
* tests/incr06.at: Likewise.
* tests/incr07.at: Likewise.
* tests/incr08.at: Likewise.
* tests/incr09.at: Likewise.
* tests/incr10.at: Likewise.
* tests/incr11.at: Likewise.
* tests/incremental.at: Likewise.
* tests/listed01.at: Likewise.
* tests/listed02.at: Likewise.
* tests/listed04.at: Likewise.
* tests/listed05.at: Likewise.
2016-03-20 23:11:27 +02:00
Sergey Poznyakoff
c0fb0740fa Testsuite fixes.
* paxutils: Update.
* src/unlink.c (flush_deferred_unlinks): OpenSolaris sets EEXIST
instead of ENOTEMPTY if trying to remove a non-empty directory.
* tests/numeric.at: Avoid using awk -v: some older awks don't support
that option.  Also fix environment variable usage.
* tests/onetop05.at: Skip test if unable to set initial directory
mode bits.
* tests/sparse06.at: Use --quiet option.
2016-03-18 22:18:58 +02:00
Sergey Poznyakoff
6ac0dd1d73 Revise docs 2016-03-18 14:27:27 +02:00
Sergey Poznyakoff
160fb9abd2 Fix build with --enable-gcc-warnings
* configure.ac: Disable stack-protector warnings
2016-03-18 13:08:39 +02:00
Sergey Poznyakoff
f6ad0e4af2 Improve testsuite
* tests/iotty.at: Skip test if ttyemu can't do its job
2016-03-17 14:22:35 +02:00
Sergey Poznyakoff
e4b246c14a Document xattrs, ACL and SELinux-related options.
* doc/tar.1: Document all options.
* doc/tar.texi: Likewise.
2016-03-16 20:08:00 +02:00
Sergey Poznyakoff
2a7c84b4a9 Fix appending to archive with changed blocking factor.
* src/buffer.c (flush_archive): If previous reading attempt resulted
in short read, correctly use the remaining record space.
(backspace_output): Fix position calculation (still has to be
improved).

* tests/append05.at: New test case.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Likewise.
2016-03-15 00:02:40 +02:00
Sergey Poznyakoff
da7845c656 Fix coredump on parsing invalid traditional option
* src/tar.c (find_argp_option): Fix loop termination condition.
2016-03-14 13:13:04 +02:00
Sergey Poznyakoff
8980ecd62d Update copyright years 2016-01-20 11:29:17 +02:00
Sergey Poznyakoff
63f2e969dd Allow escaped delimiters in transform expressions.
Patch provided by Charles McGarvey and Flavio Poletti.

* src/transform.c (parse_transform_expr): Allow escaped delimiters
in transform expressions.
* tests/xform02.at: New test case.
* tests/Makefile.am: Add xform02.at
* tests/testsuite.at: Include xform02.at
* THANKS: Update.
2016-01-20 11:16:02 +02:00
Sergey Poznyakoff
445293654d Fix eventual dereference of uninitialized pointer.
* src/exclist.c (hg_initfn): Initialize hgopt.
2015-12-17 16:04:40 +02:00
Pavel Raiskup
b5f581e637 sparse: fix use of indeterminate value
* src/xheader.c (sparse_map_decoder): Move 'e' up from loop-block.
2015-12-17 16:01:18 +02:00
Sergey Poznyakoff
0f26331b17 fix a typo
* doc/tar.texi (Incremental Dumps): Add missing --file to the
'--list' example.
2015-12-11 15:21:04 +02:00
Sergey Poznyakoff
196fef9b40 Minor fixes.
* doc/tar.texi: Document position-sensitive options in a
separate subsection.
* src/names.c (names_argp,names_argp_children): Explicitly initialize
all members.
2015-12-11 14:19:44 +02:00
Sergey Poznyakoff
68dd249987 Minor fix 2015-12-11 01:10:43 +02:00
Sergey Poznyakoff
4cf2af4500 Fix handling of filename-selection options.
Filename-selection options are --wildcards, --recursive, etc. (see
names.c for a complete list).  These options are position-sensitive,
i.e. each such option affects all filenames and filename-selection
options that appear after it until eventually cancelled by a
corresponding counterpart option.

These options can appear in "file-from" file lists, which means that
they cannot be handled right away, but instead should be put on
the "name_elt" list and processed sequentionally, as file name arguments
are.

* src/common.h (warn_regex_usage): Remove.
(name_add_name): Change signature.
(name_add_dir, name_add_file): Remove prototypes.
* src/names.c (name_add_option, name_add_dir)
(name_add_file): Static functions.
(names_options, is_file_selection_option, names_parse_opt): Static functions.
(names_argp_children): New variable.
(NELT_NAME, NELT_CHDIR)
(NELT_FILE, NELT_NOOP): Redefine as enum nelt_type.
(NELT_FMASK): Remove.
(NELT_OPTION): New constant.
(name_elt) <type>: Change type.
<v.opt>: New member.
(name_elt_alloc_matflags): Remove.
(name_add_name): Take one argument.
(name_add_option): New static function.
(name_add_file): Take one argument.
(read_next_name): Use filename_terminator and
verbatim_files_from_option to initialize file.term and file.verbatim.
* src/tar.c: Move handling of filename-selection options to names.c

* tests/T-dir00.at: Fix typo.
* tests/T-recurse.at: Remove expected failure.
2015-12-11 00:50:23 +02:00
Pavel Raiskup
cadc43ace5 better test --{,no-}recursion options
* tests/recurs02.at: Also test --list mode.
* tests/T-recurse.at: New test case.  Test that -T option works
correctly together with --{,no-}recursion.
* tests/Makefile.am: Mention new test T-recurse.at.
* tests/testsuite.at: Likewise.
2015-12-10 14:55:34 +02:00
Pavel Raiskup
239441b5df Bugfix
* src/buffer.c (try_new_volume): Warn if user supplied malformed
tar archive.
Consistently use WARN (instead of ERROR) when reporting.
2015-12-06 22:14:23 +02:00
Sergey Poznyakoff
0a93c16c62 Fix segfault when extracting from a multi-volume archive.
Fix suggested by Pavel Raiskup.

* src/buffer.c (try_new_volume): Fix dereferencing NULL pointer.
* tests/multiv09.at: New testcase.
* tests/Makefile.am: Add new testcase.
* tests/testsuite.at: Likewise.
2015-12-06 22:02:16 +02:00
Sergey Poznyakoff
5dd490e7f1 Fix NEWS 2015-12-06 21:20:48 +02:00
Pavel Raiskup
68e9ab4966 numeric-owner: print big UID/GID correctly
* src/list.c (simple_print_header): Do not parse ustar header
for UID/GID again (tar_stat_info has already been correctly
filled with respect to possible uid/gid extended headers).
* tests/numeric.at: New testcase for --numeric-owner option.
* tests/Makefile.am: Add new testcase.
* tests/testsuite.at: Likewise.
2015-12-06 21:18:51 +02:00
Sergey Poznyakoff
b684326e69 Use SEEK_HOLE for hole detection
Based on patch by Pavel Raiskup.

Use SEEK_HOLE/SEEK_DATA feature of lseek on systems that support
it.  This can make archiving of sparse files much faster.

Implement the --hole-detection option to allow users to select
hole-detection method.

* src/common.h (hole_detection_method): New enum.
(hole_detection): New global.
* src/sparse.c  (sparse_scan_file_wholesparse): New function as a
method for detecting sparse files without any data.
(sparse_scan_file_raw): Rename from sparse_scan_file; with edits.
(sparse_scan_file_seek): New function.
(sparse_scan_file): Reimplement function.
* src/tar.c: New option --hole-detection

* tests/checkseekhole.c: New file.
* tests/.gitignore: Mention two test binaries.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at (AT_SEEKHOLE_PREREQ): New macro.
Include sparse06.at.
* tests/sparse06.at: New test case.
* tests/sparse02.at: Force raw hole-detection method.
* tests/sparsemv.at: Likewise.
* tests/sparsemvp.at: Likewise.

* doc/tar.1: Document --hole-detection option.
* doc/tar.texi: Document hole-detection algorithms and
command-line options.
* NEWS: Document hole-detection.
2015-12-06 00:14:55 +02:00
Sergey Poznyakoff
589ba77faf Catch compressor execution errors.
* src/misc.c (write_fatal_details): Move to buffer.c
* src/buffer.c (write_fatal_details): Close the archive and wait for
the compressor program to terminate in order to catch eventual execution
errors.
* src/system.c (sys_child_open_for_compress): Ignore SIGPIPE so tar will
not silently terminate when unable to write to the compressor.
* tests/comperr.at: New file.
* tests/Makefile.am: Add comperr.at
* tests/testsuite.at: Include comperr.at
2015-12-05 16:54:26 +02:00
Sergey Poznyakoff
6ea9e62bb3 Upgrade paxutils 2015-12-05 08:48:03 +02:00
Sergey Poznyakoff
d02c81df15 Fix extraction from concatenated incremental archives with renamed directories.
Complements 15c02c2b.

* src/extract.c (delayed_set_stat): Change type of file_name.
(delay_set_stat): Allocate file_name member.
(free_delayed_set_stat): Free file_name.
(fixup_delayed_set_stat): New function.
(rename_directory): Call fixup_delayed_set_stat on success.

* tests/incr11.at: New testcase.
* tests/incr10.at: Improve description.
* tests/Makefile.am: Add incr11.at
* tests/testsuite.at: Add incr11.at
2015-11-29 21:11:08 +02:00
Sergey Poznyakoff
e426787454 Fix bug in the inplementation of --one-top-level.
When extracting an archive that contains './' with the --one-top-level option,
the mode and ownership of '.' would be incorrectly applied to the current
working directory, instead of the requested top-level directory.

* src/list.c (enforce_one_top_level): Map '.' to the top-level
directory.
* tests/Makefile.am: Add onetop05.at
* tests/testsuite.at: Include onetop05.at.
* tests/onetop05.at: New file.
* tests/onetop01.at: Fix keywords.
* tests/onetop02.at: Likewise.
* tests/onetop03.at: Likewise.
* tests/onetop04.at: Likewise.
2015-11-21 21:56:49 +02:00
Sergey Poznyakoff
e6fcc73efa Work around unlinkat bug on FreeBSD and GNU/Hurd
* src/unlink.c (dunlink_insert): New function.
(flush_deferred_unlinks): Skip cwds and nonempty directories
at the first pass.  If force is requested, run a second pass
removing them.
(queue_deferred_unlink): Make sure current working directory
entries are sorted in descending order by the value of dir_idx.
This makes sure they will be removed in right order, which works
around unlinkat bug on FreeBSD and GNU/Hurd.
* tests/remfiles08b.at: Remove expected failure.
* tests/remfiles09b.at: Likewise.
2015-11-11 13:01:45 +02:00
Sergey Poznyakoff
6167c23e22 Fix coredump on FreeBSD when TAR_OPTIONS is set
* src/tar.c (parse_default_options): Use program_name instead of
program_invocation_short_name.  On some systems the latter is NULL when
the function is called, which causes coredumps.
(tar_set_quoting_style): Likewise.
* src/names.c: Likewise.
2015-11-10 18:25:47 +02:00
Sergey Poznyakoff
5e2a1d5b38 Use sort in T-dir tests. 2015-11-02 13:54:26 +02:00
Sergey Poznyakoff
4aebc943bb Fix distclean in tests/
* tests/Makefile.am: Remove "download"
2015-11-02 13:19:36 +02:00
Sergey Poznyakoff
1a615a41f5 New options: --owner-map and --group-map.
* NEWS: Update.
* doc/tar.1: Document --owner-map and --group-map
* doc/tar.texi: Likewise.

* src/map.c: New file.
* src/Makefile.am: Add map.c
* src/common.h (owner_map_read, owner_map_translate)
(group_map_read, group_map_translate): New protos.
* src/create.c (start_header): Use owner_map_translate
and group_map_translate to optionally translate user/group names/ids.
* src/tar.c: New options --owner-map and --group-map.

* tests/map.at: New file.
* tests/Makefile.am: Add map.at
* tests/testsuite.at: Include map.at.
2015-11-02 13:00:39 +02:00
Kir Kolyshkin
cdf41c383f doc: fix font and spelling typos
* doc/tar.1: Fix font and spelling typos in man page.
Copyright-paperwork-exempt: yes
2015-09-24 09:22:51 -07:00
Paul Eggert
a65086c71c Fix problems caught by static checking
Most of these can be caught by configuring with --enable-gcc-warnings.
Problem reported by Pavel Raiskup in:
http://lists.gnu.org/archive/html/bug-tar/2015-09/msg00001.html
* src/buffer.c (format_total_stats):
Prefer pointer to const when it’s OK to use const.
(default_total_format): Now const.
* src/buffer.c (default_total_format):
* src/exclist.c (excfile_head, excfile_tail, vcs_ignore_files):
* src/misc.c (namebuf_add_dir, namebuf_finish):
* src/tar.c (verbatim_files_from_option, option_set_in_cl)
(optloc_eq, set_old_files_option):
Now static.
* src/common.h: Adjust to match the other changes described here.
* src/exclist.c (info_cleanup_exclist):
* src/tar.c (argp_program_version, argp_program_bug_address):
Remove; unused.
(parse_default_options): Define via prototype instead of old style.
(parse_default_options, decode_options):
Fill out incomplete initializers.
2015-09-24 08:32:15 -07:00
Sergey Poznyakoff
ae23a57d70 Improve option sanity checking
Any two conflicting options are reported only if they both occur in
the command line.  Otherwise, options defined in the command line
silently override those set in the TAR_OPTIONS environment variable.

* src/common.h (option_source): New enum.
(option_locus): New struct.
* src/names.c (name_elt): New member: line.
(name_add_file): Initialize line.
(read_name_from_file): Keep track of input line number for diagnostic
purposes.
(handle_option): Take a pointer to struct name_elt as 2nd parameter;
pass locus info to more_options().
* src/tar.c (tar_args): New member: loc.
(option_class): New enum.
(optloc_save,optloc_lookup)
(option_set_in_cl,optloc_eq): New functions.
(set_use_compress_program_option): Take into account option location.
(set_old_files_option): New function.
(parse_opt): Keep track of option locations.
(more_options): Improve error reporting.
(parse_default_options): New function.
(decode_options): Parse TAR_OPTION and command line separately.
Options from the latter silently override those from the former.

* lib/prepargs.c: Remove.
* lib/prepargs.h: Remove.
* lib/Makefile.am: Update.
2015-08-31 08:37:46 +03:00
Sergey Poznyakoff
c440a92627 Improve check-full
* tests/atlocal.in: Download external archives to $abs_builddir/download.
(tarball_prereq): Create destination directory if necessary.
* tests/.gitignore: Add download
2015-08-24 13:05:52 +03:00
Sergey Poznyakoff
aa9676dcad Fix check-full
* tests/atlocal.in (TAR_DATA_URL): Berlios is dead.  Get
test archives from gnu.org.ua
2015-08-24 12:50:49 +03:00
Sergey Poznyakoff
6cb94e37a9 Include gnulib and paxutils as submodules.
* .gitmodules: New file.
* README-alpha: Update.
* README-hacking: Update.
* bootstrap: Install slightly modified version from the gnulib repo.
* bootstrap.conf: Add paxutils-related stuff.
* .gitignore: Update.
* doc/.gitignore: Update.
* po/.gitignore: Update.
* gnu/Makefile.am
2015-08-24 11:52:14 +03:00
Sergey Poznyakoff
232a7258c3 Update docs.
* doc/tar.1: Document --verbatim-files-from option.
2015-08-24 09:29:04 +03:00
Sergey Poznyakoff
429bd311b7 Add missing VCS files to --exclude-vcs list
* src/tar.c (vcs_file_table): Add .gitmodules and .gitattributes
* doc/tar.texi: Update.
2015-08-20 17:52:20 +03:00
Sergey Poznyakoff
eb621c67cf Options to control option handling in file lists.
The --verbatim-files-from option disables option handling in
file lists.  The --no-verbatim-files-from reverts its effect.

The --null option implies --verbatim-files-from.  This restores
the documented behavior, broken by 26538c9b.

* src/common.h (verbatim_files_from_option): New global.
* src/names.c (name_elt): New member: file.verbatim
(name_add_file): Take 'verbatim' state as its third parameter.
(read_next_name): Don't call handle_option if file.verbatim
is set.
* src/tar.c: New options --verbatim-files-from and
--no-verbatim-files-from.

* doc/tar.texi: Document --verbatim-files-from and
--no-verbatim-files-from options.
* NEWS: Update.
* configure.ac: Version 1.28.90

* tests/T-null2.at: New testcase.
* tests/Makefile.am: Update.
* tests/testsuite.at: Update.
2015-08-03 16:47:22 +03:00
Anders Jonsson
21f86195b7 Fix typos (preceeded etc.)
Copyright-paperwork-exempt: yes
2015-07-25 08:47:25 -07:00
Paul Eggert
fe3b106cb3 tar: fix symlink race and symlink transform bug
Problem reported by Tobias Stoeckmann in:
http://lists.gnu.org/archive/html/bug-tar/2015-07/msg00004.html
* gnulib.modules: Add areadlinkat-with-size.
* src/create.c: Include areadlink.h.
(dump_file0): Use areadlinkat_with_size, rather than trying to do
it by hand, incorrectly.  This also avoids assumption that
the symlink contents fit on the stack.  Also, use the transformed
link name, not the original link name, when deciding whether the
name is long enough to require writing a long link.
2015-07-13 09:53:56 -07:00
Paul Eggert
3828942550 tar: port -d to longer symlinks
* src/compare.c (diff_symlink):
Don't use alloca on symlink length; it might be too big for the stack.
Don't assume that readlinkat's return value fits in 'int'.
Prefer memcmp to strncmp where either will do.
2015-07-13 09:53:56 -07:00
Paul Eggert
d95457e007 tar: port to recent gnulib
* gnulib.modules: Remove 'acl' and add 'file-has-acl'.
2015-07-13 09:53:56 -07:00
Paul Eggert
da06935f6e tar: pacify GCC 5.1 -Wformat-signedness
* lib/wordsplit.c (struct wordsplit_node.flags):
Now unsigned, so that 'printf ("%x", p->flags)' doesn't provoke GCC.
* src/incremen.c (read_num, dumpdir_ok):
Don't printf an int with %x or %o.
2015-07-13 09:53:55 -07:00
Sergey Poznyakoff
15c02c2b9d Fix extraction from concatenated incremental archives.
* src/common.h (remove_delayed_set_stat): New proto.
* src/extract.c (free_delayed_set_stat)
(remove_delayed_set_stat): New function.
(apply_nonancestor_delayed_set_stat): Use free_delayed_set_stat.
* src/misc.c (safer_rmdir): Remove delayed_set_stat entry
corresponding to the removed directory.
* tests/incr10.at: New test case.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Likewise.
2015-04-16 13:02:10 +03:00
Sergey Poznyakoff
0c4aa85e6c Fix make installcheck
Make installcheck would fail unless make check had been run before it.
Reported by Erik Brangs <erik.brangs@gmx.de>

* tests/Makefile.am (installcheck-local): Depend on $(check_PROGRAMS)
2015-04-10 11:35:44 +03:00
Paul Eggert
731b7b07de tar: don't assume GZIP
* Makefile.am (dist-hook): Port to gzip implementations that
warn about nontrivial settings in the GZIP environment var.
2015-03-17 22:56:01 -07:00
Paul Eggert
4eb1484dce tar: don't suggest GZIP
* doc/tar.texi (gzip): Don't suggest using the GZIP environment
variable, as it will be deprecated in the next gzip release.
2015-03-17 10:46:51 -07:00
Sergey Poznyakoff
1847ec67ce Improve compression format recognition
Some comressed archives can pass the checksum test, which makes tar
treat them as uncompressed archives.

* src/buffer.c (check_compressed_archive): Test the checksum only
if the block we read looks like a valid tar header (i.e. has
a magic string).
2015-02-19 17:00:58 +02:00
Paul Eggert
9c2b57232e tar: port xattr-at.c to Solaris 10
* lib/xattr-at.c (setxattrat, lsetxattrat, getxattrat, lgetxattrat)
(listxattrat, llistxattrat): Compile only if HAVE_XATTRS, so that
the code doesn't call functions that are not declared.
2015-01-05 20:24:42 -08:00
Paul Eggert
55fb2fc38f tar: port wordsplit attribute to Sun C
Reported by Ted Carr in:
http://lists.gnu.org/archive/html/bug-tar/2015-01/msg00002.html
* lib/wordsplit.h (__WORDSPLIT_ATTRIBUTE_FORMAT):
New macro, taken from Gnulib.
(struct wordsplit): Use it.
* lib/wordsplit.c (_wsplt_error): Use it.
2015-01-05 20:09:09 -08:00
Sergey Poznyakoff
5a9ac8312e Silent a cc warning
* src/xheader.c (xheader_string_end): Make sure pointer
arithmetics applies on char*.
2014-12-17 08:37:14 +02:00
Paul Eggert
7bf812579c tar: port ISFOUND, WASFOUND to C89
Problem reported by Romano Maspero in:
http://lists.gnu.org/archive/html/bug-tar/2014-12/msg00010.html
* src/common.h (ISFOUND, WASFOUND): Port to C89.
2014-12-11 19:02:43 -08:00
Sergey Poznyakoff
1209e0ebff Fix tar -c -l file file
When the same file is added several times to the archive, count
correctly the number of hard links.  See also 37ddfb0b.

* src/create.c (dump_hard_link): Don't decrease nlink if it is 0.
* tests/link04.at: Test -cl options.
2014-12-10 04:34:02 +02:00
Sergey Poznyakoff
e7b6f8e3ae Honor the pax-option overrides when creating archive.
Changes proposed by Denis Excoffier.

* NEWS: Fix typos.
* doc/tar.texi: Fix typos.  Improve recipe for creation of binary
equivalent archives.
* src/create.c (write_extended): Use the value of the
--mtime option (if specified) as the default for exthdr.mtime.
* src/xheader.c (xheader_store): Create the header if at least
one override is supplied in --pax-option.
2014-11-07 13:15:54 +02:00
Sergey Poznyakoff
586a6263e9 Add testcase for the previous commit.
* tests/sparse05.at: New file.
* tests/Makefile.am: Add sparse05.at
* tests/testsuite.at: Include sparse05.at
2014-11-07 11:47:44 +02:00
Pavel Raiskup
ec94fbdf45 Fix bug in sparse file listing
List posix archives containing sparse files >8GB correctly and do not fail.
This fixes also bug in format of listing for sparse files >8GB - now the
real size is printed instead of the effective one (this is not strictly
posix format related).

* src/list.c: Remove redundant assignment.
* src/tar.h: Add new 'real_size' and 'real_size_set' fields in
  tar_stat_info struct.
* src/xheader.c: Correctly handle (especially sparse) file sizes directly in
  xheader_decode().
2014-11-07 10:21:41 +02:00
Sergey Poznyakoff
c48f4e8f6c Fix a typo 2014-10-15 14:20:07 +03:00
Sergey Poznyakoff
e7c99a4dd1 Fix README
Remove the reference to PORTS
2014-10-01 23:19:02 +03:00
Sergey Poznyakoff
e9ddc08da0 Bugfixes.
* doc/tar.1: Fix typo in font spec.
* src/tar.c (sort_mode_arg, sort_mode_flag): Protect "inode"
(SAVEDIR_SORT_INODE) with D_INO_IN_DIRENT
2014-09-25 00:22:16 +03:00
Sergey Poznyakoff
163e96a0e6 Bugfix: entries read from the -T file did not get proper matching_flag.
* src/common.h (name_add_file): Change signature.
* src/names.c (name_elt_alloc_matflags): New function.
(name_add_name): Use name_elt_alloc_matflags.
(name_add_file): Take matching flags as third argument.
(read_next_name): Remove trailing slashes.
* src/tar.c (parse_opt): Pass matching_flags to name_add_file.

* tests/T-dir00.at: New file.
* tests/T-dir01.at: New file.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
2014-09-18 23:01:22 +03:00
Sergey Poznyakoff
0e0a852e91 Improve documentation.
* doc/tar.1: Document --skip-old-files and --warning=existing-file
* doc/tar.texi: Document --warning=existing-file
2014-08-16 09:42:25 +03:00
329 changed files with 10124 additions and 4153 deletions

9
.gitignore vendored
View File

@@ -8,6 +8,7 @@
.deps
.emacs*
.libs
.gdbinit
ABOUT-NLS
ChangeLog
INSTALL
@@ -23,13 +24,9 @@ config.h.in
config.log
config.status
configure
gnu/*.h
gnu/*/
gnu/.gitignore
gnu/charset.alias
gnulib
gnu
libtool
m4
paxutils
rmt
stamp-h1
TAGS

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "gnulib"]
path = gnulib
url = git://git.sv.gnu.org/gnulib.git
[submodule "paxutils"]
path = paxutils
url = git://git.sv.gnu.org/paxutils.git

View File

@@ -3186,7 +3186,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
Reported by Jeffrey Goldberg.
* rmt.h (_remdev): A filename is not remote if the colon is
preceeded by a slash, to take care of `/:/' which is a shorthand
preceded by a slash, to take care of `/:/' which is a shorthand
for `/.../<CELL-NAME>/fs' on OSF's Distributing Computing
Environment (DCE) and Distributed File System (DFS).
Reported by Travis L. Priest.

View File

@@ -1,7 +1,6 @@
# Main Makefile for GNU tar.
# Copyright 1994-1997, 1999-2001, 2003, 2007, 2009, 2013-2014 Free
# Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -26,7 +25,7 @@ dist-hook:
$(MAKE) changelog_dir=$(distdir) ChangeLog
-rm -f $(distdir).cpio
find $(distdir) | cpio -Hcrc -o | \
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
eval GZIP= gzip $(GZIP_ENV) -c > $(distdir).cpio.gz
distclean-local:
-rm -f $(distdir).cpio.gz

245
NEWS
View File

@@ -1,5 +1,234 @@
GNU tar NEWS - User visible changes. 2014-07-27
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
* New options: --verbatim-files-from, --no-verbatim-files-from
The --verbatim-files-from option instructs tar to treat each line read
from a file list as a file name, even if it starts with a dash.
File lists are supplied with the --files-from (-T) option. By
default, each line read from a file list is first stripped off the
leading and trailing whitespace and, if the result begins with a dash,
it is treated as tar command line option.
Use the --verbatim-files-from option to disable this special handling.
This facilitates the use of tar with file lists created automatically
(e.g. by find(1) command).
This option affects all --files-from options that occur after it in
the command line. Its effect is reverted by the
--no-verbatim-files-from option.
* --null option reads file names verbatim
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
1.27.
* New options: --owner-map=FILE and --group-map=FILE
These two options provide fine-grained control over what user/group
names (or IDs) should be mapped when adding files to archive.
For both options, FILE is a plain text file with user or group
mappings. Empty lines are ignored. Comments are introduced with
# sign (unless quoted) and extend to the end of the corresponding
line. Each non-empty line defines translation for a single UID (GID).
It must consist of two fields, delimited by any amount of whitespace:
OLDNAME NEWNAME[:NEWID]
OLDNAME is either a valid user (group) name or a ID prefixed with +. Unless
NEWID is supplied, NEWNAME must also be either a valid name or a
+ID. Otherwise, both NEWNAME and NEWID need not be listed in the
system user database.
* New option --clamp-mtime
The new --clamp-mtime option changes the behavior of --mtime to only
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,
except for files modified during the build process. In that case, using
reference (and thus reproducible) timestamps for the latter is good
enough.
See <https://wiki.debian.org/ReproducibleBuilds> for more information.
* Deprecated --preserve option removed
* Sparse file detection
Tar now uses SEEK_DATA/SEEK_HOLE on systems that support it. This
allows for considerable speed-up in sparse-file detection.
New option --hole-detection is provided, that allows the user to
select the algorithm used for hole detection. Available arguments
are:
--hole-detection=seek
Use lseek(2) SEEK_DATA and SEEK_HOLE "whence" parameters.
--hole-detection=raw
Scan entire file before storing it to determine where holes
are located.
The default is to use "seek" whenever possible, and fall back to
"raw" otherwise.
version 1.28, 2014-07-28
@@ -21,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"
@@ -60,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.
@@ -69,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
@@ -162,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.
@@ -369,7 +598,7 @@ Modification times in ustar header blocks of extended headers
are set to mtimes of the corresponding archive members. This
can be overridden by the
--pax-opion='exthdr.mtime=STRING'
--pax-option='exthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a "Time reference" (see below).
@@ -379,7 +608,7 @@ headers are set to the time when tar was invoked.
This can be overridden by the
--pax-opion='globexthdr.mtime=STRING'
--pax-option='globexthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a "Time reference" (see below).
@@ -1505,7 +1734,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
Copyright 1994-2001, 2003-2010, 2013-2014 Free Software Foundation, Inc.
Copyright 1994-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

4
README
View File

@@ -23,7 +23,6 @@ GNU 'tar' is derived from John Gilmore's public domain 'tar'.
See file 'ABOUT-NLS' for how to customize this program to your language.
See file 'COPYING' for copying conditions.
See file 'INSTALL' for compilation and installation instructions.
See file 'PORTS' for various ports of GNU tar to non-Unix systems.
See file 'NEWS' for a list of major changes in the current release.
See file 'THANKS' for a list of contributors.
@@ -222,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 Free
Software Foundation, Inc.
Copyright 1990-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -23,47 +23,19 @@ suggest using test version 1.3.5 (or later, if one becomes available).
Valgrind <http://valgrind.org/> is also highly recommended, if
Valgrind supports your architecture.
Before building the package, run "bootstrap". It obtains various
additional files from the CVS repository and the Translation Project
site and prepares the source directory for building.
Before building the package, run "bootstrap". It will obtain gnulib
and paxutils files from their Git repositories on Savannah. Then, it will
fetch the po files from tar page at Translation Project, and, finally, it
will start autoconfiguration process. Simply running bootstrap without
arguments should do in most cases.
When run without arguments, bootstrap will try to obtain gnulib and
paxutils files from their corresponding CVS repositories on Savannah
using anonymous SSH access. Then, it will fetch the po files from tar
page at Translation Project, and, finally, it will start autoconfiguration
process. Simply running it without arguments should do in most cases.
Several options allow to control the behavior of bootstrap:
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
do not want to waste your bandwidth dowloading
them again.
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
sources reside. Use this if you already
have paxutils sources on your machine, and
do not want to waste your bandwidth dowloading
them again.
--cvs-auth=METHOD Set the CVS access method used for downloading
gnulib files. METHOD is one of the keywords
accepted by cvs -d option (see info cvs
repository).
--cvs-user=USERNAME Set the CVS username to be used when accessing
the gnulib repository.
--no-po Do not download po files.
Notice also that when using CVS authentication method "ext", bootstrap
will set the variable CVS_RSH to "ssh", unless it is already set to
some other value.
Bootstrap reads its configuration from file bootstrap.conf located on the
top of tar source tree. Several options are provided that modify its
behavior. Run 'bootstrap --help' for a list.
Copyright 2001, 2003-2005, 2007, 2013-2014 Free Software Foundation,
Inc.
Copyright 2001-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -12,7 +12,6 @@ version.
- Autoconf <http://www.gnu.org/software/autoconf/>
- M4 <http://www.gnu.org/software/m4/>
- Texinfo <http://www.gnu.org/software/texinfo>
- Gnulib <http://www.gnu.org/software/gnulib>
- Git <http://git.or.cz>
* Bootstrapping
@@ -33,23 +32,14 @@ Once done, proceed as described in the file README (section
INSTALLATION).
Normally you will have to run bootstrap only once. However, if you
intend to hack on GNU tar, you might need to run it again later. In
this case, you will probably want to save some time and bandwidth by
avoiding downloading the same files again. If so, create in GNU tar
root directory the file named '.bootstrap' with the following
contents:
--gnulib-srcdir=$HOME/gnulib
Replace '$HOME/gnulib' with the actual directory where the Gnulib
sources reside.
For more information about 'bootstrap', run 'bootstrap --help'.
intend to hack on GNU tar, you might need to run it again later.
There are lots of options that you may find useful in this case.
See 'bootstrap --help' for a detailed list.
* Copyright information
Copyright 2007-2009, 2013-2014 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

10
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
@@ -78,6 +79,7 @@ Cesar Romani romani@ifm.uni-hamburg.de
Chad Hurwitz churritz@cts.com
Chance Reschke creschke@usra.edu
Charles Fu ccwf@klab.caltech.edu
Charles McGarvey chazmcgarvey@brokenzipper.com
Charles Lopes Charles.Lopes@infm.ulst.ac.uk
Charles M. Hannum mycroft@gnu.org
Chip Salzenberg tct!chip
@@ -93,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
@@ -107,6 +110,7 @@ Conrad Hughes chughes@maths.tcd.ie
Constantin Belous const@cris.net
Coranth Gryphon gryphon@bur.visidyne.com
Cyril Strejc strejc@unicontrols.cz
Dagobert Michelsen dam@opencsw.org
Dale R. Worley worley@world.std.com
Dale Wiles wiles@geordi.calspan.com
Dan Bloch dan@transarc.com
@@ -114,6 +118,7 @@ Dan Drake dan@dandrake.org
Dan Reish dreish@izzy.net
Daniel Hagerty hag@gnu.org
Daniel Quinlan quinlan@pathname.com
Daniel Kahn Gillmor dkg@fifthhorseman.net
Daniel R. Guilderson d.guilderson@ma30.bull.com
Daniel S. Barclay daniel@compass-da.com
Daniel Trinkle trinkle@cs.purdue.edu
@@ -135,11 +140,13 @@ 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
Denis Fortin fortin@acm.org
Dennis Pixton dennis@math.binghamton.edu
Derek Terveer dt@hawkmoon.mn.org
Dick Streefland dicks@tasking.nl
Dietmar Braun dietmar@highway.bertelsmann.de
Dimitri Bougoulias opus@hol.gr
@@ -172,6 +179,7 @@ Erik D. Frederick edf@deckard.mc.duke.edu
Esa Karell karell@cs.helsinki.fi
Ezra Peisach epeisach@mit.edu
Fabio d'Alessi cars@civ.bio.unipd.it
Flavio Poletti polettix@gmail.com
Frank Heckenbach frank@g-n-u.de
Frank Koenen koenfr@lidp.com
Franz-Werner Gergen gergen@edvulx.mpi-stuttgart.mpg.de
@@ -202,6 +210,7 @@ Helmut Waitzmann Helmut.Waitzmann@web.de
Henrik Bakman hb@csd.uu.se
Hernan Prieto Schmidt hernan@pea.usp.br
Hiroyuki Bessho bsh@grotto.iijnet.or.jp
Holger Levsen holger@layer-acht.org
Holger Teutsch holger@hotbso.rhein-main.de
Hugh Secker-Walker hugh@ear.mit.edu
Hunyue Yau hunyue.yau@picksys.com
@@ -240,6 +249,7 @@ Jeffrey Goldberg J.Goldberg@cranfield.ac.uk
Jeffrey Mark Siskind Qobi@emba.uvm.edu
Jeffrey W. Parker jwpkr@mcs.com
Jens Henrik Jensen recjhl@mediator.uni-c.dk
Jérémy Bobbio lunar@debian.org
Jim Blandy jimb@totoro.cs.oberlin.edu
Jim Clausing jac@postbox.acs.ohio-state.edu
Jim Farrell jwf@platinum.com

2
TODO
View File

@@ -45,7 +45,7 @@ Suggestions for improving GNU tar.
* Copyright notice
Copyright 2003-2004, 2007, 2013-2014 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 Free Software Foundation, Inc.
dnl Copyright 2009-2021 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU tar.
dnl
@@ -40,37 +40,23 @@ AC_DEFUN([TAR_HEADERS_ATTR_XATTR_H],
# First check for <sys/xattr.h>
AC_CHECK_HEADERS([sys/xattr.h])
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_sys_xattr_h" = yes])
AM_CONDITIONAL([TAR_LIB_ATTR],[false])
if test "$ac_cv_header_sys_xattr_h" = yes; then
AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
setxattr fsetxattr lsetxattr \
listxattr flistxattr llistxattr,
# only when functions are present
AC_DEFINE([HAVE_SYS_XATTR_H], [1],
[define to 1 if we have <sys/xattr.h> header])
if test "$with_xattrs" != no; then
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
fi
)
fi
# If <sys/xattr.h> is not found, then check for <attr/xattr.h>
if test "$ac_cv_header_sys_xattr_h" != yes; then
AC_CHECK_HEADERS([attr/xattr.h])
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_attr_xattr_h" = yes])
AC_CHECK_LIB([attr],[fgetxattr])
AM_CONDITIONAL([TAR_LIB_ATTR],[test "$ac_cv_lib_attr_fgetxattr" = yes])
if test "$ac_cv_header_attr_xattr_h" = yes; then
AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
setxattr fsetxattr lsetxattr \
listxattr flistxattr llistxattr,
# only when functions are present
AC_DEFINE([HAVE_ATTR_XATTR_H], [1],
[define to 1 if we have <attr/xattr.h> header])
if test "$with_xattrs" != no; then
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
fi
)
fi
if test "$with_xattrs" != no; then
for i in getxattr fgetxattr lgetxattr \
setxattr fsetxattr lsetxattr \
listxattr flistxattr llistxattr
do
AC_SEARCH_LIBS($i, attr)
eval found=\$ac_cv_search_$i
test "$found" = "no" && break
done
if test "$found" != no; then
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
fi
fi
])

942
bootstrap

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# Bootstrap configuration for GNU tar.
# Copyright 2006-2009, 2013-2014 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -26,10 +26,6 @@ avoided_gnulib_modules='
--avoid=lock
'
# gnulib modules used by this package.
gnulib_modules="$avoided_gnulib_modules
`grep '^[^#]' gnulib.modules`
"
# Additional xgettext options to use. Use "\\\newline" to break lines.
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
@@ -71,3 +67,60 @@ test -f ChangeLog || cat > ChangeLog <<EOT
This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist. Run make ChangeLog if you wish to create it earlier.
EOT
git submodule init
git submodule update
PAXUTILS=paxutils
# gnulib modules used by this package.
gnulib_modules="$avoided_gnulib_modules
`grep -h '^[^#]' gnulib.modules $PAXUTILS/gnulib.modules`
"
# copy_files srcdir dstdir
copy_files() {
for file in `cat $1/DISTFILES`
do
case $file in
"#*") continue;;
esac
dst=`echo $file | sed 's^.*/^^'`
if [ $# -eq 3 ]; then
case $dst in
${3}*) ;;
*) dst=${3}$dst;;
esac
fi
if [ "$2" = '.' ]; then
ln -sf $1/$file $2
else
symlink_to_dir "$1" "$file" "$2/$dst" || exit
fi
# FIXME ignorefile $2 $dst
done
}
# Import from paxutils
copy_files ${PAXUTILS} .
copy_files ${PAXUTILS}/am m4
echo "$0: Creating m4/paxutils.m4"
(echo "# This file is generated automatically. Please, do not edit."
echo "#"
echo "AC_DEFUN([${package}_PAXUTILS],["
cat ${PAXUTILS}/am/DISTFILES | sed '/^#/d;s/\(.*\)\.m4/pu_\1/' | tr a-z A-Z
echo "])") > ./m4/paxutils.m4
#FIXME ignorefile m4 paxutils.m4
if [ -d rmt ]; then
:
else
mkdir rmt
fi
for dir in doc rmt lib tests
do
copy_files ${PAXUTILS}/$dir $dir
done
copy_files ${PAXUTILS}/paxlib lib pax

View File

@@ -1,6 +1,6 @@
# Configure template for GNU tar. -*- autoconf -*-
# Copyright 1991, 1994-2010, 2013-2014 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.28], [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
@@ -150,6 +162,7 @@ if test "$gl_gcc_warnings" = yes; then
nw="$nw -Winline" # It's OK to not inline.
nw="$nw -Wstrict-overflow" # It's OK to optimize strictly.
nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now.
nw="$nw -Wstack-protector"
gl_MANYWARN_ALL_GCC([ws])
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
@@ -160,9 +173,10 @@ if test "$gl_gcc_warnings" = yes; then
gl_WARN_ADD([-Wno-type-limits]) # It's OK to optimize based on types.
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
gl_WARN_ADD([-Wno-format-nonliteral])
gl_WARN_ADD([-fdiagnostics-show-option])
gl_WARN_ADD([-funit-at-a-time])
AC_SUBST([WARN_CFLAGS])
@@ -204,8 +218,7 @@ fi
TAR_HEADERS_ATTR_XATTR_H
AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink grantpt])
AM_CONDITIONAL([TAR_COND_GRANTPT], [test $ac_cv_func_grantpt = yes])
AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink])
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
@@ -249,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

3
doc/.gitignore vendored
View File

@@ -1,7 +1,6 @@
genfile.texi
header.texi
manual
parse-datetime.texi
stamp-vti
tar.aux
tar.cp
@@ -24,3 +23,5 @@ tar.toc
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 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 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 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 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 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 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 Free Software
@c 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 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.
@@ -116,7 +116,7 @@ epoch. These are followed by arbitrary number of directory records.
particular directory. Parts of a directory record are delimited with
@acronym{ASCII} 0 characters. The following table describes each
part. The @dfn{Number} type in this table stands for a decimal integer
in @acronym{ASCII} notation. (Negative values are preceeded with a "-"
in @acronym{ASCII} notation. (Negative values are preceded with a "-"
character, while positive values have no leading punctuation.)
@multitable @columnfractions 0.25 0.15 0.6
@@ -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 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 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.

255
doc/tar.1
View File

@@ -1,5 +1,5 @@
.\" This file is part of GNU tar. -*- nroff -*-
.\" Copyright 2013-2014 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 "February 22, 2014" "TAR" "GNU TAR Manual"
.TH TAR 1 "July 13, 2020" "TAR" "GNU TAR Manual"
.SH NAME
tar \- an archiving utility
.SH SYNOPSIS
@@ -37,7 +37,7 @@ tar \- an archiving utility
\fBtar\fR \fB\-x\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
.SS GNU-style usage
.sp
\fBtar\fR {\fB\-\-catenate\fR|\fB\-\-concatenate} [\fIOPTIONS\fR] \fIARCHIVE\fR \fIARCHIVE\fR
\fBtar\fR {\fB\-\-catenate\fR|\fB\-\-concatenate\fR} [\fIOPTIONS\fR] \fIARCHIVE\fR \fIARCHIVE\fR
.sp
\fBtar\fR \fB\-\-create\fR [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
@@ -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
@@ -175,7 +177,7 @@ resulting archive might be unusable with non-GNU implementations of
\fBtar\fR. Notice also that when more than one archive is given, the
members from archives other than the first one will be accessible in
the resulting archive only if using the \fB\-i\fR
(\fB\-\-ignore\-zeros) option.
(\fB\-\-ignore\-zeros\fR) option.
Compressed archives cannot be concatenated.
.TP
@@ -198,7 +200,7 @@ short option equivalent.
.TP
\fB\-r\fR, \fB\-\-append\fR
Append files to the end of an archive. Arguments have the same
meaning as for \fB\-c\fR (\fB\-\-create).
meaning as for \fB\-c\fR (\fB\-\-create\fR).
.TP
\fB\-t\fR, \fB\-\-list\fR
List the contents of an archive. Arguments are optional. When given,
@@ -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,12 +258,18 @@ 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
therefore common practice to use \fB/dev/null\fR in its place.
.TP
\fB\-\-hole\-detection\fR=\fIMETHOD\fR
Use \fIMETHOD\fR to detect holes in sparse files. This option implies
\fB\-\-sparse\fR. Valid values for \fIMETHOD\fR are \fBseek\fR and
\fBraw\fR. Default is \fBseek\fR with fallback to \fBraw\fR when not
applicable.
.TP
\fB\-G\fR, \fB\-\-incremental\fR
Handle old GNU-format incremental backups.
.TP
@@ -278,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.
@@ -291,7 +302,7 @@ Process only the \fIN\fRth occurrence of each file in the
archive. This option is valid only when used with one of the
following subcommands: \fB\-\-delete\fR, \fB\-\-diff\fR,
\fB\-\-extract\fR or \fB\-\-list\fR and when a list of files is given
either on the command line or via the \fB\-\fRT option. The default
either on the command line or via the \fB\-T\fR option. The default
\fIN\fR is \fB1\fR.
.TP
\fB\-\-restrict\fR
@@ -327,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
@@ -347,6 +361,9 @@ Recursively remove all files in the directory prior to extracting it.
\fB\-\-remove\-files\fR
Remove files from disk after adding them to the archive.
.TP
\fB\-\-skip\-old\-files
Don't replace existing files when extracting, silently skip over them.
.TP
\fB\-U\fR, \fB\-\-unlink\-first\fR
Remove each file prior to extracting over it.
.TP
@@ -368,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
@@ -448,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
@@ -464,15 +482,40 @@ Delay setting modification times and permissions of extracted
directories until the end of extraction. Use this option when
extracting from an archive which has unusual member ordering.
.TP
\fB\-\-group\fR=\fINAME\fR
Force \fINAME\fR as group for added files.
\fB\-\-group\fR=\fINAME\fR[:\fIGID\fR]
Force \fINAME\fR as group for added files. If \fIGID\fR is not
supplied, \fINAME\fR can be either a user name or numeric GID. In
this case the missing part (GID or name) will be inferred from the
current host's group database.
When used with \fB\-\-group\-map\fR=\fIFILE\fR, affects only those
files whose owner group is not listed in \fIFILE\fR.
.TP
\fB\-\-group\-map\fR=\fIFILE\fR
Read group translation map from \fIFILE\fR. Empty lines are ignored.
Comments are introduced with \fB#\fR sign and extend to the end of line.
Each non-empty line in \fIFILE\fR defines translation for a single
group. It must consist of two fields, delimited by any amount of whitespace:
.EX
\fIOLDGRP\fR \fINEWGRP\fR[\fB:\fINEWGID\fR]
.EE
\fIOLDGRP\fR is either a valid group name or a GID prefixed with
\fB+\fR. Unless \fINEWGID\fR is supplied, \fINEWGRP\fR must also be
either a valid group name or a \fB+\fIGID\fR. Otherwise, both
\fINEWGRP\fR and \fINEWGID\fR need not be listed in the system group
database.
As a result, each input file with owner group \fIOLDGRP\fR will be
stored in archive with owner group \fINEWGRP\fR and GID \fINEWGID\fR.
.TP
\fB\-\-mode\fR=\fICHANGES\fR
Force symbolic mode \fICHANGES\fR for added files.
.TP
\fB\-\-mtime\fR=\fIDATE-OR-FILE\fR
Set mtime for added files. \fIDATE-OR-FILE\fR is either a date/time
in almost arbitrary formate, or the name of an existing file. In the
in almost arbitrary format, or the name of an existing file. In the
latter case the mtime of that file will be used.
.TP
\fB\-m\fR, \fB\-\-touch\fR
@@ -491,15 +534,37 @@ Apply the user's umask when extracting permissions from the archive
\fB\-\-numeric\-owner\fR
Always use numbers for user/group names.
.TP
\fB\-\-owner\fR=\fINAME\fR
Force \fINAME\fR as owner for added files.
\fB\-\-owner\fR=\fINAME\fR[:\fIUID\fR]
Force \fINAME\fR as owner for added files. If \fIUID\fR is not
supplied, \fINAME\fR can be either a user name or numeric UID. In
this case the missing part (UID or name) will be inferred from the
current host's user database.
When used with \fB\-\-owner\-map\fR=\fIFILE\fR, affects only those
files whose owner is not listed in \fIFILE\fR.
.TP
\fB\-\-owner\-map\fR=\fIFILE\fR
Read owner translation map from \fIFILE\fR. Empty lines are ignored.
Comments are introduced with \fB#\fR sign and extend to the end of line.
Each non-empty line in \fIFILE\fR defines translation for a single
UID. It must consist of two fields, delimited by any amount of whitespace:
.EX
\fIOLDUSR\fR \fINEWUSR\fR[\fB:\fINEWUID\fR]
.EE
\fIOLDUSR\fR is either a valid user name or a UID prefixed with
\fB+\fR. Unless \fINEWUID\fR is supplied, \fINEWUSR\fR must also be
either a valid user name or a \fB+\fIUID\fR. Otherwise, both
\fINEWUSR\fR and \fINEWUID\fR need not be listed in the system user
database.
As a result, each input file owned by \fIOLDUSR\fR will be
stored in archive with owner name \fINEWUSR\fR and UID \fINEWUID\fR.
.TP
\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).
@@ -524,6 +589,34 @@ Using \fB\-\-sort=inode\fR reduces the number of disk seeks made when
creating the archive and thus can considerably speed up archivation.
This sorting order is supported only if the underlying system provides
the necessary information.
.SS Extended file attributes
.TP
.B \-\-acls
Enable POSIX ACLs support.
.TP
.B \-\-no\-acls
Disable POSIX ACLs support.
.TP
.B \-\-selinux
Enable SELinux context support.
.TP
.B \-\-no-selinux
Disable SELinux context support.
.TP
.B \-\-xattrs
Enable extended attributes support.
.TP
.B \-\-no\-xattrs
Disable extended attributes support.
.TP
.BI \-\-xattrs\-exclude= PATTERN
Specify the exclude pattern for xattr keys. \fIPATTERN\fR is a POSIX
regular expression, e.g. \fB\-\-xattrs\-exclude='^user\.'\fR, to exclude
attributes from the user namespace.
.TP
.BI \-\-xattrs\-include= PATTERN
Specify the include pattern for xattr keys. \fIPATTERN\fR is a POSIX
regular expression.
.SS Device selection and switching
.TP
\fB\-f\fR, \fB\-\-file\fR=\fIARCHIVE\fR
@@ -557,7 +650,7 @@ instead. You can do so by giving the following command line option:
--rsh-command=/usr/bin/ssh
.EE
The remote mashine should have the
The remote machine should have the
.BR rmt (8)
command installed. If its pathname does not match \fBtar\fR's
default, you can inform \fBtar\fR about the correct pathname using the
@@ -567,7 +660,7 @@ option.
\fB\-\-force\-local\fR
Archive file is local even if it has a colon.
.TP
\fB\-\fRF, \fB\-\-info\-script\fR=\fICOMMAND\fR, \fB\-\-new\-volume\-script\fR=\fICOMMAND\fR
\fB\-F\fR, \fB\-\-info\-script\fR=\fICOMMAND\fR, \fB\-\-new\-volume\-script\fR=\fICOMMAND\fR
Run \fICOMMAND\fR at the end of each tape (implies \fB\-M\fR). The
command can include arguments. When started, it will inherit \fBtar\fR's
environment plus the following variables:
@@ -601,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
@@ -609,7 +702,7 @@ If the info script fails, \fBtar\fR exits; otherwise, it begins writing
the next volume.
.RE
.TP
\fB\-L\fR, \fB\-\-tape\-length\fR=\fN\fR
\fB\-L\fR, \fB\-\-tape\-length\fR=\fIN\fR
Change tape after writing \fIN\fRx1024 bytes. If \fIN\fR is followed
by a size suffix (see the subsection
.B Size suffixes
@@ -639,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
@@ -647,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
@@ -690,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.
@@ -703,7 +797,7 @@ use \fITEXT\fR as a globbing pattern for volume name.
\fB\-a\fR, \fB\-\-auto\-compress\fR
Use archive suffix to determine the compression program.
.TP
\fB\-\fRI, \fB\-\-use\-compress\-program\fI=\fICOMMAND\fR
\fB\-I\fR, \fB\-\-use\-compress\-program\fI=\fICOMMAND\fR
Filter data through \fICOMMAND\fR. It must accept the \fB\-d\fR
option, for decompression. The argument can contain command line
options.
@@ -735,9 +829,13 @@ Do not use archive suffix to determine the compression program.
Filter the archive through
.BR gzip (1).
.TP
\fB\-\fRZ, \fB\-\-compress\fR, \fB\-\-uncompress\fR
\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
@@ -768,7 +866,8 @@ environment variable. If it is not set, \fBexisting\fR is assumed.
.RE
.TP
\fB\-C\fR, \fB\-\-directory\fR=\fIDIR\fR
Change to directory DIR.
Change to \fIDIR\fR before performing any operations. This option is
order-sensitive, i.e. it affects all options that follow.
.TP
\fB\-\-exclude\fR=\fIPATTERN\fR
Exclude files matching \fIPATTERN\fR, a
@@ -841,13 +940,31 @@ Avoid descending automatically in directories.
\fB\-\-no\-unquote\fR
Do not unquote input file or member names.
.TP
\fB\-\-no\-verbatim\-files\-from\fR
Treat each line read from a file list as if it were supplied in the
command line. I.e., leading and trailing whitespace is removed and,
if the resulting string begins with a dash, it is treated as \fBtar\fR
command line option.
This is the default behavior. The \fB\-\-no\-verbatim\-files\-from\fR
option is provided as a way to restore it after
\fB\-\-verbatim\-files\-from\fR option.
This option is positional: it affects all \fB\-\-files\-from\fR
options that occur after it in, until \fB\-\-verbatim\-files\-from\fR
option or end of line, whichever occurs first.
It is implied by the \fB\-\-no\-null\fR option.
.TP
\fB\-\-null\fR
Instruct subsequent \fB\-T\fR options to read null-terminated names,
disable handling of the \fB\-C\fR option read from the file.
Instruct subsequent \fB\-T\fR options to read null-terminated names
verbatim (disables special handling of names that start with a dash).
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
@@ -865,10 +982,43 @@ unless overridden by environment variable \fBSIMPLE_BACKUP_SUFFIX\fR.
.TP
\fB\-T\fR, \fB\-\-files\-from\fR=\fIFILE\fR
Get names to extract or create from \fIFILE\fR.
Unless specified otherwise, the \fIFILE\fR must contain a list of
names separated by ASCII \fBLF\fR (i.e. one name per line). The
names read are handled the same way as command line arguments. They
undergo quote removal and word splitting, and any string that starts
with a \fB\-\fR is handled as \fBtar\fR command line option.
If this behavior is undesirable, it can be turned off using the
\fB\-\-verbatim\-files\-from\fR option.
The \fB\-\-null\fR option instructs \fBtar\fR that the names in
\fIFILE\fR are separated by ASCII \fBNUL\fR character, instead of
\fBLF\fR. It is useful if the list is generated by
.BR find (1)
.B \-print0
predicate.
.TP
\fB\-\-unquote\fR
Unquote file or member names (default).
.TP
\fB\-\-verbatim\-files\-from\fR
Treat each line obtained from a file list as a file name, even if it
starts with a dash. File lists are supplied with the
\fB\-\-files\-from\fR (\fB\-T\fR) option. The default behavior is to
handle names supplied in file lists as if they were typed in the
command line, i.e. any names starting with a dash are treated as
\fBtar\fR options. The \fB\-\-verbatim\-files\-from\fR option
disables this behavior.
This option affects all \fB\-\-files\-from\fR options that occur after
it in the command line. Its effect is reverted by the
\fB\-\-no\-verbatim\-files\-from} option.
This option is implied by the \fB\-\-null\fR option.
See also \fB\-\-add\-file\fR.
.TP
\fB\-X\fR, \fB\-\-exclude\-from\fR=\fIFILE\fR
Exclude files matching patterns listed in FILE.
.SS File name transformations
@@ -876,7 +1026,7 @@ Exclude files matching patterns listed in FILE.
\fB\-\-strip\-components\fR=\fINUMBER\fR
Strip \fINUMBER\fR leading components from file names on extraction.
.TP
\fB\-\-transform\fR=\fIEXPRESSION\dR, \fB\-\-xform\fR=\fIEXPRESSION\fR
\fB\-\-transform\fR=\fIEXPRESSION\fR, \fB\-\-xform\fR=\fIEXPRESSION\fR
Use sed replace \fIEXPRESSION\fR to transform file names.
.SS File name matching options
These options affect both exclude and include patterns.
@@ -912,6 +1062,9 @@ Display progress messages every \fIN\fRth record (default 10).
\fB\-\-checkpoint\-action\fR=\fIACTION\fR
Run \fIACTION\fR on each checkpoint.
.TP
\fB\-\-clamp\-mtime\fR
Only set time when the file is more recent than what was given with \-\-mtime.
.TP
\fB\-\-full\-time\fR
Print file time to its full resolution.
.TP
@@ -954,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"
@@ -965,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
@@ -1018,9 +1175,18 @@ 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
.B existing\-file
"%s: skipping existing file"
.TP
.B timestamp
"%s: implausibly old time stamp %s"
.br
@@ -1048,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
@@ -1139,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
@@ -1156,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>
@@ -1171,4 +1337,3 @@ There is NO WARRANTY, to the extent permitted by law.
.\" time-stamp-end: "\""
.\" time-stamp-line-limit: 20
.\" end:

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
# Copyright 2006-2007, 2013-2014 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 Free Software
@c Foundation, Inc.
@c Copyright 1992--2021 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@macro GNUTAR

View File

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

1
gnulib Submodule

Submodule gnulib added at 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.
@@ -18,8 +18,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
acl
alloca
areadlinkat-with-size
argmatch
argp
argp-version-etc
@@ -37,6 +37,7 @@ fchownat
fcntl-h
fdopendir
fdutimensat
file-has-acl
fileblocks
fnmatch-gnu
fprintftime
@@ -65,8 +66,6 @@ modechange
obstack
openat
parse-datetime
posix_openpt
ptsname
priv-set
progname
quote
@@ -84,18 +83,20 @@ stat-time
stdbool
stdint
stpcpy
stdopen
strdup-posix
strerror
strnlen
strtoimax
strtol
strtoul
strtoumax
symlinkat
timespec
timespec-sub
unlinkat
unlinkdir
unlocked-io
unlockpt
utimensat
version-etc-fsf
xalloc

View File

@@ -1,7 +1,6 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright 1994-1997, 1999-2001, 2003-2007, 2009-2010, 2013-2014 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\
@@ -41,10 +39,8 @@ noinst_HEADERS = \
libtar_a_SOURCES = \
paxerror.c paxexit-status.c paxlib.h paxnames.c \
prepargs.c prepargs.h \
rtapelib.c \
rmt.h \
stdopen.c stdopen.h \
system.h system-ioctl.h \
wordsplit.c\
xattr-at.c

View File

@@ -1,5 +1,5 @@
/* Replacement <attr/xattr.h> for platforms that lack it.
Copyright 2012-2014 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,83 +0,0 @@
/* Parse arguments from a string and prepend them to an argv.
Copyright 1999-2001, 2007, 2013-2014 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 <eggert@twinsun.com>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "prepargs.h"
#include <sys/types.h>
#include <xalloc.h>
#if HAVE_STRING_H
# include <string.h>
#endif
#include <ctype.h>
/* Find the white-space-separated options specified by OPTIONS, and
using BUF to store copies of these options, set ARGV[0], ARGV[1],
etc. to the option copies. Return the number N of options found.
Do not set ARGV[N]. If ARGV is null, do not store ARGV[0]
etc. Backslash can be used to escape whitespace (and backslashes). */
static int
prepend_args (char const *options, char *buf, char **argv)
{
char const *o = options;
char *b = buf;
int n = 0;
for (;;)
{
while (isspace ((unsigned char) *o))
o++;
if (!*o)
return n;
if (argv)
argv[n] = b;
n++;
do
if ((*b++ = *o++) == '\\' && *o)
b[-1] = *o++;
while (*o && ! isspace ((unsigned char) *o));
*b++ = '\0';
}
}
/* Prepend the whitespace-separated options in OPTIONS to the argument
vector of a main program with argument count *PARGC and argument
vector *PARGV. */
void
prepend_default_options (char const *options, int *pargc, char ***pargv)
{
if (options)
{
char *buf = xmalloc (strlen (options) + 1);
int prepended = prepend_args (options, buf, (char **) 0);
int argc = *pargc;
char * const *argv = *pargv;
char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
*pargc = prepended + argc;
*pargv = pp;
*pp++ = *argv++;
pp += prepend_args (options, buf, pp);
while ((*pp++ = *argv++))
continue;
}
}

View File

@@ -1,3 +0,0 @@
/* Parse arguments from a string and prepend them to an argv. */
void prepend_default_options (char const *, int *, char ***);

View File

@@ -1,76 +0,0 @@
/* stdopen.c - ensure that the three standard file descriptors are in use
Copyright 2005, 2007, 2013-2014 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 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,52 +12,119 @@
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
#include <stddef.h>
struct wordsplit
#if 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
# define __WORDSPLIT_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
# define __WORDSPLIT_ATTRIBUTE_FORMAT(spec) /* empty */
#endif
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 *, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
/* [Input] (WRDSF_ERROR) Function used for error
reporting */
void (*ws_debug) (const char *, ...)
__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
@@ -65,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 */
@@ -79,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 */
@@ -107,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 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
@@ -31,6 +31,8 @@
#include "openat-priv.h"
#ifdef HAVE_XATTRS
/* setxattrat */
#define AT_FUNC_NAME setxattrat
#define AT_FUNC_F1 setxattr
@@ -108,3 +110,5 @@
#undef AT_FUNC_RESULT
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#endif /* HAVE_XATTRS */

View File

@@ -1,7 +1,7 @@
/* Prototypes for openat-style fd-relative functions for operating with
extended file attributes.
Copyright 2012-2014 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
paxutils Submodule

Submodule paxutils added at b7da0d659e

3
po/.gitignore vendored
View File

@@ -1,3 +1,6 @@
/Makefile.in.in
/Makevars.template~
/Makefile.in.in~
*.gmo
*.mo
*.po

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright 2006-2007, 2010, 2013-2014 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 Free
# Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -33,6 +32,7 @@ tar_SOURCES = \
xheader.c\
incremen.c\
list.c\
map.c\
misc.c\
names.c\
sparse.c\
@@ -52,7 +52,3 @@ AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)
if TAR_LIB_ATTR
tar_LDADD += -lattr
endif

View File

@@ -1,5 +1,5 @@
/* Long integers, for GNU tar.
Copyright 1999, 2007, 2013-2014 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 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,7 +404,12 @@ check_compressed_archive (bool *pshort)
/* Restore global values */
read_full_records = sfr;
if (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;
@@ -495,7 +513,7 @@ print_stats (FILE *fp, const char *text, tarlong numbytes)
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
int n = 0;
int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
if (text && text[0])
@@ -512,12 +530,12 @@ print_stats (FILE *fp, const char *text, tarlong numbytes)
before each data item (bytes read, written, deleted, in that order).
EOR is a delimiter to output after each item (used only if deleting
from the archive), EOL is a delimiter to add at the end of the output
line. */
line. */
int
format_total_stats (FILE *fp, const char **formats, int eor, int eol)
format_total_stats (FILE *fp, char const *const *formats, int eor, int eol)
{
int n;
switch (subcommand_option)
{
case CREATE_SUBCOMMAND:
@@ -536,7 +554,7 @@ format_total_stats (FILE *fp, const char **formats, int eor, int eol)
fputc (eor, fp);
n++;
n += print_stats (fp, formats[TF_WRITE],
prev_written + bytes_written);
@@ -570,7 +588,7 @@ format_total_stats (FILE *fp, const char **formats, int eor, int eol)
return n;
}
const char *default_total_format[] = {
static char const *const default_total_format[] = {
N_("Total bytes read"),
/* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
N_("Total bytes written"),
@@ -865,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;
@@ -980,18 +1005,28 @@ short_read (size_t status)
void
flush_archive (void)
{
size_t buffer_level = current_block->buffer - record_start->buffer;
record_start_block += record_end - record_start;
current_block = record_start;
record_end = record_start + blocking_factor;
size_t buffer_level;
if (access_mode == ACCESS_READ && time_to_start_writing)
{
access_mode = ACCESS_WRITE;
time_to_start_writing = false;
backspace_output ();
if (record_end - record_start < blocking_factor)
{
memset (record_end, 0,
(blocking_factor - (record_end - record_start))
* BLOCKSIZE);
record_end = record_start + blocking_factor;
return;
}
}
buffer_level = current_block->buffer - record_start->buffer;
record_start_block += record_end - record_start;
current_block = record_start;
record_end = record_start + blocking_factor;
switch (access_mode)
{
case ACCESS_READ:
@@ -1031,7 +1066,7 @@ backspace_output (void)
/* Seek back to the beginning of this record and start writing there. */
position -= record_size;
position -= record_end->buffer - record_start->buffer;
if (position < 0)
position = 0;
if (rmtlseek (archive, position, SEEK_SET) != position)
@@ -1092,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 ();
@@ -1112,6 +1147,16 @@ close_archive (void)
bufmap_free (NULL);
}
void
write_fatal_details (char const *name, ssize_t status, size_t size)
{
write_error_details (name, status, size);
if (rmtclose (archive) != 0)
close_error (*archive_name_cursor);
sys_wait_for_child (child_pid, false);
fatal_exit ();
}
/* Called to initialize the global volume number. */
void
init_volume_number (void)
@@ -1253,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"));
}
@@ -1406,7 +1450,10 @@ try_new_volume (void)
header = find_next_block ();
if (!header)
return false;
{
WARN ((0, 0, _("This does not look like a tar archive")));
return false;
}
switch (header->header.typeflag)
{
@@ -1416,7 +1463,7 @@ try_new_volume (void)
if (read_header (&header, &dummy, read_header_x_global)
!= HEADER_SUCCESS_EXTENDED)
{
ERROR ((0, 0, _("This does not look like a tar archive")));
WARN ((0, 0, _("This does not look like a tar archive")));
return false;
}
@@ -1445,7 +1492,7 @@ try_new_volume (void)
break;
default:
ERROR ((0, 0, _("This does not look like a tar archive")));
WARN ((0, 0, _("This does not look like a tar archive")));
return false;
}
break;
@@ -1455,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 =
@@ -1480,8 +1526,14 @@ try_new_volume (void)
if (bufmap_head)
{
uintmax_t s;
if (!continued_file_name
|| strcmp (continued_file_name, bufmap_head->file_name))
if (!continued_file_name)
{
WARN ((0, 0, _("%s is not continued on this volume"),
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)
&& strlen (bufmap_head->file_name) >= NAME_FIELD_SIZE
@@ -1603,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)
{
@@ -1647,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);
@@ -1679,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;
@@ -1689,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);
}
}
@@ -1720,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 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-2014 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
@@ -211,13 +216,20 @@ GLOBAL bool multi_volume_option;
do not get archived (also see after_date_option above). */
GLOBAL struct timespec newer_mtime_option;
/* If true, override actual mtime (see below) */
GLOBAL bool set_mtime_option;
/* Value to be put in mtime header field instead of the actual mtime */
enum set_mtime_option_mode
{
USE_FILE_MTIME,
FORCE_MTIME,
CLAMP_MTIME,
};
/* Override actual mtime if set to FORCE_MTIME or CLAMP_MTIME */
GLOBAL enum set_mtime_option_mode set_mtime_option;
/* Value to use when forcing or clamping the mtime header field. */
GLOBAL struct timespec mtime_option;
/* Return true if newer_mtime_option is initialized. */
#define NEWER_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
/* Return true if mtime_option or newer_mtime_option is initialized. */
#define TIME_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
/* Return true if the struct stat ST's M time is less than
newer_mtime_option. */
@@ -280,6 +292,19 @@ GLOBAL bool sparse_option;
GLOBAL unsigned tar_sparse_major;
GLOBAL unsigned tar_sparse_minor;
enum hole_detection_method
{
HOLE_DETECTION_DEFAULT,
HOLE_DETECTION_RAW,
HOLE_DETECTION_SEEK
};
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). */
@@ -315,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;
@@ -398,10 +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;
/* Warn about implicit use of the wildcards in command line arguments.
(Default for tar prior to 1.15.91, but changed afterwards */
GLOBAL bool warn_regex_usage;
/* Declarations for each module. */
@@ -453,7 +477,7 @@ void set_start_time (void);
#define TF_READ 0
#define TF_WRITE 1
#define TF_DELETED 2
int format_total_stats (FILE *fp, const char **formats, int eor, int eol);
int format_total_stats (FILE *fp, char const *const *formats, int eor, int eol);
void print_total_stats (void);
void mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft);
@@ -523,6 +547,8 @@ void extract_archive (void);
void extract_finish (void);
bool rename_directory (char *src, char *dst);
void remove_delayed_set_stat (const char *fname);
/* Module delete.c. */
void delete_archive_members (void);
@@ -605,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);
@@ -618,8 +648,6 @@ typedef struct namebuf *namebuf_t;
namebuf_t namebuf_create (const char *dir);
void namebuf_free (namebuf_t buf);
char *namebuf_name (namebuf_t buf, const char *name);
void namebuf_add_dir (namebuf_t buf, const char *name);
char *namebuf_finish (namebuf_t buf);
const char *tar_dirname (void);
@@ -714,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);
@@ -723,14 +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);
void name_add_name (const char *name, int matching_flags);
void name_add_dir (const char *name);
void name_add_file (const char *name, int term);
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);
@@ -739,7 +781,7 @@ void collect_and_sort_names (void);
struct name *name_scan (const char *name);
struct name const *name_from_list (void);
void blank_name_list (void);
char *new_name (const char *dir_name, const char *name);
char *make_file_name (const char *dir_name, const char *name);
size_t stripped_prefix_len (char const *file_name, size_t num);
bool all_names_found (struct tar_stat_info *st);
@@ -748,10 +790,12 @@ bool is_avoided_name (char const *name);
bool contains_dot_dot (char const *name);
#define ISFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
(c)->found_count == occurrence_option)
#define WASFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
(c)->found_count >= occurrence_option)
#define ISFOUND(c) (occurrence_option == 0 \
? (c)->found_count != 0 \
: (c)->found_count == occurrence_option)
#define WASFOUND(c) (occurrence_option == 0 \
? (c)->found_count != 0 \
: (c)->found_count >= occurrence_option)
/* Module tar.c. */
@@ -769,7 +813,46 @@ const char *subcommand_string (enum subcommand c);
void set_exit_status (int val);
void request_stdin (const char *option);
void more_options (int argc, char **argv);
int decode_signal (const char *);
/* Where an option comes from: */
enum option_source
{
OPTS_ENVIRON, /* Environment variable TAR_OPTIONS */
OPTS_COMMAND_LINE, /* Command line */
OPTS_FILE /* File supplied by --files-from */
};
/* Option location */
struct option_locus
{
enum option_source source; /* Option origin */
char const *name; /* File or variable name */
size_t line; /* Number of input line if source is OPTS_FILE */
struct option_locus *prev; /* Previous occurrence of the option of same
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. */
@@ -789,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);
@@ -893,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|\
@@ -904,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)
@@ -926,9 +1013,15 @@ extern void (*fatal_exit_hook) (void);
void excfile_add (const char *name, int flags);
void info_attach_exclist (struct tar_stat_info *dir);
void info_cleanup_exclist (struct tar_stat_info *dir);
void info_free_exclist (struct tar_stat_info *dir);
bool excluded_name (char const *name, struct tar_stat_info *st);
void exclude_vcs_ignores (void);
/* Module map.c */
void owner_map_read (char const *name);
int owner_map_translate (uid_t uid, uid_t *new_uid, char const **new_name);
void group_map_read (char const *file);
int group_map_translate (gid_t gid, gid_t *new_gid, char const **new_name);
_GL_INLINE_HEADER_END

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 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,18 +264,20 @@ 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
static void
diff_symlink (void)
{
char buf[1024];
size_t len = strlen (current_stat_info.link_name);
char *linkbuf = alloca (len + 1);
char *linkbuf = len < sizeof buf ? buf : xmalloc (len + 1);
int status = readlinkat (chdir_fd, current_stat_info.file_name,
linkbuf, len + 1);
ssize_t status = readlinkat (chdir_fd, current_stat_info.file_name,
linkbuf, len + 1);
if (status < 0)
{
@@ -285,8 +288,11 @@ diff_symlink (void)
report_difference (&current_stat_info, NULL);
}
else if (status != len
|| strncmp (current_stat_info.link_name, linkbuf, len) != 0)
|| memcmp (current_stat_info.link_name, linkbuf, len) != 0)
report_difference (&current_stat_info, _("Symlink differs"));
if (linkbuf != buf)
free (linkbuf);
}
#endif
@@ -473,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 Free Software Foundation, Inc.
Copyright 1985-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -22,6 +21,7 @@
#include <system.h>
#include <areadlink.h>
#include <quotearg.h>
#include "common.h"
@@ -201,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,
@@ -517,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;
}
@@ -541,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);
@@ -706,7 +710,7 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
{
type = XHDTYPE;
p = xheader_xhdr_name (st);
t = st->stat.st_mtime;
t = set_mtime_option ? mtime_option.tv_sec : st->stat.st_mtime;
}
xheader_write (type, p, t, &st->xhdr);
free (p);
@@ -740,17 +744,17 @@ union block *
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;
/* Override some stat fields, if requested to do so. */
owner_map_translate (st->stat.st_uid, &st->stat.st_uid, &uname);
group_map_translate (st->stat.st_gid, &st->stat.st_gid, &gname);
if (owner_option != (uid_t) -1)
st->stat.st_uid = owner_option;
if (group_option != (gid_t) -1)
st->stat.st_gid = group_option;
if (mode_option)
st->stat.st_mode =
((st->stat.st_mode & ~MODE_ALL)
@@ -822,7 +826,24 @@ start_header (struct tar_stat_info *st)
}
{
struct timespec mtime = set_mtime_option ? mtime_option : st->mtime;
struct timespec mtime;
switch (set_mtime_option)
{
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;
break;
}
if (archive_format == POSIX_FORMAT)
{
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec
@@ -895,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:
@@ -909,13 +930,13 @@ start_header (struct tar_stat_info *st)
}
else
{
if (owner_name_option)
st->uname = xstrdup (owner_name_option);
if (uname)
st->uname = xstrdup (uname);
else
uid_to_uname (st->stat.st_uid, &st->uname);
if (group_name_option)
st->gname = xstrdup (group_name_option);
if (gname)
st->gname = xstrdup (gname);
else
gid_to_gname (st->stat.st_gid, &st->gname);
@@ -1114,7 +1135,7 @@ dump_dir0 (struct tar_stat_info *st, char const *directory)
return;
info_attach_exclist (st);
if (incremental_option && archive_format != POSIX_FORMAT)
blk->header.typeflag = GNUTYPE_DUMPDIR;
else /* if (standard_option) */
@@ -1198,7 +1219,7 @@ dump_dir0 (struct tar_stat_info *st, char const *directory)
char const *entry;
size_t entry_len;
size_t name_len;
name_buf = xstrdup (st->orig_file_name);
name_size = name_len = strlen (name_buf);
@@ -1327,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 ();
@@ -1350,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;
@@ -1373,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);
}
@@ -1472,8 +1487,8 @@ dump_hard_link (struct tar_stat_info *st)
/* We found a link. */
char const *link_name = safer_name_suffix (duplicate->name, true,
absolute_names_option);
duplicate->nlink--;
if (duplicate->nlink)
duplicate->nlink--;
block_ordinal = current_block_ordinal ();
assign_string (&st->link_name, link_name);
@@ -1510,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)
@@ -1837,22 +1853,17 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
#ifdef HAVE_READLINK
else if (S_ISLNK (st->stat.st_mode))
{
char *buffer;
int size;
size_t linklen = st->stat.st_size;
if (linklen != st->stat.st_size || linklen + 1 == 0)
xalloc_die ();
buffer = (char *) alloca (linklen + 1);
size = readlinkat (parentfd, name, buffer, linklen + 1);
if (size < 0)
st->link_name = areadlinkat_with_size (parentfd, name, st->stat.st_size);
if (!st->link_name)
{
if (errno == ENOMEM)
xalloc_die ();
file_removed_diag (p, top_level, readlink_diag);
return;
}
buffer[size] = '\0';
assign_string (&st->link_name, buffer);
transform_name (&st->link_name, XFORM_SYMLINK);
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
< strlen (st->link_name))
write_long_link (st);
xattrs_selinux_get (parentfd, name, st, 0);

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 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 Free Software Foundation, Inc.
Copyright 2014-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -43,7 +43,7 @@ struct excfile
char name[1];
};
struct excfile *excfile_head, *excfile_tail;
static struct excfile *excfile_head, *excfile_tail;
void
excfile_add (const char *name, int flags)
@@ -72,7 +72,7 @@ info_attach_exclist (struct tar_stat_info *dir)
struct excfile *file;
struct exclist *head = NULL, *tail = NULL, *ent;
struct vcs_ignore_file *vcsfile;
if (dir->exclude_list)
return;
for (file = excfile_head; file; file = file->next)
@@ -102,16 +102,17 @@ info_attach_exclist (struct tar_stat_info *dir)
if (vcsfile->initfn)
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;
FATAL_ERROR ((0, e, "%s", quotearg_colon (file->name)));
}
fclose (fp);
ent = xmalloc (sizeof (*ent));
ent->excluded = ex;
ent->flags = file->flags == EXCL_DEFAULT
@@ -129,34 +130,6 @@ info_attach_exclist (struct tar_stat_info *dir)
dir->exclude_list = head;
}
void
info_cleanup_exclist (struct tar_stat_info *dir)
{
struct exclist *ep = dir->exclude_list;
while (ep)
{
struct exclist *next = ep->next;
if (ep->flags & EXCL_NON_RECURSIVE)
{
/* Remove the entry */
if (ep->prev)
ep->prev->next = ep->next;
else
dir->exclude_list = ep->next;
if (ep->next)
ep->next->prev = ep->prev;
free_exclude (ep->excluded);
free (ep);
}
ep = next;
}
}
void
info_free_exclist (struct tar_stat_info *dir)
{
@@ -172,7 +145,7 @@ info_free_exclist (struct tar_stat_info *dir)
dir->exclude_list = NULL;
}
/* Return nonzero if file NAME is excluded. */
bool
@@ -183,7 +156,7 @@ excluded_name (char const *name, struct tar_stat_info *st)
char *bname = NULL;
bool result;
int nr = 0;
name += FILE_SYSTEM_PREFIX_LEN (name);
/* Try global exclusion list first */
@@ -192,7 +165,7 @@ excluded_name (char const *name, struct tar_stat_info *st)
if (!st)
return false;
for (result = false; st && !result; st = st->parent, nr = EXCL_NON_RECURSIVE)
{
for (ep = st->exclude_list; ep; ep = ep->next)
@@ -201,7 +174,7 @@ excluded_name (char const *name, struct tar_stat_info *st)
continue;
if ((result = excluded_file_name (ep->excluded, name)))
break;
if (!rname)
{
rname = name;
@@ -229,8 +202,8 @@ cvs_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
struct wordsplit ws;
size_t i;
if (wordsplit (pattern, &ws,
if (wordsplit (pattern, &ws,
WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS))
return;
for (i = 0; i < ws.ws_wordc; i++)
@@ -278,22 +251,18 @@ bzr_addfn (struct exclude *ex, char const *pattern, int options, void *data)
static void *
hg_initfn (void *data)
{
int *hgopt;
static int hg_options;
if (!data)
hgopt = &hg_options;
int *hgopt = data ? data : &hg_options;
*hgopt = EXCLUDE_REGEX;
return hgopt;
}
static void
hg_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
int *hgopt = data;
size_t len;
while (isspace (*pattern))
++pattern;
if (*pattern == 0 || *pattern == '#')
@@ -318,27 +287,27 @@ hg_addfn (struct exclude *ex, char const *pattern, int options, void *data)
--len;
p = xmalloc (len+1);
memcpy (p, pattern, len);
memcpy (p, pattern, len);
p[len] = 0;
pattern = p;
exclude_add_pattern_buffer (ex, p);
options |= FNM_LEADING_DIR|EXCLUDE_ALLOC;
}
add_exclude (ex, pattern,
((*hgopt == EXCLUDE_REGEX)
? (options & ~EXCLUDE_WILDCARDS)
: (options & ~EXCLUDE_REGEX)) | *hgopt);
}
struct vcs_ignore_file vcs_ignore_files[] = {
static struct vcs_ignore_file vcs_ignore_files[] = {
{ ".cvsignore", EXCL_NON_RECURSIVE, cvs_addfn, NULL, NULL },
{ ".gitignore", 0, git_addfn, NULL, NULL },
{ ".bzrignore", 0, bzr_addfn, NULL, NULL },
{ ".hgignore", 0, hg_addfn, hg_initfn , NULL },
{ ".hgignore", 0, hg_addfn, hg_initfn, NULL },
{ NULL, 0, git_addfn, NULL, NULL }
};
static struct vcs_ignore_file *
get_vcs_ignore_file (const char *name)
{

View File

@@ -1,6 +1,6 @@
/* Exit from GNU tar.
Copyright 2009, 2013-2014 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 Free
Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -109,7 +108,7 @@ struct delayed_set_stat
struct xattr_array *xattr_map;
/* Length and contents of name. */
size_t file_name_len;
char file_name[1];
char *file_name;
};
static struct delayed_set_stat *delayed_set_stat_head;
@@ -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,26 +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 (offsetof (struct delayed_set_stat, file_name)
+ file_name_len + 1);
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->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)
@@ -492,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);
}
@@ -507,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)
@@ -537,6 +591,56 @@ repair_delayed_set_stat (char const *dir,
quotearg_colon (dir)));
}
static void
free_delayed_set_stat (struct delayed_set_stat *data)
{
free (data->file_name);
xheader_xattr_free (data->xattr_map, data->xattr_map_size);
free (data->cntx_name);
free (data->acls_a_ptr);
free (data->acls_d_ptr);
free (data);
}
void
remove_delayed_set_stat (const char *fname)
{
struct delayed_set_stat *data, *next, *prev = NULL;
for (data = delayed_set_stat_head; data; data = next)
{
next = data->next;
if (chdir_current == data->change_dir
&& strcmp (data->file_name, fname) == 0)
{
free_delayed_set_stat (data);
if (prev)
prev->next = next;
else
delayed_set_stat_head = next;
return;
}
else
prev = data;
}
}
static void
fixup_delayed_set_stat (char const *src, char const *dst)
{
struct delayed_set_stat *data;
for (data = delayed_set_stat_head; data; data = data->next)
{
if (chdir_current == data->change_dir
&& strcmp (data->file_name, src) == 0)
{
free (data->file_name);
data->file_name = xstrdup (dst);
data->file_name_len = strlen (dst);
return;
}
}
}
/* After a file/link/directory creation has failed, see if
it's because some required directory was not present, and if so,
create all required directories. Return zero if all the required
@@ -691,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. */
@@ -711,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:
@@ -723,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. */
@@ -746,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;
@@ -760,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
@@ -846,11 +964,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
}
delayed_set_stat_head = data->next;
xheader_xattr_free (data->xattr_map, data->xattr_map_size);
free (data->cntx_name);
free (data->acls_a_ptr);
free (data->acls_d_ptr);
free (data);
free_delayed_set_stat (data);
}
}
@@ -861,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 &&
@@ -870,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
@@ -899,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 (;;)
{
@@ -926,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))
{
@@ -933,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;
@@ -946,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;
}
}
@@ -1091,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,
@@ -1178,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:
@@ -1220,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);
@@ -1236,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;
@@ -1245,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;
@@ -1267,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;
@@ -1334,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))
@@ -1427,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:
@@ -1476,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. */
@@ -1584,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)))
{
@@ -1630,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. */
@@ -1709,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;
@@ -1741,7 +1929,9 @@ extract_finish (void)
bool
rename_directory (char *src, char *dst)
{
if (renameat (chdir_fd, src, chdir_fd, dst) != 0)
if (renameat (chdir_fd, src, chdir_fd, dst) == 0)
fixup_delayed_set_stat (src, dst);
else
{
int e = errno;
bool interdir_made;

View File

@@ -1,7 +1,6 @@
/* GNU dump extensions to tar.
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2009, 2013-2014
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
@@ -735,7 +744,7 @@ scan_directory (struct tar_stat_info *st)
savedir_error (dir);
info_attach_exclist (st);
tmp = xstrdup (dir);
zap_slashes (tmp);
@@ -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);
@@ -1155,11 +1158,14 @@ read_num (FILE *fp, char const *fieldname,
}
if (c)
FATAL_ERROR ((0, 0,
_("%s: byte %s: %s %s followed by invalid byte 0x%02x"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (fp), offbuf),
fieldname, buf, c));
{
unsigned uc = c;
FATAL_ERROR ((0, 0,
_("%s: byte %s: %s %s followed by invalid byte 0x%02x"),
quotearg_colon (listed_incremental_option),
offtostr (ftello (fp), offbuf),
fieldname, buf, uc));
}
*pval = strtosysint (buf, NULL, min_val, max_val);
conversion_errno = errno;
@@ -1541,9 +1547,10 @@ dumpdir_ok (char *dumpdir)
{
if (expect && *p != expect)
{
unsigned char uc = *p;
ERROR ((0, 0,
_("Malformed dumpdir: expected '%c' but found %#3o"),
expect, *p));
expect, uc));
return false;
}
switch (*p)
@@ -1578,7 +1585,7 @@ dumpdir_ok (char *dumpdir)
if (expect != 'T')
{
ERROR ((0, 0,
_("Malformed dumpdir: 'T' not preceeded by 'R'")));
_("Malformed dumpdir: 'T' not preceded by 'R'")));
return false;
}
if (p[1] == 0 && !has_tempdir)
@@ -1708,7 +1715,7 @@ try_purge_directory (char const *directory_name)
const char *entry;
struct stat st;
free (p);
p = new_name (directory_name, cur);
p = make_file_name (directory_name, cur);
if (deref_stat (p, &st) != 0)
{

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-2014 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,22 +119,24 @@ enforce_one_top_level (char **pfile_name)
{
char *file_name = *pfile_name;
char *p;
for (p = file_name; *p && (ISSLASH (*p) || *p == '.'); p++)
;
if (!*p)
return;
if (strncmp (p, one_top_level_dir, strlen (one_top_level_dir)) == 0)
if (*p)
{
int pos = strlen (one_top_level_dir);
if (ISSLASH (p[pos]) || p[pos] == 0)
return;
}
if (strncmp (p, one_top_level_dir, pos) == 0)
{
if (ISSLASH (p[pos]) || p[pos] == 0)
return;
}
*pfile_name = new_name (one_top_level_dir, file_name);
normalize_filename_x (*pfile_name);
*pfile_name = make_file_name (one_top_level_dir, file_name);
normalize_filename_x (*pfile_name);
}
else
*pfile_name = xstrdup (one_top_level_dir);
free (file_name);
}
@@ -193,7 +194,7 @@ read_and (void (*do_something) (void))
decode_header (current_header, &current_stat_info,
&current_format, 1);
if (! name_match (current_stat_info.file_name)
|| (NEWER_OPTION_INITIALIZED (newer_mtime_option)
|| (TIME_OPTION_INITIALIZED (newer_mtime_option)
/* FIXME: We get mtime now, and again later; this causes
duplicate diagnostics if header.mtime is bogus. */
&& ((mtime.tv_sec
@@ -216,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;
@@ -271,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)
@@ -408,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. */
@@ -437,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
@@ -447,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;
@@ -517,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! */
@@ -536,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
{
@@ -567,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
{
@@ -578,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')
@@ -630,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);
@@ -689,7 +707,6 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
}
}
stat_info->archive_file_size = stat_info->stat.st_size;
xheader_decode (stat_info);
if (sparse_member_p (stat_info))
@@ -1049,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;
}
@@ -1218,18 +1231,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
&& !numeric_owner_option)
user = st->uname;
else
{
/* Try parsing it as an unsigned integer first, and as a
uid_t if that fails. This method can list positive user
ids that are too large to fit in a uid_t. */
uintmax_t u = from_header (blk->header.uid,
sizeof blk->header.uid, 0,
0, UINTMAX_MAX,
false, false);
user = (u != -1
? STRINGIFY_BIGINT (u, uform)
: imaxtostr (UID_FROM_HEADER (blk->header.uid), uform));
}
user = STRINGIFY_BIGINT (st->stat.st_uid, uform);
if (st->gname
&& st->gname[0]
@@ -1237,18 +1239,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
&& !numeric_owner_option)
group = st->gname;
else
{
/* Try parsing it as an unsigned integer first, and as a
gid_t if that fails. This method can list positive group
ids that are too large to fit in a gid_t. */
uintmax_t g = from_header (blk->header.gid,
sizeof blk->header.gid, 0,
0, UINTMAX_MAX,
false, false);
group = (g != -1
? STRINGIFY_BIGINT (g, gform)
: imaxtostr (GID_FROM_HEADER (blk->header.gid), gform));
}
group = STRINGIFY_BIGINT (st->stat.st_gid, gform);
/* Format the file size or major/minor device numbers. */
@@ -1465,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)
{

283
src/map.c Normal file
View File

@@ -0,0 +1,283 @@
/* Owner/group mapping for tar
Copyright 2015-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/>. */
#include <system.h>
#include "common.h"
#include "wordsplit.h"
#include <hash.h>
#include <pwd.h>
struct mapentry
{
uintmax_t orig_id;
uintmax_t new_id;
char *new_name;
};
static size_t
map_hash (void const *entry, size_t nbuckets)
{
struct mapentry const *map = entry;
return map->orig_id % nbuckets;
}
static bool
map_compare (void const *entry1, void const *entry2)
{
struct mapentry const *map1 = entry1;
struct mapentry const *map2 = entry2;
return map1->orig_id == map2->orig_id;
}
static int
parse_id (uintmax_t *retval,
char const *arg, char const *what, uintmax_t maxval,
char const *file, unsigned line)
{
uintmax_t v;
char *p;
errno = 0;
v = strtoumax (arg, &p, 10);
if (*p || errno)
{
error (0, 0, _("%s:%u: invalid %s: %s"), file, line, what, arg);
return -1;
}
if (v > maxval)
{
error (0, 0, _("%s:%u: %s out of range: %s"), file, line, what, arg);
return -1;
}
*retval = v;
return 0;
}
static void
map_read (Hash_table **ptab, char const *file,
uintmax_t (*name_to_id) (char const *), char const *what,
uintmax_t maxval)
{
FILE *fp;
char *buf = NULL;
size_t bufsize = 0;
ssize_t n;
struct wordsplit ws;
int wsopt;
unsigned line;
int err = 0;
fp = fopen (file, "r");
if (!fp)
open_fatal (file);
ws.ws_comment = "#";
wsopt = WRDSF_COMMENT | WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS
| WRDSF_QUOTE;
line = 0;
while ((n = getline (&buf, &bufsize, fp)) > 0)
{
struct mapentry *ent;
uintmax_t orig_id, new_id;
char *name = NULL;
char *colon;
++line;
if (wordsplit (buf, &ws, wsopt))
FATAL_ERROR ((0, 0, _("%s:%u: cannot split line: %s"),
file, line, wordsplit_strerror (&ws)));
wsopt |= WRDSF_REUSE;
if (ws.ws_wordc == 0)
continue;
if (ws.ws_wordc != 2)
{
error (0, 0, _("%s:%u: malformed line"), file, line);
err = 1;
continue;
}
if (ws.ws_wordv[0][0] == '+')
{
if (parse_id (&orig_id, ws.ws_wordv[0]+1, what, maxval, file, line))
{
err = 1;
continue;
}
}
else if (name_to_id)
{
orig_id = name_to_id (ws.ws_wordv[0]);
if (orig_id == UINTMAX_MAX)
{
error (0, 0, _("%s:%u: can't obtain %s of %s"),
file, line, what, ws.ws_wordv[0]);
err = 1;
continue;
}
}
colon = strchr (ws.ws_wordv[1], ':');
if (colon)
{
if (colon > ws.ws_wordv[1])
name = ws.ws_wordv[1];
*colon++ = 0;
if (parse_id (&new_id, colon, what, maxval, file, line))
{
err = 1;
continue;
}
}
else if (ws.ws_wordv[1][0] == '+')
{
if (parse_id (&new_id, ws.ws_wordv[1], what, maxval, file, line))
{
err = 1;
continue;
}
}
else
{
name = ws.ws_wordv[1];
new_id = name_to_id (ws.ws_wordv[1]);
if (new_id == UINTMAX_MAX)
{
error (0, 0, _("%s:%u: can't obtain %s of %s"),
file, line, what, ws.ws_wordv[1]);
err = 1;
continue;
}
}
ent = xmalloc (sizeof (*ent));
ent->orig_id = orig_id;
ent->new_id = new_id;
ent->new_name = name ? xstrdup (name) : NULL;
if (!((*ptab
|| (*ptab = hash_initialize (0, 0, map_hash, map_compare, 0)))
&& hash_insert (*ptab, ent)))
xalloc_die ();
}
if (wsopt & WRDSF_REUSE)
wordsplit_free (&ws);
fclose (fp);
if (err)
FATAL_ERROR ((0, 0, _("errors reading map file")));
}
/* UID translation */
static Hash_table *owner_map;
static uintmax_t
name_to_uid (char const *name)
{
struct passwd *pw = getpwnam (name);
return pw ? pw->pw_uid : UINTMAX_MAX;
}
void
owner_map_read (char const *file)
{
map_read (&owner_map, file, name_to_uid, "UID", TYPE_MAXIMUM (uid_t));
}
int
owner_map_translate (uid_t uid, uid_t *new_uid, char const **new_name)
{
int rc = 1;
if (owner_map)
{
struct mapentry ent, *res;
ent.orig_id = uid;
res = hash_lookup (owner_map, &ent);
if (res)
{
*new_uid = res->new_id;
*new_name = res->new_name;
return 0;
}
}
if (owner_option != (uid_t) -1)
{
*new_uid = owner_option;
rc = 0;
}
if (owner_name_option)
{
*new_name = owner_name_option;
rc = 0;
}
return rc;
}
/* GID translation */
static Hash_table *group_map;
static uintmax_t
name_to_gid (char const *name)
{
struct group *gr = getgrnam (name);
return gr ? gr->gr_gid : UINTMAX_MAX;
}
void
group_map_read (char const *file)
{
map_read (&group_map, file, name_to_gid, "GID", TYPE_MAXIMUM (gid_t));
}
int
group_map_translate (gid_t gid, gid_t *new_gid, char const **new_name)
{
int rc = 1;
if (group_map)
{
struct mapentry ent, *res;
ent.orig_id = gid;
res = hash_lookup (group_map, &ent);
if (res)
{
*new_gid = res->new_id;
*new_name = res->new_name;
return 0;
}
}
if (group_option != (uid_t) -1)
{
*new_gid = group_option;
rc = 0;
}
if (group_name_option)
{
*new_name = group_name_option;
rc = 0;
}
return rc;
}

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 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
@@ -29,8 +28,15 @@
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
#endif
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. */
@@ -43,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? */
@@ -294,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]));
@@ -586,7 +604,12 @@ safer_rmdir (const char *file_name)
return -1;
}
return unlinkat (chdir_fd, file_name, AT_REMOVEDIR);
if (unlinkat (chdir_fd, file_name, AT_REMOVEDIR) == 0)
{
remove_delayed_set_stat (file_name);
return 0;
}
return -1;
}
/* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory,
@@ -650,7 +673,7 @@ remove_any_file (const char *file_name, enum remove_option option)
(entrylen = strlen (entry)) != 0;
entry += entrylen + 1)
{
char *file_name_buffer = new_name (file_name, entry);
char *file_name_buffer = make_file_name (file_name, entry);
int r = remove_any_file (file_name_buffer,
RECURSIVE_REMOVE_OPTION);
int e = errno;
@@ -715,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 ();
@@ -885,8 +908,6 @@ chdir_count (void)
int
chdir_arg (char const *dir)
{
char *absdir;
if (wd_count == wd_alloc)
{
if (wd_alloc == 0)
@@ -896,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++;
}
@@ -913,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++;
}
@@ -1022,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;
}
@@ -1032,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);
}
@@ -1041,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);
}
@@ -1050,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);
}
@@ -1059,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);
}
@@ -1068,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);
}
@@ -1077,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);
}
@@ -1086,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);
}
@@ -1106,13 +1172,6 @@ file_removed_diag (const char *name, bool top_level,
diagfn (name);
}
void
write_fatal_details (char const *name, ssize_t status, size_t size)
{
write_error_details (name, status, size);
fatal_exit ();
}
/* Fork, aborting if unsuccessful. */
pid_t
xfork (void)
@@ -1197,7 +1256,7 @@ namebuf_name (namebuf_t buf, const char *name)
return buf->buffer;
}
void
static void
namebuf_add_dir (namebuf_t buf, const char *name)
{
static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
@@ -1210,7 +1269,7 @@ namebuf_add_dir (namebuf_t buf, const char *name)
buf->dir_length += strlen (name);
}
char *
static char *
namebuf_finish (namebuf_t buf)
{
char *res = buf->buffer;

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* Functions for dealing with sparse files
Copyright 2003-2007, 2010, 2013-2014 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
@@ -208,9 +208,9 @@ sparse_add_map (struct tar_stat_info *st, struct sp_array const *sp)
st->sparse_map_avail = avail + 1;
}
/* Scan the sparse file and create its map */
/* Scan the sparse file byte-by-byte and create its map. */
static bool
sparse_scan_file (struct tar_sparse_file *file)
sparse_scan_file_raw (struct tar_sparse_file *file)
{
struct tar_stat_info *st = file->stat_info;
int fd = file->fd;
@@ -221,41 +221,38 @@ sparse_scan_file (struct tar_sparse_file *file)
st->archive_file_size = 0;
if (ST_NBLOCKS (st->stat) == 0)
offset = st->stat.st_size;
else
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = blocking_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
{
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
/* Analyze the block. */
if (zero_block_p (buffer, count))
{
if (sp.numbytes)
{
sparse_add_map (st, &sp);
sp.numbytes = 0;
if (!tar_sparse_scan (file, scan_block, NULL))
return false;
}
}
else
{
if (sp.numbytes == 0)
sp.offset = offset;
sp.numbytes += count;
st->archive_file_size += count;
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
while ((count = blocking_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
{
/* Analyze the block. */
if (zero_block_p (buffer, count))
{
if (sp.numbytes)
{
sparse_add_map (st, &sp);
sp.numbytes = 0;
if (!tar_sparse_scan (file, scan_block, NULL))
return false;
}
}
else
{
if (sp.numbytes == 0)
sp.offset = offset;
sp.numbytes += count;
st->archive_file_size += count;
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
offset += count;
}
offset += count;
}
/* save one more sparse segment of length 0 to indicate that
the file ends with a hole */
if (sp.numbytes == 0)
sp.offset = offset;
@@ -264,6 +261,115 @@ sparse_scan_file (struct tar_sparse_file *file)
return tar_sparse_scan (file, scan_end, NULL);
}
static bool
sparse_scan_file_wholesparse (struct tar_sparse_file *file)
{
struct tar_stat_info *st = file->stat_info;
struct sp_array sp = {0, 0};
/* Note that this function is called only for truly sparse files of size >= 1
block size (checked via ST_IS_SPARSE before). See the thread
http://www.mail-archive.com/bug-tar@gnu.org/msg04209.html for more info */
if (ST_NBLOCKS (st->stat) == 0)
{
st->archive_file_size = 0;
sp.offset = st->stat.st_size;
sparse_add_map (st, &sp);
return true;
}
return false;
}
#ifdef SEEK_HOLE
/* Try to engage SEEK_HOLE/SEEK_DATA feature. */
static bool
sparse_scan_file_seek (struct tar_sparse_file *file)
{
struct tar_stat_info *st = file->stat_info;
int fd = file->fd;
struct sp_array sp = {0, 0};
off_t offset = 0;
off_t data_offset;
off_t hole_offset;
st->archive_file_size = 0;
for (;;)
{
/* locate first chunk of data */
data_offset = lseek (fd, offset, SEEK_DATA);
if (data_offset == (off_t)-1)
/* ENXIO == EOF; error otherwise */
{
if (errno == ENXIO)
{
/* file ends with hole, add one more empty chunk of data */
sp.numbytes = 0;
sp.offset = st->stat.st_size;
sparse_add_map (st, &sp);
return true;
}
return false;
}
hole_offset = lseek (fd, data_offset, SEEK_HOLE);
/* according to specs, if FS does not fully support
SEEK_DATA/SEEK_HOLE it may just implement kind of "wrapper" around
classic lseek() call. We must detect it here and try to use other
hole-detection methods. */
if (offset == 0 /* first loop */
&& data_offset == 0
&& hole_offset == st->stat.st_size)
{
lseek (fd, 0, SEEK_SET);
return false;
}
sp.offset = data_offset;
sp.numbytes = hole_offset - data_offset;
sparse_add_map (st, &sp);
st->archive_file_size += sp.numbytes;
offset = hole_offset;
}
return true;
}
#endif
static bool
sparse_scan_file (struct tar_sparse_file *file)
{
/* always check for completely sparse files */
if (sparse_scan_file_wholesparse (file))
return true;
switch (hole_detection)
{
case HOLE_DETECTION_DEFAULT:
case HOLE_DETECTION_SEEK:
#ifdef SEEK_HOLE
if (sparse_scan_file_seek (file))
return true;
#else
if (hole_detection == HOLE_DETECTION_SEEK)
WARN((0, 0,
_("\"seek\" hole detection is not supported, using \"raw\".")));
/* 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;
}
static struct tar_sparse_optab const oldgnu_optab;
static struct tar_sparse_optab const star_optab;
static struct tar_sparse_optab const pax_optab;
@@ -321,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;
@@ -358,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)
@@ -492,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)];
@@ -503,6 +639,7 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
beg += bytes_read;
}
return true;
}
@@ -529,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)
{
@@ -539,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;
@@ -560,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;
@@ -1107,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; \
@@ -1123,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; \
} \
@@ -1134,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)))
@@ -1172,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 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,6 +1,6 @@
/* System-dependent calls for tar.
Copyright 2003-2008, 2010, 2013-2014 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
@@ -26,13 +26,14 @@
static _Noreturn void
xexec (const char *cmd)
{
struct wordsplit ws;
char *argv[4];
ws.ws_env = (const char **) environ;
if (wordsplit (cmd, &ws, (WRDSF_DEFFLAGS | WRDSF_ENV) & ~WRDSF_NOVAR))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
cmd, wordsplit_strerror (&ws)));
execvp (ws.ws_wordv[0], ws.ws_wordv);
argv[0] = (char *) "/bin/sh";
argv[1] = (char *) "-c";
argv[2] = (char *) cmd;
argv[3] = NULL;
execv ("/bin/sh", argv);
exec_fatal (cmd);
}
@@ -330,6 +331,7 @@ sys_child_open_for_compress (void)
pid_t grandchild_pid;
pid_t child_pid;
signal (SIGPIPE, SIG_IGN);
xpipe (parent_pipe);
child_pid = xfork ();

1462
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 Free
Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -327,6 +326,14 @@ struct tar_stat_info
size_t sparse_map_size; /* Size of the sparse map */
struct sp_array *sparse_map;
off_t real_size; /* The real size of sparse file */
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 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);
@@ -378,13 +380,15 @@ parse_transform_expr (const char *expr)
break;
default:
/* Try to be nice */
{
char buf[2];
buf[0] = '\\';
buf[1] = *cur;
add_literal_segment (tf, buf, buf + 2);
}
if (*cur == delim)
add_char_segment (tf, delim);
else
{
char buf[2];
buf[0] = '\\';
buf[1] = *cur;
add_literal_segment (tf, buf, buf + 2);
}
cur++;
break;
}
@@ -400,6 +404,7 @@ parse_transform_expr (const char *expr)
cur++;
}
add_literal_segment (tf, beg, cur);
free(str);
return p;
}
@@ -547,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 Free Software Foundation, Inc.
Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -32,6 +32,10 @@ struct deferred_unlink
entry got added to the queue */
};
#define IS_CWD(p) \
((p)->is_dir \
&& ((p)->file_name[0] == 0 || strcmp ((p)->file_name, ".") == 0))
/* The unlink queue */
static struct deferred_unlink *dunlink_head, *dunlink_tail;
@@ -60,6 +64,24 @@ dunlink_alloc (void)
return p;
}
static void
dunlink_insert (struct deferred_unlink *anchor, struct deferred_unlink *p)
{
if (anchor)
{
p->next = anchor->next;
anchor->next = p;
}
else
{
p->next = dunlink_head;
dunlink_head = p;
}
if (!p->next)
dunlink_tail = p;
dunlink_count++;
}
static void
dunlink_reclaim (struct deferred_unlink *p)
{
@@ -73,7 +95,7 @@ flush_deferred_unlinks (bool force)
{
struct deferred_unlink *p, *prev = NULL;
int saved_chdir = chdir_current;
for (p = dunlink_head; p; )
{
struct deferred_unlink *next = p->next;
@@ -86,12 +108,11 @@ flush_deferred_unlinks (bool force)
{
const char *fname;
if (p->dir_idx
&& (p->file_name[0] == 0
|| strcmp (p->file_name, ".") == 0))
if (p->dir_idx && IS_CWD (p))
{
fname = tar_dirname ();
chdir_do (p->dir_idx - 1);
prev = p;
p = next;
continue;
}
else
fname = p->file_name;
@@ -103,16 +124,18 @@ flush_deferred_unlinks (bool force)
case ENOENT:
/* nothing to worry about */
break;
case EEXIST:
/* OpenSolaris >=10 sets EEXIST instead of ENOTEMPTY
if trying to remove a non-empty directory */
#if defined ENOTEMPTY && ENOTEMPTY != EEXIST
case ENOTEMPTY:
if (!force)
{
/* Keep the record in list, in the hope we'll
be able to remove it later */
prev = p;
p = next;
continue;
}
/* fall through */
#endif
/* Keep the record in list, in the hope we'll
be able to remove it later */
prev = p;
p = next;
continue;
default:
rmdir_error (fname);
}
@@ -139,6 +162,34 @@ flush_deferred_unlinks (bool force)
}
if (!dunlink_head)
dunlink_tail = NULL;
else if (force)
{
for (p = dunlink_head; p; )
{
struct deferred_unlink *next = p->next;
const char *fname;
chdir_do (p->dir_idx);
if (p->dir_idx && IS_CWD (p))
{
fname = tar_dirname ();
chdir_do (p->dir_idx - 1);
}
else
fname = p->file_name;
if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
{
if (errno != ENOENT)
rmdir_error (fname);
}
dunlink_reclaim (p);
dunlink_count--;
p = next;
}
dunlink_head = dunlink_tail = NULL;
}
chdir_do (saved_chdir);
}
@@ -146,6 +197,7 @@ void
finish_deferred_unlinks (void)
{
flush_deferred_unlinks (true);
while (dunlink_avail)
{
struct deferred_unlink *next = dunlink_avail->next;
@@ -171,10 +223,17 @@ queue_deferred_unlink (const char *name, bool is_dir)
p->is_dir = is_dir;
p->records_written = records_written;
if (dunlink_tail)
dunlink_tail->next = p;
if (IS_CWD (p))
{
struct deferred_unlink *q, *prev;
for (q = dunlink_head, prev = NULL; q; prev = q, q = q->next)
if (IS_CWD (q) && q->dir_idx < p->dir_idx)
break;
if (q)
dunlink_insert (prev, p);
else
dunlink_insert (dunlink_tail, p);
}
else
dunlink_head = p;
dunlink_tail = p;
dunlink_count++;
dunlink_insert (dunlink_tail, 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 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,6 +1,6 @@
/* Charset handling for GNU tar.
Copyright 2004, 2006-2007, 2013-2014 Free Software Foundation, Inc.
Copyright 2004-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -35,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
@@ -64,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)
@@ -80,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 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 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 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 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)
{
@@ -755,6 +790,16 @@ xheader_decode (struct tar_stat_info *st)
continue;
}
run_override_list (keyword_override_list, st);
/* The archived (effective) file size is always set directly in tar header
field, possibly overridden by "size" extended header - in both cases,
result is now decoded in st->stat.st_size */
st->archive_file_size = st->stat.st_size;
/* The real file size (given by stat()) may be redefined for sparse
files in "GNU.sparse.realsize" extended header */
if (st->real_size_set)
st->stat.st_size = st->real_size;
}
static void
@@ -803,11 +848,11 @@ xheader_store (char const *keyword, struct tar_stat_info *st,
t = locate_handler (keyword);
if (!t || !t->coder)
return;
if (xheader_keyword_deleted_p (keyword)
|| xheader_keyword_override_p (keyword))
if (xheader_keyword_deleted_p (keyword))
return;
xheader_init (&st->xhdr);
t->coder (st, keyword, &st->xhdr, data);
if (!xheader_keyword_override_p (keyword))
t->coder (st, keyword, &st->xhdr, data);
}
void
@@ -1017,7 +1062,7 @@ xheader_string_end (struct xheader *xhdr, char const *keyword)
}
x_obstack_blank (xhdr, p);
x_obstack_1grow (xhdr, '\n');
cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
cp = (char*) obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
memmove (cp + p, cp, xhdr->string_length);
cp = stpcpy (cp, np);
*cp++ = ' ';
@@ -1280,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
@@ -1360,7 +1423,10 @@ sparse_size_decoder (struct tar_stat_info *st,
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
st->stat.st_size = u;
{
st->real_size_set = true;
st->real_size = u;
}
}
static void
@@ -1443,13 +1509,13 @@ sparse_map_decoder (struct tar_stat_info *st,
size_t size __attribute__((unused)))
{
int offset = 1;
struct sp_array e;
st->sparse_map_avail = 0;
while (1)
{
intmax_t u;
char *delim;
struct sp_array e;
if (!ISDIGIT (*arg))
{
@@ -1717,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 },

5
tests/.gitignore vendored
View File

@@ -8,3 +8,8 @@ argcv.c
argcv.h
genfile.c
genfile
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-2013 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,28 +46,42 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## ------------ ##
TESTSUITE_AT = \
testsuite.at\
compress.m4\
T-cd.at\
T-dir00.at\
T-dir01.at\
T-empty.at\
T-null.at\
T-null2.at\
T-rec.at\
T-recurse.at\
T-zfile.at\
T-nonl.at\
T-mult.at\
T-nest.at\
testsuite.at\
add-file.at\
append.at\
append01.at\
append02.at\
append03.at\
append04.at\
append05.at\
backup01.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\
@@ -100,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\
@@ -114,9 +139,10 @@ TESTSUITE_AT = \
incr07.at\
incr08.at\
incr09.at\
incr10.at\
incr11.at\
indexfile.at\
ignfail.at\
iotty.at\
label01.at\
label02.at\
label03.at\
@@ -136,6 +162,7 @@ TESTSUITE_AT = \
lustar01.at\
lustar02.at\
lustar03.at\
map.at\
multiv01.at\
multiv02.at\
multiv03.at\
@@ -144,19 +171,27 @@ TESTSUITE_AT = \
multiv06.at\
multiv07.at\
multiv08.at\
multiv09.at\
multiv10.at\
numeric.at\
old.at\
onetop01.at\
onetop02.at\
onetop03.at\
onetop04.at\
onetop05.at\
opcomp01.at\
opcomp02.at\
opcomp03.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\
@@ -166,6 +201,7 @@ TESTSUITE_AT = \
rename03.at\
rename04.at\
rename05.at\
rename06.at\
remfiles01.at\
remfiles02.at\
remfiles03.at\
@@ -198,16 +234,24 @@ TESTSUITE_AT = \
sparse02.at\
sparse03.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\
@@ -215,6 +259,8 @@ TESTSUITE_AT = \
version.at\
xform-h.at\
xform01.at\
xform02.at\
xform03.at\
star/gtarfail.at\
star/gtarfail2.at\
star/multi-fail.at\
@@ -226,6 +272,8 @@ TESTSUITE_AT = \
xattr03.at\
xattr04.at\
xattr05.at\
xattr06.at\
xattr07.at\
acls01.at\
acls02.at\
acls03.at\
@@ -233,6 +281,9 @@ TESTSUITE_AT = \
selacl01.at\
capabs_raw01.at
distclean-local:
-rm -rf download
TESTSUITE = $(srcdir)/testsuite
AUTOTEST = $(AUTOM4TE) --language=autotest
@@ -255,7 +306,7 @@ check-full:
#check_SCRIPTS = tar
# Run the test suite on the *installed* tree.
installcheck-local:
installcheck-local: $(check_PROGRAMS)
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS) AUTOTEST_PATH=$(exec_prefix)/bin
@@ -263,15 +314,10 @@ installcheck-local:
## genfile ##
## ------------ ##
check_PROGRAMS = genfile
if TAR_COND_GRANTPT
check_PROGRAMS += ttyemu
endif
check_PROGRAMS = genfile checkseekhole ckmtime
genfile_SOURCES = genfile.c argcv.c argcv.h
ttyemu_SOURCES = ttyemu.c
checkseekhole_SOURCES = checkseekhole.c
localedir = $(datadir)/locale
AM_CPPFLAGS = \

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 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

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

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2014-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/>.
# Tar 1.27 and 1.28 did not extract files under directory members listed
# in the file read by --file-from.
#
# Reported-by: Jean-Louis Martineau <martineau@zmanda.com>
# References: <541AE02C.2050008@zmanda.com>,
# http://lists.gnu.org/archive/html/bug-tar/2014-09/msg00006.html
AT_SETUP([recursive extraction from --files-from])
AT_KEYWORDS([files-from extract T-dir T-dir00])
AT_TAR_CHECK([
AT_SORT_PREREQ
mkdir dir
genfile -f dir/file1
genfile -f dir/file2
tar cf archive dir
rm -rf dir
echo dir > list
tar xfTv archive list | sort
],
[0],
[dir/
dir/file1
dir/file2
])
AT_CLEANUP

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

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2014-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/>.
# Tar 1.27 and 1.28 did not remove trailing slashes from file names
# obtained with the --file-from option.
#
# Reported-by: Jean-Louis Martineau <martineau@zmanda.com>
# References: <541AE02C.2050008@zmanda.com>,
# http://lists.gnu.org/archive/html/bug-tar/2014-09/msg00006.html
AT_SETUP([trailing slash in --files-from])
AT_KEYWORDS([files-from extract T-dir T-dir01])
AT_TAR_CHECK([
AT_SORT_PREREQ
mkdir dir
genfile -f dir/file1
genfile -f dir/file2
tar cf archive dir
rm -rf dir
echo dir/ > list
tar xfTv archive list | sort
],
[0],
[dir/
dir/file1
dir/file2
])
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 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 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 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 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 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

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

@@ -0,0 +1,46 @@
# This file is part of test suite for GNU tar. -*- Autotest -*-
# 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
# 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([--null enables verbatim reading])
AT_KEYWORDS([files-from null T-null2 T-verbatim])
# According to the docs, --null should read each line from the file
# list verbatim. This feature was broken by commit 26538c9b (tar version
# 1.27).
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 -
],
[0],
[a
-b
--c d
:\\\\.jpg
],
[],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

View File

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

90
tests/T-recurse.at Normal file
View File

@@ -0,0 +1,90 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright 2015-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/>.
# Description: Test interaction of --recursion and --no-recursion options
# together with --files-from option. This is complementary to recurs02.at test
# case. References:
# <alpine.LSU.2.11.1502201029580.29773@nerf60.vanv.qr>
# http://lists.gnu.org/archive/html/bug-tar/2015-06/msg00006.html
AT_SETUP([files-from & recurse: toggle])
AT_KEYWORDS([recurse T-recurse files-from])
AT_TAR_CHECK([
mkdir directory1 directory2
touch directory1/file directory2/file
AT_DATA([F1],[--no-recursion
directory1/
--recursion
directory2/
])
AT_DATA([F2A],[directory1/
])
AT_DATA([F2B],[directory2/
])
a=archive
tar cf "$a" --files-from F1
tar tf "$a"
a=archive2
tar cf "$a" --no-recursion -T F2A --recursion -T F2B
tar tf "$a"
],
[0],
[directory1/
directory2/
directory2/file
directory1/
directory2/
directory2/file
])
AT_CLEANUP
AT_SETUP([toggle --recursion (not) from -T])
AT_KEYWORDS([recurse T-recurse T-recurse2 files-from])
AT_TAR_CHECK([
mkdir directory1 directory2
touch directory1/file directory2/file
AT_DATA([F1],[--no-recursion
directory1/
])
AT_DATA([F2],[directory2/
])
tar cf archive -T F1 --recursion -T F2
tar tf archive
],
[0],
[directory1/
directory2/
directory2/file
])
AT_CLEANUP

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2014 Free Software Foundation, Inc.
# Copyright 2013-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