1 Commits

Author SHA1 Message Date
Sergey Poznyakoff
bf28f95b3a Version 1.34 2021-02-13 13:11:01 +02:00
326 changed files with 2523 additions and 4253 deletions

44
.gitignore vendored
View File

@@ -1,32 +1,32 @@
*.[aios]
*.[gx]z
*.bz2
*.cache
*.diff
*.a
*.la
*.lo
*.orig
*.patch
*.rej
*.o
*.so
*DISTFILES
*~
.bootstrap
.deps
.emacs*
.libs
.gdbinit
/.bootstrap
/ABOUT-NLS
/ChangeLog
/INSTALL
/Make.rules
/aclocal.m4
/build-aux/
/conf*
!/configure.ac
/gnu/
/m4/
/rmt/
/stamp-h1
ABOUT-NLS
ChangeLog
INSTALL
Make.rules
Makefile
Makefile.in
aclocal.m4
autom4te.cache
build-aux
build-aux/
config.h
config.h.in
config.log
config.status
configure
gnu
libtool
m4
rmt
stamp-h1
TAGS

View File

@@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
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 <https://www.gnu.org/licenses/>.
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -2,7 +2,7 @@ Currently there is just one ChangeLog file for tar, but
there used to be separate ChangeLog files for each subdirectory.
This file records what used to be in those separate files.
Copyright 1989-1997, 2013, 2023 Free Software Foundation, Inc.
Copyright 1989-1997, 2013 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -2,8 +2,7 @@ Currently the ChangeLog is generated automatically from the Git
revision history, but from 1997 to 2009 the ChangeLog file was
maintained by hand, under CVS. This file records the older log.
Copyright 1997-2001, 2003-2009, 2013, 2023 Free Software Foundation,
Inc.
Copyright 1997-2001, 2003-2009, 2013 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
# Main Makefile for GNU tar.
# Copyright 1994-2023 Free Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

66
NEWS
View File

@@ -1,57 +1,5 @@
GNU tar NEWS - User visible changes. 2023-07-18
GNU tar NEWS - User visible changes. 2021-02-13
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.35 - Sergey Poznyakoff, 2023-07-18
* Fail when building GNU tar, if the platform supports 64-bit time_t
but the build uses only 32-bit time_t.
* Leave the devmajor and devminor fields empty (rather than zero) for
non-special files, as this is more compatible with traditional tar.
* Bug fixes
** Fix interaction of --update with --wildcards.
** When extracting archives into an empty directory, do not create
hard links to files outside that directory.
** Handle partial reads from regular files.
** Warn "file changed as we read it" less often.
Formerly, tar warned if the file's size or ctime changed.
However, this generated a false positive if tar read a file
while another process hard-linked to it, changing its ctime.
Now, tar warns if the file's size, mtime, user ID, group ID,
or mode changes. Although neither heuristic is perfect,
the new one should work better in practice.
** Fix --ignore-failed-read to ignore file-changed read errors
as far as exit status is concerned. You can now suppress file-changed
issues entirely with --ignore-failed-read --warning=no-file-changed.
** Fix --remove-files to not remove a file that changed while we read it.
** Fix --atime-preserve=replace to not fail if there was no need to replace,
either because we did not read the file, or the atime did not change.
** Fix race when creating a parent directory while another process is
also doing so.
** Fix handling of prefix keywords not followed by "." in pax headers.
** Fix handling of out-of-range sparse entries in pax headers.
** Fix handling of --transform='s/s/@/2'.
** Fix treatment of options ending in / in files-from list.
** Fix crash on 'tar --checkpoint-action exec=\"'.
** Fix low-memory crash when reading incremental dumps.
** Fix --exclude-vcs-ignores memory allocation misuse.
version 1.34 - Sergey Poznyakoff, 2021-02-13
@@ -72,7 +20,7 @@ See https://lists.gnu.org/archive/html/bug-tar/2021-01/msg00026.html
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.
@@ -84,7 +32,7 @@ the pid.
* 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.
@@ -94,9 +42,9 @@ owned by the current user that did not have the S_IWUSR bit set.
* 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,
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.
@@ -1786,7 +1734,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
Copyright 1994-2023 Free Software Foundation, Inc.
Copyright 1994-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -1806,7 +1754,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
Local variables:
mode: outline
paragraph-separate: "[ ]*$"
eval: (add-hook 'write-file-functions #'time-stamp nil t)
eval: (add-hook 'write-file-hooks 'time-stamp)
time-stamp-start: "changes. "
time-stamp-format: "%:y-%02m-%02d"
time-stamp-end: "\n"

2
README
View File

@@ -221,7 +221,7 @@ and share your findings by writing to <bug-tar@gnu.org>.
* Copying
Copyright 1990-2023 Free Software Foundation, Inc.
Copyright 1990-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -3,9 +3,39 @@ This is GNU tar.
This is a *pre-release* version, and not ready for production use yet.
Please send comments and problem reports to <bug-tar@gnu.org>.
If you have taken the sources from CVS you will need the following
packages (or later) to build GNU tar. We don't make any extra effort
to accommodate older versions of these packages, so please make sure
that you have the latest stable version.
- Automake <http://www.gnu.org/software/automake/>
- Autoconf <http://www.gnu.org/software/autoconf/>
- Bison <http://www.gnu.org/software/bison/>
- Gettext <http://www.gnu.org/software/gettext/>
- Gzip <http://www.gnu.org/software/gzip/>
- M4 <http://www.gnu.org/software/m4/>
- Texinfo <http://www.gnu.org/software/texinfo>
- Wget <http://www.gnu.org/software/wget/>
As of this writing, the latest stable version of Gzip is 1.2.4 but we
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 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.
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-2023 Free Software Foundation, Inc.
Copyright 2001-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -8,22 +8,11 @@ tar. We do not make any efforts to accommodate older versions of
these packages, so please make sure that you have the latest stable
version.
- Autoconf <http://www.gnu.org/software/autoconf/>
- Automake <http://www.gnu.org/software/automake/>
- Bison <http://www.gnu.org/software/bison/>
- Autoconf <http://www.gnu.org/software/autoconf/>
- M4 <http://www.gnu.org/software/m4/>
- Gettext <http://www.gnu.org/software/gettext/>
- Git <http://git.or.cz>
- Gzip <http://www.gnu.org/software/gzip/>
- Texinfo <http://www.gnu.org/software/texinfo>
- Wget <http://www.gnu.org/software/wget/>
Up-to-date compilers and libraries are also recommended, for better
static checking. You may be able to use an older compiler by building
with 'make WERROR_CFLAGS='; if so, don't worry about its false alarms.
Valgrind <http://valgrind.org/> is also highly recommended, if
Valgrind supports your architecture.
- Git <http://git.or.cz>
* Bootstrapping
@@ -45,26 +34,12 @@ 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.
There are lots of options that you may find useful in this case.
See './bootstrap --help' for a detailed list.
Bootstrapping obtains Gnulib and Paxutils files from their Git
repositories on Savannah. Then, it fetches translations from the
Translation Project, and, finally, it builds files useful for
configuration. Simply running ./bootstrap without arguments should do
in most cases.
The file bootstrap.conf contains bootstrapping configuration.
Several options are provided that modify its behavior.
Run './bootstrap --help' for a list.
To only fetch auxiliary files from the network, run './bootstrap --pull'.
To only generate files such as 'configure', without accessing the
network, run './bootstrap --gen'.
See 'bootstrap --help' for a detailed list.
* Copyright information
Copyright 2007-2023 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

2
TODO
View File

@@ -45,7 +45,7 @@ Suggestions for improving GNU tar.
* Copyright notice
Copyright 2003-2023 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-2023 Free Software Foundation, Inc.
dnl Copyright 2009-2021 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU tar.
dnl
@@ -21,7 +21,7 @@ AC_DEFUN([TAR_COMPR_PROGRAM],[
m4_pushdef([tar_compr_define],translit($1,[a-z+-],[A-ZX_])[_PROGRAM])
m4_pushdef([tar_compr_var],[tar_cv_compressor_]translit($1,[+-],[x_]))
AC_ARG_WITH($1,
AS_HELP_STRING([--with-]$1[=PROG],
AC_HELP_STRING([--with-]$1[=PROG],
[use PROG as ]$1[ compressor program]),
[tar_compr_var=${withval}],
[tar_compr_var=m4_if($2,,$1,$2)])

1694
bootstrap

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# Bootstrap configuration for GNU tar.
# Copyright 2006-2023 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -60,19 +60,21 @@ if [ -r .bootstrap ]; then
eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
fi
bootstrap_post_pull_hook() {
mkdir -p m4 $source_base
git submodule init
git submodule update
}
test -d m4 || mkdir m4
test -d $source_base || mkdir $source_base
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.
# getopt-gnu is for paxutils.
gnulib_modules="$avoided_gnulib_modules
`grep -h '^[^#]' gnulib.modules`
getopt-gnu
`grep -h '^[^#]' gnulib.modules $PAXUTILS/gnulib.modules`
"
# copy_files srcdir dstdir
@@ -98,30 +100,27 @@ copy_files() {
done
}
bootstrap_post_import_hook() {
# Import from paxutils
copy_files ${PAXUTILS} .
copy_files ${PAXUTILS}/am m4
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
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
# Import from paxutils
copy_files ${PAXUTILS} .
copy_files ${PAXUTILS}/am m4
if [ -d rmt ]; then
:
else
mkdir rmt
fi
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
for dir in doc rmt lib tests
do
copy_files ${PAXUTILS}/$dir $dir
done
mkdir -p rmt
for dir in doc rmt lib tests; do
copy_files ${PAXUTILS}/$dir $dir
done
copy_files ${PAXUTILS}/paxlib lib pax
}
copy_files ${PAXUTILS}/paxlib lib pax

View File

@@ -1,6 +1,6 @@
# Configure template for GNU tar. -*- autoconf -*-
# Copyright 1991, 1994-2010, 2013-2023 Free Software Foundation, Inc.
# Copyright 1991, 1994-2010, 2013-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -17,17 +17,17 @@
# 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.35], [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.71])
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])
AC_PROG_CC
AC_PROG_CC_STDC
AC_EXEEXT
AC_PROG_RANLIB
AC_PROG_YACC
@@ -35,6 +35,7 @@ gl_EARLY
AC_CHECK_TOOLS([AR], [ar])
AC_SYS_LARGEFILE
AC_C_INLINE
AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h memory.h net/errno.h \
sgtty.h string.h \
@@ -52,14 +53,10 @@ AC_HEADER_MAJOR
AC_MSG_CHECKING([for st_fstype string in struct stat])
AC_CACHE_VAL(diff_cv_st_fstype_string,
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/types.h>
#include <sys/stat.h>
]],
[[struct stat s; s.st_fstype[0] = 'x';]])],
[diff_cv_st_fstype_string=yes],
[diff_cv_st_fstype_string=no])])
[AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/stat.h>], [struct stat s; s.st_fstype[0] = 'x';],
diff_cv_st_fstype_string=yes,
diff_cv_st_fstype_string=no)])
AC_MSG_RESULT($diff_cv_st_fstype_string)
if test $diff_cv_st_fstype_string = yes; then
AC_DEFINE(HAVE_ST_FSTYPE_STRING, 1,
@@ -106,20 +103,6 @@ gt_TYPE_SSIZE_T
# gnulib modules
gl_INIT
AC_DEFINE([GNULIB_EXCLUDE_SINGLE_THREAD], [1],
[Define if all programs in this package call functions of the Gnulib
'exclude' module only from a single thread.])
AC_DEFINE([GNULIB_MBRTOWC_SINGLE_THREAD], [1],
[Define if all programs in this package call functions of the Gnulib
'mbtowc' module only from a single thread.])
AC_DEFINE([GNULIB_REGEX_SINGLE_THREAD], [1],
[Define if all programs in this package call functions of the Gnulib
'regex' module only from a single thread.])
AC_DEFINE([GNULIB_WCHAR_SINGLE_LOCALE], [1],
[Define if all programs in this package call locale-sensitive functions
like mbrtowc only after setting the locale, and never change the
locale once set.])
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
@@ -129,7 +112,7 @@ if test $ac_cv_lib_error_at_line = no; then
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
fi
# paxutils modules
tar_PAXUTILS
@@ -162,7 +145,7 @@ AC_ARG_ENABLE([gcc-warnings],
gl_gcc_warnings=$enableval],
[gl_gcc_warnings=no
if test -d "$srcdir"/.git; then
gl_GCC_VERSION_IFELSE([11], [2], [gl_gcc_warnings=yes])
gl_GCC_VERSION_IFELSE([4], [6], [gl_gcc_warnings=yes])
fi]
)
@@ -179,7 +162,6 @@ 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 -Wsystem-headers" # Don't let system headers trigger warnings
nw="$nw -Wstack-protector"
gl_MANYWARN_ALL_GCC([ws])
@@ -189,11 +171,12 @@ if test "$gl_gcc_warnings" = yes; then
done
gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now
gl_WARN_ADD([-Wno-type-limits]) # It's OK to optimize based on types.
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
gl_WARN_ADD([-Wno-format-nonliteral])
gl_WARN_ADD([-fdiagnostics-show-option])
gl_WARN_ADD([-funit-at-a-time])
AC_SUBST([WARN_CFLAGS])
@@ -373,7 +356,7 @@ AC_CHECK_TYPE(iconv_t,:,
# Gettext.
AM_GNU_GETTEXT([external], [need-formatstring-macros])
AM_GNU_GETTEXT_VERSION([0.21])
AM_GNU_GETTEXT_VERSION([0.16])
# Initialize the test suite.
AC_CONFIG_TESTDIR(tests)
@@ -383,8 +366,8 @@ AM_MISSING_PROG([AUTOM4TE], [autom4te])
AC_SUBST(BACKUP_LIBEXEC_SCRIPTS)
AC_SUBST(BACKUP_SBIN_SCRIPTS)
AC_ARG_ENABLE(backup-scripts,
AS_HELP_STRING([--enable-backup-scripts],
[Create and install backup and restore scripts]),
AC_HELP_STRING([--enable-backup-scripts],
[Create and install backup and restore scripts]),
[case $enableval in
yes) BACKUP_LIBEXEC_SCRIPTS='$(BACKUP_LIBEXEC_SCRIPTS_LIST)'
BACKUP_SBIN_SCRIPTS='$(BACKUP_SBIN_SCRIPTS_LIST)'
@@ -398,7 +381,7 @@ else
BACKUP_SED_COND='/^\#IF_DATE_FORMAT_OK/,/^\#ELSE_DATE_FORMAT_OK/d;/^\#ENDIF_DATE_FORMAT_OK/d'
fi
AC_CONFIG_FILES([Makefile\
AC_OUTPUT([Makefile\
doc/Makefile\
gnu/Makefile\
lib/Makefile\
@@ -406,4 +389,3 @@ AC_CONFIG_FILES([Makefile\
scripts/Makefile\
rmt/Makefile\
src/Makefile])
AC_OUTPUT

View File

@@ -1,5 +1,5 @@
%%comments:
Copyright 2004-2023 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

View File

@@ -1,6 +1,6 @@
# Makefile for GNU tar documentation.
# Copyright 1994-2023 Free Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -138,9 +138,9 @@ check-docs:
clean-local:
rm -rf manual
GENDOCS=$(srcdir)/gendocs.sh
GENDOCS=gendocs.sh
TEXI2DVI=texi2dvi -E
TEXI2DVI=texi2dvi -t '@set $(RENDITION)' -E
# Make sure you set TEXINPUTS
# Usual value is:
@@ -148,8 +148,5 @@ TEXI2DVI=texi2dvi -E
manual:
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
TEXI2DVI="$(TEXI2DVI) -t '@set DISTRIB' -t @finalout" \
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
$(GENDOCS) --texi2html tar 'GNU tar manual'
manual-rebuild: clean-local manual

View File

@@ -1,91 +0,0 @@
* Overview
This file is a short instruction for maintainers on how to create and
publish the online version of the Tar Manual.
In the sections below we assume that the tar project has been properly
cloned from the git repo, bootstrapped and configured. We also assume
that top-level directory of the project is the current local directory.
* Creating the web manual
To create the online version of the documentation, run
make -C doc manual-rebuild
This will create the directory doc/manual populated with the tar
documentation files in various formats. If the doc/manual directory
already exists, it will be removed prior to rebuilding.
The command produces very copious output. We advise you to examine it
closely to make sure no error messages slip your attention.
For the completeness sake, there are two more Makefile goals related
to the online manual:
** make -C doc clean-local
Removes the doc/manual directory, if it exists.
** make -C doc manual
Builds the doc/manual, unless it already exists.
* CVS Repository
The online tar manual[1] is a part of tar web pages[2] and is
traditionally maintained in the CVS repository[3]. To publish the
generated documentation, you will need first to check out tar web
pages from the CVS. To do so, run
cvs -z3 -d:ext:<username>@cvs.savannah.gnu.org:/web/tar co tar
where <username> is your user name on Savannah. For the rest of this
document we will assume that the checked out version of the tar web
pages resides in the ~/websrc/tar directory.
If you have already checked out the web pages, be sure to update them
before publishing:
cd ~/websrc/tar
cvs update
* Publishing
To publish the created manual, change to the tar top-level directory
and run:
rsync -avz --exclude CVS --delete manual ~/websrc/tar
This will synchronize the newly created manual pages with the content
of the CVS sandbox. Then, change to the ~/websrc/tar directory and
schedule any removed files for removal and any new files for addition
to the repository:
cvs diff --brief 2>&1 | sed -n 's/.*cannot find //p' | xargs cvs rm
cvs diff --brief 2>&1 | sed -n 's/^? //p' | xargs cvs add
Then commit your changes:
cvs commit
Once the changes are committed to CVS a job is scheduled on the server,
which synchronizes them with the content of the directory served by
the httpd daemon. Normally such synchronization happens within
several seconds from the commit.
For more information about CVS, please see its documentation[4].
* References
[1] https://www.gnu.org/software/tar/manual/
[2] https://www.gnu.org/software/tar/
[3] https://web.cvs.savannah.gnu.org/viewvc/tar/
[4] https://www.nongnu.org/cvs/#documentation
Local Variables:
mode: outline
paragraph-separate: "[ ]*$"
version-control: never
End:

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006--2023 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,9 +5,8 @@
@c hence no sectioning command or @node.
@display
Copyright @copyright{} 2000--2002, 2007--2008, 2022 Free Software
Foundation, Inc.
@uref{https://fsf.org/}
Copyright @copyright{} 2000--2021 Free Software Foundation, Inc.
@uref{http://fsf.org/}
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -98,7 +97,7 @@ format, SGML or XML using a publicly available
DTD, and standard-conforming simple HTML,
PostScript or PDF designed for human modification. Examples
of transparent image formats include PNG, XCF and
JPG@. Opaque formats include proprietary formats that can be
JPG. Opaque formats include proprietary formats that can be
read and edited only by proprietary word processors, SGML or
XML for which the DTD and/or processing tools are
not generally available, and the machine-generated HTML,
@@ -415,7 +414,7 @@ The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See
@uref{https://www.gnu.org/licenses/}.
@uref{http://www.gnu.org/copyleft/}.
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
@@ -482,7 +481,7 @@ license notices just after the title page:
@end smallexample
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the ``with@dots{}Texts.''@: line with this:
replace the ``with@dots{}Texts.'' line with this:
@smallexample
@group
@@ -504,3 +503,4 @@ to permit their use in free software.
@c Local Variables:
@c ispell-local-pdict: "ispell-dict"
@c End:

View File

@@ -1,512 +0,0 @@
#!/bin/sh -e
# gendocs.sh -- generate a GNU manual in many formats. This script is
# mentioned in maintain.texi. See the help message below for usage details.
scriptversion=2021-03-01.13
# Copyright 2003-2023 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# Original author: Mohit Agarwal.
# Send bug reports and any other correspondence to bug-gnulib@gnu.org.
#
# The latest version of this script, and the companion template, is
# available from the Gnulib repository:
#
# https://git.savannah.gnu.org/cgit/gnulib.git/tree/build-aux/gendocs.sh
# https://git.savannah.gnu.org/cgit/gnulib.git/tree/doc/gendocs_template
# TODO:
# - image importing was only implemented for HTML generated by
# makeinfo. But it should be simple enough to adjust.
# - images are not imported in the source tarball. All the needed
# formats (PDF, PNG, etc.) should be included.
prog=`basename "$0"`
srcdir=`pwd`
scripturl="https://git.savannah.gnu.org/cgit/gnulib.git/plain/build-aux/gendocs.sh"
templateurl="https://git.savannah.gnu.org/cgit/gnulib.git/plain/doc/gendocs_template"
: ${SETLANG="env LANG= LC_MESSAGES= LC_ALL= LANGUAGE="}
: ${MAKEINFO="makeinfo"}
: ${TEXI2DVI="texi2dvi"}
: ${DOCBOOK2HTML="docbook2html"}
: ${DOCBOOK2PDF="docbook2pdf"}
: ${DOCBOOK2TXT="docbook2txt"}
: ${GENDOCS_TEMPLATE_DIR="."}
: ${PERL='perl'}
: ${TEXI2HTML="texi2html"}
unset CDPATH
unset use_texi2html
MANUAL_TITLE=
PACKAGE=
EMAIL=webmasters@gnu.org # please override with --email
commonarg= # passed to all makeinfo/texi2html invcations.
dirargs= # passed to all tools (-I dir).
dirs= # -I directories.
htmlarg="--css-ref=/software/gnulib/manual.css -c TOP_NODE_UP_URL=/manual"
default_htmlarg=true
infoarg=--no-split
generate_ascii=true
generate_html=true
generate_info=true
generate_tex=true
outdir=manual
source_extra=
split=node
srcfile=
texarg="-t @finalout"
version="gendocs.sh $scriptversion
Copyright 2021 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING."
usage="Usage: $prog [OPTION]... PACKAGE MANUAL-TITLE
Generate output in various formats from PACKAGE.texinfo (or .texi or
.txi) source. See the GNU Maintainers document for a more extensive
discussion:
https://www.gnu.org/prep/maintain_toc.html
Options:
--email ADR use ADR as contact in generated web pages; always give this.
-s SRCFILE read Texinfo from SRCFILE, instead of PACKAGE.{texinfo|texi|txi}
-o OUTDIR write files into OUTDIR, instead of manual/.
-I DIR append DIR to the Texinfo search path.
--common ARG pass ARG in all invocations.
--html ARG pass ARG to makeinfo or texi2html for HTML targets,
instead of '$htmlarg'.
--info ARG pass ARG to makeinfo for Info, instead of --no-split.
--no-ascii skip generating the plain text output.
--no-html skip generating the html output.
--no-info skip generating the info output.
--no-tex skip generating the dvi and pdf output.
--source ARG include ARG in tar archive of sources.
--split HOW make split HTML by node, section, chapter; default node.
--tex ARG pass ARG to texi2dvi for DVI and PDF, instead of -t @finalout.
--texi2html use texi2html to make HTML target, with all split versions.
--docbook convert through DocBook too (xml, txt, html, pdf).
--help display this help and exit successfully.
--version display version information and exit successfully.
Simple example: $prog --email bug-gnu-emacs@gnu.org emacs \"GNU Emacs Manual\"
Typical sequence:
cd PACKAGESOURCE/doc
wget \"$scripturl\"
wget \"$templateurl\"
$prog --email BUGLIST MANUAL \"GNU MANUAL - One-line description\"
Output will be in a new subdirectory \"manual\" (by default;
use -o OUTDIR to override). Move all the new files into your web CVS
tree, as explained in the Web Pages node of maintain.texi.
Please use the --email ADDRESS option so your own bug-reporting
address will be used in the generated HTML pages.
MANUAL-TITLE is included as part of the HTML <title> of the overall
manual/index.html file. It should include the name of the package being
documented. manual/index.html is created by substitution from the file
$GENDOCS_TEMPLATE_DIR/gendocs_template. (Feel free to modify the
generic template for your own purposes.)
If you have several manuals, you'll need to run this script several
times with different MANUAL values, specifying a different output
directory with -o each time. Then write (by hand) an overall index.html
with links to them all.
If a manual's Texinfo sources are spread across several directories,
first copy or symlink all Texinfo sources into a single directory.
(Part of the script's work is to make a tar.gz of the sources.)
As implied above, by default monolithic Info files are generated.
If you want split Info, or other Info options, use --info to override.
You can set the environment variables MAKEINFO, TEXI2DVI, TEXI2HTML,
and PERL to control the programs that get executed, and
GENDOCS_TEMPLATE_DIR to control where the gendocs_template file is
looked for. With --docbook, the environment variables DOCBOOK2HTML,
DOCBOOK2PDF, and DOCBOOK2TXT are also consulted.
By default, makeinfo and texi2dvi are run in the default (English)
locale, since that's the language of most Texinfo manuals. If you
happen to have a non-English manual and non-English web site, see the
SETLANG setting in the source.
Email bug reports or enhancement requests to bug-gnulib@gnu.org.
"
while test $# -gt 0; do
case $1 in
-s) shift; srcfile=$1;;
-o) shift; outdir=$1;;
-I) shift; dirargs="$dirargs -I '$1'"; dirs="$dirs $1";;
--common) shift; commonarg=$1;;
--docbook) docbook=yes;;
--email) shift; EMAIL=$1;;
--html) shift; default_htmlarg=false; htmlarg=$1;;
--info) shift; infoarg=$1;;
--no-ascii) generate_ascii=false;;
--no-html) generate_ascii=false;;
--no-info) generate_info=false;;
--no-tex) generate_tex=false;;
--source) shift; source_extra=$1;;
--split) shift; split=$1;;
--tex) shift; texarg=$1;;
--texi2html) use_texi2html=1;;
--help) echo "$usage"; exit 0;;
--version) echo "$version"; exit 0;;
-*)
echo "$0: Unknown option \`$1'." >&2
echo "$0: Try \`--help' for more information." >&2
exit 1;;
*)
if test -z "$PACKAGE"; then
PACKAGE=$1
elif test -z "$MANUAL_TITLE"; then
MANUAL_TITLE=$1
else
echo "$0: extra non-option argument \`$1'." >&2
exit 1
fi;;
esac
shift
done
# makeinfo uses the dirargs, but texi2dvi doesn't.
commonarg=" $dirargs $commonarg"
# For most of the following, the base name is just $PACKAGE
base=$PACKAGE
if $default_htmlarg && test -n "$use_texi2html"; then
# The legacy texi2html doesn't support TOP_NODE_UP_URL
htmlarg="--css-ref=/software/gnulib/manual.css"
fi
if test -n "$srcfile"; then
# but here, we use the basename of $srcfile
base=`basename "$srcfile"`
case $base in
*.txi|*.texi|*.texinfo) base=`echo "$base"|sed 's/\.[texinfo]*$//'`;;
esac
PACKAGE=$base
elif test -s "$srcdir/$PACKAGE.texinfo"; then
srcfile=$srcdir/$PACKAGE.texinfo
elif test -s "$srcdir/$PACKAGE.texi"; then
srcfile=$srcdir/$PACKAGE.texi
elif test -s "$srcdir/$PACKAGE.txi"; then
srcfile=$srcdir/$PACKAGE.txi
else
echo "$0: cannot find .texinfo or .texi or .txi for $PACKAGE in $srcdir." >&2
exit 1
fi
if test ! -r $GENDOCS_TEMPLATE_DIR/gendocs_template; then
echo "$0: cannot read $GENDOCS_TEMPLATE_DIR/gendocs_template." >&2
echo "$0: it is available from $templateurl." >&2
exit 1
fi
# Function to return size of $1 in something resembling kilobytes.
calcsize()
{
size=`ls -ksl $1 | awk '{print $1}'`
echo $size
}
# copy_images OUTDIR HTML-FILE...
# -------------------------------
# Copy all the images needed by the HTML-FILEs into OUTDIR.
# Look for them in . and the -I directories; this is simpler than what
# makeinfo supports with -I, but hopefully it will suffice.
copy_images()
{
local odir
odir=$1
shift
$PERL -n -e "
BEGIN {
\$me = '$prog';
\$odir = '$odir';
@dirs = qw(. $dirs);
}
" -e '
/<img src="(.*?)"/g && ++$need{$1};
END {
#print "$me: @{[keys %need]}\n"; # for debugging, show images found.
FILE: for my $f (keys %need) {
for my $d (@dirs) {
if (-f "$d/$f") {
use File::Basename;
my $dest = dirname ("$odir/$f");
#
use File::Path;
-d $dest || mkpath ($dest)
|| die "$me: cannot mkdir $dest: $!\n";
#
use File::Copy;
copy ("$d/$f", $dest)
|| die "$me: cannot copy $d/$f to $dest: $!\n";
next FILE;
}
}
die "$me: $ARGV: cannot find image $f\n";
}
}
' -- "$@" || exit 1
}
case $outdir in
/*) abs_outdir=$outdir;;
*) abs_outdir=$srcdir/$outdir;;
esac
echo "Making output for $srcfile"
echo " in `pwd`"
mkdir -p "$outdir/"
#
if $generate_info; then
cmd="$SETLANG $MAKEINFO -o $PACKAGE.info $commonarg $infoarg \"$srcfile\""
echo "Generating info... ($cmd)"
rm -f $PACKAGE.info* # get rid of any strays
eval "$cmd"
tar czf "$outdir/$PACKAGE.info.tar.gz" $PACKAGE.info*
ls -l "$outdir/$PACKAGE.info.tar.gz"
info_tgz_size=`calcsize "$outdir/$PACKAGE.info.tar.gz"`
# do not mv the info files, there's no point in having them available
# separately on the web.
fi # end info
#
if $generate_tex; then
cmd="$SETLANG $TEXI2DVI $dirargs $texarg \"$srcfile\""
printf "\nGenerating dvi... ($cmd)\n"
eval "$cmd"
# compress/finish dvi:
gzip -f -9 $PACKAGE.dvi
dvi_gz_size=`calcsize $PACKAGE.dvi.gz`
mv $PACKAGE.dvi.gz "$outdir/"
ls -l "$outdir/$PACKAGE.dvi.gz"
cmd="$SETLANG $TEXI2DVI --pdf $dirargs $texarg \"$srcfile\""
printf "\nGenerating pdf... ($cmd)\n"
eval "$cmd"
pdf_size=`calcsize $PACKAGE.pdf`
mv $PACKAGE.pdf "$outdir/"
ls -l "$outdir/$PACKAGE.pdf"
fi # end tex (dvi + pdf)
#
if $generate_ascii; then
opt="-o $PACKAGE.txt --no-split --no-headers $commonarg"
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
printf "\nGenerating ascii... ($cmd)\n"
eval "$cmd"
ascii_size=`calcsize $PACKAGE.txt`
gzip -f -9 -c $PACKAGE.txt >"$outdir/$PACKAGE.txt.gz"
ascii_gz_size=`calcsize "$outdir/$PACKAGE.txt.gz"`
mv $PACKAGE.txt "$outdir/"
ls -l "$outdir/$PACKAGE.txt" "$outdir/$PACKAGE.txt.gz"
fi
#
if $generate_html; then
# Split HTML at level $1. Used for texi2html.
html_split()
{
opt="--split=$1 --node-files $commonarg $htmlarg"
cmd="$SETLANG $TEXI2HTML --output $PACKAGE.html $opt \"$srcfile\""
printf "\nGenerating html by $1... ($cmd)\n"
eval "$cmd"
split_html_dir=$PACKAGE.html
(
cd ${split_html_dir} || exit 1
if [ ! -f index.html ]; then
ln -sf ${PACKAGE}.html index.html
fi
tar -czf "$abs_outdir/${PACKAGE}.html_$1.tar.gz" -- *.html
)
eval html_$1_tgz_size=`calcsize "$outdir/${PACKAGE}.html_$1.tar.gz"`
rm -f "$outdir"/html_$1/*.html
mkdir -p "$outdir/html_$1/"
mv ${split_html_dir}/*.html "$outdir/html_$1/"
rmdir ${split_html_dir}
}
if test -z "$use_texi2html"; then
opt="--no-split --html -o $PACKAGE.html $commonarg $htmlarg"
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
printf "\nGenerating monolithic html... ($cmd)\n"
rm -rf $PACKAGE.html # in case a directory is left over
eval "$cmd"
html_mono_size=`calcsize $PACKAGE.html`
gzip -f -9 -c $PACKAGE.html >"$outdir/$PACKAGE.html.gz"
html_mono_gz_size=`calcsize "$outdir/$PACKAGE.html.gz"`
copy_images "$outdir/" $PACKAGE.html
mv $PACKAGE.html "$outdir/"
ls -l "$outdir/$PACKAGE.html" "$outdir/$PACKAGE.html.gz"
# Before Texinfo 5.0, makeinfo did not accept a --split=HOW option,
# it just always split by node. So if we're splitting by node anyway,
# leave it out.
if test "x$split" = xnode; then
split_arg=
else
split_arg=--split=$split
fi
#
opt="--html -o $PACKAGE.html $split_arg $commonarg $htmlarg"
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
printf "\nGenerating html by $split... ($cmd)\n"
eval "$cmd"
split_html_dir=$PACKAGE.html
copy_images $split_html_dir/ $split_html_dir/*.html
(
cd $split_html_dir || exit 1
tar -czf "$abs_outdir/$PACKAGE.html_$split.tar.gz" -- *
)
eval \
html_${split}_tgz_size=`calcsize "$outdir/$PACKAGE.html_$split.tar.gz"`
rm -rf "$outdir/html_$split/"
mv $split_html_dir "$outdir/html_$split/"
du -s "$outdir/html_$split/"
ls -l "$outdir/$PACKAGE.html_$split.tar.gz"
else # use texi2html:
opt="--output $PACKAGE.html $commonarg $htmlarg"
cmd="$SETLANG $TEXI2HTML $opt \"$srcfile\""
printf "\nGenerating monolithic html with texi2html... ($cmd)\n"
rm -rf $PACKAGE.html # in case a directory is left over
eval "$cmd"
html_mono_size=`calcsize $PACKAGE.html`
gzip -f -9 -c $PACKAGE.html >"$outdir/$PACKAGE.html.gz"
html_mono_gz_size=`calcsize "$outdir/$PACKAGE.html.gz"`
mv $PACKAGE.html "$outdir/"
html_split node
html_split chapter
html_split section
fi
fi # end html
#
printf "\nMaking .tar.gz for sources...\n"
d=`dirname $srcfile`
(
cd "$d"
srcfiles=`ls -d *.texinfo *.texi *.txi *.eps $source_extra 2>/dev/null` || true
tar czfh "$abs_outdir/$PACKAGE.texi.tar.gz" $srcfiles
ls -l "$abs_outdir/$PACKAGE.texi.tar.gz"
)
texi_tgz_size=`calcsize "$outdir/$PACKAGE.texi.tar.gz"`
#
# Do everything again through docbook.
if test -n "$docbook"; then
opt="-o - --docbook $commonarg"
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\" >${srcdir}/$PACKAGE-db.xml"
printf "\nGenerating docbook XML... ($cmd)\n"
eval "$cmd"
docbook_xml_size=`calcsize $PACKAGE-db.xml`
gzip -f -9 -c $PACKAGE-db.xml >"$outdir/$PACKAGE-db.xml.gz"
docbook_xml_gz_size=`calcsize "$outdir/$PACKAGE-db.xml.gz"`
mv $PACKAGE-db.xml "$outdir/"
split_html_db_dir=html_node_db
opt="$commonarg -o $split_html_db_dir"
cmd="$DOCBOOK2HTML $opt \"${outdir}/$PACKAGE-db.xml\""
printf "\nGenerating docbook HTML... ($cmd)\n"
eval "$cmd"
(
cd ${split_html_db_dir} || exit 1
tar -czf "$abs_outdir/${PACKAGE}.html_node_db.tar.gz" -- *.html
)
html_node_db_tgz_size=`calcsize "$outdir/${PACKAGE}.html_node_db.tar.gz"`
rm -f "$outdir"/html_node_db/*.html
mkdir -p "$outdir/html_node_db"
mv ${split_html_db_dir}/*.html "$outdir/html_node_db/"
rmdir ${split_html_db_dir}
cmd="$DOCBOOK2TXT \"${outdir}/$PACKAGE-db.xml\""
printf "\nGenerating docbook ASCII... ($cmd)\n"
eval "$cmd"
docbook_ascii_size=`calcsize $PACKAGE-db.txt`
mv $PACKAGE-db.txt "$outdir/"
cmd="$DOCBOOK2PDF \"${outdir}/$PACKAGE-db.xml\""
printf "\nGenerating docbook PDF... ($cmd)\n"
eval "$cmd"
docbook_pdf_size=`calcsize $PACKAGE-db.pdf`
mv $PACKAGE-db.pdf "$outdir/"
fi
#
printf "\nMaking index.html for $PACKAGE...\n"
if test -z "$use_texi2html"; then
CONDS="/%%IF *HTML_SECTION%%/,/%%ENDIF *HTML_SECTION%%/d;\
/%%IF *HTML_CHAPTER%%/,/%%ENDIF *HTML_CHAPTER%%/d"
else
# should take account of --split here.
CONDS="/%%ENDIF.*%%/d;/%%IF *HTML_SECTION%%/d;/%%IF *HTML_CHAPTER%%/d"
fi
curdate=`$SETLANG date '+%B %d, %Y'`
sed \
-e "s!%%TITLE%%!$MANUAL_TITLE!g" \
-e "s!%%EMAIL%%!$EMAIL!g" \
-e "s!%%PACKAGE%%!$PACKAGE!g" \
-e "s!%%DATE%%!$curdate!g" \
-e "s!%%HTML_MONO_SIZE%%!$html_mono_size!g" \
-e "s!%%HTML_MONO_GZ_SIZE%%!$html_mono_gz_size!g" \
-e "s!%%HTML_NODE_TGZ_SIZE%%!$html_node_tgz_size!g" \
-e "s!%%HTML_SECTION_TGZ_SIZE%%!$html_section_tgz_size!g" \
-e "s!%%HTML_CHAPTER_TGZ_SIZE%%!$html_chapter_tgz_size!g" \
-e "s!%%INFO_TGZ_SIZE%%!$info_tgz_size!g" \
-e "s!%%DVI_GZ_SIZE%%!$dvi_gz_size!g" \
-e "s!%%PDF_SIZE%%!$pdf_size!g" \
-e "s!%%ASCII_SIZE%%!$ascii_size!g" \
-e "s!%%ASCII_GZ_SIZE%%!$ascii_gz_size!g" \
-e "s!%%TEXI_TGZ_SIZE%%!$texi_tgz_size!g" \
-e "s!%%DOCBOOK_HTML_NODE_TGZ_SIZE%%!$html_node_db_tgz_size!g" \
-e "s!%%DOCBOOK_ASCII_SIZE%%!$docbook_ascii_size!g" \
-e "s!%%DOCBOOK_PDF_SIZE%%!$docbook_pdf_size!g" \
-e "s!%%DOCBOOK_XML_SIZE%%!$docbook_xml_size!g" \
-e "s!%%DOCBOOK_XML_GZ_SIZE%%!$docbook_xml_gz_size!g" \
-e "s,%%SCRIPTURL%%,$scripturl,g" \
-e "s!%%SCRIPTNAME%%!$prog!g" \
-e "$CONDS" \
$GENDOCS_TEMPLATE_DIR/gendocs_template >"$outdir/index.html"
echo "Done, see $outdir/ subdirectory for new files."
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

174
doc/gendocs_template Normal file → Executable file
View File

@@ -1,101 +1,125 @@
<!--#include virtual="/server/header.html" -->
<!-- Parent-Version: 1.78 -->
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- $Id: gendocs_template,v 1.5 2007/10/30 14:58:52 gray Exp $ -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<!--
Copyright (C) 2006-2023 Free Software Foundation, Inc.
<head>
<title>%%TITLE%% - GNU Project - Free Software Foundation (FSF)</title>
<meta http-equiv="content-type" content='text/html; charset=utf-8' />
<link rel="stylesheet" type="text/css" href="/gnu.css" />
<link rev="made" href="mailto:gray@gnu.org" />
<link rel="icon" type="image/png" href="/graphics/gnu-head-icon.png" />
</head>
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without any warranty.
-->
<!-- This document is in XML, and xhtml 1.0 -->
<!-- Please make sure to properly nest your tags -->
<!-- and ensure that your final document validates -->
<!-- consistent with W3C xhtml 1.0 and CSS standards -->
<!-- See validator.w3.org -->
<title>%%TITLE%% - GNU Project - Free Software Foundation</title>
<!--#include virtual="/server/banner.html" -->
<h2>%%TITLE%%</h2>
<body>
<h3>%%TITLE%%</h3>
<address>Free Software Foundation</address>
<address>last updated %%DATE%%</address>
<p>
<a href="/graphics/gnu-head.jpg">
<img src="/graphics/gnu-head-sm.jpg"
alt=" [image of the head of a GNU] "
width="129" height="122" />
</a>
</p>
<hr />
<p>This manual (%%PACKAGE%%) is available in the following formats:</p>
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
<ul>
<li><a href="%%PACKAGE%%.html">HTML
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
<li><a href="html_node/index.html">HTML</a> - with one web page per
node.</li>
<li><a href="%%PACKAGE%%.html">HTML
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
<li><a href="html_node/index.html">HTML</a> - with one web page per
node.</li>
%%IF HTML_SECTION%%
<li><a href="html_section/index.html">HTML</a> - with one web page per
section.</li>
<li><a href="html_section/index.html">HTML</a> - with one web page per
section.</li>
%%ENDIF HTML_SECTION%%
%%IF HTML_CHAPTER%%
<li><a href="html_chapter/index.html">HTML</a> - with one web page per
chapter.</li>
<li><a href="html_chapter/index.html">HTML</a> - with one web page per
chapter.</li>
%%ENDIF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
one web page.</li>
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per node.</li>
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
one web page.</li>
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per node.</li>
%%IF HTML_SECTION%%
<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
(%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per section.</li>
<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
(%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per section.</li>
%%ENDIF HTML_SECTION%%
%%IF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
(%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per chapter.</li>
<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
(%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per chapter.</li>
%%ENDIF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
(%%INFO_TGZ_SIZE%%K bytes gzipped tar file)</a>.</li>
<li><a href="%%PACKAGE%%.txt">ASCII text
(%%ASCII_SIZE%%K bytes)</a>.</li>
<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
(%%ASCII_GZ_SIZE%%K bytes gzipped)</a>.</li>
<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
(%%DVI_GZ_SIZE%%K bytes gzipped)</a>.</li>
<li><a href="%%PACKAGE%%.pdf">PDF file
(%%PDF_SIZE%%K bytes)</a>.</li>
<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
(%%TEXI_TGZ_SIZE%%K bytes gzipped tar file).</a></li>
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
<li><a href="%%PACKAGE%%.txt">ASCII text
(%%ASCII_SIZE%%K characters)</a>.</li>
<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
(%%ASCII_GZ_SIZE%%K gzipped characters)</a>.</li>
<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
(%%DVI_GZ_SIZE%%K characters gzipped)</a>.</li>
<li><a href="%%PACKAGE%%.ps.gz">PostScript file
(%%PS_GZ_SIZE%%K characters gzipped)</a>.</li>
<li><a href="%%PACKAGE%%.pdf">PDF file
(%%PDF_SIZE%%K characters)</a>.</li>
<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
(%%TEXI_TGZ_SIZE%%K characters gzipped tar file)</a></li>
</ul>
<p>You can <a href="https://shop.fsf.org/">buy printed copies of
some manuals</a> (among other items) from the Free Software Foundation;
this helps support FSF activities.</p>
<p>(This page generated by the <a
href="%%SCRIPTURL%%">%%SCRIPTNAME%%</a> script.)
</p>
<p>(This page generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%%
script</a>.)</p>
<p>
<a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0!" height="31" width="88" /></a>
</p>
<!-- If needed, change the copyright block at the bottom. In general,
all pages on the GNU web server should have the section about
verbatim copying. Please do NOT remove this without talking
with the webmasters first.
Please make sure the copyright date is consistent with the document
and that it is like this: "2001, 2002", not this: "2001-2002". -->
</div><!-- for id="content", starts in the include above -->
<!--#include virtual="/server/footer.html" -->
<div id="footer">
<div class="unprintable">
<div class="copyright">
<p>
Return to the <a href="/home.html">GNU Project home page</a>.
</p>
<p>Please send general FSF &amp; GNU inquiries to
<a href="mailto:gnu@gnu.org">&lt;gnu@gnu.org&gt;</a>.
There are also <a href="/contact/">other ways to contact</a>
the FSF. Broken links and other corrections or suggestions can be sent
to <a href="mailto:%%EMAIL%%">&lt;%%EMAIL%%&gt;</a>.</p>
<p>
Please send FSF &amp; GNU inquiries to
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
the FSF.
<br />
Please send broken links and other corrections (or suggestions) to
<a href="mailto:webmasters@gnu.org"><em>webmasters@gnu.org</em></a>.
</p>
<p>
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
permitted in any medium, provided this notice is preserved.
</p>
<p>
Updated:
<!-- timestamp start -->
$Date: 2007/10/30 14:58:52 $ $Author: gray $
<!-- timestamp end -->
</p>
</div>
<p>Copyright &copy; 2020 Free Software Foundation, Inc.</p>
<p>This page is licensed under a <a rel="license"
href="https://creativecommons.org/licenses/by-nd/3.0/us/">Creative
Commons Attribution-NoDerivs 3.0 United States License</a>.</p>
<!--#include virtual="/server/bottom-notes.html" -->
</div>
</div>
</body>
</html>

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006--2023 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.
@@ -13,7 +13,7 @@
@node Standard
@unnumberedsec Basic Tar Format
@UNREVISED{}
@UNREVISED
While an archive may contain many files, the archive itself is a
single ordinary file. Like any other file, an archive file can be
@@ -51,10 +51,7 @@ of the file. At the end of the archive file there are two 512-byte blocks
filled with binary zeros as an end-of-file marker. A reasonable system
should write such end-of-file marker at the end of an archive, but
must not assume that such a block exists when reading an archive. In
particular, @GNUTAR{} does not treat missing end-of-file marker as an
error and silently ignores the fact. You can instruct it to issue
a warning, however, by using the @option{--warning=missing-zero-blocks}
option (@pxref{General Warnings, missing-zero-blocks}).
particular @GNUTAR{} always issues a warning if it does not encounter it.
The blocks may be @dfn{blocked} for physical I/O operations.
Each record of @var{n} blocks (where @var{n} is set by the
@@ -114,9 +111,8 @@ The @code{uid} and @code{gid} fields are the numeric user and group
not support numeric user or group @acronym{ID}s, these fields should
be ignored.
The @code{size} field is the size of the file in bytes; for archive
members that are symbolic or hard links to another file, this field
is specified as zero.
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 represents the data modification time of the file at
the time it was archived. It represents the integer number of
@@ -127,7 +123,7 @@ 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
if it were filled with spaces (ASCII 32).
if it were all blanks.
The @code{typeflag} field specifies the type of file archived. If a
particular implementation does not recognize or permit the specified
@@ -270,7 +266,7 @@ IEEE Std 1003.2-1992, pages 380-388 (section 4.48) and pages 936-940
@node Extensions
@unnumberedsec @acronym{GNU} Extensions to the Archive Format
@UNREVISED{}
@UNREVISED
The @acronym{GNU} format uses additional file types to describe new types of
files in an archive. These are listed below.

View File

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

View File

@@ -1,5 +1,5 @@
@c This is part of the GNU tar manual.
@c Copyright (C) 2017--2023 Free Software Foundation, Inc.
@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.

View File

@@ -1,5 +1,5 @@
@c This is part of GNU tar manual.
@c Copyright 1992--2023 Free Software Foundation, Inc.
@c Copyright 1992--2021 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@c This file contains support for 'renditions' by Fran@,{c}ois Pinard

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2005--2023 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.

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006--2023 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.

View File

@@ -1,5 +1,5 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2007--2023 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.

104
doc/tar.1
View File

@@ -1,5 +1,5 @@
.\" This file is part of GNU tar. -*- nroff -*-
.\" Copyright 2013-2023 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 "July 11, 2022" "TAR" "GNU TAR Manual"
.TH TAR 1 "July 13, 2020" "TAR" "GNU TAR Manual"
.SH NAME
tar \- an archiving utility
.SH SYNOPSIS
@@ -22,22 +22,22 @@ tar \- an archiving utility
[\fBGnSkUWOmpsMBiajJzZhPlRvwo\fR] [\fIARG\fR...]
.SS UNIX-style usage
.sp
\fBtar\fR \fB\-A\fR [\fIOPTIONS\fR] \fB\-f\fR \fIARCHIVE\fR \fIARCHIVE\fR...
\fBtar\fR \fB\-A\fR [\fIOPTIONS\fR] \fIARCHIVE\fR \fIARCHIVE\fR
.sp
\fBtar\fR \fB\-c\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR \fB\-d\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR \fB\-r\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR \fB\-t\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
.sp
\fBtar\fR \fB\-r\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR \fB\-u\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\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\fR} [\fIOPTIONS\fR] \fB\-\-file\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
@@ -45,15 +45,17 @@ tar \- an archiving utility
.sp
\fBtar\fR \fB\-\-delete\fR [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
.sp
\fBtar\fR \fB\-\-append\fR [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
\fBtar\fR \fB\-\-append\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR \fB\-\-list\fR [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
\fBtar\fR \fB\-\-list\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
.sp
\fBtar\fR \fB\-\-test\-label\fR [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fILABEL\fR...]
.sp
\fBtar\fR \fB\-\-update\fR [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR {\fB\-\-extract\fR|\fB\-\-get\fR} [\fB\-\-file\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
\fBtar\fR \fB\-\-update\fR [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIFILE\fR...]
.sp
\fBtar\fR {\fB\-\-extract\fR|\fB\-\-get\fR} [\fB\-f\fR \fIARCHIVE\fR] [\fIOPTIONS\fR] [\fIMEMBER\fR...]
.SH NOTE
This manpage is a short description of GNU \fBtar\fR. For a detailed
discussion, including examples and usage recommendations, refer to the
@@ -72,7 +74,7 @@ You can also view the manual using the info mode in
or find it in various formats online at
.PP
.RS +4
.B https://www.gnu.org/software/tar/manual
.B http://www.gnu.org/software/tar/manual
.RE
.PP
If any discrepancies occur between this manpage and the
@@ -95,8 +97,8 @@ In
the first argument is a cluster of option letters and all subsequent
arguments supply arguments to those options that require them. The
arguments are read in the same order as the option letters. Any
command line words that remain after all options have been processed
are treated as non-option arguments: file or archive member names.
command line words that remain after all options has been processed
are treated as non-optional arguments: file or archive member names.
.PP
For example, the \fBc\fR option requires creating the archive, the
\fBv\fR option requests the verbose operation, and the \fBf\fR option
@@ -105,7 +107,7 @@ The following command, written in the traditional style, instructs tar
to store all files from the directory
.B /etc
into the archive file
.BR etc.tar ,
.B etc.tar
verbosely listing the files being archived:
.PP
.EX
@@ -115,15 +117,15 @@ tar cfv etc.tar /etc
In
.BR "UNIX " or " short-option style" ,
each option letter is prefixed with a single dash, as in other command
line utilities. If an option takes an argument, the argument follows it,
line utilities. If an option takes argument, the argument follows it,
either as a separate command line word, or immediately following the
option. However, if the option takes an \fBoptional\fR argument, the
argument must follow the option letter without any intervening
whitespace, as in \fB\-g/tmp/snar.db\fR.
.PP
Any number of options not taking arguments can be
clustered together after a single dash, e.g. \fB\-vkp\fR. An option
that takes an argument (whether mandatory or optional) can appear at
clustered together after a single dash, e.g. \fB\-vkp\fR. Options
that take arguments (whether mandatory or optional), can appear at
the end of such a cluster, e.g. \fB\-vkpf a.tar\fR.
.PP
The example command above written in the
@@ -164,17 +166,17 @@ with old options is not encouraged.
.SS Operation mode
The options listed in the table below tell GNU \fBtar\fR what
operation it is to perform. Exactly one of them must be given.
The meaning of non-option arguments depends on the operation mode
Meaning of non-optional arguments depends on the operation mode
requested.
.TP
\fB\-A\fR, \fB\-\-catenate\fR, \fB\-\-concatenate\fR
Append archives to the end of another archive. The arguments are
Append archive to the end of another archive. The arguments are
treated as the names of archives to append. All archives must be of
the same format as the archive they are appended to, otherwise the
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 when using the \fB\-i\fR
the resulting archive only if using the \fB\-i\fR
(\fB\-\-ignore\-zeros\fR) option.
Compressed archives cannot be concatenated.
@@ -218,7 +220,7 @@ There is no short option equivalent for this option.
.TP
\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 the \fB\-c\fR and
archive. Arguments have the same meaning as with \fB\-c\fR and
\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
@@ -230,13 +232,14 @@ they specify names of the archive members to be extracted.
.TP
.TP
\fB\-\-show\-defaults\fR
Show built-in defaults for various \fBtar\fR options and exit.
Show built-in defaults for various \fBtar\fR options and exit. No
arguments are allowed.
.TP
\fB\-?\fR, \fB\-\-help
Display a short option summary and exit.
Display a short option summary and exit. No arguments allowed.
.TP
\fB\-\-usage\fR
Display a list of available options and exit.
Display a list of available options and exit. No arguments allowed.
.TP
\fB\-\-version\fR
Print program version and copyright information and exit.
@@ -248,15 +251,16 @@ Check device numbers when creating incremental archives (default).
.TP
\fB\-g\fR, \fB\-\-listed\-incremental\fR=\fIFILE\fR
Handle new GNU-format incremental backups. \fIFILE\fR is the name of
a \fBsnapshot file\fR, where \fBtar\fR stores additional information which
a \fBsnapshot file\fR, where tar stores additional information which
is used to decide which files changed since the previous incremental
dump and, consequently, must be dumped again. If \fIFILE\fR does not
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, you need a copy of the
snapshot file created for level \fBN-1\fR, and use it as \fIFILE\fR.
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.
When listing or extracting, the actual content of \fIFILE\fR is not
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
@@ -273,7 +277,7 @@ Handle old GNU-format incremental backups.
Do not exit with nonzero on unreadable files.
.TP
\fB\-\-level\fR=\fINUMBER\fR
Set dump level for a created listed-incremental archive. Currently only
Set dump level for created listed-incremental archive. Currently only
\fB\-\-level=0\fR is meaningful: it instructs \fBtar\fR to truncate
the snapshot file before dumping, thereby forcing a level 0 dump.
.TP
@@ -305,7 +309,7 @@ either on the command line or via the \fB\-T\fR option. The default
Disable the use of some potentially harmful options.
.TP
\fB\-\-sparse\-version\fR=\fIMAJOR\fR[.\fIMINOR\fR]
Set which version of the sparse format to use.
Set version of the sparse format to use (implies \fB\-\-sparse\fR).
This option implies
.BR \-\-sparse .
Valid argument values are
@@ -313,7 +317,7 @@ Valid argument values are
.BR 0.1 ", and"
.BR 1.0 .
For a detailed discussion of sparse formats, refer to the \fBGNU Tar
Manual\fR, appendix \fBD\fR, "\fBSparse Formats\fR". Using the \fBinfo\fR
Manual\fR, appendix \fBD\fR, "\fBSparse Formats\fR". Using \fBinfo\fR
reader, it can be accessed running the following command:
.BR "info tar 'Sparse Formats'" .
.TP
@@ -368,6 +372,7 @@ Verify the archive after writing it.
.SS Output stream selection
.TP
\fB\-\-ignore\-command\-error\fR
.TP
Ignore subprocess exit codes.
.TP
\fB\-\-no\-ignore\-command\-error\fR
@@ -470,7 +475,7 @@ executing.
\fB\-\-atime\-preserve\fR[=\fIMETHOD\fR]
Preserve access times on dumped files, either by restoring the times
after reading (\fIMETHOD\fR=\fBreplace\fR, this is the default) or by
not setting the times in the first place (\fIMETHOD\fR=\fBsystem\fR).
not setting the times in the first place (\fIMETHOD\fR=\fBsystem\fR)
.TP
\fB\-\-delay\-directory\-restore\fR
Delay setting modification times and permissions of extracted
@@ -558,16 +563,14 @@ 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
Set permissions of extracted files to those recorded in the archive
(default for superuser).
extract information about file permissions (default for superuser)
.TP
\fB\-\-same\-owner\fR
Try extracting files with the same ownership as exists in the archive
(default for superuser).
.TP
\fB\-s\fR, \fB\-\-preserve\-order\fR, \fB\-\-same\-order\fR
Tell \fBtar\fR that the list of file names to process is sorted in the
same order as the files in the archive.
Sort names to extract to match archive
.TP
\fB\-\-sort=\fIORDER\fR
When creating an archive, sort directory entries according to
@@ -607,13 +610,13 @@ Enable extended attributes support.
Disable extended attributes support.
.TP
.BI \-\-xattrs\-exclude= PATTERN
Specify the exclude pattern for xattr keys. \fIPATTERN\fR is a globbing
pattern, e.g. \fB\-\-xattrs\-exclude='user.*'\fR to include only
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 globbing
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
@@ -741,7 +744,7 @@ end-of-file marker.
.TP
\fB\-i\fR, \fB\-\-ignore\-zeros\fR
Ignore zeroed blocks in archive. Normally two consecutive 512-blocks
filled with zeroes mean EOF and \fBtar\fR stops reading after encountering
filled with zeroes mean EOF and tar stops reading after encountering
them. This option instructs it to read further and is useful when
reading archives created with the \fB\-A\fR option.
.TP
@@ -1010,7 +1013,7 @@ 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\fR option.
\fB\-\-no\-verbatim\-files\-from} option.
This option is implied by the \fB\-\-null\fR option.
@@ -1060,8 +1063,7 @@ Display progress messages every \fIN\fRth record (default 10).
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
\fB\-\-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.
@@ -1120,14 +1122,14 @@ 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.2 "\fBThe '\-\-verbose' Option\fR".
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
messages are suppressed if \fIKEYWORD\fR is prefixed with \fBno\-\fR
and enabled otherwise.
Multiple \fB\-\-warning\fR options accumulate.
Multiple \fB\-\-warning\fR messages accumulate.
Keywords controlling general \fBtar\fR operation:
.RS
@@ -1166,7 +1168,7 @@ Keywords applicable for \fBtar --create\fR:
"%s: file is unchanged; not dumped"
.TP
.B ignore-archive
"%s: archive cannot contain itself; not dumped"
"%s: file is the archive; not dumped"
.TP
.B file-removed
"%s: File removed before we read it"
@@ -1267,7 +1269,7 @@ as \fB\-\-no\-same\-owner\fR.
.fi
.PP
.SH "RETURN VALUE"
Tar's exit code indicates whether it was able to successfully perform
Tar exit code indicates whether it was able to successfully perform
the requested operation, and if not, what kind of error occurred.
.TP
.B 0
@@ -1275,9 +1277,9 @@ Successful termination.
.TP
.B 1
.I Some files differ.
If \fBtar\fR was invoked with the \fB\-\-compare\fR (\fB\-\-diff\fR, \fB\-d\fR)
If tar was invoked with the \fB\-\-compare\fR (\fB\-\-diff\fR, \fB\-d\fR)
command line option, this means that some files in the archive differ
from their disk counterparts. If \fBtar\fR was given one of the \fB\-\-create\fR,
from their disk counterparts. If tar was given one of the \fB\-\-create\fR,
\fB\-\-append\fR or \fB\-\-update\fR options, this exit code means
that some files were changed while being archived and so the resulting
archive does not contain the exact copy of the file set.
@@ -1316,11 +1318,11 @@ Online copies of \fBGNU tar\fR documentation in various formats can be
found at:
.PP
.in +4
.B https://www.gnu.org/software/tar/manual
.B http://www.gnu.org/software/tar/manual
.SH "BUG REPORTS"
Report bugs to <bug\-tar@gnu.org>.
.SH COPYRIGHT
Copyright \(co 2023 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>

View File

@@ -5,16 +5,6 @@
@settitle GNU tar @value{VERSION}
@setchapternewpage odd
@documentencoding UTF-8
@c These two commands require Texinfo 5.0; for now use the older
@c equivalent @set commands supported in Texinfo 4.11 and later.
@ignore
@codequotebacktick on
@codequoteundirected on
@end ignore
@set txicodequoteundirected
@set txicodequotebacktick
@finalout
@smallbook
@@ -46,8 +36,8 @@ This manual is for @acronym{GNU} @command{tar} (version
@value{VERSION}, @value{UPDATED}), which creates and extracts files
from archives.
Copyright @copyright{} 1992, 1994--1997, 1999--2001, 2003--2017,
2021--2023 Free Software Foundation, Inc.
Copyright @copyright{} 1992, 1994--1997, 1999--2001, 2003--2017, 2021
Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -185,14 +175,13 @@ Invoking @GNUTAR{}
* Synopsis::
* using tar options::
* Styles::
* All Options:: All @command{tar} Options.
* help:: Where to Get Help.
* defaults:: What are the Default Values.
* verbose:: Checking @command{tar} progress.
* checkpoints:: Checkpoints.
* warnings:: Controlling Warning Messages.
* interactive:: Asking for Confirmation During Operations.
* external:: Running External Commands.
* All Options::
* help::
* defaults::
* verbose::
* checkpoints::
* warnings::
* interactive::
The Three Option Styles
@@ -208,15 +197,6 @@ All @command{tar} Options
* Short Option Summary::
* Position-Sensitive Options::
Controlling Warning Messages
* General Warnings:: Keywords applicable for @command{tar --create}.
* Archive Creation Warnings:: Keywords applicable for @command{tar --create}.
* Archive Extraction Warnings:: Keywords applicable for @command{tar --extract}.
* Incremental Extraction Warnings:: Keywords controlling incremental extraction.
* Warning Classes:: Convenience keywords control multiple warnings.
* Warning Defaults:: Default settings for warnings.
@GNUTAR{} Operations
* Basic tar::
@@ -329,17 +309,16 @@ Crossing File System Boundaries
Date input formats
* General date syntax:: Common rules
* Calendar date items:: 21 Jul 2020
* Time of day items:: 9:20pm
* Time zone items:: UTC, -0700, +0900, @dots{}
* Combined date and time of day items:: 2020-07-21T20:02:00,000000-0400
* Day of week items:: Monday and others
* Relative items in date strings:: next tuesday, 2 years ago
* Pure numbers in date strings:: 20200721, 1440
* Seconds since the Epoch:: @@1595289600
* Specifying time zone rules:: TZ="America/New_York", TZ="UTC0"
* Authors of parse_datetime:: Bellovin, Eggert, Salz, Berets, et al.
* General date syntax:: Common rules.
* Calendar date items:: 19 Dec 1994.
* Time of day items:: 9:20pm.
* Time zone items:: @sc{est}, @sc{pdt}, @sc{gmt}.
* Day of week items:: Monday and others.
* Relative items in date strings:: next tuesday, 2 years ago.
* Pure numbers in date strings:: 19931219, 1440.
* Seconds since the Epoch:: @@1078100502.
* Specifying time zone rules:: TZ="America/New_York", TZ="UTC0".
* Authors of parse_datetime:: Bellovin, Eggert, Salz, Berets, et al.
Controlling the Archive Format
@@ -409,29 +388,6 @@ Using Multiple Tapes
* Tarcat:: Concatenate Volumes into a Single Archive
Reliability and Security
* Reliability::
* Security::
Reliability
* Permissions problems::
* Data corruption and repair::
* Race conditions::
Security
* Privacy::
* Integrity::
* Live untrusted data::
* Security rules of thumb::
Recipes
* copy directory hierarchy::
* intermediate directories::
Tar Internals
* Standard:: Basic Tar Format
@@ -454,7 +410,7 @@ Genfile
Copying This Manual
* GNU Free Documentation License:: License for copying this manual.
* GNU Free Documentation License:: License for copying this manual
@end detailmenu
@end menu
@@ -675,7 +631,7 @@ For version 1.12, Daniel Hagerty contributed a great deal of technical
consulting. In particular, he is the primary author of @ref{Backups}.
In July, 2003 @GNUTAR{} was put on CVS at savannah.gnu.org
(see @url{https://savannah.gnu.org/projects/tar}), and
(see @url{http://savannah.gnu.org/projects/tar}), and
active development and maintenance work has started
again. Currently @GNUTAR{} is being maintained by Paul Eggert, Sergey
Poznyakoff and Jeff Bailey.
@@ -998,19 +954,6 @@ Note that you must double the hyphens properly each time.
Later in the tutorial, we will give examples using @w{@option{--verbose
--verbose}}.
The @option{--verbose} option also enables several @dfn{warning
messages}, that tar does not issue otherwise, such as the
warning about record size being used (@pxref{Blocking Factor}), selecting
the decompress program and the like. If these are of no interest to
you, you can suppress them using the @option{--warning} option
@emph{after} @option{--verbose}, e.g.:
@example
$ @kbd{tar -c -v --warning=no-verbose -f afiles.tar apple angst aspic}
@end example
@xref{Warning Classes, verbose}, for details.
@anchor{verbose member listing}
The full output consists of six fields:
@@ -1088,6 +1031,9 @@ hrw-r--r-- gray/staff 0 2006-06-09 12:06 music link to blues
@end group
@end smallexample
@smallexample
@end smallexample
@node help tutorial
@unnumberedsubsec Getting Help: Using the @option{--help} Option
@@ -1275,8 +1221,13 @@ jazz
@end smallexample
This example is just like the example we showed which did not use
@option{--verbose}, except that @command{tar} generated three output
@option{--verbose}, except that @command{tar} generated the remaining
@iftex
lines (note the different font styles).
@end iftex
@ifinfo
lines.
@end ifinfo
In the rest of the examples in this chapter, we will frequently use
@code{verbose} mode so we can show actions or @command{tar} responses that
@@ -1852,7 +1803,7 @@ will extract the file @file{folk} into the current working directory.
@node going further
@section Going Further Ahead in this Manual
@UNREVISED{}
@UNREVISED
@FIXME{need to write up a node here about the things that are going to
be in the rest of the manual.}
@@ -2411,7 +2362,7 @@ tape! @xref{delete}.
@item --diff
@itemx -d
Same as @option{--compare}. @xref{compare}.
Same @option{--compare}. @xref{compare}.
@opsummary{extract}
@item --extract
@@ -2903,7 +2854,7 @@ Ignore exit codes of subprocesses. @xref{Writing to an External Program}.
@opsummary{ignore-failed-read}
@item --ignore-failed-read
Do not exit unsuccessfully merely because reading failed.
Do not exit unsuccessfully merely because an unreadable file was encountered.
@xref{Ignore Failed Read}.
@opsummary{ignore-zeros}
@@ -2911,9 +2862,7 @@ Do not exit unsuccessfully merely because reading failed.
@itemx -i
With this option, @command{tar} will ignore zeroed blocks in the
archive, which normally signals EOF. This option also suppresses
warnings about missing or incomplete zero blocks at the end of the
archive. @xref{Ignore Zeros}.
archive, which normally signals EOF. @xref{Reading}.
@opsummary{incremental}
@item --incremental
@@ -2991,7 +2940,7 @@ the pattern specified in @var{name}. @xref{Tape Files}.
@opsummary{level}
@item --level=@var{n}
Force incremental backup of level @var{n}. As of @GNUTAR{} version
Force incremental backup of level @var{n}. As of @GNUTAR version
@value{VERSION}, the option @option{--level=0} truncates the snapshot
file, thereby forcing the level 0 dump. Other values of @var{n} are
effectively ignored. @xref{--level=0}, for details and examples.
@@ -3337,7 +3286,7 @@ Same as @option{--format=posix}.
@opsummary{preserve-order}
@item --preserve-order
(See @option{--same-order}; @pxref{Same Order}.)
(See @option{--same-order}; @pxref{Reading}.)
@opsummary{preserve-permissions}
@opsummary{same-permissions}
@@ -3427,7 +3376,7 @@ devices. @xref{Device}.
This option is an optimization for @command{tar} when running on machines with
small amounts of memory. It informs @command{tar} that the list of file
arguments has already been sorted to match the order of files in the
archive. @xref{Same Order}.
archive. @xref{Reading}.
@opsummary{same-owner}
@item --same-owner
@@ -4043,16 +3992,16 @@ itself, containing possibly many programs. The package is currently
named @samp{tar}, after the name of the main program it
contains@footnote{There are plans to merge the @command{cpio} and
@command{tar} packages into a single one which would be called
@code{paxutils}. So, who knows, one of these days
@option{--version} might output @w{@samp{tar (@acronym{GNU}
@code{paxutils}. So, who knows if, one of this days, the
@option{--version} would not output @w{@samp{tar (@acronym{GNU}
paxutils) 3.2}}.}.
@cindex Obtaining help
@cindex Listing all @command{tar} options
@xopindex{help, introduction}
Another thing you might want to do is check the spelling or meaning
Another thing you might want to do is checking the spelling or meaning
of some particular @command{tar} option, without resorting to this
manual, once you have carefully read it. @GNUTAR{}
manual, for once you have carefully read it. @GNUTAR{}
has a short help feature, triggerable through the
@option{--help} option. By using this option, @command{tar} will
print a usage message listing all available options on standard
@@ -4092,7 +4041,7 @@ The short help output is quite succinct, and you might have to get
back to the full documentation for precise points. If you are reading
this paragraph, you already have the @command{tar} manual in some
form. This manual is available in a variety of forms from
@url{https://www.gnu.org/software/tar/manual}. It may be printed out of the @GNUTAR{}
@url{http://www.gnu.org/software/tar/manual}. It may be printed out of the @GNUTAR{}
distribution, provided you have @TeX{} already installed somewhere,
and a laser printer around. Just configure the distribution, execute
the command @w{@samp{make dvi}}, then print @file{doc/tar.dvi} the
@@ -4103,10 +4052,12 @@ file. Just call @w{@samp{info tar}} or, if you do not have the
@command{info} program handy, use the Info reader provided within
@acronym{GNU} Emacs, calling @samp{tar} from the main Info menu.
Since 2014, @GNUTAR{} also has a @code{man} page.
It briefly explains all the options and operations.
This might be preferable when you don't need any background.
But bear in mind that the authoritative source of
There is currently no @code{man} page for @GNUTAR{}.
If you observe such a @code{man} page on the system you are running,
either it does not belong to @GNUTAR{}, or it has not
been produced by @acronym{GNU}. Some package maintainers convert
@kbd{tar --help} output to a man page, using @command{help2man}. In
any case, please bear in mind that the authoritative source of
information about @GNUTAR{} is this Texinfo documentation.
@node defaults
@@ -4622,154 +4573,110 @@ Control display of the warning messages identified by @var{keyword}.
If @var{keyword} starts with the prefix @samp{no-}, such messages are
suppressed. Otherwise, they are enabled.
Multiple @option{--warning} options accumulate.
Multiple @option{--warning} messages accumulate.
The tables below list allowed values for @var{keyword} along with the
warning messages they control.
@end table
By default, @GNUTAR enables all messages, except those that are
enabled in verbose mode (@pxref{verbose tutorial}). @xref{Warning
Defaults}, for details.
The subsections below discuss allowed values for @var{keyword} along with the
warning messages they control.
@menu
* General Warnings:: Keywords applicable for @command{tar --create}.
* Archive Creation Warnings:: Keywords applicable for @command{tar --create}.
* Archive Extraction Warnings:: Keywords applicable for @command{tar --extract}.
* Incremental Extraction Warnings:: Keywords controlling incremental extraction.
* Warning Classes:: Convenience keywords control multiple warnings.
* Warning Defaults:: Default settings for warnings.
@end menu
@node General Warnings
@subsection Keywords controlling @command{tar} operation
These keywords control warnings that may appear in any @GNUTAR{}
operation mode:
@defvr {warning} filename-with-nuls
@cindex @samp{file name read contains nul character}, warning message
@samp{file name read contains nul character}
@end defvr
@defvr {warning} filename-with-nuls
@subheading Keywords controlling @command{tar} operation
@table @asis
@kwindex all
@item all
Enable all warning messages. This is the default.
@kwindex none
@item none
Disable all warning messages.
@kwindex filename-with-nuls
@cindex @samp{file name read contains nul character}, warning message
@item filename-with-nuls
@samp{%s: file name read contains nul character}
@end defvr
@defvr {warning} alone-zero-block
@kwindex alone-zero-block
@cindex @samp{A lone zero block at}, warning message
@samp{A lone zero block at %s}. Notice, that this warning is
suppressed if @option{--ignore-zeros} is in effect (@pxref{Ignore
Zeros}).
@end defvr
@item alone-zero-block
@samp{A lone zero block at %s}
@end table
@defvr {warning} missing-zero-blocks
@cindex @samp{Terminating zero blocks missing}, warning message.
@samp{Terminating zero blocks missing at %s}. This warning is
suppressed if @option{--ignore-zeros} is in effect (@pxref{Ignore
Zeros}).
@end defvr
@node Archive Creation Warnings
@subsection Keywords applicable for @command{tar --create}
The following keywords control messages that can be issued while
creating archives.
@defvr {warning} cachedir
@subheading Keywords applicable for @command{tar --create}
@table @asis
@kwindex cachedir
@cindex @samp{contains a cache directory tag}, warning message
@item cachedir
@samp{%s: contains a cache directory tag %s; %s}
@end defvr
@defvr {warning} file-shrank
@kwindex file-shrank
@cindex @samp{File shrank by %s bytes}, warning message
@item file-shrank
@samp{%s: File shrank by %s bytes; padding with zeros}
@end defvr
@defvr {warning} xdev
@kwindex xdev
@cindex @samp{file is on a different filesystem}, warning message
@item xdev
@samp{%s: file is on a different filesystem; not dumped}
@end defvr
@defvr {warning} file-ignored
@kwindex file-ignored
@cindex @samp{Unknown file type; file ignored}, warning message
@cindex @samp{socket ignored}, warning message
@cindex @samp{door ignored}, warning message
@item file-ignored
@samp{%s: Unknown file type; file ignored}
@*@samp{%s: socket ignored}
@*@samp{%s: door ignored}
@end defvr
@defvr {warning} file-unchanged
@kwindex file-unchanged
@cindex @samp{file is unchanged; not dumped}, warning message
@item file-unchanged
@samp{%s: file is unchanged; not dumped}
@end defvr
@defvr {warning} ignore-archive
@cindex @samp{archive cannot contain itself; not dumped}, warning message
@samp{%s: archive cannot contain itself; not dumped}
@end defvr
@defvr {warning} file-removed
@kwindex ignore-archive
@cindex @samp{file is the archive; not dumped}, warning message
@kwindex ignore-archive
@cindex @samp{file is the archive; not dumped}, warning message
@item ignore-archive
@samp{%s: file is the archive; not dumped}
@kwindex file-removed
@cindex @samp{File removed before we read it}, warning message
@item file-removed
@samp{%s: File removed before we read it}
@end defvr
@defvr {warning} file-changed
@kwindex file-changed
@cindex @samp{file changed as we read it}, warning message
@item file-changed
@samp{%s: file changed as we read it}
Suppresses warnings about read failures, which can occur if files
or directories are unreadable, or if they change while being read. This
@item failed-read
Suppresses warnings about unreadable files or directories. This
keyword applies only if used together with the @option{--ignore-failed-read}
option. @xref{Ignore Failed Read}.
@end defvr
@end table
@node Archive Extraction Warnings
@subsection Keywords applicable for @command{tar --extract}
The following keywords control warnings that can be issued during
archive extraction.
@defvr {warning} existing-file
@subheading Keywords applicable for @command{tar --extract}
@table @asis
@kwindex existing-file
@cindex @samp{%s: skipping existing file}, warning message
@item existing-file
@samp{%s: skipping existing file}
@end defvr
@defvr {warning} timestamp
@kwindex timestamp
@cindex @samp{implausibly old time stamp %s}, warning message
@cindex @samp{time stamp %s is %s s in the future}, warning message
@item timestamp
@samp{%s: implausibly old time stamp %s}
@*@samp{%s: time stamp %s is %s s in the future}
@end defvr
@defvr {warning} contiguous-cast
@kwindex contiguous-cast
@cindex @samp{Extracting contiguous files as regular files}, warning message
@item contiguous-cast
@samp{Extracting contiguous files as regular files}
@end defvr
@defvr {warning} symlink-cast
@samp{Attempting extraction of symbolic links as hard links}, warning message
@kwindex symlink-cast
@cindex @samp{Attempting extraction of symbolic links as hard links}, warning message
@item symlink-cast
@samp{Attempting extraction of symbolic links as hard links}
@end defvr
@defvr {warning} unknown-cast
@kwindex unknown-cast
@cindex @samp{Unknown file type '%c', extracted as normal file}, warning message
@item unknown-cast
@samp{%s: Unknown file type '%c', extracted as normal file}
@end defvr
@defvr {warning} ignore-newer
@kwindex ignore-newer
@cindex @samp{Current %s is newer or same age}, warning message
@item ignore-newer
@samp{Current %s is newer or same age}
@end defvr
@defvr {warning} unknown-keyword
@kwindex unknown-keyword
@cindex @samp{Ignoring unknown extended header keyword '%s'}, warning message
@item unknown-keyword
@samp{Ignoring unknown extended header keyword '%s'}
@end defvr
@defvr {warning} decompress-program
@kwindex decompress-program
@item decompress-program
Controls verbose description of failures occurring when trying to run
alternative decompressor programs (@pxref{alternative decompression
programs}). This warning is disabled by default (unless
@@ -4785,69 +4692,33 @@ tar (child): trying gzip
This means that @command{tar} first tried to decompress
@file{archive.Z} using @command{compress}, and, when that
failed, switched to @command{gzip}.
@end defvr
@defvr {warning} record-size
@kwindex record-size
@cindex @samp{Record size = %lu blocks}, warning message
@item record-size
@samp{Record size = %lu blocks}
@end defvr
@end table
@node Incremental Extraction Warnings
@subsection Keywords controlling incremental extraction
These keywords control warnings that may appear when extracting from
incremental archives.
@defvr {warning} rename-directory
@subheading Keywords controlling incremental extraction:
@table @asis
@kwindex rename-directory
@cindex @samp{%s: Directory has been renamed from %s}, warning message
@cindex @samp{%s: Directory has been renamed}, warning message
@item rename-directory
@samp{%s: Directory has been renamed from %s}
@*@samp{%s: Directory has been renamed}
@end defvr
@defvr {warning} new-directory
@kwindex new-directory
@cindex @samp{%s: Directory is new}, warning message
@item new-directory
@samp{%s: Directory is new}
@end defvr
@defvr {warning} xdev
@kwindex xdev
@cindex @samp{%s: directory is on a different device: not purging}, warning message
@item xdev
@samp{%s: directory is on a different device: not purging}
@end defvr
@defvr {warning} bad-dumpdir
@kwindex bad-dumpdir
@cindex @samp{Malformed dumpdir: 'X' never used}, warning message
@item bad-dumpdir
@samp{Malformed dumpdir: 'X' never used}
@end defvr
@node Warning Classes
@subsection Warning Classes
These convenience keywords define @dfn{warning classes}. When used,
they affect several warnings at once.
@defvr {warning} all
Enable all warning messages.
@end defvr
@defvr {warning} none
Disable all warning messages.
@end defvr
@defvr {warning} verbose
A shorthand for all messages enabled when @option{--verbose}
(@pxref{verbose tutorial}) is in effect. These are:
@code{decompress-program}, @code{existing-file}, @code{new-directory},
@code{record-size}, @code{rename-directory}.
@end defvr
@node Warning Defaults
@subsection Default Warning Settings
@GNUTAR default settings correspond to:
@example
--warning=all --warning=no-verbose --warning=no-missing-zero-blocks
@end example
@end table
@node interactive
@section Asking for Confirmation During Operations
@@ -5400,7 +5271,7 @@ jazz
@end smallexample
@noindent
If you like, you can run @samp{tar --list} to make sure the archives
If you like, You can run @samp{tar --list} to make sure the archives
contain what they are supposed to:
@smallexample
@@ -5415,6 +5286,7 @@ $ @kbd{tar -tvf jazzfolk.tar}
We can concatenate these two archives with @command{tar}:
@smallexample
$ @kbd{cd ..}
$ @kbd{tar --concatenate --file=bluesrock.tar jazzfolk.tar}
@end smallexample
@@ -5760,7 +5632,7 @@ controlled by the following command line arguments:
@table @option
@item --xattrs
Enable extended attributes support. When used with @option{--create},
this option instructs @GNUTAR{} to store extended file attribute in the
this option instructs @GNUTAR to store extended file attribute in the
created archive. This implies POSIX.1-2001 archive format
(@option{--format=pax}).
@@ -5774,15 +5646,10 @@ Disable extended attributes support. This is the default.
Attribute names are strings prefixed by a @dfn{namespace} name and a dot.
Currently, four namespaces exist: @samp{user}, @samp{trusted},
@samp{security} and @samp{system}. By default, when @option{--xattrs}
is used, all names are stored in the archive (with @option{--create}),
but only @samp{user} namespace is extracted (if using @option{--extract}).
The reason for this behavior is that any other, system defined attributes
don't provide us sufficient compatibility promise. Storing all attributes
is safe operation for the archiving purposes. Though extracting those
(often security related) attributes on a different system than originally
archived can lead to extraction failures, or even misinterpretations.
This behavior can be controlled using the following options:
@samp{security} and @samp{system}. By default, when @option{--xattr}
is used, all names are stored in the archive (or extracted, if using
@option{--extract}). This can be controlled using the following
options:
@table @option
@item --xattrs-exclude=@var{pattern}
@@ -5796,16 +5663,12 @@ Here, the @var{pattern} is a globbing pattern. For example, the
following command:
@example
$ @kbd{tar --xattrs --xattrs-exclude='user.*' -cf a.tar .}
$ @kbd{tar --xattrs --xattrs-exclude='user.*' -c a.tar .}
@end example
will include in the archive @file{a.tar} all attributes, except those
from the @samp{user} namespace.
Users shall check the attributes are binary compatible with the target system
before any other namespace is extracted with an explicit
@option{--xattrs-include} option.
Any number of these options can be given, thereby creating lists of
include and exclude patterns.
@@ -5898,12 +5761,11 @@ Disable SELinux context support.
@table @option
@item --ignore-failed-read
@opindex ignore-failed-read
Do not exit with nonzero if there are mild problems while reading.
Do not exit with nonzero on unreadable files or directories.
@end table
This option has effect only during creation. It instructs tar to
treat as mild conditions any missing or unreadable files (directories),
or files that change while reading.
treat as mild conditions any missing or unreadable files (directories).
Such failures don't affect the program exit code, and the
corresponding diagnostic messages are marked as warnings, not errors.
These warnings can be suppressed using the
@@ -5990,11 +5852,7 @@ between file entries (which usually indicates the end of the archive).
@option{--ignore-zeros} (@option{-i}) allows @command{tar} to
completely read an archive which contains a block of zeros before the
end (i.e., a damaged archive, or one that was created by concatenating
several archives together). This option also suppresses warnings
about missing or incomplete zero blocks at the end of the archive.
This can be turned on, if the need be, using the
@option{--warning=alone-zero-block --warning=missing-zero-blocks}
options (@pxref{warnings}).
several archives together).
The @option{--ignore-zeros} (@option{-i}) option is turned off by default because many
versions of @command{tar} write garbage after the end-of-archive entry,
@@ -6012,7 +5870,7 @@ encountered while reading an archive. Use in conjunction with
@node Writing
@subsection Changing How @command{tar} Writes Files
@UNREVISED{}
@UNREVISED
@FIXME{Introductory paragraph}
@@ -6525,7 +6383,7 @@ Remove files after adding them to the archive.
@node Scarce
@subsection Coping with Scarce Resources
@UNREVISED{}
@UNREVISED
@cindex Small memory
@cindex Running out of space
@@ -6772,7 +6630,7 @@ called @dfn{dumps}.
@node Full Dumps
@section Using @command{tar} to Perform Full Dumps
@UNREVISED{}
@UNREVISED
@cindex full dumps
@cindex dumps, full
@@ -7098,8 +6956,8 @@ mainly variable assignments. However, any valid shell construct
is allowed in this file. Particularly, you may wish to define
functions within that script (e.g., see @code{RESTORE_BEGIN} below).
For more information about shell script syntax, please refer to
@url{https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html,
the definition of the Shell Command Language}. See also
@url{http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#ta
g_02, the definition of the Shell Command Language}. See also
@ref{Top,,Bash Features,bashref,Bash Reference Manual}.
The shell variables controlling behavior of @code{backup} and
@@ -7854,11 +7712,7 @@ command.
Any number of @option{-T} options can be given in the command line.
The following example shows how to use @command{find} to generate a list of
files smaller than 400 blocks in length@footnote{A file system block
is usually 512 bytes, so this amounts to 200K. Use the @samp{c}
suffix to specify size in @emph{bytes}. Also, when using
GNU find, you can specify other size units, such as @samp{k},
@samp{m}, etc. @xref{Size,,,find.info,GNU Findutils}, for details.} and put that list into a file
files smaller than 400K in length and put that list into a file
called @file{small-files}. You can then use the @option{-T} option to
@command{tar} to specify the files from that file, @file{small-files}, to
create the archive @file{little.tgz}. (The @option{-z} option to
@@ -7984,7 +7838,7 @@ file names that begin with dash (similar to
@option{--verbatim-files-from} option).
This example shows how to use @command{find} to generate a list of files
larger than 800 blocks in length and put that list into a file called
larger than 800K in length and put that list into a file called
@file{long-files}. The @option{-print0} option to @command{find} is just
like @option{-print}, except that it separates files with a @code{NUL}
rather than with a newline. You can then run @command{tar} with both the
@@ -8013,7 +7867,7 @@ $ @kbd{find . -size +800 -print0 |
This example uses short options for typographic reasons, to avoid
very long lines.
@GNUTAR{} is tries to automatically detect @code{NUL}-terminated file
@GNUTAR is tries to automatically detect @code{NUL}-terminated file
lists, so in many cases it is safe to use them even without the
@option{--null} option. In this case @command{tar} will print a
warning and continue reading such a file as if @option{--null} were
@@ -10340,9 +10194,11 @@ contain @samp{/-}. Avoid deep directory nesting. For portability to
old Unix hosts, limit your file name components to 14 characters or
less.
If you intend to have your @command{tar} archives to be read on
case-insensitive file systems like FAT32,
you should not rely on case distinction for file names.
If you intend to have your @command{tar} archives to be read under
MSDOS, you should not rely on case distinction for file names, and you
might use the @acronym{GNU} @command{doschk} program for helping you
further diagnosing illegal MSDOS names, which are even more limited
than System V's.
@node dereference
@subsection Symbolic Links
@@ -10567,9 +10423,6 @@ the following forms:
When used with one of archive-creation commands,
this option instructs @command{tar} to omit from extended header records
that it produces any keywords matching the string @var{pattern}.
If the pattern contains shell metacharacters like @samp{*}, it should
be quoted to prevent the shell from expanding the pattern before
@command{tar} sees it.
When used in extract or list mode, this option instructs tar
to ignore any keywords matching the given @var{pattern} in the extended
@@ -10578,7 +10431,7 @@ matching notation described in @acronym{POSIX 1003.2}, 3.13
(@pxref{wildcards}). For example:
@smallexample
--pax-option 'delete=security.*'
--pax-option delete=security.*
@end smallexample
would suppress security-related information.
@@ -10707,9 +10560,11 @@ For example, to set all modification times to the current date, you
use the following option:
@smallexample
--pax-option 'mtime:=@{now@}'
--pax-option='mtime:=@{now@}'
@end smallexample
Note quoting of the option's argument.
@cindex archives, binary equivalent
@cindex binary equivalent archives, creating
As another example, here is the option that ensures that any two
@@ -10717,36 +10572,36 @@ archives created using it, will be binary equivalent if they have the
same contents:
@smallexample
--pax-option delete=atime
--pax-option=atime:=0
@end smallexample
@noindent
If you extract files from such an archive and recreate the archive
from them, you will also need to eliminate changes due to ctime:
from them, you will also need to eliminate changes due to ctime, as
shown in examples below:
@smallexample
--pax-option 'delete=atime,delete=ctime'
--pax-option=atime:=0,ctime:=0
@end smallexample
Normally @command{tar} saves an mtime value with subsecond resolution
in an extended header for any file with a timestamp that is not on a
one-second boundary. This is in addition to the traditional mtime
timestamp in the header block. Although you can suppress subsecond
timestamp resolution with @option{--pax-option delete=mtime},
this hack will not work for timestamps before 1970 or after 2242-03-16
12:56:31 @sc{utc}.
If the environment variable @env{POSIXLY_CORRECT} is set, two POSIX
archives created using the same options on the same set of files might
not be byte-to-byte equivalent even with the above options. This is
because the POSIX default for extended header names includes
the @command{tar} process @acronym{ID}, which typically differs at each
run. To produce byte-to-byte equivalent archives in this case, either
unset @env{POSIXLY_CORRECT}, or use the following option, which can be
combined with the above options:
@noindent
or
@smallexample
--pax-option exthdr.name=%d/PaxHeaders/%f
--pax-option=atime:=0,delete=ctime
@end smallexample
Notice, that if you create an archive in POSIX format (@pxref{posix})
and the environment variable @env{POSIXLY_CORRECT} is set, then the
two archives created using the same options on the same set of files
will not be byte-to-byte equivalent even with the above option. This
is because the posix default for extended header names includes the
PID of the tar process, which is different at each run. To produce
byte-to-byte equivalent archives in this case, either unset
@env{POSIXLY_CORRECT}, or use the following option:
@smallexample
---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0
@end smallexample
@node Checksumming
@@ -10790,7 +10645,7 @@ a @command{tar} able to read the good archives they receive.
@cindex large values
@cindex future time stamps
@cindex negative time stamps
@UNREVISED{}
@UNREVISED
The above sections suggest to use @samp{oldest possible} archive
format if in doubt. However, sometimes it is not possible. If you
@@ -11173,7 +11028,7 @@ Done
@node cpio
@section Comparison of @command{tar} and @command{cpio}
@UNREVISED{}
@UNREVISED
@FIXME{Reorganize the following material}
@@ -11285,7 +11140,7 @@ easily test, because the resulting archive gets smaller, and
@node Media
@chapter Tapes and Other Archive Media
@UNREVISED{}
@UNREVISED
A few special cases about tape handling warrant more detailed
description. These special cases are discussed below.
@@ -11329,7 +11184,7 @@ not a good idea.
@node Device
@section Device Selection and Switching
@UNREVISED{}
@UNREVISED
@table @option
@item -f [@var{hostname}:]@var{file}
@@ -11697,7 +11552,7 @@ device.
@cindex Format Options
@cindex Options, archive format specifying
@cindex Options, format specifying
@UNREVISED{}
@UNREVISED
Format parameters specify how an archive is written on the archive
media. The best choice of format parameters will vary depending on
@@ -11721,7 +11576,7 @@ examples of format parameter considerations.
@cindex Number of bytes per record
@cindex Bytes per record
@cindex Blocks per record
@UNREVISED{}
@UNREVISED
@opindex blocking-factor
The data in an archive is grouped into blocks, which are 512 bytes.
@@ -12074,7 +11929,7 @@ you should do the proper things for that as well. @xref{Blocking}.
@node Tape Positioning
@subsection Tape Positions and Tape Marks
@UNREVISED{}
@UNREVISED
Just as archives can store more than one file from the file system,
tapes can store more than one archive file. To keep track of where
@@ -12115,7 +11970,7 @@ rrrr*rrrrrr*rrrrr*rr*rrrrr*rrr*rrrr**----------------
@node mt
@subsection The @command{mt} Utility
@UNREVISED{}
@UNREVISED
@FIXME{Is it true that this only works on non-block devices?
should explain the difference, (fixed or variable).}
@@ -12500,7 +12355,7 @@ implementation, read @ref{Split Recovery}.
@subsection Tape Files
@cindex labeling archives
@opindex label
@UNREVISED{}
@UNREVISED
To give the archive a name which will be recorded in it, use the
@option{--label=@var{volume-label}} (@option{-V @var{volume-label}})

View File

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

View File

@@ -1,5 +1,5 @@
@c This is part of GNU tar manual.
@c Copyright 1992--2023 Free Software Foundation, Inc.
@c Copyright 1992--2021 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@macro GNUTAR

2
gnulib

Submodule gnulib updated: 46f9c21a08...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-2023 Free Software Foundation, Inc.
# Copyright 2005-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -23,12 +23,10 @@ areadlinkat-with-size
argmatch
argp
argp-version-etc
attribute
backupfile
closeout
configmake
dirname
dup2
error
exclude
extern-inline
@@ -41,10 +39,8 @@ fdopendir
fdutimensat
file-has-acl
fileblocks
flexmember
fnmatch-gnu
fprintftime
free-posix
fseeko
fstatat
full-write
@@ -52,12 +48,11 @@ futimens
getline
getopt-gnu
getpagesize
gettext-h
gettext
gettime
gitlog-to-changelog
hash
human
idx
inttostr
inttypes
lchown
@@ -79,7 +74,7 @@ readlinkat
renameat
root-uid
rpmatch
full-read
safe-read
savedir
selinux-at
setenv
@@ -109,4 +104,3 @@ xalloc-die
xgetcwd
xstrtoumax
xvasprintf
year2038-recommended

View File

@@ -1,6 +1,6 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright 1994-2023 Free Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,5 +1,5 @@
/* Replacement <attr/xattr.h> for platforms that lack it.
Copyright 2012-2023 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
@@ -22,39 +22,39 @@
#endif
/* setting */
static int setxattr (const char *path, const char *name, const void
*value, size_t size, int flags)
static inline int setxattr (const char *path, const char *name, const void
*value, size_t size, int flags)
{ errno = ENOTSUP; return -1; }
static int lsetxattr (const char *path, const char *name, const void
*value, size_t size, int flags)
static inline int lsetxattr (const char *path, const char *name, const void
*value, size_t size, int flags)
{ errno = ENOTSUP; return -1; }
static int fsetxattr (int filedes, const char *name, const void *value,
size_t size, int flags)
static inline int fsetxattr (int filedes, const char *name, const void *value,
size_t size, int flags)
{ errno = ENOTSUP; return -1; }
/* getting */
static ssize_t getxattr (const char *path, const char *name, void *value,
size_t size)
static inline ssize_t getxattr (const char *path, const char *name, void *value,
size_t size)
{ errno = ENOTSUP; return -1; }
static ssize_t lgetxattr (const char *path, const char *name, void
*value, size_t size)
static inline ssize_t lgetxattr (const char *path, const char *name, void
*value, size_t size)
{ errno = ENOTSUP; return -1; }
static ssize_t fgetxattr (int filedes, const char *name, void *value,
size_t size)
static inline ssize_t fgetxattr (int filedes, const char *name, void *value,
size_t size)
{ errno = ENOTSUP; return -1; }
/* listing */
static ssize_t listxattr (const char *path, char *list, size_t size)
static inline ssize_t listxattr (const char *path, char *list, size_t size)
{ errno = ENOTSUP; return -1; }
static ssize_t llistxattr (const char *path, char *list, size_t size)
static inline ssize_t llistxattr (const char *path, char *list, size_t size)
{ errno = ENOTSUP; return -1; }
static ssize_t flistxattr (int filedes, char *list, size_t size)
static inline ssize_t flistxattr (int filedes, char *list, size_t size)
{ errno = ENOTSUP; return -1; }
#endif

View File

@@ -36,6 +36,14 @@
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
#ifndef FALLTHROUGH
# if __GNUC__ < 7
# define FALLTHROUGH ((void) 0)
# else
# define FALLTHROUGH __attribute__ ((__fallthrough__))
# endif
#endif
#include <wordsplit.h>
#define ISWS(c) ((c)==' '||(c)=='\t'||(c)=='\n')
@@ -66,7 +74,7 @@ _wsplt_alloc_die (struct wordsplit *wsp)
abort ();
}
static void ATTRIBUTE_FORMAT ((__printf__, 1, 2))
static void __WORDSPLIT_ATTRIBUTE_FORMAT ((__printf__, 1, 2))
_wsplt_error (const char *fmt, ...)
{
va_list ap;
@@ -87,7 +95,7 @@ _wsplt_seterr (struct wordsplit *wsp, int ec)
wordsplit_perror (wsp);
return ec;
}
static int
_wsplt_nomem (struct wordsplit *wsp)
{
@@ -118,7 +126,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
unsigned flags, int finalize)
{
int rc;
wss->ws_delim = wsp->ws_delim;
wss->ws_debug = wsp->ws_debug;
wss->ws_error = wsp->ws_error;
@@ -142,7 +150,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
}
wss->ws_options = wsp->ws_options;
flags |= WRDSF_DELIM
| WRDSF_ALLOC_DIE
| WRDSF_ERROR
@@ -201,7 +209,7 @@ wordsplit_init0 (struct wordsplit *wsp)
}
char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
static int
wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
unsigned flags)
@@ -274,7 +282,7 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
{
wsp->ws_escape[WRDSX_WORD] = wordsplit_c_escape_tab;
wsp->ws_escape[WRDSX_QUOTE] = wordsplit_c_escape_tab;
wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD
wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD
| WRDSO_XESC_QUOTE | WRDSO_XESC_WORD;
}
else
@@ -284,16 +292,16 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
wsp->ws_options |= WRDSO_BSKEEP_QUOTE;
}
}
wsp->ws_endp = 0;
wsp->ws_wordi = 0;
if (wsp->ws_flags & WRDSF_REUSE)
wordsplit_free_nodes (wsp);
wsp->ws_head = wsp->ws_tail = NULL;
wordsplit_init0 (wsp);
return 0;
}
@@ -416,13 +424,14 @@ wsnode_len (struct wordsplit_node *p)
return p->v.segm.end - p->v.segm.beg;
}
static struct wordsplit_node *
wsnode_new (struct wordsplit *wsp)
static int
wsnode_new (struct wordsplit *wsp, struct wordsplit_node **pnode)
{
struct wordsplit_node *node = calloc (1, sizeof (*node));
if (!node)
_wsplt_nomem (wsp);
return node;
return _wsplt_nomem (wsp);
*pnode = node;
return 0;
}
static void
@@ -472,7 +481,7 @@ wsnode_remove (struct wordsplit *wsp, struct wordsplit_node *node)
static struct wordsplit_node *
wsnode_tail (struct wordsplit_node *p)
{
while (p->next)
while (p && p->next)
p = p->next;
return p;
}
@@ -518,11 +527,14 @@ wsnode_insert (struct wordsplit *wsp, struct wordsplit_node *node,
static int
wordsplit_add_segm (struct wordsplit *wsp, size_t beg, size_t end, int flg)
{
struct wordsplit_node *node;
int rc;
if (end == beg && !(flg & _WSNF_EMPTYOK))
return 0;
struct wordsplit_node *node = wsnode_new (wsp);
if (!node)
return 1;
rc = wsnode_new (wsp, &node);
if (rc)
return rc;
node->flags = flg & ~(_WSNF_WORD | _WSNF_EMPTYOK);
node->v.segm.beg = beg;
node->v.segm.end = end;
@@ -571,16 +583,17 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
struct wordsplit_node *p, *end;
size_t len = 0;
char *buf, *cur;
int stop;
for (p = node; p->flags & _WSNF_JOIN; )
if (!(node->flags & _WSNF_JOIN))
return 0;
for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next)
{
len += wsnode_len (p);
p = p->next;
if (!p)
break;
}
if (p == node)
return 0;
if (p)
len += wsnode_len (p);
end = p;
buf = malloc (len + 1);
@@ -589,7 +602,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
cur = buf;
p = node;
for (;;)
for (stop = 0; !stop;)
{
struct wordsplit_node *next = p->next;
const char *str = wsnode_ptr (wsp, p);
@@ -601,12 +614,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
{
node->flags |= p->flags & _WSNF_QUOTE;
wsnode_remove (wsp, p);
if (p == end)
{
/* Call wsnode_free separately to work around GCC bug 106427. */
wsnode_free (p);
break;
}
stop = p == end;
wsnode_free (p);
}
p = next;
@@ -709,7 +717,7 @@ wordsplit_finish (struct wordsplit *wsp)
Nodes of type _WSNF_DELIM get inserted to the node list if either
WRDSF_RETURN_DELIMS flag or WRDSO_MAXWORDS option is set.
The following cases should be distinguished:
1. If both WRDSF_SQUEEZE_DELIMS and WRDSF_RETURN_DELIMS are set, compress
@@ -773,7 +781,7 @@ wordsplit_finish (struct wordsplit *wsp)
continue;
}
}
else
else
{
if (delim)
{
@@ -892,11 +900,11 @@ node_split_prefix (struct wordsplit *wsp,
struct wordsplit_node *node,
size_t beg, size_t len, int flg)
{
struct wordsplit_node *newnode;
if (len == 0)
return 0;
struct wordsplit_node *newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
if (node->flags & _WSNF_WORD)
@@ -950,7 +958,7 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff,
break;
}
break;
case '"':
state = st_dquote;
break;
@@ -1030,7 +1038,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
{
int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
char *v;
if (wsp->ws_envidx + n >= wsp->ws_envsiz)
{
size_t sz;
@@ -1047,7 +1055,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
for (; wsp->ws_env[i]; i++)
;
}
sz = i + n + 1;
newenv = calloc (sz, sizeof(newenv[0]));
@@ -1067,7 +1075,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
}
}
newenv[j] = NULL;
wsp->ws_envbuf = newenv;
wsp->ws_envidx = i;
wsp->ws_envsiz = sz;
@@ -1096,7 +1104,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
wsp->ws_env = (const char**) wsp->ws_envbuf;
}
}
if (wsp->ws_flags & WRDSF_ENV_KV)
{
/* A key-value pair environment */
@@ -1141,7 +1149,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
const char *start = str - 1;
int rc;
struct wordsplit ws;
if (ISVARBEG (str[0]))
{
for (i = 1; i < len; i++)
@@ -1158,7 +1166,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
if (str[i] == ':')
{
size_t j;
defstr = str + i + 1;
if (find_closing_paren (str, i + 1, len, &j, "{}"))
return _wsplt_seterr (wsp, WRDSE_CBRACE);
@@ -1174,7 +1182,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
else if (strchr ("-+?=", str[i]))
{
size_t j;
defstr = str + i;
if (find_closing_paren (str, i, len, &j, "{}"))
return _wsplt_seterr (wsp, WRDSE_CBRACE);
@@ -1187,8 +1195,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
else
{
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1240,7 +1247,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
rc = WRDSE_UNDEF;
}
}
switch (rc)
{
case WRDSE_OK:
@@ -1260,7 +1267,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
wordsplit_free (&ws);
}
break;
case WRDSE_UNDEF:
if (defstr)
{
@@ -1280,11 +1287,11 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
value = ws.ws_wordv[0];
ws.ws_wordv[0] = NULL;
wordsplit_free (&ws);
if (defstr[-1] == '=')
wsplt_assign_var (wsp, str, i, value);
}
else
else
{
if (*defstr == '?')
{
@@ -1332,7 +1339,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
}
break;
case WRDSE_NOSPACE:
return _wsplt_nomem (wsp);
@@ -1350,8 +1357,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
if (flg & _WSNF_QUOTE)
{
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
{
free (value);
return 1;
@@ -1365,8 +1371,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
free (value);
/* Empty string is a special case */
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1376,7 +1381,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
struct wordsplit ws;
int rc;
rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
WRDSF_NOVAR | WRDSF_NOCMD |
WRDSF_QUOTE
@@ -1399,8 +1404,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
size_t size = *pend - start + 1;
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1413,8 +1417,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
else
{
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1483,7 +1486,7 @@ node_expand (struct wordsplit *wsp, struct wordsplit_node *node,
}
return 0;
}
/* Remove NULL nodes from the list */
static void
wsnode_nullelim (struct wordsplit *wsp)
@@ -1536,7 +1539,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
size_t j;
char *value;
struct wordsplit_node *newnode;
str++;
len--;
@@ -1563,7 +1566,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
}
else
rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure);
if (rc == WRDSE_NOSPACE)
return _wsplt_nomem (wsp);
else if (rc)
@@ -1582,8 +1585,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
{
if (flg & _WSNF_QUOTE)
{
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1594,8 +1596,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
{
free (value);
/* Empty string is a special case */
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1626,8 +1627,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
}
else
{
newnode = wsnode_new (wsp);
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
@@ -1674,13 +1674,13 @@ wordsplit_trimws (struct wordsplit *wsp)
;
p->v.segm.beg = n;
}
while (p->next && (p->flags & _WSNF_JOIN))
p = p->next;
if (p->flags & _WSNF_QUOTE)
continue;
/* Trim trailing whitespace */
for (n = p->v.segm.end;
n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--);
@@ -1699,7 +1699,7 @@ wordsplit_tildexpand (struct wordsplit *wsp)
struct wordsplit_node *p;
char *uname = NULL;
size_t usize = 0;
for (p = wsp->ws_head; p; p = p->next)
{
const char *str;
@@ -1714,7 +1714,7 @@ wordsplit_tildexpand (struct wordsplit *wsp)
size_t slen = wsnode_len (p);
struct passwd *pw;
char *newstr;
for (i = 1; i < slen && str[i] != '/'; i++)
;
if (i == slen)
@@ -1788,7 +1788,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
if (wsp->ws_options & WRDSO_DOTGLOB)
flags = GLOB_PERIOD;
#endif
for (p = wsp->ws_head; p; p = next)
{
const char *str;
@@ -1807,23 +1807,23 @@ wordsplit_pathexpand (struct wordsplit *wsp)
glob_t g;
struct wordsplit_node *prev;
char *pattern;
pattern = malloc (slen + 1);
if (!pattern)
return _wsplt_nomem (wsp);
memcpy (pattern, str, slen);
pattern[slen] = 0;
switch (glob (pattern, flags, NULL, &g))
{
case 0:
free (pattern);
break;
case GLOB_NOSPACE:
free (pattern);
return _wsplt_nomem (wsp);
case GLOB_NOMATCH:
if (wsp->ws_options & WRDSO_NULLGLOB)
{
@@ -1846,7 +1846,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
}
free (pattern);
continue;
default:
free (pattern);
return _wsplt_seterr (wsp, WRDSE_GLOBERR);
@@ -1855,10 +1855,10 @@ wordsplit_pathexpand (struct wordsplit *wsp)
prev = p;
for (i = 0; i < g.gl_pathc; i++)
{
struct wordsplit_node *newnode = wsnode_new (wsp);
struct wordsplit_node *newnode;
char *newstr;
if (!newnode)
if (wsnode_new (wsp, &newnode))
return 1;
newstr = strdup (g.gl_pathv[i]);
if (!newstr)
@@ -1915,19 +1915,19 @@ skip_sed_expr (const char *command, size_t i, size_t len)
/* wsp->ws_endp points to a delimiter character. If RETURN_DELIMS
is true, return its value, otherwise return the index past it. */
static size_t
static inline size_t
skip_delim_internal (struct wordsplit *wsp, int return_delims)
{
return return_delims ? wsp->ws_endp : wsp->ws_endp + 1;
}
static size_t
static inline size_t
skip_delim (struct wordsplit *wsp)
{
return skip_delim_internal (wsp, WSP_RETURN_DELIMS (wsp));
}
static size_t
static inline size_t
skip_delim_real (struct wordsplit *wsp)
{
return skip_delim_internal (wsp, wsp->ws_flags & WRDSF_RETURN_DELIMS);
@@ -1975,7 +1975,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
int join = 0;
unsigned flags = 0;
struct wordsplit_node *np = wsp->ws_tail;
size_t i = start;
if (i >= len)
@@ -2064,7 +2064,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
wsp->ws_endp = i;
if (wsp->ws_flags & WRDSF_INCREMENTAL)
return _WRDS_EOF;
if (consume_all)
{
if (!np)
@@ -2075,7 +2075,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
np = np->next;
}
}
return _WRDS_OK;
}
@@ -2320,8 +2320,8 @@ static struct exptab exptab[] = {
{ NULL }
};
static int
exptab_matches (struct exptab *p, struct wordsplit *wsp)
static inline int
exptab_matches(struct exptab *p, struct wordsplit *wsp)
{
int result;
@@ -2342,7 +2342,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
if (wsp->ws_flags & WRDSF_SHOWDBG)
wsp->ws_debug (_("(%02d) Input:%.*s;"),
wsp->ws_lvl, (int) wsp->ws_len, wsp->ws_input);
if ((wsp->ws_flags & WRDSF_NOSPLIT)
|| ((wsp->ws_options & WRDSO_MAXWORDS)
&& wsp->ws_wordi + 1 == wsp->ws_maxwords))
@@ -2438,7 +2438,7 @@ wordsplit_run (const char *command, size_t length, struct wordsplit *wsp,
}
int
wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
unsigned flags)
{
return wordsplit_run (command, length, wsp, flags, 0);
@@ -2559,3 +2559,4 @@ wordsplit_perror (struct wordsplit *wsp)
wsp->ws_error ("%s", wordsplit_strerror (wsp));
}
}

View File

@@ -18,7 +18,12 @@
#define __WORDSPLIT_H
#include <stddef.h>
#include <attribute.h>
#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;
@@ -31,16 +36,16 @@ typedef struct wordsplit wordsplit_t;
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
struct wordsplit
{
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 accommodate. */
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. */
@@ -57,11 +62,11 @@ struct wordsplit
/* [Input] (WRDSF_ALLOC_DIE) Function called when
out of memory. Must not return. */
void (*ws_error) (const char *, ...)
ATTRIBUTE_FORMAT ((printf, 1, 2));
__attribute__ ((__format__ (__printf__, 1, 2)));
/* [Input] (WRDSF_ERROR) Function used for error
reporting */
void (*ws_debug) (const char *, ...)
ATTRIBUTE_FORMAT ((printf, 1, 2));
__attribute__ ((__format__ (__printf__, 1, 2)));
/* [Input] (WRDSF_DEBUG) Function used for debug
output. */
const char **ws_env; /* [Input] (WRDSF_ENV, !WRDSF_NOVAR) Array of
@@ -70,7 +75,7 @@ struct wordsplit
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
@@ -95,8 +100,8 @@ struct wordsplit
See ws_getvar for a discussion of possible
return values. */
const char *ws_input; /* Input string (the S argument to wordsplit. */
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. */
@@ -216,9 +221,9 @@ struct wordsplit
/* 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
#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
@@ -248,6 +253,15 @@ 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);

View File

@@ -1,7 +1,7 @@
/* openat-style fd-relative functions for operating with extended file
attributes.
Copyright 2012-2023 Free Software Foundation, Inc.
Copyright 2012-2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,7 +1,7 @@
/* Prototypes for openat-style fd-relative functions for operating with
extended file attributes.
Copyright 2012-2023 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
@@ -26,7 +26,6 @@
# include <attr/xattr.h>
#endif
#include <errno.h>
#ifndef ENOATTR
# define ENOATTR ENODATA /* No such attribute */
#endif
@@ -63,7 +62,7 @@ ssize_t getxattrat (int dir_fd, const char *path, const char *name,
ssize_t lgetxattrat (int dir_fd, const char *path, const char *name,
void *value, size_t size);
/* dir-fd-relative listxattr. Obtain the list of extended attributes names. For
/* dir-fd-relative listxattr. Obtain the list of extended attrubtes names. For
more info see the listxattr(2) manpage. */
ssize_t listxattrat (int dir_fd, const char *path, char *list, size_t size);

22
po/.gitignore vendored
View File

@@ -1,23 +1,25 @@
/Makefile.in.in
/Makevars.template
/Rules-quot
/boldquot.sed
/en@boldquot.header
/en@quot.header
/insert-header.sin
/quot.sed
/remove-potcdate.sed
/remove-potcdate.sin
/Makevars.template~
/Makefile.in.in~
*.gmo
*.mo
*.po
*~
.reference
LINGUAS
Makefile
Makefile.in
Makefile.in.in
Makevars
Makevars.template
POTFILES
Rules-quot
boldquot.sed
en@boldquot.header
en@quot.header
insert-header.sed
insert-header.sin
quot.sed
remove-potcdate.sed
remove-potcdate.sin
stamp-po
tar.pot

View File

@@ -1,6 +1,6 @@
# List of files which contain translatable strings.
# Copyright 1996-2023 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-2023 Free Software Foundation, Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -11,12 +11,12 @@ TAR=/bin/tar
# (Optional) Path to rsh binary or its equivalent. You may wish to
# set it to ssh as shown in the example below, to improve security.
# In this case you will have to use public key authentication.
RSH=/usr/bin/ssh
RSH=/usr/local/bin/ssh
# (Optional) Path to rsh binary on remote machines. This will be
# (Optional) Path to rsh binary on remote mashines. This will be
# passed via --rsh-command option to the remote invocation of
# tar
RSH_COMMAND=/usr/bin/ssh
RSH_COMMAND=/usr/local/bin/ssh
# Name of temporary file to hold volume numbers. This needs to be accessible
# by all the machines which have filesystems to be dumped.
@@ -43,7 +43,7 @@ BACKUP_DIRS='remote1:/etc remote1:/var/spool/crontab'
# DIRLIST=/etc/my-backup/dirlist
# List of individual files to be dumped.
# These should be accessible from the machine on which the dump is run.
# These should be accesible from the machine on which the dump is run.
BACKUP_FILES=''
# This list may also be kept in file $SYSCONFDIR/backup/files, the
# format of which is the same as described above. The location of
@@ -82,7 +82,7 @@ SLEEP_MESSAGE="`awk '
}' /dev/null`"
# Copyright 2004-2023 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-2023 Free Software Foundation, Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

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-2023 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-2023 Free Software Foundation, Inc.
# Copyright 2004-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -183,7 +183,7 @@ restore_files()
done
}
# Operation Overview:
# Operation Overwiew:
#
# 1. Determine the time of the last backup
# 2. Create list of incremental listings to process

View File

@@ -1,6 +1,6 @@
#! /usr/bin/perl -w
# Display and edit the 'dev' field in tar's snapshots
# Copyright 2007-2023 Free Software Foundation, Inc.
# Copyright 2007-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

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-2023 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-2023 Free Software Foundation, Inc.
Copyright 2006-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
# Makefile for GNU tar sources.
# Copyright 1994-2023 Free Software Foundation, Inc.
# Copyright 1994-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -49,7 +49,6 @@ tar_SOURCES = \
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
tar_LDADD = $(LIBS) ../lib/libtar.a ../gnu/libgnu.a\
$(LIB_ACL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)\
$(LIB_GETRANDOM) $(LIB_HARD_LOCALE) $(FILE_HAS_ACL_LIB) $(LIB_MBRTOWC)\
$(LIB_SELINUX) $(LIB_SETLOCALE_NULL)
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)

View File

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

View File

@@ -1,6 +1,6 @@
/* Buffer management for tar.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -20,6 +20,7 @@
Written by John Gilmore, on 1985-08-25. */
#include <system.h>
#include <system-ioctl.h>
#include <signal.h>
@@ -27,16 +28,10 @@
#include <fnmatch.h>
#include <human.h>
#include <quotearg.h>
#include <verify.h>
#include "common.h"
#include <rmt.h>
/* Work around GCC bug 109856. */
# if 13 <= __GNUC__
# pragma GCC diagnostic ignored "-Wnull-dereference"
# endif
/* Number of retries before giving up on read. */
#define READ_ERROR_MAX 10
@@ -313,7 +308,6 @@ static struct zip_magic const magic[] = {
{ ct_bzip2, 3, "BZh" },
{ ct_lzip, 4, "LZIP" },
{ ct_lzma, 6, "\xFFLZMA" },
{ ct_lzma, 3, "\x5d\x00\x00" },
{ ct_lzop, 4, "\211LZO" },
{ ct_xz, 6, "\xFD" "7zXZ" },
{ ct_zstd, 4, "\x28\xB5\x2F\xFD" },
@@ -333,15 +327,15 @@ static struct zip_program zip_program[] = {
{ ct_lzop, LZOP_PROGRAM, "--lzop" },
{ ct_xz, XZ_PROGRAM, "-J" },
{ ct_zstd, ZSTD_PROGRAM, "--zstd" },
{ ct_none }
};
enum { n_zip_programs = sizeof zip_program / sizeof *zip_program };
static struct zip_program const *
find_zip_program (enum compress_type type, int *pstate)
{
int i;
for (i = *pstate; i < n_zip_programs; i++)
for (i = *pstate; zip_program[i].type != ct_none; i++)
{
if (zip_program[i].type == type)
{
@@ -358,8 +352,6 @@ first_decompress_program (int *pstate)
{
struct zip_program const *zp;
*pstate = n_zip_programs;
if (use_compress_program_option)
return use_compress_program_option;
@@ -376,6 +368,8 @@ next_decompress_program (int *pstate)
{
struct zip_program const *zp;
if (use_compress_program_option)
return NULL;
zp = find_zip_program (archive_compression_type, pstate);
return zp ? zp->program : NULL;
}
@@ -426,6 +420,37 @@ check_compressed_archive (bool *pshort)
return ct_none;
}
/* Guess if the archive is seekable. */
static void
guess_seekable_archive (void)
{
struct stat st;
if (subcommand_option == DELETE_SUBCOMMAND)
{
/* The current code in delete.c is based on the assumption that
skip_member() reads all data from the archive. So, we should
make sure it won't use seeks. On the other hand, the same code
depends on the ability to backspace a record in the archive,
so setting seekable_archive to false is technically incorrect.
However, it is tested only in skip_member(), so it's not a
problem. */
seekable_archive = false;
}
if (seek_option != -1)
{
seekable_archive = !!seek_option;
return;
}
if (!multi_volume_option && !use_compress_program_option
&& fstat (archive, &st) == 0)
seekable_archive = S_ISREG (st.st_mode);
else
seekable_archive = false;
}
/* Open an archive named archive_name_array[0]. Detect if it is
a compressed archive of known type and use corresponding decompression
program if so */
@@ -677,41 +702,12 @@ check_tty (enum access_mode mode)
}
}
/* Fetch the status of the archive, accessed via WANTED_STATUS. */
static void
get_archive_status (enum access_mode wanted_access, bool backed_up_flag)
{
if (!sys_get_archive_stat ())
{
int saved_errno = errno;
if (backed_up_flag)
undo_last_backup ();
errno = saved_errno;
open_fatal (archive_name_array[0]);
}
seekable_archive
= (! (multi_volume_option || use_compress_program_option)
&& (seek_option < 0
? (_isrmt (archive)
|| S_ISREG (archive_stat.st_mode)
|| S_ISBLK (archive_stat.st_mode))
: seek_option));
if (wanted_access != ACCESS_READ)
sys_detect_dev_null_output ();
SET_BINARY_MODE (archive);
}
/* Open an archive file. The argument specifies whether we are
reading or writing, or both. */
static void
_open_archive (enum access_mode wanted_access)
{
bool backed_up_flag = false;
int backed_up_flag = 0;
if (record_size == 0)
FATAL_ERROR ((0, 0, _("Invalid value for record_size")));
@@ -800,13 +796,15 @@ _open_archive (enum access_mode wanted_access)
{
case ACCESS_READ:
archive = open_compressed_archive ();
if (archive >= 0)
guess_seekable_archive ();
break;
case ACCESS_WRITE:
if (backup_option)
{
maybe_backup_file (archive_name_array[0], 1);
backed_up_flag = true;
backed_up_flag = 1;
}
if (verify_option)
archive = rmtopen (archive_name_array[0], O_RDWR | O_CREAT | O_BINARY,
@@ -834,7 +832,20 @@ _open_archive (enum access_mode wanted_access)
break;
}
get_archive_status (wanted_access, backed_up_flag);
if (archive < 0
|| (! _isrmt (archive) && !sys_get_archive_stat ()))
{
int saved_errno = errno;
if (backed_up_flag)
undo_last_backup ();
errno = saved_errno;
open_fatal (archive_name_array[0]);
}
sys_detect_dev_null_output ();
sys_save_archive_dev_ino ();
SET_BINARY_MODE (archive);
switch (wanted_access)
{
@@ -987,8 +998,7 @@ short_read (size_t status)
}
record_end = record_start + (record_size - left) / BLOCKSIZE;
if (left == 0)
records_read++;
records_read++;
}
/* Flush the current buffer to/from the archive. */
@@ -1038,8 +1048,18 @@ flush_archive (void)
static void
backspace_output (void)
{
if (mtioseek (false, -1))
return;
#ifdef MTIOCTOP
{
struct mtop operation;
operation.mt_op = MTBSR;
operation.mt_count = 1;
if (rmtioctl (archive, MTIOCTOP, (char *) &operation) >= 0)
return;
if (errno == EIO && rmtioctl (archive, MTIOCTOP, (char *) &operation) >= 0)
return;
}
#endif
{
off_t position = rmtlseek (archive, (off_t) 0, SEEK_CUR);
@@ -1305,8 +1325,8 @@ new_volume (enum access_mode mode)
if (verify_option)
verify_volume ();
assign_null (&volume_label);
assign_null (&continued_file_name);
assign_string (&volume_label, NULL);
assign_string (&continued_file_name, NULL);
continued_file_size = continued_file_offset = 0;
current_block = record_start;
@@ -1352,6 +1372,7 @@ new_volume (enum access_mode mode)
case ACCESS_READ:
archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,
rsh_command_option);
guess_seekable_archive ();
break;
case ACCESS_WRITE:
@@ -1376,7 +1397,7 @@ new_volume (enum access_mode mode)
goto tryagain;
}
get_archive_status (mode, false);
SET_BINARY_MODE (archive);
return true;
}
@@ -1484,7 +1505,7 @@ try_new_volume (void)
ASSIGN_STRING_N (&volume_label, current_header->header.name);
set_next_block_after (header);
header = find_next_block ();
if (! (header && header->header.typeflag == GNUTYPE_MULTIVOL))
if (header->header.typeflag != GNUTYPE_MULTIVOL)
break;
FALLTHROUGH;
case GNUTYPE_MULTIVOL:
@@ -1667,7 +1688,6 @@ _write_volume_label (const char *str)
{
union block *label = find_next_block ();
assume (label);
memset (label, 0, BLOCKSIZE);
strcpy (label->header.name, str);
@@ -1828,7 +1848,7 @@ simple_flush_read (void)
/* Simple flush write (no multi-volume or label extensions) */
static void
simple_flush_write (MAYBE_UNUSED size_t level)
simple_flush_write (size_t level __attribute__((unused)))
{
ssize_t status;

View File

@@ -1,6 +1,6 @@
/* Checkpoint management for tar.
Copyright 2007-2023 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -84,7 +84,7 @@ copy_string_unquote (const char *str)
char *output = xstrdup (str);
size_t len = strlen (output);
if ((*output == '"' || *output == '\'')
&& len > 1 && output[len-1] == *output)
&& output[len-1] == *output)
{
memmove (output, output+1, len-2);
output[len-2] = 0;

View File

@@ -1,6 +1,6 @@
/* Common declarations for the tar program.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -43,22 +43,24 @@
# 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
#include "arith.h"
#include <attribute.h>
#include <backupfile.h>
#include <exclude.h>
#include <full-write.h>
#include <idx.h>
#include <inttostr.h>
#include <modechange.h>
#include <quote.h>
#include <safe-read.h>
#include <full-read.h>
#include <stat-time.h>
#include <timespec.h>
#define obstack_chunk_alloc xmalloc
@@ -377,7 +379,6 @@ struct name
char *name; /* File name or globbing pattern */
size_t length; /* cached strlen (name) */
int matching_flags; /* wildcard flags if name is a pattern */
bool is_wildcard; /* true if this is a wildcard pattern */
bool cmdline; /* true if this name was given in the
command line */
@@ -396,8 +397,9 @@ struct name
char *caname; /* canonical name */
};
/* Status of archive file, or all zeros if remote. */
GLOBAL struct stat archive_stat;
/* Obnoxious test to see if dimwit is trying to dump the archive. */
GLOBAL dev_t ar_dev;
GLOBAL ino_t ar_ino;
/* Flags for reading, searching, and fstatatting files. */
GLOBAL int open_read_flags;
@@ -405,9 +407,6 @@ GLOBAL int open_searchdir_flags;
GLOBAL int fstatat_flags;
GLOBAL int seek_option;
/* true if archive if lseek should be used on the archive, 0 if it
should not be used. */
GLOBAL bool seekable_archive;
GLOBAL dev_t root_device;
@@ -470,7 +469,7 @@ void reset_eof (void);
void set_next_block_after (union block *block);
void clear_read_error_count (void);
void xclose (int fd);
_Noreturn void archive_write_error (ssize_t status);
void archive_write_error (ssize_t status) __attribute__ ((noreturn));
void archive_read_error (void);
off_t seek_archive (off_t size);
void set_start_time (void);
@@ -505,8 +504,7 @@ enum dump_status
void add_exclusion_tag (const char *name, enum exclusion_tag_type type,
bool (*predicate) (int));
bool cachedir_file_p (int fd);
char *get_directory_entries (struct tar_stat_info *st)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
char *get_directory_entries (struct tar_stat_info *st);
void create_archive (void);
void pad_archive (off_t size_left);
@@ -618,7 +616,7 @@ uintmax_t uintmax_from_header (const char *buf, size_t size);
void list_archive (void);
void test_archive_label (void);
void print_for_mkdir (char *dirname, mode_t mode);
void print_for_mkdir (char *dirname, int length, mode_t mode);
void print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal);
void read_and (void (*do_something) (void));
@@ -626,9 +624,8 @@ enum read_header read_header (union block **return_block,
struct tar_stat_info *info,
enum read_header_mode m);
enum read_header tar_checksum (union block *header, bool silent);
void skim_file (off_t size, bool must_copy);
void skip_file (off_t size);
void skip_member (void);
void skim_member (bool must_copy);
/* Module misc.c. */
@@ -636,10 +633,7 @@ void skim_member (bool must_copy);
#define max(a, b) ((a) < (b) ? (b) : (a))
char const *quote_n_colon (int n, char const *arg);
void assign_string_or_null (char **dest, const char *src)
ATTRIBUTE_NONNULL ((1));
void assign_string (char **dest, const char *src) ATTRIBUTE_NONNULL ((1, 2));
void assign_null (char **dest) ATTRIBUTE_NONNULL ((1));
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);
@@ -676,18 +670,15 @@ represent_uintmax (uintmax_t n)
}
}
#define STRINGIFY_BIGINT(i, b) umaxtostr (i, b)
enum { UINTMAX_STRSIZE_BOUND = INT_BUFSIZE_BOUND (intmax_t) };
enum { SYSINT_BUFSIZE =
max (UINTMAX_STRSIZE_BOUND, INT_BUFSIZE_BOUND (intmax_t)) };
char *sysinttostr (uintmax_t, intmax_t, uintmax_t, char buf[SYSINT_BUFSIZE]);
intmax_t strtosysint (char const *, char **, intmax_t, uintmax_t);
void code_ns_fraction (int ns, char *p);
char const *code_timespec (struct timespec ts, char *sbuf);
enum { BILLION = 1000000000, LOG10_BILLION = 9 };
enum { TIMESPEC_STRSIZE_BOUND =
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
char const *code_timespec (struct timespec ts,
char sbuf[TIMESPEC_STRSIZE_BOUND]);
struct timespec decode_timespec (char const *, char **, bool);
/* Return true if T does not represent an out-of-range or invalid value. */
@@ -738,8 +729,9 @@ void stat_diag (char const *name);
void file_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name));
void write_error_details (char const *name, size_t status, size_t size);
_Noreturn void write_fatal (char const *name);
_Noreturn void write_fatal_details (char const *name, ssize_t status, size_t size);
void write_fatal (char const *name) __attribute__ ((noreturn));
void write_fatal_details (char const *name, ssize_t status, size_t size)
__attribute__ ((noreturn));
pid_t xfork (void);
void xpipe (int fd[2]);
@@ -759,7 +751,7 @@ enum files_count
extern enum files_count filename_args;
/* Return true if there are file names in the list */
COMMON_INLINE bool
static inline bool
name_more_files (void)
{
return filename_args != FILES_NONE;
@@ -773,6 +765,7 @@ void uid_to_uname (uid_t uid, char **uname);
int uname_to_uid (char const *uname, uid_t *puid);
void name_init (void);
bool name_more_files (void);
void name_add_name (const char *name);
void name_term (void);
const char *name_next (int change_dirs);
@@ -785,7 +778,7 @@ bool name_match (const char *name);
void names_notfound (void);
void label_notfound (void);
void collect_and_sort_names (void);
struct name *name_scan (const char *name, bool exact);
struct name *name_scan (const char *name);
struct name const *name_from_list (void);
void blank_name_list (void);
char *make_file_name (const char *dir_name, const char *name);
@@ -806,14 +799,14 @@ bool contains_dot_dot (char const *name);
/* Module tar.c. */
_Noreturn void usage (int);
void usage (int);
int confirm (const char *message_action, const char *name);
void tar_stat_init (struct tar_stat_info *st);
bool tar_stat_close (struct tar_stat_info *st);
void tar_stat_destroy (struct tar_stat_info *st);
_Noreturn void usage (int);
void usage (int) __attribute__ ((noreturn));
int tar_timespec_cmp (struct timespec a, struct timespec b);
const char *archive_format_string (enum archive_format fmt);
const char *subcommand_string (enum subcommand c);
@@ -892,19 +885,16 @@ bool xheader_keyword_deleted_p (const char *kw);
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
size_t n);
void xheader_xattr_init (struct tar_stat_info *st);
void xheader_xattr_free (struct xattr_array *vals, size_t sz);
void xheader_xattr_copy (const struct tar_stat_info *st,
struct xattr_array **vals, size_t *sz);
void xheader_xattr_add (struct tar_stat_info *st,
const char *key, const char *val, size_t len);
void xattr_map_init (struct xattr_map *map);
void xattr_map_copy (struct xattr_map *dst,
const struct xattr_map *src);
void xattr_map_add (struct xattr_map *map,
const char *key, const char *val, size_t len);
void xattr_map_free (struct xattr_map *xattr_map);
/* Module system.c */
void sys_detect_dev_null_output (void);
void sys_save_archive_dev_ino (void);
void sys_wait_for_child (pid_t, bool);
void sys_spawn_shell (void);
bool sys_compare_uid (struct stat *a, struct stat *b);
@@ -922,11 +912,10 @@ int sys_exec_info_script (const char **archive_name, int volume_number);
void sys_exec_checkpoint_script (const char *script_name,
const char *archive_name,
int checkpoint_number);
bool mtioseek (bool count_files, off_t count);
/* Module compare.c */
void report_difference (struct tar_stat_info *st, const char *message, ...)
ATTRIBUTE_FORMAT ((printf, 2, 3));
__attribute__ ((format (printf, 2, 3)));
/* Module sparse.c */
bool sparse_member_p (struct tar_stat_info *st);
@@ -934,7 +923,7 @@ bool sparse_fixup_header (struct tar_stat_info *st);
enum dump_status sparse_dump_file (int, struct tar_stat_info *st);
enum dump_status sparse_extract_file (int fd, struct tar_stat_info *st,
off_t *size);
enum dump_status sparse_skim_file (struct tar_stat_info *st, bool must_copy);
enum dump_status sparse_skip_file (struct tar_stat_info *st);
bool sparse_diff_file (int, struct tar_stat_info *st);
/* Module utf8.c */
@@ -989,13 +978,12 @@ void checkpoint_flush_actions (void);
#define WARN_XATTR_WRITE 0x00200000
#define WARN_RECORD_SIZE 0x00400000
#define WARN_FAILED_READ 0x00800000
#define WARN_MISSING_ZERO_BLOCKS 0x01000000
/* These warnings are enabled by default in verbose mode: */
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
WARN_DECOMPRESS_PROGRAM|WARN_EXISTING_FILE|\
WARN_RECORD_SIZE)
#define WARN_ALL 0xffffffff
#define WARN_ALL (~WARN_VERBOSE_WARNINGS)
void set_warning_option (const char *arg);

View File

@@ -1,6 +1,6 @@
/* Diff files from a tar archive.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -73,7 +73,8 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
/* Take a buffer returned by read_and_process and do nothing with it. */
static int
process_noop (MAYBE_UNUSED size_t size, MAYBE_UNUSED char *data)
process_noop (size_t size __attribute__ ((unused)),
char *data __attribute__ ((unused)))
{
return 1;
}
@@ -565,12 +566,31 @@ verify_volume (void)
ioctl (archive, FDFLUSH);
#endif
if (!mtioseek (true, -1) && rmtlseek (archive, 0, SEEK_SET) != 0)
{
/* Lseek failed. Try a different method. */
seek_warn (archive_name_array[0]);
return;
}
#ifdef MTIOCTOP
{
struct mtop operation;
int status;
operation.mt_op = MTBSF;
operation.mt_count = 1;
if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation), status < 0)
{
if (errno != EIO
|| (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
status < 0))
{
#endif
if (rmtlseek (archive, (off_t) 0, SEEK_SET) != 0)
{
/* Lseek failed. Try a different method. */
seek_warn (archive_name_array[0]);
return;
}
#ifdef MTIOCTOP
}
}
}
#endif
access_mode = ACCESS_READ;
now_verifying = 1;

View File

@@ -1,6 +1,6 @@
/* Create a tar archive.
Copyright 1985-2023 Free Software Foundation, Inc.
Copyright 1985-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -22,7 +22,6 @@
#include <system.h>
#include <areadlink.h>
#include <flexmember.h>
#include <quotearg.h>
#include "common.h"
@@ -37,7 +36,7 @@ struct link
dev_t dev;
ino_t ino;
nlink_t nlink;
char name[FLEXIBLE_ARRAY_MEMBER];
char name[1];
};
struct exclusion_tag
@@ -175,13 +174,13 @@ tar_name_copy_str (char *dst, const char *src, size_t len)
}
/* Convert NEGATIVE VALUE to a base-256 representation suitable for
tar headers. NEGATIVE is true iff VALUE was negative before being
cast to uintmax_t. Output to buffer WHERE with size SIZE.
tar headers. NEGATIVE is 1 if VALUE was negative before being cast
to uintmax_t, 0 otherwise. Output to buffer WHERE with size SIZE.
The result is undefined if SIZE is 0 or if VALUE is too large to
fit. */
static void
to_base256 (bool negative, uintmax_t value, char *where, size_t size)
to_base256 (int negative, uintmax_t value, char *where, size_t size)
{
uintmax_t v = value;
uintmax_t propagated_sign_bits =
@@ -206,13 +205,13 @@ to_base256 (bool negative, uintmax_t value, char *where, size_t size)
#define GNAME_TO_CHARS(name, buf) string_to_chars (name, buf, sizeof (buf))
static bool
to_chars (bool negative, uintmax_t value, size_t valsize,
uintmax_t (*substitute) (bool *),
to_chars (int negative, uintmax_t value, size_t valsize,
uintmax_t (*substitute) (int *),
char *where, size_t size, const char *type);
static bool
to_chars_subst (bool negative, bool gnu_format, uintmax_t value, size_t valsize,
uintmax_t (*substitute) (bool *),
to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
uintmax_t (*substitute) (int *),
char *where, size_t size, const char *type)
{
uintmax_t maxval = (gnu_format
@@ -246,7 +245,7 @@ to_chars_subst (bool negative, bool gnu_format, uintmax_t value, size_t valsize,
if (substitute)
{
bool negsub;
int negsub;
uintmax_t sub = substitute (&negsub) & maxval;
/* NOTE: This is one of the few places where GNU_FORMAT differs from
OLDGNU_FORMAT. The actual differences are:
@@ -273,25 +272,25 @@ to_chars_subst (bool negative, bool gnu_format, uintmax_t value, size_t valsize,
/* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
external form, using SUBSTITUTE (...) if VALUE won't fit. Output
to buffer WHERE with size SIZE. NEGATIVE is true iff VALUE was
to buffer WHERE with size SIZE. NEGATIVE is 1 iff VALUE was
negative before being cast to uintmax_t; its original bitpattern
can be deduced from VALSIZE, its original size before casting.
TYPE is the kind of value being output (useful for diagnostics).
Prefer the POSIX format of SIZE - 1 octal digits (with leading zero
digits), followed by '\0'. If this won't work, and if GNU or
OLDGNU format is allowed, use '\200' followed by base-256, or (if
NEGATIVE) '\377' followed by two's complement base-256.
NEGATIVE is nonzero) '\377' followed by two's complement base-256.
If neither format works, use SUBSTITUTE (...) instead. Pass to
SUBSTITUTE the address of an 0-or-1 flag recording whether the
substitute value is negative. */
static bool
to_chars (bool negative, uintmax_t value, size_t valsize,
uintmax_t (*substitute) (bool *),
to_chars (int negative, uintmax_t value, size_t valsize,
uintmax_t (*substitute) (int *),
char *where, size_t size, const char *type)
{
bool gnu_format = (archive_format == GNU_FORMAT
|| archive_format == OLDGNU_FORMAT);
int gnu_format = (archive_format == GNU_FORMAT
|| archive_format == OLDGNU_FORMAT);
/* Generate the POSIX octal representation if the number fits. */
if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
@@ -309,7 +308,7 @@ to_chars (bool negative, uintmax_t value, size_t valsize,
if (((negative ? -1 - value : value)
<= MAX_VAL_WITH_DIGITS (size - 1, LG_256)))
{
where[0] = (char) (negative ? -1 : 1 << (LG_256 - 1));
where[0] = negative ? -1 : 1 << (LG_256 - 1);
to_base256 (negative, value, where + 1, size - 1);
return true;
}
@@ -322,10 +321,10 @@ to_chars (bool negative, uintmax_t value, size_t valsize,
But this is the traditional behavior. */
else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
{
static bool warned_once;
static int warned_once;
if (! warned_once)
{
warned_once = true;
warned_once = 1;
WARN ((0, 0, _("Generating negative octal headers")));
}
where[size - 1] = '\0';
@@ -343,7 +342,7 @@ to_chars (bool negative, uintmax_t value, size_t valsize,
}
static uintmax_t
gid_substitute (bool *negative)
gid_substitute (int *negative)
{
gid_t r;
#ifdef GID_NOBODY
@@ -384,7 +383,7 @@ mode_to_chars (mode_t v, char *p, size_t s)
propagate all unknown bits to the external mode.
This matches historical practice.
Otherwise, just copy the bits we know about. */
bool negative;
int negative;
uintmax_t u;
if (S_ISUID == TSUID && S_ISGID == TSGID && S_ISVTX == TSVTX
&& S_IRUSR == TUREAD && S_IWUSR == TUWRITE && S_IXUSR == TUEXEC
@@ -399,7 +398,7 @@ mode_to_chars (mode_t v, char *p, size_t s)
}
else
{
negative = false;
negative = 0;
u = ((v & S_ISUID ? TSUID : 0)
| (v & S_ISGID ? TSGID : 0)
| (v & S_ISVTX ? TSVTX : 0)
@@ -429,7 +428,7 @@ time_to_chars (time_t v, char *p, size_t s)
}
static uintmax_t
uid_substitute (bool *negative)
uid_substitute (int *negative)
{
uid_t r;
#ifdef UID_NOBODY
@@ -453,7 +452,7 @@ uid_to_chars (uid_t v, char *p, size_t s)
static bool
uintmax_to_chars (uintmax_t v, char *p, size_t s)
{
return to_chars (false, v, sizeof v, 0, p, s, "uintmax_t");
return to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
}
static void
@@ -882,6 +881,12 @@ start_header (struct tar_stat_info *st)
if (!MINOR_TO_CHARS (devminor, header->header.devminor))
return NULL;
}
else if (archive_format != GNU_FORMAT && archive_format != OLDGNU_FORMAT)
{
if (!(MAJOR_TO_CHARS (0, header->header.devmajor)
&& MINOR_TO_CHARS (0, header->header.devminor)))
return NULL;
}
if (archive_format == POSIX_FORMAT)
{
@@ -961,9 +966,14 @@ start_header (struct tar_stat_info *st)
xheader_store ("RHT.security.selinux", st, NULL);
if (xattrs_option > 0)
{
size_t i;
for (i = 0; i < st->xattr_map.xm_size; i++)
xheader_store (st->xattr_map.xm_map[i].xkey, st, &i);
size_t scan_xattr = 0;
struct xattr_array *xattr_map = st->xattr_map;
while (scan_xattr < st->xattr_map_size)
{
xheader_store (xattr_map[scan_xattr].xkey, st, &scan_xattr);
++scan_xattr;
}
}
}
@@ -1519,7 +1529,8 @@ file_count_links (struct tar_stat_info *st)
absolute_names_option));
transform_name (&linkname, XFORM_LINK);
lp = xmalloc (FLEXNSIZEOF (struct link, name, strlen (linkname) + 1));
lp = xmalloc (offsetof (struct link, name)
+ strlen (linkname) + 1);
lp->ino = st->stat.st_ino;
lp->dev = st->stat.st_dev;
lp->nlink = st->stat.st_nlink;
@@ -1639,6 +1650,8 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
{
union block *header;
char type;
off_t original_size;
struct timespec original_ctime;
off_t block_ordinal = -1;
int fd = 0;
bool is_dir;
@@ -1681,11 +1694,10 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
return;
}
struct stat st1 = st->stat;
st->archive_file_size = st->stat.st_size;
st->archive_file_size = original_size = st->stat.st_size;
st->atime = get_stat_atime (&st->stat);
st->mtime = get_stat_mtime (&st->stat);
st->ctime = get_stat_ctime (&st->stat);
st->ctime = original_ctime = get_stat_ctime (&st->stat);
#ifdef S_ISHIDDEN
if (S_ISHIDDEN (st->stat.st_mode))
@@ -1722,7 +1734,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
if (sys_file_is_archive (st))
{
WARNOPT (WARN_IGNORE_ARCHIVE,
(0, 0, _("%s: archive cannot contain itself; not dumped"),
(0, 0, _("%s: file is the archive; not dumped"),
quotearg_colon (p)));
return;
}
@@ -1735,9 +1747,9 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
if (is_dir || S_ISREG (st->stat.st_mode) || S_ISCTG (st->stat.st_mode))
{
bool ok;
struct stat st2;
struct stat final_stat;
xattrs_acls_get (parentfd, name, st, !is_dir);
xattrs_acls_get (parentfd, name, st, 0, !is_dir);
xattrs_selinux_get (parentfd, name, st, fd);
xattrs_xattrs_get (parentfd, name, st, fd);
@@ -1803,54 +1815,31 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
errno = - parentfd;
ok = false;
}
else
ok = fstatat (parentfd, name, &final_stat, fstatat_flags) == 0;
}
else
ok = fstat (fd, &st2) == 0;
ok = fstat (fd, &final_stat) == 0;
if (! ok)
file_removed_diag (p, top_level, stat_diag);
}
if (ok && fd)
if (ok)
{
/* Heuristically check whether the file is the same in all
attributes that tar cares about and can easily check.
Although the check is not perfect since it does not
consult file contents, it is typically good enough.
Do not check atime which is saved only to replace it later.
Do not check ctime where changes might be benign (e.g.,
another process creates a hard link to the file). */
/* If the file's user ID, group ID or mode changed, tar may
have output the wrong info for the file. */
ok &= st1.st_uid == st2.st_uid;
ok &= st1.st_gid == st2.st_gid;
ok &= st1.st_mode == st2.st_mode;
/* Likewise for the file's mtime, but skip this check if it
is a directory possibly updated by --remove-files. */
if (! (is_dir && remove_files_option))
ok &= ! timespec_cmp (get_stat_mtime (&st1),
get_stat_mtime (&st2));
/* Likewise for the file's size, but skip this check if it
is a directory as tar does not output directory sizes.
Although dump_regular_file caught regular file shrinkage,
it shouldn't hurt to check for shrinkage again now;
plus, the file may have grown. */
if (!is_dir)
ok &= st1.st_size == st2.st_size;
if (!ok)
if ((timespec_cmp (get_stat_ctime (&final_stat), original_ctime) != 0
/* Original ctime will change if the file is a directory and
--remove-files is given */
&& !(remove_files_option && is_dir))
|| original_size < final_stat.st_size)
{
WARNOPT (WARN_FILE_CHANGED,
(0, 0, _("%s: file changed as we read it"),
quotearg_colon (p)));
if (! ignore_failed_read_option)
set_exit_status (TAREXIT_DIFFERS);
set_exit_status (TAREXIT_DIFFERS);
}
else if (atime_preserve_option == replace_atime_preserve
&& timespec_cmp (st->atime, get_stat_atime (&st2)) != 0
&& fd && (is_dir || original_size != 0)
&& set_file_atime (fd, parentfd, name, st->atime) != 0)
utime_error (p);
}
@@ -1900,21 +1889,21 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
else if (S_ISCHR (st->stat.st_mode))
{
type = CHRTYPE;
xattrs_acls_get (parentfd, name, st, true);
xattrs_acls_get (parentfd, name, st, 0, true);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
}
else if (S_ISBLK (st->stat.st_mode))
{
type = BLKTYPE;
xattrs_acls_get (parentfd, name, st, true);
xattrs_acls_get (parentfd, name, st, 0, true);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
}
else if (S_ISFIFO (st->stat.st_mode))
{
type = FIFOTYPE;
xattrs_acls_get (parentfd, name, st, true);
xattrs_acls_get (parentfd, name, st, 0, true);
xattrs_selinux_get (parentfd, name, st, 0);
xattrs_xattrs_get (parentfd, name, st, 0);
}
@@ -1948,6 +1937,15 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
if (!header)
return;
header->header.typeflag = type;
if (type != FIFOTYPE)
{
MAJOR_TO_CHARS (major (st->stat.st_rdev),
header->header.devmajor);
MINOR_TO_CHARS (minor (st->stat.st_rdev),
header->header.devminor);
}
finish_header (st, header, block_ordinal);
if (remove_files_option)
queue_deferred_unlink (p, false);

View File

@@ -1,6 +1,6 @@
/* Delete entries from a tar archive.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <system-ioctl.h>
#include "common.h"
#include <rmt.h>
@@ -49,31 +50,41 @@ move_archive (off_t count)
if (count == 0)
return;
if (mtioseek (false, count))
return;
#ifdef MTIOCTOP
{
struct mtop operation;
off_t position0 = rmtlseek (archive, 0, SEEK_CUR), position = 0;
if (0 <= position0)
{
/* Pretend the starting position is at the first record
boundary after POSITION0. This is useful at EOF after
a short read. */
idx_t short_size = position0 % record_size;
idx_t start_offset = short_size ? record_size - short_size : 0;
off_t increment, move_start;
if (INT_MULTIPLY_WRAPV (record_size, count, &increment)
|| INT_ADD_WRAPV (position0, start_offset, &move_start)
|| INT_ADD_WRAPV (move_start, increment, &position)
|| position < 0)
{
ERROR ((0, EOVERFLOW, "lseek: %s", archive_name_array[0]));
if (count < 0
? (operation.mt_op = MTBSR,
operation.mt_count = -count,
operation.mt_count == -count)
: (operation.mt_op = MTFSR,
operation.mt_count = count,
operation.mt_count == count))
{
if (0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
return;
}
else if (rmtlseek (archive, position, SEEK_SET) == position)
return;
}
if (!_isrmt (archive))
seek_error_details (archive_name_array[0], position);
if (errno == EIO
&& 0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
return;
}
}
#endif /* MTIOCTOP */
{
off_t position0 = rmtlseek (archive, (off_t) 0, SEEK_CUR);
off_t increment = record_size * (off_t) count;
off_t position = position0 + increment;
if (increment / count != record_size
|| (position < position0) != (increment < 0)
|| (position = position < 0 ? 0 : position,
rmtlseek (archive, position, SEEK_SET) != position))
seek_error_details (archive_name_array[0], position);
return;
}
}
/* Write out the record which has been filled. If MOVE_BACK_FLAG,
@@ -136,7 +147,7 @@ write_recent_bytes (char *data, size_t bytes)
write_record (1);
}
static void
static inline void
flush_file (void)
{
off_t blocks_to_skip;
@@ -149,9 +160,6 @@ flush_file (void)
{
blocks_to_skip -= (record_end - current_block);
flush_archive ();
if (record_end == current_block)
/* Hit EOF */
break;
}
current_block += blocks_to_skip;
}
@@ -184,15 +192,15 @@ delete_archive_members (void)
abort ();
case HEADER_SUCCESS:
if ((name = name_scan (current_stat_info.file_name, false)) == NULL)
if ((name = name_scan (current_stat_info.file_name)) == NULL)
{
skim_member (acting_as_filter);
skip_member ();
break;
}
name->found_count++;
if (!ISFOUND (name))
{
skim_member (acting_as_filter);
skip_member ();
break;
}
FALLTHROUGH;
@@ -279,7 +287,7 @@ delete_archive_members (void)
/* Found another header. */
xheader_decode (&current_stat_info);
if ((name = name_scan (current_stat_info.file_name, false)) != NULL)
if ((name = name_scan (current_stat_info.file_name)) != NULL)
{
name->found_count++;
if (ISFOUND (name))

View File

@@ -1,6 +1,6 @@
/* Per-directory exclusion files for tar.
Copyright 2014-2023 Free Software Foundation, Inc.
Copyright 2014-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -19,7 +19,6 @@
*/
#include <system.h>
#include <quotearg.h>
#include <flexmember.h>
#include <fnmatch.h>
#include <wordsplit.h>
#include "common.h"
@@ -41,7 +40,7 @@ struct excfile
{
struct excfile *next;
int flags;
char name[FLEXIBLE_ARRAY_MEMBER];
char name[1];
};
static struct excfile *excfile_head, *excfile_tail;
@@ -49,8 +48,7 @@ static struct excfile *excfile_head, *excfile_tail;
void
excfile_add (const char *name, int flags)
{
struct excfile *p = xmalloc (FLEXNSIZEOF (struct excfile, name,
strlen (name) + 1));
struct excfile *p = xmalloc (sizeof (*p) + strlen (name));
p->next = NULL;
p->flags = flags;
strcpy (p->name, name);
@@ -200,13 +198,11 @@ excluded_name (char const *name, struct tar_stat_info *st)
}
static void
cvs_addfn (struct exclude *ex, char const *pattern, int options,
MAYBE_UNUSED void *data)
cvs_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
struct wordsplit ws;
size_t i;
options |= EXCLUDE_ALLOC;
if (wordsplit (pattern, &ws,
WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS))
return;
@@ -216,8 +212,7 @@ cvs_addfn (struct exclude *ex, char const *pattern, int options,
}
static void
git_addfn (struct exclude *ex, char const *pattern, int options,
MAYBE_UNUSED void *data)
git_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
while (isspace (*pattern))
++pattern;
@@ -229,8 +224,7 @@ git_addfn (struct exclude *ex, char const *pattern, int options,
}
static void
bzr_addfn (struct exclude *ex, char const *pattern, int options,
MAYBE_UNUSED void *data)
bzr_addfn (struct exclude *ex, char const *pattern, int options, void *data)
{
while (isspace (*pattern))
++pattern;

View File

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

View File

@@ -1,6 +1,6 @@
/* Extract files from a tar archive.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -22,8 +22,6 @@
#include <system.h>
#include <quotearg.h>
#include <errno.h>
#include <flexmember.h>
#include <hash.h>
#include <priv-set.h>
#include <root-uid.h>
#include <utimens.h>
@@ -43,21 +41,6 @@ static mode_t current_umask; /* current umask (which is set to 0 if -p) */
# define fchown(fd, uid, gid) (errno = ENOSYS, -1)
#endif
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
|| defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
|| defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC \
|| (defined _WIN32 && ! defined __CYGWIN__))
# define HAVE_BIRTHTIME 1
#else
# define HAVE_BIRTHTIME 0
#endif
#if HAVE_BIRTHTIME
# define BIRTHTIME_EQ(a, b) (timespec_cmp (a, b) == 0)
#else
# define BIRTHTIME_EQ(a, b) true
#endif
/* Return true if an error number ERR means the system call is
supported in this case. */
static bool
@@ -122,7 +105,7 @@ struct delayed_set_stat
char *acls_d_ptr;
size_t acls_d_len;
size_t xattr_map_size;
struct xattr_map xattr_map;
struct xattr_array *xattr_map;
/* Length and contents of name. */
size_t file_name_len;
char *file_name;
@@ -130,11 +113,10 @@ struct delayed_set_stat
static struct delayed_set_stat *delayed_set_stat_head;
/* A link whose creation we have delayed. */
/* List of links whose creation we have delayed. */
struct delayed_link
{
/* The next in a list of delayed links that should be made after
this delayed link. */
/* The next delayed link in the list. */
struct delayed_link *next;
/* The device, inode number and birthtime of the placeholder.
@@ -145,9 +127,7 @@ struct delayed_link
when restoring hard-linked symlinks. */
dev_t dev;
ino_t ino;
#if HAVE_BIRTHTIME
struct timespec birthtime;
#endif
/* True if the link is symbolic. */
bool is_symlink;
@@ -175,45 +155,21 @@ struct delayed_link
char *acls_d_ptr;
size_t acls_d_len;
struct xattr_map xattr_map;
size_t xattr_map_size;
struct xattr_array *xattr_map;
/* The desired target of the desired link. */
char target[FLEXIBLE_ARRAY_MEMBER];
char target[1];
};
/* Table of delayed links hashed by device and inode; null if none. */
static Hash_table *delayed_link_table;
/* A list of the delayed links in tar file order,
and the tail of that list. */
static struct delayed_link *delayed_link_head;
static struct delayed_link **delayed_link_tail = &delayed_link_head;
struct string_list
{
struct string_list *next;
char string[FLEXIBLE_ARRAY_MEMBER];
char string[1];
};
static size_t
dl_hash (void const *entry, size_t table_size)
{
struct delayed_link const *dl = entry;
uintmax_t n = dl->dev;
int nshift = TYPE_WIDTH (n) - TYPE_WIDTH (dl->dev);
if (0 < nshift)
n <<= nshift;
n ^= dl->ino;
return n % table_size;
}
static bool
dl_compare (void const *a, void const *b)
{
struct delayed_link const *da = a, *db = b;
return (da->dev == db->dev) & (da->ino == db->ino);
}
/* Set up to extract files. */
void
extr_init (void)
@@ -500,7 +456,7 @@ mark_after_links (struct delayed_set_stat *head)
members. To help cope with this case the variable
delay_directory_restore_option is set by prepare_to_extract.
If an archive was explicitly created so that its member order is
If an archive was explicitely created so that its member order is
reversed, some directory timestamps can be restored incorrectly,
e.g.:
tar --no-recursion -cf archive dir dir/file1 foo dir/file2
@@ -547,7 +503,6 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->dev = st->stat.st_dev;
data->ino = st->stat.st_ino;
}
xattr_map_init (&data->xattr_map);
}
data->mode = mode;
@@ -565,7 +520,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->change_dir = chdir_current;
data->cntx_name = NULL;
if (st)
assign_string_or_null (&data->cntx_name, st->cntx_name);
assign_string (&data->cntx_name, st->cntx_name);
if (st && st->acls_a_ptr)
{
data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
@@ -587,7 +542,12 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->acls_d_len = 0;
}
if (st)
xattr_map_copy (&data->xattr_map, &st->xattr_map);
xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
else
{
data->xattr_map = NULL;
data->xattr_map_size = 0;
}
if (must_be_dot_or_slash (file_name))
mark_after_links (data);
}
@@ -635,7 +595,7 @@ static void
free_delayed_set_stat (struct delayed_set_stat *data)
{
free (data->file_name);
xattr_map_free (&data->xattr_map);
xheader_xattr_free (data->xattr_map, data->xattr_map_size);
free (data->cntx_name);
free (data->acls_a_ptr);
free (data->acls_d_ptr);
@@ -681,17 +641,16 @@ fixup_delayed_set_stat (char const *src, char const *dst)
}
}
/* After a file/link/directory creation has failed due to ENOENT,
/* 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
directories were created, nonzero (issuing a diagnostic) otherwise.
Set *INTERDIR_MADE if at least one directory was created. */
static int
make_directories (char *file_name)
make_directories (char *file_name, bool *interdir_made)
{
char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
char *cursor; /* points into the file name */
char *parent_end = NULL;
int parent_errno;
for (cursor = cursor0; *cursor; cursor++)
{
@@ -729,48 +688,33 @@ make_directories (char *file_name)
0, mode & ~ current_umask, MODE_RWX,
desired_mode, AT_SYMLINK_NOFOLLOW);
print_for_mkdir (file_name, desired_mode);
parent_end = NULL;
print_for_mkdir (file_name, cursor - file_name, desired_mode);
*interdir_made = true;
}
else if (errno == EEXIST)
status = 0;
else
switch (errno)
{
case ELOOP: case ENAMETOOLONG: case ENOENT: case ENOTDIR:
/* FILE_NAME doesn't exist and couldn't be created; fail now. */
mkdir_error (file_name);
*cursor = '/';
return status;
default:
/* FILE_NAME may be an existing directory so do not fail now.
Instead, arrange to check at loop exit, assuming this is
the last loop iteration. */
parent_end = cursor;
parent_errno = errno;
break;
}
{
/* Check whether the desired file exists. Even when the
file exists, mkdir can fail with some errno value E other
than EEXIST, so long as E describes an error condition
that also applies. */
int e = errno;
struct stat st;
status = fstatat (chdir_fd, file_name, &st, 0);
if (status)
{
errno = e;
mkdir_error (file_name);
}
}
*cursor = '/';
if (status)
return status;
}
if (!parent_end)
return 0;
/* Although we did not create the parent directory, some other
process may have created it, so check whether it exists now. */
*parent_end = '\0';
struct stat st;
int stat_status = fstatat (chdir_fd, file_name, &st, 0);
if (!stat_status && !S_ISDIR (st.st_mode))
stat_status = -1;
if (stat_status)
{
errno = parent_errno;
mkdir_error (file_name);
}
*parent_end = '/';
return stat_status;
return 0;
}
/* Return true if FILE_NAME (with status *STP, if STP) is not a
@@ -884,12 +828,9 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
FALLTHROUGH;
case ENOENT:
/* Attempt creating missing intermediate directories. */
if (make_directories (file_name) == 0)
{
*interdir_made = true;
return RECOVER_OK;
}
/* Attempt creating missing intermediate directories. */
if (make_directories (file_name, interdir_made) == 0 && *interdir_made)
return RECOVER_OK;
break;
default:
@@ -906,22 +847,44 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
(e.g. on Lustre distributed parallel filesystem - setting info about how many
servers is this file striped over, stripe size, mirror copies, etc.
in advance dramatically improves the following performance of reading and
writing a file). TYPEFLAG specifies the type of the file. Return a negative
number (setting errno) on failure, zero if successful but FILE_NAME was not
created (e.g., xattrs not available), and a positive number if FILE_NAME was
created. */
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. 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 mode, char typeflag)
mode_t invert_permissions, char typeflag, int *file_created)
{
#ifdef HAVE_XATTRS
if ((xattrs_option > 0) && st->xattr_map.xm_size)
bool interdir_made = false;
if ((xattrs_option > 0) && st->xattr_map_size)
{
int r = mknodat (chdir_fd, file_name, mode, 0);
if (r < 0)
return r;
xattrs_xattrs_set (st, file_name, typeflag, 0);
return 1;
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
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;
}
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
@@ -994,6 +957,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
sb.acls_d_ptr = data->acls_d_ptr;
sb.acls_d_len = data->acls_d_len;
sb.xattr_map = data->xattr_map;
sb.xattr_map_size = data->xattr_map_size;
set_stat (data->file_name, &sb,
-1, current_mode, current_mode_mask,
DIRTYPE, data->interdir, data->atflag);
@@ -1006,12 +970,18 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
static bool
is_directory_link (char const *file_name, struct stat *st)
is_directory_link (const char *file_name)
{
char buf[1];
return (0 <= readlinkat (chdir_fd, file_name, buf, sizeof buf)
&& fstatat (chdir_fd, file_name, st, 0) == 0
&& S_ISDIR (st->st_mode));
struct stat st;
int e = errno;
int res;
res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
S_ISLNK (st.st_mode) &&
fstatat (chdir_fd, file_name, &st, 0) == 0 &&
S_ISDIR (st.st_mode));
errno = e;
return res;
}
/* Given struct stat of a directory (or directory member) whose ownership
@@ -1024,7 +994,7 @@ is_directory_link (char const *file_name, struct stat *st)
If not root, though, make the directory writeable and searchable at first,
so that files can be created under it.
*/
static int
static inline int
safe_dir_mode (struct stat const *st)
{
return ((st->st_mode
@@ -1076,69 +1046,58 @@ extract_dir (char *file_name, int typeflag)
break;
}
if (errno == EEXIST)
{
if (interdir_made
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)
|| old_files_option == OVERWRITE_OLD_FILES))
{
struct stat st;
if (keep_directory_symlink_option && is_directory_link (file_name))
return 0;
if (deref_stat (file_name, &st) == 0)
{
struct stat st;
st.st_mode = 0;
current_mode = st.st_mode;
current_mode_mask = ALL_MODE_BITS;
if (keep_directory_symlink_option
&& is_directory_link (file_name, &st))
return 0;
if ((st.st_mode != 0 && fstatat_flags == 0)
|| deref_stat (file_name, &st) == 0)
if (S_ISDIR (current_mode))
{
current_mode = st.st_mode;
current_mode_mask = ALL_MODE_BITS;
if (S_ISDIR (current_mode))
if (interdir_made)
{
if (interdir_made)
{
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;
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;
}
}
else if (old_files_option == UNLINK_FIRST_OLD_FILES)
{
status = 0;
break;
}
errno = EEXIST;
}
@@ -1180,12 +1139,14 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
int fd;
bool overwriting_old_files = old_files_option == OVERWRITE_OLD_FILES;
int openflag = (O_WRONLY | O_BINARY | O_CLOEXEC | O_NOCTTY | O_NONBLOCK
| (file_created
? O_NOFOLLOW
: (O_CREAT
| (overwriting_old_files
? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW)
: O_EXCL))));
| O_CREAT
| (overwriting_old_files
? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW)
: O_EXCL));
/* File might be created in set_xattr. So clear O_EXCL to avoid open() fail */
if (file_created)
openflag = openflag & ~O_EXCL;
if (typeflag == CONTTYPE)
{
@@ -1205,8 +1166,9 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
if (! HAVE_WORKING_O_NOFOLLOW
&& overwriting_old_files && ! dereference_option)
{
char buf[1];
if (0 <= readlinkat (chdir_fd, file_name, buf, sizeof buf))
struct stat st;
if (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0
&& S_ISLNK (st.st_mode))
{
errno = ELOOP;
return -1;
@@ -1216,12 +1178,7 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
fd = openat (chdir_fd, file_name, openflag, mode);
if (0 <= fd)
{
if (openflag & O_EXCL)
{
*current_mode = mode & ~ current_umask;
*current_mode_mask = MODE_RWX;
}
else
if (overwriting_old_files)
{
struct stat st;
if (fstat (fd, &st) != 0)
@@ -1240,6 +1197,11 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
*current_mode = st.st_mode;
*current_mode_mask = ALL_MODE_BITS;
}
else
{
*current_mode = mode & ~ current_umask;
*current_mode_mask = MODE_RWX;
}
}
return fd;
@@ -1257,6 +1219,8 @@ extract_file (char *file_name, int typeflag)
bool interdir_made = false;
mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
& ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
mode_t invert_permissions = 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO)
: 0;
mode_t current_mode = 0;
mode_t current_mode_mask = 0;
@@ -1273,18 +1237,15 @@ extract_file (char *file_name, int typeflag)
}
else
{
int file_created;
/* Either we pre-create the file in set_xattr(), or we just directly open
the file in open_output_file() with O_CREAT. If pre-creating, we need
to use S_IWUSR so we can open the file O_WRONLY in open_output_file().
The additional mode bit is cleared later by set_stat()->set_mode(). */
while (((file_created = set_xattr (file_name, &current_stat_info,
mode | S_IWUSR, typeflag))
< 0)
|| ((fd = open_output_file (file_name, typeflag, mode,
file_created, &current_mode,
&current_mode_mask))
< 0))
int file_created = 0;
if (set_xattr (file_name, &current_stat_info, invert_permissions,
typeflag, &file_created))
return 1;
while ((fd = open_output_file (file_name, typeflag, mode,
file_created, &current_mode,
&current_mode_mask))
< 0)
{
int recover = maybe_recoverable (file_name, true, &interdir_made);
if (recover != RECOVER_OK)
@@ -1336,7 +1297,7 @@ extract_file (char *file_name, int typeflag)
}
}
skim_file (size, false);
skip_file (size);
mv_end ();
@@ -1362,45 +1323,54 @@ extract_file (char *file_name, int typeflag)
return status;
}
/* Return true if NAME is a delayed link. This can happen only if the link
/* 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 table.
Otherwise, look for the entry in the table that has the matching dev
and ino numbers. Return false if not found.
Do not rely on comparing file names, which may differ for
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 bool
static struct delayed_link *
find_delayed_link_source (char const *name)
{
struct delayed_link *dl;
struct stat st;
if (!delayed_link_table)
return false;
if (!delayed_link_head)
return NULL;
if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW))
{
if (errno != ENOENT)
stat_error (name);
return false;
return NULL;
}
struct delayed_link dl;
dl.dev = st.st_dev;
dl.ino = st.st_ino;
return hash_lookup (delayed_link_table, &dl) != 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.
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;
@@ -1415,7 +1385,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
*/
return 0;
}
switch (maybe_recoverable (file_name, false, interdir_made))
{
case RECOVER_OK:
@@ -1441,14 +1411,22 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
{
struct delayed_set_stat *h;
struct delayed_link *p =
xmalloc (FLEXNSIZEOF (struct delayed_link, target,
strlen (current_stat_info.link_name) + 1));
p->next = NULL;
xmalloc (offsetof (struct delayed_link, target)
+ strlen (current_stat_info.link_name)
+ 1);
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;
#if HAVE_BIRTHTIME
p->birthtime = get_stat_birthtime (&st);
#endif
p->is_symlink = is_symlink;
if (is_symlink)
{
@@ -1459,28 +1437,20 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
p->mtime = current_stat_info.mtime;
}
p->change_dir = chdir_current;
p->sources = xmalloc (FLEXNSIZEOF (struct string_list, string,
strlen (file_name) + 1));
p->sources = xmalloc (offsetof (struct string_list, string)
+ strlen (file_name) + 1);
p->sources->next = 0;
strcpy (p->sources->string, file_name);
p->cntx_name = NULL;
assign_string_or_null (&p->cntx_name, current_stat_info.cntx_name);
assign_string (&p->cntx_name, current_stat_info.cntx_name);
p->acls_a_ptr = NULL;
p->acls_a_len = 0;
p->acls_d_ptr = NULL;
p->acls_d_len = 0;
xattr_map_init (&p->xattr_map);
xattr_map_copy (&p->xattr_map, &current_stat_info.xattr_map);
xheader_xattr_copy (&current_stat_info, &p->xattr_map,
&p->xattr_map_size);
strcpy (p->target, current_stat_info.link_name);
*delayed_link_tail = p;
delayed_link_tail = &p->next;
if (! ((delayed_link_table
|| (delayed_link_table = hash_initialize (0, 0, dl_hash,
dl_compare, free)))
&& hash_insert (delayed_link_table, p)))
xalloc_die ();
if ((h = find_direct_ancestor (file_name)) != NULL)
mark_after_links (h);
@@ -1491,18 +1461,21 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
}
static int
extract_link (char *file_name, MAYBE_UNUSED int typeflag)
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))
|| find_delayed_link_source (link_name))
return create_placeholder_file (file_name, false, &interdir_made);
if (! absolute_names_option && contains_dot_dot (link_name))
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;
@@ -1512,25 +1485,23 @@ extract_link (char *file_name, MAYBE_UNUSED int typeflag)
if (status == 0)
{
if (delayed_link_table
struct delayed_link *ds = delayed_link_head;
if (ds
&& fstatat (chdir_fd, link_name, &st1, AT_SYMLINK_NOFOLLOW) == 0)
{
struct delayed_link dl1;
dl1.ino = st1.st_ino;
dl1.dev = st1.st_dev;
struct delayed_link *ds = hash_lookup (delayed_link_table, &dl1);
if (ds && ds->change_dir == chdir_current
&& BIRTHTIME_EQ (ds->birthtime, get_stat_birthtime (&st1)))
for (; ds; ds = ds->next)
if (ds->change_dir == chdir_current
&& ds->dev == st1.st_dev
&& ds->ino == st1.st_ino
&& (timespec_cmp (ds->birthtime, get_stat_birthtime (&st1))
== 0))
{
struct string_list *p
= xmalloc (FLEXNSIZEOF (struct string_list,
string, strlen (file_name) + 1));
struct string_list *p = xmalloc (offsetof (struct string_list, string)
+ strlen (file_name) + 1);
strcpy (p->string, file_name);
p->next = ds->sources;
ds->sources = p;
break;
}
}
return 0;
}
else if ((e == EEXIST && strcmp (link_name, file_name) == 0)
@@ -1558,7 +1529,7 @@ extract_link (char *file_name, MAYBE_UNUSED int typeflag)
}
static int
extract_symlink (char *file_name, MAYBE_UNUSED int typeflag)
extract_symlink (char *file_name, int typeflag)
{
#ifdef HAVE_SYMLINK
bool interdir_made = false;
@@ -1566,7 +1537,7 @@ extract_symlink (char *file_name, MAYBE_UNUSED 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))
@@ -1726,7 +1697,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
case GNUTYPE_VOLHDR:
return false;
case GNUTYPE_MULTIVOL:
ERROR ((0, 0,
_("%s: Cannot extract -- file is continued from another volume"),
@@ -1782,7 +1753,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
}
}
*fun = extractor;
return true;
}
@@ -1856,68 +1827,69 @@ extract_archive (void)
undo_last_backup ();
}
/* Extract the link DS whose final extraction was delayed. */
/* Extract the links whose final extraction were delayed. */
static void
apply_delayed_link (struct delayed_link *ds)
apply_delayed_links (void)
{
struct string_list *sources = ds->sources;
char const *valid_source = 0;
struct delayed_link *ds;
chdir_do (ds->change_dir);
for (sources = ds->sources; sources; sources = sources->next)
for (ds = delayed_link_head; ds; )
{
char const *source = sources->string;
struct stat st;
struct string_list *sources = ds->sources;
char const *valid_source = 0;
/* Make sure the placeholder file is still there. If not,
don't create a link, as the placeholder was probably
removed by a later extraction. */
if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
&& st.st_dev == ds->dev
&& st.st_ino == ds->ino
&& BIRTHTIME_EQ (get_stat_birthtime (&st), ds->birthtime))
chdir_do (ds->change_dir);
for (sources = ds->sources; sources; sources = sources->next)
{
/* Unlink the placeholder, then create a hard link if possible,
a symbolic link otherwise. */
if (unlinkat (chdir_fd, source, 0) != 0)
unlink_error (source);
else if (valid_source
&& (linkat (chdir_fd, valid_source, chdir_fd, source, 0)
== 0))
;
else if (!ds->is_symlink)
char const *source = sources->string;
struct stat st;
/* Make sure the placeholder file is still there. If not,
don't create a link, as the placeholder was probably
removed by a later extraction. */
if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
&& st.st_dev == ds->dev
&& st.st_ino == ds->ino
&& timespec_cmp (get_stat_birthtime (&st), ds->birthtime) == 0)
{
if (linkat (chdir_fd, ds->target, chdir_fd, source, 0) != 0)
link_error (ds->target, source);
}
else if (symlinkat (ds->target, chdir_fd, source) != 0)
symlink_error (ds->target, source);
else
{
struct tar_stat_info st1;
st1.stat.st_mode = ds->mode;
st1.stat.st_uid = ds->uid;
st1.stat.st_gid = ds->gid;
st1.atime = ds->atime;
st1.mtime = ds->mtime;
st1.cntx_name = ds->cntx_name;
st1.acls_a_ptr = ds->acls_a_ptr;
st1.acls_a_len = ds->acls_a_len;
st1.acls_d_ptr = ds->acls_d_ptr;
st1.acls_d_len = ds->acls_d_len;
st1.xattr_map = ds->xattr_map;
set_stat (source, &st1, -1, 0, 0, SYMTYPE,
false, AT_SYMLINK_NOFOLLOW);
valid_source = source;
/* Unlink the placeholder, then create a hard link if possible,
a symbolic link otherwise. */
if (unlinkat (chdir_fd, source, 0) != 0)
unlink_error (source);
else if (valid_source
&& (linkat (chdir_fd, valid_source, chdir_fd, source, 0)
== 0))
;
else if (!ds->is_symlink)
{
if (linkat (chdir_fd, ds->target, chdir_fd, source, 0) != 0)
link_error (ds->target, source);
}
else if (symlinkat (ds->target, chdir_fd, source) != 0)
symlink_error (ds->target, source);
else
{
struct tar_stat_info st1;
st1.stat.st_mode = ds->mode;
st1.stat.st_uid = ds->uid;
st1.stat.st_gid = ds->gid;
st1.atime = ds->atime;
st1.mtime = ds->mtime;
st1.cntx_name = ds->cntx_name;
st1.acls_a_ptr = ds->acls_a_ptr;
st1.acls_a_len = ds->acls_a_len;
st1.acls_d_ptr = ds->acls_d_ptr;
st1.acls_d_len = ds->acls_d_len;
st1.xattr_map = ds->xattr_map;
st1.xattr_map_size = ds->xattr_map_size;
set_stat (source, &st1, -1, 0, 0, SYMTYPE,
false, AT_SYMLINK_NOFOLLOW);
valid_source = source;
}
}
}
}
/* There is little point to freeing, as we are about to exit,
and freeing is more likely to cause than cure trouble. */
if (false)
{
for (sources = ds->sources; sources; )
{
struct string_list *next = sources->next;
@@ -1925,27 +1897,17 @@ apply_delayed_link (struct delayed_link *ds)
sources = next;
}
xattr_map_free (&ds->xattr_map);
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
free (ds->cntx_name);
}
}
/* Extract the links whose final extraction were delayed. */
static void
apply_delayed_links (void)
{
for (struct delayed_link *ds = delayed_link_head; ds; ds = ds->next)
apply_delayed_link (ds);
if (false)
{
/* There is little point to freeing, as we are about to exit,
and freeing is more likely to cause than cure trouble.
Also, the above code has not bothered to free the list
in delayed_link_head. */
hash_free (delayed_link_table);
delayed_link_table = NULL;
{
struct delayed_link *next = ds->next;
free (ds);
ds = next;
}
}
delayed_link_head = 0;
}
/* Finish the extraction of an archive. */
@@ -1972,11 +1934,12 @@ rename_directory (char *src, char *dst)
else
{
int e = errno;
bool interdir_made;
switch (e)
{
case ENOENT:
if (make_directories (dst) == 0)
if (make_directories (dst, &interdir_made) == 0)
{
if (renameat (chdir_fd, src, chdir_fd, dst) == 0)
return true;

View File

@@ -1,6 +1,6 @@
/* GNU dump extensions to tar.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -903,19 +903,19 @@ store_rename (struct directory *dir, struct obstack *stk)
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);
}
@@ -993,7 +993,7 @@ read_incr_db_01 (int version, const char *initbuf)
}
else
{
buf = xstrdup (initbuf);
buf = strdup (initbuf);
bufsize = strlen (buf) + 1;
}

View File

@@ -1,6 +1,6 @@
/* List a tar archive, with support routines for reading a tar archive.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -256,13 +256,6 @@ read_and (void (*do_something) (void))
continue;
case HEADER_END_OF_FILE:
if (!ignore_zeros_option)
{
char buf[UINTMAX_STRSIZE_BOUND];
WARNOPT (WARN_MISSING_ZERO_BLOCKS,
(0, 0, _("Terminating zero blocks missing at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
}
if (block_number_option)
{
char buf[UINTMAX_STRSIZE_BOUND];
@@ -423,7 +416,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
size_t next_long_name_blocks = 0;
size_t next_long_link_blocks = 0;
enum read_header status = HEADER_SUCCESS;
while (1)
{
header = find_next_block ();
@@ -881,9 +874,8 @@ from_header (char const *where0, size_t digs, char const *type,
where++;
}
}
else if (where <= lim - 2
&& (*where == '\200' /* positive base-256 */
|| *where == '\377' /* negative base-256 */))
else if (*where == '\200' /* positive base-256 */
|| *where == '\377' /* negative base-256 */)
{
/* Parse base-256 output. A nonnegative number N is
represented as (256**DIGS)/2 + N; a negative number -N is
@@ -1376,7 +1368,7 @@ print_header (struct tar_stat_info *st, union block *blk,
/* Print a similar line when we make a directory automatically. */
void
print_for_mkdir (char *dirname, mode_t mode)
print_for_mkdir (char *dirname, int length, mode_t mode)
{
char modes[11];
@@ -1399,17 +1391,15 @@ print_for_mkdir (char *dirname, mode_t mode)
}
}
/* Skip over SIZE bytes of data in blocks in the archive.
This may involve copying the data.
If MUST_COPY, always copy instead of skipping. */
/* Skip over SIZE bytes of data in blocks in the archive. */
void
skim_file (off_t size, bool must_copy)
skip_file (off_t size)
{
union block *x;
/* FIXME: Make sure mv_begin_read is always called before it */
if (seekable_archive && !must_copy)
if (seekable_archive)
{
off_t nblk = seek_archive (size);
if (nblk >= 0)
@@ -1436,14 +1426,6 @@ skim_file (off_t size, bool must_copy)
NOTE: Current header must be decoded before calling this function. */
void
skip_member (void)
{
skim_member (false);
}
/* Skip the current member in the archive.
If MUST_COPY, always copy instead of skipping. */
void
skim_member (bool must_copy)
{
if (!current_stat_info.skipped)
{
@@ -1453,9 +1435,9 @@ skim_member (bool must_copy)
mv_begin_read (&current_stat_info);
if (current_stat_info.is_sparse)
sparse_skim_file (&current_stat_info, must_copy);
sparse_skip_file (&current_stat_info);
else if (save_typeflag != DIRTYPE)
skim_file (current_stat_info.stat.st_size, must_copy);
skip_file (current_stat_info.stat.st_size);
mv_end ();
}

View File

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

View File

@@ -1,6 +1,6 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright 1988-2023 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
@@ -42,28 +42,11 @@ quote_n_colon (int n, char const *arg)
/* Assign STRING to a copy of VALUE if not zero, or to zero. If
STRING was nonzero, it is freed first. */
void
assign_string_or_null (char **string, const char *value)
{
if (value)
assign_string (string, value);
else
assign_null (string);
}
void
assign_string (char **string, const char *value)
{
free (*string);
*string = xstrdup (value);
}
void
assign_null (char **string)
{
char *old = *string;
*string = NULL;
free (old);
*string = value ? xstrdup (value) : 0;
}
void
@@ -78,8 +61,6 @@ assign_string_n (char **string, const char *value, size_t n)
p[l] = 0;
*string = p;
}
else
*string = NULL;
}
#if 0
@@ -695,11 +676,13 @@ remove_any_file (const char *file_name, enum remove_option option)
char *file_name_buffer = make_file_name (file_name, entry);
int r = remove_any_file (file_name_buffer,
RECURSIVE_REMOVE_OPTION);
int e = errno;
free (file_name_buffer);
if (! r)
{
free (directory);
errno = e;
return 0;
}
}
@@ -732,7 +715,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
possible, real problems are unlikely. Doing any better would require a
convention, GNU-wide, for all programs doing backups. */
assign_null (&after_backup_name);
assign_string (&after_backup_name, 0);
/* Check if we really need to backup the file. */
@@ -775,7 +758,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
ERROR ((0, e, _("%s: Cannot rename to %s"),
quotearg_colon (before_backup_name),
quote_n (1, after_backup_name)));
assign_null (&after_backup_name);
assign_string (&after_backup_name, 0);
return false;
}
}
@@ -799,7 +782,7 @@ undo_last_backup (void)
fprintf (stdlis, _("Renaming %s back to %s\n"),
quote_n (0, after_backup_name),
quote_n (1, before_backup_name));
assign_null (&after_backup_name);
assign_string (&after_backup_name, 0);
}
}
@@ -821,7 +804,7 @@ deref_stat (char const *name, struct stat *buf)
size_t
blocking_read (int fd, void *buf, size_t count)
{
size_t bytes = full_read (fd, buf, count);
size_t bytes = safe_read (fd, buf, count);
#if defined F_SETFL && O_NONBLOCK
if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
@@ -829,12 +812,10 @@ blocking_read (int fd, void *buf, size_t count)
int flags = fcntl (fd, F_GETFL);
if (0 <= flags && flags & O_NONBLOCK
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
bytes = full_read (fd, buf, count);
bytes = safe_read (fd, buf, count);
}
#endif
if (bytes == 0 && errno != 0)
bytes = SAFE_READ_ERROR;
return bytes;
}
@@ -1060,11 +1041,11 @@ tar_getcdpath (int idx)
{
int i;
int save_cwdi = chdir_current;
for (i = idx; i >= 0; i--)
if (wd[i].abspath)
break;
while (++i <= idx)
{
chdir_do (i);
@@ -1088,7 +1069,7 @@ tar_getcdpath (int idx)
chdir_do (save_cwdi);
}
return wd[idx].abspath;
}
@@ -1214,7 +1195,7 @@ xpipe (int fd[2])
PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
locations. */
static void *
static inline void *
ptr_align (void *ptr, size_t alignment)
{
char *p0 = ptr;

View File

@@ -1,6 +1,6 @@
/* Various processing of names.
Copyright 1988-2023 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
@@ -199,7 +199,7 @@ names_parse_opt (int key, char *arg, struct argp_state *state)
case ADD_FILE_OPTION:
name_add_name (arg);
break;
case ARGP_KEY_ERROR:
{
struct tar_args *args = state->input;
@@ -217,7 +217,7 @@ names_parse_opt (int key, char *arg, struct argp_state *state)
name_add_option (key, arg);
else
return ARGP_ERR_UNKNOWN;
}
return 0;
}
@@ -348,7 +348,7 @@ handle_file_selection_option (int key, const char *arg)
break;
case EXCLUDE_VCS_OPTION:
add_exclude_array (vcs_file_table, FNM_LEADING_DIR);
add_exclude_array (vcs_file_table, 0);
break;
case EXCLUDE_VCS_IGNORES_OPTION:
@@ -395,7 +395,7 @@ handle_file_selection_option (int key, const char *arg)
break;
case NO_ANCHORED_OPTION:
include_anchored = 0; /* Clear the default for command line args */
include_anchored = 0; /* Clear the default for comman line args */
matching_flags &= ~ EXCLUDE_ANCHORED;
break;
@@ -744,7 +744,7 @@ unconsumed_option_report (void)
{
struct name_elt *elt;
ERROR ((0, 0, _("The following options were used after non-option arguments. These options are positional and affect only arguments that follow them. Please, rearrange them properly.")));
ERROR ((0, 0, _("The following options were used after any non-optional arguments in archive create or update mode. These options are positional and affect only arguments that follow them. Please, rearrange them properly.")));
elt = unconsumed_option_tail;
while (elt->prev)
@@ -980,6 +980,7 @@ read_name_from_file (struct name_elt *ent)
if (counter == name_buffer_length)
name_buffer = x2realloc (name_buffer, &name_buffer_length);
name_buffer[counter] = 0;
chopslash (name_buffer);
return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
}
@@ -1028,10 +1029,8 @@ read_next_name (struct name_elt *ent, struct name_elt *ret)
name_list_advance ();
return 1;
}
FILE *fp = fopen (ent->v.file.name, "r");
if (!fp)
if ((ent->v.file.fp = fopen (ent->v.file.name, "r")) == NULL)
open_fatal (ent->v.file.name);
ent->v.file.fp = fp;
}
ent->v.file.term = filename_terminator;
ent->v.file.verbatim = verbatim_files_from_option;
@@ -1061,7 +1060,6 @@ read_next_name (struct name_elt *ent, struct name_elt *ret)
return 1;
}
}
chopslash (name_buffer);
ret->type = NELT_NAME;
ret->v.name = name_buffer;
return 0;
@@ -1153,13 +1151,6 @@ name_next (int change_dirs)
return nelt ? nelt->v.name : NULL;
}
static bool
name_is_wildcard (struct name const *name)
{
return (name->matching_flags & EXCLUDE_WILDCARDS) &&
fnmatch_pattern_has_wildcards (name->name, name->matching_flags);
}
/* Gather names in a list for scanning. Could hash them later if we
really care.
@@ -1196,7 +1187,6 @@ name_gather (void)
buffer->directory = NULL;
buffer->parent = NULL;
buffer->cmdline = true;
buffer->is_wildcard = name_is_wildcard (buffer);
namelist = nametail = buffer;
}
@@ -1240,7 +1230,6 @@ addname (char const *string, int change_dir, bool cmdline, struct name *parent)
name->directory = NULL;
name->parent = parent;
name->cmdline = cmdline;
name->is_wildcard = name_is_wildcard (name);
if (nametail)
nametail->next = name;
@@ -1261,35 +1250,33 @@ add_starting_file (char const *file_name)
remname (head);
free_name (head);
}
name->prev = NULL;
name->next = namelist;
namelist = name;
if (!nametail)
nametail = namelist;
name->found_count = 0;
name->matching_flags = INCLUDE_OPTIONS;
name->change_dir = 0;
name->directory = NULL;
name->parent = NULL;
name->cmdline = true;
name->is_wildcard = name_is_wildcard (name);
starting_file_option = true;
}
/* Find a match for FILE_NAME in the name list. If EXACT is true,
look for exact match (no wildcards). */
/* Find a match for FILE_NAME (whose string length is LENGTH) in the name
list. */
static struct name *
namelist_match (char const *file_name, bool exact)
namelist_match (char const *file_name, size_t length)
{
struct name *p;
for (p = namelist; p; p = p->next)
{
if (p->name[0]
&& (exact ? !p->is_wildcard : true)
&& exclude_fnmatch (p->name, file_name, p->matching_flags))
return p;
}
@@ -1318,6 +1305,8 @@ remname (struct name *name)
bool
name_match (const char *file_name)
{
size_t length = strlen (file_name);
while (1)
{
struct name *cursor = namelist;
@@ -1333,7 +1322,7 @@ name_match (const char *file_name)
return true;
}
cursor = namelist_match (file_name, false);
cursor = namelist_match (file_name, length);
if (starting_file_option)
{
/* If starting_file_option is set, the head of the list is the name
@@ -1882,14 +1871,15 @@ collect_and_sort_names (void)
1. It returns a pointer to the name it matched, and doesn't set FOUND
in structure. The caller will have to do that if it wants to.
2. If the namelist is empty, it returns null, unlike name_match, which
returns TRUE.
3. If EXACT is true, it looks for exact matches only (no wildcards). */
returns TRUE. */
struct name *
name_scan (const char *file_name, bool exact)
name_scan (const char *file_name)
{
size_t length = strlen (file_name);
while (1)
{
struct name *cursor = namelist_match (file_name, exact);
struct name *cursor = namelist_match (file_name, length);
if (cursor)
return cursor;
@@ -1909,10 +1899,9 @@ name_scan (const char *file_name, bool exact)
}
}
/* This returns a name from the namelist which is an exact match (i.e.
not a pattern) and doesn't have ->found set. It sets ->found before
returning, so successive calls will find and return all the non-found
names in the namelist. */
/* This returns a name from the namelist which doesn't have ->found
set. It sets ->found before returning, so successive calls will
find and return all the non-found names in the namelist. */
struct name *gnu_list_name;
struct name const *
@@ -1921,13 +1910,11 @@ name_from_list (void)
if (!gnu_list_name)
gnu_list_name = namelist;
while (gnu_list_name
&& (gnu_list_name->is_wildcard ||
gnu_list_name->found_count || gnu_list_name->name[0] == 0))
&& (gnu_list_name->found_count || gnu_list_name->name[0] == 0))
gnu_list_name = gnu_list_name->next;
if (gnu_list_name)
{
if (!gnu_list_name->is_wildcard)
gnu_list_name->found_count++;
gnu_list_name->found_count++;
chdir_do (gnu_list_name->change_dir);
return gnu_list_name;
}

View File

@@ -1,6 +1,6 @@
/* Functions for dealing with sparse files
Copyright 2003-2023 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
@@ -335,6 +335,8 @@ sparse_scan_file_seek (struct tar_sparse_file *file)
st->archive_file_size += sp.numbytes;
offset = hole_offset;
}
return true;
}
#endif
@@ -415,7 +417,7 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
size_t bytes_read;
blk = find_next_block ();
bytes_read = full_read (file->fd, blk->buffer, bufsize);
bytes_read = safe_read (file->fd, blk->buffer, bufsize);
if (bytes_read == SAFE_READ_ERROR)
{
read_diag_details (file->stat_info->orig_file_name,
@@ -427,39 +429,27 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
}
else if (bytes_read == 0)
{
if (errno != 0)
{
read_diag_details (file->stat_info->orig_file_name,
(file->stat_info->sparse_map[i].offset
+ file->stat_info->sparse_map[i].numbytes
- bytes_left),
bufsize);
return false;
}
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
{
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;
}
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);
@@ -580,10 +570,7 @@ sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
size_t i;
if (!tar_sparse_init (&file))
{
*size = st->stat.st_size;
return dump_status_not_implemented;
}
return dump_status_not_implemented;
file.stat_info = st;
file.fd = fd;
@@ -598,7 +585,7 @@ sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
}
enum dump_status
sparse_skim_file (struct tar_stat_info *st, bool must_copy)
sparse_skip_file (struct tar_stat_info *st)
{
bool rc = true;
struct tar_sparse_file file;
@@ -610,7 +597,7 @@ sparse_skim_file (struct tar_stat_info *st, bool must_copy)
file.fd = -1;
rc = tar_sparse_decode_header (&file);
skim_file (file.stat_info->archive_file_size - file.dumped_size, must_copy);
skip_file (file.stat_info->archive_file_size - file.dumped_size);
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
}
@@ -627,7 +614,7 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
char diff_buffer[BLOCKSIZE];
bytes_read = full_read (file->fd, diff_buffer, rdsize);
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
if (bytes_read == SAFE_READ_ERROR)
{
read_diag_details (file->stat_info->orig_file_name,
@@ -637,15 +624,10 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
}
else if (bytes_read == 0)
{
if (errno != 0)
read_diag_details (file->stat_info->orig_file_name,
beg,
rdsize);
else
report_difference (file->stat_info, _("Size differs"));
report_difference (file->stat_info, _("Size differs"));
return false;
}
if (!zero_block_p (diff_buffer, bytes_read))
{
char begbuf[INT_BUFSIZE_BOUND (off_t)];
@@ -684,8 +666,8 @@ check_data_region (struct tar_sparse_file *file, size_t i)
return false;
}
set_next_block_after (blk);
file->dumped_size += BLOCKSIZE;
bytes_read = full_read (file->fd, diff_buffer, rdsize);
file->dumped_size += BLOCKSIZE;
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
if (bytes_read == SAFE_READ_ERROR)
{
read_diag_details (file->stat_info->orig_file_name,
@@ -697,14 +679,7 @@ check_data_region (struct tar_sparse_file *file, size_t i)
}
else if (bytes_read == 0)
{
if (errno != 0)
read_diag_details (file->stat_info->orig_file_name,
(file->stat_info->sparse_map[i].offset
+ file->stat_info->sparse_map[i].numbytes
- size_left),
rdsize);
else
report_difference (&current_stat_info, _("Size differs"));
report_difference (&current_stat_info, _("Size differs"));
return false;
}
size_left -= bytes_read;
@@ -745,7 +720,7 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
}
if (!rc)
skim_file (file.stat_info->archive_file_size - file.dumped_size, false);
skip_file (file.stat_info->archive_file_size - file.dumped_size);
mv_end ();
tar_sparse_done (&file);
@@ -779,7 +754,7 @@ enum oldgnu_add_status
};
static bool
oldgnu_sparse_member_p (MAYBE_UNUSED struct tar_sparse_file *file)
oldgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
{
return current_header->header.typeflag == GNUTYPE_SPARSE;
}
@@ -923,7 +898,7 @@ static struct tar_sparse_optab const oldgnu_optab = {
/* Star */
static bool
star_sparse_member_p (MAYBE_UNUSED struct tar_sparse_file *file)
star_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
{
return current_header->header.typeflag == GNUTYPE_SPARSE;
}
@@ -1043,7 +1018,7 @@ static struct tar_sparse_optab const star_optab = {
* 1.0
Starting from this version, the exact sparse format version is specified
explicitly in the header using the following variables:
explicitely in the header using the following variables:
GNU.sparse.major Major version
GNU.sparse.minor Minor version
@@ -1275,7 +1250,7 @@ pax_decode_header (struct tar_sparse_file *file)
char *p;
size_t i;
off_t start;
#define COPY_BUF(b,buf,src) do \
{ \
char *endp = b->buffer + BLOCKSIZE; \
@@ -1333,9 +1308,7 @@ pax_decode_header (struct tar_sparse_file *file)
}
sp.offset = u;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t))
|| INT_ADD_OVERFLOW (sp.offset, u)
|| file->stat_info->stat.st_size < sp.offset + u)
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright 2007-2023 Free Software Foundation, Inc.
Copyright 2007-2021 Free Software Foundation, Inc.
Written by Sergey Poznyakoff.

View File

@@ -1,6 +1,6 @@
/* System-dependent calls for tar.
Copyright 2003-2023 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
@@ -16,7 +16,6 @@
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <system-ioctl.h>
#include "common.h"
#include <priv-set.h>
@@ -38,35 +37,6 @@ xexec (const char *cmd)
exec_fatal (cmd);
}
/* True if the archive is seekable via ioctl and MTIOCTOP,
or if it is not known whether it is seekable.
False if it is known to be not seekable. */
static bool mtioseekable_archive;
bool
mtioseek (bool count_files, off_t count)
{
if (mtioseekable_archive)
{
#ifdef MTIOCTOP
struct mtop operation;
operation.mt_op = (count_files
? (count < 0 ? MTBSF : MTFSF)
: (count < 0 ? MTBSR : MTFSR));
if (! (count < 0
? INT_SUBTRACT_WRAPV (0, count, &operation.mt_count)
: INT_ADD_WRAPV (count, 0, &operation.mt_count))
&& (0 <= rmtioctl (archive, MTIOCTOP, &operation)
|| (errno == EIO
&& 0 <= rmtioctl (archive, MTIOCTOP, &operation))))
return true;
#endif
mtioseekable_archive = false;
}
return false;
}
#if MSDOS
bool
@@ -81,6 +51,11 @@ sys_file_is_archive (struct tar_stat_info *p)
return false;
}
void
sys_save_archive_dev_ino (void)
{
}
void
sys_detect_dev_null_output (void)
{
@@ -153,34 +128,31 @@ sys_child_open_for_uncompress (void)
extern union block *record_start; /* FIXME */
static struct stat archive_stat; /* stat block for archive file */
bool
sys_get_archive_stat (void)
{
bool remote = _isrmt (archive);
mtioseekable_archive = true;
if (!remote && 0 <= archive && fstat (archive, &archive_stat) == 0)
{
if (!S_ISCHR (archive_stat.st_mode))
mtioseekable_archive = false;
return true;
}
else
{
/* FIXME: This memset should not be needed. It is present only
because other parts of tar may incorrectly access
archive_stat even if it's not the archive status. */
memset (&archive_stat, 0, sizeof archive_stat);
return remote;
}
return fstat (archive, &archive_stat) == 0;
}
bool
sys_file_is_archive (struct tar_stat_info *p)
{
return (!dev_null_output && !_isrmt (archive)
&& p->stat.st_dev == archive_stat.st_dev
&& p->stat.st_ino == archive_stat.st_ino);
return (ar_dev && p->stat.st_dev == ar_dev && p->stat.st_ino == ar_ino);
}
/* Save archive file inode and device numbers */
void
sys_save_archive_dev_ino (void)
{
if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
{
ar_dev = archive_stat.st_dev;
ar_ino = archive_stat.st_ino;
}
else
ar_dev = 0;
}
/* Detect if outputting to "/dev/null". */
@@ -188,15 +160,14 @@ void
sys_detect_dev_null_output (void)
{
static char const dev_null[] = "/dev/null";
static struct stat dev_null_stat;
struct stat dev_null_stat;
dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
|| (! _isrmt (archive)
&& S_ISCHR (archive_stat.st_mode)
&& (dev_null_stat.st_ino != 0
|| stat (dev_null, &dev_null_stat) == 0)
&& archive_stat.st_ino == dev_null_stat.st_ino
&& archive_stat.st_dev == dev_null_stat.st_dev));
&& stat (dev_null, &dev_null_stat) == 0
&& archive_stat.st_dev == dev_null_stat.st_dev
&& archive_stat.st_ino == dev_null_stat.st_ino));
}
void
@@ -299,11 +270,6 @@ sys_write_archive_buffer (void)
#define PREAD 0 /* read file descriptor from pipe() */
#define PWRITE 1 /* write file descriptor from pipe() */
/* Work around GCC bug 109839. */
#if 13 <= __GNUC__
# pragma GCC diagnostic ignored "-Wanalyzer-fd-leak"
#endif
/* Duplicate file descriptor FROM into becoming INTO.
INTO is closed first and has to be the next available slot. */
static void
@@ -311,17 +277,31 @@ xdup2 (int from, int into)
{
if (from != into)
{
if (dup2 (from, into) < 0)
int status = close (into);
if (status != 0 && errno != EBADF)
{
int e = errno;
FATAL_ERROR ((0, e, _("Cannot dup2")));
FATAL_ERROR ((0, e, _("Cannot close")));
}
status = dup (from);
if (status != into)
{
if (status < 0)
{
int e = errno;
FATAL_ERROR ((0, e, _("Cannot dup")));
}
abort ();
}
xclose (from);
}
}
static void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
/* Propagate any failure of the grandchild back to the parent. */
static _Noreturn void
static void
wait_for_grandchild (pid_t pid)
{
int wait_status;
@@ -560,7 +540,7 @@ sys_child_open_for_uncompress (void)
&& !_remdev (archive_name_array[0])
&& is_regular_file (archive_name_array[0]))
{
/* We don't need a grandchild tar. Open the archive and launch the
/* We don't need a grandchild tar. Open the archive and lauch the
uncompressor. */
archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);

View File

@@ -1,6 +1,6 @@
/* A tar (tape archiver) program.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
Written by John Gilmore, starting 1985-08-25.
@@ -47,7 +47,6 @@
#include <wordsplit.h>
#include <sysexits.h>
#include <quotearg.h>
#include <verify.h>
#include <version-etc.h>
#include <xstrtol.h>
#include <stdopen.h>
@@ -393,36 +392,36 @@ enum
{
GRH_COMMAND,
GRID_COMMAND, /* Main operation mode */
GRH_MODIFIER,
GRID_MODIFIER, /* Operation modifiers */
GRID_FILE_NAME,
GRH_OVERWRITE,
GRID_OVERWRITE, /* Overwrite control options */
GRH_OUTPUT,
GRID_OUTPUT, /* Output stream selection */
GRH_FATTR,
GRID_FATTR, /* File attributes (ownership and mode) */
GRH_XATTR,
GRID_XATTR, /* Extended file attributes */
GRH_DEVICE,
GRID_DEVICE, /* Device selection */
GRH_BLOCKING,
GRID_BLOCKING, /* Block and record length */
GRH_FORMAT,
GRID_FORMAT, /* Archive format options */
GRDOC_FORMAT,
GRID_FORMAT_OPT,
GRH_COMPRESS,
GRID_COMPRESS, /* Compression options */
@@ -846,25 +845,10 @@ static enum atime_preserve const atime_preserve_types[] =
ARGMATCH_VERIFY (atime_preserve_args, atime_preserve_types);
static char * ATTRIBUTE_FORMAT ((printf, 1, 2))
easprintf (char const *format, ...)
{
va_list args;
va_start (args, format);
char *result = xvasprintf (format, args);
int err = errno;
va_end (args);
if (!result)
FATAL_ERROR ((0, err, "vasprintf"));
return result;
}
static char *
format_default_settings (void)
{
return easprintf (
return xasprintf (
"--format=%s -f%s -b%d --quoting-style=%s --rmt-command=%s"
#ifdef REMOTE_SHELL
" --rsh-command=%s"
@@ -905,7 +889,7 @@ enum option_class
};
/* Table of locations of potentially conflicting options. Two options can
conflict only if they proceed from the command line. Otherwise, options
conflict only if they procede from the command line. Otherwise, options
in command line silently override those defined in TAR_OPTIONS. */
static struct option_locus *option_class[OC_MAX];
@@ -960,7 +944,6 @@ option_set_in_cl (int id)
static int
optloc_eq (struct option_locus *a, struct option_locus *b)
{
assume (a); /* Pacify GCC bug 106436. */
if (a->source != b->source)
return 0;
if (a->source == OPTS_COMMAND_LINE)
@@ -1135,7 +1118,7 @@ report_textual_dates (struct tar_args *args)
static char *
tar_help_filter (int key, const char *text, MAYBE_UNUSED void *input)
tar_help_filter (int key, const char *text, void *input)
{
struct obstack stk;
char *s;
@@ -1147,35 +1130,35 @@ tar_help_filter (int key, const char *text, MAYBE_UNUSED void *input)
break;
case 'j':
s = easprintf (_("filter the archive through %s"), BZIP2_PROGRAM);
s = xasprintf (_("filter the archive through %s"), BZIP2_PROGRAM);
break;
case 'z':
s = easprintf (_("filter the archive through %s"), GZIP_PROGRAM);
s = xasprintf (_("filter the archive through %s"), GZIP_PROGRAM);
break;
case 'Z':
s = easprintf (_("filter the archive through %s"), COMPRESS_PROGRAM);
s = xasprintf (_("filter the archive through %s"), COMPRESS_PROGRAM);
break;
case LZIP_OPTION:
s = easprintf (_("filter the archive through %s"), LZIP_PROGRAM);
s = xasprintf (_("filter the archive through %s"), LZIP_PROGRAM);
break;
case LZMA_OPTION:
s = easprintf (_("filter the archive through %s"), LZMA_PROGRAM);
s = xasprintf (_("filter the archive through %s"), LZMA_PROGRAM);
break;
case LZOP_OPTION:
s = easprintf (_("filter the archive through %s"), LZOP_PROGRAM);
s = xasprintf (_("filter the archive through %s"), LZOP_PROGRAM);
break;
case 'J':
s = easprintf (_("filter the archive through %s"), XZ_PROGRAM);
s = xasprintf (_("filter the archive through %s"), XZ_PROGRAM);
break;
case ZSTD_OPTION:
s = easprintf (_("filter the archive through %s"), ZSTD_PROGRAM);
s = xasprintf (_("filter the archive through %s"), ZSTD_PROGRAM);
break;
case ARGP_KEY_HELP_EXTRA:
@@ -1371,12 +1354,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (state->root_argp->children)
{
int i;
for (i = 0; state->root_argp->children[i].argp; i++)
state->child_inputs[i] = state->input;
}
break;
case ARGP_KEY_ARG:
/* File name or non-parsed option, because of ARGP_IN_ORDER */
name_add_name (arg);
@@ -1768,7 +1751,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case WARNING_OPTION:
set_warning_option (arg);
break;
case 'x':
set_subcommand_option (EXTRACT_SUBCOMMAND);
break;
@@ -2248,7 +2231,7 @@ parse_default_options (struct tar_args *args)
struct wordsplit ws;
struct option_locus loc = { OPTS_ENVIRON, "TAR_OPTIONS", 0, 0 };
struct option_locus *save_loc_ptr;
if (!opts)
return;
@@ -2269,7 +2252,7 @@ parse_default_options (struct tar_args *args)
abort (); /* shouldn't happen */
args->loc = save_loc_ptr;
if (name_more_files ())
USAGE_ERROR ((0, 0, _("non-option arguments in %s"), loc.name));
USAGE_ERROR ((0, 0, _("non-option arguments in %s"), loc.name));
/* Don't free consumed words */
ws.ws_wordc = 0;
}
@@ -2649,7 +2632,7 @@ decode_options (int argc, char **argv)
if (optloc_eq (preserve_order_loc, listed_incremental_loc))
option_conflict_error ("--preserve-order", "--listed-incremental");
else if (preserve_order_loc->source == OPTS_COMMAND_LINE)
listed_incremental_option = NULL;
listed_incremental_option = false;
else
same_order_option = false;
}
@@ -2714,7 +2697,7 @@ decode_options (int argc, char **argv)
if (backup_option)
{
backup_type = xget_version ("--backup", args.version_control_string);
/* No backup is needed either if explicitly disabled or if
/* No backup is needed either if explicitely disabled or if
the extracted files are not being written to disk. */
if (backup_type == no_backups || EXTRACT_OVER_PIPE)
backup_option = false;
@@ -2852,14 +2835,11 @@ main (int argc, char **argv)
if (volno_file_option)
closeout_volume_number ();
/* There is little point to freeing, as we are about to exit,
and freeing is more likely to cause than cure trouble. */
if (false)
{
free (archive_name_array);
xattrs_clear_setup ();
name_term ();
}
/* Dispose of allocated memory, and return. */
free (archive_name_array);
xattrs_clear_setup ();
name_term ();
if (exit_status == TAREXIT_FAILURE)
error (0, 0, _("Exiting with failure status due to previous errors"));
@@ -2903,7 +2883,7 @@ void
tar_stat_destroy (struct tar_stat_info *st)
{
tar_stat_close (st);
xattr_map_free (&st->xattr_map);
xheader_xattr_free (st->xattr_map, st->xattr_map_size);
free (st->orig_file_name);
free (st->file_name);
free (st->link_name);

View File

@@ -1,6 +1,6 @@
/* GNU tar Archive Format description.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -284,13 +284,6 @@ struct xattr_array
size_t xval_len;
};
struct xattr_map
{
struct xattr_array *xm_map;
size_t xm_size; /* Size of the xattr map */
size_t xm_max; /* Max. number of entries in xattr_map */
};
struct tar_stat_info
{
char *orig_file_name; /* name of file read from the archive header */
@@ -341,7 +334,8 @@ struct tar_stat_info
processed pax header parsing. Following 'path'
header (lower priority) will be ignored. */
struct xattr_map xattr_map;
size_t xattr_map_size; /* Size of the xattr map */
struct xattr_array *xattr_map;
/* Extended headers */
struct xheader xhdr;

View File

@@ -1,5 +1,5 @@
/* This file is part of GNU tar.
Copyright 2006-2023 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
@@ -493,6 +493,9 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
disp = rmp[0].rm_eo;
if (rmp[0].rm_so)
obstack_grow (&stk, input, rmp[0].rm_so);
nmatches++;
if (tf->match_number && nmatches < tf->match_number)
{
@@ -501,9 +504,6 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
continue;
}
if (rmp[0].rm_so)
obstack_grow (&stk, input, rmp[0].rm_so);
for (segm = tf->repl_head; segm; segm = segm->next)
{
switch (segm->type)

View File

@@ -1,6 +1,6 @@
/* Unlink files.
Copyright 2009-2023 Free Software Foundation, Inc.
Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
/* Update a tar archive.
Copyright 1988-2023 Free Software Foundation, Inc.
Copyright 1988-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -42,14 +42,13 @@ bool time_to_start_writing;
first part of the record. */
char *output_start;
static bool acting_as_filter;
/* Catenate file FILE_NAME to the archive without creating a header for it.
It had better be a tar file or the archive is screwed. */
static void
append_file (char *file_name)
{
int handle = openat (chdir_fd, file_name, O_RDONLY | O_BINARY);
struct stat stat_data;
if (handle < 0)
{
@@ -57,48 +56,49 @@ append_file (char *file_name)
return;
}
while (true)
if (fstat (handle, &stat_data) != 0)
stat_error (file_name);
else
{
union block *start = find_next_block ();
size_t status = full_read (handle, start->buffer,
available_space_after (start));
if (status == 0)
off_t bytes_left = stat_data.st_size;
while (bytes_left > 0)
{
if (errno == 0)
break;
read_fatal (file_name);
union block *start = find_next_block ();
size_t buffer_size = available_space_after (start);
size_t status;
char buf[UINTMAX_STRSIZE_BOUND];
if (bytes_left < buffer_size)
{
buffer_size = bytes_left;
status = buffer_size % BLOCKSIZE;
if (status)
memset (start->buffer + bytes_left, 0, BLOCKSIZE - status);
}
status = safe_read (handle, start->buffer, buffer_size);
if (status == SAFE_READ_ERROR)
read_fatal_details (file_name, stat_data.st_size - bytes_left,
buffer_size);
if (status == 0)
FATAL_ERROR ((0, 0,
ngettext ("%s: File shrank by %s byte",
"%s: File shrank by %s bytes",
bytes_left),
quotearg_colon (file_name),
STRINGIFY_BIGINT (bytes_left, buf)));
bytes_left -= status;
set_next_block_after (start + (status - 1) / BLOCKSIZE);
}
if (status == SAFE_READ_ERROR)
read_fatal (file_name);
if (status % BLOCKSIZE)
memset (start->buffer + status - status % BLOCKSIZE, 0,
BLOCKSIZE - status % BLOCKSIZE);
set_next_block_after (start + (status - 1) / BLOCKSIZE);
}
if (close (handle) != 0)
close_error (file_name);
}
/* If NAME is not a pattern, remove it from the namelist. Otherwise,
remove the FILE_NAME that matched it. Take care to look for exact
match when removing it. */
static void
remove_exact_name (struct name *name, char const *file_name)
{
if (name->is_wildcard)
{
struct name *match = name_scan (file_name, true);
name->found_count++;
if (match)
name = match;
else
return;
}
remname (name);
}
/* Implement the 'r' (add files to end of archive), and 'u' (add files
to end of archive if they aren't there, or are more up to date than
the version in the archive) commands. */
@@ -110,7 +110,6 @@ update_archive (void)
name_gather ();
open_archive (ACCESS_UPDATE);
acting_as_filter = strcmp (archive_name_array[0], "-") == 0;
xheader_forbid_global ();
while (!found_end)
@@ -136,7 +135,7 @@ update_archive (void)
archive_format = current_format;
if (subcommand_option == UPDATE_SUBCOMMAND
&& (name = name_scan (current_stat_info.file_name, false)) != NULL)
&& (name = name_scan (current_stat_info.file_name)) != NULL)
{
struct stat s;
@@ -145,10 +144,10 @@ update_archive (void)
{
if (S_ISDIR (s.st_mode))
{
char *p, *dirp = tar_savedir (current_stat_info.file_name, 1);
char *p, *dirp = tar_savedir (name->name, 1);
if (dirp)
{
namebuf_t nbuf = namebuf_create (current_stat_info.file_name);
namebuf_t nbuf = namebuf_create (name->name);
for (p = dirp; *p; p += strlen (p) + 1)
addname (namebuf_name (nbuf, p),
@@ -157,22 +156,17 @@ update_archive (void)
namebuf_free (nbuf);
free (dirp);
remove_exact_name (name, current_stat_info.file_name);
remname (name);
}
}
else if (tar_timespec_cmp (get_stat_mtime (&s),
current_stat_info.mtime)
<= 0)
{
remove_exact_name (name, current_stat_info.file_name);
}
else if (name->is_wildcard)
addname (current_stat_info.file_name,
name->change_dir, false, NULL);
remname (name);
}
}
skim_member (acting_as_filter);
skip_member ();
break;
}

View File

@@ -1,6 +1,6 @@
/* Charset handling for GNU tar.
Copyright 2004-2023 Free Software Foundation, Inc.
Copyright 2004-2021 Free Software Foundation, Inc.
This file is part of GNU tar.

View File

@@ -1,6 +1,6 @@
/* Warnings for GNU tar.
Copyright 2009-2023 Free Software Foundation, Inc.
Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -48,8 +48,6 @@ static char const *const warning_args[] = {
"xattr-write",
"record-size",
"failed-read",
"missing-zero-blocks",
"verbose",
NULL
};
@@ -78,14 +76,12 @@ static int warning_types[] = {
WARN_EXISTING_FILE,
WARN_XATTR_WRITE,
WARN_RECORD_SIZE,
WARN_FAILED_READ,
WARN_MISSING_ZERO_BLOCKS,
WARN_VERBOSE_WARNINGS,
WARN_FAILED_READ
};
ARGMATCH_VERIFY (warning_args, warning_types);
int warning_option = WARN_ALL & ~(WARN_VERBOSE_WARNINGS|WARN_MISSING_ZERO_BLOCKS);
int warning_option = WARN_ALL;
void
set_warning_option (const char *arg)

View File

@@ -1,6 +1,6 @@
/* Support for extended attributes.
Copyright (C) 2006-2023 Free Software Foundation, Inc.
Copyright (C) 2006-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -30,83 +30,6 @@
#include "xattr-at.h"
#include "selinux-at.h"
#define XATTRS_PREFIX "SCHILY.xattr."
#define XATTRS_PREFIX_LEN (sizeof XATTRS_PREFIX - 1)
void
xheader_xattr_init (struct tar_stat_info *st)
{
xattr_map_init (&st->xattr_map);
st->acls_a_ptr = NULL;
st->acls_a_len = 0;
st->acls_d_ptr = NULL;
st->acls_d_len = 0;
st->cntx_name = NULL;
}
void
xattr_map_init (struct xattr_map *map)
{
memset (map, 0, sizeof *map);
}
void
xattr_map_free (struct xattr_map *xattr_map)
{
size_t i;
for (i = 0; i < xattr_map->xm_size; i++)
{
free (xattr_map->xm_map[i].xkey);
free (xattr_map->xm_map[i].xval_ptr);
}
free (xattr_map->xm_map);
}
void
xattr_map_add (struct xattr_map *map,
const char *key, const char *val, size_t len)
{
struct xattr_array *p;
if (map->xm_size == map->xm_max)
map->xm_map = x2nrealloc (map->xm_map, &map->xm_max,
sizeof (map->xm_map[0]));
p = &map->xm_map[map->xm_size];
p->xkey = xstrdup (key);
p->xval_ptr = xmemdup (val, len + 1);
p->xval_len = len;
map->xm_size++;
}
void
xheader_xattr_add (struct tar_stat_info *st,
const char *key, const char *val, size_t len)
{
size_t klen = strlen (key);
char *xkey = xmalloc (XATTRS_PREFIX_LEN + klen + 1);
char *tmp = xkey;
tmp = stpcpy (tmp, XATTRS_PREFIX);
stpcpy (tmp, key);
xattr_map_add (&st->xattr_map, xkey, val, len);
free (xkey);
}
void
xattr_map_copy (struct xattr_map *dst, const struct xattr_map *src)
{
size_t i;
for (i = 0; i < src->xm_size; i++)
xattr_map_add (dst, src->xm_map[i].xkey,
src->xm_map[i].xval_ptr,
src->xm_map[i].xval_len);
}
struct xattrs_mask_map
{
const char **masks;
@@ -130,10 +53,6 @@ static struct
#ifdef HAVE_POSIX_ACLS
# include "acl.h"
# include <sys/acl.h>
# ifdef HAVE_ACL_LIBACL_H
# /* needed for numeric-owner support */
# include <acl/libacl.h>
# endif
#endif
#ifdef HAVE_POSIX_ACLS
@@ -285,12 +204,13 @@ fixup_extra_acl_fields (char *ptr)
static void
xattrs__acls_set (struct tar_stat_info const *st,
char const *file_name, int type,
char *ptr, bool def)
char *ptr, size_t len, bool def)
{
acl_t acl;
if (ptr)
{
/* assert (strlen (ptr) == len); */
ptr = fixup_extra_acl_fields (ptr);
acl = acl_from_text (ptr);
}
@@ -351,35 +271,21 @@ xattrs_acls_cleanup (char *val, size_t *plen)
}
static void
acls_get_text (int parentfd, const char *file_name, acl_type_t type,
char **ret_ptr, size_t * ret_len)
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;
acl_t acl;
if (!(acl = acl_get_file_at (parentfd, file_name, type)))
if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS)))
{
if (errno != ENOTSUP)
call_arg_warn ("acl_get_file_at", file_name);
return;
}
if (numeric_owner_option)
{
#ifdef HAVE_ACL_LIBACL_H
val = acl_to_any_text (acl, NULL, '\n',
TEXT_SOME_EFFECTIVE | TEXT_NUMERIC_IDS);
#else
static int warned;
if (!warned)
{
WARN ((0, 0, _("--numeric-owner is ignored for ACLs: libacl is not available")));
warned = 1;
}
#endif
}
else
val = acl_to_text (acl, NULL);
val = acl_to_text (acl, NULL);
acl_free (acl);
if (!val)
@@ -393,19 +299,34 @@ acls_get_text (int parentfd, const char *file_name, acl_type_t type,
acl_free (val);
}
static void
xattrs__acls_get_a (int parentfd, const char *file_name,
char **ret_ptr, size_t *ret_len)
{
acls_get_text (parentfd, file_name, ACL_TYPE_ACCESS, ret_ptr, ret_len);
}
/* "system.posix_acl_default" */
static void
xattrs__acls_get_d (int parentfd, char const *file_name,
struct tar_stat_info *st,
char **ret_ptr, size_t * ret_len)
{
acls_get_text (parentfd, file_name, ACL_TYPE_DEFAULT, ret_ptr, ret_len);
char *val = NULL;
acl_t acl;
if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)))
{
if (errno != ENOTSUP)
call_arg_warn ("acl_get_file_at", file_name);
return;
}
val = acl_to_text (acl, NULL);
acl_free (acl);
if (!val)
{
call_arg_warn ("acl_to_text", file_name);
return;
}
*ret_ptr = xstrdup (val);
xattrs_acls_cleanup (*ret_ptr, ret_len);
acl_free (val);
}
#endif /* HAVE_POSIX_ACLS */
@@ -448,7 +369,7 @@ acls_one_line (const char *prefix, char delim,
void
xattrs_acls_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int xisfile)
struct tar_stat_info *st, int fd, int xisfile)
{
if (acls_option > 0)
{
@@ -467,10 +388,10 @@ xattrs_acls_get (int parentfd, char const *file_name,
return;
}
xattrs__acls_get_a (parentfd, file_name,
xattrs__acls_get_a (parentfd, file_name, st,
&st->acls_a_ptr, &st->acls_a_len);
if (!xisfile)
xattrs__acls_get_d (parentfd, file_name,
xattrs__acls_get_d (parentfd, file_name, st,
&st->acls_d_ptr, &st->acls_d_len);
#endif
}
@@ -489,10 +410,10 @@ xattrs_acls_set (struct tar_stat_info const *st,
done = 1;
#else
xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS,
st->acls_a_ptr, false);
st->acls_a_ptr, st->acls_a_len, false);
if (typeflag == DIRTYPE || typeflag == GNUTYPE_DUMPDIR)
xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT,
st->acls_d_ptr, true);
st->acls_d_ptr, st->acls_d_len, true);
#endif
}
}
@@ -612,7 +533,8 @@ xattrs_xattrs_get (int parentfd, char const *file_name,
#ifdef HAVE_XATTRS
static void
xattrs__fd_set (char const *file_name, char typeflag,
xattrs__fd_set (struct tar_stat_info const *st,
char const *file_name, char typeflag,
const char *attr, const char *ptr, size_t len)
{
if (ptr)
@@ -728,7 +650,7 @@ xattrs_kw_included (const char *kw, bool archiving)
}
static bool
xattrs_kw_excluded (const char *kw)
xattrs_kw_excluded (const char *kw, bool archiving)
{
return xattrs_setup.excl.size ?
xattrs_matches_mask (kw, &xattrs_setup.excl) : false;
@@ -740,7 +662,8 @@ xattrs_kw_excluded (const char *kw)
static bool
xattrs_masked_out (const char *kw, bool archiving)
{
return xattrs_kw_included (kw, archiving) ? xattrs_kw_excluded (kw) : true;
return xattrs_kw_included (kw, archiving) ?
xattrs_kw_excluded (kw, archiving) : true;
}
void
@@ -755,14 +678,15 @@ xattrs_xattrs_set (struct tar_stat_info const *st,
WARN ((0, 0, _("XATTR support is not available")));
done = 1;
#else
size_t i;
size_t scan = 0;
if (!st->xattr_map.xm_size)
if (!st->xattr_map_size)
return;
for (i = 0; i < st->xattr_map.xm_size; i++)
for (; scan < st->xattr_map_size; ++scan)
{
char *keyword = st->xattr_map.xm_map[i].xkey + XATTRS_PREFIX_LEN;
char *keyword = st->xattr_map[scan].xkey;
keyword += strlen ("SCHILY.xattr.");
/* TODO: this 'later_run' workaround is temporary solution -> once
capabilities should become fully supported by it's API and there
@@ -778,9 +702,9 @@ xattrs_xattrs_set (struct tar_stat_info const *st,
/* we don't want to restore this keyword */
continue;
xattrs__fd_set (file_name, typeflag, keyword,
st->xattr_map.xm_map[i].xval_ptr,
st->xattr_map.xm_map[i].xval_len);
xattrs__fd_set (st, file_name, typeflag, keyword,
st->xattr_map[scan].xval_ptr,
st->xattr_map[scan].xval_len);
}
#endif
}
@@ -804,10 +728,10 @@ xattrs_print_char (struct tar_stat_info const *st, char *output)
output[1] = 0;
}
if (xattrs_option > 0 && st->xattr_map.xm_size)
for (i = 0; i < st->xattr_map.xm_size; ++i)
if (xattrs_option > 0 && st->xattr_map_size)
for (i = 0; i < st->xattr_map_size; ++i)
{
char *keyword = st->xattr_map.xm_map[i].xkey + XATTRS_PREFIX_LEN;
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
{
*output = '*';
@@ -844,16 +768,16 @@ xattrs_print (struct tar_stat_info const *st)
}
/* xattrs */
if (xattrs_option > 0 && st->xattr_map.xm_size)
if (xattrs_option > 0 && st->xattr_map_size)
{
int i;
for (i = 0; i < st->xattr_map.xm_size; ++i)
for (i = 0; i < st->xattr_map_size; ++i)
{
char *keyword = st->xattr_map.xm_map[i].xkey + XATTRS_PREFIX_LEN;
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
fprintf (stdlis, " x: %lu %s\n",
(unsigned long) st->xattr_map.xm_map[i].xval_len, keyword);
(unsigned long) st->xattr_map[i].xval_len, keyword);
}
}
}

View File

@@ -1,6 +1,6 @@
/* Support for extended attributes.
Copyright (C) 2006-2023 Free Software Foundation, Inc.
Copyright (C) 2006-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -30,7 +30,7 @@ extern void xattrs_mask_add (const char *mask, bool incl);
extern void xattrs_clear_setup (void);
extern void xattrs_acls_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int xisfile);
struct tar_stat_info *st, int fd, int xisfile);
extern void xattrs_selinux_get (int parentfd, char const *file_name,
struct tar_stat_info *st, int fd);
extern void xattrs_xattrs_get (int parentfd, char const *file_name,

View File

@@ -1,6 +1,6 @@
/* POSIX extended headers for tar.
Copyright (C) 2003-2023 Free Software Foundation, Inc.
Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -29,6 +29,7 @@
static void xheader_init (struct xheader *xhdr);
static bool xheader_protected_pattern_p (char const *pattern);
static bool xheader_protected_keyword_p (char const *keyword);
static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
/* Used by xheader_finish() */
static void code_string (char const *string, char const *keyword,
@@ -157,7 +158,7 @@ xheader_list_destroy (struct keyword_list **root)
}
}
static _Noreturn void
static void
xheader_set_single_keyword (char *kw)
{
USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));
@@ -185,7 +186,7 @@ xheader_set_keyword_equal (char *kw, char *eq)
if (eq == kw)
USAGE_ERROR ((0, 0, _("Malformed pax option: %s"), quote (kw)));
if (eq[-1] == ':')
{
p--;
@@ -305,7 +306,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
nptr = umaxtostr (n, nbuf);
len += nbuf + sizeof nbuf - 1 - nptr;
break;
default:
len += 2;
}
@@ -492,6 +493,48 @@ xheader_forbid_global (void)
USAGE_ERROR ((0, 0, _("can't update global extended header record")));
}
void
xheader_xattr_init (struct tar_stat_info *st)
{
st->xattr_map = NULL;
st->xattr_map_size = 0;
st->acls_a_ptr = NULL;
st->acls_a_len = 0;
st->acls_d_ptr = NULL;
st->acls_d_len = 0;
st->cntx_name = NULL;
}
void
xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
{
size_t scan = 0;
while (scan < xattr_map_size)
{
free (xattr_map[scan].xkey);
free (xattr_map[scan].xval_ptr);
++scan;
}
free (xattr_map);
}
static void
xheader_xattr__add (struct xattr_array **xattr_map,
size_t *xattr_map_size,
const char *key, const char *val, size_t len)
{
size_t pos = (*xattr_map_size)++;
*xattr_map = xrealloc (*xattr_map,
*xattr_map_size * sizeof(struct xattr_array));
(*xattr_map)[pos].xkey = xstrdup (key);
(*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1);
(*xattr_map)[pos].xval_len = len;
}
/* This is reversal function for xattr_encode_keyword. See comment for
xattr_encode_keyword() for more info. */
static void
@@ -529,6 +572,44 @@ xattr_decode_keyword (char *keyword)
kpl++;
}
}
void
xheader_xattr_add (struct tar_stat_info *st,
const char *key, const char *val, size_t len)
{
size_t klen = strlen (key);
char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1);
char *tmp = xkey;
tmp = stpcpy (tmp, "SCHILY.xattr.");
stpcpy (tmp, key);
xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len);
free (xkey);
}
void
xheader_xattr_copy (const struct tar_stat_info *st,
struct xattr_array **xattr_map, size_t *xattr_map_size)
{
size_t scan = 0;
*xattr_map = NULL;
*xattr_map_size = 0;
while (scan < st->xattr_map_size)
{
char *key = st->xattr_map[scan].xkey;
char *val = st->xattr_map[scan].xval_ptr;
size_t len = st->xattr_map[scan].xval_len;
xheader_xattr__add(xattr_map, xattr_map_size, key, val, len);
++scan;
}
}
/* General Interface */
@@ -557,11 +638,11 @@ static struct xhdr_tab const *
locate_handler (char const *keyword)
{
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
if (p->prefix)
{
size_t kwlen = strlen (p->keyword);
if (strncmp (p->keyword, keyword, kwlen) == 0 && keyword[kwlen] == '.')
if (strncmp (p->keyword, keyword, strlen(p->keyword)) == 0)
return p;
}
else
@@ -628,7 +709,7 @@ decode_record (struct xheader *xhdr,
if (len_max < len)
{
int len_len = len_lim - p;
ERROR ((0, 0, _("Extended header length %.*s is out of range"),
ERROR ((0, 0, _("Extended header length %*s is out of range"),
len_len, p));
return false;
}
@@ -723,7 +804,7 @@ xheader_decode (struct tar_stat_info *st)
static void
decg (void *data, char const *keyword, char const *value,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
struct keyword_list **kwl = data;
struct xhdr_tab const *tab = locate_handler (keyword);
@@ -839,7 +920,7 @@ xattr_encode_keyword(const char *keyword)
{
char c = *keyword;
if (bp + 3 /* enough for URL encoding also.. */ >= encode_buffer_size)
if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
{
encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
}
@@ -1059,12 +1140,6 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
keyword, arg));
return false;
}
if (*arg_lim)
{
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
}
*ts = t;
return true;
@@ -1121,24 +1196,24 @@ decode_num (uintmax_t *num, char const *arg, uintmax_t maxval,
}
static void
dummy_coder (MAYBE_UNUSED struct tar_stat_info const *st,
MAYBE_UNUSED char const *keyword,
MAYBE_UNUSED struct xheader *xhdr,
MAYBE_UNUSED void const *data)
dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
char const *keyword __attribute__ ((unused)),
struct xheader *xhdr __attribute__ ((unused)),
void const *data __attribute__ ((unused)))
{
}
static void
dummy_decoder (MAYBE_UNUSED struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
MAYBE_UNUSED char const *arg,
MAYBE_UNUSED size_t size)
dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
char const *keyword __attribute__ ((unused)),
char const *arg __attribute__ ((unused)),
size_t size __attribute__((unused)))
{
}
static void
atime_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_time (st->atime, keyword, xhdr);
}
@@ -1147,7 +1222,7 @@ static void
atime_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
struct timespec ts;
if (decode_time (&ts, arg, keyword))
@@ -1156,7 +1231,7 @@ atime_decoder (struct tar_stat_info *st,
static void
gid_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_signed_num (st->stat.st_gid, keyword,
TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t), xhdr);
@@ -1166,7 +1241,7 @@ static void
gid_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
intmax_t u;
if (decode_signed_num (&u, arg, TYPE_MINIMUM (gid_t),
@@ -1176,39 +1251,39 @@ gid_decoder (struct tar_stat_info *st,
static void
gname_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_string (st->gname, keyword, xhdr);
}
static void
gname_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
decode_string (&st->gname, arg);
}
static void
linkpath_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_string (st->link_name, keyword, xhdr);
}
static void
linkpath_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
decode_string (&st->link_name, arg);
}
static void
ctime_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_time (st->ctime, keyword, xhdr);
}
@@ -1217,7 +1292,7 @@ static void
ctime_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
struct timespec ts;
if (decode_time (&ts, arg, keyword))
@@ -1236,7 +1311,7 @@ static void
mtime_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
struct timespec ts;
if (decode_time (&ts, arg, keyword))
@@ -1245,7 +1320,7 @@ mtime_decoder (struct tar_stat_info *st,
static void
path_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_string (st->file_name, keyword, xhdr);
}
@@ -1253,20 +1328,17 @@ path_coder (struct tar_stat_info const *st, char const *keyword,
static void
raw_path_decoder (struct tar_stat_info *st, char const *arg)
{
if (*arg)
{
decode_string (&st->orig_file_name, arg);
decode_string (&st->file_name, arg);
st->had_trailing_slash = strip_trailing_slashes (st->file_name);
}
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,
MAYBE_UNUSED char const *keyword,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
if (! st->sparse_name_done)
raw_path_decoder (st, arg);
@@ -1274,9 +1346,9 @@ path_decoder (struct tar_stat_info *st,
static void
sparse_path_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
st->sparse_name_done = true;
raw_path_decoder (st, arg);
@@ -1284,7 +1356,7 @@ sparse_path_decoder (struct tar_stat_info *st,
static void
size_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_num (st->stat.st_size, keyword, xhdr);
}
@@ -1293,7 +1365,7 @@ static void
size_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
@@ -1302,7 +1374,7 @@ size_decoder (struct tar_stat_info *st,
static void
uid_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_signed_num (st->stat.st_uid, keyword,
TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t), xhdr);
@@ -1312,7 +1384,7 @@ static void
uid_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
intmax_t u;
if (decode_signed_num (&u, arg, TYPE_MINIMUM (uid_t),
@@ -1322,16 +1394,16 @@ uid_decoder (struct tar_stat_info *st,
static void
uname_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data __attribute__ ((unused)))
{
code_string (st->uname, keyword, xhdr);
}
static void
uname_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
decode_string (&st->uname, arg);
}
@@ -1347,7 +1419,7 @@ static void
sparse_size_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
@@ -1360,7 +1432,7 @@ sparse_size_decoder (struct tar_stat_info *st,
static void
sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr,
MAYBE_UNUSED void const *data)
void const *data __attribute__ ((unused)))
{
code_num (st->sparse_map_avail, keyword, xhdr);
}
@@ -1369,7 +1441,7 @@ static void
sparse_numblocks_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, SIZE_MAX, keyword))
@@ -1392,7 +1464,7 @@ static void
sparse_offset_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
@@ -1417,7 +1489,7 @@ static void
sparse_numbytes_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
@@ -1434,7 +1506,7 @@ static void
sparse_map_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
int offset = 1;
struct sp_array e;
@@ -1508,7 +1580,7 @@ sparse_map_decoder (struct tar_stat_info *st,
}
static void
dumpdir_coder (MAYBE_UNUSED struct tar_stat_info const *st, char const *keyword,
dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
xheader_print_n (xhdr, keyword, data, dumpdir_size (data));
@@ -1516,7 +1588,7 @@ dumpdir_coder (MAYBE_UNUSED struct tar_stat_info const *st, char const *keyword,
static void
dumpdir_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size)
{
@@ -1525,25 +1597,23 @@ dumpdir_decoder (struct tar_stat_info *st,
}
static void
volume_label_coder (MAYBE_UNUSED struct tar_stat_info const *st,
char const *keyword,
volume_label_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
code_string (data, keyword, xhdr);
}
static void
volume_label_decoder (MAYBE_UNUSED struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
volume_label_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
decode_string (&volume_label, arg);
}
static void
volume_size_coder (MAYBE_UNUSED struct tar_stat_info const *st,
char const *keyword,
volume_size_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
off_t const *v = data;
@@ -1551,9 +1621,9 @@ volume_size_coder (MAYBE_UNUSED struct tar_stat_info const *st,
}
static void
volume_size_decoder (MAYBE_UNUSED struct tar_stat_info *st,
volume_size_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg, MAYBE_UNUSED size_t size)
char const *arg, size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
@@ -1562,8 +1632,7 @@ volume_size_decoder (MAYBE_UNUSED struct tar_stat_info *st,
/* FIXME: Merge with volume_size_coder */
static void
volume_offset_coder (MAYBE_UNUSED struct tar_stat_info const *st,
char const *keyword,
volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
off_t const *v = data;
@@ -1571,9 +1640,9 @@ volume_offset_coder (MAYBE_UNUSED struct tar_stat_info const *st,
}
static void
volume_offset_decoder (MAYBE_UNUSED struct tar_stat_info *st,
volume_offset_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg, MAYBE_UNUSED size_t size)
char const *arg, size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
@@ -1581,40 +1650,38 @@ volume_offset_decoder (MAYBE_UNUSED struct tar_stat_info *st,
}
static void
volume_filename_decoder (MAYBE_UNUSED struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
volume_filename_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
MAYBE_UNUSED size_t size)
size_t size __attribute__((unused)))
{
decode_string (&continued_file_name, arg);
}
static void
xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data)
{
code_string (st->cntx_name, keyword, xhdr);
}
static void
xattr_selinux_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword, char const *arg,
MAYBE_UNUSED size_t size)
char const *keyword, char const *arg, size_t size)
{
decode_string (&st->cntx_name, arg);
}
static void
xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data)
{
xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len);
}
static void
xattr_acls_a_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword,
char const *arg, size_t size)
char const *keyword, char const *arg, size_t size)
{
st->acls_a_ptr = xmemdup (arg, size + 1);
st->acls_a_len = size;
@@ -1622,15 +1689,14 @@ xattr_acls_a_decoder (struct tar_stat_info *st,
static void
xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data)
{
xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len);
}
static void
xattr_acls_d_decoder (struct tar_stat_info *st,
MAYBE_UNUSED char const *keyword, char const *arg,
size_t size)
char const *keyword, char const *arg, size_t size)
{
st->acls_d_ptr = xmemdup (arg, size + 1);
st->acls_d_len = size;
@@ -1640,31 +1706,35 @@ static void
xattr_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
size_t n = *(size_t *)data;
struct xattr_array *xattr_map = st->xattr_map;
const size_t *off = data;
xheader_print_n (xhdr, keyword,
st->xattr_map.xm_map[n].xval_ptr,
st->xattr_map.xm_map[n].xval_len);
xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
}
static void
xattr_decoder (struct tar_stat_info *st,
char const *keyword, char const *arg, size_t size)
{
char *xkey;
char *xstr, *xkey;
/* copy keyword */
xkey = xstrdup (keyword);
size_t klen_raw = strlen (keyword);
xkey = alloca (klen_raw + 1);
memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
/* copy value */
xstr = alloca (size + 1);
memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
xattr_decode_keyword (xkey);
xattr_map_add (&st->xattr_map, xkey, arg, size);
free (xkey);
xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
}
static void
sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data)
{
code_num (st->sparse_major, keyword, xhdr);
}
@@ -1673,7 +1743,7 @@ static void
sparse_major_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
@@ -1682,7 +1752,7 @@ sparse_major_decoder (struct tar_stat_info *st,
static void
sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, MAYBE_UNUSED void const *data)
struct xheader *xhdr, void const *data)
{
code_num (st->sparse_minor, keyword, xhdr);
}
@@ -1691,7 +1761,7 @@ static void
sparse_minor_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
MAYBE_UNUSED size_t size)
size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))

View File

@@ -1,6 +1,6 @@
# Makefile for GNU tar regression tests.
# Copyright 1996-2023 Free Software Foundation, Inc.
# Copyright 1996-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -81,7 +81,6 @@ TESTSUITE_AT = \
delete03.at\
delete04.at\
delete05.at\
delete06.at\
difflink.at\
exclude.at\
exclude01.at\
@@ -124,7 +123,6 @@ TESTSUITE_AT = \
extrac22.at\
extrac23.at\
extrac24.at\
extrac25.at\
filerem01.at\
filerem02.at\
dirrem01.at\
@@ -254,7 +252,6 @@ TESTSUITE_AT = \
update01.at\
update02.at\
update03.at\
update04.at\
volsize.at\
volume.at\
verbose.at\
@@ -277,7 +274,6 @@ TESTSUITE_AT = \
xattr05.at\
xattr06.at\
xattr07.at\
xattr08.at\
acls01.at\
acls02.at\
acls03.at\
@@ -331,7 +327,4 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/lib\
-DLOCALEDIR=\"$(localedir)\"
LDADD = ../gnu/libgnu.a\
$(LIB_ACL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)\
$(LIB_GETRANDOM) $(LIB_HARD_LOCALE) $(FILE_HAS_ACL_LIB) $(LIB_MBRTOWC)\
$(LIB_SELINUX) $(LIB_SETLOCALE_NULL)
LDADD = ../gnu/libgnu.a $(LIBINTL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright 2006-2023 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-2023 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-2023 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-2023 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 2006-2023 Free Software Foundation, Inc.
# Copyright 2006-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

@@ -1,5 +1,5 @@
# This file is part of test suite for GNU tar. -*- Autotest -*-
# Copyright 2015-2023 Free Software Foundation, Inc.
# Copyright 2015-2021 Free Software Foundation, Inc.
#
# GNU tar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013-2023 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 2016-2023 Free Software Foundation, Inc.
# Copyright 2016-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 2004-2023 Free Software Foundation, Inc.
# Copyright 2004-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 2005-2023 Free Software Foundation, Inc.
# Copyright 2005-2021 Free Software Foundation, Inc.
# This file is part of GNU tar.

View File

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