Compare commits
1 Commits
v1.35
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf28f95b3a |
44
.gitignore
vendored
44
.gitignore
vendored
@@ -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
|
||||
|
||||
8
COPYING
8
COPYING
@@ -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>.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
66
NEWS
@@ -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
2
README
@@ -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.
|
||||
|
||||
|
||||
32
README-alpha
32
README-alpha
@@ -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.
|
||||
|
||||
|
||||
@@ -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
2
TODO
@@ -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.
|
||||
|
||||
|
||||
@@ -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)])
|
||||
|
||||
@@ -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
|
||||
|
||||
54
configure.ac
54
configure.ac
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
@@ -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.
|
||||
|
||||
12
doc/fdl.texi
12
doc/fdl.texi
@@ -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:
|
||||
|
||||
|
||||
512
doc/gendocs.sh
512
doc/gendocs.sh
@@ -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
174
doc/gendocs_template
Normal file → Executable 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 & GNU inquiries to
|
||||
<a href="mailto:gnu@gnu.org"><gnu@gnu.org></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%%"><%%EMAIL%%></a>.</p>
|
||||
<p>
|
||||
Please send FSF & 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 © 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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
104
doc/tar.1
@@ -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>
|
||||
|
||||
507
doc/tar.texi
507
doc/tar.texi
@@ -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}})
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
2
gnulib
Submodule gnulib updated: 46f9c21a08...30820c2d7c
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
183
lib/wordsplit.c
183
lib/wordsplit.c
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
2
paxutils
2
paxutils
Submodule paxutils updated: 481bae1105...b7da0d659e
22
po/.gitignore
vendored
22
po/.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
128
src/buffer.c
128
src/buffer.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
74
src/common.h
74
src/common.h
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
142
src/create.c
142
src/create.c
@@ -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);
|
||||
|
||||
72
src/delete.c
72
src/delete.c
@@ -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 (¤t_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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
625
src/extract.c
625
src/extract.c
@@ -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, ¤t_stat_info,
|
||||
mode | S_IWUSR, typeflag))
|
||||
< 0)
|
||||
|| ((fd = open_output_file (file_name, typeflag, mode,
|
||||
file_created, ¤t_mode,
|
||||
¤t_mode_mask))
|
||||
< 0))
|
||||
int file_created = 0;
|
||||
if (set_xattr (file_name, ¤t_stat_info, invert_permissions,
|
||||
typeflag, &file_created))
|
||||
return 1;
|
||||
|
||||
while ((fd = open_output_file (file_name, typeflag, mode,
|
||||
file_created, ¤t_mode,
|
||||
¤t_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, ¤t_stat_info.xattr_map);
|
||||
xheader_xattr_copy (¤t_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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
38
src/list.c
38
src/list.c
@@ -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 (¤t_stat_info);
|
||||
|
||||
if (current_stat_info.is_sparse)
|
||||
sparse_skim_file (¤t_stat_info, must_copy);
|
||||
sparse_skip_file (¤t_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 ();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
45
src/misc.c
45
src/misc.c
@@ -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;
|
||||
|
||||
65
src/names.c
65
src/names.c
@@ -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;
|
||||
}
|
||||
|
||||
105
src/sparse.c
105
src/sparse.c
@@ -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 (¤t_stat_info, _("Size differs"));
|
||||
report_difference (¤t_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));
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
110
src/system.c
110
src/system.c
@@ -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);
|
||||
|
||||
88
src/tar.c
88
src/tar.c
@@ -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);
|
||||
|
||||
12
src/tar.h
12
src/tar.h
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
90
src/update.c
90
src/update.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
188
src/xattrs.c
188
src/xattrs.c
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
268
src/xheader.c
268
src/xheader.c
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user