Compare commits
64 Commits
release_1_
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8e0b6cb7a | ||
|
|
338add8d10 | ||
|
|
46b07a52f9 | ||
|
|
a06b3a29fb | ||
|
|
6f02669c7b | ||
|
|
e1e1f87eb4 | ||
|
|
bffe1074aa | ||
|
|
9a3e8a6f43 | ||
|
|
a0fd0d95e2 | ||
|
|
3925776b41 | ||
|
|
762be4f2bd | ||
|
|
b7899bb121 | ||
|
|
6e196273a4 | ||
|
|
bdb9de4b1e | ||
|
|
c4acbdaa97 | ||
|
|
c3fa22fc80 | ||
|
|
706bd01915 | ||
|
|
0057cd6803 | ||
|
|
45cf3a7426 | ||
|
|
28f2669b15 | ||
|
|
166b7c7d02 | ||
|
|
cd91cd3c62 | ||
|
|
cac45fffc5 | ||
|
|
0c6c288b53 | ||
|
|
87240ee7c4 | ||
|
|
84a55f12e5 | ||
|
|
a7e9b6a17b | ||
|
|
f0ceef8596 | ||
|
|
63e092548a | ||
|
|
7cb84c25ee | ||
|
|
4dfcd6c054 | ||
|
|
2947023d27 | ||
|
|
92773d860f | ||
|
|
dccb3806a6 | ||
|
|
0d8e324912 | ||
|
|
cef4d5e838 | ||
|
|
ba954ea1e1 | ||
|
|
006c1efbe8 | ||
|
|
aeffa4f266 | ||
|
|
829b3feb26 | ||
|
|
88347995b2 | ||
|
|
acd833fb98 | ||
|
|
51aee274e8 | ||
|
|
2b1bffbad6 | ||
|
|
df59690240 | ||
|
|
1bcbbcf1ff | ||
|
|
ac5288c1ac | ||
|
|
67a1a0eac5 | ||
|
|
471c0f76cd | ||
|
|
755c246588 | ||
|
|
5944f452b0 | ||
|
|
f74cab3a93 | ||
|
|
01c4475b17 | ||
|
|
b7d206cb1e | ||
|
|
c30c4ffb9f | ||
|
|
b216fed634 | ||
|
|
0d6720288b | ||
|
|
da760e3faa | ||
|
|
af30244849 | ||
|
|
be34933b63 | ||
|
|
8f390db92f | ||
|
|
705fab49eb | ||
|
|
f14558de94 | ||
|
|
67cad0792b |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -11,21 +11,21 @@
|
||||
ABOUT-NLS
|
||||
ChangeLog
|
||||
INSTALL
|
||||
Make.rules
|
||||
Makefile
|
||||
Makefile.in
|
||||
Make.rules
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
build-aux/
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
gnu
|
||||
gnulib
|
||||
libtool
|
||||
m4
|
||||
paxutils
|
||||
stamp-h1
|
||||
build-aux/
|
||||
gnu
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ EXTRA_DIST = ChangeLog.1 Make.rules
|
||||
SUBDIRS = doc gnu lib rmt src scripts po tests
|
||||
|
||||
dist-hook:
|
||||
$(MAKE) changelog_dir=$(distdir) make-ChangeLog
|
||||
$(MAKE) changelog_dir=$(distdir) ChangeLog
|
||||
-rm -f $(distdir).cpio
|
||||
find $(distdir) | cpio -Hcrc -o | \
|
||||
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
|
||||
|
||||
112
NEWS
112
NEWS
@@ -1,6 +1,114 @@
|
||||
GNU tar NEWS - User visible changes. 2009-03-05
|
||||
GNU tar NEWS - User visible changes. 2010-03-10
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
version 1.23 - Sergey Poznyakoff, 2010-03-10
|
||||
|
||||
* Record size autodetection
|
||||
|
||||
When listing or extracting archives, the actual record size is
|
||||
reported only if the archive is read from a device (as opposed
|
||||
to regular files and pipes).
|
||||
|
||||
* Seekable archives
|
||||
|
||||
When a read-only operation (e.g. --list or --extract) is requested
|
||||
on a regular file, tar attemtps to speed up accesses by using lseek.
|
||||
|
||||
* New command line option `--warning'
|
||||
|
||||
The `--warning' command line option allows to suppress or enable
|
||||
particular warning messages during `tar' run. It takes a single
|
||||
argument (a `keyword'), identifying the class of warning messages
|
||||
to affect. If the argument is prefixed with `no-', such warning
|
||||
messages are suppressed. For example,
|
||||
|
||||
tar --warning=no-alone-zero-block -x -f archive
|
||||
|
||||
suppresses the output of `A lone zero block' diagnostics, which is
|
||||
normally issued if `archive' ends with a single block of zeros.
|
||||
|
||||
See Tar Manual, section 3.9 "Controlling Warning Messages", for a
|
||||
detailed discussion.
|
||||
|
||||
* New command line option `--level'
|
||||
|
||||
The `--level=N' option sets the incremental dump level N. It
|
||||
is valid when used in conjunction with the -c and --listed-incremental
|
||||
options. So far the only meaningful value for N is 0. The
|
||||
`--level=0' option forces creating the level 0 dump, by truncating
|
||||
the snapshot file if it exists.
|
||||
|
||||
* Files removed during incremental dumps
|
||||
|
||||
If a file or directory is removed while incremental dump is
|
||||
in progress, tar exact actions depend on whether this file
|
||||
was explicitly listed in the command line, or was found
|
||||
during file system scan.
|
||||
|
||||
If the file was explicitly listed in the command line, tar
|
||||
issues error message and exits with the code 2, meaning
|
||||
fatal error.
|
||||
|
||||
Otherwise, if the file was found during the file system scan,
|
||||
tar issues a warning, saying "File removed before we read it",
|
||||
and sets exit code to 1, which means "some files differ".
|
||||
If the --warning=no-file-removed option is given, no warning
|
||||
is issued and exit code remains 0.
|
||||
|
||||
* Modification times of PAX extended headers.
|
||||
|
||||
Modification times in ustar header blocks of extended headers
|
||||
are set to mtimes of the corresponding archive members. This
|
||||
can be overridden by the
|
||||
|
||||
--pax-opion='exthdr.mtime=STRING'
|
||||
|
||||
command line option. The STRING is either number of seconds since
|
||||
the Epoch or a `Time reference' (see below).
|
||||
|
||||
Modification times in ustar header blocks of global extended
|
||||
headers are set to the time when tar was invoked.
|
||||
|
||||
This can be overridden by the
|
||||
|
||||
--pax-opion='globexthdr.mtime=STRING'
|
||||
|
||||
command line option. The STRING is either number of seconds since
|
||||
the Epoch or a `Time reference' (see below).
|
||||
|
||||
* Time references in --pax-option argument.
|
||||
|
||||
Any value from the --pax-option argument that is enclosed in a pair
|
||||
of curly braces represents a time reference. The string between the
|
||||
braces is understood either as a textual time representation, as described in
|
||||
chapter 7, "Date input formats", of the Tar manual, or as a name of
|
||||
an existing file, starting with `/' or `.'. In the latter
|
||||
case, it is replaced with the modification time of that file.
|
||||
|
||||
* Environment of --to-command script.
|
||||
|
||||
The environment passed to the --to-command script is extended with
|
||||
the following variables:
|
||||
|
||||
TAR_VERSION GNU tar version number
|
||||
TAR_ARCHIVE The name of the archive
|
||||
TAR_VOLUME Ordinal number of the volume
|
||||
TAR_FORMAT Format of the archive
|
||||
TAR_BLOCKING_FACTOR Current blocking factor
|
||||
|
||||
* Bugfixes
|
||||
** Fix handling of hard link targets by -c --transform.
|
||||
** Fix hard links recognition with -c --remove-files.
|
||||
** Fix restoring files from backup (debian bug #508199).
|
||||
** Correctly restore modes and permissions on existing directories.
|
||||
** The --remove-files option removes files only if they were
|
||||
succesfully stored in the archive.
|
||||
** Fix storing and listing of the volume labels in POSIX format.
|
||||
** Improve algorithm for splitting long file names (ustar
|
||||
format).
|
||||
** Fix possible memory overflow in the rmt client code (CVE-2010-0624).
|
||||
|
||||
|
||||
version 1.22 - Sergey Poznyakoff, 2009-03-05
|
||||
|
||||
@@ -1091,7 +1199,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
|
||||
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
|
||||
4
THANKS
4
THANKS
@@ -70,6 +70,7 @@ Burkhard Plache plache@krusty.optimax.ns.ca
|
||||
Calvin Cliff cliff@trifid.astro.ucla.edu
|
||||
Cameron Elliott cam@mvbms.mvbms.com
|
||||
Carl Streeter streeter@cae.wisc.edu
|
||||
Carl Worth cworth@cworth.org
|
||||
Carsten Heyl heyl@nads.de
|
||||
Catrin Urbanneck cur@gppc.de
|
||||
Cesar Romani romani@ifm.uni-hamburg.de
|
||||
@@ -132,6 +133,7 @@ David Steiner dsteiner@ispa.uni-osnabrueck.de
|
||||
David Taylor taylor@think.com
|
||||
Dean Gaudet dgaudet@watdragon.uwaterloo.ca
|
||||
Demizu Noritoshi nori-d@is.aist-nara.ac.jp
|
||||
Denis Excoffier denis.excoffier@airbus.com
|
||||
Denis Fortin fortin@acm.org
|
||||
Dennis Pixton dennis@math.binghamton.edu
|
||||
Dick Streefland dicks@tasking.nl
|
||||
@@ -367,6 +369,7 @@ Olaf Schlueter olaf@toppoint.de
|
||||
Olaf Wucknitz owucknitz@hs.uni-hamburg.de
|
||||
Oliver Trepte oliver@fysik4.kth.se
|
||||
Olivier Roussel roussel@lifl.fr
|
||||
Ondřej Vašík ovasik@redhat.com
|
||||
Oswald P. Backus IV backus@lks.csi.com
|
||||
Pascal Meheut pascal@cnam.cnam.fr
|
||||
Patrick Fulconis fulco@sig.uvsq.fr
|
||||
@@ -388,6 +391,7 @@ Peter Fox fox@gec-mi-at.co.uk
|
||||
Peter Kutschera peter@zditr1.arcs.ac.at
|
||||
Peter Seebach seebs@taniemarie.solon.com
|
||||
Phil Hands phil@hands.com
|
||||
Phil Proudman phil@proudman51.freeserve.co.uk
|
||||
Philippe Defert defert@cern.ch
|
||||
Piercarlo Grandi piercarl@sabi.demon.co.uk
|
||||
Pierce Cantrell cantrell@ee.tamu.edu
|
||||
|
||||
26
acinclude.m4
Normal file
26
acinclude.m4
Normal file
@@ -0,0 +1,26 @@
|
||||
dnl Special Autoconf macros for GNU Tar -*- autoconf -*-
|
||||
dnl Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl GNU tar is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 3, or (at your option)
|
||||
dnl any later version.
|
||||
dnl
|
||||
dnl GNU tar is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
dnl GNU General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License along
|
||||
dnl with GNU tar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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,
|
||||
AC_HELP_STRING([--with-]$1[=PROG],
|
||||
[use PROG as ]$1[ compressor program]),
|
||||
[tar_compr_var=${withval}],
|
||||
[tar_compr_var=m4_if($2,,$1,$2)])
|
||||
AC_DEFINE_UNQUOTED(tar_compr_define, "$tar_compr_var",
|
||||
[Define to the program name of ]$1[ compressor program])])
|
||||
@@ -415,6 +415,7 @@ symlink_to_dir()
|
||||
/*) ;;
|
||||
*)
|
||||
case /$dst/ in
|
||||
/./*) ;;
|
||||
*//* | */../* | */./* | /*/*/*/*/*/)
|
||||
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
|
||||
exit 1;;
|
||||
|
||||
20
configure.ac
20
configure.ac
@@ -1,7 +1,8 @@
|
||||
# Configure template for GNU tar. -*- autoconf -*-
|
||||
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
|
||||
@@ -18,12 +19,15 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AC_INIT([GNU tar], [1.22], [bug-tar@gnu.org])
|
||||
AC_INIT([GNU tar], [1.23], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_PREREQ([2.60])
|
||||
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
|
||||
AC_PREREQ([2.63])
|
||||
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-shar std-options silent-rules])
|
||||
|
||||
# Enable silent rules by default:
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_EXEEXT
|
||||
@@ -121,6 +125,14 @@ else
|
||||
[Define to the full path of your rsh, if any.])
|
||||
fi
|
||||
|
||||
TAR_COMPR_PROGRAM(compress)
|
||||
TAR_COMPR_PROGRAM(gzip)
|
||||
TAR_COMPR_PROGRAM(bzip2)
|
||||
TAR_COMPR_PROGRAM(lzip)
|
||||
TAR_COMPR_PROGRAM(lzma)
|
||||
TAR_COMPR_PROGRAM(lzop)
|
||||
TAR_COMPR_PROGRAM(xz)
|
||||
|
||||
AC_MSG_CHECKING(for default archive format)
|
||||
|
||||
AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],
|
||||
|
||||
4
doc/.gitignore
vendored
4
doc/.gitignore
vendored
@@ -1,4 +1,6 @@
|
||||
genfile.texi
|
||||
getdate.texi
|
||||
header.texi
|
||||
manual
|
||||
stamp-vti
|
||||
tar.aux
|
||||
@@ -22,5 +24,3 @@ tar.toc
|
||||
tar.tp
|
||||
tar.vr
|
||||
version.texi
|
||||
genfile.texi
|
||||
header.texi
|
||||
|
||||
@@ -59,25 +59,28 @@ check-format:
|
||||
fi
|
||||
|
||||
check-options:
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
|
||||
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
$(top_builddir)/src/tar --usage | \
|
||||
sed -n 's/^\[--\([^]\=\[]*\).*/\1/p' | sort | uniq > opts.$$$$;\
|
||||
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
|
||||
$(info_TEXINFOS) | \
|
||||
sed -n '/^@macro/,/^@end macro/d;s/@opindex *\([^@,]*\).*/\1/p' \
|
||||
| sort | uniq > docs.$$$$;\
|
||||
(echo 'Not documented options:';\
|
||||
join -v1 opts.$$$$ docs.$$$$;\
|
||||
echo 'Non-existing options:';\
|
||||
join -v2 opts.$$$$ docs.$$$$) > report.$$$$;\
|
||||
rm opts.$$$$ docs.$$$$;\
|
||||
if [ -n "`sed '1,2d' report.$$$$`" ]; then \
|
||||
cat report.$$$$;\
|
||||
rm report.$$$$;\
|
||||
exit 1;\
|
||||
fi;\
|
||||
rm report.$$$$
|
||||
status=0;\
|
||||
join -v1 opts.$$$$ docs.$$$$ > report.$$$$;\
|
||||
if test -s report.$$$$; then \
|
||||
echo 'Not documented options:'; \
|
||||
cat report.$$$$; \
|
||||
status=1; \
|
||||
fi; \
|
||||
join -v2 opts.$$$$ docs.$$$$ > report.$$$$;\
|
||||
if test -s report.$$$$; then \
|
||||
echo 'Non-existing options:';\
|
||||
cat report.$$$$; \
|
||||
status=1; \
|
||||
fi; \
|
||||
rm opts.$$$$ docs.$$$$ report.$$$$;\
|
||||
test $$status -ne 0 && exit $$status
|
||||
|
||||
check-refs:
|
||||
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
|
||||
|
||||
@@ -23,14 +23,14 @@ snapshots only in format 2.
|
||||
This appendix describes all three formats in detail.
|
||||
|
||||
@enumerate 0
|
||||
@cindex format 0, snapshot file
|
||||
@cindex format 0, snapshot file
|
||||
@cindex snapshot file, format 0
|
||||
@item
|
||||
@item
|
||||
@samp{Format 0} snapshot file begins with a line containing a
|
||||
decimal number that represents a @acronym{UNIX} timestamp of the
|
||||
beginning of the last archivation. This line is followed by directory
|
||||
metadata descriptions, one per line. Each description has the
|
||||
following format:
|
||||
following format:
|
||||
|
||||
@smallexample
|
||||
@var{nfs}@var{dev} @var{inode} @var{name}
|
||||
@@ -55,9 +55,9 @@ Name of the directory. Any special characters (white-space,
|
||||
backslashes, etc.) are quoted.
|
||||
@end table
|
||||
|
||||
@cindex format 1, snapshot file
|
||||
@cindex format 1, snapshot file
|
||||
@cindex snapshot file, format 1
|
||||
@item
|
||||
@item
|
||||
@samp{Format 1} snapshot file begins with a line specifying the
|
||||
format of the file. This line has the following structure:
|
||||
|
||||
@@ -69,7 +69,7 @@ format of the file. This line has the following structure:
|
||||
where @var{tar-version} is the version number of @GNUTAR{}
|
||||
implementation that created this snapshot, and
|
||||
@var{incr-format-version} is the version number of the snapshot format
|
||||
(in this case @samp{1}).
|
||||
(in this case @samp{1}).
|
||||
|
||||
Next line contains two decimal numbers, representing the
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
@@ -89,11 +89,11 @@ modification time of this directory with nanosecond precision;
|
||||
@var{nfs}, @var{dev}, @var{inode} and @var{name} have the same meaning
|
||||
as with @samp{format 0}.
|
||||
|
||||
@cindex format 2, snapshot file
|
||||
@cindex format 2, snapshot file
|
||||
@cindex snapshot file, format 2
|
||||
@item
|
||||
@FIXME{}
|
||||
A snapshot file begins with a format identifier, as described for
|
||||
@item
|
||||
@samp{Format 2} snapshot file begins with a format identifier, as described for
|
||||
version 1, e.g.:
|
||||
|
||||
@smallexample
|
||||
@@ -109,7 +109,7 @@ snapshot is a binary file.
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
second one is the number of nanoseconds, since the beginning of the
|
||||
epoch. These are followed by arbitrary number of directory records.
|
||||
|
||||
|
||||
Each @dfn{directory record} contains a set of metadata describing a
|
||||
particular directory. Parts of a directory record are delimited with
|
||||
@acronym{ASCII} 0 characters. The following table describes each
|
||||
@@ -124,11 +124,11 @@ an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
|
||||
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
|
||||
@item dev-no @tab Number @tab Device number;
|
||||
@item i-no @tab Number @tab I-node number;
|
||||
@item name @tab String @tab Directory name; In contrast to the
|
||||
previous versions it is not quoted.
|
||||
@item name @tab String @tab Directory name; in contrast to the
|
||||
previous versions it is not quoted;
|
||||
@item contents @tab Dumpdir @tab Contents of the directory;
|
||||
@xref{Dumpdir}, for a description of its format.
|
||||
@item
|
||||
@item
|
||||
@end multitable
|
||||
|
||||
Dumpdirs stored in snapshot files contain only records of types
|
||||
@@ -138,4 +138,3 @@ previous versions it is not quoted.
|
||||
|
||||
@c End of snapshot.texi
|
||||
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@ The support for sparse files in @GNUTAR{} has a long history. The
|
||||
earliest version featuring this support that I was able to find was 1.09,
|
||||
released in November, 1990. The format introduced back then is called
|
||||
@dfn{old GNU} sparse format and in spite of the fact that its design
|
||||
contained many flaws, it was the only format @GNUTAR{} supported
|
||||
contained many flaws, it was the only format @GNUTAR{} supported
|
||||
until version 1.14 (May, 2004), which introduced initial support for
|
||||
sparse archives in @acronym{PAX} archives (@pxref{posix}). This
|
||||
format was not free from design flows, either and it was subsequently
|
||||
format was not free from design flaws, either and it was subsequently
|
||||
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
|
||||
2006).
|
||||
2006).
|
||||
|
||||
In addition to GNU sparse format, @GNUTAR{} is able to read and
|
||||
extract sparse files archived by @command{star}.
|
||||
@@ -37,7 +37,7 @@ The following subsections describe each format in detail.
|
||||
|
||||
@cindex sparse formats, Old GNU
|
||||
@cindex Old GNU sparse format
|
||||
The format introduced some time around 1990 (v. 1.09). It was
|
||||
The format introduced in November 1990 (v. 1.09) was
|
||||
designed on top of standard @code{ustar} headers in such an
|
||||
unfortunate way that some of its fields overwrote fields required by
|
||||
POSIX.
|
||||
@@ -61,7 +61,7 @@ extension sparse header follows, @code{0} otherwise.
|
||||
@end multitable
|
||||
|
||||
Each of @code{sparse_header} object at offset 386 describes a single
|
||||
data chunk. It has the following structure:
|
||||
data chunk. It has the following structure:
|
||||
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.60
|
||||
@headitem Offset @tab Size @tab Data type @tab Contents
|
||||
@@ -78,7 +78,7 @@ the following structure:
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
|
||||
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
|
||||
@item 0 @tab 21 @tab sp @tab @code{sparse_header} @tab
|
||||
(21 entires) File map.
|
||||
(21 entries) File map.
|
||||
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
|
||||
extension sparse header follows, or @code{0} otherwise.
|
||||
@end multitable
|
||||
@@ -97,19 +97,19 @@ versions 1.14--1.15.1. The sparse file map is kept in extended
|
||||
@table @code
|
||||
@vrindex GNU.sparse.size, extended header variable
|
||||
@item GNU.sparse.size
|
||||
Real size of the stored file
|
||||
Real size of the stored file;
|
||||
|
||||
@item GNU.sparse.numblocks
|
||||
@vrindex GNU.sparse.numblocks, extended header variable
|
||||
Number of blocks in the sparse map
|
||||
Number of blocks in the sparse map;
|
||||
|
||||
@item GNU.sparse.offset
|
||||
@vrindex GNU.sparse.offset, extended header variable
|
||||
Offset of the data block
|
||||
Offset of the data block;
|
||||
|
||||
@item GNU.sparse.numbytes
|
||||
@vrindex GNU.sparse.numbytes, extended header variable
|
||||
Size of the data block
|
||||
Size of the data block.
|
||||
@end table
|
||||
|
||||
The latter two variables repeat for each data block, so the overall
|
||||
@@ -117,11 +117,11 @@ structure is like this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
GNU.sparse.size=@var{size}
|
||||
GNU.sparse.numblocks=@var{numblocks}
|
||||
GNU.sparse.size=@var{size}
|
||||
GNU.sparse.numblocks=@var{numblocks}
|
||||
repeat @var{numblocks} times
|
||||
GNU.sparse.offset=@var{offset}
|
||||
GNU.sparse.numbytes=@var{numbytes}
|
||||
GNU.sparse.offset=@var{offset}
|
||||
GNU.sparse.numbytes=@var{numbytes}
|
||||
end repeat
|
||||
@end group
|
||||
@end smallexample
|
||||
@@ -136,8 +136,8 @@ meaningful. Thus, multiple occurrences of @code{GNU.sparse.offset} and
|
||||
@code{GNU.sparse.numbytes} are conflicting with the POSIX specs.
|
||||
|
||||
@item
|
||||
Attempting to extract such archives using a third-party @command{tar}s
|
||||
results in extraction of sparse files in @emph{compressed form}. If
|
||||
Attempting to extract such archives using a third-party's @command{tar}
|
||||
results in extraction of sparse files in @emph{condensed form}. If
|
||||
the @command{tar} implementation in question does not support POSIX
|
||||
format, it will also extract a file containing extension header
|
||||
attributes. This file can be used to expand the file to its original
|
||||
@@ -160,7 +160,7 @@ it uses a single variable:
|
||||
@item GNU.sparse.map
|
||||
@vrindex GNU.sparse.map, extended header variable
|
||||
Map of non-null data chunks. It is a string consisting of
|
||||
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
|
||||
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
|
||||
@end table
|
||||
|
||||
To address the 2nd problem, the @code{name} field in @code{ustar}
|
||||
@@ -181,7 +181,7 @@ restore such members using non-GNU @command{tar}s.
|
||||
|
||||
The resulting @code{GNU.sparse.map} string can be @emph{very} long.
|
||||
Although POSIX does not impose any limit on the length of a @code{x}
|
||||
header variable, this possibly can confuse some tars.
|
||||
header variable, this possibly can confuse some @command{tar}s.
|
||||
|
||||
@node PAX 1
|
||||
@appendixsubsec PAX Format, Version 1.0
|
||||
@@ -218,18 +218,18 @@ The real name of the sparse file is stored in the variable
|
||||
variable @code{GNU.sparse.realsize}.
|
||||
|
||||
The sparse map itself is stored in the file data block, preceding the actual
|
||||
file data. It consists of a series of octal numbers of arbitrary length, delimited
|
||||
file data. It consists of a series of octal numbers of arbitrary length, delimited
|
||||
by newlines. The map is padded with nulls to the nearest block boundary.
|
||||
|
||||
The first number gives the number of entries in the map. Following are map entries,
|
||||
each one consisting of two numbers giving the offset and size of the
|
||||
data block it describes.
|
||||
|
||||
The format is designed in such a way that non-posix aware tars and tars not
|
||||
The format is designed in such a way that non-posix aware @command{tar}s and @command{tar}s not
|
||||
supporting @code{GNU.sparse.*} keywords will extract each sparse file
|
||||
in its condensed form with the file map prepended and will place it
|
||||
into a separate directory. Then, using a simple program it would be
|
||||
possible to expand the file to its original form even without @GNUTAR{}.
|
||||
@xref{Sparse Recovery}, for the detailed information on how to extract
|
||||
sparse members without @GNUTAR{}.
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@cindex snapshot files, editing
|
||||
@cindex snapshot files, fixing device numbers
|
||||
Sometimes device numbers can change after upgrading your kernel
|
||||
version or recofiguring the harvare. Reportedly this is the case with
|
||||
version or reconfiguring the hardware. Reportedly this is the case with
|
||||
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
|
||||
cases this change is unnoticed by the users. However, it influences
|
||||
@command{tar} incremental backups: the device number is stored in tar
|
||||
@@ -21,9 +21,9 @@ the @command{tar-snapshot-edit} utility for inspecting and updating
|
||||
device numbers in snapshot files. The utility, written by
|
||||
Dustin J.@: Mitchell, is available from
|
||||
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
|
||||
@GNUTAR{} home page}.
|
||||
@GNUTAR{} home page}.
|
||||
|
||||
To obtain the device numbers used in the snapshot file, run
|
||||
To obtain the device numbers used in the snapshot file, run
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar-snapshot-edit @var{snapfile}}
|
||||
@@ -31,7 +31,7 @@ $ @kbd{tar-snapshot-edit @var{snapfile}}
|
||||
|
||||
@noindent
|
||||
where @var{snapfile} is the name of the snapshot file (you can supply as many
|
||||
files as you wish in a single command line ).
|
||||
files as you wish in a single command line).
|
||||
|
||||
To update all occurrences of the given device number in the file, use
|
||||
@option{-r} option. It takes a single argument of the form
|
||||
|
||||
717
doc/tar.texi
717
doc/tar.texi
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,9 @@
|
||||
alloca
|
||||
argmatch
|
||||
argp
|
||||
argp-version-etc
|
||||
backupfile
|
||||
canonicalize
|
||||
closeout
|
||||
configmake
|
||||
dirname
|
||||
@@ -18,7 +20,7 @@ ftruncate
|
||||
full-write
|
||||
getdate
|
||||
getline
|
||||
getopt
|
||||
getopt-gnu
|
||||
getpagesize
|
||||
gettext
|
||||
gettime
|
||||
@@ -31,6 +33,8 @@ localcharset
|
||||
mkdtemp
|
||||
modechange
|
||||
obstack
|
||||
priv-set
|
||||
progname
|
||||
quote
|
||||
quotearg
|
||||
rpmatch
|
||||
@@ -50,10 +54,10 @@ strtoul
|
||||
timespec
|
||||
unlinkdir
|
||||
unlocked-io
|
||||
utime
|
||||
utimens
|
||||
version-etc-fsf
|
||||
xalloc
|
||||
xalloc-die
|
||||
xgetcwd
|
||||
xstrtoumax
|
||||
xvasprintf
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile for GNU tar library. -*- Makefile -*-
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
|
||||
# 2005, 2006, 2007, 2009, 2010 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
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
noinst_LIBRARIES=libtar.a
|
||||
rmt-command.h : Makefile
|
||||
rm -f $@-t $@
|
||||
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
|
||||
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
|
||||
echo "#endif" >> $@-t
|
||||
mv $@-t $@
|
||||
$(AM_V_GEN)rm -f $@-t $@
|
||||
$(AM_V_at)echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
|
||||
$(AM_V_at)echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
|
||||
$(AM_V_at)echo "#endif" >> $@-t
|
||||
$(AM_V_at)mv $@-t $@
|
||||
BUILT_SOURCES = rmt-command.h
|
||||
CLEANFILES = rmt-command.h rmt-command.h-t
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
|
||||
|
||||
445
lib/modechange.c
445
lib/modechange.c
@@ -1,445 +0,0 @@
|
||||
/* modechange.c -- file mode manipulation
|
||||
Copyright (C) 1989, 1990, 1997, 1998, 1999 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 2, 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, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@ai.mit.edu> */
|
||||
|
||||
/* The ASCII mode string is compiled into a linked list of `struct
|
||||
modechange', which can then be applied to each file to be changed.
|
||||
We do this instead of re-parsing the ASCII string for each file
|
||||
because the compiled form requires less computation to use; when
|
||||
changing the mode of many files, this probably results in a
|
||||
performance gain. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "modechange.h"
|
||||
#include <sys/stat.h>
|
||||
#include "xstrtol.h"
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
char *malloc ();
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#if STAT_MACROS_BROKEN
|
||||
# undef S_ISDIR
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 04000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 04000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 01000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 0400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 0200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 0100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 0040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 0020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 0010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 0004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 0002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 0001
|
||||
#endif
|
||||
#ifndef S_IRWXU
|
||||
# define S_IRWXU 0700
|
||||
#endif
|
||||
#ifndef S_IRWXG
|
||||
# define S_IRWXG 0070
|
||||
#endif
|
||||
#ifndef S_IRWXO
|
||||
# define S_IRWXO 0007
|
||||
#endif
|
||||
|
||||
/* All the mode bits that can be affected by chmod. */
|
||||
#define CHMOD_MODE_BITS \
|
||||
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
|
||||
/* Return newly allocated memory to hold one element of type TYPE. */
|
||||
#define talloc(type) ((type *) malloc (sizeof (type)))
|
||||
|
||||
/* Create a mode_change entry with the specified `=ddd'-style
|
||||
mode change operation, where NEW_MODE is `ddd'. Return the
|
||||
new entry, or NULL upon failure. */
|
||||
|
||||
static struct mode_change *
|
||||
make_node_op_equals (mode_t new_mode)
|
||||
{
|
||||
struct mode_change *p;
|
||||
p = talloc (struct mode_change);
|
||||
if (p == NULL)
|
||||
return p;
|
||||
p->next = NULL;
|
||||
p->op = '=';
|
||||
p->flags = 0;
|
||||
p->value = new_mode;
|
||||
p->affected = CHMOD_MODE_BITS; /* Affect all permissions. */
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Append entry E to the end of the link list with the specified
|
||||
HEAD and TAIL. */
|
||||
|
||||
static void
|
||||
mode_append_entry (struct mode_change **head,
|
||||
struct mode_change **tail,
|
||||
struct mode_change *e)
|
||||
{
|
||||
if (*head == NULL)
|
||||
*head = *tail = e;
|
||||
else
|
||||
{
|
||||
(*tail)->next = e;
|
||||
*tail = e;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a linked list of file mode change operations created from
|
||||
MODE_STRING, an ASCII string that contains either an octal number
|
||||
specifying an absolute mode, or symbolic mode change operations with
|
||||
the form:
|
||||
[ugoa...][[+-=][rwxXstugo...]...][,...]
|
||||
MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-)
|
||||
should not affect bits set in the umask when no users are given.
|
||||
Operators not selected in MASKED_OPS ignore the umask.
|
||||
|
||||
Return MODE_INVALID if `mode_string' does not contain a valid
|
||||
representation of file mode change operations;
|
||||
return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */
|
||||
|
||||
struct mode_change *
|
||||
mode_compile (const char *mode_string, unsigned int masked_ops)
|
||||
{
|
||||
struct mode_change *head; /* First element of the linked list. */
|
||||
struct mode_change *tail; /* An element of the linked list. */
|
||||
uintmax_t mode_value; /* The mode value, if octal. */
|
||||
char *string_end; /* Pointer to end of parsed value. */
|
||||
mode_t umask_value; /* The umask value (surprise). */
|
||||
|
||||
head = NULL;
|
||||
#ifdef lint
|
||||
tail = NULL;
|
||||
#endif
|
||||
|
||||
if (xstrtoumax (mode_string, &string_end, 8, &mode_value, "") == LONGINT_OK)
|
||||
{
|
||||
struct mode_change *p;
|
||||
if (mode_value != (mode_value & CHMOD_MODE_BITS))
|
||||
return MODE_INVALID;
|
||||
p = make_node_op_equals ((mode_t) mode_value);
|
||||
if (p == NULL)
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
mode_append_entry (&head, &tail, p);
|
||||
return head;
|
||||
}
|
||||
|
||||
umask_value = umask (0);
|
||||
umask (umask_value); /* Restore the old value. */
|
||||
--mode_string;
|
||||
|
||||
/* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
|
||||
do
|
||||
{
|
||||
/* Which bits in the mode are operated on. */
|
||||
mode_t affected_bits = 0;
|
||||
/* `affected_bits' modified by umask. */
|
||||
mode_t affected_masked;
|
||||
/* Operators to actually use umask on. */
|
||||
unsigned ops_to_mask = 0;
|
||||
|
||||
int who_specified_p;
|
||||
|
||||
affected_bits = 0;
|
||||
ops_to_mask = 0;
|
||||
/* Turn on all the bits in `affected_bits' for each group given. */
|
||||
for (++mode_string;; ++mode_string)
|
||||
switch (*mode_string)
|
||||
{
|
||||
case 'u':
|
||||
affected_bits |= S_ISUID | S_IRWXU;
|
||||
break;
|
||||
case 'g':
|
||||
affected_bits |= S_ISGID | S_IRWXG;
|
||||
break;
|
||||
case 'o':
|
||||
affected_bits |= S_ISVTX | S_IRWXO;
|
||||
break;
|
||||
case 'a':
|
||||
affected_bits |= CHMOD_MODE_BITS;
|
||||
break;
|
||||
default:
|
||||
goto no_more_affected;
|
||||
}
|
||||
|
||||
no_more_affected:
|
||||
/* If none specified, affect all bits, except perhaps those
|
||||
set in the umask. */
|
||||
if (affected_bits)
|
||||
who_specified_p = 1;
|
||||
else
|
||||
{
|
||||
who_specified_p = 0;
|
||||
affected_bits = CHMOD_MODE_BITS;
|
||||
ops_to_mask = masked_ops;
|
||||
}
|
||||
|
||||
while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')
|
||||
{
|
||||
struct mode_change *change = talloc (struct mode_change);
|
||||
if (change == NULL)
|
||||
{
|
||||
mode_free (head);
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
}
|
||||
|
||||
change->next = NULL;
|
||||
change->op = *mode_string; /* One of "=+-". */
|
||||
affected_masked = affected_bits;
|
||||
|
||||
/* Per the Single Unix Spec, if `who' is not specified and the
|
||||
`=' operator is used, then clear all the bits first. */
|
||||
if (!who_specified_p &&
|
||||
ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS : 0))
|
||||
{
|
||||
struct mode_change *p = make_node_op_equals (0);
|
||||
if (p == NULL)
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
mode_append_entry (&head, &tail, p);
|
||||
}
|
||||
|
||||
if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
|
||||
: *mode_string == '+' ? MODE_MASK_PLUS
|
||||
: MODE_MASK_MINUS))
|
||||
affected_masked &= ~umask_value;
|
||||
change->affected = affected_masked;
|
||||
change->value = 0;
|
||||
change->flags = 0;
|
||||
|
||||
/* Add the element to the tail of the list, so the operations
|
||||
are performed in the correct order. */
|
||||
mode_append_entry (&head, &tail, change);
|
||||
|
||||
/* Set `value' according to the bits set in `affected_masked'. */
|
||||
for (++mode_string;; ++mode_string)
|
||||
switch (*mode_string)
|
||||
{
|
||||
case 'r':
|
||||
change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
|
||||
& affected_masked);
|
||||
break;
|
||||
case 'w':
|
||||
change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
|
||||
& affected_masked);
|
||||
break;
|
||||
case 'X':
|
||||
change->flags |= MODE_X_IF_ANY_X;
|
||||
/* Fall through. */
|
||||
case 'x':
|
||||
change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
|
||||
& affected_masked);
|
||||
break;
|
||||
case 's':
|
||||
/* Set the setuid/gid bits if `u' or `g' is selected. */
|
||||
change->value |= (S_ISUID | S_ISGID) & affected_masked;
|
||||
break;
|
||||
case 't':
|
||||
/* Set the "save text image" bit if `o' is selected. */
|
||||
change->value |= S_ISVTX & affected_masked;
|
||||
break;
|
||||
case 'u':
|
||||
/* Set the affected bits to the value of the `u' bits
|
||||
on the same file. */
|
||||
if (change->value)
|
||||
goto invalid;
|
||||
change->value = S_IRWXU;
|
||||
change->flags |= MODE_COPY_EXISTING;
|
||||
break;
|
||||
case 'g':
|
||||
/* Set the affected bits to the value of the `g' bits
|
||||
on the same file. */
|
||||
if (change->value)
|
||||
goto invalid;
|
||||
change->value = S_IRWXG;
|
||||
change->flags |= MODE_COPY_EXISTING;
|
||||
break;
|
||||
case 'o':
|
||||
/* Set the affected bits to the value of the `o' bits
|
||||
on the same file. */
|
||||
if (change->value)
|
||||
goto invalid;
|
||||
change->value = S_IRWXO;
|
||||
change->flags |= MODE_COPY_EXISTING;
|
||||
break;
|
||||
default:
|
||||
goto no_more_values;
|
||||
}
|
||||
no_more_values:;
|
||||
}
|
||||
} while (*mode_string == ',');
|
||||
if (*mode_string == 0)
|
||||
return head;
|
||||
invalid:
|
||||
mode_free (head);
|
||||
return MODE_INVALID;
|
||||
}
|
||||
|
||||
/* Return a file mode change operation that sets permissions to match those
|
||||
of REF_FILE. Return MODE_BAD_REFERENCE if REF_FILE can't be accessed. */
|
||||
|
||||
struct mode_change *
|
||||
mode_create_from_ref (const char *ref_file)
|
||||
{
|
||||
struct mode_change *change; /* the only change element */
|
||||
struct stat ref_stats;
|
||||
|
||||
if (stat (ref_file, &ref_stats))
|
||||
return MODE_BAD_REFERENCE;
|
||||
|
||||
change = talloc (struct mode_change);
|
||||
|
||||
if (change == NULL)
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
|
||||
change->op = '=';
|
||||
change->flags = 0;
|
||||
change->affected = CHMOD_MODE_BITS;
|
||||
change->value = ref_stats.st_mode;
|
||||
change->next = NULL;
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
/* Return file mode OLDMODE, adjusted as indicated by the list of change
|
||||
operations CHANGES. If OLDMODE is a directory, the type `X'
|
||||
change affects it even if no execute bits were set in OLDMODE.
|
||||
The returned value has the S_IFMT bits cleared. */
|
||||
|
||||
mode_t
|
||||
mode_adjust (mode_t oldmode, const struct mode_change *changes)
|
||||
{
|
||||
mode_t newmode; /* The adjusted mode and one operand. */
|
||||
mode_t value; /* The other operand. */
|
||||
|
||||
newmode = oldmode & CHMOD_MODE_BITS;
|
||||
|
||||
for (; changes; changes = changes->next)
|
||||
{
|
||||
if (changes->flags & MODE_COPY_EXISTING)
|
||||
{
|
||||
/* Isolate in `value' the bits in `newmode' to copy, given in
|
||||
the mask `changes->value'. */
|
||||
value = newmode & changes->value;
|
||||
|
||||
if (changes->value & S_IRWXU)
|
||||
/* Copy `u' permissions onto `g' and `o'. */
|
||||
value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
|
||||
| (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
|
||||
| (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
|
||||
else if (changes->value & S_IRWXG)
|
||||
/* Copy `g' permissions onto `u' and `o'. */
|
||||
value |= ((value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
|
||||
| (value & S_IWGRP ? S_IWUSR | S_IROTH : 0)
|
||||
| (value & S_IXGRP ? S_IXUSR | S_IXOTH : 0));
|
||||
else
|
||||
/* Copy `o' permissions onto `u' and `g'. */
|
||||
value |= ((value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
|
||||
| (value & S_IWOTH ? S_IWUSR | S_IRGRP : 0)
|
||||
| (value & S_IXOTH ? S_IXUSR | S_IXGRP : 0));
|
||||
|
||||
/* In order to change only `u', `g', or `o' permissions,
|
||||
or some combination thereof, clear unselected bits.
|
||||
This can not be done in mode_compile because the value
|
||||
to which the `changes->affected' mask is applied depends
|
||||
on the old mode of each file. */
|
||||
value &= changes->affected;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = changes->value;
|
||||
/* If `X', do not affect the execute bits if the file is not a
|
||||
directory and no execute bits are already set. */
|
||||
if ((changes->flags & MODE_X_IF_ANY_X)
|
||||
&& !S_ISDIR (oldmode)
|
||||
&& (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
|
||||
/* Clear the execute bits. */
|
||||
value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
|
||||
}
|
||||
|
||||
switch (changes->op)
|
||||
{
|
||||
case '=':
|
||||
/* Preserve the previous values in `newmode' of bits that are
|
||||
not affected by this change operation. */
|
||||
newmode = (newmode & ~changes->affected) | value;
|
||||
break;
|
||||
case '+':
|
||||
newmode |= value;
|
||||
break;
|
||||
case '-':
|
||||
newmode &= ~value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return newmode;
|
||||
}
|
||||
|
||||
/* Free the memory used by the list of file mode change operations
|
||||
CHANGES. */
|
||||
|
||||
void
|
||||
mode_free (register struct mode_change *changes)
|
||||
{
|
||||
register struct mode_change *next;
|
||||
|
||||
while (changes)
|
||||
{
|
||||
next = changes->next;
|
||||
free (changes);
|
||||
changes = next;
|
||||
}
|
||||
}
|
||||
852
rebox.el
852
rebox.el
@@ -1,852 +0,0 @@
|
||||
;;; Handling of comment boxes.
|
||||
;;; Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
|
||||
;;; Fran<61>ois Pinard <pinard@iro.umontreal.ca>, April 1991.
|
||||
|
||||
;;; I first observed rounded corners, as in style 223 boxes, in code from
|
||||
;;; Warren Tucker <wht@n4hgf.mt-park.ga.us>, a previous shar maintainer.
|
||||
|
||||
;;; Refilling paragraphs inside comments, stretching or shrinking the
|
||||
;;; surrounding box as needed, is a pain to do "by hand". This GNU Emacs
|
||||
;;; LISP code eases my life on this and I find it fair, giving all sources
|
||||
;;; for a package, to also give the means for nicely modifying comments.
|
||||
|
||||
;;; The function rebox-comment discovers the extent of the boxed comments
|
||||
;;; near the cursor, possibly refills the text, then adjusts the comment
|
||||
;;; box style. The function rebox-region does the same, except that it
|
||||
;;; takes the current region as a boxed comment. Numeric prefixes are
|
||||
;;; used to add or remove a box, change its style (language, quality or
|
||||
;;; type), or to prevent refilling of its text. A minus sign alone as
|
||||
;;; prefix asks for interactive style selection.
|
||||
|
||||
;;; For most Emacs language editing modes, refilling does not make sense
|
||||
;;; outside comments, so you may redefine the M-q command and link it to
|
||||
;;; this file. For example, I use this in my .emacs file:
|
||||
|
||||
;;; (setq c-mode-hook
|
||||
;;; '(lambda ()
|
||||
;;; (define-key c-mode-map "\M-q" 'rebox-comment)))
|
||||
;;; (autoload 'rebox-comment "rebox" nil t)
|
||||
;;; (autoload 'rebox-region "rebox" nil t)
|
||||
|
||||
;;; The cursor should be within a comment before any of these commands,
|
||||
;;; or else it should be between two comments, in which case the command
|
||||
;;; applies to the next comment. When the command is given without prefix,
|
||||
;;; the current comment box style is recognized from the comment itself
|
||||
;;; as far as possible, and preserved. A prefix may be used to force
|
||||
;;; a particular box style. A style is made up of three attributes: a
|
||||
;;; language (the hundreds digit), a quality (the tens digit) and a type
|
||||
;;; (the units digit). A zero or negative flag value changes the default
|
||||
;;; box style to its absolute value. Zero digits in default style,
|
||||
;;; when not overriden in flag, asks for recognition of corresponding
|
||||
;;; attributes from the current box. `C-u' avoids refilling the text,
|
||||
;;; using the default box style. `C-u -' defines the style interactively.
|
||||
|
||||
;;; Box language is associated with comment delimiters. Values are 100
|
||||
;;; for none or unknown, 200 for `/*' and `*/' as in plain C, 300 for
|
||||
;;; '//' as in C++, 400 for `#' as in most scripting languages, 500 for
|
||||
;;; `;' as in LISP or assembler and 600 for `%' as in TeX or PostScript.
|
||||
|
||||
;;; Box quality differs according to language. For unknown languages (100)
|
||||
;;; or for the C language (200), values are 10 for simple, 20 or 30 for
|
||||
;;; rounded, and 40 for starred. For all others, box quality indicates
|
||||
;;; the thickness in characters of the left and right sides of the box:
|
||||
;;; values are 10, 20, 30 or 40 for 1, 2, 3 or 4 characters wide. C++
|
||||
;;; quality 10 is always promoted to 20. Roughly said, simple quality
|
||||
;;; boxes (10) use comment delimiters to left and right of each comment
|
||||
;;; line, and also for the top or bottom line when applicable. Rounded
|
||||
;;; quality boxes (20 or 30) try to suggest rounded corners in boxes.
|
||||
;;; Starred quality boxes (40) mostly use a left margin of asterisks or
|
||||
;;; X'es, and use them also in box surroundings. Experiment a little to
|
||||
;;; see what happens.
|
||||
|
||||
;;; Box type values are 1 for fully opened boxes for which boxing is done
|
||||
;;; only for the left and right but not for top or bottom, 2 for half
|
||||
;;; single lined boxes for which boxing is done on all sides except top,
|
||||
;;; 3 for fully single lined boxes for which boxing is done on all sides,
|
||||
;;; 4 for half double lined boxes which is like type 2 but more bold,
|
||||
;;; or 5 for fully double lined boxes which is like type 3 but more bold.
|
||||
|
||||
;;; The special style 221 or 231 is worth a note, because it is fairly
|
||||
;;; common: the whole C comment stays between a single opening `/*'
|
||||
;;; and a single closing `*/'. The special style 111 deletes a box.
|
||||
;;; The initial default style is 023 so, unless overriden, comments are
|
||||
;;; put in single lined boxes, C comments are of rounded quality.
|
||||
|
||||
(defvar rebox-default-style 0 "*Preferred style for box comments.")
|
||||
|
||||
;;; Help strings for prompting or error messages.
|
||||
|
||||
(defconst REBOX_HELP_FOR_LANGUAGE
|
||||
"Box language is 100-none, 200-/*, 300-//, 400-#, 500-;, 600-%%")
|
||||
(defconst REBOX_LANGUAGE_NONE 100)
|
||||
(defconst REBOX_LANGUAGE_C 200)
|
||||
(defconst REBOX_LANGUAGE_C++ 300)
|
||||
(defconst REBOX_LANGUAGE_AWK 400)
|
||||
(defconst REBOX_LANGUAGE_LISP 500)
|
||||
(defconst REBOX_LANGUAGE_TEX 600)
|
||||
|
||||
(defun rebox-help-string-for-language (language)
|
||||
(cond ((= language 0) "default language")
|
||||
((= language REBOX_LANGUAGE_NONE) "no language")
|
||||
((= language REBOX_LANGUAGE_C) "plain C")
|
||||
((= language REBOX_LANGUAGE_C++) "C++")
|
||||
((= language REBOX_LANGUAGE_AWK) "sh/Perl/make")
|
||||
((= language REBOX_LANGUAGE_LISP) "LISP/assembler")
|
||||
((= language REBOX_LANGUAGE_TEX) "TeX/PostScript")
|
||||
(t "<Unknown Language>")))
|
||||
|
||||
(defconst REBOX_HELP_FOR_QUALITY
|
||||
"Box quality/width is 10-simple, 20-rounded, 30-rounded or 40-starred")
|
||||
(defconst REBOX_QUALITY_SIMPLE_ONE 10)
|
||||
(defconst REBOX_QUALITY_ROUNDED_TWO 20)
|
||||
(defconst REBOX_QUALITY_ROUNDED_THREE 30)
|
||||
(defconst REBOX_QUALITY_STARRED_FOUR 40)
|
||||
|
||||
(defun rebox-help-string-for-quality (quality)
|
||||
(cond ((= quality 0) "default quality")
|
||||
((= quality REBOX_QUALITY_SIMPLE_ONE) "square or 1-wide")
|
||||
((= quality REBOX_QUALITY_ROUNDED_TWO) "rounded or 2-wide")
|
||||
((= quality REBOX_QUALITY_ROUNDED_THREE) "rounded or 3-wide")
|
||||
((= quality REBOX_QUALITY_STARRED_FOUR) "starred or 4-wide")
|
||||
(t "<Unknown Quality>")))
|
||||
|
||||
(defconst REBOX_HELP_FOR_TYPE
|
||||
"Box type is 1-open, 2-half-single, 3-single, 4-half-double or 5-double")
|
||||
(defconst REBOX_TYPE_OPEN 1)
|
||||
(defconst REBOX_TYPE_HALF_SINGLE 2)
|
||||
(defconst REBOX_TYPE_SINGLE 3)
|
||||
(defconst REBOX_TYPE_HALF_DOUBLE 4)
|
||||
(defconst REBOX_TYPE_DOUBLE 5)
|
||||
|
||||
(defun rebox-help-string-for-type (type)
|
||||
(cond ((= type 0) "default type")
|
||||
((= type REBOX_TYPE_OPEN) "opened box")
|
||||
((= type REBOX_TYPE_HALF_SINGLE) "half normal")
|
||||
((= type REBOX_TYPE_SINGLE) "full normal")
|
||||
((= type REBOX_TYPE_HALF_DOUBLE) "half bold")
|
||||
((= type REBOX_TYPE_DOUBLE) "full bold")
|
||||
(t "<Unknown Type>")))
|
||||
|
||||
(defconst REBOX_MAX_LANGUAGE 6)
|
||||
(defconst REBOX_MAX_QUALITY 4)
|
||||
(defconst REBOX_MAX_TYPE 5)
|
||||
|
||||
;;; Request the style interactively, using the minibuffer.
|
||||
|
||||
(defun rebox-ask-for-style ()
|
||||
(let (key language quality type)
|
||||
(while (not language)
|
||||
(message REBOX_HELP_FOR_LANGUAGE)
|
||||
(setq key (read-char))
|
||||
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_LANGUAGE)))
|
||||
(setq language (- key ?0))))
|
||||
(while (not quality)
|
||||
(message REBOX_HELP_FOR_QUALITY)
|
||||
(setq key (read-char))
|
||||
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_QUALITY)))
|
||||
(setq quality (- key ?0))))
|
||||
(while (not type)
|
||||
(message REBOX_HELP_FOR_TYPE)
|
||||
(setq key (read-char))
|
||||
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_TYPE)))
|
||||
(setq type (- key ?0))))
|
||||
(+ (* 100 language) (* 10 quality) type)))
|
||||
|
||||
;;; Write some TEXT followed by an edited STYLE value into the minibuffer.
|
||||
|
||||
(defun rebox-show-style (text style)
|
||||
(message
|
||||
(concat text (format " (%03d)" style)
|
||||
": " (rebox-help-string-for-language (* (/ style 100) 100))
|
||||
", " (rebox-help-string-for-quality (* (% (/ style 10) 10) 10))
|
||||
", " (rebox-help-string-for-type (% style 10)))))
|
||||
|
||||
;;; Validate FLAG and usually return t if not interrupted by errors.
|
||||
;;; But if FLAG is zero or negative, then change default box style and
|
||||
;;; return nil.
|
||||
|
||||
(defun rebox-validate-flag (flag)
|
||||
|
||||
;; Validate flag.
|
||||
|
||||
(if (numberp flag)
|
||||
(let ((value (if (< flag 0) (- flag) flag)))
|
||||
(if (> (/ value 100) REBOX_MAX_LANGUAGE)
|
||||
(error REBOX_HELP_FOR_LANGUAGE))
|
||||
(if (> (% (/ value 10) 10) REBOX_MAX_QUALITY)
|
||||
(error REBOX_HELP_FOR_QUALITY))
|
||||
(if (> (% value 10) REBOX_MAX_TYPE)
|
||||
(error REBOX_HELP_FOR_TYPE))))
|
||||
|
||||
;; Change default box style if requested.
|
||||
|
||||
(if (and (numberp flag) (<= flag 0))
|
||||
(progn
|
||||
(setq flag (- flag))
|
||||
(if (not (zerop (/ flag 100)))
|
||||
(setq rebox-default-style
|
||||
(+ (* (/ flag 100) 100)
|
||||
(% rebox-default-style 100))))
|
||||
(if (not (zerop (% (/ flag 10) 10)))
|
||||
(setq rebox-default-style
|
||||
(+ (* (/ rebox-default-style 100) 100)
|
||||
(* (% (/ flag 10) 10) 10)
|
||||
(% rebox-default-style 10))))
|
||||
(if (not (zerop (% flag 10)))
|
||||
(setq rebox-default-style
|
||||
(+ (* (/ rebox-default-style 10) 10)
|
||||
(% flag 10))))
|
||||
(rebox-show-style "Default style" rebox-default-style)
|
||||
nil)
|
||||
t))
|
||||
|
||||
;;; Return the minimum value of the left margin of all lines, or -1 if
|
||||
;;; all lines are empty.
|
||||
|
||||
(defun rebox-left-margin ()
|
||||
(let ((margin -1))
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(skip-chars-forward " \t")
|
||||
(if (not (looking-at "\n"))
|
||||
(setq margin
|
||||
(if (< margin 0)
|
||||
(current-column)
|
||||
(min margin (current-column)))))
|
||||
(forward-line 1))
|
||||
margin))
|
||||
|
||||
;;; Return the maximum value of the right margin of all lines. Any
|
||||
;;; sentence ending a line has a space guaranteed before the margin.
|
||||
|
||||
(defun rebox-right-margin ()
|
||||
(let ((margin 0) period)
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(end-of-line)
|
||||
(if (bobp)
|
||||
(setq period 0)
|
||||
(backward-char 1)
|
||||
(setq period (if (looking-at "[.?!]") 1 0))
|
||||
(forward-char 1))
|
||||
(setq margin (max margin (+ (current-column) period)))
|
||||
(forward-char 1))
|
||||
margin))
|
||||
|
||||
;;; Return a regexp to match the start or end of a comment for some
|
||||
;;; LANGUAGE, leaving the comment marks themselves available in \1.
|
||||
|
||||
;; FIXME: Recognize style 1** boxes.
|
||||
|
||||
(defun rebox-regexp-start (language)
|
||||
(cond ((= language 0) "^[ \t]*\\(/\\*\\|//+\\|#+\\|;+\\|%+\\)")
|
||||
((= language REBOX_LANGUAGE_NONE) "^\\(\\)")
|
||||
((= language REBOX_LANGUAGE_C) "^[ \t]*\\(/\\*\\)")
|
||||
((= language REBOX_LANGUAGE_C++) "^[ \t]*\\(//+\\)")
|
||||
((= language REBOX_LANGUAGE_AWK) "^[ \t]*\\(#+\\)")
|
||||
((= language REBOX_LANGUAGE_LISP) "^[ \t]*\\(;+\\)")
|
||||
((= language REBOX_LANGUAGE_TEX) "^[ \t]*\\(%+\\)")))
|
||||
|
||||
(defun rebox-regexp-end (language)
|
||||
(cond ((= language 0) "\\(\\*/\\|//+\\|#+\\|;+\\|%+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_NONE) "\\(\\)$")
|
||||
((= language REBOX_LANGUAGE_C) "\\(\\*/\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_C++) "\\(//+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_AWK) "\\(#+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_LISP) "\\(;+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_TEX) "\\(%+\\)[ \t]*$")))
|
||||
|
||||
;;; By looking at the text starting at the cursor position, guess the
|
||||
;;; language in use, and return it.
|
||||
|
||||
(defun rebox-guess-language ()
|
||||
(let ((language REBOX_LANGUAGE_NONE)
|
||||
(value (* 100 REBOX_MAX_LANGUAGE)))
|
||||
(while (not (zerop value))
|
||||
(if (looking-at (rebox-regexp-start value))
|
||||
(progn
|
||||
(setq language value)
|
||||
(setq value 0))
|
||||
(setq value (- value 100))))
|
||||
language))
|
||||
|
||||
;;; Find the limits of the block of comments following or enclosing
|
||||
;;; the cursor, or return an error if the cursor is not within such a
|
||||
;;; block of comments. Extend it as far as possible in both
|
||||
;;; directions, then narrow the buffer around it.
|
||||
|
||||
(defun rebox-find-and-narrow ()
|
||||
(save-excursion
|
||||
(let (start end temp language)
|
||||
|
||||
;; Find the start of the current or immediately following comment.
|
||||
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t\n")
|
||||
(beginning-of-line)
|
||||
(if (not (looking-at (rebox-regexp-start 0)))
|
||||
(progn
|
||||
(setq temp (point))
|
||||
(if (re-search-forward "\\*/" nil t)
|
||||
(progn
|
||||
(re-search-backward "/\\*")
|
||||
(if (> (point) temp)
|
||||
(error "outside any comment block"))
|
||||
(setq temp (point))
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t")
|
||||
(if (not (= (point) temp))
|
||||
(error "text before start of comment"))
|
||||
(beginning-of-line))
|
||||
(error "outside any comment block"))))
|
||||
|
||||
(setq start (point))
|
||||
(setq language (rebox-guess-language))
|
||||
|
||||
;; - find the end of this comment
|
||||
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(search-forward "*/")
|
||||
(if (not (looking-at "[ \t]*$"))
|
||||
(error "text after end of comment"))))
|
||||
(end-of-line)
|
||||
(if (eobp)
|
||||
(insert "\n")
|
||||
(forward-char 1))
|
||||
(setq end (point))
|
||||
|
||||
;; - try to extend the comment block backwards
|
||||
|
||||
(goto-char start)
|
||||
(while (and (not (bobp))
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(skip-chars-backward " \t\n")
|
||||
(if (and (looking-at "[ \t]*\n[ \t]*/\\*")
|
||||
(> (point) 2))
|
||||
(progn
|
||||
(backward-char 2)
|
||||
(if (looking-at "\\*/")
|
||||
(progn
|
||||
(re-search-backward "/\\*")
|
||||
(setq temp (point))
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t")
|
||||
(if (= (point) temp)
|
||||
(progn (beginning-of-line) t)))))))
|
||||
(previous-line 1)
|
||||
(looking-at (rebox-regexp-start language))))
|
||||
(setq start (point)))
|
||||
|
||||
;; - try to extend the comment block forward
|
||||
|
||||
(goto-char end)
|
||||
(while (looking-at (rebox-regexp-start language))
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(re-search-forward "[ \t]*/\\*")
|
||||
(re-search-forward "\\*/")
|
||||
(if (looking-at "[ \t]*$")
|
||||
(progn
|
||||
(beginning-of-line)
|
||||
(forward-line 1)
|
||||
(setq end (point)))))
|
||||
(forward-line 1)
|
||||
(setq end (point))))
|
||||
|
||||
;; - narrow to the whole block of comments
|
||||
|
||||
(narrow-to-region start end))))
|
||||
|
||||
;;; After refilling it if REFILL is not nil, while respecting a left
|
||||
;;; MARGIN, put the narrowed buffer back into a boxed LANGUAGE comment
|
||||
;;; box of a given QUALITY and TYPE.
|
||||
|
||||
(defun rebox-reconstruct (refill margin language quality type)
|
||||
(rebox-show-style "Style" (+ language quality type))
|
||||
|
||||
(let (right-margin nw nn ne ww ee sw ss se x xx)
|
||||
|
||||
;; - decide the elements of the box being produced
|
||||
|
||||
(cond ((= language REBOX_LANGUAGE_NONE)
|
||||
;; - planify a comment for no language in particular
|
||||
|
||||
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
|
||||
;; - planify a simple box
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "+-") (setq ss ?-) (setq se "-+"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "+-") (setq nn ?-) (setq ne "-+")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "+-") (setq ss ?-) (setq se "-+"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "*=") (setq ss ?=) (setq se "=*"))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "*=") (setq nn ?=) (setq ne "=*")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "*=") (setq ss ?=) (setq se "=*"))))
|
||||
|
||||
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(= quality REBOX_QUALITY_ROUNDED_THREE))
|
||||
;; - planify a rounded box
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "| ") (setq ee " |"))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "-'"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw ".-") (setq nn ?-) (setq ne "-.")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "-'"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/=" ) (setq nn ?=) (setq ne "=\\")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))))
|
||||
|
||||
((= quality REBOX_QUALITY_STARRED_FOUR)
|
||||
;; - planify a starred box
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "| ") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "* ") (setq ee " *")
|
||||
(setq sw "**") (setq ss ?*) (setq se "**"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "**") (setq nn ?*) (setq ne "**")
|
||||
(setq ww "* ") (setq ee " *")
|
||||
(setq sw "**") (setq ss ?*) (setq se "**"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "X ") (setq ee " X")
|
||||
(setq sw "XX") (setq ss ?X) (setq se "XX"))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "XX") (setq nn ?X) (setq ne "XX")
|
||||
(setq ww "X ") (setq ee " X")
|
||||
(setq sw "XX") (setq ss ?X) (setq se "XX"))))))
|
||||
|
||||
((= language REBOX_LANGUAGE_C)
|
||||
;; - planify a comment for C
|
||||
|
||||
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
|
||||
;; - planify a simple C comment
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "/* ") (setq ee " */"))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?-) (setq se " */"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "/* ") (setq nn ?-) (setq ne " */")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?-) (setq se " */"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?=) (setq se " */"))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/* ") (setq nn ?=) (setq ne " */")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?=) (setq se " */"))))
|
||||
|
||||
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(= quality REBOX_QUALITY_ROUNDED_THREE))
|
||||
;; - planify a rounded C comment
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
;; ``open rounded'' is a special case
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww " ") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "/*") (setq nn ? ) (setq ne " .")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "*/"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "/*") (setq nn ?-) (setq ne "-.")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "*/"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "/*" ) (setq nn ? ) (setq ne " \\")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/*" ) (setq nn ?=) (setq ne "=\\")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))))
|
||||
|
||||
((= quality REBOX_QUALITY_STARRED_FOUR)
|
||||
;; - planify a starred C comment
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "/* ") (setq nn ? ) (setq ne "")
|
||||
(setq ww " * ") (setq ee "")
|
||||
(setq sw " */") (setq ss ? ) (setq se ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "/* ") (setq nn ? ) (setq ne " *")
|
||||
(setq ww " * ") (setq ee " *")
|
||||
(setq sw " **") (setq ss ?*) (setq se "**/"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "/**") (setq nn ?*) (setq ne "**")
|
||||
(setq ww " * ") (setq ee " *")
|
||||
(setq sw " **") (setq ss ?*) (setq se "**/"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "/* " ) (setq nn ? ) (setq ne " *\\")
|
||||
(setq ww "|* " ) (setq ee " *|" )
|
||||
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/**" ) (setq nn ?*) (setq ne "**\\")
|
||||
(setq ww "|* " ) (setq ee " *|" )
|
||||
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))))))
|
||||
|
||||
(t
|
||||
;; - planify a comment for all other things
|
||||
|
||||
(if (and (= language REBOX_LANGUAGE_C++)
|
||||
(= quality REBOX_QUALITY_SIMPLE_ONE))
|
||||
(setq quality REBOX_QUALITY_ROUNDED_TWO))
|
||||
(setq x (cond ((= language REBOX_LANGUAGE_C++) ?/)
|
||||
((= language REBOX_LANGUAGE_AWK) ?#)
|
||||
((= language REBOX_LANGUAGE_LISP) ?\;)
|
||||
((= language REBOX_LANGUAGE_TEX) ?%)))
|
||||
(setq xx (make-string (/ quality 10) x))
|
||||
(setq ww (concat xx " "))
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq nw "")
|
||||
(setq sw ww) (setq ss ?-) (setq se ee))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq nw ww) (setq nn ?-) (setq ne ee)
|
||||
(setq sw ww) (setq ss ?-) (setq se ee))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq xx (make-string (1+ (/ quality 10)) x))
|
||||
(setq nw "")
|
||||
(setq sw xx) (setq ss x) (setq se xx))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq xx (make-string (1+ (/ quality 10)) x))
|
||||
(setq nw xx) (setq nn x) (setq ne xx)
|
||||
(setq sw xx) (setq ss x) (setq se xx)))))
|
||||
|
||||
;; - possibly refill, and adjust margins to account for left inserts
|
||||
|
||||
(if (not (and flag (listp flag)))
|
||||
(let ((fill-prefix (make-string margin ? ))
|
||||
(fill-column (- fill-column (+ (length ww) (length ee)))))
|
||||
(fill-region (point-min) (point-max))))
|
||||
|
||||
(setq right-margin (+ (rebox-right-margin) (length ww)))
|
||||
|
||||
;; - construct the box comment, from top to bottom
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (and (= language REBOX_LANGUAGE_C)
|
||||
(or (= quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(= quality REBOX_QUALITY_ROUNDED_THREE))
|
||||
(= type REBOX_TYPE_OPEN))
|
||||
(progn
|
||||
;; - construct an 33 style comment
|
||||
|
||||
(skip-chars-forward " " (+ (point) margin))
|
||||
(insert (make-string (- margin (current-column)) ? )
|
||||
"/* ")
|
||||
(end-of-line)
|
||||
(forward-char 1)
|
||||
(while (not (eobp))
|
||||
(skip-chars-forward " " (+ (point) margin))
|
||||
(insert (make-string (- margin (current-column)) ? )
|
||||
ww)
|
||||
(beginning-of-line)
|
||||
(forward-line 1))
|
||||
(backward-char 1)
|
||||
(insert " */"))
|
||||
|
||||
;; - construct all other comment styles
|
||||
|
||||
;; construct one top line
|
||||
(if (not (zerop (length nw)))
|
||||
(progn
|
||||
(indent-to margin)
|
||||
(insert nw)
|
||||
(if (or (not (eq nn ? )) (not (zerop (length ne))))
|
||||
(insert (make-string (- right-margin (current-column)) nn)
|
||||
ne))
|
||||
(insert "\n")))
|
||||
|
||||
;; construct one middle line
|
||||
(while (not (eobp))
|
||||
(skip-chars-forward " " (+ (point) margin))
|
||||
(insert (make-string (- margin (current-column)) ? )
|
||||
ww)
|
||||
(end-of-line)
|
||||
(if (not (zerop (length ee)))
|
||||
(progn
|
||||
(indent-to right-margin)
|
||||
(insert ee)))
|
||||
(beginning-of-line)
|
||||
(forward-line 1))
|
||||
|
||||
;; construct one bottom line
|
||||
(if (not (zerop (length sw)))
|
||||
(progn
|
||||
(indent-to margin)
|
||||
(insert sw)
|
||||
(if (or (not (eq ss ? )) (not (zerop (length se))))
|
||||
(insert (make-string (- right-margin (current-column)) ss)
|
||||
se "\n")))))))
|
||||
|
||||
;;; Add, delete or adjust a comment box in the narrowed buffer.
|
||||
;;; Various FLAG values are explained at beginning of this file.
|
||||
|
||||
(defun rebox-engine (flag)
|
||||
(let ((undo-list buffer-undo-list)
|
||||
(marked-point (point-marker))
|
||||
(language (progn (goto-char (point-min)) (rebox-guess-language)))
|
||||
(quality 0)
|
||||
(type 0))
|
||||
|
||||
(untabify (point-min) (point-max))
|
||||
|
||||
;; Remove all the comment marks, and move all the text rigidly to the
|
||||
;; left for insuring that the left margin stays at the same place.
|
||||
;; At the same time, try recognizing the box style, saving its quality
|
||||
;; in QUALITY and its type in TYPE. (LANGUAGE is already guessed.)
|
||||
|
||||
(let ((indent-tabs-mode nil)
|
||||
(previous-margin (rebox-left-margin))
|
||||
actual-margin)
|
||||
|
||||
;; FIXME: Cleanup style 1** boxes.
|
||||
;; FIXME: Recognize really all cases of type and quality.
|
||||
|
||||
;; - remove all comment marks
|
||||
|
||||
(if (= language REBOX_LANGUAGE_NONE)
|
||||
nil
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward (rebox-regexp-start language) nil t)
|
||||
(goto-char (match-beginning 1))
|
||||
(delete-region (point) (match-end 1))
|
||||
(insert (make-string (- (match-end 1) (point)) ? )))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward (rebox-regexp-end language) nil t)
|
||||
(replace-match "" t t)))
|
||||
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\*/ */\\*" nil t)
|
||||
(replace-match " " t t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\( *\\)|\\*\\(.*\\)\\*| *$" nil t)
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_DOUBLE)
|
||||
(replace-match "\\1 \\2" t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\( *\\)\\*\\(.*\\)\\* *$" nil t)
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_SINGLE)
|
||||
(replace-match "\\1 \\2" t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\( *\\)|\\(.*\\)| *$" nil t)
|
||||
(setq quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(replace-match "\\1 \\2" t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (zerop quality)
|
||||
(while (re-search-forward "^\\( +\\)\\* " nil t)
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_OPEN)
|
||||
(replace-match "\\1 " t)))))
|
||||
|
||||
;; - remove the first dashed or starred line
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (looking-at "^ *\\(--+\\|\\*\\*+\\)[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq type REBOX_TYPE_SINGLE)
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *\\(==\\|XX+\\|##+\\|;;+\\)[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq type REBOX_TYPE_DOUBLE)
|
||||
(replace-match "" t t))))
|
||||
|
||||
;; - remove the last dashed or starred line
|
||||
|
||||
(goto-char (point-max))
|
||||
(previous-line 1)
|
||||
(if (looking-at "^ *[`\+\\]?*--+ *\n")
|
||||
(progn
|
||||
(if (= type REBOX_TYPE_OPEN)
|
||||
(setq type REBOX_TYPE_HALF_SINGLE))
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *[`\+\\]?*\\(==+\\|##+\\|;;+\\) *\n")
|
||||
(progn
|
||||
(if (= type REBOX_TYPE_OPEN)
|
||||
(setq type REBOX_TYPE_HALF_DOUBLE))
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *\\*\\*+[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_HALF_SINGLE)
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *XX+[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_HALF_DOUBLE)
|
||||
(replace-match "" t t))))))
|
||||
|
||||
;; - remove all spurious whitespace
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward " +$" nil t)
|
||||
(replace-match "" t t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (looking-at "\n+")
|
||||
(replace-match "" t t))
|
||||
|
||||
(goto-char (point-max))
|
||||
(skip-chars-backward "\n")
|
||||
(if (looking-at "\n\n+")
|
||||
(replace-match "\n" t t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\n\n\n+" nil t)
|
||||
(replace-match "\n\n" t t))
|
||||
|
||||
;; - move the text left is adequate
|
||||
|
||||
(setq actual-margin (rebox-left-margin))
|
||||
(if (not (= previous-margin actual-margin))
|
||||
(indent-rigidly (point-min) (point-max)
|
||||
(- previous-margin actual-margin))))
|
||||
|
||||
;; Override box style according to FLAG or chosen default style.
|
||||
;; Else, use either recognized style elements or built-in defaults.
|
||||
|
||||
(cond ((and (numberp flag) (not (zerop (/ flag 100))))
|
||||
(setq language (* (/ flag 100) 100)))
|
||||
((not (zerop (/ rebox-default-style 100)))
|
||||
(setq language (* (/ rebox-default-style 100) 100))))
|
||||
|
||||
(cond ((and (numberp flag) (not (zerop (% (/ flag 10) 10))))
|
||||
(setq quality (* (% (/ flag 10) 10) 10)))
|
||||
((not (zerop (% (/ rebox-default-style 10) 10)))
|
||||
(setq quality (* (% (/ rebox-default-style 10) 10) 10)))
|
||||
((zerop quality)
|
||||
(setq quality REBOX_QUALITY_ROUNDED_TWO)))
|
||||
|
||||
(cond ((and (numberp flag) (not (zerop (% flag 10))))
|
||||
(setq type (% flag 10)))
|
||||
((not (zerop (% rebox-default-style 10)))
|
||||
(setq type (% rebox-default-style 10)))
|
||||
((zerop type)
|
||||
(setq type 1)))
|
||||
|
||||
;; Possibly refill, then reconstruct the comment box.
|
||||
|
||||
(let ((indent-tabs-mode nil))
|
||||
(rebox-reconstruct (not (and flag (listp flag)))
|
||||
(rebox-left-margin)
|
||||
language quality type))
|
||||
|
||||
;; Retabify to the left only (adapted from tabify.el).
|
||||
|
||||
(if indent-tabs-mode
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^[ \t][ \t]+" nil t)
|
||||
(let ((column (current-column)))
|
||||
(delete-region (match-beginning 0) (point))
|
||||
(indent-to column)))))
|
||||
|
||||
;; Restore the point position.
|
||||
|
||||
(goto-char (marker-position marked-point))
|
||||
|
||||
;; Remove all intermediate boundaries from the undo list.
|
||||
|
||||
(if (not (eq buffer-undo-list undo-list))
|
||||
(let ((cursor buffer-undo-list))
|
||||
(while (not (eq (cdr cursor) undo-list))
|
||||
(if (car (cdr cursor))
|
||||
(setq cursor (cdr cursor))
|
||||
(rplacd cursor (cdr (cdr cursor)))))))))
|
||||
|
||||
;;; Set or reset the Taarna team's own way for a C style. You do not
|
||||
;;; really want to know about this.
|
||||
|
||||
(defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.")
|
||||
|
||||
(defun taarna-mode ()
|
||||
(interactive)
|
||||
(if c-mode-taarna-style
|
||||
(progn
|
||||
|
||||
(setq c-mode-taarna-style nil)
|
||||
(setq c-indent-level 2)
|
||||
(setq c-continued-statement-offset 2)
|
||||
(setq c-brace-offset 0)
|
||||
(setq c-argdecl-indent 5)
|
||||
(setq c-label-offset -2)
|
||||
(setq c-tab-always-indent t)
|
||||
(setq rebox-default-style REBOX_QUALITY_ROUNDED_TWO)
|
||||
(message "C mode: GNU style"))
|
||||
|
||||
(setq c-mode-taarna-style t)
|
||||
(setq c-indent-level 4)
|
||||
(setq c-continued-statement-offset 4)
|
||||
(setq c-brace-offset -4)
|
||||
(setq c-argdecl-indent 4)
|
||||
(setq c-label-offset -4)
|
||||
(setq c-tab-always-indent t)
|
||||
(setq rebox-default-style
|
||||
(+ REBOX_QUALITY_SIMPLE_ONE REBOX_TYPE_HALF_SINGLE))
|
||||
(message "C mode: Taarna style")))
|
||||
|
||||
;;; Rebox the current region.
|
||||
|
||||
(defun rebox-region (flag)
|
||||
(interactive "P")
|
||||
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
|
||||
(if (rebox-validate-flag flag)
|
||||
(save-restriction
|
||||
(narrow-to-region (region-beginning) (region-end))
|
||||
(rebox-engine flag))))
|
||||
|
||||
;;; Rebox the surrounding comment.
|
||||
|
||||
(defun rebox-comment (flag)
|
||||
(interactive "P")
|
||||
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
|
||||
(if (rebox-validate-flag flag)
|
||||
(save-restriction
|
||||
(rebox-find-and-narrow)
|
||||
(rebox-engine flag))))
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -279,8 +280,8 @@ read_map (FILE *ifp)
|
||||
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
|
||||
}
|
||||
|
||||
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
|
||||
SEEK_SET);
|
||||
fseeko (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
|
||||
SEEK_SET);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -27,6 +27,7 @@ tar_SOURCES = \
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
exit.c\
|
||||
extract.c\
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
@@ -38,10 +39,12 @@ tar_SOURCES = \
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
unlink.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
utf8.c\
|
||||
warning.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
|
||||
|
||||
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
|
||||
|
||||
|
||||
973
src/Makefile.in
973
src/Makefile.in
@@ -1,973 +0,0 @@
|
||||
# Makefile.in generated by automake 1.10.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
# Makefile for GNU tar sources.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
|
||||
# 2007, 2009 Free Software Foundation, Inc.
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
bin_PROGRAMS = tar$(EXEEXT)
|
||||
subdir = src
|
||||
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in ansi2knr.1 ansi2knr.c
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
|
||||
$(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/argmatch.m4 \
|
||||
$(top_srcdir)/m4/argp.m4 $(top_srcdir)/m4/backupfile.m4 \
|
||||
$(top_srcdir)/m4/bison.m4 $(top_srcdir)/m4/btowc.m4 \
|
||||
$(top_srcdir)/m4/canonicalize-lgpl.m4 \
|
||||
$(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/chown.m4 \
|
||||
$(top_srcdir)/m4/clock_time.m4 \
|
||||
$(top_srcdir)/m4/close-stream.m4 $(top_srcdir)/m4/close.m4 \
|
||||
$(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \
|
||||
$(top_srcdir)/m4/d-ino.m4 $(top_srcdir)/m4/dirent_h.m4 \
|
||||
$(top_srcdir)/m4/dirfd.m4 $(top_srcdir)/m4/dirname.m4 \
|
||||
$(top_srcdir)/m4/dos.m4 $(top_srcdir)/m4/double-slash-root.m4 \
|
||||
$(top_srcdir)/m4/dup2.m4 $(top_srcdir)/m4/eealloc.m4 \
|
||||
$(top_srcdir)/m4/environ.m4 $(top_srcdir)/m4/errno_h.m4 \
|
||||
$(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exclude.m4 \
|
||||
$(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \
|
||||
$(top_srcdir)/m4/fchdir.m4 $(top_srcdir)/m4/fclose.m4 \
|
||||
$(top_srcdir)/m4/fcntl-safer.m4 $(top_srcdir)/m4/fcntl_h.m4 \
|
||||
$(top_srcdir)/m4/fileblocks.m4 $(top_srcdir)/m4/float_h.m4 \
|
||||
$(top_srcdir)/m4/fnmatch.m4 $(top_srcdir)/m4/fpending.m4 \
|
||||
$(top_srcdir)/m4/fseeko.m4 $(top_srcdir)/m4/ftruncate.m4 \
|
||||
$(top_srcdir)/m4/getcwd-abort-bug.m4 \
|
||||
$(top_srcdir)/m4/getcwd-path-max.m4 $(top_srcdir)/m4/getcwd.m4 \
|
||||
$(top_srcdir)/m4/getdate.m4 $(top_srcdir)/m4/getdelim.m4 \
|
||||
$(top_srcdir)/m4/getline.m4 $(top_srcdir)/m4/getopt.m4 \
|
||||
$(top_srcdir)/m4/getpagesize.m4 $(top_srcdir)/m4/gettext.m4 \
|
||||
$(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \
|
||||
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \
|
||||
$(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/hash.m4 \
|
||||
$(top_srcdir)/m4/human.m4 $(top_srcdir)/m4/iconv.m4 \
|
||||
$(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inline.m4 \
|
||||
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \
|
||||
$(top_srcdir)/m4/inttostr.m4 $(top_srcdir)/m4/inttypes-pri.m4 \
|
||||
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
|
||||
$(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/lib-ld.m4 \
|
||||
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
|
||||
$(top_srcdir)/m4/localcharset.m4 $(top_srcdir)/m4/locale-fr.m4 \
|
||||
$(top_srcdir)/m4/locale-ja.m4 $(top_srcdir)/m4/locale-zh.m4 \
|
||||
$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/lseek.m4 \
|
||||
$(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/malloc.m4 \
|
||||
$(top_srcdir)/m4/malloca.m4 $(top_srcdir)/m4/mbchar.m4 \
|
||||
$(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \
|
||||
$(top_srcdir)/m4/mbscasecmp.m4 $(top_srcdir)/m4/mbsinit.m4 \
|
||||
$(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/mempcpy.m4 \
|
||||
$(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mkdtemp.m4 \
|
||||
$(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/modechange.m4 \
|
||||
$(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/nls.m4 \
|
||||
$(top_srcdir)/m4/open.m4 $(top_srcdir)/m4/openat.m4 \
|
||||
$(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/paxutils.m4 \
|
||||
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \
|
||||
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/quote.m4 \
|
||||
$(top_srcdir)/m4/quotearg.m4 $(top_srcdir)/m4/rawmemchr.m4 \
|
||||
$(top_srcdir)/m4/readlink.m4 $(top_srcdir)/m4/realloc.m4 \
|
||||
$(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/rmt.m4 \
|
||||
$(top_srcdir)/m4/rpmatch.m4 $(top_srcdir)/m4/rtapelib.m4 \
|
||||
$(top_srcdir)/m4/safe-read.m4 $(top_srcdir)/m4/safe-write.m4 \
|
||||
$(top_srcdir)/m4/save-cwd.m4 $(top_srcdir)/m4/savedir.m4 \
|
||||
$(top_srcdir)/m4/setenv.m4 $(top_srcdir)/m4/size_max.m4 \
|
||||
$(top_srcdir)/m4/sleep.m4 $(top_srcdir)/m4/snprintf.m4 \
|
||||
$(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \
|
||||
$(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \
|
||||
$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \
|
||||
$(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \
|
||||
$(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strcase.m4 \
|
||||
$(top_srcdir)/m4/strchrnul.m4 $(top_srcdir)/m4/strdup.m4 \
|
||||
$(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/string_h.m4 \
|
||||
$(top_srcdir)/m4/strings_h.m4 $(top_srcdir)/m4/strndup.m4 \
|
||||
$(top_srcdir)/m4/strnlen.m4 $(top_srcdir)/m4/strtoimax.m4 \
|
||||
$(top_srcdir)/m4/strtol.m4 $(top_srcdir)/m4/strtoll.m4 \
|
||||
$(top_srcdir)/m4/strtoul.m4 $(top_srcdir)/m4/strtoull.m4 \
|
||||
$(top_srcdir)/m4/strtoumax.m4 $(top_srcdir)/m4/sys_stat_h.m4 \
|
||||
$(top_srcdir)/m4/sys_time_h.m4 $(top_srcdir)/m4/sysexits.m4 \
|
||||
$(top_srcdir)/m4/system.m4 $(top_srcdir)/m4/tempname.m4 \
|
||||
$(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \
|
||||
$(top_srcdir)/m4/timespec.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \
|
||||
$(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \
|
||||
$(top_srcdir)/m4/unlinkdir.m4 $(top_srcdir)/m4/unlocked-io.m4 \
|
||||
$(top_srcdir)/m4/utimbuf.m4 $(top_srcdir)/m4/utime.m4 \
|
||||
$(top_srcdir)/m4/utimens.m4 $(top_srcdir)/m4/utimes-null.m4 \
|
||||
$(top_srcdir)/m4/utimes.m4 $(top_srcdir)/m4/vasnprintf.m4 \
|
||||
$(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/wchar.m4 \
|
||||
$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wcrtomb.m4 \
|
||||
$(top_srcdir)/m4/wctype.m4 $(top_srcdir)/m4/wcwidth.m4 \
|
||||
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/write.m4 \
|
||||
$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xgetcwd.m4 \
|
||||
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/xstrndup.m4 \
|
||||
$(top_srcdir)/m4/xstrtol.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_tar_OBJECTS = buffer.$(OBJEXT) checkpoint.$(OBJEXT) \
|
||||
compare.$(OBJEXT) create.$(OBJEXT) delete.$(OBJEXT) \
|
||||
extract.$(OBJEXT) xheader.$(OBJEXT) incremen.$(OBJEXT) \
|
||||
list.$(OBJEXT) misc.$(OBJEXT) names.$(OBJEXT) sparse.$(OBJEXT) \
|
||||
suffix.$(OBJEXT) system.$(OBJEXT) tar.$(OBJEXT) \
|
||||
transform.$(OBJEXT) update.$(OBJEXT) utf8.$(OBJEXT)
|
||||
tar_OBJECTS = $(am_tar_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
am__DEPENDENCIES_2 = ../lib/libtar.a ../gnu/libgnu.a \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
|
||||
tar_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(tar_SOURCES)
|
||||
DIST_SOURCES = $(tar_SOURCES)
|
||||
HEADERS = $(noinst_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ALLOCA = @ALLOCA@
|
||||
ALLOCA_H = @ALLOCA_H@
|
||||
AMTAR = @AMTAR@
|
||||
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOM4TE = @AUTOM4TE@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BACKUP_LIBEXEC_SCRIPTS = @BACKUP_LIBEXEC_SCRIPTS@
|
||||
BACKUP_SBIN_SCRIPTS = @BACKUP_SBIN_SCRIPTS@
|
||||
BACKUP_SED_COND = @BACKUP_SED_COND@
|
||||
BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@
|
||||
BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@
|
||||
BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
|
||||
BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
|
||||
BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFAULT_ARCHIVE = @DEFAULT_ARCHIVE@
|
||||
DEFAULT_ARCHIVE_FORMAT = @DEFAULT_ARCHIVE_FORMAT@
|
||||
DEFAULT_BLOCKING = @DEFAULT_BLOCKING@
|
||||
DEFAULT_QUOTING_STYLE = @DEFAULT_QUOTING_STYLE@
|
||||
DEFAULT_RMT_COMMAND = @DEFAULT_RMT_COMMAND@
|
||||
DEFAULT_RMT_DIR = @DEFAULT_RMT_DIR@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DIRENT_H = @DIRENT_H@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
|
||||
EMULTIHOP_VALUE = @EMULTIHOP_VALUE@
|
||||
ENOLINK_HIDDEN = @ENOLINK_HIDDEN@
|
||||
ENOLINK_VALUE = @ENOLINK_VALUE@
|
||||
EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
|
||||
EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
|
||||
ERRNO_H = @ERRNO_H@
|
||||
EXEEXT = @EXEEXT@
|
||||
FCNTL_H = @FCNTL_H@
|
||||
FLOAT_H = @FLOAT_H@
|
||||
FNMATCH_H = @FNMATCH_H@
|
||||
GETOPT_H = @GETOPT_H@
|
||||
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||
GLIBC21 = @GLIBC21@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GMSGFMT_015 = @GMSGFMT_015@
|
||||
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
|
||||
GNULIB_ATOLL = @GNULIB_ATOLL@
|
||||
GNULIB_BTOWC = @GNULIB_BTOWC@
|
||||
GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
|
||||
GNULIB_CHOWN = @GNULIB_CHOWN@
|
||||
GNULIB_CLOSE = @GNULIB_CLOSE@
|
||||
GNULIB_DIRFD = @GNULIB_DIRFD@
|
||||
GNULIB_DPRINTF = @GNULIB_DPRINTF@
|
||||
GNULIB_DUP2 = @GNULIB_DUP2@
|
||||
GNULIB_ENVIRON = @GNULIB_ENVIRON@
|
||||
GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
|
||||
GNULIB_FCHDIR = @GNULIB_FCHDIR@
|
||||
GNULIB_FCLOSE = @GNULIB_FCLOSE@
|
||||
GNULIB_FFLUSH = @GNULIB_FFLUSH@
|
||||
GNULIB_FOPEN = @GNULIB_FOPEN@
|
||||
GNULIB_FPRINTF = @GNULIB_FPRINTF@
|
||||
GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
|
||||
GNULIB_FPUTC = @GNULIB_FPUTC@
|
||||
GNULIB_FPUTS = @GNULIB_FPUTS@
|
||||
GNULIB_FREOPEN = @GNULIB_FREOPEN@
|
||||
GNULIB_FSEEK = @GNULIB_FSEEK@
|
||||
GNULIB_FSEEKO = @GNULIB_FSEEKO@
|
||||
GNULIB_FSYNC = @GNULIB_FSYNC@
|
||||
GNULIB_FTELL = @GNULIB_FTELL@
|
||||
GNULIB_FTELLO = @GNULIB_FTELLO@
|
||||
GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
|
||||
GNULIB_FWRITE = @GNULIB_FWRITE@
|
||||
GNULIB_GETCWD = @GNULIB_GETCWD@
|
||||
GNULIB_GETDELIM = @GNULIB_GETDELIM@
|
||||
GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
|
||||
GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
|
||||
GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
|
||||
GNULIB_GETLINE = @GNULIB_GETLINE@
|
||||
GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
|
||||
GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
|
||||
GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
|
||||
GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
|
||||
GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
|
||||
GNULIB_IMAXABS = @GNULIB_IMAXABS@
|
||||
GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
|
||||
GNULIB_LCHMOD = @GNULIB_LCHMOD@
|
||||
GNULIB_LCHOWN = @GNULIB_LCHOWN@
|
||||
GNULIB_LINK = @GNULIB_LINK@
|
||||
GNULIB_LSEEK = @GNULIB_LSEEK@
|
||||
GNULIB_LSTAT = @GNULIB_LSTAT@
|
||||
GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
|
||||
GNULIB_MBRLEN = @GNULIB_MBRLEN@
|
||||
GNULIB_MBRTOWC = @GNULIB_MBRTOWC@
|
||||
GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
|
||||
GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
|
||||
GNULIB_MBSCHR = @GNULIB_MBSCHR@
|
||||
GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
|
||||
GNULIB_MBSINIT = @GNULIB_MBSINIT@
|
||||
GNULIB_MBSLEN = @GNULIB_MBSLEN@
|
||||
GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
|
||||
GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
|
||||
GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@
|
||||
GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
|
||||
GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
|
||||
GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
|
||||
GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@
|
||||
GNULIB_MBSSEP = @GNULIB_MBSSEP@
|
||||
GNULIB_MBSSPN = @GNULIB_MBSSPN@
|
||||
GNULIB_MBSSTR = @GNULIB_MBSSTR@
|
||||
GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
|
||||
GNULIB_MEMMEM = @GNULIB_MEMMEM@
|
||||
GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
|
||||
GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
|
||||
GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
|
||||
GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
|
||||
GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
|
||||
GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
|
||||
GNULIB_OPEN = @GNULIB_OPEN@
|
||||
GNULIB_PERROR = @GNULIB_PERROR@
|
||||
GNULIB_PRINTF = @GNULIB_PRINTF@
|
||||
GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
|
||||
GNULIB_PUTC = @GNULIB_PUTC@
|
||||
GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
|
||||
GNULIB_PUTENV = @GNULIB_PUTENV@
|
||||
GNULIB_PUTS = @GNULIB_PUTS@
|
||||
GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
|
||||
GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
|
||||
GNULIB_READLINK = @GNULIB_READLINK@
|
||||
GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
|
||||
GNULIB_RPMATCH = @GNULIB_RPMATCH@
|
||||
GNULIB_SCANDIR = @GNULIB_SCANDIR@
|
||||
GNULIB_SETENV = @GNULIB_SETENV@
|
||||
GNULIB_SLEEP = @GNULIB_SLEEP@
|
||||
GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
|
||||
GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
|
||||
GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
|
||||
GNULIB_STPCPY = @GNULIB_STPCPY@
|
||||
GNULIB_STPNCPY = @GNULIB_STPNCPY@
|
||||
GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
|
||||
GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
|
||||
GNULIB_STRDUP = @GNULIB_STRDUP@
|
||||
GNULIB_STRERROR = @GNULIB_STRERROR@
|
||||
GNULIB_STRNDUP = @GNULIB_STRNDUP@
|
||||
GNULIB_STRNLEN = @GNULIB_STRNLEN@
|
||||
GNULIB_STRPBRK = @GNULIB_STRPBRK@
|
||||
GNULIB_STRSEP = @GNULIB_STRSEP@
|
||||
GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
|
||||
GNULIB_STRSTR = @GNULIB_STRSTR@
|
||||
GNULIB_STRTOD = @GNULIB_STRTOD@
|
||||
GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
|
||||
GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
|
||||
GNULIB_STRTOLL = @GNULIB_STRTOLL@
|
||||
GNULIB_STRTOULL = @GNULIB_STRTOULL@
|
||||
GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
|
||||
GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
|
||||
GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
|
||||
GNULIB_UNSETENV = @GNULIB_UNSETENV@
|
||||
GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
|
||||
GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
|
||||
GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
|
||||
GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
|
||||
GNULIB_VPRINTF = @GNULIB_VPRINTF@
|
||||
GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
|
||||
GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
|
||||
GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
|
||||
GNULIB_WCRTOMB = @GNULIB_WCRTOMB@
|
||||
GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@
|
||||
GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@
|
||||
GNULIB_WCTOB = @GNULIB_WCTOB@
|
||||
GNULIB_WCWIDTH = @GNULIB_WCWIDTH@
|
||||
GNULIB_WRITE = @GNULIB_WRITE@
|
||||
GREP = @GREP@
|
||||
HAVE_ALPHASORT = @HAVE_ALPHASORT@
|
||||
HAVE_ATOLL = @HAVE_ATOLL@
|
||||
HAVE_BTOWC = @HAVE_BTOWC@
|
||||
HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@
|
||||
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
|
||||
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
|
||||
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
|
||||
HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
|
||||
HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@
|
||||
HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@
|
||||
HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@
|
||||
HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@
|
||||
HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
|
||||
HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
|
||||
HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
|
||||
HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
|
||||
HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
|
||||
HAVE_DECL_STRERROR = @HAVE_DECL_STRERROR@
|
||||
HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@
|
||||
HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
|
||||
HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
|
||||
HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
|
||||
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
|
||||
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
|
||||
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
|
||||
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
|
||||
HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@
|
||||
HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@
|
||||
HAVE_DPRINTF = @HAVE_DPRINTF@
|
||||
HAVE_DUP2 = @HAVE_DUP2@
|
||||
HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
|
||||
HAVE_FSEEKO = @HAVE_FSEEKO@
|
||||
HAVE_FSYNC = @HAVE_FSYNC@
|
||||
HAVE_FTELLO = @HAVE_FTELLO@
|
||||
HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
|
||||
HAVE_GETDOMAINNAME = @HAVE_GETDOMAINNAME@
|
||||
HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
|
||||
HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
|
||||
HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
|
||||
HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
|
||||
HAVE_GETUSERSHELL = @HAVE_GETUSERSHELL@
|
||||
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
|
||||
HAVE_ISWCNTRL = @HAVE_ISWCNTRL@
|
||||
HAVE_LCHMOD = @HAVE_LCHMOD@
|
||||
HAVE_LINK = @HAVE_LINK@
|
||||
HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
|
||||
HAVE_LSTAT = @HAVE_LSTAT@
|
||||
HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@
|
||||
HAVE_MBRLEN = @HAVE_MBRLEN@
|
||||
HAVE_MBRTOWC = @HAVE_MBRTOWC@
|
||||
HAVE_MBSINIT = @HAVE_MBSINIT@
|
||||
HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@
|
||||
HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@
|
||||
HAVE_MEMPCPY = @HAVE_MEMPCPY@
|
||||
HAVE_MKDTEMP = @HAVE_MKDTEMP@
|
||||
HAVE_OS_H = @HAVE_OS_H@
|
||||
HAVE_RANDOM_H = @HAVE_RANDOM_H@
|
||||
HAVE_RANDOM_R = @HAVE_RANDOM_R@
|
||||
HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@
|
||||
HAVE_READLINK = @HAVE_READLINK@
|
||||
HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@
|
||||
HAVE_RPMATCH = @HAVE_RPMATCH@
|
||||
HAVE_SCANDIR = @HAVE_SCANDIR@
|
||||
HAVE_SETENV = @HAVE_SETENV@
|
||||
HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
|
||||
HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
|
||||
HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
|
||||
HAVE_SLEEP = @HAVE_SLEEP@
|
||||
HAVE_STDINT_H = @HAVE_STDINT_H@
|
||||
HAVE_STPCPY = @HAVE_STPCPY@
|
||||
HAVE_STPNCPY = @HAVE_STPNCPY@
|
||||
HAVE_STRCASECMP = @HAVE_STRCASECMP@
|
||||
HAVE_STRCASESTR = @HAVE_STRCASESTR@
|
||||
HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
|
||||
HAVE_STRNDUP = @HAVE_STRNDUP@
|
||||
HAVE_STRPBRK = @HAVE_STRPBRK@
|
||||
HAVE_STRSEP = @HAVE_STRSEP@
|
||||
HAVE_STRTOD = @HAVE_STRTOD@
|
||||
HAVE_STRTOLL = @HAVE_STRTOLL@
|
||||
HAVE_STRTOULL = @HAVE_STRTOULL@
|
||||
HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
|
||||
HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@
|
||||
HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
|
||||
HAVE_SYSEXITS_H = @HAVE_SYSEXITS_H@
|
||||
HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
|
||||
HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
|
||||
HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
|
||||
HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
|
||||
HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@
|
||||
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
|
||||
HAVE_UNISTD_H = @HAVE_UNISTD_H@
|
||||
HAVE_UNSETENV = @HAVE_UNSETENV@
|
||||
HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
|
||||
HAVE_VASPRINTF = @HAVE_VASPRINTF@
|
||||
HAVE_VDPRINTF = @HAVE_VDPRINTF@
|
||||
HAVE_WCHAR_H = @HAVE_WCHAR_H@
|
||||
HAVE_WCRTOMB = @HAVE_WCRTOMB@
|
||||
HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@
|
||||
HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@
|
||||
HAVE_WCTYPE_H = @HAVE_WCTYPE_H@
|
||||
HAVE_WINT_T = @HAVE_WINT_T@
|
||||
HAVE__BOOL = @HAVE__BOOL@
|
||||
INCLUDE_NEXT = @INCLUDE_NEXT@
|
||||
INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@
|
||||
INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||
INTTYPES_H = @INTTYPES_H@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
|
||||
LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
|
||||
LIBICONV = @LIBICONV@
|
||||
LIBINTL = @LIBINTL@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
|
||||
LIB_CLOSE = @LIB_CLOSE@
|
||||
LIB_SETSOCKOPT = @LIB_SETSOCKOPT@
|
||||
LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@
|
||||
LOCALE_FR = @LOCALE_FR@
|
||||
LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
|
||||
LOCALE_JA = @LOCALE_JA@
|
||||
LOCALE_ZH_CN = @LOCALE_ZH_CN@
|
||||
LTLIBICONV = @LTLIBICONV@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MSGFMT = @MSGFMT@
|
||||
MSGFMT_015 = @MSGFMT_015@
|
||||
MSGMERGE = @MSGMERGE@
|
||||
NEXT_DIRENT_H = @NEXT_DIRENT_H@
|
||||
NEXT_ERRNO_H = @NEXT_ERRNO_H@
|
||||
NEXT_FCNTL_H = @NEXT_FCNTL_H@
|
||||
NEXT_FLOAT_H = @NEXT_FLOAT_H@
|
||||
NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
|
||||
NEXT_STDARG_H = @NEXT_STDARG_H@
|
||||
NEXT_STDINT_H = @NEXT_STDINT_H@
|
||||
NEXT_STDIO_H = @NEXT_STDIO_H@
|
||||
NEXT_STDLIB_H = @NEXT_STDLIB_H@
|
||||
NEXT_STRINGS_H = @NEXT_STRINGS_H@
|
||||
NEXT_STRING_H = @NEXT_STRING_H@
|
||||
NEXT_SYSEXITS_H = @NEXT_SYSEXITS_H@
|
||||
NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@
|
||||
NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@
|
||||
NEXT_TIME_H = @NEXT_TIME_H@
|
||||
NEXT_UNISTD_H = @NEXT_UNISTD_H@
|
||||
NEXT_WCHAR_H = @NEXT_WCHAR_H@
|
||||
NEXT_WCTYPE_H = @NEXT_WCTYPE_H@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
POSUB = @POSUB@
|
||||
PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
|
||||
PRIPTR_PREFIX = @PRIPTR_PREFIX@
|
||||
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
|
||||
PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
|
||||
PU_RMT_PROG = @PU_RMT_PROG@
|
||||
RANLIB = @RANLIB@
|
||||
REPLACE_BTOWC = @REPLACE_BTOWC@
|
||||
REPLACE_CHOWN = @REPLACE_CHOWN@
|
||||
REPLACE_CLOSE = @REPLACE_CLOSE@
|
||||
REPLACE_DPRINTF = @REPLACE_DPRINTF@
|
||||
REPLACE_FCHDIR = @REPLACE_FCHDIR@
|
||||
REPLACE_FCLOSE = @REPLACE_FCLOSE@
|
||||
REPLACE_FFLUSH = @REPLACE_FFLUSH@
|
||||
REPLACE_FOPEN = @REPLACE_FOPEN@
|
||||
REPLACE_FPRINTF = @REPLACE_FPRINTF@
|
||||
REPLACE_FREOPEN = @REPLACE_FREOPEN@
|
||||
REPLACE_FSEEK = @REPLACE_FSEEK@
|
||||
REPLACE_FSEEKO = @REPLACE_FSEEKO@
|
||||
REPLACE_FTELL = @REPLACE_FTELL@
|
||||
REPLACE_FTELLO = @REPLACE_FTELLO@
|
||||
REPLACE_GETCWD = @REPLACE_GETCWD@
|
||||
REPLACE_GETLINE = @REPLACE_GETLINE@
|
||||
REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
|
||||
REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
|
||||
REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@
|
||||
REPLACE_LCHOWN = @REPLACE_LCHOWN@
|
||||
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
|
||||
REPLACE_LSEEK = @REPLACE_LSEEK@
|
||||
REPLACE_LSTAT = @REPLACE_LSTAT@
|
||||
REPLACE_MBRLEN = @REPLACE_MBRLEN@
|
||||
REPLACE_MBRTOWC = @REPLACE_MBRTOWC@
|
||||
REPLACE_MBSINIT = @REPLACE_MBSINIT@
|
||||
REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@
|
||||
REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@
|
||||
REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@
|
||||
REPLACE_MEMMEM = @REPLACE_MEMMEM@
|
||||
REPLACE_MKDIR = @REPLACE_MKDIR@
|
||||
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
|
||||
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
|
||||
REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@
|
||||
REPLACE_OPEN = @REPLACE_OPEN@
|
||||
REPLACE_PERROR = @REPLACE_PERROR@
|
||||
REPLACE_PRINTF = @REPLACE_PRINTF@
|
||||
REPLACE_PUTENV = @REPLACE_PUTENV@
|
||||
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
|
||||
REPLACE_SPRINTF = @REPLACE_SPRINTF@
|
||||
REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
|
||||
REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
|
||||
REPLACE_STRDUP = @REPLACE_STRDUP@
|
||||
REPLACE_STRERROR = @REPLACE_STRERROR@
|
||||
REPLACE_STRPTIME = @REPLACE_STRPTIME@
|
||||
REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
|
||||
REPLACE_STRSTR = @REPLACE_STRSTR@
|
||||
REPLACE_STRTOD = @REPLACE_STRTOD@
|
||||
REPLACE_TIMEGM = @REPLACE_TIMEGM@
|
||||
REPLACE_VASPRINTF = @REPLACE_VASPRINTF@
|
||||
REPLACE_VDPRINTF = @REPLACE_VDPRINTF@
|
||||
REPLACE_VFPRINTF = @REPLACE_VFPRINTF@
|
||||
REPLACE_VPRINTF = @REPLACE_VPRINTF@
|
||||
REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
|
||||
REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
|
||||
REPLACE_WCRTOMB = @REPLACE_WCRTOMB@
|
||||
REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@
|
||||
REPLACE_WCTOB = @REPLACE_WCTOB@
|
||||
REPLACE_WCWIDTH = @REPLACE_WCWIDTH@
|
||||
REPLACE_WRITE = @REPLACE_WRITE@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
|
||||
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
|
||||
STDARG_H = @STDARG_H@
|
||||
STDBOOL_H = @STDBOOL_H@
|
||||
STDINT_H = @STDINT_H@
|
||||
STRIP = @STRIP@
|
||||
SYSEXITS_H = @SYSEXITS_H@
|
||||
SYS_STAT_H = @SYS_STAT_H@
|
||||
SYS_TIME_H = @SYS_TIME_H@
|
||||
SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
|
||||
TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
|
||||
UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
|
||||
UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
|
||||
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
VOID_UNSETENV = @VOID_UNSETENV@
|
||||
WCHAR_H = @WCHAR_H@
|
||||
WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
|
||||
WCTYPE_H = @WCTYPE_H@
|
||||
WINT_T_SUFFIX = @WINT_T_SUFFIX@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
YACC = @YACC@
|
||||
YFLAGS = @YFLAGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
gl_LIBOBJS = @gl_LIBOBJS@
|
||||
gl_LTLIBOBJS = @gl_LTLIBOBJS@
|
||||
gltests_LIBOBJS = @gltests_LIBOBJS@
|
||||
gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
checkpoint.c\
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
extract.c\
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
list.c\
|
||||
misc.c\
|
||||
names.c\
|
||||
sparse.c\
|
||||
suffix.c\
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib
|
||||
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
|
||||
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnits src/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
if test -f $$p \
|
||||
; then \
|
||||
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
|
||||
installcheck-binPROGRAMS: $(bin_PROGRAMS)
|
||||
bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
|
||||
case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
|
||||
*" $$p "* | *" $(srcdir)/$$p "*) continue;; \
|
||||
esac; \
|
||||
f=`echo "$$p" | \
|
||||
sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
for opt in --help --version; do \
|
||||
if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \
|
||||
2>c$${pid}_.err </dev/null \
|
||||
&& test -n "`cat c$${pid}_.out`" \
|
||||
&& test -z "`cat c$${pid}_.err`"; then :; \
|
||||
else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
|
||||
done; \
|
||||
done; rm -f c$${pid}_.???; exit $$bad
|
||||
tar$(EXEEXT): $(tar_OBJECTS) $(tar_DEPENDENCIES)
|
||||
@rm -f tar$(EXEEXT)
|
||||
$(LINK) $(tar_OBJECTS) $(tar_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkpoint.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compare.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremen.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sparse.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suffix.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tar.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xheader.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS) $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
installcheck-am: installcheck-binPROGRAMS
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||
clean-generic ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installcheck-binPROGRAMS \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
|
||||
ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -1,42 +0,0 @@
|
||||
.\" $Id: ansi2knr.1 $
|
||||
.TH ANSI2KNR 1 "9 September 1998" \" -*- nroff -*-
|
||||
.SH NAME
|
||||
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
|
||||
.SH SYNOPSIS
|
||||
\fBansi2knr\fR [\fB--filename\fR \fIfilename\fR] [\fIinput_file\fR [\fIoutput_file\fR]]
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
\fB--filename\fR provides the file name for the #line directive in the output,
|
||||
overriding \fIinput_file\fR (if present).
|
||||
.sp
|
||||
If no \fIinput_file\fR is supplied, input is read from stdin.
|
||||
.sp
|
||||
If no \fIoutput_file\fR is supplied, output goes to stdout.
|
||||
.sp
|
||||
There are no error messages.
|
||||
.sp
|
||||
\fBansi2knr\fR
|
||||
recognizes function definitions by seeing a non-keyword identifier at the left
|
||||
margin, followed by a left parenthesis, with a right parenthesis as the last
|
||||
character on the line, and with a left brace as the first token on the
|
||||
following line (ignoring possible intervening comments). It will recognize a
|
||||
multi-line header provided that no intervening line ends with a left or right
|
||||
brace or a semicolon. These algorithms ignore whitespace and comments, except
|
||||
that the function name must be the first thing on the line.
|
||||
.sp
|
||||
The following constructs will confuse it:
|
||||
.br
|
||||
- Any other construct that starts at the left margin and follows the
|
||||
above syntax (such as a macro or function call).
|
||||
.br
|
||||
- Some macros that tinker with the syntax of the function header.
|
||||
.sp
|
||||
The --varargs switch is obsolete, and is recognized only for
|
||||
backwards compatibility. The present version of
|
||||
\fBansi2knr\fR
|
||||
will always attempt to convert a ... argument to va_alist and va_dcl.
|
||||
.SH AUTHOR
|
||||
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
|
||||
continues to maintain the current version; most of the code in the current
|
||||
version is his work. ansi2knr also includes contributions by Francois
|
||||
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.
|
||||
720
src/ansi2knr.c
720
src/ansi2knr.c
@@ -1,720 +0,0 @@
|
||||
/* Copyright (C) 1989, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved. */
|
||||
|
||||
/*$Id: ansi2knr.c $*/
|
||||
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
|
||||
|
||||
/*
|
||||
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone for the
|
||||
consequences of using it or for whether it serves any particular purpose or
|
||||
works at all, unless he says so in writing. Refer to the GNU General Public
|
||||
License (the "GPL") for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute ansi2knr,
|
||||
but only under the conditions described in the GPL. A copy of this license
|
||||
is supposed to have been given to you along with ansi2knr so you can know
|
||||
your rights and responsibilities. It should be in a file named COPYLEFT,
|
||||
or, if there is no file named COPYLEFT, a file named COPYING. Among other
|
||||
things, the copyright notice and this notice must be preserved on all
|
||||
copies.
|
||||
|
||||
We explicitly state here what we believe is already implied by the GPL: if
|
||||
the ansi2knr program is distributed as a separate set of sources and a
|
||||
separate executable file which are aggregated on a storage medium together
|
||||
with another program, this in itself does not bring the other program under
|
||||
the GPL, nor does the mere fact that such a program or the procedures for
|
||||
constructing it invoke the ansi2knr executable bring any other part of the
|
||||
program under the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
|
||||
* --filename provides the file name for the #line directive in the output,
|
||||
* overriding input_file (if present).
|
||||
* If no input_file is supplied, input is read from stdin.
|
||||
* If no output_file is supplied, output goes to stdout.
|
||||
* There are no error messages.
|
||||
*
|
||||
* ansi2knr recognizes function definitions by seeing a non-keyword
|
||||
* identifier at the left margin, followed by a left parenthesis, with a
|
||||
* right parenthesis as the last character on the line, and with a left
|
||||
* brace as the first token on the following line (ignoring possible
|
||||
* intervening comments and/or preprocessor directives), except that a line
|
||||
* consisting of only
|
||||
* identifier1(identifier2)
|
||||
* will not be considered a function definition unless identifier2 is
|
||||
* the word "void", and a line consisting of
|
||||
* identifier1(identifier2, <<arbitrary>>)
|
||||
* will not be considered a function definition.
|
||||
* ansi2knr will recognize a multi-line header provided that no intervening
|
||||
* line ends with a left or right brace or a semicolon. These algorithms
|
||||
* ignore whitespace, comments, and preprocessor directives, except that
|
||||
* the function name must be the first thing on the line. The following
|
||||
* constructs will confuse it:
|
||||
* - Any other construct that starts at the left margin and
|
||||
* follows the above syntax (such as a macro or function call).
|
||||
* - Some macros that tinker with the syntax of function headers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original and principal author of ansi2knr is L. Peter Deutsch
|
||||
* <ghost@aladdin.com>. Other authors are noted in the change history
|
||||
* that follows (in reverse chronological order):
|
||||
lpd 1999-08-17 added code to allow preprocessor directives
|
||||
wherever comments are allowed
|
||||
lpd 1999-04-12 added minor fixes from Pavel Roskin
|
||||
<pavel_roskin@geocities.com> for clean compilation with
|
||||
gcc -W -Wall
|
||||
lpd 1999-03-22 added hack to recognize lines consisting of
|
||||
identifier1(identifier2, xxx) as *not* being procedures
|
||||
lpd 1999-02-03 made indentation of preprocessor commands consistent
|
||||
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
|
||||
endless loop; quoted strings within an argument list
|
||||
confused the parser
|
||||
lpd 1999-01-24 added a check for write errors on the output,
|
||||
suggested by Jim Meyering <meyering@ascend.com>
|
||||
lpd 1998-11-09 added further hack to recognize identifier(void)
|
||||
as being a procedure
|
||||
lpd 1998-10-23 added hack to recognize lines consisting of
|
||||
identifier1(identifier2) as *not* being procedures
|
||||
lpd 1997-12-08 made input_file optional; only closes input and/or
|
||||
output file if not stdin or stdout respectively; prints
|
||||
usage message on stderr rather than stdout; adds
|
||||
--filename switch (changes suggested by
|
||||
<ceder@lysator.liu.se>)
|
||||
lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
|
||||
compilers that don't understand void, as suggested by
|
||||
Tom Lane
|
||||
lpd 1996-01-15 changed to require that the first non-comment token
|
||||
on the line following a function header be a left brace,
|
||||
to reduce sensitivity to macros, as suggested by Tom Lane
|
||||
<tgl@sss.pgh.pa.us>
|
||||
lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
|
||||
undefined preprocessor symbols as 0; changed all #ifdefs
|
||||
for configuration symbols to #ifs
|
||||
lpd 1995-04-05 changed copyright notice to make it clear that
|
||||
including ansi2knr in a program does not bring the entire
|
||||
program under the GPL
|
||||
lpd 1994-12-18 added conditionals for systems where ctype macros
|
||||
don't handle 8-bit characters properly, suggested by
|
||||
Francois Pinard <pinard@iro.umontreal.ca>;
|
||||
removed --varargs switch (this is now the default)
|
||||
lpd 1994-10-10 removed CONFIG_BROKETS conditional
|
||||
lpd 1994-07-16 added some conditionals to help GNU `configure',
|
||||
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
|
||||
properly erase prototype args in function parameters,
|
||||
contributed by Jim Avera <jima@netcom.com>;
|
||||
correct error in writeblanks (it shouldn't erase EOLs)
|
||||
lpd 1989-xx-xx original version
|
||||
*/
|
||||
|
||||
/* Most of the conditionals here are to make ansi2knr work with */
|
||||
/* or without the GNU configure machinery. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
|
||||
/*
|
||||
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
|
||||
This will define HAVE_CONFIG_H and so, activate the following lines.
|
||||
*/
|
||||
|
||||
# if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# else
|
||||
# include <strings.h>
|
||||
# endif
|
||||
|
||||
#else /* not HAVE_CONFIG_H */
|
||||
|
||||
/* Otherwise do it the hard way */
|
||||
|
||||
# ifdef BSD
|
||||
# include <strings.h>
|
||||
# else
|
||||
# ifdef VMS
|
||||
extern int strlen(), strncmp();
|
||||
# else
|
||||
# include <string.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* not HAVE_CONFIG_H */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
/*
|
||||
malloc and free should be declared in stdlib.h,
|
||||
but if you've got a K&R compiler, they probably aren't.
|
||||
*/
|
||||
# ifdef MSDOS
|
||||
# include <malloc.h>
|
||||
# else
|
||||
# ifdef VMS
|
||||
extern char *malloc();
|
||||
extern void free();
|
||||
# else
|
||||
extern char *malloc();
|
||||
extern int free();
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Define NULL (for *very* old compilers). */
|
||||
#ifndef NULL
|
||||
# define NULL (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The ctype macros don't always handle 8-bit characters correctly.
|
||||
* Compensate for this here.
|
||||
*/
|
||||
#ifdef isascii
|
||||
# undef HAVE_ISASCII /* just in case */
|
||||
# define HAVE_ISASCII 1
|
||||
#else
|
||||
#endif
|
||||
#if STDC_HEADERS || !HAVE_ISASCII
|
||||
# define is_ascii(c) 1
|
||||
#else
|
||||
# define is_ascii(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#define is_space(c) (is_ascii(c) && isspace(c))
|
||||
#define is_alpha(c) (is_ascii(c) && isalpha(c))
|
||||
#define is_alnum(c) (is_ascii(c) && isalnum(c))
|
||||
|
||||
/* Scanning macros */
|
||||
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
|
||||
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
|
||||
|
||||
/* Forward references */
|
||||
char *ppdirforward();
|
||||
char *ppdirbackward();
|
||||
char *skipspace();
|
||||
char *scanstring();
|
||||
int writeblanks();
|
||||
int test1();
|
||||
int convert1();
|
||||
|
||||
/* The main program */
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{ FILE *in = stdin;
|
||||
FILE *out = stdout;
|
||||
char *filename = 0;
|
||||
char *program_name = argv[0];
|
||||
char *output_name = 0;
|
||||
#define bufsize 5000 /* arbitrary size */
|
||||
char *buf;
|
||||
char *line;
|
||||
char *more;
|
||||
char *usage =
|
||||
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
|
||||
/*
|
||||
* In previous versions, ansi2knr recognized a --varargs switch.
|
||||
* If this switch was supplied, ansi2knr would attempt to convert
|
||||
* a ... argument to va_alist and va_dcl; if this switch was not
|
||||
* supplied, ansi2knr would simply drop any such arguments.
|
||||
* Now, ansi2knr always does this conversion, and we only
|
||||
* check for this switch for backward compatibility.
|
||||
*/
|
||||
int convert_varargs = 1;
|
||||
int output_error;
|
||||
|
||||
while ( argc > 1 && argv[1][0] == '-' ) {
|
||||
if ( !strcmp(argv[1], "--varargs") ) {
|
||||
convert_varargs = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
|
||||
filename = argv[2];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
|
||||
argv[1]);
|
||||
fprintf(stderr, usage);
|
||||
exit(1);
|
||||
}
|
||||
switch ( argc )
|
||||
{
|
||||
default:
|
||||
fprintf(stderr, usage);
|
||||
exit(0);
|
||||
case 3:
|
||||
output_name = argv[2];
|
||||
out = fopen(output_name, "w");
|
||||
if ( out == NULL ) {
|
||||
fprintf(stderr, "%s: Cannot open output file %s\n",
|
||||
program_name, output_name);
|
||||
exit(1);
|
||||
}
|
||||
/* falls through */
|
||||
case 2:
|
||||
in = fopen(argv[1], "r");
|
||||
if ( in == NULL ) {
|
||||
fprintf(stderr, "%s: Cannot open input file %s\n",
|
||||
program_name, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
if ( filename == 0 )
|
||||
filename = argv[1];
|
||||
/* falls through */
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
if ( filename )
|
||||
fprintf(out, "#line 1 \"%s\"\n", filename);
|
||||
buf = malloc(bufsize);
|
||||
if ( buf == NULL )
|
||||
{
|
||||
fprintf(stderr, "Unable to allocate read buffer!\n");
|
||||
exit(1);
|
||||
}
|
||||
line = buf;
|
||||
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
||||
{
|
||||
test: line += strlen(line);
|
||||
switch ( test1(buf) )
|
||||
{
|
||||
case 2: /* a function header */
|
||||
convert1(buf, out, 1, convert_varargs);
|
||||
break;
|
||||
case 1: /* a function */
|
||||
/* Check for a { at the start of the next line. */
|
||||
more = ++line;
|
||||
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
|
||||
goto wl;
|
||||
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
|
||||
goto wl;
|
||||
switch ( *skipspace(ppdirforward(more), 1) )
|
||||
{
|
||||
case '{':
|
||||
/* Definitely a function header. */
|
||||
convert1(buf, out, 0, convert_varargs);
|
||||
fputs(more, out);
|
||||
break;
|
||||
case 0:
|
||||
/* The next line was blank or a comment: */
|
||||
/* keep scanning for a non-comment. */
|
||||
line += strlen(line);
|
||||
goto f;
|
||||
default:
|
||||
/* buf isn't a function header, but */
|
||||
/* more might be. */
|
||||
fputs(buf, out);
|
||||
strcpy(buf, more);
|
||||
line = buf;
|
||||
goto test;
|
||||
}
|
||||
break;
|
||||
case -1: /* maybe the start of a function */
|
||||
if ( line != buf + (bufsize - 1) ) /* overflow check */
|
||||
continue;
|
||||
/* falls through */
|
||||
default: /* not a function */
|
||||
wl: fputs(buf, out);
|
||||
break;
|
||||
}
|
||||
line = buf;
|
||||
}
|
||||
if ( line != buf )
|
||||
fputs(buf, out);
|
||||
free(buf);
|
||||
if ( output_name ) {
|
||||
output_error = ferror(out);
|
||||
output_error |= fclose(out);
|
||||
} else { /* out == stdout */
|
||||
fflush(out);
|
||||
output_error = ferror(out);
|
||||
}
|
||||
if ( output_error ) {
|
||||
fprintf(stderr, "%s: error writing to %s\n", program_name,
|
||||
(output_name ? output_name : "stdout"));
|
||||
exit(1);
|
||||
}
|
||||
if ( in != stdin )
|
||||
fclose(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip forward or backward over one or more preprocessor directives.
|
||||
*/
|
||||
char *
|
||||
ppdirforward(p)
|
||||
char *p;
|
||||
{
|
||||
for (; *p == '#'; ++p) {
|
||||
for (; *p != '\r' && *p != '\n'; ++p)
|
||||
if (*p == 0)
|
||||
return p;
|
||||
if (*p == '\r' && p[1] == '\n')
|
||||
++p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
char *
|
||||
ppdirbackward(p, limit)
|
||||
char *p;
|
||||
char *limit;
|
||||
{
|
||||
char *np = p;
|
||||
|
||||
for (;; p = --np) {
|
||||
if (*np == '\n' && np[-1] == '\r')
|
||||
--np;
|
||||
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
|
||||
if (np[-1] == 0)
|
||||
return np;
|
||||
if (*np != '#')
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over whitespace, comments, and preprocessor directives,
|
||||
* in either direction.
|
||||
*/
|
||||
char *
|
||||
skipspace(p, dir)
|
||||
char *p;
|
||||
int dir; /* 1 for forward, -1 for backward */
|
||||
{
|
||||
for ( ; ; ) {
|
||||
while ( is_space(*p) )
|
||||
p += dir;
|
||||
if ( !(*p == '/' && p[dir] == '*') )
|
||||
break;
|
||||
p += dir; p += dir;
|
||||
while ( !(*p == '*' && p[dir] == '/') ) {
|
||||
if ( *p == 0 )
|
||||
return p; /* multi-line comment?? */
|
||||
p += dir;
|
||||
}
|
||||
p += dir; p += dir;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Scan over a quoted string, in either direction. */
|
||||
char *
|
||||
scanstring(p, dir)
|
||||
char *p;
|
||||
int dir;
|
||||
{
|
||||
for (p += dir; ; p += dir)
|
||||
if (*p == '"' && p[-dir] != '\\')
|
||||
return p + dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blanks over part of a string.
|
||||
* Don't overwrite end-of-line characters.
|
||||
*/
|
||||
int
|
||||
writeblanks(start, end)
|
||||
char *start;
|
||||
char *end;
|
||||
{ char *p;
|
||||
for ( p = start; p < end; p++ )
|
||||
if ( *p != '\r' && *p != '\n' )
|
||||
*p = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether the string in buf is a function definition.
|
||||
* The string may contain and/or end with a newline.
|
||||
* Return as follows:
|
||||
* 0 - definitely not a function definition;
|
||||
* 1 - definitely a function definition;
|
||||
* 2 - definitely a function prototype (NOT USED);
|
||||
* -1 - may be the beginning of a function definition,
|
||||
* append another line and look again.
|
||||
* The reason we don't attempt to convert function prototypes is that
|
||||
* Ghostscript's declaration-generating macros look too much like
|
||||
* prototypes, and confuse the algorithms.
|
||||
*/
|
||||
int
|
||||
test1(buf)
|
||||
char *buf;
|
||||
{ char *p = buf;
|
||||
char *bend;
|
||||
char *endfn;
|
||||
int contin;
|
||||
|
||||
if ( !isidfirstchar(*p) )
|
||||
return 0; /* no name at left margin */
|
||||
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
|
||||
switch ( *bend )
|
||||
{
|
||||
case ';': contin = 0 /*2*/; break;
|
||||
case ')': contin = 1; break;
|
||||
case '{': return 0; /* not a function */
|
||||
case '}': return 0; /* not a function */
|
||||
default: contin = -1;
|
||||
}
|
||||
while ( isidchar(*p) )
|
||||
p++;
|
||||
endfn = p;
|
||||
p = skipspace(p, 1);
|
||||
if ( *p++ != '(' )
|
||||
return 0; /* not a function */
|
||||
p = skipspace(p, 1);
|
||||
if ( *p == ')' )
|
||||
return 0; /* no parameters */
|
||||
/* Check that the apparent function name isn't a keyword. */
|
||||
/* We only need to check for keywords that could be followed */
|
||||
/* by a left parenthesis (which, unfortunately, is most of them). */
|
||||
{ static char *words[] =
|
||||
{ "asm", "auto", "case", "char", "const", "double",
|
||||
"extern", "float", "for", "if", "int", "long",
|
||||
"register", "return", "short", "signed", "sizeof",
|
||||
"static", "switch", "typedef", "unsigned",
|
||||
"void", "volatile", "while", 0
|
||||
};
|
||||
char **key = words;
|
||||
char *kp;
|
||||
unsigned len = endfn - buf;
|
||||
|
||||
while ( (kp = *key) != 0 )
|
||||
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
||||
return 0; /* name is a keyword */
|
||||
key++;
|
||||
}
|
||||
}
|
||||
{
|
||||
char *id = p;
|
||||
int len;
|
||||
/*
|
||||
* Check for identifier1(identifier2) and not
|
||||
* identifier1(void), or identifier1(identifier2, xxxx).
|
||||
*/
|
||||
|
||||
while ( isidchar(*p) )
|
||||
p++;
|
||||
len = p - id;
|
||||
p = skipspace(p, 1);
|
||||
if (*p == ',' ||
|
||||
(*p == ')' && (len != 4 || strncmp(id, "void", 4)))
|
||||
)
|
||||
return 0; /* not a function */
|
||||
}
|
||||
/*
|
||||
* If the last significant character was a ), we need to count
|
||||
* parentheses, because it might be part of a formal parameter
|
||||
* that is a procedure.
|
||||
*/
|
||||
if (contin > 0) {
|
||||
int level = 0;
|
||||
|
||||
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
|
||||
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
|
||||
if (level > 0)
|
||||
contin = -1;
|
||||
}
|
||||
return contin;
|
||||
}
|
||||
|
||||
/* Convert a recognized function definition or header to K&R syntax. */
|
||||
int
|
||||
convert1(buf, out, header, convert_varargs)
|
||||
char *buf;
|
||||
FILE *out;
|
||||
int header; /* Boolean */
|
||||
int convert_varargs; /* Boolean */
|
||||
{ char *endfn;
|
||||
char *p;
|
||||
/*
|
||||
* The breaks table contains pointers to the beginning and end
|
||||
* of each argument.
|
||||
*/
|
||||
char **breaks;
|
||||
unsigned num_breaks = 2; /* for testing */
|
||||
char **btop;
|
||||
char **bp;
|
||||
char **ap;
|
||||
char *vararg = 0;
|
||||
|
||||
/* Pre-ANSI implementations don't agree on whether strchr */
|
||||
/* is called strchr or index, so we open-code it here. */
|
||||
for ( endfn = buf; *(endfn++) != '('; )
|
||||
;
|
||||
top: p = endfn;
|
||||
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
||||
if ( breaks == NULL )
|
||||
{ /* Couldn't allocate break table, give up */
|
||||
fprintf(stderr, "Unable to allocate break table!\n");
|
||||
fputs(buf, out);
|
||||
return -1;
|
||||
}
|
||||
btop = breaks + num_breaks * 2 - 2;
|
||||
bp = breaks;
|
||||
/* Parse the argument list */
|
||||
do
|
||||
{ int level = 0;
|
||||
char *lp = NULL;
|
||||
char *rp = NULL;
|
||||
char *end = NULL;
|
||||
|
||||
if ( bp >= btop )
|
||||
{ /* Filled up break table. */
|
||||
/* Allocate a bigger one and start over. */
|
||||
free((char *)breaks);
|
||||
num_breaks <<= 1;
|
||||
goto top;
|
||||
}
|
||||
*bp++ = p;
|
||||
/* Find the end of the argument */
|
||||
for ( ; end == NULL; p++ )
|
||||
{ switch(*p)
|
||||
{
|
||||
case ',':
|
||||
if ( !level ) end = p;
|
||||
break;
|
||||
case '(':
|
||||
if ( !level ) lp = p;
|
||||
level++;
|
||||
break;
|
||||
case ')':
|
||||
if ( --level < 0 ) end = p;
|
||||
else rp = p;
|
||||
break;
|
||||
case '/':
|
||||
if (p[1] == '*')
|
||||
p = skipspace(p, 1) - 1;
|
||||
break;
|
||||
case '"':
|
||||
p = scanstring(p, 1) - 1;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
/* Erase any embedded prototype parameters. */
|
||||
if ( lp && rp )
|
||||
writeblanks(lp + 1, rp);
|
||||
p--; /* back up over terminator */
|
||||
/* Find the name being declared. */
|
||||
/* This is complicated because of procedure and */
|
||||
/* array modifiers. */
|
||||
for ( ; ; )
|
||||
{ p = skipspace(p - 1, -1);
|
||||
switch ( *p )
|
||||
{
|
||||
case ']': /* skip array dimension(s) */
|
||||
case ')': /* skip procedure args OR name */
|
||||
{ int level = 1;
|
||||
while ( level )
|
||||
switch ( *--p )
|
||||
{
|
||||
case ']': case ')':
|
||||
level++;
|
||||
break;
|
||||
case '[': case '(':
|
||||
level--;
|
||||
break;
|
||||
case '/':
|
||||
if (p > buf && p[-1] == '*')
|
||||
p = skipspace(p, -1) + 1;
|
||||
break;
|
||||
case '"':
|
||||
p = scanstring(p, -1) + 1;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
||||
{ /* We found the name being declared */
|
||||
while ( !isidfirstchar(*p) )
|
||||
p = skipspace(p, 1) + 1;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
||||
{ if ( convert_varargs )
|
||||
{ *bp++ = "va_alist";
|
||||
vararg = p-2;
|
||||
}
|
||||
else
|
||||
{ p++;
|
||||
if ( bp == breaks + 1 ) /* sole argument */
|
||||
writeblanks(breaks[0], p);
|
||||
else
|
||||
writeblanks(bp[-1] - 1, p);
|
||||
bp--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ while ( isidchar(*p) ) p--;
|
||||
*bp++ = p+1;
|
||||
}
|
||||
p = end;
|
||||
}
|
||||
while ( *p++ == ',' );
|
||||
*bp = p;
|
||||
/* Make a special check for 'void' arglist */
|
||||
if ( bp == breaks+2 )
|
||||
{ p = skipspace(breaks[0], 1);
|
||||
if ( !strncmp(p, "void", 4) )
|
||||
{ p = skipspace(p+4, 1);
|
||||
if ( p == breaks[2] - 1 )
|
||||
{ bp = breaks; /* yup, pretend arglist is empty */
|
||||
writeblanks(breaks[0], p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Put out the function name and left parenthesis. */
|
||||
p = buf;
|
||||
while ( p != endfn ) putc(*p, out), p++;
|
||||
/* Put out the declaration. */
|
||||
if ( header )
|
||||
{ fputs(");", out);
|
||||
for ( p = breaks[0]; *p; p++ )
|
||||
if ( *p == '\r' || *p == '\n' )
|
||||
putc(*p, out);
|
||||
}
|
||||
else
|
||||
{ for ( ap = breaks+1; ap < bp; ap += 2 )
|
||||
{ p = *ap;
|
||||
while ( isidchar(*p) )
|
||||
putc(*p, out), p++;
|
||||
if ( ap < bp - 1 )
|
||||
fputs(", ", out);
|
||||
}
|
||||
fputs(") ", out);
|
||||
/* Put out the argument declarations */
|
||||
for ( ap = breaks+2; ap <= bp; ap += 2 )
|
||||
(*ap)[-1] = ';';
|
||||
if ( vararg != 0 )
|
||||
{ *vararg = 0;
|
||||
fputs(breaks[0], out); /* any prior args */
|
||||
fputs("va_dcl", out); /* the final arg */
|
||||
fputs(bp[0], out);
|
||||
}
|
||||
else
|
||||
fputs(breaks[0], out);
|
||||
}
|
||||
free((char *)breaks);
|
||||
return 0;
|
||||
}
|
||||
163
src/arith.c
163
src/arith.c
@@ -1,163 +0,0 @@
|
||||
/* Arithmetic for numbers greater than a long int, for GNU tar.
|
||||
Copyright (C) 1996, 1997 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 2, 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, write to the Free Software Foundation, Inc.,
|
||||
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */
|
||||
#include "common.h"
|
||||
|
||||
/* GNU tar needs handling numbers exceeding 32 bits, which is the size of
|
||||
unsigned long ints for many C compilers. This module should provide
|
||||
machinery for handling at least BITS_PER_TARLONG bits per number. If
|
||||
`long long' ints are available and are sufficient for the task, they will
|
||||
be used preferrably.
|
||||
|
||||
Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on
|
||||
Ampex drives), so requiring 38 bits for the tape length in bytes. He
|
||||
also reports breaking the terabyte limit with a single file (using SGI
|
||||
xFS file system over 37 28GB disk arrays attached to a Power Challenge
|
||||
XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a
|
||||
little more than 40 bits for the file size in bytes. The POSIX header
|
||||
structure allows for 12 octal digits to represent file lengths, that is,
|
||||
up to 36 bits for the byte size of files.
|
||||
|
||||
If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be
|
||||
set to zero by configure. In this case, or if `long long' ints does not
|
||||
have enough bits, then huge numbers are rather represented by an array of
|
||||
longs, with the least significant super-digit at position 0. For making
|
||||
multiplication and decimal input/output easy, the base of a super-digit
|
||||
is an exact exponent of 10, and is such that base*base fits in a long. */
|
||||
|
||||
#if SUPERDIGIT
|
||||
|
||||
/*-------------------------------.
|
||||
| Check if ACCUMULATOR is zero. |
|
||||
`-------------------------------*/
|
||||
|
||||
int
|
||||
zerop_tarlong_helper (unsigned long *accumulator)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
|
||||
if (accumulator[counter])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------.
|
||||
| Check if FIRST is strictly less than SECOND. |
|
||||
`----------------------------------------------*/
|
||||
|
||||
int
|
||||
lessp_tarlong_helper (unsigned long *first, unsigned long *second)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
|
||||
if (first[counter] != second[counter])
|
||||
return first[counter] < second[counter];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------.
|
||||
| Reset ACCUMULATOR to zero. |
|
||||
`----------------------------*/
|
||||
|
||||
void
|
||||
clear_tarlong_helper (unsigned long *accumulator)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
accumulator[counter] = 0;
|
||||
}
|
||||
|
||||
/*----------------------------.
|
||||
| To ACCUMULATOR, add VALUE. |
|
||||
`----------------------------*/
|
||||
|
||||
void
|
||||
add_to_tarlong_helper (unsigned long *accumulator, int value)
|
||||
{
|
||||
int counter;
|
||||
|
||||
if (value < 0)
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
{
|
||||
if (accumulator[counter] >= -value)
|
||||
{
|
||||
accumulator[counter] += value;
|
||||
return;
|
||||
}
|
||||
accumulator[counter] += value + SUPERDIGIT;
|
||||
value = -1;
|
||||
}
|
||||
else
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
{
|
||||
if (accumulator[counter] + value < SUPERDIGIT)
|
||||
{
|
||||
accumulator[counter] += value;
|
||||
return;
|
||||
}
|
||||
accumulator[counter] += value - SUPERDIGIT;
|
||||
value = 1;
|
||||
}
|
||||
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
|
||||
}
|
||||
|
||||
/*--------------------------------.
|
||||
| Multiply ACCUMULATOR by VALUE. |
|
||||
`--------------------------------*/
|
||||
|
||||
void
|
||||
mult_tarlong_helper (unsigned long *accumulator, int value)
|
||||
{
|
||||
int carry = 0;
|
||||
int counter;
|
||||
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
{
|
||||
carry += accumulator[counter] * value;
|
||||
accumulator[counter] = carry % SUPERDIGIT;
|
||||
carry /= SUPERDIGIT;
|
||||
}
|
||||
if (carry)
|
||||
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------.
|
||||
| Print the decimal representation of ACCUMULATOR on FILE. |
|
||||
`----------------------------------------------------------*/
|
||||
|
||||
void
|
||||
print_tarlong_helper (unsigned long *accumulator, FILE *file)
|
||||
{
|
||||
int counter = LONGS_PER_TARLONG - 1;
|
||||
|
||||
while (counter > 0 && accumulator[counter] == 0)
|
||||
counter--;
|
||||
|
||||
fprintf (file, "%uld", accumulator[counter]);
|
||||
while (counter > 0)
|
||||
fprintf (file, TARLONG_FORMAT, accumulator[--counter]);
|
||||
}
|
||||
|
||||
#endif /* SUPERDIGIT */
|
||||
222
src/buffer.c
222
src/buffer.c
@@ -1,7 +1,8 @@
|
||||
/* Buffer management for tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-25.
|
||||
|
||||
@@ -35,9 +36,6 @@
|
||||
/* Number of retries before giving up on read. */
|
||||
#define READ_ERROR_MAX 10
|
||||
|
||||
/* Globbing pattern to append to volume label if initial match failed. */
|
||||
#define VOLUME_LABEL_APPEND " Volume [1-9]*"
|
||||
|
||||
/* Variables. */
|
||||
|
||||
static tarlong prev_written; /* bytes written on previous volumes */
|
||||
@@ -203,6 +201,7 @@ enum compress_type {
|
||||
ct_compress,
|
||||
ct_gzip,
|
||||
ct_bzip2,
|
||||
ct_lzip,
|
||||
ct_lzma,
|
||||
ct_lzop,
|
||||
ct_xz
|
||||
@@ -220,12 +219,13 @@ struct zip_magic
|
||||
static struct zip_magic const magic[] = {
|
||||
{ ct_tar },
|
||||
{ ct_none, },
|
||||
{ ct_compress, 2, "\037\235", "compress", "-Z" },
|
||||
{ ct_gzip, 2, "\037\213", "gzip", "-z" },
|
||||
{ ct_bzip2, 3, "BZh", "bzip2", "-j" },
|
||||
{ ct_lzma, 6, "\xFFLZMA", "lzma", "--lzma" }, /* FIXME: ???? */
|
||||
{ ct_lzop, 4, "\211LZO", "lzop", "--lzop" },
|
||||
{ ct_xz, 6, "\0xFD7zXZ", "-J" },
|
||||
{ ct_compress, 2, "\037\235", COMPRESS_PROGRAM, "-Z" },
|
||||
{ ct_gzip, 2, "\037\213", GZIP_PROGRAM, "-z" },
|
||||
{ ct_bzip2, 3, "BZh", BZIP2_PROGRAM, "-j" },
|
||||
{ ct_lzip, 4, "LZIP", LZIP_PROGRAM, "--lzip" },
|
||||
{ ct_lzma, 6, "\xFFLZMA", LZMA_PROGRAM, "--lzma" },
|
||||
{ ct_lzop, 4, "\211LZO", LZOP_PROGRAM, "--lzop" },
|
||||
{ ct_xz, 6, "\0xFD7zXZ", XZ_PROGRAM, "-J" },
|
||||
};
|
||||
|
||||
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
|
||||
@@ -265,6 +265,37 @@ check_compressed_archive (bool *pshort)
|
||||
return ct_none;
|
||||
}
|
||||
|
||||
/* Guess if the archive is seekable. */
|
||||
static void
|
||||
guess_seekable_archive ()
|
||||
{
|
||||
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 */
|
||||
@@ -295,7 +326,7 @@ open_compressed_archive ()
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
set_comression_program_by_suffix (archive_name_array[0], NULL);
|
||||
if (!use_compress_program_option)
|
||||
return archive;
|
||||
return archive;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -306,7 +337,7 @@ open_compressed_archive ()
|
||||
|
||||
/* FD is not needed any more */
|
||||
rmtclose (archive);
|
||||
|
||||
|
||||
hit_eof = false; /* It might have been set by find_next_block in
|
||||
check_compressed_archive */
|
||||
|
||||
@@ -565,6 +596,8 @@ _open_archive (enum access_mode wanted_access)
|
||||
{
|
||||
case ACCESS_READ:
|
||||
archive = open_compressed_archive ();
|
||||
if (archive >= 0)
|
||||
guess_seekable_archive ();
|
||||
break;
|
||||
|
||||
case ACCESS_WRITE:
|
||||
@@ -679,6 +712,19 @@ archive_read_error (void)
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
archive_is_dev ()
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (fstat (archive, &st))
|
||||
{
|
||||
stat_diag (*archive_name_cursor);
|
||||
return false;
|
||||
}
|
||||
return S_ISBLK (st.st_mode) || S_ISCHR (st.st_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
short_read (size_t status)
|
||||
{
|
||||
@@ -690,7 +736,8 @@ short_read (size_t status)
|
||||
|
||||
if (left && left % BLOCKSIZE == 0
|
||||
&& verbose_option
|
||||
&& record_start_block == 0 && status != 0)
|
||||
&& record_start_block == 0 && status != 0
|
||||
&& archive_is_dev ())
|
||||
{
|
||||
unsigned long rsize = status / BLOCKSIZE;
|
||||
WARN ((0, 0,
|
||||
@@ -809,16 +856,16 @@ seek_archive (off_t size)
|
||||
off_t start = current_block_ordinal ();
|
||||
off_t offset;
|
||||
off_t nrec, nblk;
|
||||
off_t skipped = (blocking_factor - (current_block - record_start));
|
||||
off_t skipped = (blocking_factor - (current_block - record_start))
|
||||
* BLOCKSIZE;
|
||||
|
||||
size -= skipped * BLOCKSIZE;
|
||||
|
||||
if (size < record_size)
|
||||
if (size <= skipped)
|
||||
return 0;
|
||||
/* FIXME: flush? */
|
||||
|
||||
|
||||
/* Compute number of records to skip */
|
||||
nrec = size / record_size;
|
||||
nrec = (size - skipped) / record_size;
|
||||
if (nrec == 0)
|
||||
return 0;
|
||||
offset = rmtlseek (archive, nrec * record_size, SEEK_CUR);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
@@ -1084,6 +1131,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:
|
||||
@@ -1119,7 +1167,7 @@ read_header0 (struct tar_stat_info *info)
|
||||
enum read_header rc;
|
||||
|
||||
tar_stat_init (info);
|
||||
rc = read_header_primitive (false, info);
|
||||
rc = read_header (¤t_header, info, read_header_auto);
|
||||
if (rc == HEADER_SUCCESS)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
@@ -1167,17 +1215,42 @@ try_new_volume ()
|
||||
{
|
||||
case XGLTYPE:
|
||||
{
|
||||
if (!read_header0 (&dummy))
|
||||
return false;
|
||||
tar_stat_init (&dummy);
|
||||
if (read_header (&header, &dummy, read_header_x_global)
|
||||
!= HEADER_SUCCESS_EXTENDED)
|
||||
{
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
return false;
|
||||
}
|
||||
|
||||
xheader_decode (&dummy); /* decodes values from the global header */
|
||||
tar_stat_destroy (&dummy);
|
||||
if (!real_s_name)
|
||||
{
|
||||
/* We have read the extended header of the first member in
|
||||
this volume. Put it back, so next read_header works as
|
||||
expected. */
|
||||
current_block = record_start;
|
||||
}
|
||||
|
||||
/* The initial global header must be immediately followed by
|
||||
an extended PAX header for the first member in this volume.
|
||||
However, in some cases tar may split volumes in the middle
|
||||
of a PAX header. This is incorrect, and should be fixed
|
||||
in the future versions. In the meantime we must be
|
||||
prepared to correctly list and extract such archives.
|
||||
|
||||
If this happens, the following call to read_header returns
|
||||
HEADER_FAILURE, which is ignored.
|
||||
|
||||
See also tests/multiv07.at */
|
||||
|
||||
switch (read_header (&header, &dummy, read_header_auto))
|
||||
{
|
||||
case HEADER_SUCCESS:
|
||||
set_next_block_after (header);
|
||||
break;
|
||||
|
||||
case HEADER_FAILURE:
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1264,31 +1337,57 @@ try_new_volume ()
|
||||
}
|
||||
|
||||
|
||||
/* Check the LABEL block against the volume label, seen as a globbing
|
||||
#define VOLUME_TEXT " Volume "
|
||||
#define VOLUME_TEXT_LEN (sizeof VOLUME_TEXT - 1)
|
||||
|
||||
char *
|
||||
drop_volume_label_suffix (const char *label)
|
||||
{
|
||||
const char *p;
|
||||
size_t len = strlen (label);
|
||||
|
||||
if (len < 1)
|
||||
return NULL;
|
||||
|
||||
for (p = label + len - 1; p > label && isdigit ((unsigned char) *p); p--)
|
||||
;
|
||||
if (p > label && p - (VOLUME_TEXT_LEN - 1) > label)
|
||||
{
|
||||
p -= VOLUME_TEXT_LEN - 1;
|
||||
if (memcmp (p, VOLUME_TEXT, VOLUME_TEXT_LEN) == 0)
|
||||
{
|
||||
char *s = xmalloc ((len = p - label) + 1);
|
||||
memcpy (s, label, len);
|
||||
s[len] = 0;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check LABEL against the volume label, seen as a globbing
|
||||
pattern. Return true if the pattern matches. In case of failure,
|
||||
retry matching a volume sequence number before giving up in
|
||||
multi-volume mode. */
|
||||
static bool
|
||||
check_label_pattern (union block *label)
|
||||
check_label_pattern (const char *label)
|
||||
{
|
||||
char *string;
|
||||
bool result;
|
||||
|
||||
if (! memchr (label->header.name, '\0', sizeof label->header.name))
|
||||
return false;
|
||||
|
||||
if (fnmatch (volume_label_option, label->header.name, 0) == 0)
|
||||
if (fnmatch (volume_label_option, label, 0) == 0)
|
||||
return true;
|
||||
|
||||
if (!multi_volume_option)
|
||||
return false;
|
||||
|
||||
string = xmalloc (strlen (volume_label_option)
|
||||
+ sizeof VOLUME_LABEL_APPEND + 1);
|
||||
strcpy (string, volume_label_option);
|
||||
strcat (string, VOLUME_LABEL_APPEND);
|
||||
result = fnmatch (string, label->header.name, 0) == 0;
|
||||
free (string);
|
||||
string = drop_volume_label_suffix (label);
|
||||
if (string)
|
||||
{
|
||||
result = fnmatch (string, volume_label_option, 0) == 0;
|
||||
free (string);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1297,14 +1396,43 @@ check_label_pattern (union block *label)
|
||||
static void
|
||||
match_volume_label (void)
|
||||
{
|
||||
union block *label = find_next_block ();
|
||||
|
||||
if (!label)
|
||||
if (!volume_label)
|
||||
{
|
||||
union block *label = find_next_block ();
|
||||
|
||||
if (!label)
|
||||
FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
|
||||
quote (volume_label_option)));
|
||||
if (label->header.typeflag == GNUTYPE_VOLHDR)
|
||||
{
|
||||
if (memchr (label->header.name, '\0', sizeof label->header.name))
|
||||
assign_string (&volume_label, label->header.name);
|
||||
else
|
||||
{
|
||||
volume_label = xmalloc (sizeof (label->header.name) + 1);
|
||||
memcpy (volume_label, label->header.name,
|
||||
sizeof (label->header.name));
|
||||
volume_label[sizeof (label->header.name)] = 0;
|
||||
}
|
||||
}
|
||||
else if (label->header.typeflag == XGLTYPE)
|
||||
{
|
||||
struct tar_stat_info st;
|
||||
tar_stat_init (&st);
|
||||
xheader_read (&st.xhdr, label,
|
||||
OFF_FROM_HEADER (label->header.size));
|
||||
xheader_decode (&st);
|
||||
tar_stat_destroy (&st);
|
||||
}
|
||||
}
|
||||
|
||||
if (!volume_label)
|
||||
FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
|
||||
quote (volume_label_option)));
|
||||
if (!check_label_pattern (label))
|
||||
|
||||
if (!check_label_pattern (volume_label))
|
||||
FATAL_ERROR ((0, 0, _("Volume %s does not match %s"),
|
||||
quote_n (0, label->header.name),
|
||||
quote_n (0, volume_label),
|
||||
quote_n (1, volume_label_option)));
|
||||
}
|
||||
|
||||
|
||||
159
src/common.h
159
src/common.h
@@ -1,7 +1,8 @@
|
||||
/* Common declarations for the tar program.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
|
||||
@@ -60,6 +61,8 @@
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
#include <obstack.h>
|
||||
#include <progname.h>
|
||||
#include <xvasprintf.h>
|
||||
|
||||
#include <paxlib.h>
|
||||
|
||||
@@ -70,9 +73,6 @@
|
||||
|
||||
/* Information gleaned from the command line. */
|
||||
|
||||
/* Name of this program. */
|
||||
GLOBAL const char *program_name;
|
||||
|
||||
/* Main command option. */
|
||||
|
||||
enum subcommand
|
||||
@@ -85,7 +85,8 @@ enum subcommand
|
||||
DIFF_SUBCOMMAND, /* -d */
|
||||
EXTRACT_SUBCOMMAND, /* -x */
|
||||
LIST_SUBCOMMAND, /* -t */
|
||||
UPDATE_SUBCOMMAND /* -u */
|
||||
UPDATE_SUBCOMMAND, /* -u */
|
||||
TEST_LABEL_SUBCOMMAND, /* --test-label */
|
||||
};
|
||||
|
||||
GLOBAL enum subcommand subcommand_option;
|
||||
@@ -185,6 +186,8 @@ GLOBAL enum old_files old_files_option;
|
||||
|
||||
/* Specified file name for incremental list. */
|
||||
GLOBAL const char *listed_incremental_option;
|
||||
/* Incremental dump level */
|
||||
GLOBAL int incremental_level;
|
||||
/* Check device numbers when doing incremental dumps. */
|
||||
GLOBAL bool check_device_option;
|
||||
|
||||
@@ -318,25 +321,41 @@ GLOBAL const char **archive_name_cursor;
|
||||
/* Output index file name. */
|
||||
GLOBAL char const *index_file_name;
|
||||
|
||||
/* Opaque structure for keeping directory meta-data */
|
||||
struct directory;
|
||||
|
||||
/* Structure for keeping track of filenames and lists thereof. */
|
||||
struct name
|
||||
{
|
||||
struct name *next; /* Link to the next element */
|
||||
struct name *prev; /* Link to the previous element */
|
||||
|
||||
char *name; /* File name or globbing pattern */
|
||||
size_t length; /* cached strlen (name) */
|
||||
int matching_flags; /* wildcard flags if name is a pattern */
|
||||
bool cmdline; /* true if this name was given in the
|
||||
command line */
|
||||
|
||||
int change_dir; /* Number of the directory to change to.
|
||||
Set with the -C option. */
|
||||
uintmax_t found_count; /* number of times a matching file has
|
||||
been found */
|
||||
int matching_flags; /* this name is a regexp, not literal */
|
||||
char const *dir_contents; /* for incremental_option */
|
||||
|
||||
size_t length; /* cached strlen(name) */
|
||||
char name[1];
|
||||
|
||||
/* The following members are used for incremental dumps only,
|
||||
if this struct name represents a directory;
|
||||
see incremen.c */
|
||||
struct directory *directory;/* directory meta-data and contents */
|
||||
struct name *parent; /* pointer to the parent hierarchy */
|
||||
struct name *child; /* pointer to the first child */
|
||||
struct name *sibling; /* pointer to the next sibling */
|
||||
char *caname; /* canonical name */
|
||||
};
|
||||
|
||||
/* Obnoxious test to see if dimwit is trying to dump the archive. */
|
||||
GLOBAL dev_t ar_dev;
|
||||
GLOBAL ino_t ar_ino;
|
||||
|
||||
GLOBAL int seek_option;
|
||||
GLOBAL bool seekable_archive;
|
||||
|
||||
GLOBAL dev_t root_device;
|
||||
@@ -344,8 +363,6 @@ GLOBAL dev_t root_device;
|
||||
/* Unquote filenames */
|
||||
GLOBAL bool unquote_option;
|
||||
|
||||
GLOBAL bool test_label_option; /* Test archive volume label and exit */
|
||||
|
||||
/* Show file or archive names after transformation.
|
||||
In particular, when creating archive in verbose mode, list member names
|
||||
as stored in the archive */
|
||||
@@ -379,9 +396,13 @@ extern enum access_mode access_mode;
|
||||
extern FILE *stdlis;
|
||||
extern bool write_archive_to_stdout;
|
||||
extern char *volume_label;
|
||||
extern size_t volume_label_count;
|
||||
extern char *continued_file_name;
|
||||
extern uintmax_t continued_file_size;
|
||||
extern uintmax_t continued_file_offset;
|
||||
extern off_t records_written;
|
||||
|
||||
char *drop_volume_label_suffix (const char *label);
|
||||
|
||||
size_t available_space_after (union block *pointer);
|
||||
off_t current_block_ordinal (void);
|
||||
@@ -428,19 +449,19 @@ bool cachedir_file_p (const char *name);
|
||||
bool file_dumpable_p (struct tar_stat_info *st);
|
||||
void create_archive (void);
|
||||
void pad_archive (off_t size_left);
|
||||
void dump_file (const char *st, int top_level, dev_t parent_device);
|
||||
void dump_file (const char *st, bool top_level, dev_t parent_device);
|
||||
union block *start_header (struct tar_stat_info *st);
|
||||
void finish_header (struct tar_stat_info *st, union block *header,
|
||||
off_t block_ordinal);
|
||||
void simple_finish_header (union block *header);
|
||||
union block * write_extended (bool global, struct tar_stat_info *st,
|
||||
union block *old_header);
|
||||
union block *start_private_header (const char *name, size_t size);
|
||||
union block *start_private_header (const char *name, size_t size, time_t t);
|
||||
void write_eot (void);
|
||||
void check_links (void);
|
||||
void exclusion_tag_warning (const char *dirname, const char *tagname,
|
||||
const char *message);
|
||||
enum exclusion_tag_type check_exclusion_tags (char *dirname,
|
||||
enum exclusion_tag_type check_exclusion_tags (const char *dirname,
|
||||
const char **tag_file_name);
|
||||
|
||||
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
|
||||
@@ -496,9 +517,16 @@ char *dumpdir_locate (dumpdir_t dump, const char *name);
|
||||
char *dumpdir_next (dumpdir_iter_t itr);
|
||||
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
|
||||
|
||||
struct directory *scan_directory (char *dir, dev_t device, bool cmdline);
|
||||
void name_fill_directory (struct name *name, dev_t device, bool cmdline);
|
||||
const char *directory_contents (struct directory *dir);
|
||||
const char *safe_directory_contents (struct directory *dir);
|
||||
|
||||
const char *get_directory_contents (char *dir_name, dev_t device);
|
||||
const char *append_incremental_renames (const char *dump);
|
||||
void rebase_directory (struct directory *dir,
|
||||
const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen);
|
||||
|
||||
void append_incremental_renames (struct directory *dir);
|
||||
void read_directory_file (void);
|
||||
void write_directory_file (void);
|
||||
void purge_directory (char const *directory_name);
|
||||
@@ -520,6 +548,17 @@ enum read_header
|
||||
HEADER_FAILURE /* ill-formed header, or bad checksum */
|
||||
};
|
||||
|
||||
/* Operation mode for read_header: */
|
||||
|
||||
enum read_header_mode
|
||||
{
|
||||
read_header_auto, /* process extended headers automatically */
|
||||
read_header_x_raw, /* return raw extended headers (return
|
||||
HEADER_SUCCESS_EXTENDED) */
|
||||
read_header_x_global /* when POSIX global extended header is read,
|
||||
decode it and return
|
||||
HEADER_SUCCESS_EXTENDED */
|
||||
};
|
||||
extern union block *current_header;
|
||||
extern enum archive_format current_format;
|
||||
extern size_t recent_long_name_blocks;
|
||||
@@ -532,7 +571,8 @@ char const *tartime (struct timespec t, bool full_time);
|
||||
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
|
||||
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
|
||||
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
|
||||
#define MODE_FROM_HEADER(where) mode_from_header (where, sizeof (where))
|
||||
#define MODE_FROM_HEADER(where, hbits) \
|
||||
mode_from_header (where, sizeof (where), hbits)
|
||||
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
|
||||
#define SIZE_FROM_HEADER(where) size_from_header (where, sizeof (where))
|
||||
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
|
||||
@@ -542,20 +582,22 @@ char const *tartime (struct timespec t, bool full_time);
|
||||
gid_t gid_from_header (const char *buf, size_t size);
|
||||
major_t major_from_header (const char *buf, size_t size);
|
||||
minor_t minor_from_header (const char *buf, size_t size);
|
||||
mode_t mode_from_header (const char *buf, size_t size);
|
||||
mode_t mode_from_header (const char *buf, size_t size, unsigned *hbits);
|
||||
off_t off_from_header (const char *buf, size_t size);
|
||||
size_t size_from_header (const char *buf, size_t size);
|
||||
time_t time_from_header (const char *buf, size_t size);
|
||||
uid_t uid_from_header (const char *buf, size_t size);
|
||||
uintmax_t uintmax_from_header (const char * buf, size_t size);
|
||||
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, int length, mode_t mode);
|
||||
void print_header (struct tar_stat_info *st, off_t block_ordinal);
|
||||
void print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal);
|
||||
void read_and (void (*do_something) (void));
|
||||
enum read_header read_header_primitive (bool raw_extended_headers,
|
||||
struct tar_stat_info *info);
|
||||
enum read_header read_header (bool raw_extended_headers);
|
||||
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 skip_file (off_t size);
|
||||
void skip_member (void);
|
||||
@@ -565,6 +607,15 @@ void skip_member (void);
|
||||
void assign_string (char **dest, const char *src);
|
||||
char *quote_copy_string (const char *str);
|
||||
int unquote_string (char *str);
|
||||
char *zap_slashes (char *name);
|
||||
char *normalize_filename (const char *name);
|
||||
void replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen);
|
||||
|
||||
typedef struct namebuf *namebuf_t;
|
||||
namebuf_t namebuf_create (const char *dir);
|
||||
void namebuf_free (namebuf_t buf);
|
||||
char *namebuf_name (namebuf_t buf, const char *name);
|
||||
|
||||
void code_ns_fraction (int ns, char *p);
|
||||
char const *code_timespec (struct timespec ts, char *sbuf);
|
||||
@@ -594,6 +645,7 @@ int deref_stat (bool deref, char const *name, struct stat *buf);
|
||||
|
||||
int chdir_arg (char const *dir);
|
||||
void chdir_do (int dir);
|
||||
int chdir_count (void);
|
||||
|
||||
void close_diag (char const *name);
|
||||
void open_diag (char const *name);
|
||||
@@ -602,6 +654,10 @@ void readlink_diag (char const *name);
|
||||
void savedir_diag (char const *name);
|
||||
void seek_diag_details (char const *name, off_t offset);
|
||||
void stat_diag (char const *name);
|
||||
void file_removed_diag (const char *name, bool top_level,
|
||||
void (*diagfn) (char const *name));
|
||||
void dir_removed_diag (char const *name, bool top_level,
|
||||
void (*diagfn) (char const *name));
|
||||
void write_error_details (char const *name, size_t status, size_t size);
|
||||
void write_fatal (char const *name) __attribute__ ((noreturn));
|
||||
void write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
@@ -629,12 +685,14 @@ void name_add_dir (const char *name);
|
||||
void name_term (void);
|
||||
const char *name_next (int change_dirs);
|
||||
void name_gather (void);
|
||||
struct name *addname (char const *string, int change_dir);
|
||||
struct name *addname (char const *string, int change_dir,
|
||||
bool cmdline, struct name *parent);
|
||||
void remname (struct name *name);
|
||||
bool name_match (const char *name);
|
||||
void names_notfound (void);
|
||||
void collect_and_sort_names (void);
|
||||
struct name *name_scan (const char *name);
|
||||
char *name_from_list (void);
|
||||
struct name const *name_from_list (void);
|
||||
void blank_name_list (void);
|
||||
char *new_name (const char *dir_name, const char *name);
|
||||
size_t stripped_prefix_len (char const *file_name, size_t num);
|
||||
@@ -666,6 +724,7 @@ 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);
|
||||
void set_exit_status (int val);
|
||||
|
||||
/* Module update.c. */
|
||||
|
||||
@@ -681,7 +740,7 @@ void xheader_decode_global (struct xheader *xhdr);
|
||||
void xheader_store (char const *keyword, struct tar_stat_info *st,
|
||||
void const *data);
|
||||
void xheader_read (struct xheader *xhdr, union block *header, size_t size);
|
||||
void xheader_write (char type, char *name, struct xheader *xhdr);
|
||||
void xheader_write (char type, char *name, time_t t, struct xheader *xhdr);
|
||||
void xheader_write_global (struct xheader *xhdr);
|
||||
void xheader_finish (struct xheader *hdr);
|
||||
void xheader_destroy (struct xheader *hdr);
|
||||
@@ -752,3 +811,49 @@ void set_comression_program_by_suffix (const char *name, const char *defprog);
|
||||
void checkpoint_compile_action (const char *str);
|
||||
void checkpoint_finish_compile (void);
|
||||
void checkpoint_run (bool do_write);
|
||||
|
||||
/* Module warning.c */
|
||||
#define WARN_ALONE_ZERO_BLOCK 0x00000001
|
||||
#define WARN_BAD_DUMPDIR 0x00000002
|
||||
#define WARN_CACHEDIR 0x00000004
|
||||
#define WARN_CONTIGUOUS_CAST 0x00000008
|
||||
#define WARN_FILE_CHANGED 0x00000010
|
||||
#define WARN_FILE_IGNORED 0x00000020
|
||||
#define WARN_FILE_REMOVED 0x00000040
|
||||
#define WARN_FILE_SHRANK 0x00000080
|
||||
#define WARN_FILE_UNCHANGED 0x00000100
|
||||
#define WARN_FILENAME_WITH_NULS 0x00000200
|
||||
#define WARN_IGNORE_ARCHIVE 0x00000400
|
||||
#define WARN_IGNORE_NEWER 0x00000800
|
||||
#define WARN_NEW_DIRECTORY 0x00001000
|
||||
#define WARN_RENAME_DIRECTORY 0x00002000
|
||||
#define WARN_SYMLINK_CAST 0x00004000
|
||||
#define WARN_TIMESTAMP 0x00008000
|
||||
#define WARN_UNKNOWN_CAST 0x00010000
|
||||
#define WARN_UNKNOWN_KEYWORD 0x00020000
|
||||
#define WARN_XDEV 0x00040000
|
||||
|
||||
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
|
||||
in verbose mode */
|
||||
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY)
|
||||
#define WARN_ALL (0xffffffff & ~WARN_VERBOSE_WARNINGS)
|
||||
|
||||
void set_warning_option (const char *arg);
|
||||
|
||||
extern int warning_option;
|
||||
|
||||
#define WARNOPT(opt,args) \
|
||||
do \
|
||||
{ \
|
||||
if (warning_option & opt) WARN (args); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Module unlink.c */
|
||||
|
||||
void queue_deferred_unlink (const char *name, bool is_dir);
|
||||
void finish_deferred_unlinks (void);
|
||||
|
||||
/* Module exit.c */
|
||||
extern void (*fatal_exit_hook) (void);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Diff files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1987-04-30.
|
||||
|
||||
@@ -66,8 +66,7 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
|
||||
fprintf (stdlis, "\n");
|
||||
}
|
||||
|
||||
if (exit_status == TAREXIT_SUCCESS)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
|
||||
/* Take a buffer returned by read_and_process and do nothing with it. */
|
||||
@@ -380,7 +379,8 @@ diff_dumpdir (void)
|
||||
else
|
||||
dev = stat_data.st_dev;
|
||||
|
||||
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
|
||||
dumpdir_buffer = directory_contents
|
||||
(scan_directory (current_stat_info.file_name, dev, false));
|
||||
|
||||
if (dumpdir_buffer)
|
||||
{
|
||||
@@ -460,7 +460,7 @@ diff_archive (void)
|
||||
{
|
||||
if (now_verifying)
|
||||
fprintf (stdlis, _("Verify "));
|
||||
print_header (¤t_stat_info, -1);
|
||||
print_header (¤t_stat_info, current_header, -1);
|
||||
}
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
@@ -578,7 +578,9 @@ verify_volume (void)
|
||||
flush_read ();
|
||||
while (1)
|
||||
{
|
||||
enum read_header status = read_header (false);
|
||||
enum read_header status = read_header (¤t_header,
|
||||
¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
if (status == HEADER_FAILURE)
|
||||
{
|
||||
@@ -588,7 +590,8 @@ verify_volume (void)
|
||||
{
|
||||
counter++;
|
||||
set_next_block_after (current_header);
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
}
|
||||
while (status == HEADER_FAILURE);
|
||||
|
||||
@@ -606,11 +609,13 @@ verify_volume (void)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
WARNOPT (WARN_ALONE_ZERO_BLOCK,
|
||||
(0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
362
src/create.c
362
src/create.c
@@ -1,7 +1,7 @@
|
||||
/* Create a tar archive.
|
||||
|
||||
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-25.
|
||||
|
||||
@@ -63,22 +63,23 @@ exclusion_tag_warning (const char *dirname, const char *tagname,
|
||||
const char *message)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
_("%s: contains a cache directory tag %s; %s"),
|
||||
quotearg_colon (dirname),
|
||||
quotearg_n (1, tagname),
|
||||
message));
|
||||
WARNOPT (WARN_CACHEDIR,
|
||||
(0, 0,
|
||||
_("%s: contains a cache directory tag %s; %s"),
|
||||
quotearg_colon (dirname),
|
||||
quotearg_n (1, tagname),
|
||||
message));
|
||||
}
|
||||
|
||||
enum exclusion_tag_type
|
||||
check_exclusion_tags (char *dirname, const char **tag_file_name)
|
||||
check_exclusion_tags (const char *dirname, const char **tag_file_name)
|
||||
{
|
||||
static char *tagname;
|
||||
static size_t tagsize;
|
||||
struct exclusion_tag *tag;
|
||||
size_t dlen = strlen (dirname);
|
||||
int addslash = dirname[dlen-1] != '/';
|
||||
char *nptr = NULL;
|
||||
int addslash = !ISSLASH (dirname[dlen-1]);
|
||||
size_t noff = 0;
|
||||
|
||||
for (tag = exclusion_tags; tag; tag = tag->next)
|
||||
{
|
||||
@@ -89,14 +90,14 @@ check_exclusion_tags (char *dirname, const char **tag_file_name)
|
||||
tagname = xrealloc (tagname, tagsize);
|
||||
}
|
||||
|
||||
if (!nptr)
|
||||
if (noff == 0)
|
||||
{
|
||||
strcpy (tagname, dirname);
|
||||
nptr = tagname + dlen;
|
||||
noff = dlen;
|
||||
if (addslash)
|
||||
*nptr++ = '/';
|
||||
tagname[noff++] = '/';
|
||||
}
|
||||
strcpy (nptr, tag->name);
|
||||
strcpy (tagname + noff, tag->name);
|
||||
if (access (tagname, F_OK) == 0
|
||||
&& (!tag->predicate || tag->predicate (tagname)))
|
||||
{
|
||||
@@ -401,8 +402,7 @@ mode_to_chars (mode_t v, char *p, size_t s)
|
||||
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
|
||||
&& archive_format != POSIX_FORMAT
|
||||
&& archive_format != USTAR_FORMAT
|
||||
&& archive_format != GNU_FORMAT
|
||||
&& archive_format != OLDGNU_FORMAT)
|
||||
&& archive_format != GNU_FORMAT)
|
||||
{
|
||||
negative = v < 0;
|
||||
u = v;
|
||||
@@ -515,9 +515,8 @@ write_eot (void)
|
||||
|
||||
/* Write a "private" header */
|
||||
union block *
|
||||
start_private_header (const char *name, size_t size)
|
||||
start_private_header (const char *name, size_t size, time_t t)
|
||||
{
|
||||
time_t t;
|
||||
union block *header = find_next_block ();
|
||||
|
||||
memset (header->buffer, 0, sizeof (union block));
|
||||
@@ -525,7 +524,6 @@ start_private_header (const char *name, size_t size)
|
||||
tar_name_copy_str (header->header.name, name, NAME_FIELD_SIZE);
|
||||
OFF_TO_CHARS (size, header->header.size);
|
||||
|
||||
time (&t);
|
||||
TIME_TO_CHARS (t, header->header.mtime);
|
||||
MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
|
||||
UID_TO_CHARS (getuid (), header->header.uid);
|
||||
@@ -563,13 +561,13 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
|
||||
union block *header;
|
||||
char *tmpname;
|
||||
|
||||
header = start_private_header ("././@LongLink", size);
|
||||
FILL(header->header.mtime, '0');
|
||||
FILL(header->header.mode, '0');
|
||||
FILL(header->header.uid, '0');
|
||||
FILL(header->header.gid, '0');
|
||||
FILL(header->header.devmajor, 0);
|
||||
FILL(header->header.devminor, 0);
|
||||
header = start_private_header ("././@LongLink", size, time (NULL));
|
||||
FILL (header->header.mtime, '0');
|
||||
FILL (header->header.mode, '0');
|
||||
FILL (header->header.uid, '0');
|
||||
FILL (header->header.gid, '0');
|
||||
FILL (header->header.devmajor, 0);
|
||||
FILL (header->header.devminor, 0);
|
||||
uid_to_uname (0, &tmpname);
|
||||
UNAME_TO_CHARS (tmpname, header->header.uname);
|
||||
free (tmpname);
|
||||
@@ -604,8 +602,10 @@ split_long_name (const char *name, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (length > PREFIX_FIELD_SIZE)
|
||||
if (length > PREFIX_FIELD_SIZE + 1)
|
||||
length = PREFIX_FIELD_SIZE + 1;
|
||||
else if (ISSLASH (name[length - 1]))
|
||||
length--;
|
||||
for (i = length - 1; i > 0; i--)
|
||||
if (ISSLASH (name[i]))
|
||||
break;
|
||||
@@ -616,9 +616,9 @@ static union block *
|
||||
write_ustar_long_name (const char *name)
|
||||
{
|
||||
size_t length = strlen (name);
|
||||
size_t i;
|
||||
size_t i, nlen;
|
||||
union block *header;
|
||||
|
||||
|
||||
if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)
|
||||
{
|
||||
ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"),
|
||||
@@ -628,7 +628,7 @@ write_ustar_long_name (const char *name)
|
||||
}
|
||||
|
||||
i = split_long_name (name, length);
|
||||
if (i == 0 || length - i - 1 > NAME_FIELD_SIZE)
|
||||
if (i == 0 || (nlen = length - i - 1) > NAME_FIELD_SIZE || nlen == 0)
|
||||
{
|
||||
ERROR ((0, 0,
|
||||
_("%s: file name is too long (cannot be split); not dumped"),
|
||||
@@ -712,7 +712,8 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
|
||||
union block *header, hp;
|
||||
char *p;
|
||||
int type;
|
||||
|
||||
time_t t;
|
||||
|
||||
if (st->xhdr.buffer || st->xhdr.stk == NULL)
|
||||
return old_header;
|
||||
|
||||
@@ -722,13 +723,15 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
|
||||
{
|
||||
type = XGLTYPE;
|
||||
p = xheader_ghdr_name ();
|
||||
time (&t);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = XHDTYPE;
|
||||
p = xheader_xhdr_name (st);
|
||||
t = st->stat.st_mtime;
|
||||
}
|
||||
xheader_write (type, p, &st->xhdr);
|
||||
xheader_write (type, p, t, &st->xhdr);
|
||||
free (p);
|
||||
header = find_next_block ();
|
||||
memcpy (header, &hp.buffer, sizeof (hp.buffer));
|
||||
@@ -993,11 +996,9 @@ finish_header (struct tar_stat_info *st,
|
||||
&& header->header.typeflag != XHDTYPE
|
||||
&& header->header.typeflag != XGLTYPE)
|
||||
{
|
||||
/* These globals are parameters to print_header, sigh. */
|
||||
|
||||
current_header = header;
|
||||
/* FIXME: This global is used in print_header, sigh. */
|
||||
current_format = archive_format;
|
||||
print_header (st, block_ordinal);
|
||||
print_header (st, header, block_ordinal);
|
||||
}
|
||||
|
||||
header = write_extended (false, st, header);
|
||||
@@ -1072,14 +1073,15 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
memset (blk->buffer + count, 0, bufsize - count);
|
||||
WARN ((0, 0,
|
||||
ngettext ("%s: File shrank by %s byte; padding with zeros",
|
||||
"%s: File shrank by %s bytes; padding with zeros",
|
||||
size_left),
|
||||
quotearg_colon (st->orig_file_name),
|
||||
STRINGIFY_BIGINT (size_left, buf)));
|
||||
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",
|
||||
size_left),
|
||||
quotearg_colon (st->orig_file_name),
|
||||
STRINGIFY_BIGINT (size_left, buf)));
|
||||
if (! ignore_failed_read_option)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
pad_archive (size_left - (bufsize - count));
|
||||
return dump_status_short;
|
||||
}
|
||||
@@ -1090,79 +1092,74 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
|
||||
static void
|
||||
dump_dir0 (char *directory,
|
||||
struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
struct tar_stat_info *st, bool top_level, dev_t parent_device)
|
||||
{
|
||||
dev_t our_device = st->stat.st_dev;
|
||||
const char *tag_file_name;
|
||||
|
||||
if (!is_avoided_name (st->orig_file_name))
|
||||
union block *blk = NULL;
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
|
||||
st->stat.st_size = 0; /* force 0 size on dir */
|
||||
|
||||
blk = start_header (st);
|
||||
if (!blk)
|
||||
return;
|
||||
|
||||
if (incremental_option && archive_format != POSIX_FORMAT)
|
||||
blk->header.typeflag = GNUTYPE_DUMPDIR;
|
||||
else /* if (standard_option) */
|
||||
blk->header.typeflag = DIRTYPE;
|
||||
|
||||
/* If we're gnudumping, we aren't done yet so don't close it. */
|
||||
|
||||
if (!incremental_option)
|
||||
finish_header (st, blk, block_ordinal);
|
||||
else if (gnu_list_name->directory)
|
||||
{
|
||||
union block *blk = NULL;
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
st->stat.st_size = 0; /* force 0 size on dir */
|
||||
|
||||
blk = start_header (st);
|
||||
if (!blk)
|
||||
return;
|
||||
|
||||
if (incremental_option && archive_format != POSIX_FORMAT)
|
||||
blk->header.typeflag = GNUTYPE_DUMPDIR;
|
||||
else /* if (standard_option) */
|
||||
blk->header.typeflag = DIRTYPE;
|
||||
|
||||
/* If we're gnudumping, we aren't done yet so don't close it. */
|
||||
|
||||
if (!incremental_option)
|
||||
finish_header (st, blk, block_ordinal);
|
||||
else if (gnu_list_name->dir_contents)
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
{
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
{
|
||||
xheader_store ("GNU.dumpdir", st, gnu_list_name->dir_contents);
|
||||
finish_header (st, blk, block_ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
off_t size_left;
|
||||
off_t totsize;
|
||||
size_t bufsize;
|
||||
ssize_t count;
|
||||
const char *buffer, *p_buffer;
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
buffer = gnu_list_name->dir_contents;
|
||||
if (buffer)
|
||||
totsize = dumpdir_size (buffer);
|
||||
else
|
||||
totsize = 0;
|
||||
OFF_TO_CHARS (totsize, blk->header.size);
|
||||
finish_header (st, blk, block_ordinal);
|
||||
p_buffer = buffer;
|
||||
size_left = totsize;
|
||||
|
||||
mv_begin (st);
|
||||
mv_total_size (totsize);
|
||||
while (size_left > 0)
|
||||
{
|
||||
mv_size_left (size_left);
|
||||
blk = find_next_block ();
|
||||
bufsize = available_space_after (blk);
|
||||
if (size_left < bufsize)
|
||||
{
|
||||
bufsize = size_left;
|
||||
count = bufsize % BLOCKSIZE;
|
||||
if (count)
|
||||
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
|
||||
}
|
||||
memcpy (blk->buffer, p_buffer, bufsize);
|
||||
size_left -= bufsize;
|
||||
p_buffer += bufsize;
|
||||
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
|
||||
}
|
||||
mv_end ();
|
||||
}
|
||||
return;
|
||||
xheader_store ("GNU.dumpdir", st,
|
||||
safe_directory_contents (gnu_list_name->directory));
|
||||
finish_header (st, blk, block_ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
off_t size_left;
|
||||
off_t totsize;
|
||||
size_t bufsize;
|
||||
ssize_t count;
|
||||
const char *buffer, *p_buffer;
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
buffer = safe_directory_contents (gnu_list_name->directory);
|
||||
totsize = dumpdir_size (buffer);
|
||||
OFF_TO_CHARS (totsize, blk->header.size);
|
||||
finish_header (st, blk, block_ordinal);
|
||||
p_buffer = buffer;
|
||||
size_left = totsize;
|
||||
|
||||
mv_begin (st);
|
||||
mv_total_size (totsize);
|
||||
while (size_left > 0)
|
||||
{
|
||||
mv_size_left (size_left);
|
||||
blk = find_next_block ();
|
||||
bufsize = available_space_after (blk);
|
||||
if (size_left < bufsize)
|
||||
{
|
||||
bufsize = size_left;
|
||||
count = bufsize % BLOCKSIZE;
|
||||
if (count)
|
||||
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
|
||||
}
|
||||
memcpy (blk->buffer, p_buffer, bufsize);
|
||||
size_left -= bufsize;
|
||||
p_buffer += bufsize;
|
||||
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
|
||||
}
|
||||
mv_end ();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!recursion_option)
|
||||
@@ -1173,9 +1170,10 @@ dump_dir0 (char *directory,
|
||||
&& parent_device != st->stat.st_dev)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
_("%s: file is on a different filesystem; not dumped"),
|
||||
quotearg_colon (st->orig_file_name)));
|
||||
WARNOPT (WARN_XDEV,
|
||||
(0, 0,
|
||||
_("%s: file is on a different filesystem; not dumped"),
|
||||
quotearg_colon (st->orig_file_name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1209,7 +1207,7 @@ dump_dir0 (char *directory,
|
||||
}
|
||||
strcpy (name_buf + name_len, entry);
|
||||
if (!excluded_name (name_buf))
|
||||
dump_file (name_buf, 0, our_device);
|
||||
dump_file (name_buf, false, our_device);
|
||||
}
|
||||
|
||||
free (name_buf);
|
||||
@@ -1223,7 +1221,7 @@ dump_dir0 (char *directory,
|
||||
name_buf = xmalloc (name_size);
|
||||
strcpy (name_buf, st->orig_file_name);
|
||||
strcat (name_buf, tag_file_name);
|
||||
dump_file (name_buf, 0, our_device);
|
||||
dump_file (name_buf, false, our_device);
|
||||
free (name_buf);
|
||||
break;
|
||||
|
||||
@@ -1249,7 +1247,8 @@ ensure_slash (char **pstr)
|
||||
}
|
||||
|
||||
static bool
|
||||
dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
dump_dir (int fd, struct tar_stat_info *st, bool top_level,
|
||||
dev_t parent_device)
|
||||
{
|
||||
char *directory = fdsavedir (fd);
|
||||
if (!directory)
|
||||
@@ -1270,7 +1269,7 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
void
|
||||
create_archive (void)
|
||||
{
|
||||
const char *p;
|
||||
struct name const *p;
|
||||
|
||||
open_archive (ACCESS_WRITE);
|
||||
buffer_write_global_xheader ();
|
||||
@@ -1284,24 +1283,24 @@ create_archive (void)
|
||||
collect_and_sort_names ();
|
||||
|
||||
while ((p = name_from_list ()) != NULL)
|
||||
if (!excluded_name (p))
|
||||
dump_file (p, -1, (dev_t) 0);
|
||||
if (!excluded_name (p->name))
|
||||
dump_file (p->name, p->cmdline, (dev_t) 0);
|
||||
|
||||
blank_name_list ();
|
||||
while ((p = name_from_list ()) != NULL)
|
||||
if (!excluded_name (p))
|
||||
if (!excluded_name (p->name))
|
||||
{
|
||||
size_t plen = strlen (p);
|
||||
size_t plen = strlen (p->name);
|
||||
if (buffer_size <= plen)
|
||||
{
|
||||
while ((buffer_size *= 2) <= plen)
|
||||
continue;
|
||||
buffer = xrealloc (buffer, buffer_size);
|
||||
}
|
||||
memcpy (buffer, p, plen);
|
||||
memcpy (buffer, p->name, plen);
|
||||
if (! ISSLASH (buffer[plen - 1]))
|
||||
buffer[plen++] = '/';
|
||||
q = gnu_list_name->dir_contents;
|
||||
buffer[plen++] = DIRECTORY_SEPARATOR;
|
||||
q = directory_contents (gnu_list_name->directory);
|
||||
if (q)
|
||||
while (*q)
|
||||
{
|
||||
@@ -1315,7 +1314,7 @@ create_archive (void)
|
||||
buffer = xrealloc (buffer, buffer_size);
|
||||
}
|
||||
strcpy (buffer + plen, q + 1);
|
||||
dump_file (buffer, -1, (dev_t) 0);
|
||||
dump_file (buffer, false, (dev_t) 0);
|
||||
}
|
||||
q += qlen + 1;
|
||||
}
|
||||
@@ -1324,14 +1323,15 @@ create_archive (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((p = name_next (1)) != NULL)
|
||||
if (!excluded_name (p))
|
||||
dump_file (p, 1, (dev_t) 0);
|
||||
const char *name;
|
||||
while ((name = name_next (1)) != NULL)
|
||||
if (!excluded_name (name))
|
||||
dump_file (name, true, (dev_t) 0);
|
||||
}
|
||||
|
||||
write_eot ();
|
||||
close_archive ();
|
||||
|
||||
finish_deferred_unlinks ();
|
||||
if (listed_incremental_option)
|
||||
write_directory_file ();
|
||||
}
|
||||
@@ -1358,10 +1358,11 @@ compare_links (void const *entry1, void const *entry2)
|
||||
static void
|
||||
unknown_file_error (char const *p)
|
||||
{
|
||||
WARN ((0, 0, _("%s: Unknown file type; file ignored"),
|
||||
quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
(0, 0, _("%s: Unknown file type; file ignored"),
|
||||
quotearg_colon (p)));
|
||||
if (!ignore_failed_read_option)
|
||||
exit_status = TAREXIT_FAILURE;
|
||||
set_exit_status (TAREXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1377,7 +1378,7 @@ static Hash_table *link_table;
|
||||
static bool
|
||||
dump_hard_link (struct tar_stat_info *st)
|
||||
{
|
||||
if (link_table && st->stat.st_nlink > 1)
|
||||
if (link_table && (st->stat.st_nlink > 1 || remove_files_option))
|
||||
{
|
||||
struct link lp;
|
||||
struct link *duplicate;
|
||||
@@ -1410,8 +1411,8 @@ dump_hard_link (struct tar_stat_info *st)
|
||||
blk->header.typeflag = LNKTYPE;
|
||||
finish_header (st, blk, block_ordinal);
|
||||
|
||||
if (remove_files_option && unlink (st->orig_file_name) != 0)
|
||||
unlink_error (st->orig_file_name);
|
||||
if (remove_files_option)
|
||||
queue_deferred_unlink (st->orig_file_name, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1427,19 +1428,26 @@ file_count_links (struct tar_stat_info *st)
|
||||
if (st->stat.st_nlink > 1)
|
||||
{
|
||||
struct link *duplicate;
|
||||
struct link *lp = xmalloc (offsetof (struct link, name)
|
||||
+ strlen (st->orig_file_name) + 1);
|
||||
char *linkname = NULL;
|
||||
struct link *lp;
|
||||
|
||||
assign_string (&linkname, st->orig_file_name);
|
||||
transform_name (&linkname, XFORM_LINK);
|
||||
|
||||
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;
|
||||
strcpy (lp->name, st->orig_file_name);
|
||||
|
||||
strcpy (lp->name, linkname);
|
||||
free (linkname);
|
||||
|
||||
if (! ((link_table
|
||||
|| (link_table = hash_initialize (0, 0, hash_link,
|
||||
compare_links, 0)))
|
||||
&& (duplicate = hash_insert (link_table, lp))))
|
||||
xalloc_die ();
|
||||
|
||||
|
||||
if (duplicate != lp)
|
||||
abort ();
|
||||
lp->nlink--;
|
||||
@@ -1461,12 +1469,11 @@ check_links (void)
|
||||
{
|
||||
if (lp->nlink)
|
||||
{
|
||||
WARN ((0, 0, _("Missing links to %s.\n"), quote (lp->name)));
|
||||
WARN ((0, 0, _("Missing links to %s."), quote (lp->name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Dump a single file, recursing on directories. P is the file name
|
||||
to dump. TOP_LEVEL tells whether this is a top-level call; zero
|
||||
means no, positive means yes, and negative means the top level
|
||||
@@ -1478,7 +1485,7 @@ check_links (void)
|
||||
|
||||
static void
|
||||
dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
int top_level, dev_t parent_device)
|
||||
bool top_level, dev_t parent_device)
|
||||
{
|
||||
union block *header;
|
||||
char type;
|
||||
@@ -1499,7 +1506,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
if (deref_stat (dereference_option, p, &st->stat) != 0)
|
||||
{
|
||||
stat_diag (p);
|
||||
file_removed_diag (p, top_level, stat_diag);
|
||||
return;
|
||||
}
|
||||
st->archive_file_size = original_size = st->stat.st_size;
|
||||
@@ -1522,32 +1529,31 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
/* See if we want only new files, and check if this one is too old to
|
||||
put in the archive.
|
||||
|
||||
|
||||
This check is omitted if incremental_option is set *and* the
|
||||
requested file is not explicitely listed in the command line. */
|
||||
|
||||
|
||||
if (!(incremental_option && !is_individual_file (p))
|
||||
&& !S_ISDIR (st->stat.st_mode)
|
||||
&& OLDER_TAR_STAT_TIME (*st, m)
|
||||
&& (!after_date_option || OLDER_TAR_STAT_TIME (*st, c)))
|
||||
{
|
||||
if (!incremental_option && verbose_option)
|
||||
WARN ((0, 0, _("%s: file is unchanged; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_UNCHANGED,
|
||||
(0, 0, _("%s: file is unchanged; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if we are trying to dump the archive. */
|
||||
if (sys_file_is_archive (st))
|
||||
{
|
||||
WARN ((0, 0, _("%s: file is the archive; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
WARNOPT (WARN_IGNORE_ARCHIVE,
|
||||
(0, 0, _("%s: file is the archive; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_avoided_name (p))
|
||||
return;
|
||||
|
||||
is_dir = S_ISDIR (st->stat.st_mode) != 0;
|
||||
|
||||
if (!is_dir && dump_hard_link (st))
|
||||
@@ -1569,11 +1575,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
: 0)));
|
||||
if (fd < 0)
|
||||
{
|
||||
if (!top_level && errno == ENOENT)
|
||||
WARN ((0, 0, _("%s: File removed before we read it"),
|
||||
quotearg_colon (p)));
|
||||
else
|
||||
open_diag (p);
|
||||
file_removed_diag (p, top_level, open_diag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1589,6 +1591,8 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
{
|
||||
exclusion_tag_warning (st->orig_file_name, tag_file_name,
|
||||
_("directory not dumped"));
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1643,7 +1647,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
: fstat (fd, &final_stat))
|
||||
!= 0)
|
||||
{
|
||||
stat_diag (p);
|
||||
file_removed_diag (p, top_level, stat_diag);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
@@ -1656,10 +1660,10 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
&& !(remove_files_option && is_dir))
|
||||
|| original_size < final_stat.st_size)
|
||||
{
|
||||
WARN ((0, 0, _("%s: file changed as we read it"),
|
||||
quotearg_colon (p)));
|
||||
if (exit_status == TAREXIT_SUCCESS)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
WARNOPT (WARN_FILE_CHANGED,
|
||||
(0, 0, _("%s: file changed as we read it"),
|
||||
quotearg_colon (p)));
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
else if (atime_preserve_option == replace_atime_preserve
|
||||
&& set_file_atime (fd, p, restore_times) != 0)
|
||||
@@ -1673,18 +1677,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
}
|
||||
|
||||
if (ok && remove_files_option)
|
||||
{
|
||||
if (is_dir)
|
||||
{
|
||||
if (rmdir (p) != 0 && errno != ENOTEMPTY)
|
||||
rmdir_error (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlink (p) != 0)
|
||||
unlink_error (p);
|
||||
}
|
||||
}
|
||||
queue_deferred_unlink (p, is_dir);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1700,7 +1693,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
size = readlink (p, buffer, linklen + 1);
|
||||
if (size < 0)
|
||||
{
|
||||
readlink_diag (p);
|
||||
file_removed_diag (p, top_level, readlink_diag);
|
||||
return;
|
||||
}
|
||||
buffer[size] = '\0';
|
||||
@@ -1720,10 +1713,8 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
/* nothing more to do to it */
|
||||
|
||||
if (remove_files_option)
|
||||
{
|
||||
if (unlink (p) == -1)
|
||||
unlink_error (p);
|
||||
}
|
||||
queue_deferred_unlink (p, false);
|
||||
|
||||
file_count_links (st);
|
||||
return;
|
||||
}
|
||||
@@ -1736,12 +1727,14 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
type = FIFOTYPE;
|
||||
else if (S_ISSOCK (st->stat.st_mode))
|
||||
{
|
||||
WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
(0, 0, _("%s: socket ignored"), quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
else if (S_ISDOOR (st->stat.st_mode))
|
||||
{
|
||||
WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
(0, 0, _("%s: door ignored"), quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -1773,14 +1766,11 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
finish_header (st, header, block_ordinal);
|
||||
if (remove_files_option)
|
||||
{
|
||||
if (unlink (p) == -1)
|
||||
unlink_error (p);
|
||||
}
|
||||
queue_deferred_unlink (p, false);
|
||||
}
|
||||
|
||||
void
|
||||
dump_file (const char *p, int top_level, dev_t parent_device)
|
||||
dump_file (const char *p, bool top_level, dev_t parent_device)
|
||||
{
|
||||
struct tar_stat_info st;
|
||||
tar_stat_init (&st);
|
||||
|
||||
10
src/delete.c
10
src/delete.c
@@ -1,7 +1,7 @@
|
||||
/* Delete entries from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
2005, 2006, 2010 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
|
||||
@@ -35,7 +35,6 @@ extern union block *current_block;
|
||||
extern union block *recent_long_name;
|
||||
extern union block *recent_long_link;
|
||||
extern off_t records_read;
|
||||
extern off_t records_written;
|
||||
|
||||
/* The number of records skipped at the start of the archive, when
|
||||
passing over members that are not deleted. */
|
||||
@@ -166,7 +165,9 @@ delete_archive_members (void)
|
||||
|
||||
do
|
||||
{
|
||||
enum read_header status = read_header (true);
|
||||
enum read_header status = read_header (¤t_header,
|
||||
¤t_stat_info,
|
||||
read_header_x_raw);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -261,7 +262,8 @@ delete_archive_members (void)
|
||||
|
||||
if (current_block == record_end)
|
||||
flush_archive ();
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
xheader_decode (¤t_stat_info);
|
||||
|
||||
|
||||
759
src/diffarch.c
759
src/diffarch.c
@@ -1,759 +0,0 @@
|
||||
/* Diff files from a tar archive.
|
||||
Copyright (C) 1988, 1992, 1993 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* Diff files from a tar archive.
|
||||
*
|
||||
* Written 30 April 1987 by John Gilmore, ihnp4!hoptoad!gnu.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifndef STDC_HEADERS
|
||||
extern int errno;
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef BSD42
|
||||
#include <sys/file.h>
|
||||
#else
|
||||
#ifndef V7
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MTIO_H
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mtio.h>
|
||||
#endif
|
||||
|
||||
#include "tar.h"
|
||||
#include "port.h"
|
||||
#include "rmt.h"
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#endif
|
||||
|
||||
extern void *valloc ();
|
||||
|
||||
extern union record *head; /* Points to current tape header */
|
||||
extern struct stat hstat; /* Stat struct corresponding */
|
||||
extern int head_standard; /* Tape header is in ANSI format */
|
||||
|
||||
void decode_header ();
|
||||
void diff_sparse_files ();
|
||||
void fill_in_sparse_array ();
|
||||
void fl_read ();
|
||||
long from_oct ();
|
||||
int do_stat ();
|
||||
extern void print_header ();
|
||||
int read_header ();
|
||||
void saverec ();
|
||||
void sigh ();
|
||||
extern void skip_file ();
|
||||
extern void skip_extended_headers ();
|
||||
int wantbytes ();
|
||||
|
||||
extern FILE *msg_file;
|
||||
|
||||
int now_verifying = 0; /* Are we verifying at the moment? */
|
||||
|
||||
int diff_fd; /* Descriptor of file we're diffing */
|
||||
|
||||
char *diff_buf = 0; /* Pointer to area for reading
|
||||
file contents into */
|
||||
|
||||
char *diff_dir; /* Directory contents for LF_DUMPDIR */
|
||||
|
||||
int different = 0;
|
||||
|
||||
/*struct sp_array *sparsearray;
|
||||
int sp_ar_size = 10;*/
|
||||
/*
|
||||
* Initialize for a diff operation
|
||||
*/
|
||||
void
|
||||
diff_init ()
|
||||
{
|
||||
/*NOSTRICT*/
|
||||
diff_buf = (char *) valloc ((unsigned) blocksize);
|
||||
if (!diff_buf)
|
||||
{
|
||||
msg ("could not allocate memory for diff buffer of %d bytes",
|
||||
blocksize);
|
||||
exit (EX_ARGSBAD);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Diff a file against the archive.
|
||||
*/
|
||||
void
|
||||
diff_archive ()
|
||||
{
|
||||
register char *data;
|
||||
int check, namelen;
|
||||
int err;
|
||||
long offset;
|
||||
struct stat filestat;
|
||||
int compare_chunk ();
|
||||
int compare_dir ();
|
||||
int no_op ();
|
||||
#ifndef __MSDOS__
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
#endif
|
||||
char *get_dir_contents ();
|
||||
long from_oct ();
|
||||
|
||||
errno = EPIPE; /* FIXME, remove perrors */
|
||||
|
||||
saverec (&head); /* Make sure it sticks around */
|
||||
userec (head); /* And go past it in the archive */
|
||||
decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
|
||||
|
||||
/* Print the record from 'head' and 'hstat' */
|
||||
if (f_verbose)
|
||||
{
|
||||
if (now_verifying)
|
||||
fprintf (msg_file, "Verify ");
|
||||
print_header ();
|
||||
}
|
||||
|
||||
switch (head->header.linkflag)
|
||||
{
|
||||
|
||||
default:
|
||||
msg ("Unknown file type '%c' for %s, diffed as normal file",
|
||||
head->header.linkflag, current_file_name);
|
||||
/* FALL THRU */
|
||||
|
||||
case LF_OLDNORMAL:
|
||||
case LF_NORMAL:
|
||||
case LF_SPARSE:
|
||||
case LF_CONTIG:
|
||||
/*
|
||||
* Appears to be a file.
|
||||
* See if it's really a directory.
|
||||
*/
|
||||
namelen = strlen (current_file_name) - 1;
|
||||
if (current_file_name[namelen] == '/')
|
||||
goto really_dir;
|
||||
|
||||
|
||||
if (do_stat (&filestat))
|
||||
{
|
||||
if (head->header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (!S_ISREG (filestat.st_mode))
|
||||
{
|
||||
fprintf (msg_file, "%s: not a regular file\n",
|
||||
current_file_name);
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
filestat.st_mode &= 07777;
|
||||
if (filestat.st_mode != hstat.st_mode)
|
||||
sigh ("mode");
|
||||
if (filestat.st_uid != hstat.st_uid)
|
||||
sigh ("uid");
|
||||
if (filestat.st_gid != hstat.st_gid)
|
||||
sigh ("gid");
|
||||
if (filestat.st_mtime != hstat.st_mtime)
|
||||
sigh ("mod time");
|
||||
if (head->header.linkflag != LF_SPARSE &&
|
||||
filestat.st_size != hstat.st_size)
|
||||
{
|
||||
sigh ("size");
|
||||
skip_file ((long) hstat.st_size);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_fd < 0 && !f_absolute_paths)
|
||||
{
|
||||
char tmpbuf[NAMSIZ + 2];
|
||||
|
||||
tmpbuf[0] = '/';
|
||||
strcpy (&tmpbuf[1], current_file_name);
|
||||
diff_fd = open (tmpbuf, O_NDELAY | O_RDONLY);
|
||||
}
|
||||
if (diff_fd < 0)
|
||||
{
|
||||
msg_perror ("cannot open %s", current_file_name);
|
||||
if (head->header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
goto quit;
|
||||
}
|
||||
/*
|
||||
* Need to treat sparse files completely differently here.
|
||||
*/
|
||||
if (head->header.linkflag == LF_SPARSE)
|
||||
diff_sparse_files (hstat.st_size);
|
||||
else
|
||||
wantbytes ((long) (hstat.st_size), compare_chunk);
|
||||
|
||||
check = close (diff_fd);
|
||||
if (check < 0)
|
||||
msg_perror ("Error while closing %s", current_file_name);
|
||||
|
||||
quit:
|
||||
break;
|
||||
|
||||
#ifndef __MSDOS__
|
||||
case LF_LINK:
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
dev = filestat.st_dev;
|
||||
ino = filestat.st_ino;
|
||||
err = stat (current_link_name, &filestat);
|
||||
if (err < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fprintf (msg_file, "%s: does not exist\n", current_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_perror ("cannot stat file %s", current_file_name);
|
||||
}
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
if (filestat.st_dev != dev || filestat.st_ino != ino)
|
||||
{
|
||||
fprintf (msg_file, "%s not linked to %s\n", current_file_name, current_link_name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef S_ISLNK
|
||||
case LF_SYMLINK:
|
||||
{
|
||||
char linkbuf[NAMSIZ + 3];
|
||||
check = readlink (current_file_name, linkbuf,
|
||||
(sizeof linkbuf) - 1);
|
||||
|
||||
if (check < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fprintf (msg_file,
|
||||
"%s: no such file or directory\n",
|
||||
current_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_perror ("cannot read link %s", current_file_name);
|
||||
}
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
linkbuf[check] = '\0'; /* Null-terminate it */
|
||||
if (strncmp (current_link_name, linkbuf, check) != 0)
|
||||
{
|
||||
fprintf (msg_file, "%s: symlink differs\n",
|
||||
current_link_name);
|
||||
different++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef S_IFCHR
|
||||
case LF_CHR:
|
||||
hstat.st_mode |= S_IFCHR;
|
||||
goto check_node;
|
||||
#endif
|
||||
|
||||
#ifdef S_IFBLK
|
||||
/* If local system doesn't support block devices, use default case */
|
||||
case LF_BLK:
|
||||
hstat.st_mode |= S_IFBLK;
|
||||
goto check_node;
|
||||
#endif
|
||||
|
||||
#ifdef S_ISFIFO
|
||||
/* If local system doesn't support FIFOs, use default case */
|
||||
case LF_FIFO:
|
||||
#ifdef S_IFIFO
|
||||
hstat.st_mode |= S_IFIFO;
|
||||
#endif
|
||||
hstat.st_rdev = 0; /* FIXME, do we need this? */
|
||||
goto check_node;
|
||||
#endif
|
||||
|
||||
check_node:
|
||||
/* FIXME, deal with umask */
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
if (hstat.st_rdev != filestat.st_rdev)
|
||||
{
|
||||
fprintf (msg_file, "%s: device numbers changed\n", current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
#ifdef S_IFMT
|
||||
if (hstat.st_mode != filestat.st_mode)
|
||||
#else /* POSIX lossage */
|
||||
if ((hstat.st_mode & 07777) != (filestat.st_mode & 07777))
|
||||
#endif
|
||||
{
|
||||
fprintf (msg_file, "%s: mode or device-type changed\n", current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LF_DUMPDIR:
|
||||
data = diff_dir = get_dir_contents (current_file_name, 0);
|
||||
if (data)
|
||||
{
|
||||
wantbytes ((long) (hstat.st_size), compare_dir);
|
||||
free (data);
|
||||
}
|
||||
else
|
||||
wantbytes ((long) (hstat.st_size), no_op);
|
||||
/* FALL THROUGH */
|
||||
|
||||
case LF_DIR:
|
||||
/* Check for trailing / */
|
||||
namelen = strlen (current_file_name) - 1;
|
||||
really_dir:
|
||||
while (namelen && current_file_name[namelen] == '/')
|
||||
current_file_name[namelen--] = '\0'; /* Zap / */
|
||||
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
if (!S_ISDIR (filestat.st_mode))
|
||||
{
|
||||
fprintf (msg_file, "%s is no longer a directory\n", current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
if ((filestat.st_mode & 07777) != (hstat.st_mode & 07777))
|
||||
sigh ("mode");
|
||||
break;
|
||||
|
||||
case LF_VOLHDR:
|
||||
break;
|
||||
|
||||
case LF_MULTIVOL:
|
||||
namelen = strlen (current_file_name) - 1;
|
||||
if (current_file_name[namelen] == '/')
|
||||
goto really_dir;
|
||||
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
|
||||
if (!S_ISREG (filestat.st_mode))
|
||||
{
|
||||
fprintf (msg_file, "%s: not a regular file\n",
|
||||
current_file_name);
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
filestat.st_mode &= 07777;
|
||||
offset = from_oct (1 + 12, head->header.offset);
|
||||
if (filestat.st_size != hstat.st_size + offset)
|
||||
{
|
||||
sigh ("size");
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_fd < 0)
|
||||
{
|
||||
msg_perror ("cannot open file %s", current_file_name);
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
err = lseek (diff_fd, offset, 0);
|
||||
if (err != offset)
|
||||
{
|
||||
msg_perror ("cannot seek to %ld in file %s", offset, current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
wantbytes ((long) (hstat.st_size), compare_chunk);
|
||||
|
||||
check = close (diff_fd);
|
||||
if (check < 0)
|
||||
{
|
||||
msg_perror ("Error while closing %s", current_file_name);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* We don't need to save it any longer. */
|
||||
saverec ((union record **) 0);/* Unsave it */
|
||||
}
|
||||
|
||||
int
|
||||
compare_chunk (bytes, buffer)
|
||||
long bytes;
|
||||
char *buffer;
|
||||
{
|
||||
int err;
|
||||
|
||||
err = read (diff_fd, diff_buf, bytes);
|
||||
if (err != bytes)
|
||||
{
|
||||
if (err < 0)
|
||||
{
|
||||
msg_perror ("can't read %s", current_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (msg_file, "%s: could only read %d of %d bytes\n", current_file_name, err, bytes);
|
||||
}
|
||||
different++;
|
||||
return -1;
|
||||
}
|
||||
if (bcmp (buffer, diff_buf, bytes))
|
||||
{
|
||||
fprintf (msg_file, "%s: data differs\n", current_file_name);
|
||||
different++;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
compare_dir (bytes, buffer)
|
||||
long bytes;
|
||||
char *buffer;
|
||||
{
|
||||
if (bcmp (buffer, diff_dir, bytes))
|
||||
{
|
||||
fprintf (msg_file, "%s: data differs\n", current_file_name);
|
||||
different++;
|
||||
return -1;
|
||||
}
|
||||
diff_dir += bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sigh about something that differs.
|
||||
*/
|
||||
void
|
||||
sigh (what)
|
||||
char *what;
|
||||
{
|
||||
|
||||
fprintf (msg_file, "%s: %s differs\n",
|
||||
current_file_name, what);
|
||||
}
|
||||
|
||||
void
|
||||
verify_volume ()
|
||||
{
|
||||
int status;
|
||||
#ifdef MTIOCTOP
|
||||
struct mtop t;
|
||||
int er;
|
||||
#endif
|
||||
|
||||
if (!diff_buf)
|
||||
diff_init ();
|
||||
#ifdef MTIOCTOP
|
||||
t.mt_op = MTBSF;
|
||||
t.mt_count = 1;
|
||||
if ((er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
|
||||
{
|
||||
if (errno != EIO || (er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
|
||||
{
|
||||
#endif
|
||||
if (rmtlseek (archive, 0L, 0) != 0)
|
||||
{
|
||||
/* Lseek failed. Try a different method */
|
||||
msg_perror ("Couldn't rewind archive file for verify");
|
||||
return;
|
||||
}
|
||||
#ifdef MTIOCTOP
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ar_reading = 1;
|
||||
now_verifying = 1;
|
||||
fl_read ();
|
||||
for (;;)
|
||||
{
|
||||
status = read_header ();
|
||||
if (status == 0)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
n++;
|
||||
status = read_header ();
|
||||
}
|
||||
while (status == 0);
|
||||
msg ("VERIFY FAILURE: %d invalid header%s detected!", n, n == 1 ? "" : "s");
|
||||
}
|
||||
if (status == 2 || status == EOF)
|
||||
break;
|
||||
diff_archive ();
|
||||
}
|
||||
ar_reading = 0;
|
||||
now_verifying = 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
do_stat (statp)
|
||||
struct stat *statp;
|
||||
{
|
||||
int err;
|
||||
|
||||
err = f_follow_links ? stat (current_file_name, statp) : lstat (current_file_name, statp);
|
||||
if (err < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fprintf (msg_file, "%s: does not exist\n", current_file_name);
|
||||
}
|
||||
else
|
||||
msg_perror ("can't stat file %s", current_file_name);
|
||||
/* skip_file((long)hstat.st_size);
|
||||
different++;*/
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* JK
|
||||
* Diff'ing a sparse file with its counterpart on the tar file is a
|
||||
* bit of a different story than a normal file. First, we must know
|
||||
* what areas of the file to skip through, i.e., we need to contruct
|
||||
* a sparsearray, which will hold all the information we need. We must
|
||||
* compare small amounts of data at a time as we find it.
|
||||
*/
|
||||
|
||||
void
|
||||
diff_sparse_files (filesize)
|
||||
int filesize;
|
||||
|
||||
{
|
||||
int sparse_ind = 0;
|
||||
char *buf;
|
||||
int buf_size = RECORDSIZE;
|
||||
union record *datarec;
|
||||
int err;
|
||||
long numbytes;
|
||||
/* int amt_read = 0;*/
|
||||
int size = filesize;
|
||||
|
||||
buf = (char *) ck_malloc (buf_size * sizeof (char));
|
||||
|
||||
fill_in_sparse_array ();
|
||||
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
datarec = findrec ();
|
||||
if (!sparsearray[sparse_ind].numbytes)
|
||||
break;
|
||||
|
||||
/*
|
||||
* 'numbytes' is nicer to write than
|
||||
* 'sparsearray[sparse_ind].numbytes' all the time ...
|
||||
*/
|
||||
numbytes = sparsearray[sparse_ind].numbytes;
|
||||
|
||||
lseek (diff_fd, sparsearray[sparse_ind].offset, 0);
|
||||
/*
|
||||
* take care to not run out of room in our buffer
|
||||
*/
|
||||
while (buf_size < numbytes)
|
||||
{
|
||||
buf = (char *) ck_realloc (buf, buf_size * 2 * sizeof (char));
|
||||
buf_size *= 2;
|
||||
}
|
||||
while (numbytes > RECORDSIZE)
|
||||
{
|
||||
if ((err = read (diff_fd, buf, RECORDSIZE)) != RECORDSIZE)
|
||||
{
|
||||
if (err < 0)
|
||||
msg_perror ("can't read %s", current_file_name);
|
||||
else
|
||||
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
|
||||
current_file_name, err, numbytes);
|
||||
break;
|
||||
}
|
||||
if (bcmp (buf, datarec->charptr, RECORDSIZE))
|
||||
{
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
numbytes -= err;
|
||||
size -= err;
|
||||
userec (datarec);
|
||||
datarec = findrec ();
|
||||
}
|
||||
if ((err = read (diff_fd, buf, numbytes)) != numbytes)
|
||||
{
|
||||
if (err < 0)
|
||||
msg_perror ("can't read %s", current_file_name);
|
||||
else
|
||||
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
|
||||
current_file_name, err, numbytes);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bcmp (buf, datarec->charptr, numbytes))
|
||||
{
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
/* amt_read += numbytes;
|
||||
if (amt_read >= RECORDSIZE) {
|
||||
amt_read = 0;
|
||||
userec(datarec);
|
||||
datarec = findrec();
|
||||
}*/
|
||||
userec (datarec);
|
||||
sparse_ind++;
|
||||
size -= numbytes;
|
||||
}
|
||||
/*
|
||||
* if the number of bytes read isn't the
|
||||
* number of bytes supposedly in the file,
|
||||
* they're different
|
||||
*/
|
||||
/* if (amt_read != filesize)
|
||||
different++;*/
|
||||
userec (datarec);
|
||||
free (sparsearray);
|
||||
if (different)
|
||||
fprintf (msg_file, "%s: data differs\n", current_file_name);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* JK
|
||||
* This routine should be used more often than it is ... look into
|
||||
* that. Anyhow, what it does is translate the sparse information
|
||||
* on the header, and in any subsequent extended headers, into an
|
||||
* array of structures with true numbers, as opposed to character
|
||||
* strings. It simply makes our life much easier, doing so many
|
||||
* comparisong and such.
|
||||
*/
|
||||
void
|
||||
fill_in_sparse_array ()
|
||||
{
|
||||
int ind;
|
||||
|
||||
/*
|
||||
* allocate space for our scratch space; it's initially
|
||||
* 10 elements long, but can change in this routine if
|
||||
* necessary
|
||||
*/
|
||||
sp_array_size = 10;
|
||||
sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
|
||||
|
||||
/*
|
||||
* there are at most five of these structures in the header
|
||||
* itself; read these in first
|
||||
*/
|
||||
for (ind = 0; ind < SPARSE_IN_HDR; ind++)
|
||||
{
|
||||
if (!head->header.sp[ind].numbytes)
|
||||
break;
|
||||
sparsearray[ind].offset =
|
||||
from_oct (1 + 12, head->header.sp[ind].offset);
|
||||
sparsearray[ind].numbytes =
|
||||
from_oct (1 + 12, head->header.sp[ind].numbytes);
|
||||
}
|
||||
/*
|
||||
* if the header's extended, we gotta read in exhdr's till
|
||||
* we're done
|
||||
*/
|
||||
if (head->header.isextended)
|
||||
{
|
||||
/* how far into the sparsearray we are 'so far' */
|
||||
static int so_far_ind = SPARSE_IN_HDR;
|
||||
union record *exhdr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
exhdr = findrec ();
|
||||
for (ind = 0; ind < SPARSE_EXT_HDR; ind++)
|
||||
{
|
||||
if (ind + so_far_ind > sp_array_size - 1)
|
||||
{
|
||||
/*
|
||||
* we just ran out of room in our
|
||||
* scratch area - realloc it
|
||||
*/
|
||||
sparsearray = (struct sp_array *)
|
||||
ck_realloc (sparsearray,
|
||||
sp_array_size * 2 * sizeof (struct sp_array));
|
||||
sp_array_size *= 2;
|
||||
}
|
||||
/*
|
||||
* convert the character strings into longs
|
||||
*/
|
||||
sparsearray[ind + so_far_ind].offset =
|
||||
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset);
|
||||
sparsearray[ind + so_far_ind].numbytes =
|
||||
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes);
|
||||
}
|
||||
/*
|
||||
* if this is the last extended header for this
|
||||
* file, we can stop
|
||||
*/
|
||||
if (!exhdr->ext_hdr.isextended)
|
||||
break;
|
||||
else
|
||||
{
|
||||
so_far_ind += SPARSE_EXT_HDR;
|
||||
userec (exhdr);
|
||||
}
|
||||
}
|
||||
/* be sure to skip past the last one */
|
||||
userec (exhdr);
|
||||
}
|
||||
}
|
||||
37
src/exit.c
Normal file
37
src/exit.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
|
||||
void (*fatal_exit_hook) (void);
|
||||
|
||||
void
|
||||
fatal_exit (void)
|
||||
{
|
||||
if (fatal_exit_hook)
|
||||
fatal_exit_hook ();
|
||||
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (0, 0, "%s", _("memory exhausted"));
|
||||
fatal_exit ();
|
||||
}
|
||||
134
src/extract.c
134
src/extract.c
@@ -1,7 +1,7 @@
|
||||
/* Extract files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-11-19.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <utimens.h>
|
||||
#include <errno.h>
|
||||
#include <xgetcwd.h>
|
||||
#include <priv-set.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -144,7 +145,8 @@ set_mode (char const *file_name,
|
||||
char typeflag)
|
||||
{
|
||||
mode_t mode;
|
||||
|
||||
bool failed;
|
||||
|
||||
if (0 < same_permissions_option
|
||||
&& permstatus != INTERDIR_PERMSTATUS)
|
||||
{
|
||||
@@ -186,7 +188,17 @@ set_mode (char const *file_name,
|
||||
mode = cur_info->st_mode ^ invert_permissions;
|
||||
}
|
||||
|
||||
if (chmod (file_name, mode) != 0)
|
||||
failed = chmod (file_name, mode) != 0;
|
||||
if (failed && errno == EPERM)
|
||||
{
|
||||
/* On Solaris, chmod may fail if we don't have PRIV_ALL. */
|
||||
if (priv_set_restore_linkdir () == 0)
|
||||
{
|
||||
failed = chmod (file_name, mode) != 0;
|
||||
priv_set_remove_linkdir ();
|
||||
}
|
||||
}
|
||||
if (failed)
|
||||
chmod_error_details (file_name, mode);
|
||||
}
|
||||
|
||||
@@ -195,8 +207,9 @@ static void
|
||||
check_time (char const *file_name, struct timespec t)
|
||||
{
|
||||
if (t.tv_sec <= 0)
|
||||
WARN ((0, 0, _("%s: implausibly old time stamp %s"),
|
||||
file_name, tartime (t, true)));
|
||||
WARNOPT (WARN_TIMESTAMP,
|
||||
(0, 0, _("%s: implausibly old time stamp %s"),
|
||||
file_name, tartime (t, true)));
|
||||
else if (timespec_cmp (volume_start_time, t) < 0)
|
||||
{
|
||||
struct timespec now;
|
||||
@@ -212,8 +225,9 @@ check_time (char const *file_name, struct timespec t)
|
||||
diff.tv_nsec += BILLION;
|
||||
diff.tv_sec--;
|
||||
}
|
||||
WARN ((0, 0, _("%s: time stamp %s is %s s in the future"),
|
||||
file_name, tartime (t, true), code_timespec (diff, buf)));
|
||||
WARNOPT (WARN_TIMESTAMP,
|
||||
(0, 0, _("%s: time stamp %s is %s s in the future"),
|
||||
file_name, tartime (t, true), code_timespec (diff, buf)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,9 +488,13 @@ file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
|
||||
|
||||
if (stat (file_name, &st))
|
||||
{
|
||||
stat_warn (file_name);
|
||||
/* Be on the safe side: if the file does exist assume it is newer */
|
||||
return errno != ENOENT;
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
stat_warn (file_name);
|
||||
/* Be on the safe side: if the file does exist assume it is newer */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!S_ISDIR (st.st_mode)
|
||||
&& tar_timespec_cmp (tar_stat->mtime, get_stat_mtime (&st)) <= 0)
|
||||
@@ -486,17 +504,24 @@ file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
|
||||
return false;
|
||||
}
|
||||
|
||||
#define RECOVER_NO 0
|
||||
#define RECOVER_OK 1
|
||||
#define RECOVER_SKIP 2
|
||||
|
||||
/* Attempt repairing what went wrong with the extraction. Delete an
|
||||
already existing file or create missing intermediate directories.
|
||||
Return nonzero if we somewhat increased our chances at a successful
|
||||
extraction. errno is properly restored on zero return. */
|
||||
Return RECOVER_OK if we somewhat increased our chances at a successful
|
||||
extraction, RECOVER_NO if there are no chances, and RECOVER_SKIP if the
|
||||
caller should skip extraction of that member. The value of errno is
|
||||
properly restored on returning RECOVER_NO. */
|
||||
|
||||
static int
|
||||
maybe_recoverable (char *file_name, int *interdir_made)
|
||||
{
|
||||
int e = errno;
|
||||
|
||||
if (*interdir_made)
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
@@ -506,13 +531,13 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
switch (old_files_option)
|
||||
{
|
||||
case KEEP_OLD_FILES:
|
||||
return 0;
|
||||
return RECOVER_SKIP;
|
||||
|
||||
case KEEP_NEWER_FILES:
|
||||
if (file_newer_p (file_name, ¤t_stat_info))
|
||||
{
|
||||
errno = e;
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
|
||||
@@ -522,7 +547,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
{
|
||||
int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);
|
||||
errno = EEXIST;
|
||||
return r;
|
||||
return r > 0 ? RECOVER_OK : RECOVER_NO;
|
||||
}
|
||||
|
||||
case UNLINK_FIRST_OLD_FILES:
|
||||
@@ -534,15 +559,15 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
if (! make_directories (file_name))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
}
|
||||
*interdir_made = 1;
|
||||
return 1;
|
||||
return RECOVER_OK;
|
||||
|
||||
default:
|
||||
/* Just say we can't do anything about it... */
|
||||
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,6 +684,7 @@ extract_dir (char *file_name, int typeflag)
|
||||
}
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
status = 0;
|
||||
mode = st.st_mode;
|
||||
break;
|
||||
}
|
||||
@@ -666,13 +692,21 @@ extract_dir (char *file_name, int typeflag)
|
||||
errno = EEXIST;
|
||||
}
|
||||
|
||||
if (maybe_recoverable (file_name, &interdir_made))
|
||||
continue;
|
||||
|
||||
if (errno != EEXIST)
|
||||
switch (maybe_recoverable (file_name, &interdir_made))
|
||||
{
|
||||
mkdir_error (file_name);
|
||||
return 1;
|
||||
case RECOVER_OK:
|
||||
continue;
|
||||
|
||||
case RECOVER_SKIP:
|
||||
break;
|
||||
|
||||
case RECOVER_NO:
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
mkdir_error (file_name);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -721,7 +755,8 @@ open_output_file (char *file_name, int typeflag, mode_t mode)
|
||||
if (!conttype_diagnosed)
|
||||
{
|
||||
conttype_diagnosed = 1;
|
||||
WARN ((0, 0, _("Extracting contiguous files as regular files")));
|
||||
WARNOPT (WARN_CONTIGUOUS_CAST,
|
||||
(0, 0, _("Extracting contiguous files as regular files")));
|
||||
}
|
||||
}
|
||||
fd = open (file_name, openflag, mode);
|
||||
@@ -760,13 +795,18 @@ extract_file (char *file_name, int typeflag)
|
||||
}
|
||||
else
|
||||
{
|
||||
int recover = RECOVER_NO;
|
||||
do
|
||||
fd = open_output_file (file_name, typeflag, mode ^ invert_permissions);
|
||||
while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
|
||||
while (fd < 0
|
||||
&& (recover = maybe_recoverable (file_name, &interdir_made))
|
||||
== RECOVER_OK);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
skip_member ();
|
||||
if (recover == RECOVER_SKIP)
|
||||
return 0;
|
||||
open_error (file_name);
|
||||
return 1;
|
||||
}
|
||||
@@ -994,7 +1034,9 @@ extract_symlink (char *file_name, int typeflag)
|
||||
if (!warned_once)
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
|
||||
WARNOPT (WARN_SYMBOLIC_CAST,
|
||||
(0, 0,
|
||||
_("Attempting extraction of symbolic links as hard links")));
|
||||
}
|
||||
return extract_link (file_name, typeflag);
|
||||
#endif
|
||||
@@ -1050,8 +1092,6 @@ extract_fifo (char *file_name, int typeflag)
|
||||
static int
|
||||
extract_volhdr (char *file_name, int typeflag)
|
||||
{
|
||||
if (verbose_option)
|
||||
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
|
||||
skip_member ();
|
||||
return 0;
|
||||
}
|
||||
@@ -1152,9 +1192,10 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN ((0, 0,
|
||||
_("%s: Unknown file type `%c', extracted as normal file"),
|
||||
quotearg_colon (file_name), typeflag));
|
||||
WARNOPT (WARN_UNKNOWN_CAST,
|
||||
(0, 0,
|
||||
_("%s: Unknown file type `%c', extracted as normal file"),
|
||||
quotearg_colon (file_name), typeflag));
|
||||
*fun = extract_file;
|
||||
}
|
||||
|
||||
@@ -1178,8 +1219,9 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
||||
case KEEP_NEWER_FILES:
|
||||
if (file_newer_p (file_name, ¤t_stat_info))
|
||||
{
|
||||
WARN ((0, 0, _("Current %s is newer or same age"),
|
||||
quote (file_name)));
|
||||
WARNOPT (WARN_IGNORE_NEWER,
|
||||
(0, 0, _("Current %s is newer or same age"),
|
||||
quote (file_name)));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -1198,6 +1240,11 @@ extract_archive (void)
|
||||
char typeflag;
|
||||
tar_extractor_t fun;
|
||||
|
||||
fatal_exit_hook = extract_finish;
|
||||
|
||||
/* Try to disable the ability to unlink a directory. */
|
||||
priv_set_remove_linkdir ();
|
||||
|
||||
set_next_block_after (current_header);
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
||||
if (!current_stat_info.file_name[0]
|
||||
@@ -1210,7 +1257,7 @@ extract_archive (void)
|
||||
|
||||
/* Print the block from current_header and current_stat. */
|
||||
if (verbose_option)
|
||||
print_header (¤t_stat_info, -1);
|
||||
print_header (¤t_stat_info, current_header, -1);
|
||||
|
||||
/* Restore stats for all non-ancestor directories, unless
|
||||
it is an incremental archive.
|
||||
@@ -1359,18 +1406,3 @@ rename_directory (char *src, char *dst)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
fatal_exit (void)
|
||||
{
|
||||
extract_finish ();
|
||||
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (0, 0, "%s", _("memory exhausted"));
|
||||
fatal_exit ();
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/* Replacement for getopt() that can be used by tar.
|
||||
Copyright (C) 1988 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* Plug-compatible replacement for getopt() for parsing tar-like
|
||||
* arguments. If the first argument begins with "-", it uses getopt;
|
||||
* otherwise, it uses the old rules used by tar, dump, and ps.
|
||||
*
|
||||
* Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "getopt.h"
|
||||
#include "tar.h" /* For msg() declaration if STDC_MSG. */
|
||||
#include <sys/types.h>
|
||||
#include "port.h"
|
||||
|
||||
int
|
||||
getoldopt (argc, argv, optstring, long_options, opt_index)
|
||||
int argc;
|
||||
char **argv;
|
||||
char *optstring;
|
||||
struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
extern char *optarg; /* Points to next arg */
|
||||
extern int optind; /* Global argv index */
|
||||
static char *key; /* Points to next keyletter */
|
||||
static char use_getopt; /* !=0 if argv[1][0] was '-' */
|
||||
char c;
|
||||
char *place;
|
||||
|
||||
optarg = NULL;
|
||||
|
||||
if (key == NULL)
|
||||
{ /* First time */
|
||||
if (argc < 2)
|
||||
return EOF;
|
||||
key = argv[1];
|
||||
if ((*key == '-') || (*key == '+'))
|
||||
use_getopt++;
|
||||
else
|
||||
optind = 2;
|
||||
}
|
||||
|
||||
if (use_getopt)
|
||||
return getopt_long (argc, argv, optstring,
|
||||
long_options, opt_index);
|
||||
|
||||
c = *key++;
|
||||
if (c == '\0')
|
||||
{
|
||||
key--;
|
||||
return EOF;
|
||||
}
|
||||
place = index (optstring, c);
|
||||
|
||||
if (place == NULL || c == ':')
|
||||
{
|
||||
msg ("unknown option %c", c);
|
||||
return ('?');
|
||||
}
|
||||
|
||||
place++;
|
||||
if (*place == ':')
|
||||
{
|
||||
if (optind < argc)
|
||||
{
|
||||
optarg = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg ("%c argument missing", c);
|
||||
return ('?');
|
||||
}
|
||||
}
|
||||
|
||||
return (c);
|
||||
}
|
||||
677
src/gnu.c
677
src/gnu.c
@@ -1,677 +0,0 @@
|
||||
/* GNU dump extensions to tar.
|
||||
Copyright (C) 1988, 1992, 1993 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifndef STDC_HEADERS
|
||||
extern int errno;
|
||||
#endif
|
||||
#include <time.h>
|
||||
time_t time ();
|
||||
|
||||
#include "tar.h"
|
||||
#include "port.h"
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#endif
|
||||
|
||||
extern time_t new_time;
|
||||
extern FILE *msg_file;
|
||||
|
||||
void addname ();
|
||||
int check_exclude ();
|
||||
extern PTR ck_malloc ();
|
||||
extern PTR ck_realloc ();
|
||||
int confirm ();
|
||||
extern PTR init_buffer ();
|
||||
extern char *get_buffer ();
|
||||
int is_dot_or_dotdot ();
|
||||
extern void add_buffer ();
|
||||
extern void flush_buffer ();
|
||||
void name_gather ();
|
||||
int recursively_delete ();
|
||||
void skip_file ();
|
||||
char *un_quote_string ();
|
||||
|
||||
extern char *new_name ();
|
||||
|
||||
static void add_dir_name ();
|
||||
|
||||
struct dirname
|
||||
{
|
||||
struct dirname *next;
|
||||
char *name;
|
||||
char *dir_text;
|
||||
int dev;
|
||||
int ino;
|
||||
int allnew;
|
||||
};
|
||||
static struct dirname *dir_list;
|
||||
static time_t this_time;
|
||||
|
||||
void
|
||||
add_dir (name, dev, ino, text)
|
||||
char *name;
|
||||
char *text;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
{
|
||||
struct dirname *dp;
|
||||
|
||||
dp = (struct dirname *) ck_malloc (sizeof (struct dirname));
|
||||
if (!dp)
|
||||
abort ();
|
||||
dp->next = dir_list;
|
||||
dir_list = dp;
|
||||
dp->dev = dev;
|
||||
dp->ino = ino;
|
||||
dp->name = ck_malloc (strlen (name) + 1);
|
||||
strcpy (dp->name, name);
|
||||
dp->dir_text = text;
|
||||
dp->allnew = 0;
|
||||
}
|
||||
|
||||
void
|
||||
read_dir_file ()
|
||||
{
|
||||
int dev;
|
||||
int ino;
|
||||
char *strp;
|
||||
FILE *fp;
|
||||
char buf[512];
|
||||
static char *path = 0;
|
||||
|
||||
if (path == 0)
|
||||
path = ck_malloc (PATH_MAX);
|
||||
time (&this_time);
|
||||
if (gnu_dumpfile[0] != '/')
|
||||
{
|
||||
#if defined(__MSDOS__) || defined(HAVE_GETCWD) || defined(_POSIX_VERSION)
|
||||
if (!getcwd (path, PATH_MAX))
|
||||
{
|
||||
msg ("Couldn't get current directory.");
|
||||
exit (EX_SYSTEM);
|
||||
}
|
||||
#else
|
||||
char *getwd ();
|
||||
|
||||
if (!getwd (path))
|
||||
{
|
||||
msg ("Couldn't get current directory: %s", path);
|
||||
exit (EX_SYSTEM);
|
||||
}
|
||||
#endif
|
||||
/* If this doesn't fit, we're in serious trouble */
|
||||
strcat (path, "/");
|
||||
strcat (path, gnu_dumpfile);
|
||||
gnu_dumpfile = path;
|
||||
}
|
||||
fp = fopen (gnu_dumpfile, "r");
|
||||
if (fp == 0 && errno != ENOENT)
|
||||
{
|
||||
msg_perror ("Can't open %s", gnu_dumpfile);
|
||||
return;
|
||||
}
|
||||
if (!fp)
|
||||
return;
|
||||
fgets (buf, sizeof (buf), fp);
|
||||
if (!f_new_files)
|
||||
{
|
||||
f_new_files++;
|
||||
new_time = atol (buf);
|
||||
}
|
||||
while (fgets (buf, sizeof (buf), fp))
|
||||
{
|
||||
strp = &buf[strlen (buf)];
|
||||
if (strp[-1] == '\n')
|
||||
strp[-1] = '\0';
|
||||
strp = buf;
|
||||
dev = atol (strp);
|
||||
while (isdigit (*strp))
|
||||
strp++;
|
||||
ino = atol (strp);
|
||||
while (isspace (*strp))
|
||||
strp++;
|
||||
while (isdigit (*strp))
|
||||
strp++;
|
||||
strp++;
|
||||
add_dir (un_quote_string (strp), dev, ino, (char *) 0);
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
void
|
||||
write_dir_file ()
|
||||
{
|
||||
FILE *fp;
|
||||
struct dirname *dp;
|
||||
char *str;
|
||||
extern char *quote_copy_string ();
|
||||
|
||||
fp = fopen (gnu_dumpfile, "w");
|
||||
if (fp == 0)
|
||||
{
|
||||
msg_perror ("Can't write to %s", gnu_dumpfile);
|
||||
return;
|
||||
}
|
||||
fprintf (fp, "%lu\n", this_time);
|
||||
for (dp = dir_list; dp; dp = dp->next)
|
||||
{
|
||||
if (!dp->dir_text)
|
||||
continue;
|
||||
str = quote_copy_string (dp->name);
|
||||
if (str)
|
||||
{
|
||||
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, str);
|
||||
free (str);
|
||||
}
|
||||
else
|
||||
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, dp->name);
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
struct dirname *
|
||||
get_dir (name)
|
||||
char *name;
|
||||
{
|
||||
struct dirname *dp;
|
||||
|
||||
for (dp = dir_list; dp; dp = dp->next)
|
||||
{
|
||||
if (!strcmp (dp->name, name))
|
||||
return dp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Collect all the names from argv[] (or whatever), then expand them into
|
||||
a directory tree, and put all the directories at the beginning. */
|
||||
void
|
||||
collect_and_sort_names ()
|
||||
{
|
||||
struct name *n, *n_next;
|
||||
int num_names;
|
||||
struct stat statbuf;
|
||||
int name_cmp ();
|
||||
char *merge_sort ();
|
||||
|
||||
name_gather ();
|
||||
|
||||
if (gnu_dumpfile)
|
||||
read_dir_file ();
|
||||
if (!namelist)
|
||||
addname (".");
|
||||
for (n = namelist; n; n = n_next)
|
||||
{
|
||||
n_next = n->next;
|
||||
if (n->found || n->dir_contents)
|
||||
continue;
|
||||
if (n->regexp) /* FIXME just skip regexps for now */
|
||||
continue;
|
||||
if (n->change_dir)
|
||||
if (chdir (n->change_dir) < 0)
|
||||
{
|
||||
msg_perror ("can't chdir to %s", n->change_dir);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef AIX
|
||||
if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK))
|
||||
#else
|
||||
if (lstat (n->name, &statbuf) < 0)
|
||||
#endif /* AIX */
|
||||
{
|
||||
msg_perror ("can't stat %s", n->name);
|
||||
continue;
|
||||
}
|
||||
if (S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
n->found++;
|
||||
add_dir_name (n->name, statbuf.st_dev);
|
||||
}
|
||||
}
|
||||
|
||||
num_names = 0;
|
||||
for (n = namelist; n; n = n->next)
|
||||
num_names++;
|
||||
namelist = (struct name *) merge_sort ((PTR) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, name_cmp);
|
||||
|
||||
for (n = namelist; n; n = n->next)
|
||||
{
|
||||
n->found = 0;
|
||||
}
|
||||
if (gnu_dumpfile)
|
||||
write_dir_file ();
|
||||
}
|
||||
|
||||
int
|
||||
name_cmp (n1, n2)
|
||||
struct name *n1, *n2;
|
||||
{
|
||||
if (n1->found)
|
||||
{
|
||||
if (n2->found)
|
||||
return strcmp (n1->name, n2->name);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else if (n2->found)
|
||||
return 1;
|
||||
else
|
||||
return strcmp (n1->name, n2->name);
|
||||
}
|
||||
|
||||
int
|
||||
dirent_cmp (p1, p2)
|
||||
const PTR p1;
|
||||
const PTR p2;
|
||||
{
|
||||
char *frst, *scnd;
|
||||
|
||||
frst = (*(char **) p1) + 1;
|
||||
scnd = (*(char **) p2) + 1;
|
||||
|
||||
return strcmp (frst, scnd);
|
||||
}
|
||||
|
||||
char *
|
||||
get_dir_contents (p, device)
|
||||
char *p;
|
||||
int device;
|
||||
{
|
||||
DIR *dirp;
|
||||
register struct dirent *d;
|
||||
char *new_buf;
|
||||
char *namebuf;
|
||||
int bufsiz;
|
||||
int len;
|
||||
PTR the_buffer;
|
||||
char *buf;
|
||||
size_t n_strs;
|
||||
/* int n_size;*/
|
||||
char *p_buf;
|
||||
char **vec, **p_vec;
|
||||
|
||||
extern int errno;
|
||||
|
||||
errno = 0;
|
||||
dirp = opendir (p);
|
||||
bufsiz = strlen (p) + NAMSIZ;
|
||||
namebuf = ck_malloc (bufsiz + 2);
|
||||
if (!dirp)
|
||||
{
|
||||
if (errno)
|
||||
msg_perror ("can't open directory %s", p);
|
||||
else
|
||||
msg ("error opening directory %s", p);
|
||||
new_buf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct dirname *dp;
|
||||
int all_children;
|
||||
|
||||
dp = get_dir (p);
|
||||
all_children = dp ? dp->allnew : 0;
|
||||
(void) strcpy (namebuf, p);
|
||||
if (p[strlen (p) - 1] != '/')
|
||||
(void) strcat (namebuf, "/");
|
||||
len = strlen (namebuf);
|
||||
|
||||
the_buffer = init_buffer ();
|
||||
while (d = readdir (dirp))
|
||||
{
|
||||
struct stat hs;
|
||||
|
||||
/* Skip . and .. */
|
||||
if (is_dot_or_dotdot (d->d_name))
|
||||
continue;
|
||||
if (NLENGTH (d) + len >= bufsiz)
|
||||
{
|
||||
bufsiz += NAMSIZ;
|
||||
namebuf = ck_realloc (namebuf, bufsiz + 2);
|
||||
}
|
||||
(void) strcpy (namebuf + len, d->d_name);
|
||||
#ifdef AIX
|
||||
if (0 != f_follow_links ?
|
||||
statx (namebuf, &hs, STATSIZE, STX_HIDDEN) :
|
||||
statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
|
||||
#else
|
||||
if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
|
||||
#endif
|
||||
{
|
||||
msg_perror ("can't stat %s", namebuf);
|
||||
continue;
|
||||
}
|
||||
if ((f_local_filesys && device != hs.st_dev)
|
||||
|| (f_exclude && check_exclude (namebuf)))
|
||||
add_buffer (the_buffer, "N", 1);
|
||||
#ifdef AIX
|
||||
else if (S_ISHIDDEN (hs.st_mode))
|
||||
{
|
||||
add_buffer (the_buffer, "D", 1);
|
||||
strcat (d->d_name, "A");
|
||||
d->d_namlen++;
|
||||
}
|
||||
#endif /* AIX */
|
||||
else if (S_ISDIR (hs.st_mode))
|
||||
{
|
||||
if (dp = get_dir (namebuf))
|
||||
{
|
||||
if (dp->dev != hs.st_dev
|
||||
|| dp->ino != hs.st_ino)
|
||||
{
|
||||
if (f_verbose)
|
||||
msg ("directory %s has been renamed.", namebuf);
|
||||
dp->allnew = 1;
|
||||
dp->dev = hs.st_dev;
|
||||
dp->ino = hs.st_ino;
|
||||
}
|
||||
dp->dir_text = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f_verbose)
|
||||
msg ("Directory %s is new", namebuf);
|
||||
add_dir (namebuf, hs.st_dev, hs.st_ino, "");
|
||||
dp = get_dir (namebuf);
|
||||
dp->allnew = 1;
|
||||
}
|
||||
if (all_children)
|
||||
dp->allnew = 1;
|
||||
|
||||
add_buffer (the_buffer, "D", 1);
|
||||
}
|
||||
else if (!all_children
|
||||
&& f_new_files
|
||||
&& new_time > hs.st_mtime
|
||||
&& (f_new_files > 1
|
||||
|| new_time > hs.st_ctime))
|
||||
add_buffer (the_buffer, "N", 1);
|
||||
else
|
||||
add_buffer (the_buffer, "Y", 1);
|
||||
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
|
||||
}
|
||||
add_buffer (the_buffer, "\000\000", 2);
|
||||
closedir (dirp);
|
||||
|
||||
/* Well, we've read in the contents of the dir, now sort them */
|
||||
buf = get_buffer (the_buffer);
|
||||
if (buf[0] == '\0')
|
||||
{
|
||||
flush_buffer (the_buffer);
|
||||
new_buf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_strs = 0;
|
||||
for (p_buf = buf; *p_buf;)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
tmp = strlen (p_buf) + 1;
|
||||
n_strs++;
|
||||
p_buf += tmp;
|
||||
}
|
||||
vec = (char **) ck_malloc (sizeof (char *) * (n_strs + 1));
|
||||
for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
|
||||
*p_vec++ = p_buf;
|
||||
*p_vec = 0;
|
||||
qsort ((PTR) vec, n_strs, sizeof (char *), dirent_cmp);
|
||||
new_buf = (char *) ck_malloc (p_buf - buf + 2);
|
||||
for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
|
||||
{
|
||||
char *p_tmp;
|
||||
|
||||
for (p_tmp = *p_vec; *p_buf++ = *p_tmp++;)
|
||||
;
|
||||
}
|
||||
*p_buf++ = '\0';
|
||||
free (vec);
|
||||
flush_buffer (the_buffer);
|
||||
}
|
||||
}
|
||||
free (namebuf);
|
||||
return new_buf;
|
||||
}
|
||||
|
||||
/* p is a directory. Add all the files in P to the namelist. If any of the
|
||||
files is a directory, recurse on the subdirectory. . . */
|
||||
static void
|
||||
add_dir_name (p, device)
|
||||
char *p;
|
||||
int device;
|
||||
{
|
||||
char *new_buf;
|
||||
char *p_buf;
|
||||
|
||||
char *namebuf;
|
||||
int buflen;
|
||||
register int len;
|
||||
int sublen;
|
||||
|
||||
/* PTR the_buffer;*/
|
||||
|
||||
/* char *buf;*/
|
||||
/* char **vec,**p_vec;*/
|
||||
/* int n_strs,n_size;*/
|
||||
|
||||
struct name *n;
|
||||
|
||||
int dirent_cmp ();
|
||||
|
||||
new_buf = get_dir_contents (p, device);
|
||||
|
||||
for (n = namelist; n; n = n->next)
|
||||
{
|
||||
if (!strcmp (n->name, p))
|
||||
{
|
||||
n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_buf)
|
||||
{
|
||||
len = strlen (p);
|
||||
buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
|
||||
namebuf = ck_malloc (buflen + 1);
|
||||
|
||||
(void) strcpy (namebuf, p);
|
||||
if (namebuf[len - 1] != '/')
|
||||
{
|
||||
namebuf[len++] = '/';
|
||||
namebuf[len] = '\0';
|
||||
}
|
||||
for (p_buf = new_buf; *p_buf; p_buf += sublen + 1)
|
||||
{
|
||||
sublen = strlen (p_buf);
|
||||
if (*p_buf == 'D')
|
||||
{
|
||||
if (len + sublen >= buflen)
|
||||
{
|
||||
buflen += NAMSIZ;
|
||||
namebuf = ck_realloc (namebuf, buflen + 1);
|
||||
}
|
||||
(void) strcpy (namebuf + len, p_buf + 1);
|
||||
addname (namebuf);
|
||||
add_dir_name (namebuf, device);
|
||||
}
|
||||
}
|
||||
free (namebuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns non-zero if p is . or .. This could be a macro for speed. */
|
||||
int
|
||||
is_dot_or_dotdot (p)
|
||||
char *p;
|
||||
{
|
||||
return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
gnu_restore (skipcrud)
|
||||
int skipcrud;
|
||||
{
|
||||
char *current_dir;
|
||||
/* int current_dir_length; */
|
||||
|
||||
char *archive_dir;
|
||||
/* int archive_dir_length; */
|
||||
PTR the_buffer;
|
||||
char *p;
|
||||
DIR *dirp;
|
||||
struct dirent *d;
|
||||
char *cur, *arc;
|
||||
extern struct stat hstat; /* Stat struct corresponding */
|
||||
long size, copied;
|
||||
char *from, *to;
|
||||
extern union record *head;
|
||||
|
||||
dirp = opendir (skipcrud + current_file_name);
|
||||
|
||||
if (!dirp)
|
||||
{
|
||||
/* The directory doesn't exist now. It'll be created.
|
||||
In any case, we don't have to delete any files out
|
||||
of it */
|
||||
skip_file ((long) hstat.st_size);
|
||||
return;
|
||||
}
|
||||
|
||||
the_buffer = init_buffer ();
|
||||
while (d = readdir (dirp))
|
||||
{
|
||||
if (is_dot_or_dotdot (d->d_name))
|
||||
continue;
|
||||
|
||||
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
|
||||
}
|
||||
closedir (dirp);
|
||||
add_buffer (the_buffer, "", 1);
|
||||
|
||||
current_dir = get_buffer (the_buffer);
|
||||
archive_dir = (char *) ck_malloc (hstat.st_size);
|
||||
if (archive_dir == 0)
|
||||
{
|
||||
msg ("Can't allocate %d bytes for restore", hstat.st_size);
|
||||
skip_file ((long) hstat.st_size);
|
||||
return;
|
||||
}
|
||||
to = archive_dir;
|
||||
for (size = hstat.st_size; size > 0; size -= copied)
|
||||
{
|
||||
from = findrec ()->charptr;
|
||||
if (!from)
|
||||
{
|
||||
msg ("Unexpected EOF in archive\n");
|
||||
break;
|
||||
}
|
||||
copied = endofrecs ()->charptr - from;
|
||||
if (copied > size)
|
||||
copied = size;
|
||||
bcopy ((PTR) from, (PTR) to, (int) copied);
|
||||
to += copied;
|
||||
userec ((union record *) (from + copied - 1));
|
||||
}
|
||||
|
||||
for (cur = current_dir; *cur; cur += strlen (cur) + 1)
|
||||
{
|
||||
for (arc = archive_dir; *arc; arc += strlen (arc) + 1)
|
||||
{
|
||||
arc++;
|
||||
if (!strcmp (arc, cur))
|
||||
break;
|
||||
}
|
||||
if (*arc == '\0')
|
||||
{
|
||||
p = new_name (skipcrud + current_file_name, cur);
|
||||
if (f_confirm && !confirm ("delete", p))
|
||||
{
|
||||
free (p);
|
||||
continue;
|
||||
}
|
||||
if (f_verbose)
|
||||
fprintf (msg_file, "%s: deleting %s\n", tar, p);
|
||||
if (recursively_delete (p))
|
||||
{
|
||||
msg ("%s: Error while deleting %s\n", tar, p);
|
||||
}
|
||||
free (p);
|
||||
}
|
||||
|
||||
}
|
||||
flush_buffer (the_buffer);
|
||||
free (archive_dir);
|
||||
}
|
||||
|
||||
int
|
||||
recursively_delete (path)
|
||||
char *path;
|
||||
{
|
||||
struct stat sbuf;
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *path_buf;
|
||||
/* int path_len; */
|
||||
|
||||
|
||||
if (lstat (path, &sbuf) < 0)
|
||||
return 1;
|
||||
if (S_ISDIR (sbuf.st_mode))
|
||||
{
|
||||
|
||||
/* path_len=strlen(path); */
|
||||
dirp = opendir (path);
|
||||
if (dirp == 0)
|
||||
return 1;
|
||||
while (dp = readdir (dirp))
|
||||
{
|
||||
if (is_dot_or_dotdot (dp->d_name))
|
||||
continue;
|
||||
path_buf = new_name (path, dp->d_name);
|
||||
if (recursively_delete (path_buf))
|
||||
{
|
||||
free (path_buf);
|
||||
closedir (dirp);
|
||||
return 1;
|
||||
}
|
||||
free (path_buf);
|
||||
}
|
||||
closedir (dirp);
|
||||
|
||||
if (rmdir (path) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if (unlink (path) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
278
src/incremen.c
278
src/incremen.c
@@ -1,7 +1,7 @@
|
||||
/* GNU dump extensions to tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009 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
|
||||
@@ -73,6 +73,7 @@ struct directory
|
||||
the original directory structure */
|
||||
const char *tagfile; /* Tag file, if the directory falls under
|
||||
exclusion_tag_under */
|
||||
char *caname; /* canonical name */
|
||||
char *name; /* file name of directory */
|
||||
};
|
||||
|
||||
@@ -212,19 +213,19 @@ static Hash_table *directory_meta_table;
|
||||
|
||||
/* Calculate the hash of a directory. */
|
||||
static size_t
|
||||
hash_directory_name (void const *entry, size_t n_buckets)
|
||||
hash_directory_canonical_name (void const *entry, size_t n_buckets)
|
||||
{
|
||||
struct directory const *directory = entry;
|
||||
return hash_string (directory->name, n_buckets);
|
||||
return hash_string (directory->caname, n_buckets);
|
||||
}
|
||||
|
||||
/* Compare two directories for equality of their names. */
|
||||
static bool
|
||||
compare_directory_names (void const *entry1, void const *entry2)
|
||||
compare_directory_canonical_names (void const *entry1, void const *entry2)
|
||||
{
|
||||
struct directory const *directory1 = entry1;
|
||||
struct directory const *directory2 = entry2;
|
||||
return strcmp (directory1->name, directory2->name) == 0;
|
||||
return strcmp (directory1->caname, directory2->caname) == 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
@@ -245,9 +246,11 @@ compare_directory_meta (void const *entry1, void const *entry2)
|
||||
&& directory1->inode_number == directory2->inode_number;
|
||||
}
|
||||
|
||||
/* Make a directory entry for given NAME */
|
||||
/* Make a directory entry for given relative NAME and canonical name CANAME.
|
||||
The latter is "stolen", i.e. the returned directory contains pointer to
|
||||
it. */
|
||||
static struct directory *
|
||||
make_directory (const char *name)
|
||||
make_directory (const char *name, char *caname)
|
||||
{
|
||||
size_t namelen = strlen (name);
|
||||
struct directory *directory = xmalloc (sizeof (*directory));
|
||||
@@ -260,6 +263,7 @@ make_directory (const char *name)
|
||||
directory->name = xmalloc (namelen + 1);
|
||||
memcpy (directory->name, name, namelen);
|
||||
directory->name[namelen] = 0;
|
||||
directory->caname = caname;
|
||||
directory->tagfile = NULL;
|
||||
return directory;
|
||||
}
|
||||
@@ -267,6 +271,7 @@ make_directory (const char *name)
|
||||
static void
|
||||
free_directory (struct directory *dir)
|
||||
{
|
||||
free (dir->caname);
|
||||
free (dir->name);
|
||||
free (dir);
|
||||
}
|
||||
@@ -274,7 +279,8 @@ free_directory (struct directory *dir)
|
||||
static struct directory *
|
||||
attach_directory (const char *name)
|
||||
{
|
||||
struct directory *dir = make_directory (name);
|
||||
char *cname = normalize_filename (name);
|
||||
struct directory *dir = make_directory (name, cname);
|
||||
if (dirtail)
|
||||
dirtail->next = dir;
|
||||
else
|
||||
@@ -284,24 +290,6 @@ attach_directory (const char *name)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen)
|
||||
{
|
||||
char *name = *pname;
|
||||
size_t nlen = strlen (name);
|
||||
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
|
||||
{
|
||||
if (rlen > slen)
|
||||
{
|
||||
name = xrealloc (name, nlen - slen + rlen + 1);
|
||||
*pname = name;
|
||||
}
|
||||
memmove (name + rlen, name + slen, nlen - slen + 1);
|
||||
memcpy (name, repl, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dirlist_replace_prefix (const char *pref, const char *repl)
|
||||
{
|
||||
@@ -338,8 +326,8 @@ note_directory (char const *name, struct timespec mtime,
|
||||
|
||||
if (! ((directory_table
|
||||
|| (directory_table = hash_initialize (0, 0,
|
||||
hash_directory_name,
|
||||
compare_directory_names, 0)))
|
||||
hash_directory_canonical_name,
|
||||
compare_directory_canonical_names, 0)))
|
||||
&& hash_insert (directory_table, directory)))
|
||||
xalloc_die ();
|
||||
|
||||
@@ -362,13 +350,38 @@ find_directory (const char *name)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
struct directory *dir = make_directory (name);
|
||||
char *caname = normalize_filename (name);
|
||||
struct directory *dir = make_directory (name, caname);
|
||||
struct directory *ret = hash_lookup (directory_table, dir);
|
||||
free_directory (dir);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Remove directory entry for the given CANAME */
|
||||
void
|
||||
remove_directory (const char *caname)
|
||||
{
|
||||
struct directory *dir = make_directory (caname, xstrdup (caname));
|
||||
struct directory *ret = hash_delete (directory_table, dir);
|
||||
if (ret)
|
||||
free_directory (ret);
|
||||
free_directory (dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If first OLD_PREFIX_LEN bytes of DIR->NAME name match OLD_PREFIX,
|
||||
replace them with NEW_PREFIX. */
|
||||
void
|
||||
rebase_directory (struct directory *dir,
|
||||
const char *old_prefix, size_t old_prefix_len,
|
||||
const char *new_prefix, size_t new_prefix_len)
|
||||
{
|
||||
replace_prefix (&dir->name, old_prefix, old_prefix_len,
|
||||
new_prefix, new_prefix_len);
|
||||
}
|
||||
|
||||
/* Return a directory entry for a given combination of device and inode
|
||||
numbers, or zero if none found. */
|
||||
static struct directory *
|
||||
@@ -378,7 +391,7 @@ find_directory_meta (dev_t dev, ino_t ino)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
struct directory *dir = make_directory ("");
|
||||
struct directory *dir = make_directory ("", NULL);
|
||||
struct directory *ret;
|
||||
dir->device_number = dev;
|
||||
dir->inode_number = ino;
|
||||
@@ -400,19 +413,23 @@ update_parent_directory (const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
if (deref_stat (dereference_option, p, &st) != 0)
|
||||
stat_diag (name);
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
stat_diag (directory->name);
|
||||
/* else: should have been already reported */
|
||||
}
|
||||
else
|
||||
directory->mtime = get_stat_mtime (&st);
|
||||
}
|
||||
free (p);
|
||||
}
|
||||
|
||||
#define PD_VERBOSE 0x10
|
||||
#define PD_FORCE_CHILDREN 0x20
|
||||
#define PD_FORCE_CHILDREN 0x10
|
||||
#define PD_FORCE_INIT 0x20
|
||||
#define PD_CHILDREN(f) ((f) & 3)
|
||||
|
||||
static struct directory *
|
||||
procdir (char *name_buffer, struct stat *stat_data,
|
||||
procdir (const char *name_buffer, struct stat *stat_data,
|
||||
dev_t device,
|
||||
int flag,
|
||||
char *entry)
|
||||
@@ -423,15 +440,31 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
if ((directory = find_directory (name_buffer)) != NULL)
|
||||
{
|
||||
if (DIR_IS_INITED (directory))
|
||||
return directory;
|
||||
{
|
||||
if (flag & PD_FORCE_INIT)
|
||||
{
|
||||
assign_string (&directory->name, name_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
*entry = 'N'; /* Avoid duplicating this directory */
|
||||
return directory;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp (directory->name, name_buffer))
|
||||
{
|
||||
*entry = 'N';
|
||||
return directory;
|
||||
}
|
||||
|
||||
/* With NFS, the same file can have two different devices
|
||||
if an NFS directory is mounted in multiple locations,
|
||||
which is relatively common when automounting.
|
||||
To avoid spurious incremental redumping of
|
||||
directories, consider all NFS devices as equal,
|
||||
relying on the i-node to establish differences. */
|
||||
|
||||
|
||||
if (! ((!check_device_option
|
||||
|| (DIR_IS_NFS (directory) && nfs)
|
||||
|| directory->device_number == stat_data->st_dev)
|
||||
@@ -444,10 +477,11 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
{
|
||||
if (strcmp (d->name, name_buffer))
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
WARNOPT (WARN_RENAME_DIRECTORY,
|
||||
(0, 0,
|
||||
_("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
dirlist_replace_prefix (d->name, name_buffer);
|
||||
@@ -456,9 +490,9 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed"),
|
||||
quotearg_colon (name_buffer)));
|
||||
WARNOPT (WARN_RENAME_DIRECTORY,
|
||||
(0, 0, _("%s: Directory has been renamed"),
|
||||
quotearg_colon (name_buffer)));
|
||||
directory->children = ALL_CHILDREN;
|
||||
directory->device_number = stat_data->st_dev;
|
||||
directory->inode_number = stat_data->st_ino;
|
||||
@@ -468,14 +502,14 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
}
|
||||
else
|
||||
directory->children = CHANGED_CHILDREN;
|
||||
|
||||
|
||||
DIR_SET_FLAG (directory, DIRF_FOUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct directory *d = find_directory_meta (stat_data->st_dev,
|
||||
stat_data->st_ino);
|
||||
|
||||
|
||||
directory = note_directory (name_buffer,
|
||||
get_stat_mtime(stat_data),
|
||||
stat_data->st_dev,
|
||||
@@ -488,10 +522,10 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
{
|
||||
if (strcmp (d->name, name_buffer))
|
||||
{
|
||||
if (flag & PD_VERBOSE)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
WARNOPT (WARN_RENAME_DIRECTORY,
|
||||
(0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
dirlist_replace_prefix (d->name, name_buffer);
|
||||
@@ -501,9 +535,9 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
else
|
||||
{
|
||||
DIR_SET_FLAG (directory, DIRF_NEW);
|
||||
if (flag & PD_VERBOSE)
|
||||
WARN ((0, 0, _("%s: Directory is new"),
|
||||
quotearg_colon (name_buffer)));
|
||||
WARNOPT (WARN_NEW_DIRECTORY,
|
||||
(0, 0, _("%s: Directory is new"),
|
||||
quotearg_colon (name_buffer)));
|
||||
directory->children =
|
||||
(listed_incremental_option
|
||||
|| (OLDER_STAT_TIME (*stat_data, m)
|
||||
@@ -519,6 +553,12 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
if (one_file_system_option && device != stat_data->st_dev
|
||||
/* ... except if it was explicitely given in the command line */
|
||||
&& !is_individual_file (name_buffer))
|
||||
/* FIXME:
|
||||
WARNOPT (WARN_XDEV,
|
||||
(0, 0,
|
||||
_("%s: directory is on a different filesystem; not dumped"),
|
||||
quotearg_colon (directory->name)));
|
||||
*/
|
||||
directory->children = NO_CHILDREN;
|
||||
else if (flag & PD_FORCE_CHILDREN)
|
||||
{
|
||||
@@ -541,8 +581,7 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
an exclusion tag. */
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("directory not dumped"));
|
||||
if (entry)
|
||||
*entry = 'N';
|
||||
*entry = 'N';
|
||||
directory->children = NO_CHILDREN;
|
||||
break;
|
||||
|
||||
@@ -643,44 +682,47 @@ makedumpdir (struct directory *directory, const char *dir)
|
||||
free (array);
|
||||
}
|
||||
|
||||
/* Recursively scan the given directory. */
|
||||
static const char *
|
||||
scan_directory (char *dir, dev_t device)
|
||||
/* Recursively scan the given directory DIR.
|
||||
DEVICE is the device number where DIR resides (for --one-file-system).
|
||||
If CMDLINE is true, the directory name was explicitly listed in the
|
||||
command line.
|
||||
Unless *PDIR is NULL, store there a pointer to the struct directory
|
||||
describing DIR. */
|
||||
struct directory *
|
||||
scan_directory (char *dir, dev_t device, bool cmdline)
|
||||
{
|
||||
char *dirp = savedir (dir); /* for scanning directory */
|
||||
char *name_buffer; /* directory, `/', and directory member */
|
||||
size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */
|
||||
size_t name_length; /* used length in name_buffer */
|
||||
namebuf_t nbuf;
|
||||
char *tmp;
|
||||
struct stat stat_data;
|
||||
struct directory *directory;
|
||||
char ch;
|
||||
|
||||
if (! dirp)
|
||||
savedir_error (dir);
|
||||
|
||||
name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
|
||||
name_buffer = xmalloc (name_buffer_size + 2);
|
||||
strcpy (name_buffer, dir);
|
||||
if (! ISSLASH (dir[strlen (dir) - 1]))
|
||||
strcat (name_buffer, "/");
|
||||
name_length = strlen (name_buffer);
|
||||
|
||||
if (deref_stat (dereference_option, name_buffer, &stat_data))
|
||||
tmp = xstrdup (dir);
|
||||
zap_slashes (tmp);
|
||||
|
||||
if (deref_stat (dereference_option, tmp, &stat_data))
|
||||
{
|
||||
stat_diag (name_buffer);
|
||||
/* FIXME: used to be
|
||||
children = CHANGED_CHILDREN;
|
||||
but changed to: */
|
||||
free (name_buffer);
|
||||
dir_removed_diag (tmp, cmdline, stat_diag);
|
||||
free (tmp);
|
||||
free (dirp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
directory = procdir (name_buffer, &stat_data, device, 0, NULL);
|
||||
directory = procdir (tmp, &stat_data, device,
|
||||
(cmdline ? PD_FORCE_INIT : 0),
|
||||
&ch);
|
||||
|
||||
free (tmp);
|
||||
|
||||
nbuf = namebuf_create (dir);
|
||||
|
||||
if (dirp && directory->children != NO_CHILDREN)
|
||||
{
|
||||
char *entry; /* directory entry being scanned */
|
||||
size_t entrylen; /* length of directory entry */
|
||||
dumpdir_iter_t itr;
|
||||
|
||||
makedumpdir (directory, dirp);
|
||||
@@ -689,38 +731,30 @@ scan_directory (char *dir, dev_t device)
|
||||
entry;
|
||||
entry = dumpdir_next (itr))
|
||||
{
|
||||
entrylen = strlen (entry);
|
||||
if (name_buffer_size <= entrylen - 1 + name_length)
|
||||
{
|
||||
do
|
||||
name_buffer_size += NAME_FIELD_SIZE;
|
||||
while (name_buffer_size <= entrylen - 1 + name_length);
|
||||
name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
|
||||
}
|
||||
strcpy (name_buffer + name_length, entry + 1);
|
||||
char *full_name = namebuf_name (nbuf, entry + 1);
|
||||
|
||||
if (*entry == 'I') /* Ignored entry */
|
||||
*entry = 'N';
|
||||
else if (excluded_name (name_buffer))
|
||||
else if (excluded_name (full_name))
|
||||
*entry = 'N';
|
||||
else
|
||||
{
|
||||
if (deref_stat (dereference_option, name_buffer, &stat_data))
|
||||
if (deref_stat (dereference_option, full_name, &stat_data))
|
||||
{
|
||||
stat_diag (name_buffer);
|
||||
file_removed_diag (full_name, false, stat_diag);
|
||||
*entry = 'N';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR (stat_data.st_mode))
|
||||
{
|
||||
int pd_flag = (verbose_option ? PD_VERBOSE : 0);
|
||||
int pd_flag = 0;
|
||||
if (!recursion_option)
|
||||
pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
|
||||
else if (directory->children == ALL_CHILDREN)
|
||||
pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
|
||||
*entry = 'D';
|
||||
procdir (name_buffer, &stat_data, device, pd_flag, entry);
|
||||
procdir (full_name, &stat_data, device, pd_flag, entry);
|
||||
}
|
||||
|
||||
else if (one_file_system_option && device != stat_data.st_dev)
|
||||
@@ -742,17 +776,35 @@ scan_directory (char *dir, dev_t device)
|
||||
free (itr);
|
||||
}
|
||||
|
||||
free (name_buffer);
|
||||
namebuf_free (nbuf);
|
||||
|
||||
if (dirp)
|
||||
free (dirp);
|
||||
|
||||
return directory->dump ? directory->dump->contents : NULL;
|
||||
return directory;
|
||||
}
|
||||
|
||||
/* Return pointer to the contents of the directory DIR */
|
||||
const char *
|
||||
get_directory_contents (char *dir, dev_t device)
|
||||
directory_contents (struct directory *dir)
|
||||
{
|
||||
return scan_directory (dir, device);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
return dir->dump ? dir->dump->contents : NULL;
|
||||
}
|
||||
|
||||
/* A "safe" version of directory_contents, which never returns NULL. */
|
||||
const char *
|
||||
safe_directory_contents (struct directory *dir)
|
||||
{
|
||||
const char *ret = directory_contents (dir);
|
||||
return ret ? ret : "\0\0\0\0";
|
||||
}
|
||||
|
||||
void
|
||||
name_fill_directory (struct name *name, dev_t device, bool cmdline)
|
||||
{
|
||||
name->directory = scan_directory (name->name, device, cmdline);
|
||||
}
|
||||
|
||||
|
||||
@@ -815,17 +867,19 @@ store_rename (struct directory *dir, struct obstack *stk)
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
append_incremental_renames (const char *dump)
|
||||
void
|
||||
append_incremental_renames (struct directory *dir)
|
||||
{
|
||||
struct obstack stk;
|
||||
size_t size;
|
||||
struct directory *dp;
|
||||
const char *dump;
|
||||
|
||||
if (dirhead == NULL)
|
||||
return dump;
|
||||
return;
|
||||
|
||||
obstack_init (&stk);
|
||||
dump = directory_contents (dir);
|
||||
if (dump)
|
||||
{
|
||||
size = dumpdir_size (dump) - 1;
|
||||
@@ -840,11 +894,10 @@ append_incremental_renames (const char *dump)
|
||||
if (obstack_object_size (&stk) != size)
|
||||
{
|
||||
obstack_1grow (&stk, 0);
|
||||
dump = obstack_finish (&stk);
|
||||
dumpdir_free (dir->dump);
|
||||
dir->dump = dumpdir_create (obstack_finish (&stk));
|
||||
}
|
||||
else
|
||||
obstack_free (&stk, NULL);
|
||||
return dump;
|
||||
obstack_free (&stk, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -869,8 +922,8 @@ read_incr_db_01 (int version, const char *initbuf)
|
||||
uintmax_t u;
|
||||
time_t sec;
|
||||
long int nsec;
|
||||
char *buf = 0;
|
||||
size_t bufsize;
|
||||
char *buf = NULL;
|
||||
size_t bufsize = 0;
|
||||
char *ebuf;
|
||||
long lineno = 1;
|
||||
|
||||
@@ -1229,13 +1282,16 @@ void
|
||||
read_directory_file (void)
|
||||
{
|
||||
int fd;
|
||||
char *buf = 0;
|
||||
size_t bufsize;
|
||||
char *buf = NULL;
|
||||
size_t bufsize = 0;
|
||||
int flags = O_RDWR | O_CREAT;
|
||||
|
||||
if (incremental_level == 0)
|
||||
flags |= O_TRUNC;
|
||||
/* Open the file for both read and write. That way, we can write
|
||||
it later without having to reopen it, and don't have to worry if
|
||||
we chdir in the meantime. */
|
||||
fd = open (listed_incremental_option, O_RDWR | O_CREAT, MODE_RW);
|
||||
fd = open (listed_incremental_option, flags, MODE_RW);
|
||||
if (fd < 0)
|
||||
{
|
||||
open_error (listed_incremental_option);
|
||||
@@ -1250,6 +1306,13 @@ read_directory_file (void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Consume the first name from the name list and reset the
|
||||
list afterwards. This is done to change to the new
|
||||
directory, if the first name is a chdir request (-C dir),
|
||||
which is necessary to recreate absolute file names. */
|
||||
name_from_list ();
|
||||
blank_name_list ();
|
||||
|
||||
if (0 < getline (&buf, &bufsize, listed_incremental_stream))
|
||||
{
|
||||
char *ebuf;
|
||||
@@ -1347,7 +1410,7 @@ write_directory_file (void)
|
||||
if (! fp)
|
||||
return;
|
||||
|
||||
if (fseek (fp, 0L, SEEK_SET) != 0)
|
||||
if (fseeko (fp, 0L, SEEK_SET) != 0)
|
||||
seek_error (listed_incremental_option);
|
||||
if (sys_truncate (fileno (fp)) != 0)
|
||||
truncate_error (listed_incremental_option);
|
||||
@@ -1504,7 +1567,8 @@ dumpdir_ok (char *dumpdir)
|
||||
}
|
||||
|
||||
if (has_tempdir)
|
||||
WARN ((0, 0, _("Malformed dumpdir: 'X' never used")));
|
||||
WARNOPT (WARN_BAD_DUMPDIR,
|
||||
(0, 0, _("Malformed dumpdir: 'X' never used")));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
205
src/list.c
205
src/list.c
@@ -1,7 +1,7 @@
|
||||
/* List a tar archive, with support routines for reading a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-26.
|
||||
|
||||
@@ -33,6 +33,7 @@ union block *recent_long_name; /* recent long name header and contents */
|
||||
union block *recent_long_link; /* likewise, for long link */
|
||||
size_t recent_long_name_blocks; /* number of blocks in recent_long_name */
|
||||
size_t recent_long_link_blocks; /* likewise, for long link */
|
||||
union block *recent_global_header; /* Recent global header block */
|
||||
|
||||
static uintmax_t from_header (const char *, size_t, const char *,
|
||||
uintmax_t, uintmax_t, bool, bool);
|
||||
@@ -77,7 +78,8 @@ read_and (void (*do_something) (void))
|
||||
prev_status = status;
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
switch (status)
|
||||
{
|
||||
case HEADER_STILL_UNREAD:
|
||||
@@ -138,11 +140,13 @@ read_and (void (*do_something) (void))
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
WARNOPT (WARN_ALONE_ZERO_BLOCK,
|
||||
(0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
break;
|
||||
}
|
||||
status = prev_status;
|
||||
@@ -204,11 +208,12 @@ void
|
||||
list_archive (void)
|
||||
{
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
/* Print the header block. */
|
||||
|
||||
/* Print the header block. */
|
||||
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 0);
|
||||
if (verbose_option)
|
||||
print_header (¤t_stat_info, block_ordinal);
|
||||
print_header (¤t_stat_info, current_header, block_ordinal);
|
||||
|
||||
if (incremental_option)
|
||||
{
|
||||
@@ -279,20 +284,29 @@ tar_checksum (union block *header, bool silent)
|
||||
}
|
||||
|
||||
/* Read a block that's supposed to be a header block. Return its
|
||||
address in "current_header", and if it is good, the file's size
|
||||
and names (file name, link name) in *info.
|
||||
address in *RETURN_BLOCK, and if it is good, the file's size
|
||||
and names (file name, link name) in *INFO.
|
||||
|
||||
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
|
||||
block full of zeros (EOF marker).
|
||||
Return one of enum read_header describing the status of the
|
||||
operation.
|
||||
|
||||
If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the
|
||||
GNU long name and link headers into later headers.
|
||||
The MODE parameter instructs read_header what to do with special
|
||||
header blocks, i.e.: extended POSIX, GNU long name or long link,
|
||||
etc.:
|
||||
|
||||
You must always set_next_block_after(current_header) to skip past
|
||||
read_header_auto process them automatically,
|
||||
read_header_x_raw when a special header is read, return
|
||||
HEADER_SUCCESS_EXTENDED without actually
|
||||
processing the header,
|
||||
read_header_x_global when a POSIX global header is read,
|
||||
decode it and return HEADER_SUCCESS_EXTENDED.
|
||||
|
||||
You must always set_next_block_after(*return_block) to skip past
|
||||
the header which this routine reads. */
|
||||
|
||||
enum read_header
|
||||
read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
read_header (union block **return_block, struct tar_stat_info *info,
|
||||
enum read_header_mode mode)
|
||||
{
|
||||
union block *header;
|
||||
union block *header_copy;
|
||||
@@ -309,7 +323,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
enum read_header status;
|
||||
|
||||
header = find_next_block ();
|
||||
current_header = header;
|
||||
*return_block = header;
|
||||
if (!header)
|
||||
return HEADER_END_OF_FILE;
|
||||
|
||||
@@ -329,7 +343,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
|| header->header.typeflag == XGLTYPE
|
||||
|| header->header.typeflag == SOLARIS_XHDTYPE)
|
||||
{
|
||||
if (raw_extended_headers)
|
||||
if (mode == read_header_x_raw)
|
||||
return HEADER_SUCCESS_EXTENDED;
|
||||
else if (header->header.typeflag == GNUTYPE_LONGNAME
|
||||
|| header->header.typeflag == GNUTYPE_LONGLINK)
|
||||
@@ -391,11 +405,18 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
else if (header->header.typeflag == XGLTYPE)
|
||||
{
|
||||
struct xheader xhdr;
|
||||
|
||||
if (!recent_global_header)
|
||||
recent_global_header = xmalloc (sizeof *recent_global_header);
|
||||
memcpy (recent_global_header, header,
|
||||
sizeof *recent_global_header);
|
||||
memset (&xhdr, 0, sizeof xhdr);
|
||||
xheader_read (&xhdr, header,
|
||||
OFF_FROM_HEADER (header->header.size));
|
||||
xheader_decode_global (&xhdr);
|
||||
xheader_destroy (&xhdr);
|
||||
if (mode == read_header_x_global)
|
||||
return HEADER_SUCCESS_EXTENDED;
|
||||
}
|
||||
|
||||
/* Loop! */
|
||||
@@ -404,7 +425,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
else
|
||||
{
|
||||
char const *name;
|
||||
struct posix_header const *h = ¤t_header->header;
|
||||
struct posix_header const *h = &header->header;
|
||||
char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
|
||||
|
||||
if (recent_long_name)
|
||||
@@ -463,12 +484,6 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
enum read_header
|
||||
read_header (bool raw_extended_headers)
|
||||
{
|
||||
return read_header_primitive (raw_extended_headers, ¤t_stat_info);
|
||||
}
|
||||
|
||||
static char *
|
||||
decode_xform (char *file_name, void *data)
|
||||
{
|
||||
@@ -530,7 +545,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
enum archive_format *format_pointer, int do_user_group)
|
||||
{
|
||||
enum archive_format format;
|
||||
|
||||
unsigned hbits; /* high bits of the file mode. */
|
||||
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
|
||||
|
||||
if (strcmp (header->header.magic, TMAGIC) == 0)
|
||||
{
|
||||
if (header->star_header.prefix[130] == 0
|
||||
@@ -545,12 +562,12 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
format = USTAR_FORMAT;
|
||||
}
|
||||
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
|
||||
format = OLDGNU_FORMAT;
|
||||
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
|
||||
else
|
||||
format = V7_FORMAT;
|
||||
*format_pointer = format;
|
||||
|
||||
stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
|
||||
stat_info->stat.st_mode = mode;
|
||||
stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
|
||||
stat_info->mtime.tv_nsec = 0;
|
||||
assign_string (&stat_info->uname,
|
||||
@@ -667,7 +684,8 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
{
|
||||
if (type && !silent)
|
||||
ERROR ((0, 0,
|
||||
/* TRANSLATORS: %s is type of the value (gid_t, uid_t, etc.) */
|
||||
/* TRANSLATORS: %s is type of the value (gid_t, uid_t,
|
||||
etc.) */
|
||||
_("Blanks in header where numeric %s value expected"),
|
||||
type));
|
||||
return -1;
|
||||
@@ -884,25 +902,28 @@ minor_from_header (const char *p, size_t s)
|
||||
(uintmax_t) TYPE_MAXIMUM (minor_t), false, false);
|
||||
}
|
||||
|
||||
/* Convert P to the file mode, as understood by tar.
|
||||
Store unrecognized mode bits (from 10th up) in HBITS. */
|
||||
mode_t
|
||||
mode_from_header (const char *p, size_t s)
|
||||
mode_from_header (const char *p, size_t s, unsigned *hbits)
|
||||
{
|
||||
/* Do not complain about unrecognized mode bits. */
|
||||
unsigned u = from_header (p, s, "mode_t",
|
||||
- (uintmax_t) TYPE_MINIMUM (mode_t),
|
||||
TYPE_MAXIMUM (uintmax_t), false, false);
|
||||
return ((u & TSUID ? S_ISUID : 0)
|
||||
| (u & TSGID ? S_ISGID : 0)
|
||||
| (u & TSVTX ? S_ISVTX : 0)
|
||||
| (u & TUREAD ? S_IRUSR : 0)
|
||||
| (u & TUWRITE ? S_IWUSR : 0)
|
||||
| (u & TUEXEC ? S_IXUSR : 0)
|
||||
| (u & TGREAD ? S_IRGRP : 0)
|
||||
| (u & TGWRITE ? S_IWGRP : 0)
|
||||
| (u & TGEXEC ? S_IXGRP : 0)
|
||||
| (u & TOREAD ? S_IROTH : 0)
|
||||
| (u & TOWRITE ? S_IWOTH : 0)
|
||||
| (u & TOEXEC ? S_IXOTH : 0));
|
||||
mode_t mode = ((u & TSUID ? S_ISUID : 0)
|
||||
| (u & TSGID ? S_ISGID : 0)
|
||||
| (u & TSVTX ? S_ISVTX : 0)
|
||||
| (u & TUREAD ? S_IRUSR : 0)
|
||||
| (u & TUWRITE ? S_IWUSR : 0)
|
||||
| (u & TUEXEC ? S_IXUSR : 0)
|
||||
| (u & TGREAD ? S_IRGRP : 0)
|
||||
| (u & TGWRITE ? S_IWGRP : 0)
|
||||
| (u & TGEXEC ? S_IXGRP : 0)
|
||||
| (u & TOREAD ? S_IROTH : 0)
|
||||
| (u & TOWRITE ? S_IWOTH : 0)
|
||||
| (u & TOEXEC ? S_IXOTH : 0));
|
||||
*hbits = mode ^ u;
|
||||
return mode;
|
||||
}
|
||||
|
||||
off_t
|
||||
@@ -1013,9 +1034,6 @@ tartime (struct timespec t, bool full_time)
|
||||
they shouldn't. Unix tar is pretty random here anyway. */
|
||||
|
||||
|
||||
/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
|
||||
HEAD_STANDARD, which must be set up in advance. Not very clean.. */
|
||||
|
||||
/* Width of "user/group size", with initial value chosen
|
||||
heuristically. This grows as needed, though this may cause some
|
||||
stairstepping in the output. Make it too small and the output will
|
||||
@@ -1028,8 +1046,11 @@ static int ugswidth = 19;
|
||||
USGWIDTH, some stairstepping may occur. */
|
||||
static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;
|
||||
|
||||
void
|
||||
print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
static bool volume_label_printed = false;
|
||||
|
||||
static void
|
||||
simple_print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal)
|
||||
{
|
||||
char modes[11];
|
||||
char const *time_stamp;
|
||||
@@ -1045,9 +1066,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
int pad;
|
||||
int sizelen;
|
||||
|
||||
if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR)
|
||||
return;
|
||||
|
||||
if (show_transformed_names_option)
|
||||
temp_name = st->file_name ? st->file_name : st->orig_file_name;
|
||||
else
|
||||
@@ -1074,9 +1092,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
/* File type and modes. */
|
||||
|
||||
modes[0] = '?';
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case GNUTYPE_VOLHDR:
|
||||
volume_label_printed = true;
|
||||
modes[0] = 'V';
|
||||
break;
|
||||
|
||||
@@ -1144,8 +1163,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
/* Try parsing it as an unsigned integer first, and as a
|
||||
uid_t if that fails. This method can list positive user
|
||||
ids that are too large to fit in a uid_t. */
|
||||
uintmax_t u = from_header (current_header->header.uid,
|
||||
sizeof current_header->header.uid, 0,
|
||||
uintmax_t u = from_header (blk->header.uid,
|
||||
sizeof blk->header.uid, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
|
||||
false, false);
|
||||
@@ -1154,7 +1173,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
else
|
||||
{
|
||||
sprintf (uform, "%ld",
|
||||
(long) UID_FROM_HEADER (current_header->header.uid));
|
||||
(long) UID_FROM_HEADER (blk->header.uid));
|
||||
user = uform;
|
||||
}
|
||||
}
|
||||
@@ -1169,8 +1188,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
/* Try parsing it as an unsigned integer first, and as a
|
||||
gid_t if that fails. This method can list positive group
|
||||
ids that are too large to fit in a gid_t. */
|
||||
uintmax_t g = from_header (current_header->header.gid,
|
||||
sizeof current_header->header.gid, 0,
|
||||
uintmax_t g = from_header (blk->header.gid,
|
||||
sizeof blk->header.gid, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
|
||||
false, false);
|
||||
@@ -1179,14 +1198,14 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
else
|
||||
{
|
||||
sprintf (gform, "%ld",
|
||||
(long) GID_FROM_HEADER (current_header->header.gid));
|
||||
(long) GID_FROM_HEADER (blk->header.gid));
|
||||
group = gform;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the file size or major/minor device numbers. */
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case CHRTYPE:
|
||||
case BLKTYPE:
|
||||
@@ -1216,7 +1235,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
|
||||
fprintf (stdlis, " %s", quotearg (temp_name));
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case SYMTYPE:
|
||||
fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
|
||||
@@ -1229,7 +1248,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
default:
|
||||
{
|
||||
char type_string[2];
|
||||
type_string[0] = current_header->header.typeflag;
|
||||
type_string[0] = blk->header.typeflag;
|
||||
type_string[1] = '\0';
|
||||
fprintf (stdlis, _(" unknown file type %s\n"),
|
||||
quote (type_string));
|
||||
@@ -1263,7 +1282,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
case GNUTYPE_MULTIVOL:
|
||||
strcpy (size,
|
||||
STRINGIFY_BIGINT
|
||||
(UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset),
|
||||
(UINTMAX_FROM_HEADER (blk->oldgnu_header.offset),
|
||||
uintbuf));
|
||||
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
|
||||
break;
|
||||
@@ -1272,6 +1291,40 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
fflush (stdlis);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_volume_label ()
|
||||
{
|
||||
struct tar_stat_info vstat;
|
||||
union block vblk;
|
||||
enum archive_format dummy;
|
||||
|
||||
memset (&vblk, 0, sizeof (vblk));
|
||||
vblk.header.typeflag = GNUTYPE_VOLHDR;
|
||||
if (recent_global_header)
|
||||
memcpy (vblk.header.mtime, recent_global_header->header.mtime,
|
||||
sizeof vblk.header.mtime);
|
||||
tar_stat_init (&vstat);
|
||||
assign_string (&vstat.file_name, ".");
|
||||
decode_header (&vblk, &vstat, &dummy, 0);
|
||||
assign_string (&vstat.file_name, volume_label);
|
||||
simple_print_header (&vstat, &vblk, 0);
|
||||
tar_stat_destroy (&vstat);
|
||||
}
|
||||
|
||||
void
|
||||
print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal)
|
||||
{
|
||||
if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
|
||||
{
|
||||
print_volume_label ();
|
||||
volume_label_printed = true;
|
||||
}
|
||||
|
||||
simple_print_header (st, blk, block_ordinal);
|
||||
}
|
||||
|
||||
/* Print a similar line when we make a directory automatically. */
|
||||
void
|
||||
print_for_mkdir (char *dirname, int length, mode_t mode)
|
||||
@@ -1348,3 +1401,33 @@ skip_member (void)
|
||||
mv_end ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_archive_label ()
|
||||
{
|
||||
base64_init ();
|
||||
name_gather ();
|
||||
|
||||
open_archive (ACCESS_READ);
|
||||
if (read_header (¤t_header, ¤t_stat_info, read_header_auto)
|
||||
== HEADER_SUCCESS)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
decode_header (current_header,
|
||||
¤t_stat_info, ¤t_format, 0);
|
||||
if (current_header->header.typeflag == GNUTYPE_VOLHDR)
|
||||
assign_string (&volume_label, current_header->header.name);
|
||||
|
||||
if (volume_label
|
||||
&& (name_match (volume_label)
|
||||
|| (multi_volume_option
|
||||
&& (s = drop_volume_label_suffix (volume_label))
|
||||
&& name_match (s))))
|
||||
if (verbose_option)
|
||||
print_volume_label ();
|
||||
free (s);
|
||||
}
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# Makefile for GNU tar on MS-DOS using Turbo C 2.0.
|
||||
# Copyright (C) 1991 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 2, 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, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
CC = tcc
|
||||
RM = rm -f
|
||||
|
||||
MODEL = m
|
||||
DEFS = -DNONAMES -DNO_REMOTE -DNO_MTIO -DSTDC_HEADERS -m$(MODEL) -Dmain=_main
|
||||
LIBS =
|
||||
DEF_AR_FILE = tar.out
|
||||
DEFBLOCKING = 20
|
||||
|
||||
CFLAGS = -I. $(DEFS) \
|
||||
-DDEF_AR_FILE="$(DEF_AR_FILE)" \
|
||||
-DDEFBLOCKING=$(DEFBLOCKING)
|
||||
LDFLAGS = -m$(MODEL)
|
||||
|
||||
OBJ1 = tar.obj create.obj extract.obj buffer.obj getoldopt.obj update.obj gnu.obj mangle.obj
|
||||
OBJ2 = version.obj list.obj names.obj diffarch.obj port.obj wildmat.obj getopt.obj
|
||||
OBJ3 = getopt1.obj regex.obj getdate.obj alloca.obj tcexparg.obj msd_dir.obj
|
||||
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
|
||||
|
||||
all: tar
|
||||
|
||||
tar: testpad.h getdate.c $(OBJS)
|
||||
$(RM) testpad.obj
|
||||
$(CC) $(LDFLAGS) -etar *.obj $(LIBS)
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
testpad.h: testpad.exe
|
||||
testpad
|
||||
|
||||
testpad.exe: testpad.c
|
||||
$(CC) $(LDFLAGS) -etestpad testpad.c $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) errs *.obj tar testpad testpad.h
|
||||
|
||||
distclean: clean
|
||||
|
||||
realclean: clean
|
||||
164
src/misc.c
164
src/misc.c
@@ -1,7 +1,7 @@
|
||||
/* Miscellaneous functions, not really specific to GNU tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009 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
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <xgetcwd.h>
|
||||
#include <unlinkdir.h>
|
||||
#include <utimens.h>
|
||||
#include <canonicalize.h>
|
||||
|
||||
#if HAVE_STROPTS_H
|
||||
# include <stropts.h>
|
||||
@@ -214,6 +215,46 @@ unquote_string (char *string)
|
||||
*destination = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Zap trailing slashes. */
|
||||
char *
|
||||
zap_slashes (char *name)
|
||||
{
|
||||
char *q;
|
||||
|
||||
if (!name || *name == 0)
|
||||
return name;
|
||||
q = name + strlen (name) - 1;
|
||||
while (q > name && ISSLASH (*q))
|
||||
*q-- = '\0';
|
||||
return name;
|
||||
}
|
||||
|
||||
char *
|
||||
normalize_filename (const char *name)
|
||||
{
|
||||
return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen)
|
||||
{
|
||||
char *name = *pname;
|
||||
size_t nlen = strlen (name);
|
||||
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
|
||||
{
|
||||
if (rlen > slen)
|
||||
{
|
||||
name = xrealloc (name, nlen - slen + rlen + 1);
|
||||
*pname = name;
|
||||
}
|
||||
memmove (name + rlen, name + slen, nlen - slen + 1);
|
||||
memcpy (name, repl, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handling numbers. */
|
||||
|
||||
@@ -257,6 +298,10 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
|
||||
char *np;
|
||||
bool negative = s < 0;
|
||||
|
||||
/* ignore invalid values of ns */
|
||||
if (BILLION <= ns || ns < 0)
|
||||
ns = 0;
|
||||
|
||||
if (negative && ns != 0)
|
||||
{
|
||||
s++;
|
||||
@@ -417,6 +462,15 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
|
||||
{
|
||||
struct stat file_stat;
|
||||
|
||||
assign_string (&before_backup_name, file_name);
|
||||
|
||||
/* A run situation may exist between Emacs or other GNU programs trying to
|
||||
make a backup for the same file simultaneously. If theoretically
|
||||
possible, real problems are unlikely. Doing any better would require a
|
||||
convention, GNU-wide, for all programs doing backups. */
|
||||
|
||||
assign_string (&after_backup_name, 0);
|
||||
|
||||
/* Check if we really need to backup the file. */
|
||||
|
||||
if (this_is_the_archive && _remdev (file_name))
|
||||
@@ -438,14 +492,6 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
|
||||
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
|
||||
return true;
|
||||
|
||||
assign_string (&before_backup_name, file_name);
|
||||
|
||||
/* A run situation may exist between Emacs or other GNU programs trying to
|
||||
make a backup for the same file simultaneously. If theoretically
|
||||
possible, real problems are unlikely. Doing any better would require a
|
||||
convention, GNU-wide, for all programs doing backups. */
|
||||
|
||||
assign_string (&after_backup_name, 0);
|
||||
after_backup_name = find_backup_file_name (file_name, backup_type);
|
||||
if (! after_backup_name)
|
||||
xalloc_die ();
|
||||
@@ -531,17 +577,25 @@ struct wd
|
||||
static struct wd *wd;
|
||||
|
||||
/* The number of working directories in the vector. */
|
||||
static size_t wds;
|
||||
static size_t wd_count;
|
||||
|
||||
/* The allocated size of the vector. */
|
||||
static size_t wd_alloc;
|
||||
|
||||
int
|
||||
chdir_count ()
|
||||
{
|
||||
if (wd_count == 0)
|
||||
return wd_count;
|
||||
return wd_count - 1;
|
||||
}
|
||||
|
||||
/* DIR is the operand of a -C option; add it to vector of chdir targets,
|
||||
and return the index of its location. */
|
||||
int
|
||||
chdir_arg (char const *dir)
|
||||
{
|
||||
if (wds == wd_alloc)
|
||||
if (wd_count == wd_alloc)
|
||||
{
|
||||
if (wd_alloc == 0)
|
||||
{
|
||||
@@ -551,11 +605,11 @@ chdir_arg (char const *dir)
|
||||
else
|
||||
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
|
||||
|
||||
if (! wds)
|
||||
if (! wd_count)
|
||||
{
|
||||
wd[wds].name = ".";
|
||||
wd[wds].saved = 0;
|
||||
wds++;
|
||||
wd[wd_count].name = ".";
|
||||
wd[wd_count].saved = 0;
|
||||
wd_count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,12 +621,12 @@ chdir_arg (char const *dir)
|
||||
for (dir += 2; ISSLASH (*dir); dir++)
|
||||
continue;
|
||||
if (! dir[dir[0] == '.'])
|
||||
return wds - 1;
|
||||
return wd_count - 1;
|
||||
}
|
||||
|
||||
wd[wds].name = dir;
|
||||
wd[wds].saved = 0;
|
||||
return wds++;
|
||||
wd[wd_count].name = dir;
|
||||
wd[wd_count].saved = 0;
|
||||
return wd_count++;
|
||||
}
|
||||
|
||||
/* Change to directory I. If I is 0, change to the initial working
|
||||
@@ -695,6 +749,36 @@ stat_diag (char const *name)
|
||||
stat_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
file_removed_diag (const char *name, bool top_level,
|
||||
void (*diagfn) (char const *name))
|
||||
{
|
||||
if (!top_level && errno == ENOENT)
|
||||
{
|
||||
WARNOPT (WARN_FILE_REMOVED,
|
||||
(0, 0, _("%s: File removed before we read it"),
|
||||
quotearg_colon (name)));
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
else
|
||||
diagfn (name);
|
||||
}
|
||||
|
||||
void
|
||||
dir_removed_diag (const char *name, bool top_level,
|
||||
void (*diagfn) (char const *name))
|
||||
{
|
||||
if (!top_level && errno == ENOENT)
|
||||
{
|
||||
WARNOPT (WARN_FILE_REMOVED,
|
||||
(0, 0, _("%s: Directory removed before we read it"),
|
||||
quotearg_colon (name)));
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
else
|
||||
diagfn (name);
|
||||
}
|
||||
|
||||
void
|
||||
write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
{
|
||||
@@ -746,3 +830,45 @@ page_aligned_alloc (void **ptr, size_t size)
|
||||
*ptr = xmalloc (size1);
|
||||
return ptr_align (*ptr, alignment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct namebuf
|
||||
{
|
||||
char *buffer; /* directory, `/', and directory member */
|
||||
size_t buffer_size; /* allocated size of name_buffer */
|
||||
size_t dir_length; /* length of directory part in buffer */
|
||||
};
|
||||
|
||||
namebuf_t
|
||||
namebuf_create (const char *dir)
|
||||
{
|
||||
namebuf_t buf = xmalloc (sizeof (*buf));
|
||||
buf->buffer_size = strlen (dir) + 2;
|
||||
buf->buffer = xmalloc (buf->buffer_size);
|
||||
strcpy (buf->buffer, dir);
|
||||
buf->dir_length = strlen (buf->buffer);
|
||||
if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
|
||||
buf->buffer[buf->dir_length++] = DIRECTORY_SEPARATOR;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
namebuf_free (namebuf_t buf)
|
||||
{
|
||||
free (buf->buffer);
|
||||
free (buf);
|
||||
}
|
||||
|
||||
char *
|
||||
namebuf_name (namebuf_t buf, const char *name)
|
||||
{
|
||||
size_t len = strlen (name);
|
||||
while (buf->dir_length + len + 1 >= buf->buffer_size)
|
||||
buf->buffer = x2realloc (buf->buffer, &buf->buffer_size);
|
||||
strcpy (buf->buffer + buf->dir_length, name);
|
||||
return buf->buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
218
src/msd_dir.c
218
src/msd_dir.c
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* @(#)msd_dir.c 1.4 87/11/06 Public Domain.
|
||||
*
|
||||
* A public domain implementation of BSD directory routines for
|
||||
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
|
||||
* August 1897
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "msd_dir.h"
|
||||
#ifndef __TURBOC__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <dos.h>
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif /* NULL */
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
# define MAXPATHLEN 255
|
||||
#endif /* MAXPATHLEN */
|
||||
|
||||
/* attribute stuff */
|
||||
#define A_RONLY 0x01
|
||||
#define A_HIDDEN 0x02
|
||||
#define A_SYSTEM 0x04
|
||||
#define A_LABEL 0x08
|
||||
#define A_DIR 0x10
|
||||
#define A_ARCHIVE 0x20
|
||||
|
||||
/* dos call values */
|
||||
#define DOSI_FINDF 0x4e
|
||||
#define DOSI_FINDN 0x4f
|
||||
#define DOSI_SDTA 0x1a
|
||||
|
||||
#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
|
||||
/* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */
|
||||
#define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR)
|
||||
|
||||
/* what find first/next calls look use */
|
||||
typedef struct {
|
||||
char d_buf[21];
|
||||
char d_attribute;
|
||||
unsigned short d_time;
|
||||
unsigned short d_date;
|
||||
long d_size;
|
||||
char d_name[13];
|
||||
} Dta_buf;
|
||||
|
||||
static char *getdirent();
|
||||
static void mysetdta();
|
||||
static void free_dircontents();
|
||||
|
||||
static Dta_buf dtabuf;
|
||||
static Dta_buf *dtapnt = &dtabuf;
|
||||
static union REGS reg, nreg;
|
||||
|
||||
#if defined(M_I86LM)
|
||||
static struct SREGS sreg;
|
||||
#endif
|
||||
|
||||
DIR *
|
||||
opendir(name)
|
||||
char *name;
|
||||
{
|
||||
struct stat statb;
|
||||
DIR *dirp;
|
||||
char c;
|
||||
char *s;
|
||||
struct _dircontents *dp;
|
||||
char nbuf[MAXPATHLEN + 1];
|
||||
|
||||
if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
|
||||
return (DIR *) NULL;
|
||||
if (Newisnull(dirp, DIR))
|
||||
return (DIR *) NULL;
|
||||
if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
|
||||
(void) strcat(strcpy(nbuf, name), "\\*.*");
|
||||
else
|
||||
(void) strcat(strcpy(nbuf, name), "*.*");
|
||||
dirp->dd_loc = 0;
|
||||
mysetdta();
|
||||
dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
|
||||
if ((s = getdirent(nbuf)) == (char *) NULL)
|
||||
return dirp;
|
||||
do {
|
||||
if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
|
||||
malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
|
||||
{
|
||||
if (dp)
|
||||
free((char *) dp);
|
||||
free_dircontents(dirp->dd_contents);
|
||||
return (DIR *) NULL;
|
||||
}
|
||||
if (dirp->dd_contents)
|
||||
dirp->dd_cp = dirp->dd_cp->_d_next = dp;
|
||||
else
|
||||
dirp->dd_contents = dirp->dd_cp = dp;
|
||||
(void) strcpy(dp->_d_entry, s);
|
||||
dp->_d_next = (struct _dircontents *) NULL;
|
||||
} while ((s = getdirent((char *) NULL)) != (char *) NULL);
|
||||
dirp->dd_cp = dirp->dd_contents;
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
void
|
||||
closedir(dirp)
|
||||
DIR *dirp;
|
||||
{
|
||||
free_dircontents(dirp->dd_contents);
|
||||
free((char *) dirp);
|
||||
}
|
||||
|
||||
struct dirent *
|
||||
readdir(dirp)
|
||||
DIR *dirp;
|
||||
{
|
||||
static struct dirent dp;
|
||||
|
||||
if (dirp->dd_cp == (struct _dircontents *) NULL)
|
||||
return (struct dirent *) NULL;
|
||||
dp.d_namlen = dp.d_reclen =
|
||||
strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
|
||||
strlwr(dp.d_name); /* JF */
|
||||
dp.d_ino = 0;
|
||||
dirp->dd_cp = dirp->dd_cp->_d_next;
|
||||
dirp->dd_loc++;
|
||||
|
||||
return &dp;
|
||||
}
|
||||
|
||||
void
|
||||
seekdir(dirp, off)
|
||||
DIR *dirp;
|
||||
long off;
|
||||
{
|
||||
long i = off;
|
||||
struct _dircontents *dp;
|
||||
|
||||
if (off < 0)
|
||||
return;
|
||||
for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
|
||||
;
|
||||
dirp->dd_loc = off - (i + 1);
|
||||
dirp->dd_cp = dp;
|
||||
}
|
||||
|
||||
long
|
||||
telldir(dirp)
|
||||
DIR *dirp;
|
||||
{
|
||||
return dirp->dd_loc;
|
||||
}
|
||||
|
||||
static void
|
||||
free_dircontents(dp)
|
||||
struct _dircontents *dp;
|
||||
{
|
||||
struct _dircontents *odp;
|
||||
|
||||
while (dp) {
|
||||
if (dp->_d_entry)
|
||||
free(dp->_d_entry);
|
||||
dp = (odp = dp)->_d_next;
|
||||
free((char *) odp);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
getdirent(dir)
|
||||
char *dir;
|
||||
{
|
||||
if (dir != (char *) NULL) { /* get first entry */
|
||||
reg.h.ah = DOSI_FINDF;
|
||||
reg.h.cl = ATTRIBUTES;
|
||||
#if defined(M_I86LM)
|
||||
reg.x.dx = FP_OFF(dir);
|
||||
sreg.ds = FP_SEG(dir);
|
||||
#else
|
||||
reg.x.dx = (unsigned) dir;
|
||||
#endif
|
||||
} else { /* get next entry */
|
||||
reg.h.ah = DOSI_FINDN;
|
||||
#if defined(M_I86LM)
|
||||
reg.x.dx = FP_OFF(dtapnt);
|
||||
sreg.ds = FP_SEG(dtapnt);
|
||||
#else
|
||||
reg.x.dx = (unsigned) dtapnt;
|
||||
#endif
|
||||
}
|
||||
#if defined(M_I86LM)
|
||||
intdosx(®, &nreg, &sreg);
|
||||
#else
|
||||
intdos(®, &nreg);
|
||||
#endif
|
||||
if (nreg.x.cflag)
|
||||
return (char *) NULL;
|
||||
|
||||
return dtabuf.d_name;
|
||||
}
|
||||
|
||||
static void
|
||||
mysetdta()
|
||||
{
|
||||
reg.h.ah = DOSI_SDTA;
|
||||
#if defined(M_I86LM)
|
||||
reg.x.dx = FP_OFF(dtapnt);
|
||||
sreg.ds = FP_SEG(dtapnt);
|
||||
intdosx(®, &nreg, &sreg);
|
||||
#else
|
||||
reg.x.dx = (int) dtapnt;
|
||||
intdos(®, &nreg);
|
||||
#endif
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* @(#)msd_dir.h 1.4 87/11/06 Public Domain.
|
||||
*
|
||||
* A public domain implementation of BSD directory routines for
|
||||
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
|
||||
* August 1897
|
||||
*/
|
||||
|
||||
#define rewinddir(dirp) seekdir(dirp, 0L)
|
||||
|
||||
#define MAXNAMLEN 12
|
||||
|
||||
#ifdef __TURBOC__
|
||||
typedef int ino_t;
|
||||
typedef int dev_t;
|
||||
#endif
|
||||
|
||||
struct direct {
|
||||
ino_t d_ino; /* a bit of a farce */
|
||||
int d_reclen; /* more farce */
|
||||
int d_namlen; /* length of d_name */
|
||||
char d_name[MAXNAMLEN + 1]; /* garentee null termination */
|
||||
};
|
||||
|
||||
struct _dircontents {
|
||||
char *_d_entry;
|
||||
struct _dircontents *_d_next;
|
||||
};
|
||||
|
||||
typedef struct _dirdesc {
|
||||
int dd_id; /* uniquely identify each open directory */
|
||||
long dd_loc; /* where we are in directory entry is this */
|
||||
struct _dircontents *dd_contents; /* pointer to contents of dir */
|
||||
struct _dircontents *dd_cp; /* pointer to current position */
|
||||
} DIR;
|
||||
|
||||
extern DIR *opendir();
|
||||
extern struct direct *readdir();
|
||||
extern void seekdir();
|
||||
extern long telldir();
|
||||
extern void closedir();
|
||||
379
src/names.c
379
src/names.c
@@ -1,7 +1,7 @@
|
||||
/* Various processing of names.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009 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
|
||||
@@ -178,11 +178,34 @@ gname_to_gid (char const *gname, gid_t *gidp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct name *
|
||||
make_name (const char *file_name)
|
||||
{
|
||||
struct name *p = xzalloc (sizeof (*p));
|
||||
if (!file_name)
|
||||
file_name = "";
|
||||
p->name = xstrdup (file_name);
|
||||
p->length = strlen (p->name);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
free_name (struct name *p)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
free (p->name);
|
||||
free (p->caname);
|
||||
free (p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Names from the command call. */
|
||||
|
||||
static struct name *namelist; /* first name in list, if any */
|
||||
static struct name **nametail = &namelist; /* end of name list */
|
||||
static struct name *nametail; /* end of name list */
|
||||
|
||||
/* File name arguments are processed in two stages: first a
|
||||
name_array (see below) is filled, then the names from it
|
||||
@@ -376,8 +399,7 @@ void
|
||||
name_gather (void)
|
||||
{
|
||||
/* Buffer able to hold a single name. */
|
||||
static struct name *buffer;
|
||||
static size_t allocated_size;
|
||||
static struct name *buffer = NULL;
|
||||
|
||||
struct name_elt *ep;
|
||||
|
||||
@@ -385,44 +407,25 @@ name_gather (void)
|
||||
{
|
||||
static int change_dir;
|
||||
|
||||
if (allocated_size == 0)
|
||||
{
|
||||
allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1;
|
||||
buffer = xzalloc (allocated_size);
|
||||
}
|
||||
|
||||
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name));
|
||||
|
||||
if (ep)
|
||||
{
|
||||
size_t needed_size;
|
||||
|
||||
buffer->length = strlen (ep->v.name);
|
||||
needed_size = offsetof (struct name, name) + buffer->length + 1;
|
||||
if (allocated_size < needed_size)
|
||||
{
|
||||
do
|
||||
{
|
||||
allocated_size *= 2;
|
||||
if (! allocated_size)
|
||||
xalloc_die ();
|
||||
}
|
||||
while (allocated_size < needed_size);
|
||||
|
||||
buffer = xrealloc (buffer, allocated_size);
|
||||
}
|
||||
free_name (buffer);
|
||||
buffer = make_name (ep->v.name);
|
||||
buffer->change_dir = change_dir;
|
||||
strcpy (buffer->name, ep->v.name);
|
||||
buffer->next = 0;
|
||||
buffer->found_count = 0;
|
||||
buffer->matching_flags = matching_flags;
|
||||
buffer->directory = NULL;
|
||||
buffer->parent = NULL;
|
||||
buffer->cmdline = true;
|
||||
|
||||
namelist = buffer;
|
||||
nametail = &namelist->next;
|
||||
namelist = nametail = buffer;
|
||||
}
|
||||
else if (change_dir)
|
||||
addname (0, change_dir);
|
||||
addname (0, change_dir, false, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -436,11 +439,11 @@ name_gather (void)
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name));
|
||||
|
||||
if (ep)
|
||||
addname (ep->v.name, change_dir);
|
||||
addname (ep->v.name, change_dir, true, NULL);
|
||||
else
|
||||
{
|
||||
if (change_dir != change_dir0)
|
||||
addname (0, change_dir);
|
||||
addname (NULL, change_dir, false, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -449,25 +452,24 @@ name_gather (void)
|
||||
|
||||
/* Add a name to the namelist. */
|
||||
struct name *
|
||||
addname (char const *string, int change_dir)
|
||||
addname (char const *string, int change_dir, bool cmdline, struct name *parent)
|
||||
{
|
||||
size_t length = string ? strlen (string) : 0;
|
||||
struct name *name = xmalloc (offsetof (struct name, name) + length + 1);
|
||||
|
||||
if (string)
|
||||
strcpy (name->name, string);
|
||||
else
|
||||
name->name[0] = 0;
|
||||
struct name *name = make_name (string);
|
||||
|
||||
name->prev = nametail;
|
||||
name->next = NULL;
|
||||
name->length = length;
|
||||
name->found_count = 0;
|
||||
name->matching_flags = matching_flags;
|
||||
name->change_dir = change_dir;
|
||||
name->dir_contents = NULL;
|
||||
name->directory = NULL;
|
||||
name->parent = parent;
|
||||
name->cmdline = cmdline;
|
||||
|
||||
*nametail = name;
|
||||
nametail = &name->next;
|
||||
if (nametail)
|
||||
nametail->next = name;
|
||||
else
|
||||
namelist = name;
|
||||
nametail = name;
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -488,6 +490,22 @@ namelist_match (char const *file_name, size_t length)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
remname (struct name *name)
|
||||
{
|
||||
struct name *p;
|
||||
|
||||
if ((p = name->prev) != NULL)
|
||||
p->next = name->next;
|
||||
else
|
||||
namelist = name->next;
|
||||
|
||||
if ((p = name->next) != NULL)
|
||||
p->prev = name->prev;
|
||||
else
|
||||
nametail = name->prev;
|
||||
}
|
||||
|
||||
/* Return true if and only if name FILE_NAME (from an archive) matches any
|
||||
name from the namelist. */
|
||||
bool
|
||||
@@ -505,8 +523,8 @@ name_match (const char *file_name)
|
||||
if (cursor->name[0] == 0)
|
||||
{
|
||||
chdir_do (cursor->change_dir);
|
||||
namelist = 0;
|
||||
nametail = &namelist;
|
||||
namelist = NULL;
|
||||
nametail = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -519,8 +537,8 @@ name_match (const char *file_name)
|
||||
if (starting_file_option)
|
||||
{
|
||||
free (namelist);
|
||||
namelist = 0;
|
||||
nametail = &namelist;
|
||||
namelist = NULL;
|
||||
nametail = NULL;
|
||||
}
|
||||
chdir_do (cursor->change_dir);
|
||||
|
||||
@@ -559,8 +577,6 @@ all_names_found (struct tar_stat_info *p)
|
||||
struct name const *cursor;
|
||||
size_t len;
|
||||
|
||||
if (test_label_option)
|
||||
return true;
|
||||
if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash)
|
||||
return false;
|
||||
len = strlen (p->file_name);
|
||||
@@ -573,28 +589,19 @@ all_names_found (struct tar_stat_info *p)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_pattern (const char *string)
|
||||
{
|
||||
return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
|
||||
}
|
||||
|
||||
static void
|
||||
regex_usage_warning (const char *name)
|
||||
{
|
||||
static int warned_once = 0;
|
||||
|
||||
if (warn_regex_usage && is_pattern (name))
|
||||
if (warn_regex_usage && fnmatch_pattern_has_wildcards (name, 0))
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0,
|
||||
/* TRANSLATORS: The following three msgids form a single sentence.
|
||||
*/
|
||||
_("Pattern matching characters used in file names. Please,")));
|
||||
_("Pattern matching characters used in file names")));
|
||||
WARN ((0, 0,
|
||||
_("use --wildcards to enable pattern matching, or --no-wildcards to")));
|
||||
WARN ((0, 0,
|
||||
_("suppress this warning.")));
|
||||
_("Use --wildcards to enable pattern matching,"
|
||||
" or --no-wildcards to suppress this warning")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,8 +624,8 @@ names_notfound (void)
|
||||
}
|
||||
|
||||
/* Don't bother freeing the name list; we're about to exit. */
|
||||
namelist = 0;
|
||||
nametail = &namelist;
|
||||
namelist = NULL;
|
||||
nametail = NULL;
|
||||
|
||||
if (same_order_option)
|
||||
{
|
||||
@@ -635,15 +642,18 @@ names_notfound (void)
|
||||
|
||||
/* Sorting name lists. */
|
||||
|
||||
/* Sort linked LIST of names, of given LENGTH, using COMPARE to order
|
||||
names. Return the sorted list. Apart from the type `struct name'
|
||||
and the definition of SUCCESSOR, this is a generic list-sorting
|
||||
function, but it's too painful to make it both generic and portable
|
||||
/* Sort *singly* linked LIST of names, of given LENGTH, using COMPARE
|
||||
to order names. Return the sorted list. Note that after calling
|
||||
this function, the `prev' links in list elements are messed up.
|
||||
|
||||
Apart from the type `struct name' and the definition of SUCCESSOR,
|
||||
this is a generic list-sorting function, but it's too painful to
|
||||
make it both generic and portable
|
||||
in C. */
|
||||
|
||||
static struct name *
|
||||
merge_sort (struct name *list, int length,
|
||||
int (*compare) (struct name const*, struct name const*))
|
||||
merge_sort_sll (struct name *list, int length,
|
||||
int (*compare) (struct name const*, struct name const*))
|
||||
{
|
||||
struct name *first_list;
|
||||
struct name *second_list;
|
||||
@@ -681,8 +691,8 @@ merge_sort (struct name *list, int length,
|
||||
second_list = SUCCESSOR (cursor);
|
||||
SUCCESSOR (cursor) = 0;
|
||||
|
||||
first_list = merge_sort (first_list, first_length, compare);
|
||||
second_list = merge_sort (second_list, second_length, compare);
|
||||
first_list = merge_sort_sll (first_list, first_length, compare);
|
||||
second_list = merge_sort_sll (second_list, second_length, compare);
|
||||
|
||||
merge_point = &result;
|
||||
while (first_list && second_list)
|
||||
@@ -710,30 +720,53 @@ merge_sort (struct name *list, int length,
|
||||
#undef SUCCESSOR
|
||||
}
|
||||
|
||||
/* Sort doubly linked LIST of names, of given LENGTH, using COMPARE
|
||||
to order names. Return the sorted list. */
|
||||
static struct name *
|
||||
merge_sort (struct name *list, int length,
|
||||
int (*compare) (struct name const*, struct name const*))
|
||||
{
|
||||
struct name *head, *p, *prev;
|
||||
head = merge_sort_sll (list, length, compare);
|
||||
/* Fixup prev pointers */
|
||||
for (prev = NULL, p = head; p; prev = p, p = p->next)
|
||||
p->prev = prev;
|
||||
return head;
|
||||
}
|
||||
|
||||
/* A comparison function for sorting names. Put found names last;
|
||||
break ties by string comparison. */
|
||||
|
||||
static int
|
||||
compare_names (struct name const *n1, struct name const *n2)
|
||||
compare_names_found (struct name const *n1, struct name const *n2)
|
||||
{
|
||||
int found_diff = WASFOUND(n2) - WASFOUND(n1);
|
||||
int found_diff = WASFOUND (n2) - WASFOUND (n1);
|
||||
return found_diff ? found_diff : strcmp (n1->name, n2->name);
|
||||
}
|
||||
|
||||
/* Simple comparison by names. */
|
||||
static int
|
||||
compare_names (struct name const *n1, struct name const *n2)
|
||||
{
|
||||
return strcmp (n1->name, n2->name);
|
||||
}
|
||||
|
||||
|
||||
/* Add all the dirs under NAME, which names a directory, to the namelist.
|
||||
If any of the files is a directory, recurse on the subdirectory.
|
||||
DEVICE is the device not to leave, if the -l option is specified. */
|
||||
DEVICE is the device not to leave, if the -l option is specified.
|
||||
CMDLINE is true, if the NAME appeared on the command line. */
|
||||
|
||||
static void
|
||||
add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
add_hierarchy_to_namelist (struct name *name, dev_t device, bool cmdline)
|
||||
{
|
||||
char *file_name = name->name;
|
||||
const char *buffer = get_directory_contents (file_name, device);
|
||||
|
||||
if (! buffer)
|
||||
name->dir_contents = "\0\0\0\0";
|
||||
else
|
||||
const char *buffer;
|
||||
|
||||
name_fill_directory (name, device, cmdline);
|
||||
buffer = directory_contents (name->directory);
|
||||
if (buffer)
|
||||
{
|
||||
struct name *child_head = NULL, *child_tail = NULL;
|
||||
size_t name_length = name->length;
|
||||
size_t allocated_length = (name_length >= NAME_FIELD_SIZE
|
||||
? name_length + NAME_FIELD_SIZE
|
||||
@@ -744,8 +777,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
size_t string_length;
|
||||
int change_dir = name->change_dir;
|
||||
|
||||
name->dir_contents = buffer;
|
||||
strcpy (namebuf, file_name);
|
||||
strcpy (namebuf, name->name);
|
||||
if (! ISSLASH (namebuf[name_length - 1]))
|
||||
{
|
||||
namebuf[name_length++] = '/';
|
||||
@@ -772,15 +804,65 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
namebuf = xrealloc (namebuf, allocated_length + 1);
|
||||
}
|
||||
strcpy (namebuf + name_length, string + 1);
|
||||
np = addname (namebuf, change_dir);
|
||||
add_hierarchy_to_namelist (np, device);
|
||||
np = addname (namebuf, change_dir, false, name);
|
||||
if (!child_head)
|
||||
child_head = np;
|
||||
else
|
||||
child_tail->sibling = np;
|
||||
child_tail = np;
|
||||
add_hierarchy_to_namelist (np, device, false);
|
||||
}
|
||||
}
|
||||
|
||||
free (namebuf);
|
||||
name->child = child_head;
|
||||
}
|
||||
}
|
||||
|
||||
/* Auxiliary functions for hashed table of struct name's. */
|
||||
|
||||
static size_t
|
||||
name_hash (void const *entry, size_t n_buckets)
|
||||
{
|
||||
struct name const *name = entry;
|
||||
return hash_string (name->caname, n_buckets);
|
||||
}
|
||||
|
||||
/* Compare two directories for equality of their names. */
|
||||
static bool
|
||||
name_compare (void const *entry1, void const *entry2)
|
||||
{
|
||||
struct name const *name1 = entry1;
|
||||
struct name const *name2 = entry2;
|
||||
return strcmp (name1->caname, name2->caname) == 0;
|
||||
}
|
||||
|
||||
|
||||
/* Rebase `name' member of CHILD and all its siblings to
|
||||
the new PARENT. */
|
||||
static void
|
||||
rebase_child_list (struct name *child, struct name *parent)
|
||||
{
|
||||
size_t old_prefix_len = child->parent->length;
|
||||
size_t new_prefix_len = parent->length;
|
||||
char *new_prefix = parent->name;
|
||||
|
||||
for (; child; child = child->sibling)
|
||||
{
|
||||
size_t size = child->length - old_prefix_len + new_prefix_len;
|
||||
char *newp = xmalloc (size + 1);
|
||||
strcpy (newp, new_prefix);
|
||||
strcat (newp, child->name + old_prefix_len);
|
||||
free (child->name);
|
||||
child->name = newp;
|
||||
child->length = size;
|
||||
|
||||
rebase_directory (child->directory,
|
||||
child->parent->name, old_prefix_len,
|
||||
new_prefix, new_prefix_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect all the names from argv[] (or whatever), expand them into a
|
||||
directory tree, and sort them. This gets only subdirectories, not
|
||||
all files. */
|
||||
@@ -789,28 +871,50 @@ void
|
||||
collect_and_sort_names (void)
|
||||
{
|
||||
struct name *name;
|
||||
struct name *next_name;
|
||||
struct name *next_name, *prev_name;
|
||||
int num_names;
|
||||
struct stat statbuf;
|
||||
|
||||
Hash_table *nametab;
|
||||
|
||||
name_gather ();
|
||||
|
||||
if (listed_incremental_option)
|
||||
read_directory_file ();
|
||||
|
||||
if (!namelist)
|
||||
addname (".", 0);
|
||||
addname (".", 0, false, NULL);
|
||||
|
||||
for (name = namelist; name; name = next_name)
|
||||
if (listed_incremental_option)
|
||||
{
|
||||
next_name = name->next;
|
||||
if (name->found_count || name->dir_contents)
|
||||
switch (chdir_count ())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (namelist->change_dir == 0)
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("Using -C option inside file list is not "
|
||||
"allowed with --listed-incremental")));
|
||||
break;
|
||||
|
||||
default:
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("Only one -C option is allowed with "
|
||||
"--listed-incremental")));
|
||||
}
|
||||
|
||||
read_directory_file ();
|
||||
}
|
||||
|
||||
num_names = 0;
|
||||
for (name = namelist; name; name = name->next, num_names++)
|
||||
{
|
||||
if (name->found_count || name->directory)
|
||||
continue;
|
||||
if (name->matching_flags & EXCLUDE_WILDCARDS)
|
||||
/* NOTE: EXCLUDE_ANCHORED is not relevant here */
|
||||
/* FIXME: just skip regexps for now */
|
||||
continue;
|
||||
chdir_do (name->change_dir);
|
||||
|
||||
if (name->name[0] == 0)
|
||||
continue;
|
||||
|
||||
@@ -822,24 +926,63 @@ collect_and_sort_names (void)
|
||||
if (S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
name->found_count++;
|
||||
add_hierarchy_to_namelist (name, statbuf.st_dev);
|
||||
add_hierarchy_to_namelist (name, statbuf.st_dev, true);
|
||||
}
|
||||
}
|
||||
|
||||
num_names = 0;
|
||||
for (name = namelist; name; name = name->next)
|
||||
num_names++;
|
||||
namelist = merge_sort (namelist, num_names, compare_names);
|
||||
|
||||
for (name = namelist; name; name = name->next)
|
||||
name->found_count = 0;
|
||||
num_names = 0;
|
||||
nametab = hash_initialize (0, 0,
|
||||
name_hash,
|
||||
name_compare, NULL);
|
||||
for (name = namelist; name; name = next_name)
|
||||
{
|
||||
next_name = name->next;
|
||||
name->caname = normalize_filename (name->name);
|
||||
if (prev_name)
|
||||
{
|
||||
struct name *p = hash_lookup (nametab, name);
|
||||
if (p)
|
||||
{
|
||||
/* Keep the one listed in the command line */
|
||||
if (!name->parent)
|
||||
{
|
||||
if (p->child)
|
||||
rebase_child_list (p->child, name);
|
||||
/* FIXME: remove_directory (p->caname); ? */
|
||||
remname (p);
|
||||
free_name (p);
|
||||
num_names--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name->child)
|
||||
rebase_child_list (name->child, p);
|
||||
/* FIXME: remove_directory (name->caname); ? */
|
||||
remname (name);
|
||||
free_name (name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
name->found_count = 0;
|
||||
if (!hash_insert (nametab, name))
|
||||
xalloc_die ();
|
||||
prev_name = name;
|
||||
num_names++;
|
||||
}
|
||||
nametail = prev_name;
|
||||
hash_free (nametab);
|
||||
|
||||
namelist = merge_sort (namelist, num_names, compare_names_found);
|
||||
|
||||
if (listed_incremental_option)
|
||||
{
|
||||
for (name = namelist; name && name->name[0] == 0; name++)
|
||||
;
|
||||
if (name)
|
||||
name->dir_contents = append_incremental_renames (name->dir_contents);
|
||||
append_incremental_renames (name->directory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,8 +1023,8 @@ name_scan (const char *file_name)
|
||||
find and return all the non-found names in the namelist. */
|
||||
struct name *gnu_list_name;
|
||||
|
||||
char *
|
||||
name_from_list (void)
|
||||
struct name const *
|
||||
name_from_list ()
|
||||
{
|
||||
if (!gnu_list_name)
|
||||
gnu_list_name = namelist;
|
||||
@@ -892,9 +1035,9 @@ name_from_list (void)
|
||||
{
|
||||
gnu_list_name->found_count++;
|
||||
chdir_do (gnu_list_name->change_dir);
|
||||
return gnu_list_name->name;
|
||||
return gnu_list_name;
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -928,24 +1071,6 @@ excluded_name (char const *name)
|
||||
{
|
||||
return excluded_file_name (excluded, name + FILE_SYSTEM_PREFIX_LEN (name));
|
||||
}
|
||||
|
||||
/* Names to avoid dumping. */
|
||||
static Hash_table *avoided_name_table;
|
||||
|
||||
/* Remember to not archive NAME. */
|
||||
void
|
||||
add_avoided_name (char const *name)
|
||||
{
|
||||
hash_string_insert (&avoided_name_table, name);
|
||||
}
|
||||
|
||||
/* Should NAME be avoided when archiving? */
|
||||
bool
|
||||
is_avoided_name (char const *name)
|
||||
{
|
||||
return hash_string_lookup (avoided_name_table, name);
|
||||
}
|
||||
|
||||
|
||||
static Hash_table *individual_file_table;
|
||||
|
||||
@@ -953,12 +1078,12 @@ static void
|
||||
register_individual_file (char const *name)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
|
||||
if (deref_stat (dereference_option, name, &st) != 0)
|
||||
return; /* Will be complained about later */
|
||||
if (S_ISDIR (st.st_mode))
|
||||
return;
|
||||
|
||||
|
||||
hash_string_insert (&individual_file_table, name);
|
||||
}
|
||||
|
||||
|
||||
178
src/open3.c
178
src/open3.c
@@ -1,178 +0,0 @@
|
||||
/* Defines for Sys V style 3-argument open call.
|
||||
Copyright (C) 1988, 1994, 1995, 1996 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 2, 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, write to the Free Software Foundation, Inc.,
|
||||
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#if EMUL_OPEN3
|
||||
|
||||
/* open3.h -- #defines for the various flags for the Sys V style 3-argument
|
||||
open() call. On BSD or System 5, the system already has this in an
|
||||
include file. This file is needed for V7 and MINIX systems for the
|
||||
benefit of open3() in port.c, a routine that emulates the 3-argument call
|
||||
using system calls available on V7/MINIX.
|
||||
|
||||
Written 1987-06-10 by Richard Todd.
|
||||
|
||||
The names have been changed by John Gilmore, 1987-07-31, since Richard
|
||||
called it "bsdopen", and really this change was introduced in AT&T Unix
|
||||
systems before BSD picked it up. */
|
||||
|
||||
/*-----------------------------------------------------------------------.
|
||||
| open3 -- routine to emulate the 3-argument open system. |
|
||||
| |
|
||||
| open3 (path, flag, mode); |
|
||||
| |
|
||||
| Attempts to open the file specified by the given pathname. The |
|
||||
| following flag bits specify options to the routine. Needless to say, |
|
||||
| you should only specify one of the first three. Function returns file |
|
||||
| descriptor if successful, -1 and errno if not. |
|
||||
`-----------------------------------------------------------------------*/
|
||||
|
||||
/* The routine obeys the following mode arguments:
|
||||
|
||||
O_RDONLY file open for read only
|
||||
O_WRONLY file open for write only
|
||||
O_RDWR file open for both read & write
|
||||
|
||||
O_CREAT file is created with specified mode if it needs to be
|
||||
O_TRUNC if file exists, it is truncated to 0 bytes
|
||||
O_EXCL used with O_CREAT--routine returns error if file exists */
|
||||
|
||||
/* Call that if present in most modern Unix systems. This version attempts
|
||||
to support all the flag bits except for O_NDELAY and O_APPEND, which are
|
||||
silently ignored. The emulation is not as efficient as the real thing
|
||||
(at worst, 4 system calls instead of one), but there's not much I can do
|
||||
about that. */
|
||||
|
||||
/* Array to give arguments to access for various modes FIXME, this table
|
||||
depends on the specific integer values of O_*, and also contains
|
||||
integers (args to 'access') that should be #define's. */
|
||||
|
||||
static int modes[] =
|
||||
{
|
||||
04, /* O_RDONLY */
|
||||
02, /* O_WRONLY */
|
||||
06, /* O_RDWR */
|
||||
06, /* invalid, just cope: O_WRONLY+O_RDWR */
|
||||
};
|
||||
|
||||
/* Shut off the automatic emulation of open(), we'll need it. */
|
||||
#undef open
|
||||
|
||||
int
|
||||
open3 (char *path, int flags, int mode)
|
||||
{
|
||||
int exists = 1;
|
||||
int call_creat = 0;
|
||||
|
||||
/* We actually do the work by calling the open() or creat() system
|
||||
call, depending on the flags. Call_creat is true if we will use
|
||||
creat(), false if we will use open(). */
|
||||
|
||||
/* See if the file exists and is accessible in the requested mode.
|
||||
|
||||
Strictly speaking we shouldn't be using access, since access checks
|
||||
against real uid, and the open call should check against euid. Most
|
||||
cases real uid == euid, so it won't matter. FIXME. FIXME, the
|
||||
construction "flags & 3" and the modes table depends on the specific
|
||||
integer values of the O_* #define's. Foo! */
|
||||
|
||||
if (access (path, modes[flags & 3]) < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
/* The file does not exist. */
|
||||
|
||||
exists = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Probably permission violation. */
|
||||
|
||||
if (flags & O_EXCL)
|
||||
{
|
||||
/* Oops, the file exists, we didn't want it. No matter
|
||||
what the error, claim EEXIST. */
|
||||
|
||||
errno = EEXIST; /* FIXME: errno should be read-only */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have the O_CREAT bit set, check for O_EXCL. */
|
||||
|
||||
if (flags & O_CREAT)
|
||||
{
|
||||
if ((flags & O_EXCL) && exists)
|
||||
{
|
||||
/* Oops, the file exists and we didn't want it to. */
|
||||
|
||||
errno = EEXIST; /* FIXME: errno should be read-only */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the file doesn't exist, be sure to call creat() so that it
|
||||
will be created with the proper mode. */
|
||||
|
||||
if (!exists)
|
||||
call_creat = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If O_CREAT isn't set and the file doesn't exist, error. */
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
errno = ENOENT; /* FIXME: errno should be read-only */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the O_TRUNC flag is set and the file exists, we want to call
|
||||
creat() anyway, since creat() guarantees that the file will be
|
||||
truncated and open()-for-writing doesn't. (If the file doesn't
|
||||
exist, we're calling creat() anyway and the file will be created
|
||||
with zero length.) */
|
||||
|
||||
if ((flags & O_TRUNC) && exists)
|
||||
call_creat = 1;
|
||||
|
||||
/* Actually do the call. */
|
||||
|
||||
if (call_creat)
|
||||
|
||||
/* Call creat. May have to close and reopen the file if we want
|
||||
O_RDONLY or O_RDWR access -- creat() only gives O_WRONLY. */
|
||||
|
||||
{
|
||||
int fd = creat (path, mode);
|
||||
|
||||
if (fd < 0 || (flags & O_WRONLY))
|
||||
return fd;
|
||||
if (close (fd) < 0)
|
||||
return -1;
|
||||
|
||||
/* Fall out to reopen the file we've created. */
|
||||
}
|
||||
|
||||
/* Calling old open, we strip most of the new flags just in case. */
|
||||
|
||||
return open (path, flags & (O_RDONLY | O_WRONLY | O_RDWR | O_BINARY));
|
||||
}
|
||||
|
||||
#endif /* EMUL_OPEN3 */
|
||||
69
src/open3.h
69
src/open3.h
@@ -1,69 +0,0 @@
|
||||
/* Defines for Sys V style 3-argument open call.
|
||||
Copyright (C) 1988 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* @(#)open3.h 1.4 87/11/11
|
||||
*
|
||||
* open3.h -- #defines for the various flags for the Sys V style 3-argument
|
||||
* open() call. On BSD or System 5, the system already has this in an
|
||||
* include file. This file is needed for V7 and MINIX systems for the
|
||||
* benefit of open3() in port.c, a routine that emulates the 3-argument
|
||||
* call using system calls available on V7/MINIX.
|
||||
*
|
||||
* This file is needed by PD tar even if we aren't using the
|
||||
* emulator, since the #defines for O_WRONLY, etc. are used in
|
||||
* a couple of places besides the open() calls, (e.g. in the assignment
|
||||
* to openflag in extract.c). We just #include this rather than
|
||||
* #ifdef them out.
|
||||
*
|
||||
* Written 6/10/87 by rmtodd@uokmax (Richard Todd).
|
||||
*
|
||||
* The names have been changed by John Gilmore, 31 July 1987, since
|
||||
* Richard called it "bsdopen", and really this change was introduced in
|
||||
* AT&T Unix systems before BSD picked it up.
|
||||
*/
|
||||
|
||||
/* Only one of the next three should be specified */
|
||||
#define O_RDONLY 0 /* only allow read */
|
||||
#define O_WRONLY 1 /* only allow write */
|
||||
#define O_RDWR 2 /* both are allowed */
|
||||
|
||||
/* The rest of these can be OR-ed in to the above. */
|
||||
/*
|
||||
* O_NDELAY isn't implemented by the emulator. It's only useful (to tar) on
|
||||
* systems that have named pipes anyway; it prevents tar's hanging by
|
||||
* opening a named pipe. We #ifndef it because some systems already have
|
||||
* it defined.
|
||||
*/
|
||||
#ifndef O_NDELAY
|
||||
#define O_NDELAY 4 /* don't block on opening devices that would
|
||||
* block on open -- ignored by emulator. */
|
||||
#endif
|
||||
#define O_CREAT 8 /* create file if needed */
|
||||
#define O_EXCL 16 /* file cannot already exist */
|
||||
#define O_TRUNC 32 /* truncate file on open */
|
||||
#define O_APPEND 64 /* always write at end of file -- ignored by emul */
|
||||
|
||||
#ifdef EMUL_OPEN3
|
||||
/*
|
||||
* make emulation transparent to rest of file -- redirect all open() calls
|
||||
* to our routine
|
||||
*/
|
||||
#define open open3
|
||||
#endif
|
||||
1256
src/port.c
1256
src/port.c
File diff suppressed because it is too large
Load Diff
215
src/port.h
215
src/port.h
@@ -1,215 +0,0 @@
|
||||
/* Portability declarations. Requires sys/types.h.
|
||||
Copyright (C) 1988, 1992 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#ifdef __GNUC__
|
||||
#define alloca __builtin_alloca
|
||||
#else /* not __GNUC__ */
|
||||
#if HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#else /* not HAVE_ALLOCA_H */
|
||||
#ifdef _AIX
|
||||
#pragma alloca
|
||||
#else /* not _AIX */
|
||||
char *alloca ();
|
||||
#endif /* not _AIX */
|
||||
#endif /* not HAVE_ALLOCA_H */
|
||||
#endif /* not __GNUC__ */
|
||||
|
||||
#include "pathmax.h"
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#include <sys/wait.h>
|
||||
#else /* !_POSIX_VERSION */
|
||||
#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
|
||||
#define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0)
|
||||
#define WIFEXITED(w) (((w) & 0xff) == 0)
|
||||
|
||||
#define WSTOPSIG(w) (((w) >> 8) & 0xff)
|
||||
#define WTERMSIG(w) ((w) & 0x7f)
|
||||
#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
|
||||
#endif /* _POSIX_VERSION */
|
||||
|
||||
/* nonstandard */
|
||||
#ifndef WIFCOREDUMPED
|
||||
#define WIFCOREDUMPED(w) (((w) & 0x80) != 0)
|
||||
#endif
|
||||
|
||||
#ifdef __MSDOS__
|
||||
/* missing things from sys/stat.h */
|
||||
#define S_ISUID 0
|
||||
#define S_ISGID 0
|
||||
#define S_ISVTX 0
|
||||
|
||||
/* device stuff */
|
||||
#define makedev(ma, mi) ((ma << 8) | mi)
|
||||
#define major(dev) (dev)
|
||||
#define minor(dev) (dev)
|
||||
typedef long off_t;
|
||||
#endif /* __MSDOS__ */
|
||||
|
||||
#if defined(__STDC__) || defined(__TURBOC__)
|
||||
#define PTR void *
|
||||
#else
|
||||
#define PTR char *
|
||||
#define const
|
||||
#endif
|
||||
|
||||
/* Since major is a function on SVR4, we can't just use `ifndef major'. */
|
||||
#ifdef major /* Might be defined in sys/types.h. */
|
||||
#define HAVE_MAJOR
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_MKDEV)
|
||||
#include <sys/mkdev.h>
|
||||
#define HAVE_MAJOR
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_SYSMACROS)
|
||||
#include <sys/sysmacros.h>
|
||||
#define HAVE_MAJOR
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MAJOR
|
||||
#define major(dev) (((dev) >> 8) & 0xff)
|
||||
#define minor(dev) ((dev) & 0xff)
|
||||
#define makedev(maj, min) (((maj) << 8) | (min))
|
||||
#endif
|
||||
#undef HAVE_MAJOR
|
||||
|
||||
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#if !defined(__MSDOS__) && !defined(STDC_HEADERS)
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#ifdef index
|
||||
#undef index
|
||||
#endif
|
||||
#ifdef rindex
|
||||
#undef rindex
|
||||
#endif
|
||||
#define index strchr
|
||||
#define rindex strrchr
|
||||
#define bcopy(s, d, n) memcpy(d, s, n)
|
||||
#define bzero(s, n) memset(s, 0, n)
|
||||
#define bcmp memcmp
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#if defined(STDC_HEADERS)
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
char *malloc (), *realloc ();
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_VERSION
|
||||
#ifdef __MSDOS__
|
||||
#include <io.h>
|
||||
#else /* !__MSDOS__ */
|
||||
off_t lseek ();
|
||||
#endif /* !__MSDOS__ */
|
||||
char *getcwd ();
|
||||
#endif /* !_POSIX_VERSION */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_CREAT
|
||||
#define O_CREAT 0
|
||||
#endif
|
||||
#ifndef O_NDELAY
|
||||
#define O_NDELAY 0
|
||||
#endif
|
||||
#ifndef O_RDONLY
|
||||
#define O_RDONLY 0
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
#define O_RDWR 2
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
|
||||
#define mode_t unsigned short
|
||||
#endif
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
#if !defined(S_ISCTG) && defined(S_IFCTG) /* contiguous file */
|
||||
#define S_ISCTG(m) (((m) & S_IFMT) == S_IFCTG)
|
||||
#endif
|
||||
#if !defined(S_ISVTX)
|
||||
#define S_ISVTX 0001000
|
||||
#endif
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#include "msd_dir.h"
|
||||
#define NLENGTH(direct) ((direct)->d_namlen)
|
||||
|
||||
#else /* not __MSDOS__ */
|
||||
|
||||
#if defined(DIRENT) || defined(_POSIX_VERSION)
|
||||
#include <dirent.h>
|
||||
#define NLENGTH(direct) (strlen((direct)->d_name))
|
||||
#else /* not (DIRENT or _POSIX_VERSION) */
|
||||
#define dirent direct
|
||||
#define NLENGTH(direct) ((direct)->d_namlen)
|
||||
#ifdef SYSNDIR
|
||||
#include <sys/ndir.h>
|
||||
#endif /* SYSNDIR */
|
||||
#ifdef SYSDIR
|
||||
#include <sys/dir.h>
|
||||
#endif /* SYSDIR */
|
||||
#ifdef NDIR
|
||||
#include <ndir.h>
|
||||
#endif /* NDIR */
|
||||
#endif /* DIRENT or _POSIX_VERSION */
|
||||
|
||||
#endif /* not __MSDOS__ */
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Read files directly from the fast file system
|
||||
Copyright (C) 1992 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
|
||||
|
||||
|
||||
37
src/suffix.c
37
src/suffix.c
@@ -26,26 +26,29 @@ struct compression_suffix
|
||||
const char *program;
|
||||
};
|
||||
|
||||
struct compression_suffix compression_suffixes[] = {
|
||||
#define S(s,p) #s, sizeof (#s) - 1, #p
|
||||
{ S(gz, gzip) },
|
||||
{ S(tgz, gzip) },
|
||||
{ S(taz, gzip) },
|
||||
{ S(Z, compress) },
|
||||
{ S(taZ, compress) },
|
||||
{ S(bz2, bzip2) },
|
||||
{ S(tbz, bzip2) },
|
||||
{ S(tbz2, bzip2) },
|
||||
{ S(tz2, bzip2) },
|
||||
{ S(lzma, lzma) },
|
||||
{ S(tlz, lzma) },
|
||||
{ S(lzo, lzop) },
|
||||
{ S(xz, xz) },
|
||||
static struct compression_suffix compression_suffixes[] = {
|
||||
#define __CAT2__(a,b) a ## b
|
||||
#define S(s,p) #s, sizeof (#s) - 1, __CAT2__(p,_PROGRAM)
|
||||
{ S(gz, GZIP) },
|
||||
{ S(tgz, GZIP) },
|
||||
{ S(taz, GZIP) },
|
||||
{ S(Z, COMPRESS) },
|
||||
{ S(taZ, COMPRESS) },
|
||||
{ S(bz2, BZIP2) },
|
||||
{ S(tbz, BZIP2) },
|
||||
{ S(tbz2, BZIP2) },
|
||||
{ S(tz2, BZIP2) },
|
||||
{ S(lz, LZIP) },
|
||||
{ S(lzma, LZMA) },
|
||||
{ S(tlz, LZMA) },
|
||||
{ S(lzo, LZOP) },
|
||||
{ S(xz, XZ) },
|
||||
#undef S
|
||||
#undef __CAT2__
|
||||
};
|
||||
|
||||
int nsuffixes = sizeof (compression_suffixes) /
|
||||
sizeof (compression_suffixes[0]);
|
||||
static int nsuffixes = sizeof (compression_suffixes) /
|
||||
sizeof (compression_suffixes[0]);
|
||||
|
||||
static const char *
|
||||
find_compression_program (const char *name, const char *defprog)
|
||||
|
||||
90
src/system.c
90
src/system.c
@@ -174,11 +174,11 @@ sys_wait_for_child (pid_t child_pid, bool eof)
|
||||
{
|
||||
int sig = WTERMSIG (wait_status);
|
||||
if (!(!eof && sig == SIGPIPE))
|
||||
ERROR ((0, 0, _("Child died with signal %d"), sig));
|
||||
FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig));
|
||||
}
|
||||
else if (WEXITSTATUS (wait_status) != 0)
|
||||
ERROR ((0, 0, _("Child returned status %d"),
|
||||
WEXITSTATUS (wait_status)));
|
||||
FATAL_ERROR ((0, 0, _("Child returned status %d"),
|
||||
WEXITSTATUS (wait_status)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,30 @@ xdup2 (int from, int into)
|
||||
}
|
||||
}
|
||||
|
||||
void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
|
||||
|
||||
/* Propagate any failure of the grandchild back to the parent. */
|
||||
void
|
||||
wait_for_grandchild (pid_t pid)
|
||||
{
|
||||
int wait_status;
|
||||
int exit_code = 0;
|
||||
|
||||
while (waitpid (pid, &wait_status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (use_compress_program_option);
|
||||
break;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
raise (WTERMSIG (wait_status));
|
||||
else if (WEXITSTATUS (wait_status) != 0)
|
||||
exit_code = WEXITSTATUS (wait_status);
|
||||
|
||||
exit (exit_code);
|
||||
}
|
||||
|
||||
/* Set ARCHIVE for writing, then compressing an archive. */
|
||||
pid_t
|
||||
sys_child_open_for_compress (void)
|
||||
@@ -291,7 +315,6 @@ sys_child_open_for_compress (void)
|
||||
int child_pipe[2];
|
||||
pid_t grandchild_pid;
|
||||
pid_t child_pid;
|
||||
int wait_status;
|
||||
|
||||
xpipe (parent_pipe);
|
||||
child_pid = xfork ();
|
||||
@@ -307,8 +330,9 @@ sys_child_open_for_compress (void)
|
||||
|
||||
/* The new born child tar is here! */
|
||||
|
||||
program_name = _("tar (child)");
|
||||
|
||||
set_program_name (_("tar (child)"));
|
||||
signal (SIGPIPE, SIG_DFL);
|
||||
|
||||
xdup2 (parent_pipe[PREAD], STDIN_FILENO);
|
||||
xclose (parent_pipe[PWRITE]);
|
||||
|
||||
@@ -351,7 +375,7 @@ sys_child_open_for_compress (void)
|
||||
{
|
||||
/* The newborn grandchild tar is here! Launch the compressor. */
|
||||
|
||||
program_name = _("tar (grandchild)");
|
||||
set_program_name (_("tar (grandchild)"));
|
||||
|
||||
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
|
||||
xclose (child_pipe[PREAD]);
|
||||
@@ -424,24 +448,7 @@ sys_child_open_for_compress (void)
|
||||
archive_write_error (status);
|
||||
}
|
||||
|
||||
/* Propagate any failure of the grandchild back to the parent. */
|
||||
|
||||
while (waitpid (grandchild_pid, &wait_status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (use_compress_program_option);
|
||||
break;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
{
|
||||
kill (child_pid, WTERMSIG (wait_status));
|
||||
exit_status = TAREXIT_FAILURE;
|
||||
}
|
||||
else if (WEXITSTATUS (wait_status) != 0)
|
||||
exit_status = WEXITSTATUS (wait_status);
|
||||
|
||||
exit (exit_status);
|
||||
wait_for_grandchild (grandchild_pid);
|
||||
}
|
||||
|
||||
/* Set ARCHIVE for uncompressing, then reading an archive. */
|
||||
@@ -452,7 +459,6 @@ sys_child_open_for_uncompress (void)
|
||||
int child_pipe[2];
|
||||
pid_t grandchild_pid;
|
||||
pid_t child_pid;
|
||||
int wait_status;
|
||||
|
||||
xpipe (parent_pipe);
|
||||
child_pid = xfork ();
|
||||
@@ -468,8 +474,9 @@ sys_child_open_for_uncompress (void)
|
||||
|
||||
/* The newborn child tar is here! */
|
||||
|
||||
program_name = _("tar (child)");
|
||||
|
||||
set_program_name (_("tar (child)"));
|
||||
signal (SIGPIPE, SIG_DFL);
|
||||
|
||||
xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
|
||||
xclose (parent_pipe[PREAD]);
|
||||
|
||||
@@ -503,7 +510,7 @@ sys_child_open_for_uncompress (void)
|
||||
{
|
||||
/* The newborn grandchild tar is here! Launch the uncompressor. */
|
||||
|
||||
program_name = _("tar (grandchild)");
|
||||
set_program_name (_("tar (grandchild)"));
|
||||
|
||||
xdup2 (child_pipe[PREAD], STDIN_FILENO);
|
||||
xclose (child_pipe[PWRITE]);
|
||||
@@ -562,24 +569,7 @@ sys_child_open_for_uncompress (void)
|
||||
|
||||
xclose (STDOUT_FILENO);
|
||||
|
||||
/* Propagate any failure of the grandchild back to the parent. */
|
||||
|
||||
while (waitpid (grandchild_pid, &wait_status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (use_compress_program_option);
|
||||
break;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
{
|
||||
kill (child_pid, WTERMSIG (wait_status));
|
||||
exit_status = TAREXIT_FAILURE;
|
||||
}
|
||||
else if (WEXITSTATUS (wait_status) != 0)
|
||||
exit_status = WEXITSTATUS (wait_status);
|
||||
|
||||
exit (exit_status);
|
||||
wait_for_grandchild (grandchild_pid);
|
||||
}
|
||||
|
||||
|
||||
@@ -639,6 +629,12 @@ static void
|
||||
stat_to_env (char *name, char type, struct tar_stat_info *st)
|
||||
{
|
||||
str_to_env ("TAR_VERSION", PACKAGE_VERSION);
|
||||
str_to_env ("TAR_ARCHIVE", *archive_name_cursor);
|
||||
dec_to_env ("TAR_VOLUME", archive_name_cursor - archive_name_array + 1);
|
||||
dec_to_env ("TAR_BLOCKING_FACTOR", blocking_factor);
|
||||
str_to_env ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
archive_format : current_format));
|
||||
chr_to_env ("TAR_FILETYPE", type);
|
||||
oct_to_env ("TAR_MODE", st->stat.st_mode);
|
||||
str_to_env ("TAR_FILENAME", name);
|
||||
|
||||
240
src/tcexparg.c
240
src/tcexparg.c
@@ -1,240 +0,0 @@
|
||||
/* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0
|
||||
|
||||
This file is in the public domain.
|
||||
|
||||
Compile your main program with -Dmain=_main and link with this file.
|
||||
|
||||
After that, it is just as if the operating system had expanded the
|
||||
arguments, except that they are not sorted. The program name and all
|
||||
arguments that are expanded from wildcards are lowercased.
|
||||
|
||||
Syntax for wildcards:
|
||||
* Matches zero or more of any character (except a '.' at
|
||||
the beginning of a name).
|
||||
? Matches any single character.
|
||||
[r3z] Matches 'r', '3', or 'z'.
|
||||
[a-d] Matches a single character in the range 'a' through 'd'.
|
||||
[!a-d] Matches any single character except a character in the
|
||||
range 'a' through 'd'.
|
||||
|
||||
The period between the filename root and its extension need not be
|
||||
given explicitly. Thus, the pattern `a*e' will match 'abacus.exe'
|
||||
and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive.
|
||||
|
||||
Authors:
|
||||
The expargs code is a modification of wildcard expansion code
|
||||
written for Turbo C 1.0 by
|
||||
Richard Hargrove
|
||||
Texas Instruments, Inc.
|
||||
P.O. Box 869305, m/s 8473
|
||||
Plano, Texas 75086
|
||||
214/575-4128
|
||||
and posted to USENET in September, 1987.
|
||||
|
||||
The wild_match code was written by Rich Salz, rsalz@bbn.com,
|
||||
posted to net.sources in November, 1986.
|
||||
|
||||
The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2,
|
||||
posted to comp.sys.ibm.pc in November, 1988.
|
||||
|
||||
Major performance enhancements and bug fixes, and source cleanup,
|
||||
by David MacKenzie, djm@gnu.ai.mit.edu. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dos.h>
|
||||
#include <dir.h>
|
||||
|
||||
/* Number of new arguments to allocate space for at a time. */
|
||||
#define ARGS_INCREMENT 10
|
||||
|
||||
/* The name this program was run with, for error messages. */
|
||||
static char *program_name;
|
||||
|
||||
static char **grow_argv (char **new_argv, int new_argc);
|
||||
static void fatal_error (const char *message);
|
||||
|
||||
int wild_match (char *string, char *pattern);
|
||||
char *basename (char *path);
|
||||
|
||||
char **expargs (int *, char **);
|
||||
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, char **argv, char **envp)
|
||||
{
|
||||
argv = expargs (&argc, argv);
|
||||
return _main (argc, argv, envp);
|
||||
}
|
||||
|
||||
char **
|
||||
expargs (int *pargc, char **argv)
|
||||
{
|
||||
char path[MAXPATH + 1];
|
||||
char **new_argv;
|
||||
struct ffblk block;
|
||||
char *path_base;
|
||||
char *arg_base;
|
||||
int argind;
|
||||
int new_argc;
|
||||
int path_length;
|
||||
int matched;
|
||||
|
||||
program_name = argv[0];
|
||||
if (program_name && *program_name)
|
||||
strlwr (program_name);
|
||||
new_argv = grow_argv (NULL, 0);
|
||||
new_argv[0] = argv[0];
|
||||
new_argc = 1;
|
||||
|
||||
for (argind = 1; argind < *pargc; ++argind)
|
||||
{
|
||||
matched = 0;
|
||||
if (strpbrk (argv[argind], "?*[") != NULL)
|
||||
{
|
||||
strncpy (path, argv[argind], MAXPATH - 3);
|
||||
path_base = basename (path);
|
||||
strcpy (path_base, "*.*");
|
||||
arg_base = argv[argind] + (path_base - path);
|
||||
|
||||
if (!findfirst (path, &block, FA_DIREC))
|
||||
{
|
||||
strlwr (path);
|
||||
do
|
||||
{
|
||||
/* Only match "." and ".." explicitly. */
|
||||
if (*block.ff_name == '.' && *arg_base != '.')
|
||||
continue;
|
||||
path_length = stpcpy (path_base, block.ff_name) - path + 1;
|
||||
strlwr (path_base);
|
||||
if (wild_match (path, argv[argind]))
|
||||
{
|
||||
matched = 1;
|
||||
new_argv[new_argc] = (char *) malloc (path_length);
|
||||
if (new_argv[new_argc] == NULL)
|
||||
fatal_error ("memory exhausted");
|
||||
strcpy (new_argv[new_argc++], path);
|
||||
new_argv = grow_argv (new_argv, new_argc);
|
||||
}
|
||||
} while (!findnext (&block));
|
||||
}
|
||||
}
|
||||
if (matched == 0)
|
||||
new_argv[new_argc++] = argv[argind];
|
||||
new_argv = grow_argv (new_argv, new_argc);
|
||||
}
|
||||
|
||||
*pargc = new_argc;
|
||||
new_argv[new_argc] = NULL;
|
||||
return &new_argv[0];
|
||||
}
|
||||
|
||||
/* Return a pointer to the last element of PATH. */
|
||||
|
||||
char *
|
||||
basename (char *path)
|
||||
{
|
||||
char *tail;
|
||||
|
||||
for (tail = path; *path; ++path)
|
||||
if (*path == ':' || *path == '\\')
|
||||
tail = path + 1;
|
||||
return tail;
|
||||
}
|
||||
|
||||
static char **
|
||||
grow_argv (char **new_argv, int new_argc)
|
||||
{
|
||||
if (new_argc % ARGS_INCREMENT == 0)
|
||||
{
|
||||
new_argv = (char **) realloc
|
||||
(new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT));
|
||||
if (new_argv == NULL)
|
||||
fatal_error ("memory exhausted");
|
||||
}
|
||||
return new_argv;
|
||||
}
|
||||
|
||||
static void
|
||||
fatal_error (const char *message)
|
||||
{
|
||||
putc ('\n', stderr);
|
||||
if (program_name && *program_name)
|
||||
{
|
||||
fputs (program_name, stderr);
|
||||
fputs (": ", stderr);
|
||||
}
|
||||
fputs (message, stderr);
|
||||
putc ('\n', stderr);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Shell-style pattern matching for ?, \, [], and * characters.
|
||||
I'm putting this replacement in the public domain.
|
||||
|
||||
Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */
|
||||
|
||||
/* The character that inverts a character class; '!' or '^'. */
|
||||
#define INVERT '!'
|
||||
|
||||
static int star (char *string, char *pattern);
|
||||
|
||||
/* Return nonzero if `string' matches Unix-style wildcard pattern
|
||||
`pattern'; zero if not. */
|
||||
|
||||
int
|
||||
wild_match (char *string, char *pattern)
|
||||
{
|
||||
int prev; /* Previous character in character class. */
|
||||
int matched; /* If 1, character class has been matched. */
|
||||
int reverse; /* If 1, character class is inverted. */
|
||||
|
||||
for (; *pattern; string++, pattern++)
|
||||
switch (*pattern)
|
||||
{
|
||||
case '\\':
|
||||
/* Literal match with following character; fall through. */
|
||||
pattern++;
|
||||
default:
|
||||
if (*string != *pattern)
|
||||
return 0;
|
||||
continue;
|
||||
case '?':
|
||||
/* Match anything. */
|
||||
if (*string == '\0')
|
||||
return 0;
|
||||
continue;
|
||||
case '*':
|
||||
/* Trailing star matches everything. */
|
||||
return *++pattern ? star (string, pattern) : 1;
|
||||
case '[':
|
||||
/* Check for inverse character class. */
|
||||
reverse = pattern[1] == INVERT;
|
||||
if (reverse)
|
||||
pattern++;
|
||||
for (prev = 256, matched = 0; *++pattern && *pattern != ']';
|
||||
prev = *pattern)
|
||||
if (*pattern == '-'
|
||||
? *string <= *++pattern && *string >= prev
|
||||
: *string == *pattern)
|
||||
matched = 1;
|
||||
if (matched == reverse)
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
return *string == '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
star (char *string, char *pattern)
|
||||
{
|
||||
while (wild_match (string, pattern) == 0)
|
||||
if (*++string == '\0')
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* Find out if we need the pad field in the header for this machine
|
||||
Copyright (C) 1991 Free Software Foundation
|
||||
|
||||
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 2, 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct inc
|
||||
{
|
||||
char a[20];
|
||||
char b[20];
|
||||
};
|
||||
|
||||
struct test1
|
||||
{
|
||||
char a;
|
||||
struct inc in[5];
|
||||
};
|
||||
|
||||
struct test2
|
||||
{
|
||||
char a;
|
||||
char b;
|
||||
struct inc in[5];
|
||||
};
|
||||
|
||||
void
|
||||
main ()
|
||||
{
|
||||
struct test1 t1;
|
||||
struct test2 t2;
|
||||
int t1diff, t2diff;
|
||||
FILE *fp = fopen ("testpad.h", "w");
|
||||
|
||||
if (fp == 0)
|
||||
{
|
||||
fprintf (stderr, "testpad: cannot open ");
|
||||
fflush (stderr);
|
||||
perror ("testpad.h");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
t1diff = (char *) &t1.in[0] - (char *) &t1;
|
||||
t2diff = (char *) &t2.in[0] - (char *) &t2;
|
||||
|
||||
if (t2diff == t1diff + 1)
|
||||
fprintf (fp, "#define NEEDPAD\n");
|
||||
else if (t1diff != t2diff)
|
||||
fprintf (stderr, "Cannot determine padding for tar struct, \n\
|
||||
will try with none.\n");
|
||||
|
||||
fclose (fp);
|
||||
exit (0);
|
||||
}
|
||||
@@ -430,21 +430,21 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
|
||||
switch (case_ctl)
|
||||
{
|
||||
case ctl_upcase_next:
|
||||
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
|
||||
case_ctl_buffer[0] = toupper ((unsigned char) case_ctl_buffer[0]);
|
||||
break;
|
||||
|
||||
case ctl_locase_next:
|
||||
case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
|
||||
case_ctl_buffer[0] = tolower ((unsigned char) case_ctl_buffer[0]);
|
||||
break;
|
||||
|
||||
case ctl_upcase:
|
||||
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
||||
*p = toupper (*p);
|
||||
*p = toupper ((unsigned char) *p);
|
||||
break;
|
||||
|
||||
case ctl_locase:
|
||||
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
||||
*p = tolower (*p);
|
||||
*p = tolower ((unsigned char) *p);
|
||||
break;
|
||||
|
||||
case ctl_stop:
|
||||
@@ -628,4 +628,3 @@ transform_name (char **pinput, int type)
|
||||
{
|
||||
return transform_name_fp (pinput, type, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
158
src/unlink.c
Normal file
158
src/unlink.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
#include <quotearg.h>
|
||||
|
||||
struct deferred_unlink
|
||||
{
|
||||
struct deferred_unlink *next; /* Next unlink in the queue */
|
||||
char *file_name; /* Absolute name of the file to unlink */
|
||||
bool is_dir; /* True if file_name is a directory */
|
||||
off_t records_written; /* Number of records written when this
|
||||
entry got added to the queue */
|
||||
};
|
||||
|
||||
/* The unlink queue */
|
||||
static struct deferred_unlink *dunlink_head, *dunlink_tail;
|
||||
|
||||
/* Number of entries in the queue */
|
||||
static size_t dunlink_count;
|
||||
|
||||
/* List of entries available for allocation */
|
||||
static struct deferred_unlink *dunlink_avail;
|
||||
|
||||
/* Delay (number of records written) between adding entry to the
|
||||
list and its actual removal. */
|
||||
size_t deferred_unlink_delay = 0;
|
||||
|
||||
static struct deferred_unlink *
|
||||
dunlink_alloc ()
|
||||
{
|
||||
struct deferred_unlink *p;
|
||||
if (dunlink_avail)
|
||||
{
|
||||
p = dunlink_avail;
|
||||
dunlink_avail = p->next;
|
||||
p->next = NULL;
|
||||
}
|
||||
else
|
||||
p = xmalloc (sizeof (*p));
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
dunlink_reclaim (struct deferred_unlink *p)
|
||||
{
|
||||
free (p->file_name);
|
||||
p->next = dunlink_avail;
|
||||
dunlink_avail = p;
|
||||
}
|
||||
|
||||
static void
|
||||
flush_deferred_unlinks (bool force)
|
||||
{
|
||||
struct deferred_unlink *p, *prev = NULL;
|
||||
|
||||
for (p = dunlink_head; p; )
|
||||
{
|
||||
struct deferred_unlink *next = p->next;
|
||||
if (force
|
||||
|| records_written > p->records_written + deferred_unlink_delay)
|
||||
{
|
||||
if (p->is_dir)
|
||||
{
|
||||
if (rmdir (p->file_name) != 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
/* nothing to worry about */
|
||||
break;
|
||||
case ENOTEMPTY:
|
||||
if (!force)
|
||||
{
|
||||
/* Keep the record in list, in the hope we'll
|
||||
be able to remove it later */
|
||||
prev = p;
|
||||
p = next;
|
||||
continue;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
rmdir_error (p->file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlink (p->file_name) != 0 && errno != ENOENT)
|
||||
unlink_error (p->file_name);
|
||||
}
|
||||
dunlink_reclaim (p);
|
||||
dunlink_count--;
|
||||
p = next;
|
||||
if (prev)
|
||||
prev->next = p;
|
||||
else
|
||||
dunlink_head = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = p;
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
if (!dunlink_head)
|
||||
dunlink_tail = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
finish_deferred_unlinks ()
|
||||
{
|
||||
flush_deferred_unlinks (true);
|
||||
while (dunlink_avail)
|
||||
{
|
||||
struct deferred_unlink *next = dunlink_avail->next;
|
||||
free (dunlink_avail);
|
||||
dunlink_avail = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
queue_deferred_unlink (const char *name, bool is_dir)
|
||||
{
|
||||
struct deferred_unlink *p;
|
||||
|
||||
if (dunlink_head
|
||||
&& records_written > dunlink_head->records_written + deferred_unlink_delay)
|
||||
flush_deferred_unlinks (false);
|
||||
|
||||
p = dunlink_alloc ();
|
||||
p->next = NULL;
|
||||
p->file_name = normalize_filename (name);
|
||||
p->is_dir = is_dir;
|
||||
p->records_written = records_written;
|
||||
|
||||
if (dunlink_tail)
|
||||
dunlink_tail->next = p;
|
||||
else
|
||||
dunlink_head = p;
|
||||
dunlink_tail = p;
|
||||
dunlink_count++;
|
||||
}
|
||||
46
src/update.c
46
src/update.c
@@ -1,7 +1,7 @@
|
||||
/* Update a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
2004, 2005, 2007, 2010 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
|
||||
@@ -114,7 +114,9 @@ update_archive (void)
|
||||
|
||||
while (!found_end)
|
||||
{
|
||||
enum read_header status = read_header (false);
|
||||
enum read_header status = read_header (¤t_header,
|
||||
¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -137,13 +139,35 @@ update_archive (void)
|
||||
|
||||
chdir_do (name->change_dir);
|
||||
if (deref_stat (dereference_option,
|
||||
current_stat_info.file_name, &s) == 0
|
||||
&& (tar_timespec_cmp (get_stat_mtime (&s),
|
||||
current_stat_info.mtime)
|
||||
<= 0))
|
||||
add_avoided_name (current_stat_info.file_name);
|
||||
current_stat_info.file_name, &s) == 0)
|
||||
{
|
||||
if (S_ISDIR (s.st_mode))
|
||||
{
|
||||
char *p, *dirp;
|
||||
dirp = savedir (name->name);
|
||||
if (!dirp)
|
||||
savedir_error (name->name);
|
||||
else
|
||||
{
|
||||
namebuf_t nbuf = namebuf_create (name->name);
|
||||
|
||||
for (p = dirp; *p; p += strlen (p) + 1)
|
||||
addname (namebuf_name (nbuf, p),
|
||||
0, false, NULL);
|
||||
|
||||
namebuf_free (nbuf);
|
||||
free (dirp);
|
||||
|
||||
remname (name);
|
||||
}
|
||||
}
|
||||
else if (tar_timespec_cmp (get_stat_mtime (&s),
|
||||
current_stat_info.mtime)
|
||||
<= 0)
|
||||
remname (name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
@@ -189,10 +213,10 @@ update_archive (void)
|
||||
output_start = current_block->buffer;
|
||||
|
||||
{
|
||||
char *file_name;
|
||||
|
||||
while ((file_name = name_from_list ()) != NULL)
|
||||
struct name const *p;
|
||||
while ((p = name_from_list ()) != NULL)
|
||||
{
|
||||
char *file_name = p->name;
|
||||
if (excluded_name (file_name))
|
||||
continue;
|
||||
if (interactive_option && !confirm ("add", file_name))
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/* Version info for tar.
|
||||
Copyright (C) 1989, 1992, Free Software Foundation.
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
char version_string[] = "GNU tar version 1.11";
|
||||
98
src/warning.c
Normal file
98
src/warning.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* This file is part of GNU tar.
|
||||
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include <argmatch.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static char const *const warning_args[] = {
|
||||
"all",
|
||||
"alone-zero-block",
|
||||
"bad-dumpdir",
|
||||
"cachedir",
|
||||
"contiguous-cast",
|
||||
"file-changed",
|
||||
"file-ignored",
|
||||
"file-removed",
|
||||
"file-shrank",
|
||||
"file-unchanged",
|
||||
"filename-with-nuls",
|
||||
"ignore-archive",
|
||||
"ignore-newer",
|
||||
"new-directory",
|
||||
"rename-directory",
|
||||
"symlink-cast",
|
||||
"timestamp",
|
||||
"unknown-cast",
|
||||
"unknown-keyword",
|
||||
"xdev",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int warning_types[] = {
|
||||
WARN_ALL,
|
||||
WARN_ALONE_ZERO_BLOCK,
|
||||
WARN_BAD_DUMPDIR,
|
||||
WARN_CACHEDIR,
|
||||
WARN_CONTIGUOUS_CAST,
|
||||
WARN_FILE_CHANGED,
|
||||
WARN_FILE_IGNORED,
|
||||
WARN_FILE_REMOVED,
|
||||
WARN_FILE_SHRANK,
|
||||
WARN_FILE_UNCHANGED,
|
||||
WARN_FILENAME_WITH_NULS,
|
||||
WARN_IGNORE_ARCHIVE,
|
||||
WARN_IGNORE_NEWER,
|
||||
WARN_NEW_DIRECTORY,
|
||||
WARN_RENAME_DIRECTORY,
|
||||
WARN_SYMLINK_CAST,
|
||||
WARN_TIMESTAMP,
|
||||
WARN_UNKNOWN_CAST,
|
||||
WARN_UNKNOWN_KEYWORD,
|
||||
WARN_XDEV
|
||||
};
|
||||
|
||||
ARGMATCH_VERIFY (warning_args, warning_types);
|
||||
|
||||
int warning_option = WARN_ALL;
|
||||
|
||||
void
|
||||
set_warning_option (const char *arg)
|
||||
{
|
||||
int negate = 0;
|
||||
int option;
|
||||
|
||||
if (strcmp (arg, "none") == 0)
|
||||
{
|
||||
warning_option = 0;
|
||||
return;
|
||||
}
|
||||
if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
|
||||
{
|
||||
negate = 1;
|
||||
arg += 3;
|
||||
}
|
||||
|
||||
option = XARGMATCH ("--warning", arg,
|
||||
warning_args, warning_types);
|
||||
if (negate)
|
||||
warning_option &= ~option;
|
||||
else
|
||||
warning_option |= option;
|
||||
}
|
||||
|
||||
156
src/xheader.c
156
src/xheader.c
@@ -1,6 +1,7 @@
|
||||
/* POSIX extended headers for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 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
|
||||
@@ -96,9 +97,15 @@ static struct keyword_list *global_header_override_list;
|
||||
/* Template for the name field of an 'x' type header */
|
||||
static char *exthdr_name;
|
||||
|
||||
static char *exthdr_mtime_option;
|
||||
static time_t exthdr_mtime;
|
||||
|
||||
/* Template for the name field of a 'g' type header */
|
||||
static char *globexthdr_name;
|
||||
|
||||
static char *globexthdr_mtime_option;
|
||||
static time_t globexthdr_mtime;
|
||||
|
||||
bool
|
||||
xheader_keyword_deleted_p (const char *kw)
|
||||
{
|
||||
@@ -156,6 +163,21 @@ xheader_set_single_keyword (char *kw)
|
||||
USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));
|
||||
}
|
||||
|
||||
static void
|
||||
assign_time_option (char **sval, time_t *tval, const char *input)
|
||||
{
|
||||
uintmax_t u;
|
||||
char *p;
|
||||
time_t t = u = strtoumax (input, &p, 10);
|
||||
if (t != u || *p || errno == ERANGE)
|
||||
ERROR ((0, 0, _("Time stamp is out of allowed range")));
|
||||
else
|
||||
{
|
||||
*tval = t;
|
||||
assign_string (sval, input);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xheader_set_keyword_equal (char *kw, char *eq)
|
||||
{
|
||||
@@ -168,12 +190,12 @@ xheader_set_keyword_equal (char *kw, char *eq)
|
||||
global = false;
|
||||
}
|
||||
|
||||
while (p > kw && isspace (*p))
|
||||
while (p > kw && isspace ((unsigned char) *p))
|
||||
p--;
|
||||
|
||||
*p = 0;
|
||||
|
||||
for (p = eq + 1; *p && isspace (*p); p++)
|
||||
for (p = eq + 1; *p && isspace ((unsigned char) *p); p++)
|
||||
;
|
||||
|
||||
if (strcmp (kw, "delete") == 0)
|
||||
@@ -186,6 +208,10 @@ xheader_set_keyword_equal (char *kw, char *eq)
|
||||
assign_string (&exthdr_name, p);
|
||||
else if (strcmp (kw, "globexthdr.name") == 0)
|
||||
assign_string (&globexthdr_name, p);
|
||||
else if (strcmp (kw, "exthdr.mtime") == 0)
|
||||
assign_time_option (&exthdr_mtime_option, &exthdr_mtime, p);
|
||||
else if (strcmp (kw, "globexthdr.mtime") == 0)
|
||||
assign_time_option (&globexthdr_mtime_option, &globexthdr_mtime, p);
|
||||
else
|
||||
{
|
||||
if (xheader_protected_keyword_p (kw))
|
||||
@@ -364,14 +390,26 @@ xheader_ghdr_name (void)
|
||||
}
|
||||
|
||||
void
|
||||
xheader_write (char type, char *name, struct xheader *xhdr)
|
||||
xheader_write (char type, char *name, time_t t, struct xheader *xhdr)
|
||||
{
|
||||
union block *header;
|
||||
size_t size;
|
||||
char *p;
|
||||
|
||||
size = xhdr->size;
|
||||
header = start_private_header (name, size);
|
||||
switch (type)
|
||||
{
|
||||
case XGLTYPE:
|
||||
if (globexthdr_mtime_option)
|
||||
t = globexthdr_mtime;
|
||||
break;
|
||||
|
||||
case XHDTYPE:
|
||||
if (exthdr_mtime_option)
|
||||
t = exthdr_mtime;
|
||||
break;
|
||||
}
|
||||
header = start_private_header (name, size, t);
|
||||
header->header.typeflag = type;
|
||||
|
||||
simple_finish_header (header);
|
||||
@@ -403,30 +441,37 @@ xheader_write (char type, char *name, struct xheader *xhdr)
|
||||
void
|
||||
xheader_write_global (struct xheader *xhdr)
|
||||
{
|
||||
char *name;
|
||||
struct keyword_list *kp;
|
||||
if (keyword_global_override_list)
|
||||
{
|
||||
struct keyword_list *kp;
|
||||
|
||||
if (!keyword_global_override_list)
|
||||
return;
|
||||
|
||||
xheader_init (xhdr);
|
||||
for (kp = keyword_global_override_list; kp; kp = kp->next)
|
||||
code_string (kp->value, kp->pattern, xhdr);
|
||||
xheader_finish (xhdr);
|
||||
xheader_write (XGLTYPE, name = xheader_ghdr_name (), xhdr);
|
||||
free (name);
|
||||
xheader_init (xhdr);
|
||||
for (kp = keyword_global_override_list; kp; kp = kp->next)
|
||||
code_string (kp->value, kp->pattern, xhdr);
|
||||
}
|
||||
if (xhdr->stk)
|
||||
{
|
||||
char *name;
|
||||
|
||||
xheader_finish (xhdr);
|
||||
xheader_write (XGLTYPE, name = xheader_ghdr_name (), time (NULL), xhdr);
|
||||
free (name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* General Interface */
|
||||
|
||||
#define XHDR_PROTECTED 0x01
|
||||
#define XHDR_GLOBAL 0x02
|
||||
|
||||
struct xhdr_tab
|
||||
{
|
||||
char const *keyword;
|
||||
void (*coder) (struct tar_stat_info const *, char const *,
|
||||
struct xheader *, void const *data);
|
||||
void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
|
||||
bool protect;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* This declaration must be extern, because ISO C99 section 6.9.2
|
||||
@@ -454,7 +499,7 @@ xheader_protected_pattern_p (const char *pattern)
|
||||
struct xhdr_tab const *p;
|
||||
|
||||
for (p = xhdr_tab; p->keyword; p++)
|
||||
if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
|
||||
if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -465,7 +510,7 @@ xheader_protected_keyword_p (const char *keyword)
|
||||
struct xhdr_tab const *p;
|
||||
|
||||
for (p = xhdr_tab; p->keyword; p++)
|
||||
if (p->protect && strcmp (p->keyword, keyword) == 0)
|
||||
if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -571,8 +616,9 @@ decx (void *data, char const *keyword, char const *value, size_t size)
|
||||
if (t)
|
||||
t->decoder (st, keyword, value, size);
|
||||
else
|
||||
WARN((0, 0, _("Ignoring unknown extended header keyword `%s'"),
|
||||
keyword));
|
||||
WARNOPT (WARN_UNKNOWN_KEYWORD,
|
||||
(0, 0, _("Ignoring unknown extended header keyword `%s'"),
|
||||
keyword));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -595,7 +641,11 @@ decg (void *data, char const *keyword, char const *value,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
struct keyword_list **kwl = data;
|
||||
xheader_list_append (kwl, keyword, value);
|
||||
struct xhdr_tab const *tab = locate_handler (keyword);
|
||||
if (tab && (tab->flags & XHDR_GLOBAL))
|
||||
tab->decoder (data, keyword, value, size);
|
||||
else
|
||||
xheader_list_append (kwl, keyword, value);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -644,7 +694,6 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
|
||||
{
|
||||
size_t j = 0;
|
||||
|
||||
xheader_init (xhdr);
|
||||
size += BLOCKSIZE;
|
||||
xhdr->size = size;
|
||||
xhdr->buffer = xmalloc (size + 1);
|
||||
@@ -657,6 +706,9 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
|
||||
if (len > BLOCKSIZE)
|
||||
len = BLOCKSIZE;
|
||||
|
||||
if (!p)
|
||||
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
|
||||
|
||||
memcpy (&xhdr->buffer[j], p->buffer, len);
|
||||
set_next_block_after (p);
|
||||
|
||||
@@ -1453,51 +1505,53 @@ sparse_minor_decoder (struct tar_stat_info *st,
|
||||
}
|
||||
|
||||
struct xhdr_tab const xhdr_tab[] = {
|
||||
{ "atime", atime_coder, atime_decoder, false },
|
||||
{ "comment", dummy_coder, dummy_decoder, false },
|
||||
{ "charset", dummy_coder, dummy_decoder, false },
|
||||
{ "ctime", ctime_coder, ctime_decoder, false },
|
||||
{ "gid", gid_coder, gid_decoder, false },
|
||||
{ "gname", gname_coder, gname_decoder, false },
|
||||
{ "linkpath", linkpath_coder, linkpath_decoder, false },
|
||||
{ "mtime", mtime_coder, mtime_decoder, false },
|
||||
{ "path", path_coder, path_decoder, false },
|
||||
{ "size", size_coder, size_decoder, false },
|
||||
{ "uid", uid_coder, uid_decoder, false },
|
||||
{ "uname", uname_coder, uname_decoder, false },
|
||||
{ "atime", atime_coder, atime_decoder, 0 },
|
||||
{ "comment", dummy_coder, dummy_decoder, 0 },
|
||||
{ "charset", dummy_coder, dummy_decoder, 0 },
|
||||
{ "ctime", ctime_coder, ctime_decoder, 0 },
|
||||
{ "gid", gid_coder, gid_decoder, 0 },
|
||||
{ "gname", gname_coder, gname_decoder, 0 },
|
||||
{ "linkpath", linkpath_coder, linkpath_decoder, 0 },
|
||||
{ "mtime", mtime_coder, mtime_decoder, 0 },
|
||||
{ "path", path_coder, path_decoder, 0 },
|
||||
{ "size", size_coder, size_decoder, 0 },
|
||||
{ "uid", uid_coder, uid_decoder, 0 },
|
||||
{ "uname", uname_coder, uname_decoder, 0 },
|
||||
|
||||
/* Sparse file handling */
|
||||
{ "GNU.sparse.name", path_coder, path_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
{ "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
{ "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
{ "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
|
||||
/* tar 1.14 - 1.15.90 keywords. */
|
||||
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
|
||||
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder,
|
||||
XHDR_PROTECTED },
|
||||
/* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
|
||||
headers, and each of them was meaningful. It confilcted with POSIX specs,
|
||||
which requires that "when extended header records conflict, the last one
|
||||
given in the header shall take precedence." */
|
||||
{ "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
/* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
|
||||
{ "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
|
||||
sparse_map_decoder, false },
|
||||
sparse_map_decoder, 0 },
|
||||
|
||||
{ "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
|
||||
true },
|
||||
XHDR_PROTECTED },
|
||||
|
||||
/* Keeps the tape/volume label. May be present only in the global headers.
|
||||
Equivalent to GNUTYPE_VOLHDR. */
|
||||
{ "GNU.volume.label", volume_label_coder, volume_label_decoder, true },
|
||||
{ "GNU.volume.label", volume_label_coder, volume_label_decoder,
|
||||
XHDR_PROTECTED | XHDR_GLOBAL },
|
||||
|
||||
/* These may be present in a first global header of the archive.
|
||||
They provide the same functionality as GNUTYPE_MULTIVOL header.
|
||||
@@ -1506,9 +1560,11 @@ struct xhdr_tab const xhdr_tab[] = {
|
||||
GNU.volume.offset keeps the offset of the start of this volume,
|
||||
otherwise kept in oldgnu_header.offset. */
|
||||
{ "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
|
||||
true },
|
||||
{ "GNU.volume.size", volume_size_coder, volume_size_decoder, true },
|
||||
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true },
|
||||
XHDR_PROTECTED | XHDR_GLOBAL },
|
||||
{ "GNU.volume.size", volume_size_coder, volume_size_decoder,
|
||||
XHDR_PROTECTED | XHDR_GLOBAL },
|
||||
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
|
||||
XHDR_PROTECTED | XHDR_GLOBAL },
|
||||
|
||||
{ NULL, NULL, NULL, false }
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -52,6 +52,7 @@ TESTSUITE_AT = \
|
||||
append.at\
|
||||
append01.at\
|
||||
append02.at\
|
||||
backup01.at\
|
||||
chtype.at\
|
||||
comprec.at\
|
||||
delete01.at\
|
||||
@@ -60,6 +61,11 @@ TESTSUITE_AT = \
|
||||
delete04.at\
|
||||
delete05.at\
|
||||
exclude.at\
|
||||
exclude01.at\
|
||||
exclude02.at\
|
||||
exclude03.at\
|
||||
exclude04.at\
|
||||
exclude05.at\
|
||||
extrac01.at\
|
||||
extrac02.at\
|
||||
extrac03.at\
|
||||
@@ -67,6 +73,9 @@ TESTSUITE_AT = \
|
||||
extrac05.at\
|
||||
extrac06.at\
|
||||
extrac07.at\
|
||||
extrac08.at\
|
||||
filerem01.at\
|
||||
filerem02.at\
|
||||
gzip.at\
|
||||
grow.at\
|
||||
incremental.at\
|
||||
@@ -74,9 +83,15 @@ TESTSUITE_AT = \
|
||||
incr02.at\
|
||||
incr03.at\
|
||||
incr04.at\
|
||||
incr05.at\
|
||||
incr06.at\
|
||||
indexfile.at\
|
||||
ignfail.at\
|
||||
label01.at\
|
||||
label02.at\
|
||||
link01.at\
|
||||
link02.at\
|
||||
link03.at\
|
||||
listed01.at\
|
||||
listed02.at\
|
||||
long01.at\
|
||||
@@ -90,6 +105,7 @@ TESTSUITE_AT = \
|
||||
multiv04.at\
|
||||
multiv05.at\
|
||||
multiv06.at\
|
||||
multiv07.at\
|
||||
old.at\
|
||||
options.at\
|
||||
options02.at\
|
||||
@@ -100,6 +116,8 @@ TESTSUITE_AT = \
|
||||
rename03.at\
|
||||
rename04.at\
|
||||
rename05.at\
|
||||
remfiles01.at\
|
||||
remfiles02.at\
|
||||
same-order01.at\
|
||||
same-order02.at\
|
||||
shortfile.at\
|
||||
@@ -115,10 +133,13 @@ TESTSUITE_AT = \
|
||||
spmvp10.at\
|
||||
truncate.at\
|
||||
update.at\
|
||||
update01.at\
|
||||
update02.at\
|
||||
volsize.at\
|
||||
volume.at\
|
||||
verbose.at\
|
||||
version.at\
|
||||
xform-h.at\
|
||||
star/gtarfail.at\
|
||||
star/gtarfail2.at\
|
||||
star/multi-fail.at\
|
||||
@@ -140,7 +161,7 @@ clean-local:
|
||||
test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
|
||||
|
||||
check-local: atconfig atlocal $(TESTSUITE)
|
||||
$(SHELL) $(TESTSUITE)
|
||||
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS)
|
||||
|
||||
check-full:
|
||||
FULL_TEST=1 $(MAKE) check
|
||||
@@ -149,7 +170,7 @@ check-full:
|
||||
|
||||
# Run the test suite on the *installed* tree.
|
||||
installcheck-local:
|
||||
$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
|
||||
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS) AUTOTEST_PATH=$(exec_prefix)/bin
|
||||
|
||||
|
||||
## ------------ ##
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009 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,13 +26,27 @@
|
||||
# tar rf archive file1
|
||||
# tar rt archive file2
|
||||
#
|
||||
# produced different archives (GNU format is assumed). Namely, in the
|
||||
# second case the mode field of all members, except the first, was truncated
|
||||
# to lower 3 octets (& 0777).
|
||||
# produced different archives (GNU format is assumed). It was reported
|
||||
# by TAMUKI Shoichi on 2006-07-21 [1].
|
||||
#
|
||||
# The bug was due to tar being unable to discern between GNU and OLDGNU
|
||||
# formats and always assuming the latter. The main difference between
|
||||
# the two is that OLDGNU preserves all bits in the mode field, whereas
|
||||
# GNU format keeps only the lower 9 ones (mode & 0777).
|
||||
#
|
||||
# This was fixed on 2006-07-24 (commit f4e4adea80a) by making tar truncate
|
||||
# the mode field even in OLDGNU format. Obviously, the fix broke the
|
||||
# format backward compatibility, but it went unnoticed until 2009-10-03
|
||||
# (after all, the OLDGNU format is not in much use nowadays), when
|
||||
# Igor Zhbanov reported it [2].
|
||||
#
|
||||
# The final fix was applied on 2009-10-04.
|
||||
#
|
||||
# References:
|
||||
# <200607210526.AA03440@tamuki.linet.gr.jp>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2006-07/msg00029.html
|
||||
# [1] <200607210526.AA03440@tamuki.linet.gr.jp>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2006-07/msg00029.html
|
||||
# [2] <f44001920910020335v4cadfesf54f6593d5124814@mail.gmail.com>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-10/msg00006.html
|
||||
|
||||
# The test case below verifies that the equivalent create and append commands
|
||||
# produce binary equivalent archives for all formats.
|
||||
|
||||
49
tests/backup01.at
Normal file
49
tests/backup01.at
Normal file
@@ -0,0 +1,49 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description:
|
||||
# When extracting, tar (<1.22) sometimes renamed a backup back to the
|
||||
# original name (overwriting the newly-extracted file) for no good reason.
|
||||
#
|
||||
# Reported by: Carl Worth <cworth@cworth.org>,
|
||||
# Eric Lammerts <eric@lammerts.org>
|
||||
#
|
||||
# References: <1249419998.4905.84.camel@yoom.home.cworth.org>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-08/msg00005.html
|
||||
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508199
|
||||
#
|
||||
|
||||
AT_SETUP([extracting existing dir with --backup])
|
||||
AT_KEYWORDS([extract backup backup01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir dir1 dir2
|
||||
echo bla > dir1/file1
|
||||
tar cf test.tar dir1 dir2
|
||||
tar xfv test.tar --backup
|
||||
],
|
||||
[0],
|
||||
[dir1/
|
||||
dir1/file1
|
||||
Renaming `dir1/file1' to `dir1/file1~'
|
||||
dir2/
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
69
tests/exclude01.at
Normal file
69
tests/exclude01.at
Normal file
@@ -0,0 +1,69 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([exclude wildcards])
|
||||
AT_KEYWORDS([exclude exclude01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
rm -rf testdir
|
||||
mkdir -p testdir/dir1 testdir/dir2 testdir/dir3
|
||||
touch testdir/dir1/file1
|
||||
touch testdir/dir1/\*
|
||||
touch testdir/dir2/file2
|
||||
touch testdir/dir2/\*
|
||||
touch testdir/dir3/file3
|
||||
touch testdir/dir3/\*
|
||||
|
||||
tar cf archive --exclude=testdir/dir1/\* \
|
||||
--no-wildcards \
|
||||
--exclude=testdir/dir2/\* \
|
||||
--wildcards \
|
||||
--exclude=testdir/dir3/\* \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar cf archive testdir
|
||||
tar t "testdir/dir1/*" -f archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar cf archive testdir/dir1
|
||||
tar t --no-wildcards "testdir/dir1/*" -f archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar cf archive testdir
|
||||
tar t --wildcards "testdir/dir1/*" -f archive | sort
|
||||
|
||||
rm -rf testdir
|
||||
],
|
||||
[0],
|
||||
[testdir/
|
||||
testdir/dir1/
|
||||
testdir/dir2/
|
||||
testdir/dir2/file2
|
||||
testdir/dir3/
|
||||
NEXT
|
||||
testdir/dir1/*
|
||||
NEXT
|
||||
testdir/dir1/*
|
||||
NEXT
|
||||
testdir/dir1/*
|
||||
testdir/dir1/file1
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
77
tests/exclude02.at
Normal file
77
tests/exclude02.at
Normal file
@@ -0,0 +1,77 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([exclude: anchoring])
|
||||
AT_KEYWORDS([exclude exclude02])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
rm -rf testdir
|
||||
mkdir -p testdir
|
||||
touch file1.txt
|
||||
touch testdir/file1.txt
|
||||
touch testdir/file2
|
||||
|
||||
tar cf archive --exclude="file1.txt" \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "SUB 1"
|
||||
tar cf archive --no-anchored \
|
||||
--exclude="file1.txt" \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "SUB 2"
|
||||
tar cf archive --anchored \
|
||||
--exclude="file1.txt" \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "SUB 3"
|
||||
tar cf archive testdir file1.txt
|
||||
tar t "file1.txt" -f archive | sort
|
||||
|
||||
echo "SUB 4"
|
||||
tar t --no-anchored "file1.txt" -f archive | sort
|
||||
|
||||
echo "SUB 5"
|
||||
tar t --anchored "file1.txt" -f archive | sort
|
||||
|
||||
rm -rf testdir file1.txt
|
||||
|
||||
],
|
||||
[0],
|
||||
[testdir/
|
||||
testdir/file2
|
||||
SUB 1
|
||||
testdir/
|
||||
testdir/file2
|
||||
SUB 2
|
||||
testdir/
|
||||
testdir/file1.txt
|
||||
testdir/file2
|
||||
SUB 3
|
||||
file1.txt
|
||||
SUB 4
|
||||
file1.txt
|
||||
testdir/file1.txt
|
||||
SUB 5
|
||||
file1.txt
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
73
tests/exclude03.at
Normal file
73
tests/exclude03.at
Normal file
@@ -0,0 +1,73 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([exclude: wildcards match slash])
|
||||
AT_KEYWORDS([exclude exclude03])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
rm -rf testdir
|
||||
mkdir -p testdir/dir1 testdir/dir2 testdir/dir3
|
||||
touch testdir/\*f\*1
|
||||
touch testdir/dir1/file1
|
||||
touch testdir/dir1/\*
|
||||
touch testdir/dir2/file2
|
||||
touch testdir/dir2/\*
|
||||
touch testdir/dir3/file3
|
||||
touch testdir/dir3/\*
|
||||
|
||||
tar cf archive --exclude='testdir*f*1' \
|
||||
--no-wildcards-match-slash \
|
||||
--exclude='testdir*f*2' \
|
||||
--wildcards-match-slash \
|
||||
--exclude='testdir*f*3' \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar cf archive testdir
|
||||
tar t --wildcards 'testdir/*f*1' -f archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar t --wildcards --no-wildcards-match-slash 'testdir/*f*1' -f archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar t --wildcards --wildcards-match-slash 'testdir/*f*1' -f archive | sort
|
||||
|
||||
rm -rf testdir
|
||||
|
||||
],
|
||||
[0],
|
||||
[testdir/
|
||||
testdir/dir1/
|
||||
testdir/dir1/*
|
||||
testdir/dir2/
|
||||
testdir/dir2/*
|
||||
testdir/dir2/file2
|
||||
testdir/dir3/
|
||||
testdir/dir3/*
|
||||
NEXT
|
||||
testdir/*f*1
|
||||
testdir/dir1/file1
|
||||
NEXT
|
||||
testdir/*f*1
|
||||
NEXT
|
||||
testdir/*f*1
|
||||
testdir/dir1/file1
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
73
tests/exclude04.at
Normal file
73
tests/exclude04.at
Normal file
@@ -0,0 +1,73 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([exclude: case insensitive])
|
||||
AT_KEYWORDS([exclude exclude04])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
rm -rf testdir
|
||||
mkdir -p testdir/dir
|
||||
touch testdir/file1
|
||||
touch testdir/file2
|
||||
touch testdir/file3
|
||||
touch testdir/file4
|
||||
touch testdir/dir/File1
|
||||
touch testdir/dir/File2
|
||||
touch testdir/dir/File3
|
||||
touch testdir/dir/File4
|
||||
|
||||
tar cf archive --exclude=FILE2 \
|
||||
--exclude=file1 \
|
||||
--ignore-case \
|
||||
--exclude=file3 \
|
||||
--no-ignore-case \
|
||||
--exclude=FILE2 \
|
||||
--exclude=file4 \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "SUB 1"
|
||||
tar cf archive testdir
|
||||
tar t --wildcards --wildcards-match-slash '*File2' -f archive | sort
|
||||
|
||||
echo "SUB 2"
|
||||
tar t --wildcards --wildcards-match-slash --ignore-case '*File2' -f archive | sort
|
||||
|
||||
echo "SUB 3"
|
||||
tar t --wildcards --wildcards-match-slash --no-ignore-case '*File2' -f archive | sort
|
||||
|
||||
rm -rf testdir
|
||||
|
||||
],
|
||||
[0],
|
||||
[testdir/
|
||||
testdir/dir/
|
||||
testdir/dir/File1
|
||||
testdir/dir/File2
|
||||
testdir/dir/File4
|
||||
testdir/file2
|
||||
SUB 1
|
||||
testdir/dir/File2
|
||||
SUB 2
|
||||
testdir/dir/File2
|
||||
testdir/file2
|
||||
SUB 3
|
||||
testdir/dir/File2
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
59
tests/exclude05.at
Normal file
59
tests/exclude05.at
Normal file
@@ -0,0 +1,59 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
# Copyright (C) 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test the functioning of many items in an exclude list (should run quickly)
|
||||
|
||||
AT_SETUP([exclude: lots of excludes])
|
||||
AT_KEYWORDS([exclude exclude05])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
rm -rf testdir exclfile
|
||||
mkdir -p testdir
|
||||
awk 'BEGIN {for (i=9; i < 100; ++i ) { print "testdir/file" i; }}' < /dev/null | \
|
||||
while read name
|
||||
do
|
||||
genfile --file $name
|
||||
done
|
||||
|
||||
awk 'BEGIN {for (i=1000000; i >= 12; --i ) { print "testdir/file" i }}' < /dev/null > exclfile
|
||||
|
||||
tar cf archive --anchored --exclude-from=exclfile \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
echo "NEXT"
|
||||
tar cf archive --exclude-from=exclfile \
|
||||
testdir
|
||||
tar tf archive | sort
|
||||
|
||||
rm -rf testdir exclfile
|
||||
|
||||
],
|
||||
[0],
|
||||
[testdir/
|
||||
testdir/file10
|
||||
testdir/file11
|
||||
testdir/file9
|
||||
NEXT
|
||||
testdir/
|
||||
testdir/file10
|
||||
testdir/file11
|
||||
testdir/file9
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -36,10 +36,10 @@ cztery
|
||||
])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile --sparse --file sparsefile 0 ABCD 1M EFGH 2000K IJKL || AT_SKIP_TEST
|
||||
genfile --length 118 --file jeden
|
||||
genfile --length 223 --file dwa
|
||||
genfile --length 517 --file trzy
|
||||
genfile --sparse --file sparsefile 0 ABCD 1M EFGH 2000K IJKL
|
||||
genfile --length 110 --file cztery
|
||||
|
||||
tar cf archive jeden dwa trzy cztery || exit 1
|
||||
|
||||
52
tests/extrac08.at
Normal file
52
tests/extrac08.at
Normal file
@@ -0,0 +1,52 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description:
|
||||
# When extracting, tar (<1.22) did not restore directory permissions on
|
||||
# existing directories.
|
||||
# This was discovered when fixing debian bug #508199. See also backup01.at.
|
||||
#
|
||||
# Reported by: Carl Worth <cworth@cworth.org>,
|
||||
#
|
||||
# References: <1249419998.4905.84.camel@yoom.home.cworth.org>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-08/msg00005.html
|
||||
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508199
|
||||
#
|
||||
|
||||
AT_SETUP([restoring mode on existing directory])
|
||||
AT_KEYWORDS([extract extrac08])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
umask 000
|
||||
mkdir dir
|
||||
chmod 755 dir
|
||||
echo bla > dir/file
|
||||
tar cf test.tar dir
|
||||
chmod 700 dir
|
||||
tar xfv test.tar
|
||||
genfile --stat=mode.777 dir
|
||||
],
|
||||
[0],
|
||||
[dir/
|
||||
dir/file
|
||||
755
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
101
tests/filerem01.at
Normal file
101
tests/filerem01.at
Normal file
@@ -0,0 +1,101 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Description: when a file in a deep directory disappeared during creation
|
||||
# of incremental dump, tar v. <1.23 would exit with TAREXIT_FAILURE (2).
|
||||
# However, such events are quite common and don't necessarily constitute
|
||||
# an error. Exiting with code 2 in such cases makes it impossible to
|
||||
# distinguish serious errors from benign ones.
|
||||
#
|
||||
# Starting from tar 1.22.90, tar exits with TAREXIT_DIFFERS (1)
|
||||
# instead.
|
||||
#
|
||||
# Reported by: Solar Designer <solar@openwall.com>
|
||||
#
|
||||
# References: <20090228235820.GA13362@openwall.com>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-03/msg00000.html
|
||||
#
|
||||
|
||||
AT_SETUP([file removed as we read it (ca. 22 seconds)])
|
||||
AT_KEYWORDS([create incremental filechange filerem filerem01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir dir
|
||||
mkdir dir/sub
|
||||
genfile --file dir/file1
|
||||
genfile --file dir/sub/file2
|
||||
|
||||
genfile --run --checkpoint=3 --unlink dir/file1 -- \
|
||||
tar --blocking-factor=1 --checkpoint=1 --checkpoint-action='sleep=1' \
|
||||
--checkpoint-action='echo' -c -f archive.tar \
|
||||
--listed-incremental db -v dir >/dev/null
|
||||
],
|
||||
[1],
|
||||
[ignore],
|
||||
[tar: dir: Directory is new
|
||||
tar: dir/sub: Directory is new
|
||||
tar: dir/file1: File removed before we read it
|
||||
],[],[],[gnu, posix])
|
||||
|
||||
# Timing information:
|
||||
#
|
||||
# For -Hgnu the above command line takes about 8 seconds to execute and
|
||||
# produces:
|
||||
#
|
||||
# tar: dir: Directory is new
|
||||
# tar: dir/sub: Directory is new
|
||||
# dir/
|
||||
# tar: Write checkpoint 1
|
||||
# tar: Write checkpoint 2
|
||||
# dir/sub/
|
||||
# tar: Write checkpoint 3
|
||||
# tar: Write checkpoint 4
|
||||
# dir/file1
|
||||
# tar: Write checkpoint 5
|
||||
# dir/sub/file2
|
||||
# tar: Write checkpoint 6
|
||||
# tar: Write checkpoint 7
|
||||
# tar: Write checkpoint 8
|
||||
#
|
||||
# For -Hposix the above command line takes about 14 seconds to execute and
|
||||
# produces:
|
||||
#
|
||||
# ./tar: dir: Directory is new
|
||||
# ./tar: dir/sub: Directory is new
|
||||
# dir/
|
||||
# ./tar: Write checkpoint 1
|
||||
# ./tar: Write checkpoint 2
|
||||
# ./tar: Write checkpoint 3
|
||||
# dir/sub/
|
||||
# ./tar: Write checkpoint 4
|
||||
# ./tar: Write checkpoint 5
|
||||
# ./tar: Write checkpoint 6
|
||||
# dir/file1
|
||||
# ./tar: Write checkpoint 7
|
||||
# ./tar: Write checkpoint 8
|
||||
# ./tar: Write checkpoint 9
|
||||
# dir/sub/file2
|
||||
# ./tar: Write checkpoint 10
|
||||
# ./tar: Write checkpoint 11
|
||||
# ./tar: Write checkpoint 12
|
||||
# ./tar: Write checkpoint 13
|
||||
# ./tar: Write checkpoint 14
|
||||
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
50
tests/filerem02.at
Normal file
50
tests/filerem02.at
Normal file
@@ -0,0 +1,50 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Description: see filerem01.at
|
||||
# This test case checks if the tar exit code is still 2 if a
|
||||
# file or directory disappears that is explicitly mentioned
|
||||
# in the command line.
|
||||
|
||||
AT_SETUP([toplevel file removed (ca. 24 seconds)])
|
||||
AT_KEYWORDS([create incremental filechange filerem filerem02])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir dir
|
||||
mkdir dir/sub
|
||||
genfile --file dir/file1
|
||||
genfile --file dir/sub/file2
|
||||
mkdir dir2
|
||||
genfile --file dir2/file1
|
||||
|
||||
genfile --run --checkpoint=3 --exec 'rm -rf dir2' -- \
|
||||
tar --blocking-factor=1 --checkpoint=1 --checkpoint-action='sleep=1' \
|
||||
--checkpoint-action='echo' -c -f archive.tar \
|
||||
--listed-incremental db -v --warning=no-new-dir dir dir2 >/dev/null
|
||||
],
|
||||
[2],
|
||||
[ignore],
|
||||
[tar: dir2: Cannot stat: No such file or directory
|
||||
tar: dir2/file1: File removed before we read it
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],[],[],[gnu, posix])
|
||||
|
||||
# Timing information: see filerem01.at
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -27,8 +27,7 @@ AT_KEYWORDS([grow filechange])
|
||||
AT_TAR_CHECK([
|
||||
genfile --file foo --length 50000k
|
||||
genfile --file baz
|
||||
genfile --run 'tar -vcf bar foo baz' --checkpoint 10 --length 1024 \
|
||||
--append foo
|
||||
genfile --run --checkpoint 10 --length 1024 --append foo -- tar --checkpoint -vcf bar foo baz
|
||||
],
|
||||
[1],
|
||||
[foo
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007, 2009 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
|
||||
@@ -28,14 +28,13 @@ unset TAR_OPTIONS
|
||||
AT_CHECK([
|
||||
AT_GZIP_PREREQ
|
||||
tar xfvz /dev/null
|
||||
test $? = 2 || exit 1
|
||||
],
|
||||
[0],
|
||||
[2],
|
||||
[],
|
||||
[
|
||||
gzip: stdin: unexpected end of file
|
||||
tar: Child returned status 1
|
||||
tar: Exiting with failure status due to previous errors
|
||||
tar: Error is not recoverable: exiting now
|
||||
],
|
||||
[],[])
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009 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
|
||||
@@ -39,6 +39,7 @@ sleep 1
|
||||
tar -cf archive.1 -g db directory
|
||||
|
||||
mv directory/x directory/z
|
||||
cp db db.old
|
||||
tar -cf archive.2 -g db directory
|
||||
|
||||
mv directory orig
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009 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
|
||||
@@ -56,7 +56,8 @@ Incremental dump
|
||||
a/
|
||||
a/c/
|
||||
],
|
||||
[tar: a/b: Directory is new
|
||||
[tar: a: Directory is new
|
||||
tar: a/b: Directory is new
|
||||
tar: a/c: Directory has been renamed from `a/b'
|
||||
],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
|
||||
47
tests/incr05.at
Normal file
47
tests/incr05.at
Normal file
@@ -0,0 +1,47 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([incremental dumps with -C])
|
||||
AT_KEYWORDS([incremental incr05])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir dir
|
||||
mkdir dir/sub
|
||||
genfile --file dir/file1
|
||||
genfile --file dir/sub/file2
|
||||
|
||||
echo Level 0
|
||||
tar -c -f archive.tar -g db -C dir -v --warning=no-new-dir .
|
||||
|
||||
genfile --file dir/file3
|
||||
echo Level 1
|
||||
tar -c -f archive.tar -g db -C dir -v --warning=no-new-dir .
|
||||
],
|
||||
[0],
|
||||
[Level 0
|
||||
./
|
||||
./sub/
|
||||
./file1
|
||||
./sub/file2
|
||||
Level 1
|
||||
./
|
||||
./sub/
|
||||
./file3
|
||||
],[],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
AT_CLEANUP
|
||||
79
tests/incr06.at
Normal file
79
tests/incr06.at
Normal file
@@ -0,0 +1,79 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([incremental dumps of nested directories])
|
||||
AT_KEYWORDS([incremental incr06])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir dir
|
||||
mkdir dir/sub
|
||||
mkdir dir/sub/a
|
||||
mkdir dir/sub/b
|
||||
genfile --file dir/file1
|
||||
genfile --file dir/sub/file2
|
||||
genfile --file dir/sub/a/file3
|
||||
|
||||
echo Level 0 . sub
|
||||
tar -c -f archive-0.1.tar -g db.1 -C dir -v --warning=no-new-dir . sub
|
||||
echo Level 0 sub .
|
||||
tar -c -f archive-0.2.tar -g db.2 -C dir -v --warning=no-new-dir sub .
|
||||
|
||||
mkdir dir/c
|
||||
genfile --file dir/sub/b/file4
|
||||
|
||||
echo Level 1 . sub
|
||||
tar -c -f archive-1.1.tar -g db.1 -C dir -v --warning=no-new-dir . sub
|
||||
echo Level 1 sub .
|
||||
tar -c -f archive-1.2.tar -g db.2 -C dir -v --warning=no-new-dir sub .
|
||||
],
|
||||
[0],
|
||||
[Level 0 . sub
|
||||
./
|
||||
sub/
|
||||
sub/a/
|
||||
sub/b/
|
||||
./file1
|
||||
sub/file2
|
||||
sub/a/file3
|
||||
Level 0 sub .
|
||||
./
|
||||
sub/
|
||||
sub/a/
|
||||
sub/b/
|
||||
./file1
|
||||
sub/file2
|
||||
sub/a/file3
|
||||
Level 1 . sub
|
||||
./
|
||||
./c/
|
||||
sub/
|
||||
sub/a/
|
||||
sub/b/
|
||||
sub/b/file4
|
||||
Level 1 sub .
|
||||
./
|
||||
./c/
|
||||
sub/
|
||||
sub/a/
|
||||
sub/b/
|
||||
sub/b/file4
|
||||
],[],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
35
tests/label01.at
Normal file
35
tests/label01.at
Normal file
@@ -0,0 +1,35 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([single-volume label])
|
||||
AT_KEYWORDS([label label01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile --file foo
|
||||
genfile --file bar
|
||||
tar -cf archive --label=Test foo bar
|
||||
tar tf archive
|
||||
],
|
||||
[0],
|
||||
[Test
|
||||
foo
|
||||
bar
|
||||
],
|
||||
[],[],[],[gnu,oldgnu,posix])
|
||||
|
||||
AT_CLEANUP
|
||||
38
tests/label02.at
Normal file
38
tests/label02.at
Normal file
@@ -0,0 +1,38 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AT_SETUP([multi-volume label])
|
||||
AT_KEYWORDS([label label02 multi-label multivolume multiv])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
exec <&-
|
||||
genfile --length 0 --file foo
|
||||
genfile --length 12288 --file bar
|
||||
genfile --length 12288 --file baz
|
||||
tar --label=Test -cM -L10 -f 1.tar -f 2.tar -f 3.tar -f 4.tar foo bar baz
|
||||
tar -Mt -f 1.tar -f 2.tar -f 3.tar -f 4.tar
|
||||
],
|
||||
[0],
|
||||
[Test Volume 1
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
],
|
||||
[],[],[],[gnu,oldgnu,posix])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -31,7 +31,7 @@
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2004-07/msg00009.html
|
||||
|
||||
AT_SETUP([link count gt 2])
|
||||
AT_KEYWORDS([link01])
|
||||
AT_KEYWORDS([hardlinks link01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir directory
|
||||
|
||||
52
tests/link02.at
Normal file
52
tests/link02.at
Normal file
@@ -0,0 +1,52 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Tar 1.22 failed to recognize last hard link when creating an archive with
|
||||
# the --remove-files option.
|
||||
#
|
||||
# Reported by: "Theodore Y. Ts'o" <tytso@mit.edu>,
|
||||
# Carl Worth <cworth@cworth.org>
|
||||
# References:
|
||||
# <E194EAe-0001lE-00@think.thunk.org>
|
||||
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=188663
|
||||
# <1248955024.1545.1.camel@yoom.home.cworth.org>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-07/msg00015.html
|
||||
|
||||
AT_SETUP([preserve hard links with --remove-files])
|
||||
AT_KEYWORDS([hardlinks link02])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile -l 64 -f file1
|
||||
link file1 file2
|
||||
link file2 file3
|
||||
link file3 file4
|
||||
tar -c -f archive --remove-files file1 file2 file3 file4
|
||||
tar tfv archive | sed -n 's/.*file[[2-4]] link to //p'
|
||||
],
|
||||
[0],
|
||||
[file1
|
||||
file1
|
||||
file1
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
# End of link02.at
|
||||
|
||||
56
tests/link03.at
Normal file
56
tests/link03.at
Normal file
@@ -0,0 +1,56 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Make sure -l option works correctly in conjunction with --remove-files
|
||||
# See also link02.at
|
||||
|
||||
AT_SETUP([working -l with --remove-files])
|
||||
AT_KEYWORDS([hardlinks link03])
|
||||
|
||||
m4_define([create_files],[
|
||||
genfile -l 64 -f file1
|
||||
link file1 file2
|
||||
link file2 file3
|
||||
link file3 file4
|
||||
])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
create_files
|
||||
echo archive.1
|
||||
tar -c -f archive.1 -l --remove-files file1 file2 file3 file4
|
||||
create_files
|
||||
echo archive.2
|
||||
tar -c -f archive.2 -l --remove-files file1 file2 file3
|
||||
echo testing archive.2
|
||||
tar tfv archive.2 | sed -n 's/.*file[[2-3]] link to //p'
|
||||
],
|
||||
[0],
|
||||
[archive.1
|
||||
archive.2
|
||||
testing archive.2
|
||||
file1
|
||||
file1
|
||||
],
|
||||
[tar: Missing links to `file1'.
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007, 2009 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
|
||||
@@ -44,7 +44,7 @@ sleep 2
|
||||
genfile --length 10240 --pattern zeros --file directory/file2
|
||||
|
||||
echo "separator"
|
||||
|
||||
cp listing listing.old
|
||||
tar --create \
|
||||
--file=archive.2 \
|
||||
--listed-incremental=listing \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007, 2009 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
|
||||
@@ -47,6 +47,7 @@ done
|
||||
|
||||
sleep 1
|
||||
echo Creating main archive
|
||||
echo >&2 "Creating main archive"
|
||||
tar -c -v --listed-incremental=tart.incr1 -f archive.1 tart 2> err || exit 1
|
||||
|
||||
# The above prints two lines to stderr announcing the new directories c0 and c1.
|
||||
@@ -66,6 +67,7 @@ find tart -print | sort 2>/dev/null
|
||||
|
||||
sleep 1
|
||||
echo Creating incremental archive
|
||||
echo >&2 "Creating incremental archive"
|
||||
cp -p tart.incr1 tart.incr2
|
||||
tar -c -v --listed-incremental=tart.incr2 -f archive.2 tart || exit 1
|
||||
|
||||
@@ -73,6 +75,7 @@ sleep 1
|
||||
|
||||
rm -rf tart/*
|
||||
echo Extracting main archive
|
||||
echo >&2 "Extracting main archive"
|
||||
tar -x -v --listed-incremental=tart.incr1 -f archive.1 || exit 1
|
||||
echo Extracting incremental archive
|
||||
# This command should produce three messages about deletion
|
||||
@@ -141,9 +144,13 @@ tart/c2/ca1
|
||||
tart/c2/ca2
|
||||
tart/c2/ca3
|
||||
],
|
||||
[tar: tart/c0: Directory is new
|
||||
[Creating main archive
|
||||
tar: tart/c0: Directory is new
|
||||
tar: tart/c1: Directory is new
|
||||
tar: tart: Directory is new
|
||||
Creating incremental archive
|
||||
tar: tart/c2: Directory has been renamed from `tart/c1'
|
||||
Extracting main archive
|
||||
],
|
||||
[],[],[gnu, oldgnu])
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007, 2009 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
|
||||
@@ -46,7 +46,6 @@ else
|
||||
fi
|
||||
|
||||
tar -c --multi-volume --tape-length=$TAPE_LENGTH \
|
||||
--listed-incremental=t.snar \
|
||||
-f t1-pipe.tar -f t2-pipe.tar ./file1 ./file2 || exit 1
|
||||
|
||||
mkdir extract-dir-pipe
|
||||
|
||||
43
tests/multiv07.at
Normal file
43
tests/multiv07.at
Normal file
@@ -0,0 +1,43 @@
|
||||
# Test suite for GNU tar. -*- Autotest -*-
|
||||
# Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Description: When creating POSIX multivolume archives, tar may in
|
||||
# some cases write an extended header at the end of one volume, and
|
||||
# the corresponding ustar header at the beginning of the next volume.
|
||||
# Such archives do not fully comply with the POSIX specs, but tar must
|
||||
# be able to read them anyway. This is what this script tests.
|
||||
#
|
||||
# See function try_new_volume, in file src/buffer.c near line 1227
|
||||
# for additional details.
|
||||
|
||||
AT_SETUP([volumes split at an extended header])
|
||||
AT_KEYWORDS([multivolume multiv multiv07 xsplit])
|
||||
|
||||
AT_CHECK([
|
||||
AT_XFAIL_IF(test -f $[]XFAILFILE)
|
||||
AT_TARBALL_PREREQ([xsplit-1.tar],[0e008c84c517e48fbf23ca6a7033cde6])
|
||||
AT_TARBALL_PREREQ([xsplit-2.tar],[03150b9852d285458f43734e9e0b9a45])
|
||||
|
||||
cd $TEST_DATA_DIR
|
||||
tar -t -M -fxsplit-1.tar -fxsplit-2.tar
|
||||
],
|
||||
[0],
|
||||
[Archive volumes split at an extended header Volume 1
|
||||
foo
|
||||
bar
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,7 +1,8 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007, 2008,
|
||||
# 2009 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
|
||||
@@ -30,16 +31,15 @@ AT_SETUP([decompressing from stdin])
|
||||
|
||||
AT_KEYWORDS([pipe])
|
||||
|
||||
AT_TAR_WITH_HOOK([TAR_IGNREC_HOOK],
|
||||
[AT_TAR_CHECK([
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
mkdir directory
|
||||
genfile --length 10240 --pattern zeros --file directory/file1
|
||||
genfile --length 13 --file directory/file2
|
||||
tar cf archive directory|sort
|
||||
tar cf archive directory
|
||||
mv directory orig
|
||||
cat archive | tar xfv - | sort
|
||||
cat archive | tar xfv - | sort
|
||||
echo "separator"
|
||||
cmp orig/file1 directory/file1
|
||||
echo "separator"
|
||||
@@ -50,7 +50,6 @@ directory/file1
|
||||
directory/file2
|
||||
separator
|
||||
separator
|
||||
],
|
||||
[stderr])])
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
66
tests/remfiles01.at
Normal file
66
tests/remfiles01.at
Normal file
@@ -0,0 +1,66 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: When called with --create --remove-files and a compression
|
||||
# options tar (v. <= 1.22.90) would remove files even if it had failed
|
||||
# to store them in the archive.
|
||||
#
|
||||
# References: <77cb99c00910020940k6ce15da4wb564d2418ec52cfb@mail.gmail.com>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-10/msg00005.html
|
||||
|
||||
AT_SETUP([remove-files with compression])
|
||||
AT_KEYWORDS([create remove-files remfiles01 gzip])
|
||||
|
||||
unset TAR_OPTIONS
|
||||
AT_CHECK([
|
||||
AT_GZIP_PREREQ
|
||||
AT_SORT_PREREQ
|
||||
|
||||
mkdir dir
|
||||
cd dir
|
||||
genfile --file a --length 0
|
||||
chmod 0 a
|
||||
genfile --file b
|
||||
mkdir c
|
||||
|
||||
# Depending on when the SIGPIPE gets delivered, the invocation below
|
||||
# may finish with either
|
||||
# tar: a: Cannot write: Broken pipe
|
||||
# or
|
||||
# tar: Child returned status 2
|
||||
|
||||
tar -c -f a -z --remove-files b c 2>err
|
||||
EC=$?
|
||||
sed -n '/(child)/p' err >&2
|
||||
rm err
|
||||
find . | sort
|
||||
exit $EC
|
||||
],
|
||||
[2],
|
||||
[.
|
||||
./a
|
||||
./b
|
||||
./c
|
||||
],
|
||||
[tar (child): a: Cannot open: Permission denied
|
||||
tar (child): Error is not recoverable: exiting now
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
59
tests/remfiles02.at
Normal file
59
tests/remfiles02.at
Normal file
@@ -0,0 +1,59 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: When called with --create --remove-files and a compression
|
||||
# options tar (v. <= 1.22.90) would remove files even if it had failed
|
||||
# to store them in the archive.
|
||||
#
|
||||
# References: <77cb99c00910020940k6ce15da4wb564d2418ec52cfb@mail.gmail.com>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-10/msg00005.html
|
||||
|
||||
AT_SETUP([remove-files with compression: grand-child])
|
||||
AT_KEYWORDS([create remove-files remfiles02 gzip])
|
||||
|
||||
unset TAR_OPTIONS
|
||||
AT_CHECK([
|
||||
AT_GZIP_PREREQ
|
||||
AT_SORT_PREREQ
|
||||
|
||||
mkdir dir
|
||||
cd dir
|
||||
mkdir a
|
||||
genfile --file b
|
||||
mkdir c
|
||||
|
||||
tar -c -f a -z --remove-files b c 2>err
|
||||
EC=$?
|
||||
sed -n '/(child)/p' err >&2
|
||||
rm err
|
||||
find . | sort
|
||||
exit $EC
|
||||
],
|
||||
[2],
|
||||
[.
|
||||
./a
|
||||
./b
|
||||
./c
|
||||
],
|
||||
[tar (child): a: Cannot open: Is a directory
|
||||
tar (child): Error is not recoverable: exiting now
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009 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
|
||||
@@ -79,7 +79,8 @@ foo/file1
|
||||
foo/file2
|
||||
End directory listing 2
|
||||
],
|
||||
[tar: foo/bar: Directory is new
|
||||
[tar: foo: Directory is new
|
||||
tar: foo/bar: Directory is new
|
||||
tar: foo/baz: Directory has been renamed from `foo/bar'
|
||||
],
|
||||
[],[],[gnu, oldgnu, posix])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009 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
|
||||
@@ -93,7 +93,8 @@ foo/file1
|
||||
foo/file2
|
||||
End directory listing 2
|
||||
],
|
||||
[tar: foo/bar: Directory is new
|
||||
[tar: foo: Directory is new
|
||||
tar: foo/bar: Directory is new
|
||||
tar: foo/bar/baz: Directory is new
|
||||
tar: foo/baz: Directory has been renamed from `foo/bar/baz'
|
||||
],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009 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
|
||||
@@ -116,6 +116,7 @@ End directory listing 2
|
||||
tar: foo/a: Directory is new
|
||||
tar: foo/b: Directory is new
|
||||
tar: foo/c: Directory is new
|
||||
tar: foo: Directory is new
|
||||
Second dump
|
||||
tar: foo/a: Directory has been renamed from `foo/c'
|
||||
tar: foo/b: Directory has been renamed from `foo/a'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2005, 2007, 2008, 2009 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
|
||||
@@ -25,20 +25,15 @@
|
||||
AT_SETUP([short records])
|
||||
AT_KEYWORDS([shortrec])
|
||||
|
||||
AT_TAR_WITH_HOOK([TAR_IGNREC_HOOK],
|
||||
[AT_TAR_CHECK([
|
||||
AT_TAR_CHECK([
|
||||
mkdir directory
|
||||
(cd directory && touch a b c d e f g h i j k l m n o p q r)
|
||||
tar -c -b 1 -f - directory | tar -t -f -
|
||||
tar -c -b 1 -f - directory | tar -t -f - > /dev/null
|
||||
tar -c -b 1 -f archive directory
|
||||
tar -t -f archive
|
||||
tar -t -f - < archive
|
||||
tar -t -f archive > /dev/null
|
||||
tar -t -f - < archive > /dev/null
|
||||
|
||||
rm -r directory
|
||||
],
|
||||
[0],
|
||||
[ignore],
|
||||
[stderr])
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2005, 2006, 2007, 2008, 2009 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
|
||||
@@ -56,7 +56,5 @@ Test archive
|
||||
sparsefile
|
||||
Compare archive
|
||||
],
|
||||
[tar: Record size = 12 blocks
|
||||
tar: Record size = 12 blocks
|
||||
],[],[],[pax])])
|
||||
[],[],[],[pax])])
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ m4_define([AT_TARBALL_PREREQ],[
|
||||
test -z "$[]TEST_DATA_DIR" && AT_SKIP_TEST
|
||||
tarball_prereq $1 $2 $[]TEST_DATA_DIR $[]TEST_DATA_URL || AT_SKIP_TEST])
|
||||
|
||||
dnl AT_TARBALL_PREREQ(tarball, md5sum) - Same for star testfiles
|
||||
dnl AT_STAR_PREREQ(tarball, md5sum) - Same for star testfiles
|
||||
m4_define([AT_STAR_PREREQ],[
|
||||
test -z "$STAR_TESTSCRIPTS" && AT_SKIP_TEST
|
||||
tarball_prereq $1 $2 $[]STAR_TESTSCRIPTS $[]STAR_DATA_URL || AT_SKIP_TEST
|
||||
@@ -122,7 +122,14 @@ m4_include([append.at])
|
||||
m4_include([append01.at])
|
||||
m4_include([append02.at])
|
||||
|
||||
m4_include([xform-h.at])
|
||||
|
||||
m4_include([exclude.at])
|
||||
m4_include([exclude01.at])
|
||||
m4_include([exclude02.at])
|
||||
m4_include([exclude03.at])
|
||||
m4_include([exclude04.at])
|
||||
m4_include([exclude05.at])
|
||||
|
||||
m4_include([delete01.at])
|
||||
m4_include([delete02.at])
|
||||
@@ -137,6 +144,12 @@ m4_include([extrac04.at])
|
||||
m4_include([extrac05.at])
|
||||
m4_include([extrac06.at])
|
||||
m4_include([extrac07.at])
|
||||
m4_include([extrac08.at])
|
||||
|
||||
m4_include([label01.at])
|
||||
m4_include([label02.at])
|
||||
|
||||
m4_include([backup01.at])
|
||||
|
||||
m4_include([gzip.at])
|
||||
|
||||
@@ -147,6 +160,12 @@ m4_include([listed01.at])
|
||||
m4_include([listed02.at])
|
||||
m4_include([incr03.at])
|
||||
m4_include([incr04.at])
|
||||
m4_include([incr05.at])
|
||||
m4_include([incr06.at])
|
||||
|
||||
m4_include([filerem01.at])
|
||||
m4_include([filerem02.at])
|
||||
|
||||
m4_include([rename01.at])
|
||||
m4_include([rename02.at])
|
||||
m4_include([rename03.at])
|
||||
@@ -157,6 +176,8 @@ m4_include([chtype.at])
|
||||
m4_include([ignfail.at])
|
||||
|
||||
m4_include([link01.at])
|
||||
m4_include([link02.at])
|
||||
m4_include([link03.at])
|
||||
|
||||
m4_include([longv7.at])
|
||||
m4_include([long01.at])
|
||||
@@ -170,6 +191,7 @@ m4_include([multiv03.at])
|
||||
m4_include([multiv04.at])
|
||||
m4_include([multiv05.at])
|
||||
m4_include([multiv06.at])
|
||||
m4_include([multiv07.at])
|
||||
|
||||
m4_include([old.at])
|
||||
|
||||
@@ -189,6 +211,8 @@ m4_include([spmvp01.at])
|
||||
m4_include([spmvp10.at])
|
||||
|
||||
m4_include([update.at])
|
||||
m4_include([update01.at])
|
||||
m4_include([update02.at])
|
||||
|
||||
m4_include([volume.at])
|
||||
m4_include([volsize.at])
|
||||
@@ -200,6 +224,9 @@ m4_include([shortupd.at])
|
||||
m4_include([truncate.at])
|
||||
m4_include([grow.at])
|
||||
|
||||
m4_include([remfiles01.at])
|
||||
m4_include([remfiles02.at])
|
||||
|
||||
m4_include([star/gtarfail.at])
|
||||
m4_include([star/gtarfail2.at])
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ AT_KEYWORDS([truncate filechange])
|
||||
AT_TAR_CHECK([
|
||||
genfile --file foo --length 50000k
|
||||
genfile --file baz
|
||||
genfile --run 'tar -vcf bar foo baz' --checkpoint 10 --length 49995k --truncate foo
|
||||
genfile --run --checkpoint 10 --length 49995k --truncate foo -- tar --checkpoint -vcf bar foo baz
|
||||
echo Exit status: $?
|
||||
echo separator
|
||||
sleep 1
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
# References: <42AB0D28.6030706@mein-horde.de>
|
||||
# by Martin Lohmeier <martin@mein-horde.de>
|
||||
# on Sat, 11 Jun 2005 18:11:20 +0200
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2005-06/msg00024.html
|
||||
|
||||
AT_SETUP([update unchanged directories])
|
||||
AT_KEYWORDS([update])
|
||||
AT_KEYWORDS([update update00])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
58
tests/update01.at
Normal file
58
tests/update01.at
Normal file
@@ -0,0 +1,58 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: If dir is a directory and arc is a tar archive which
|
||||
# contains that directory, and dir contains some modifications added
|
||||
# after adding it to the archive, then `tar -u dir' would add dir/ to
|
||||
# the archive.
|
||||
# Last-Affected-Version: 1.22.90
|
||||
# References: <4AD4E703.80500@teclabs.eu>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-10/msg00017.html
|
||||
|
||||
AT_SETUP([update directories])
|
||||
AT_KEYWORDS([update update01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
mkdir a
|
||||
genfile --file a/b
|
||||
|
||||
tar cf arc a
|
||||
|
||||
echo "separator"
|
||||
|
||||
sleep 2
|
||||
genfile --file a/c
|
||||
|
||||
tar ufv arc a
|
||||
echo "separator"
|
||||
tar tf arc | sort || exit 1
|
||||
],
|
||||
[0],
|
||||
[separator
|
||||
a/c
|
||||
separator
|
||||
a/
|
||||
a/b
|
||||
a/c
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
55
tests/update02.at
Normal file
55
tests/update02.at
Normal file
@@ -0,0 +1,55 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: See update01.at
|
||||
# Last-Affected-Version: 1.22.90
|
||||
# References: <4AD4E703.80500@teclabs.eu>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-10/msg00017.html
|
||||
|
||||
AT_SETUP([update changed files])
|
||||
AT_KEYWORDS([update update02])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
mkdir a
|
||||
genfile --file a/b
|
||||
|
||||
tar cf arc a
|
||||
|
||||
echo "separator"
|
||||
|
||||
sleep 2
|
||||
touch a/b
|
||||
|
||||
tar ufv arc a
|
||||
echo "separator"
|
||||
tar tf arc | sort || exit 1
|
||||
],
|
||||
[0],
|
||||
[separator
|
||||
a/b
|
||||
separator
|
||||
a/
|
||||
a/b
|
||||
a/b
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2008, 2009 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
|
||||
@@ -52,9 +52,7 @@ Extracted directory
|
||||
abc
|
||||
abc/CCC
|
||||
],
|
||||
[tar: Record size = 5 blocks
|
||||
tar: Record size = 5 blocks
|
||||
])
|
||||
[])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
59
tests/xform-h.at
Normal file
59
tests/xform-h.at
Normal file
@@ -0,0 +1,59 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# When creating archives, tar 1.22 did not apply the --transform option
|
||||
# to hard links.
|
||||
#
|
||||
# Reported by: Jose Miguel Goncalves <jose.goncalves@inov.pt>
|
||||
# References:
|
||||
# <4A436D1D.4040408@inov.pt>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2009-06/msg00017.html
|
||||
#
|
||||
|
||||
AT_SETUP([transforming hard links on create])
|
||||
AT_KEYWORDS([transform xform xform-h])
|
||||
|
||||
m4_define([xform],[
|
||||
echo "$1"
|
||||
tar cf archive --transform="s,^basedir/,,$2" basedir/test basedir/test_link
|
||||
tar tvf archive | sed -n 's/.*test_link link to //p'
|
||||
])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir basedir
|
||||
echo "hello" > basedir/test
|
||||
ln basedir/test basedir/test_link
|
||||
|
||||
xform(Default transform scope)
|
||||
xform(Transforming hard links,h)
|
||||
xform(Not transforming hard links,H)
|
||||
],
|
||||
[0],
|
||||
[Default transform scope
|
||||
test
|
||||
Transforming hard links
|
||||
test
|
||||
Not transforming hard links
|
||||
basedir/test
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
# End of xform-h.at
|
||||
Reference in New Issue
Block a user