Compare commits
2 Commits
release_1_
...
new
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8225f274ff | ||
|
|
e439c9fe36 |
17
.cvsignore
17
.cvsignore
@@ -1,17 +0,0 @@
|
||||
*.bz2
|
||||
*.gz
|
||||
*.tar
|
||||
.bootstrap
|
||||
ABOUT-NLS
|
||||
COPYING
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
config.*
|
||||
configure
|
||||
gnulib
|
||||
rmt
|
||||
stamp-h1
|
||||
6
AUTHORS
6
AUTHORS
@@ -3,12 +3,6 @@ Authors of GNU tar.
|
||||
The following contributions warranted legal paper exchanges with the
|
||||
Free Software Foundation. Also see files ChangeLog and THANKS.
|
||||
|
||||
TAR Sergey Poznyakoff 2003-10
|
||||
Assigns his past and future changes.
|
||||
|
||||
TAR Paul Eggert 2000-10
|
||||
Assigns his past and future changes.
|
||||
|
||||
TAR Jay Fenlason
|
||||
Assigns his changes.
|
||||
|
||||
|
||||
854
ChangeLog.1
854
ChangeLog.1
File diff suppressed because it is too large
Load Diff
75
Makefile.am
75
Makefile.am
@@ -1,31 +1,60 @@
|
||||
# Main Makefile for GNU tar.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 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 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
AUTOMAKE_OPTIONS = gnits dist-shar
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
EXTRA_DIST = ChangeLog.1 PORTS
|
||||
SUBDIRS = doc lib rmt src scripts po tests
|
||||
BABYL = rmail/* admin/*/RMAIL
|
||||
EXTRA_DIST = AC-PATCHES AM-PATCHES BI-PATCHES PORTS rebox.el
|
||||
SUBDIRS = doc lib intl src scripts po tests
|
||||
|
||||
dist-hook:
|
||||
-rm -f $(distdir).cpio
|
||||
find $(distdir) | cpio -Hcrc -o | \
|
||||
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
|
||||
all-local: $(CONFIG_HEADER)
|
||||
|
||||
distclean-local:
|
||||
-rm -f $(PACKAGE)-$(VERSION).cpio.gz
|
||||
id: ID
|
||||
|
||||
ID:
|
||||
cd lib && $(MAKE) $@
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
dist-zoo: $(DISTFILES)
|
||||
rm -rf $(distdir)
|
||||
mkdir $(distdir)
|
||||
distdir=`cd $(distdir) && pwd` \
|
||||
&& cd $(srcdir) \
|
||||
&& automake --include-deps --output-dir=$$distdir
|
||||
@for file in $(DISTFILES); do \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $(srcdir)/$$file $(distdir)/$$file; \
|
||||
done
|
||||
for subdir in $(SUBDIRS); do \
|
||||
test -d $(distdir)/$$subdir \
|
||||
|| mkdir $(distdir)/$$subdir \
|
||||
|| exit 1; \
|
||||
chmod 777 $(distdir)/$$subdir; \
|
||||
(cd $$subdir && $(MAKE) dist) || exit 1; \
|
||||
done
|
||||
@sublist="$(DIST_SUBDIRS)"; \
|
||||
for dir in $$sublist; do \
|
||||
echo copying directory $$dir; \
|
||||
tar -chf - $$dir | (cd $(distdir) && tar -xBpf -); \
|
||||
done
|
||||
chmod -R a+r $(distdir)
|
||||
find $(distdir) -type f | xargs dosfn
|
||||
# find $(distdir) -type f | xargs recode :ibmpc
|
||||
mv $(distdir) $(PACKAGE)
|
||||
find $(PACKAGE) -type f | zoo ahIq $(PACKAGE).zoo
|
||||
rm -rf $(PACKAGE)
|
||||
|
||||
410
NEWS
410
NEWS
@@ -1,373 +1,26 @@
|
||||
GNU tar NEWS - User visible changes.
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
version 1.16 - Sergey Poznyakoff, 2006-10-21
|
||||
|
||||
* After creating an archive, tar exits with code 1 if some files were
|
||||
changed while being read. Previous versions exited with code 2 (fatal
|
||||
error), and only if some files were truncated while being archived.
|
||||
|
||||
* New option --mtime allows to set modification times for all archive
|
||||
members during creation.
|
||||
|
||||
* Bug fixes
|
||||
** Avoid running off file descriptors when using multiple -C options.
|
||||
** tar --index-file=FILE --file=- sent the archive to FILE, and
|
||||
the listing to stderr.
|
||||
|
||||
|
||||
version 1.15.91 - Sergey Poznyakoff, 2006-06-16
|
||||
|
||||
* Incompatible changes
|
||||
|
||||
** Globbing
|
||||
|
||||
Previous versions of GNU tar assumed shell-style globbing when
|
||||
extracting from or listing an archive. For example:
|
||||
|
||||
tar xf foo.tar '*.c'
|
||||
|
||||
would extract all files whose names end in '.c'. This behavior
|
||||
was not documented and was incompatible with traditional tar
|
||||
implementations. Therefore, starting from this version, GNU tar
|
||||
no longer uses globbing by default. For example, the above invocation
|
||||
is now interpreted as a request to extract from the archive the file
|
||||
named '*.c'.
|
||||
|
||||
To treat member names as globbing patterns, use --wildcards option.
|
||||
If you wish tar to mimic the behavior of versions up to 1.15.90,
|
||||
add --wildcards to the value of the environment variable TAR_OPTIONS.
|
||||
|
||||
The exact way in which tar interprets member names is controlled by the
|
||||
following command line options:
|
||||
|
||||
--wildcards use wildcards
|
||||
--anchored patterns match file name start
|
||||
--ignore-case ignore case
|
||||
--wildcards-match-slash wildcards match `/'
|
||||
|
||||
Each of these options has a '--no-' counterpart that disables its
|
||||
effect (e.g. --no-wildcards).
|
||||
|
||||
These options affect both the interpretation of member names from
|
||||
command line and that of the exclusion patterns (given with --exclude
|
||||
and --exclude-from options). The defaults are:
|
||||
|
||||
1. For member names: --no-wildcards --anchored
|
||||
2. For exclusion patterns: --wildcards --no-anchored --wildcards-match-slash
|
||||
|
||||
The options can appear multiple times in the command line, thereby
|
||||
changing the way command line arguments are interpreted. For example,
|
||||
to use case-insensitive matching in exclude patterns and to revert to
|
||||
case-sensitive matching for the rest of command line, one could write:
|
||||
|
||||
tar xf foo.tar --ignore-case --exclude-from=FILE --no-ignore-case file.name
|
||||
|
||||
** Short option -l is now an alias of --check-links option, which complies
|
||||
with UNIX98. This ends the transition period started with version 1.14.
|
||||
|
||||
* New features
|
||||
|
||||
** New option --transform allows to transform file names before storing them
|
||||
in the archive or member names before extracting. The option takes a
|
||||
sed replace expression as its argument. For example,
|
||||
|
||||
tar cf foo.tar --transform 's,^,prefix/,'
|
||||
|
||||
will add 'prefix/' to all file names stored in foo.tar.
|
||||
|
||||
** --strip-components option works when deleting and comparing. In previous
|
||||
versions it worked only with --extract.
|
||||
|
||||
** New option --show-transformed-names enables display of transformed file
|
||||
or archive. It generalizes --show-stored-names option, introduced in
|
||||
1.15.90. In particular, when creating an archive in verbose mode, it lists
|
||||
member names as stored in the archive, i.e., with any eventual prefixes
|
||||
removed and file name transformations applied. The option is useful,
|
||||
for example, while comparing `tar cv' and `tar tv' outputs.
|
||||
|
||||
** New incremental snapshot file format keeps information about file names
|
||||
as well as that about directories.
|
||||
|
||||
** The --checkpoint option takes an optional argument specifying the number
|
||||
of records between the two successive checkpoints. Optional dot
|
||||
starting the argument intructs tar to print dots instead of textual
|
||||
checkpoints.
|
||||
|
||||
** The --totals option can be used with any tar operation (previous versions
|
||||
understood it only with --create). If an argument to this option is
|
||||
given, it specifies the signal upon delivery of which the statistics
|
||||
is to be printed. Both forms of this option (with and without
|
||||
argument) can be given to in a single invocation of tar.
|
||||
|
||||
* Bug fixes
|
||||
** Detect attempts to update compressed archives.
|
||||
|
||||
|
||||
version 1.15.90 - Sergey Poznyakoff, 2006-02-19
|
||||
|
||||
* New features
|
||||
|
||||
** Any number of -T (--files-from) options may be used in the command line.
|
||||
The file specified with -T may include any valid `tar' options,
|
||||
including another -T option.
|
||||
Compatibility note: older versions of tar would only recognize -C
|
||||
as an option name within the file list file. Now any file whose name
|
||||
starts with - is handled as an option. To insert file names starting with
|
||||
dash, use the --add-file option.
|
||||
|
||||
** List files containing null-separated file names are detected and processed
|
||||
automatically. It is no longer necessary to give the --null option.
|
||||
|
||||
** New option --no-unquote disables the unquoting of input file names.
|
||||
This is useful for processing output from `find dir -print0'.
|
||||
An orthogonal option --unquote is provided as well.
|
||||
|
||||
** New option --test-label tests the archive volume label.
|
||||
If an argument is specified, the label is compared against its value.
|
||||
Tar exits with code 0 if the two strings match, and with code 2 if
|
||||
they do not.
|
||||
|
||||
If no argument is given, the --verbose option is implied. In this case,
|
||||
tar prints the label name if present and exits with code 0.
|
||||
|
||||
** New option --show-stored-names. When creating an archive in verbose mode,
|
||||
it lists member names as stored in the archive, i.e., with any eventual
|
||||
prefixes removed. The option is useful, for example, while comparing
|
||||
`tar cv' and `tar tv' outputs.
|
||||
|
||||
** New option --to-command pipes the contents of archive members to the
|
||||
specified command.
|
||||
|
||||
** New option --atime-preserve=system, which uses the O_NOATIME feature
|
||||
of recent Linux kernels to avoid some problems when preserving file
|
||||
access times.
|
||||
|
||||
** New option --delay-directory-restore delays restoring modification times
|
||||
and permissions of extracted directories until the end of extraction.
|
||||
This is necessary for restoring from archives with unusual member
|
||||
ordering (in particular, those created with --no-recursion option).
|
||||
This option is implied when restoring from incremental archives.
|
||||
|
||||
** New option --restrict prohibits use of some potentially harmful tar
|
||||
options. Currently it disables '!' escape in multi-volume name menu.
|
||||
|
||||
** New options --quoting-style and --quote-chars control the way tar
|
||||
quotes member names on output. The --quoting-style takes an argument
|
||||
specifying the quoting style to use (literal, shell, shell-always,
|
||||
c, escape, locale, clocale). The argument to --quote-chars is a string
|
||||
specifying characters to quote, even if the selected quoting style
|
||||
would not quote them otherwise. The option --no-quote-chars is
|
||||
provided to disable quoting certain characters.
|
||||
|
||||
** The end-of-volume script (introduced with --info-script option) can
|
||||
get current archive name from the environment variable TAR_ARCHIVE and
|
||||
the volume number from the variable TAR_VOLUME. It can alter the
|
||||
archive name by writing new name to the file descriptor 3.
|
||||
|
||||
** Better support for full-resolution time stamps. Tar cannot restore
|
||||
time stamps to full nanosecond resolution, though, until the kernel
|
||||
guys get their act together and give us a system call to set file time
|
||||
stamps to nanosecond resolution.
|
||||
|
||||
** The -v option now prints time stamps only to 1-minute resolution,
|
||||
not full resolution, to avoid using up too many output columns.
|
||||
Nanosecond resolution is now supported, but that would be too much.
|
||||
|
||||
* Bug fixes
|
||||
|
||||
** Allow non-option arguments to be interspersed with options.
|
||||
** When extracting or listing archives in old GNU format, tar
|
||||
used to read an extra block of data after a long name header
|
||||
if length of the member name was divisible by block size (512).
|
||||
Consequently, the file pointer was set off and the next member
|
||||
was not processed correctly.
|
||||
** Previous version created invalid archives when files shrink
|
||||
during reading.
|
||||
** Compare mode (tar d) hanged when trying to compare file contents.
|
||||
** Previous versions in certain cases failed to restore directory
|
||||
modification times.
|
||||
** When creating an archive, do not attempt to store files whose
|
||||
meta-data cannot be stored in the header due to format limitations
|
||||
(for ustar and v7 formats).
|
||||
** The --version option now also outputs information about copyright,
|
||||
license, and credits. This reverts to the behavior of tar 1.14 and
|
||||
earlier, and conforms to the GNU coding standards. The --license (-L)
|
||||
option introduced in tar 1.15 has been removed, since it's no longer
|
||||
needed.
|
||||
|
||||
|
||||
version 1.15.1 - Sergey Poznyakoff, 2004-12-21
|
||||
|
||||
This version fixes a bug introduced in 1.15 which caused
|
||||
tar to refuse to extract files from standard input.
|
||||
|
||||
|
||||
version 1.15 - Sergey Poznyakoff, 2004-12-20
|
||||
|
||||
* Compressed archives are recognised automatically, it is no longer
|
||||
necessary to specify -Z, -z, or -j options to read them. Thus, you can
|
||||
now run `tar tf archive.tar.gz'.
|
||||
|
||||
* When restoring incremental dumps, --one-file-system option
|
||||
prevents directory hierarchies residing on different devices
|
||||
from being purged.
|
||||
|
||||
With the previous versions of tar it was dangerous to create
|
||||
incremental dumps with --one-file-system option, since they
|
||||
would recursively remove mount points when restoring from the
|
||||
back up. This change fixes the bug.
|
||||
|
||||
* Renamed --strip-path to --strip-components for consistency with
|
||||
the GNU convention.
|
||||
|
||||
* Skipping archive members is sped up if the archive media supports
|
||||
seeks.
|
||||
|
||||
* Restore script starts restoring only if it is given --all (-a) option,
|
||||
or some patterns. This is to prevent accidental restores.
|
||||
|
||||
* `tar --verify' prints a warning if during archive creation some of
|
||||
the file names had their prefixes stripped off.
|
||||
|
||||
* New option --exclude-caches instructs tar to exclude cache directories
|
||||
automatically on archive creation. Cache directories are those
|
||||
containing a standardized tag file, as specified at:
|
||||
|
||||
http://www.brynosaurus.com/cachedir/spec.html
|
||||
|
||||
* New configure option --with-rmt allows to specify full path name to
|
||||
the `rmt' utility. This supersedes DEFAULT_RMT_COMMAND variable
|
||||
introduced in version 1.14
|
||||
|
||||
* New configure variable DEFAULT_RMT_DIR allows to specify the directory
|
||||
where to install `rmt' utility. This is necessary since modifying
|
||||
--libexecdir as was suggested for version 1.14 produced a side effect: it
|
||||
also modified installation prefix for backup scripts (if
|
||||
--enable-backup-scripts was given).
|
||||
|
||||
* Bug fixes:
|
||||
** Fixed flow in recognizing files to be included in incremental dumps.
|
||||
** Correctly recognize sparse archive members when used with -T option.
|
||||
** GNU multivolume headers cannot store filenames longer than 100 characters.
|
||||
Do not allow multivolume archives to begin with such filenames.
|
||||
** If a member with link count > 2 was stored in the archive twice,
|
||||
previous versions of tar were not able to extract it, since they
|
||||
were trying to link the file to itself, which always failed and
|
||||
lead to removing the already extracted copy. Preserve the first
|
||||
extracted copy in such cases.
|
||||
** Restore script was passing improper argument to tar --listed option (which
|
||||
didn't affect the functionality, but was logically incorrect).
|
||||
** Fixed verification of created archives.
|
||||
** Fixed unquoting of file names containing backslash escapes (previous
|
||||
versions failed to recognize \a and \v).
|
||||
** When attempting to delete a non-existing member from the archive, previous
|
||||
versions of tar used to overwrite last archive block with zeroes.
|
||||
|
||||
|
||||
version 1.14 - Sergey Poznyakoff, 2004-05-11
|
||||
|
||||
* Added support for POSIX.1-2001 and ustar archive formats.
|
||||
* New option --format allows to select the output archive format
|
||||
* The default output format can be selected at configuration time
|
||||
by presetting the environment variable DEFAULT_ARCHIVE_FORMAT.
|
||||
Allowed values are GNU, V7, OLDGNU and POSIX.
|
||||
* New option --strip-path allows to cut off a given number of
|
||||
path elements from the name of the file being extracted.
|
||||
|
||||
* New options --index-file, --no-overwrite-dir. The --overwrite-dir
|
||||
option is now the default; use --no-overwrite-dir if you prefer
|
||||
the previous default behavior.
|
||||
|
||||
* The semantics of -o option is changed. When extracting, it
|
||||
does the same as --no-same-owner GNU tar option. This is compatible
|
||||
with UNIX98 tar. Otherwise, its effect is the same as that of
|
||||
--old-archive option. This latter is deprecated and will be removed
|
||||
in future.
|
||||
|
||||
* New option --check-links prints a message if not all links are dumped
|
||||
for a file being archived. This corresponds to the UNIX98 -l option.
|
||||
The current semantics of the -l option is retained for compatibility
|
||||
with previous releases, however such usage is strongly deprecated as
|
||||
the option will change to its UNIX98 semantics in the future releases.
|
||||
|
||||
* New option --occurrence[=N] can be used in conjunction with one of
|
||||
the subcommands --delete, --diff, --extract or --list when a list of
|
||||
files is given either on the command line or via -T option. This
|
||||
option instructs tar to process only the Nth occurrence of each named
|
||||
file. N defaults to 1, so `tar -x -f archive --occurrence filename'
|
||||
extracts the first occurrence of `filename' from `archive'
|
||||
and terminates without scanning to the end of the archive.
|
||||
|
||||
* New option --pax-option allows to control the handling of POSIX
|
||||
keywords in `pax' extended headers. It is equivalent to `pax'
|
||||
-o option.
|
||||
|
||||
* --incremental and --listed-incremental options work correctly on
|
||||
individual files, as well as on directories.
|
||||
|
||||
* New scripts: backup (replaces old level-0 and level-1) and restore.
|
||||
The scripts are compiled and installed if --enable-backup-scripts
|
||||
option is given to configure.
|
||||
|
||||
* By default tar searches "rmt" utility in "$prefix/libexec/rmt",
|
||||
which is consistent with the location where the version of "rmt"
|
||||
included in the package is installed. Previous versions of tar
|
||||
used "/etc/rmt". To install "rmt" to its traditional location,
|
||||
run configure with option --libexecdir=/etc. Otherwise, if you
|
||||
already have rmt installed and wish to use it, instead of the
|
||||
shipped in version, set the variable DEFAULT_RMT_COMMAND to
|
||||
the full path name of the utility, e.g., ./configure
|
||||
DEFAULT_RMT_COMMAND=/etc/rmt.
|
||||
|
||||
Notice also that the full path name of the "rmt" utility to
|
||||
use can be set at runtime, by giving option --rmt-command to
|
||||
tar.
|
||||
|
||||
* Removed obsolete command line options:
|
||||
** --absolute-paths superseded by --absolute-names
|
||||
** --block-compress is not needed any longer
|
||||
** --block-size superseded by --blocking-factor
|
||||
** --modification-time superseded by --touch
|
||||
** --read-full-blocks superseded by --read-full-records
|
||||
** --record-number superseded by --block-number
|
||||
** --version-control superseded by --backup
|
||||
|
||||
* New message translations fi (Finnish), gl (Galician), hr (Croatian),
|
||||
hu (Hungarian), ms (Malaysian), nb (Norwegian), ro (Romanian), sk
|
||||
(Slovak), zh_CN (Chinese simplified), zh_TW (Chinese traditional).
|
||||
The code 'no' for Norwegian (Bokmål) has been withdrawn; use 'nb' instead.
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
|
||||
version 1.13.25 - Paul Eggert, 2001-09-26
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
|
||||
version 1.13.24 - Paul Eggert, 2001-09-22
|
||||
|
||||
* New option --overwrite-dir.
|
||||
* Fixes for buffer overrun, porting, and copyright notice problems.
|
||||
* The message translations for Korean are available again.
|
||||
|
||||
|
||||
version 1.13.23 - Paul Eggert, 2001-09-13
|
||||
|
||||
* Bug, porting, and copyright notice fixes.
|
||||
|
||||
|
||||
version 1.13.22 - Paul Eggert, 2001-08-29
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
|
||||
version 1.13.21 - Paul Eggert, 2001-08-28
|
||||
|
||||
* Porting and copyright notice fixes.
|
||||
|
||||
|
||||
version 1.13.20 - Paul Eggert, 2001-08-27
|
||||
|
||||
* Some bugs were fixed:
|
||||
@@ -394,7 +47,6 @@ version 1.13.20 - Paul Eggert, 2001-08-27
|
||||
The translation for Korean has been withdrawn due to encoding errors.
|
||||
It will be reissued once those are fixed.
|
||||
|
||||
|
||||
version 1.13.19 - Paul Eggert, 2001-01-13
|
||||
|
||||
* The -I option has been withdrawn, as it was buggy and confusing.
|
||||
@@ -403,7 +55,6 @@ version 1.13.19 - Paul Eggert, 2001-01-13
|
||||
* With an option like -N DATE, if DATE starts with "/" or ".", it is taken
|
||||
to be a file name; the last-modified time of that file is used as the date.
|
||||
|
||||
|
||||
version 1.13.18 - Paul Eggert, 2000-10-29
|
||||
|
||||
* Some security problems have been fixed. `tar -x' now modifies only
|
||||
@@ -431,16 +82,14 @@ version 1.13.18 - Paul Eggert, 2000-10-29
|
||||
|
||||
* This version of tar works best with GNU gzip test version 1.3 or later.
|
||||
Please see <ftp://alpha.gnu.org/gnu/gzip/>.
|
||||
|
||||
|
||||
* `tar --delete -f -' now works again.
|
||||
|
||||
|
||||
version 1.13.17 - Paul Eggert, 2000-01-07.
|
||||
|
||||
* `tar --delete -f -' is no longer allowed; it was too buggy.
|
||||
* Diagnostic messages have been made more regular and consistent.
|
||||
|
||||
|
||||
version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
|
||||
* By default, tar now refuses to overwrite an existing file when
|
||||
@@ -463,8 +112,8 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
when extracting, and warns about such file names when creating an archive.
|
||||
To enable the old behavior, use the -P or --absolute-names option.
|
||||
|
||||
* Tar now handles file names with multibyte encodings (e.g., UTF-8, Shift-JIS)
|
||||
correctly. It relies on the mbrtowc function to handle multibyte characters.
|
||||
* Tar now handles file names with multibyte encodings (e.g. UTF-8, Shift-JIS)
|
||||
correctly. It relies on the mbrtowc function to handle multibytes.
|
||||
|
||||
* The file generated by -g or --listed-incremental now uses a format
|
||||
that is independent of locale, so that users need not worry about
|
||||
@@ -478,26 +127,23 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
`quoted like this' (in the default C locale) or are followed by
|
||||
colon, newline, or space, depending on context. Unprintable
|
||||
characters are escaped with a C-like backslash conventions.
|
||||
Terminating characters (e.g., close-quote, colon, newline)
|
||||
Terminating characters (e.g. close-quote, colon, newline)
|
||||
are also escaped as needed.
|
||||
|
||||
* tar now ignores socket files when creating an archive.
|
||||
Previously tar archived sockets as fifos, which caused problems.
|
||||
|
||||
|
||||
version 1.13.15 - Paul Eggert, 1999-12-03.
|
||||
|
||||
* If a file's ctime changes when being archived, report an error.
|
||||
Previously tar looked at mtime, which missed some errors.
|
||||
|
||||
|
||||
version 1.13.14 - Paul Eggert, 1999-11-07.
|
||||
|
||||
* New translations ja, pt_BR.
|
||||
* New options --help and --version for rmt.
|
||||
* Ignore Solaris door files when creating an archive.
|
||||
|
||||
|
||||
version 1.13.13 - Paul Eggert, 1999-10-11.
|
||||
|
||||
* Invalid headers in tar files now elicit errors, not just warnings.
|
||||
@@ -505,7 +151,6 @@ version 1.13.13 - Paul Eggert, 1999-10-11.
|
||||
* If you specify an invalid date, `tar' now substitutes (time_t) -1.
|
||||
* `configure --with-dmalloc' is no longer available.
|
||||
|
||||
|
||||
version 1.13.12 - Paul Eggert, 1999-09-24.
|
||||
|
||||
* `tar' now supports hard links to symbolic links.
|
||||
@@ -536,7 +181,7 @@ version 1.13.12 - Paul Eggert, 1999-09-24.
|
||||
|
||||
* Some diagnostics have been reworded for consistency.
|
||||
|
||||
|
||||
|
||||
version 1.13.11 - Paul Eggert, 1999-08-23.
|
||||
|
||||
* The short name of the --bzip option has been changed to -I,
|
||||
@@ -556,14 +201,14 @@ version 1.13.11 - Paul Eggert, 1999-08-23.
|
||||
numeric UTC offsets like `-0500' instead of abbreviations like
|
||||
`EST', as abbreviations are not standardized and are ambiguous.
|
||||
|
||||
|
||||
|
||||
version 1.13.10 - Paul Eggert, 1999-08-20.
|
||||
|
||||
* `tar' now uses signed base-64 when outputting header values that are
|
||||
out of the range of the standard unsigned base-8 format. [This
|
||||
change was superseded in 1.13.12, described above.]
|
||||
|
||||
|
||||
|
||||
version 1.13.9 - Paul Eggert, 1999-08-18.
|
||||
|
||||
* `tar' now writes two zero blocks at end-of-archive instead of just one.
|
||||
@@ -575,14 +220,14 @@ version 1.13.9 - Paul Eggert, 1999-08-18.
|
||||
* `tar' now reads buggy tar files that have a null byte at the start of a
|
||||
numeric header field.
|
||||
|
||||
|
||||
|
||||
version 1.13.8 - Paul Eggert, 1999-08-16.
|
||||
|
||||
* For compatibility with traditional `tar', intermediate directories
|
||||
created automatically by root are no longer given the uid and gid of
|
||||
the original file or directory.
|
||||
|
||||
|
||||
|
||||
version 1.13.7 - Paul Eggert, 1999-08-14.
|
||||
|
||||
* --listed-incremental and --newer are now incompatible options.
|
||||
@@ -592,7 +237,7 @@ version 1.13.7 - Paul Eggert, 1999-08-14.
|
||||
|
||||
* --diff without --absolute-names no longer falls back on absolute names.
|
||||
|
||||
|
||||
|
||||
version 1.13.6 - Paul Eggert, 1999-08-11.
|
||||
|
||||
* An --exclude pattern containing / now excludes a file only if it matches an
|
||||
@@ -601,7 +246,7 @@ version 1.13.6 - Paul Eggert, 1999-08-11.
|
||||
|
||||
* The protocol for talking to rmt has been extended slightly.
|
||||
Open flags are now communicated in symbolic format as well as numeric.
|
||||
The symbolic format (e.g., "O_WRONLY|O_CREAT|O_TRUNC") is for portability
|
||||
The symbolic format (e.g. "O_WRONLY|O_CREAT|O_TRUNC") is for portability
|
||||
when rmt is operating on a different operating system from tar.
|
||||
The numeric format is retained, and rmt uses it if symbolic format is absent,
|
||||
for backward compatibility with older versions of tar and rmt.
|
||||
@@ -619,37 +264,37 @@ version 1.13.6 - Paul Eggert, 1999-08-11.
|
||||
|
||||
* New option -y or --bzip2 for bzip2 compression, by popular request.
|
||||
|
||||
|
||||
|
||||
version 1.13.5 - Paul Eggert, 1999-07-20.
|
||||
|
||||
* Do the delayed updates of file metadata even after a fatal error.
|
||||
|
||||
|
||||
|
||||
version 1.13.4 - Paul Eggert, 1999-07-20.
|
||||
|
||||
* Do not chmod unless we are root or the -p option was given;
|
||||
this matches historical practice.
|
||||
|
||||
|
||||
|
||||
version 1.13.3 - Paul Eggert, 1999-07-16.
|
||||
|
||||
* A path name is excluded if any of its file name components matches an
|
||||
excluded pattern, even if the path name was specified on the command line.
|
||||
Also see 1.13.6 for later changes in this area.
|
||||
|
||||
|
||||
|
||||
version 1.13.2 - Paul Eggert, 1999-07-14.
|
||||
|
||||
* Bug reporting address changed to <bug-tar@gnu.org>.
|
||||
|
||||
|
||||
|
||||
version 1.13.1 - Paul Eggert, 1999-07-12.
|
||||
|
||||
* Bug fixes only.
|
||||
|
||||
version 1.13 - Paul Eggert, 1999-07-08.
|
||||
|
||||
* Support for large files, e.g., files larger than 2 GB on many 32-bit hosts.
|
||||
* Support for large files, e.g. files larger than 2 GB on many 32-bit hosts.
|
||||
Also, support for larger uids, device ids, etc.
|
||||
* Many bug fixes and porting fixes.
|
||||
* This release is only for fixes. A more ambitious test release,
|
||||
@@ -661,7 +306,7 @@ version 1.13 - Paul Eggert, 1999-07-08.
|
||||
but they have been removed to maintain compatibility with paxutils.
|
||||
Please try --use=bzip2 instead of --bzip2.
|
||||
|
||||
Version 1.12 - François Pinard, 1997-04.
|
||||
Version 1.12 - Fran<EFBFBD>ois Pinard, 1997-04.
|
||||
|
||||
Sensitive matters
|
||||
* Use shell globbing patterns for --label, instead of regular expressions.
|
||||
@@ -704,7 +349,7 @@ Various changes
|
||||
|
||||
Many bugs are squashed, while others still run free.
|
||||
|
||||
Version 1.11.8 - François Pinard, 1995-06.
|
||||
Version 1.11.8 - Fran<EFBFBD>ois Pinard, 1995-06.
|
||||
|
||||
* Messages available in French, German, Portuguese and Swedish.
|
||||
* The distribution provides a rudimentary Texinfo manual.
|
||||
@@ -840,8 +485,8 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
@@ -857,10 +502,11 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
end:
|
||||
|
||||
Local Variables:
|
||||
coding: iso-latin-1
|
||||
End:
|
||||
|
||||
128
PORTS
128
PORTS
@@ -1,60 +1,48 @@
|
||||
Ports of GNU tar and other tars
|
||||
See the end of file for copying conditions.
|
||||
* Ports of GNU tar and other micro-tars -*- outline -*-
|
||||
|
||||
* Introduction
|
||||
|
||||
Most entries in this file are out of date, unfortunately. Such
|
||||
entries are marked with an `X'. Run grep '^\*\*[^X]' PORTS to
|
||||
extract valid entries.
|
||||
|
||||
Please write bug-tar@gnu.org if you are aware of various ports of GNU tar
|
||||
to non-GNU and non-Unix systems not listed here, or for corrections.
|
||||
Please write tar-bugs@gnu.ai.mit.edu if you are aware of various ports
|
||||
of GNU tar to non-Unix systems not listed here, or for corrections.
|
||||
Please provide the goal system, a complete and stable URL, the maintainer
|
||||
name and address, the tar version used as a base, and your comments.
|
||||
|
||||
* GNU/Linux and Unix
|
||||
.* Amiga
|
||||
|
||||
** Star is a tape archiver similar to tar.
|
||||
<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/star.html>
|
||||
|
||||
* Amiga
|
||||
|
||||
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
|
||||
. + ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
|
||||
maintained by Enrico Forestieri <enrico@com.unipr.it>
|
||||
Based on tar 1.11.8.
|
||||
|
||||
**X ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
|
||||
. + ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
|
||||
maintained by the ADE group <fnf@fishpond.ninemoons.com>
|
||||
Based on tar 1.11.8, needs ixemul.library.
|
||||
|
||||
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
|
||||
. + ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
|
||||
maintained by <mscheler@wuarchive.wustl.edu>
|
||||
|
||||
* DEC alpha (NT)
|
||||
.* DEC alpha (NT)
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
|
||||
* DEC VAX (VMS)
|
||||
.* DEC VAX (VMS)
|
||||
|
||||
**X http://www.lp.se/free/vmstar/
|
||||
. + http://www.lp.se/free/vmstar/
|
||||
maintained by Richard Levitte <levitte@lp.se>
|
||||
This is not GNU tar, but a separate implementation.
|
||||
|
||||
** maintained by William Bader <william@nscs.fast.net>
|
||||
. + maintained by William Bader <william@nscs.fast.net>
|
||||
For V4.7. Based on an old PDtar. Requires compatible shared libraries
|
||||
to run V5 or V6 executables.
|
||||
|
||||
* IBM/PC (DV/X)
|
||||
.* IBM/PC (DV/X)
|
||||
|
||||
**X ftp://qdeck.com/ (?)
|
||||
. + ftp://qdeck.com/ (?)
|
||||
maintained by David Ronis <ronis@gibbs.chem.mcgill.ca>
|
||||
For Desqview/X. Everything works besides compression. Copy of hacked
|
||||
sources available, some of DV/X's programmer's library also needed.
|
||||
|
||||
* IBM/PC (MSDOS)
|
||||
.* IBM/PC (MSDOS)
|
||||
|
||||
**X http://www.simtel.net/simtel.net/
|
||||
. + http://www.simtel.net/simtel.net/
|
||||
http://www.leo.org/pub/comp/platforms/pc/gnuish (Germany)
|
||||
ftp://ftp.simtel.net/simtelnet/gnu
|
||||
ftp://ftp.leo.org/pub/comp/platforms/pc/gnuish
|
||||
@@ -62,112 +50,82 @@ See the end of file for copying conditions.
|
||||
You get many GNU tools, not only `tar'. The GNUish project is described
|
||||
in `gnuish_t.htm'.
|
||||
|
||||
** The DJGPP development tools also include some `tar' utilities.
|
||||
. + The DJGPP development tools also include some `tar' utilities.
|
||||
|
||||
**X ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
|
||||
. + ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Based on tar 1.11.2. Support for SCSI (via ASPI) and network (rsh over
|
||||
packet driver). No support for win95 long file names.
|
||||
|
||||
**X ftp://ftp.wu-wien.ac.at/pub/src/PCmisc/aspi-tar/*
|
||||
. + ftp://ftp.wu-wien.ac.at:pub/src/PCmisc/aspi-tar/*
|
||||
maintained by Christoph Splittgerber <chris@orion.sdata.de>
|
||||
Based on tar 1.10. Support for SCSI (via ASPI).
|
||||
|
||||
**X ftp://wuarchive (?)
|
||||
. + ftp://wuarchive (?)
|
||||
Several DOS version based on PDtar. John Gilmore <gnu@toad.com> says
|
||||
he has copies of several vintages saved.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
|
||||
. + ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.taz
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.zip
|
||||
|
||||
**X ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
|
||||
. + ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
|
||||
Based on PDtar.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
**X http://people.darmstadt.netsurf.de/tst/tar.htm
|
||||
. + http://people.darmstadt.netsurf.de/tst/tar.htm
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
This is not a `tar' port, but an index of them.
|
||||
|
||||
* IBM/PC (OS/2)
|
||||
.* IBM/PC (OS/2)
|
||||
|
||||
**X http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
|
||||
. + http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
|
||||
http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtak254.zip
|
||||
maintained by Andreas Kaiser <Andreas.Kaiser@stuttgart.netsurf.de>
|
||||
Version 2.54. Based on tar 1.10. The second archive contains SCSI
|
||||
drivers (DAT streamers notably) and rmt-type programs.
|
||||
|
||||
* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
|
||||
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
**X ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
|
||||
.* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
|
||||
|
||||
. + ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
|
||||
maintained by Cygnus
|
||||
GNU-Win32 B17.1 distribution. Download all files, `cat' them together,
|
||||
and `untar' the result. You get many GNU tools, not only `tar'.
|
||||
Based on tar 1.11.2.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
* IBM/PC (Windows 3.1)
|
||||
.* IBM/PC (Windows 3.1)
|
||||
|
||||
**X ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
|
||||
. + ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Support for network (rsh over winsock). No support for win95 long
|
||||
file names.
|
||||
|
||||
**X ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
|
||||
. + ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
|
||||
Based on GNU tar 1.11.2.
|
||||
|
||||
* Macintosh
|
||||
.* Macintosh
|
||||
|
||||
** Paulo Abreu (paulotex at yahoo dot com) did a
|
||||
limited port of GNU tar to Darwin, with support for resource forks
|
||||
and finder info, but this no longer seems to be available.
|
||||
. + There is a tar in Stuffit Expander which is available many places and
|
||||
comes with MacOS. It creates some spurious files but works on average.
|
||||
|
||||
** There is a tar in Stuffit Expander which is available many places and
|
||||
comes with MacOS. It creates some spurious files but works on average.
|
||||
|
||||
** There is an excellent GNU tar bundled in Tenon MachTen, but it does not
|
||||
seem to be available separately.
|
||||
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 1999, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 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, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
. + There is an excellent GNU tar bundled in Tenon MachTen, but it does not
|
||||
seem to be available separately.
|
||||
|
||||
185
README
185
README
@@ -1,7 +1,25 @@
|
||||
README for GNU tar
|
||||
See the end of file for copying conditions.
|
||||
|
||||
* Introduction
|
||||
Copyright 1990, 1991, 1992, 1994, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
Please glance through *all* sections of this
|
||||
`README' file before starting configuration. Also make sure you read files
|
||||
@@ -30,15 +48,9 @@ See file `THANKS' for a list of contributors.
|
||||
Besides those configure options documented in files `INSTALL' and
|
||||
`ABOUT-NLS', an extra option may be accepted after `./configure':
|
||||
|
||||
* Install
|
||||
|
||||
** Selecting the default archive format.
|
||||
|
||||
The default archive format is GNU, this can be overridden by
|
||||
presetting DEFAULT_ARCHIVE_FORMAT while configuring. The allowed
|
||||
values are GNU, V7, OLDGNU, USTAR and POSIX.
|
||||
|
||||
** Selecting the default archive device
|
||||
* `--disable-largefile' omits support for large files, even if the
|
||||
operating system supports large files. Typically, large files are
|
||||
those larger on 2 GB on a 32-bit host.
|
||||
|
||||
The default archive device is now `stdin' on read and `stdout' on write.
|
||||
The installer can still override this by presetting `DEFAULT_ARCHIVE'
|
||||
@@ -46,45 +58,34 @@ in the environment before configuring (the behavior of `-[0-7]' or
|
||||
`-[0-7]lmh' options in `tar' are then derived automatically). Similarly,
|
||||
`DEFAULT_BLOCKING' can be preset to something else than 20.
|
||||
|
||||
** Selecting full pathname of the "rmt" binary.
|
||||
For comprehensive modifications to GNU tar, you might need tools beyond
|
||||
those used in simple installations. Fully install GNU m4 1.4 first,
|
||||
and only then, Autoconf 2.13 or later. Install Perl, then Automake
|
||||
1.4 or later. You might need Bison 1.28 or later, and GNU tar itself.
|
||||
All are available on GNU archive sites, like in
|
||||
ftp://ftp.gnu.org/pub/gnu/.
|
||||
|
||||
Previous versions of tar always looked for "rmt" binary in the
|
||||
directory "/etc/rmt". However, the "rmt" program included
|
||||
in the distribution was installed under "$prefix/libexec/rmt".
|
||||
To fix this discrepancy, tar now looks for "$prefix/libexec/rmt".
|
||||
If you do not want this behavior, specify full path name of
|
||||
"rmt" binary using DEFAULT_RMT_DIR variable, e.g.:
|
||||
Send bug reports to `bug-tar@gnu.org'. (Beware, old-timers: it is
|
||||
`@gnu', not `@prep'; and not `bug-gnu-utils' anymore.) A bug report is
|
||||
an adequate description of the problem: your input, what you expected,
|
||||
what you got, and why this is wrong. Diffs are welcome, but they only
|
||||
describe a solution, from which the problem might be uneasy to infer.
|
||||
If needed, submit actual data files with your report. Small data files
|
||||
are preferred. Big files may sometimes be necessary, but do not send them
|
||||
to the report address; rather take special arrangement with the maintainer.
|
||||
|
||||
./configure DEFAULT_RMT_DIR=/etc
|
||||
Your feedback will help us to make a better and more portable package.
|
||||
Consider documentation errors as bugs, and report them as such. If you
|
||||
develop anything pertaining to `tar' or have suggestions, let us know
|
||||
and share your findings by writing to <bug-tar@gnu.org>.
|
||||
|
||||
If you already have a copy of "rmt" installed and wish to use it
|
||||
instead of the version supplied with the distribution, use --with-rmt
|
||||
option:
|
||||
|
||||
./configure --with-rmt=/etc/rmt
|
||||
|
||||
This will also disable building the included version of rmt.
|
||||
|
||||
** Installing backup scripts.
|
||||
|
||||
This version of tar is shipped with the shell scripts for producing
|
||||
incremental backups (dumps) and restoring filesystems from them.
|
||||
The name of the backup script is "backup". The name of the
|
||||
restore script is "restore". They are installed in "$prefix/sbin"
|
||||
directory.
|
||||
|
||||
Use option --enable-backup-scripts to compile and install these
|
||||
scripts.
|
||||
|
||||
** `--disable-largefile' omits support for large files, even if the
|
||||
operating system supports large files. Typically, large files are
|
||||
those larger than 2 GB on a 32-bit host.
|
||||
|
||||
* Installation hints
|
||||
Installation hints
|
||||
------------------
|
||||
|
||||
Here are a few hints which might help installing `tar' on some systems.
|
||||
|
||||
** gzip and bzip2.
|
||||
* gzip and bzip2.
|
||||
|
||||
GNU tar uses the gzip and bzip2 programs to read and write compressed
|
||||
archives. If you don't have these programs already, you need to
|
||||
@@ -105,7 +106,7 @@ in gzip test version 1.3, which as of this writing is available at
|
||||
incompatibility by using a shell command like
|
||||
`gzip -d <file.tar.gz | tar -xzf -'.
|
||||
|
||||
** Solaris issues.
|
||||
* Solaris issues.
|
||||
|
||||
GNU tar exercises many features that can cause problems with older GCC
|
||||
versions. In particular, GCC 2.8.1 (sparc, -O1 or -O2) is known to
|
||||
@@ -116,7 +117,7 @@ Recent versions of Solaris tar sport a new -E option to generate
|
||||
extended headers in an undocumented format. GNU tar does not
|
||||
understand these headers.
|
||||
|
||||
** Static linking.
|
||||
* Static linking.
|
||||
|
||||
Some platform will, by default, prepare a smaller `tar' executable
|
||||
which depends on shared libraries. Since GNU `tar' may be used for
|
||||
@@ -137,32 +138,34 @@ to a value from the table below, before configuration (see `INSTALL').
|
||||
Solaris (vendor) -Bstatic
|
||||
SunOS (vendor) -Bstatic
|
||||
|
||||
** Failed tests `ignfail.sh' or `incremen.sh'.
|
||||
* Failed tests `ignfail.sh' or `incremen.sh'.
|
||||
|
||||
In an NFS environment, lack of synchronization between machine clocks
|
||||
might create difficulties to any tool comparing dates and file time stamps,
|
||||
like `tar' in incremental dumps. This has been a recurrent problem with
|
||||
GNU Make for the last few years. We would like a general solution.
|
||||
|
||||
** BSD compatibility matters.
|
||||
* BSD compatibility matters.
|
||||
|
||||
Set LIBS to `-lbsd' before configuration (see `INSTALL') if the linker
|
||||
complains about `bsd_ioctl' (Slackware). Also set CPPFLAGS to
|
||||
`-I/usr/include/bsd' if <sgtty.h> is not found (Slackware).
|
||||
|
||||
** OPENStep 4.2 swap files
|
||||
* OPENStep 4.2 swap files
|
||||
|
||||
Tar cannot read the file /private/vm/swapfile.front (even as root).
|
||||
This file is not a real file, but some kind of uncompressed view of
|
||||
the real compressed swap file; there is no reason to back it up, so
|
||||
the simplest workaround is to avoid tarring this file.
|
||||
|
||||
* Special topics
|
||||
|
||||
Special topics
|
||||
--------------
|
||||
|
||||
Here are a few special matters about GNU `tar', not related to build
|
||||
matters. See previous section for such.
|
||||
|
||||
** File attributes.
|
||||
* File attributes.
|
||||
|
||||
About *security*, it is probable that future releases of `tar' will have
|
||||
some behavior changed. There are many pending suggestions to choose from.
|
||||
@@ -175,77 +178,19 @@ implement flavors of symbolic links showing different behavior and
|
||||
properties. We did not successfully sorted all these out yet. Currently,
|
||||
the `lchown' call will be used if available, but that's all.
|
||||
|
||||
** POSIX compliance.
|
||||
* POSIX compliance.
|
||||
|
||||
GNU `tar' is able to create archive in the following formats:
|
||||
|
||||
*** The format of UNIX version 7
|
||||
*** POSIX.1-1988 format, also known as "ustar format"
|
||||
*** POSIX.1-2001 format, also known as "pax format"
|
||||
*** Old GNU format (described below)
|
||||
|
||||
In addition to those, GNU `tar' is also able to read archives
|
||||
produced by `star' archiver.
|
||||
|
||||
A so called `Old GNU' format is based on an early draft of the
|
||||
POSIX 1003.1 `ustar' standard which is different from the final
|
||||
standard. It defines its extensions (such as incremental backups
|
||||
and handling of the long file names) in a way incompatible with
|
||||
any existing tar archive format, therefore the use of old GNU
|
||||
format is strongly discouraged.
|
||||
|
||||
Please read the file NEWS for more information about POSIX compliance
|
||||
and new `tar' features.
|
||||
GNU `tar' implements an early draft of the POSIX 1003.1 `ustar' standard
|
||||
which is different from the final standard. This will be progressively
|
||||
corrected over the incoming few years. Don't be mislead by the mere
|
||||
existence of the --posix option. Later releases will become able to
|
||||
read truly POSIX archives, and also to produce them under option. (Also,
|
||||
if you look at the internals, don't take the GNU extensions you see for
|
||||
granted, as they are planned to change.) GNU tar 2.0 will produce POSIX
|
||||
archives by default, but there is a long way before we get there.
|
||||
|
||||
* What's next?
|
||||
|
||||
GNU tar will be merged into GNU paxutils: a project containing
|
||||
several utilities related to creating and handling archives in
|
||||
various formats. The project will include tar, cpio and pax
|
||||
utilities.
|
||||
|
||||
* Bug reporting.
|
||||
|
||||
Send bug reports to <bug-tar@gnu.org>. A bug report should contain
|
||||
an adequate description of the problem, your input, what you expected,
|
||||
what you got, and why this is wrong. Diffs are welcome, but they only
|
||||
describe a solution, from which the problem might be uneasy to infer.
|
||||
If needed, submit actual data files with your report. Small data files
|
||||
are preferred. Big files may sometimes be necessary, but do not send them
|
||||
to the report address; rather take special arrangement with the maintainer.
|
||||
|
||||
Your feedback will help us to make a better and more portable package.
|
||||
Consider documentation errors as bugs, and report them as such. If you
|
||||
develop anything pertaining to `tar' or have suggestions, let us know
|
||||
and share your findings by writing to <bug-tar@gnu.org>.
|
||||
|
||||
|
||||
* Copying
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1994, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
In the future we will try to release tar-1.14 as soon as possible and
|
||||
start merging with paxutils afterwards. We'll also try to rewrite
|
||||
some parts of the documentation after paxutils has been merged.
|
||||
|
||||
284
README-alpha
284
README-alpha
@@ -1,82 +1,242 @@
|
||||
This is GNU tar.
|
||||
This is a test release of GNU tar.
|
||||
|
||||
This is a *pre-release* version, and not ready for production use yet.
|
||||
Please send comments and problem reports to <bug-tar@gnu.org>.
|
||||
|
||||
If you have taken the sources from CVS you will need the following
|
||||
packages (or later) to build GNU tar. We don't make any extra effort
|
||||
to accommodate older versions of these packages, so please make sure
|
||||
that you have the latest stable version.
|
||||
Copyright 2001 Free Software Foundation, Inc.
|
||||
|
||||
- Automake <http://www.gnu.org/software/automake/>
|
||||
- Autoconf <http://www.gnu.org/software/autoconf/>
|
||||
- Bison <http://www.gnu.org/software/bison/>
|
||||
- Gettext <http://www.gnu.org/software/gettext/>
|
||||
- Gzip <http://www.gnu.org/software/gzip/>
|
||||
- M4 <http://www.gnu.org/software/m4/>
|
||||
- Texinfo <http://www.gnu.org/software/texinfo>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
This file is part of GNU tar.
|
||||
|
||||
As of this writing, the latest stable version of Gzip is 1.2.4 but we
|
||||
suggest using test version 1.3.5 (or later, if one becomes available).
|
||||
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.
|
||||
|
||||
Valgrind <http://valgrind.org/> is also highly recommended, if
|
||||
Valgrind supports your architecture.
|
||||
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.
|
||||
|
||||
Before building the package, run "bootstrap". It obtains various
|
||||
additional files from the CVS repository and the Translation Project
|
||||
site and prepares the source directory for building.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
When run without arguments, bootstrap will try to obtain gnulib and
|
||||
paxutils files from their corresponding CVS repositories on Savannah
|
||||
using anonymous SSH access. Then, it will fetch the po files from tar
|
||||
page at Translation Project, and, finally, it will start autoconfiguration
|
||||
process. Simply running it without arguments should do in most cases.
|
||||
Several options allow to control the behavior of bootstrap:
|
||||
This release was built with GNU automake 1.5 patched as follows:
|
||||
|
||||
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
|
||||
sources reside. Use this if you already
|
||||
have gnulib sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
2001-09-24 Paul Eggert <eggert@twinsun.com>
|
||||
|
||||
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
|
||||
sources reside. Use this if you already
|
||||
have paxutils sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
* m4/header.m4 (_AM_Config_Header_Index): Remove.
|
||||
(AM_CONFIG_HEADER): Don't use it. It wasn't working, and was
|
||||
causing needless rebuilds.
|
||||
|
||||
--cvs-auth=METHOD Set the CVS access method used for downloading
|
||||
gnulib files. METHOD is one of the keywords
|
||||
accepted by cvs -d option (see info cvs
|
||||
repository).
|
||||
2001-09-14 Paul Eggert <eggert@twinsun.com>
|
||||
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
* lib/am/distdir.am (REMOVE_DISTDIR):
|
||||
New macro. Do not change permission of non-directories.
|
||||
(distdir, dist, dist-bzip2, dist-tarZ, dist-shar, dist-zip, dist-all,
|
||||
distcheck): Use it.
|
||||
|
||||
--no-po Do not download po files.
|
||||
===================================================================
|
||||
RCS file: lib/am/distdir.am,v
|
||||
retrieving revision 1.5
|
||||
retrieving revision 1.5.0.1
|
||||
diff -pu -r1.5 -r1.5.0.1
|
||||
--- lib/am/distdir.am 2001/07/14 20:12:52 1.5
|
||||
+++ lib/am/distdir.am 2001/09/15 05:12:18 1.5.0.1
|
||||
@@ -29,6 +29,11 @@ else !%?TOPDIR_P%
|
||||
?DISTDIR?distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
||||
endif !%?TOPDIR_P%
|
||||
|
||||
+REMOVE_DISTDIR = \
|
||||
+ { test ! -d $(distdir) \
|
||||
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
+ && rm -fr $(distdir); }; }
|
||||
+
|
||||
distdir: $(DISTFILES)
|
||||
##
|
||||
## For Gnits users, this is pretty handy. Look at 15 lines
|
||||
@@ -47,7 +52,7 @@ endif %?TOPDIR_P%
|
||||
## Only for the top dir.
|
||||
##
|
||||
if %?TOPDIR_P%
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
mkdir $(distdir)
|
||||
endif %?TOPDIR_P%
|
||||
##
|
||||
@@ -168,13 +173,13 @@ GZIP_ENV = --best
|
||||
.PHONY: dist
|
||||
dist: distdir
|
||||
$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
|
||||
if %?BZIP2%
|
||||
.PHONY: dist-bzip2
|
||||
dist-bzip2: distdir
|
||||
$(AMTAR) chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
endif %?BZIP2%
|
||||
|
||||
|
||||
@@ -182,7 +187,7 @@ if %?COMPRESS%
|
||||
.PHONY: dist-tarZ
|
||||
dist-tarZ: distdir
|
||||
$(AMTAR) chof - $(distdir) | compress -c >$(distdir).tar.Z
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
endif %?COMPRESS%
|
||||
|
||||
|
||||
@@ -190,7 +195,7 @@ if %?SHAR%
|
||||
.PHONY: dist-shar
|
||||
dist-shar: distdir
|
||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
endif %?SHAR%
|
||||
|
||||
|
||||
@@ -199,7 +204,7 @@ if %?ZIP%
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
endif %?ZIP%
|
||||
|
||||
endif %?TOPDIR_P%
|
||||
@@ -223,7 +228,7 @@ dist-all: distdir
|
||||
?SHAR? shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
?ZIP? -rm -f $(distdir).zip
|
||||
?ZIP? zip -rq $(distdir).zip $(distdir)
|
||||
- -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
|
||||
endif %?TOPDIR_P%
|
||||
|
||||
@@ -239,8 +244,7 @@ if %?TOPDIR_P%
|
||||
# tarfile.
|
||||
.PHONY: distcheck
|
||||
distcheck: dist
|
||||
-## Make sure we can remove distdir before trying to remove it.
|
||||
- -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf -
|
||||
## Make the new source tree read-only. Distributions ought to work in
|
||||
## this case. However, make the top-level directory writable so we
|
||||
@@ -273,7 +277,7 @@ distcheck: dist
|
||||
&& (test `find . -type f -print | wc -l` -eq 0 \
|
||||
|| (echo "Error: files left after distclean" 1>&2; \
|
||||
exit 1) )
|
||||
- -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir)
|
||||
+ $(REMOVE_DISTDIR)
|
||||
@echo "$(distdir).tar.gz is ready for distribution" | \
|
||||
sed 'h;s/./=/g;p;x;p;x'
|
||||
endif %?TOPDIR_P%
|
||||
===================================================================
|
||||
RCS file: m4/header.m4,v
|
||||
retrieving revision 1.5
|
||||
retrieving revision 1.5.0.1
|
||||
diff -pu -r1.5 -r1.5.0.1
|
||||
--- m4/header.m4 2001/07/21 05:27:26 1.5
|
||||
+++ m4/header.m4 2001/09/24 18:29:30 1.5.0.1
|
||||
@@ -11,18 +11,16 @@ AC_PREREQ([2.12])
|
||||
|
||||
AC_DEFUN([AM_CONFIG_HEADER],
|
||||
[ifdef([AC_FOREACH],dnl
|
||||
- [dnl init our file count if it isn't already
|
||||
- m4_ifndef([_AM_Config_Header_Index], m4_define([_AM_Config_Header_Index], [0]))
|
||||
+ [
|
||||
dnl prepare to store our destination file list for use in config.status
|
||||
AC_FOREACH([_AM_File], [$1],
|
||||
[m4_pushdef([_AM_Dest], m4_patsubst(_AM_File, [:.*]))
|
||||
- m4_define([_AM_Config_Header_Index], m4_incr(_AM_Config_Header_Index))
|
||||
dnl and add it to the list of files AC keeps track of, along
|
||||
dnl with our hook
|
||||
AC_CONFIG_HEADERS(_AM_File,
|
||||
dnl COMMANDS, [, INIT-CMDS]
|
||||
[# update the timestamp
|
||||
-echo timestamp >"AS_ESCAPE(_AM_DIRNAME(]_AM_Dest[))/stamp-h]_AM_Config_Header_Index["
|
||||
+echo timestamp >"AS_ESCAPE(_AM_DIRNAME(]_AM_Dest[))/stamp-h"
|
||||
][$2]m4_ifval([$3], [, [$3]]))dnl AC_CONFIG_HEADERS
|
||||
m4_popdef([_AM_Dest])])],dnl
|
||||
[AC_CONFIG_HEADER([$1])
|
||||
|
||||
Notice also that when using CVS authentication method "ext", bootstrap
|
||||
will set the variable CVS_RSH to "ssh", unless it is already set to
|
||||
some other value.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
and with GNU autoconf 2.52 patched as follows:
|
||||
|
||||
This file is part of GNU tar.
|
||||
2001-09-15 Paul Eggert <eggert@twinsun.com>
|
||||
|
||||
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.
|
||||
Fix bug reported by Paul Townsend on AIX 4.3.3.0 with
|
||||
CFLAGS=-O4 or CFLAGS=-O5. In that case, the linker has a
|
||||
relaxed view of fatal errors, and AC_CHECK_LIB causes it to
|
||||
include libraries even when they don't exist.
|
||||
|
||||
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.
|
||||
* acheaders.m4 (AC_HEADER_DIRENT): Use AC_SEARCH_LIBS, not
|
||||
AC_CHECK_LIB, so that we don't use -ldir or -lx if we don't
|
||||
need it.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
* acspecific.m4 (AC_ISC_POSIX): Replace the old, crufty
|
||||
version with the version used by fileutils 4.1, except use
|
||||
AC_SEARCH_LIBS, not AC_CHECK_LIB, so that we don't use
|
||||
-lcposix if we don't need it.
|
||||
|
||||
===================================================================
|
||||
RCS file: acheaders.m4,v
|
||||
retrieving revision 2.52
|
||||
retrieving revision 2.52.0.1
|
||||
diff -pu -r2.52 -r2.52.0.1
|
||||
--- acheaders.m4 2001/07/03 14:19:09 2.52
|
||||
+++ acheaders.m4 2001/09/16 02:53:51 2.52.0.1
|
||||
@@ -158,9 +158,9 @@ ac_header_dirent=$ac_hdr; break])
|
||||
done
|
||||
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
|
||||
if test $ac_header_dirent = dirent.h; then
|
||||
- AC_CHECK_LIB(dir, opendir, LIBS="$LIBS -ldir")
|
||||
+ AC_SEARCH_LIBS(opendir, dir)
|
||||
else
|
||||
- AC_CHECK_LIB(x, opendir, LIBS="$LIBS -lx")
|
||||
+ AC_SEARCH_LIBS(opendir, x)
|
||||
fi
|
||||
])# AC_HEADER_DIRENT
|
||||
|
||||
===================================================================
|
||||
RCS file: acspecific.m4,v
|
||||
retrieving revision 2.52
|
||||
retrieving revision 2.52.0.1
|
||||
diff -pu -r2.52 -r2.52.0.1
|
||||
--- acspecific.m4 2001/06/15 17:46:01 2.52
|
||||
+++ acspecific.m4 2001/09/16 02:53:51 2.52.0.1
|
||||
@@ -993,28 +993,7 @@ fi
|
||||
# AC_ISC_POSIX
|
||||
# ------------
|
||||
AC_DEFUN([AC_ISC_POSIX],
|
||||
-[AC_REQUIRE([AC_PROG_CC])dnl
|
||||
-AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl
|
||||
-AC_BEFORE([$0], [AC_RUN_IFELSE])dnl
|
||||
-AC_MSG_CHECKING([for POSIXized ISC])
|
||||
-if test -d /etc/conf/kconfig.d &&
|
||||
- grep _POSIX_VERSION [/usr/include/sys/unistd.h] >/dev/null 2>&1
|
||||
-then
|
||||
- AC_MSG_RESULT([yes])
|
||||
- ISC=yes # If later tests want to check for ISC.
|
||||
- AC_DEFINE(_POSIX_SOURCE, 1,
|
||||
- [Define if you need to in order for stat and other things to
|
||||
- work.])
|
||||
- if test "$GCC" = yes; then
|
||||
- CC="$CC -posix"
|
||||
- else
|
||||
- CC="$CC -Xp"
|
||||
- fi
|
||||
-else
|
||||
- AC_MSG_RESULT([no])
|
||||
- ISC=
|
||||
-fi
|
||||
-])# AC_ISC_POSIX
|
||||
+[AC_SEARCH_LIBS(strerror, cposix)])
|
||||
|
||||
|
||||
# AC_XENIX_DIR
|
||||
|
||||
136
THANKS
136
THANKS
@@ -1,19 +1,11 @@
|
||||
GNU tar THANKS file
|
||||
|
||||
Public domain tar was written by John Gilmore, with contributions
|
||||
from Henry Spencer, Fred Fish, Ian Darwin, Geoff Collyer, Stan Barber,
|
||||
Guy Harris, Dave Brower, Richard Todd, Michael Rendell, Stu Heiss and
|
||||
Rich $alz. The FSF version, named GNU tar, was derived from PDTAR by
|
||||
Jay Fenlason and Joy Kendall, and was maintained in turn by François
|
||||
Pinard, Paul Eggert and Sergey Poznyakoff.
|
||||
|
||||
Many people further contributed to GNU tar by reporting problems,
|
||||
suggesting various improvements or submitting actual code. Here is a
|
||||
list of these people. Help me keep it complete and exempt of errors.
|
||||
See various ChangeLogs for a detailed description of contributions.
|
||||
GNU tar has originally been written by Graham Todd. Many people
|
||||
further contributed to GNU tar by reporting problems, suggesting
|
||||
various improvements or submitting actual code. Here is a list of
|
||||
these people. Help me keep it complete and exempt of errors.
|
||||
|
||||
Aage Robeck aagero@ifi.uio.no
|
||||
Adye, TJ (Tim) T.J.Adye@rl.ac.uk
|
||||
Akiko Matsushita matusita@sra.co.jp
|
||||
Alan Bawden Alan@lcs.mit.edu
|
||||
Alan Cox alan@cymru.net
|
||||
@@ -33,7 +25,6 @@ Andreas Haumer andreas@vlsivie.tuwien.ac.at
|
||||
Andreas Jaeger aj@arthur.pfalz.de
|
||||
Andreas Koppenhoefer koppenh@trick.informatik.uni-stuttgart.de
|
||||
Andreas Reuter ar205@bonzo.geowiss.nat.tu-bs.de
|
||||
Andreas Schuldei andreas@schuldei.org
|
||||
Andreas Schwab schwab@issan.informatik.uni-dortmund.de
|
||||
Andrew A. Ivanov ivanov@mics.msu.su
|
||||
Andrew J. Schorr schorr@ead.dsa.com
|
||||
@@ -43,7 +34,7 @@ Andy Gay andy@rdl.co.uk
|
||||
Antonio Jose Coutinho ajc@di.uminho.pt
|
||||
Ariel Faigon ariel@engr.sgi.com
|
||||
Arne Wichmann aw@math.uni-sb.de
|
||||
Arnold Robbins arnold@gnu.org
|
||||
Arnold Robbins arnold@gnu.ai.mit.edu
|
||||
Art Isbell aisbell@cubicsol.com
|
||||
Axel Boldt boldt@math.ucsb.edu
|
||||
Axel Habermann kiwi@belly.in-berlin.de
|
||||
@@ -53,11 +44,9 @@ Bela Lubkin filbo@armory.com
|
||||
Ben A. Mesander ben@piglet.cr.usgs.gov
|
||||
Benedikt Stockebrand benedikt@devnull.ruhr.de
|
||||
Bennett Todd bet@mordor.com
|
||||
Benno Schulenberg benno@nietvergeten.nl
|
||||
Benny Holmgren benny@hgs.se
|
||||
Bernard Chen bern@cs.ucla.edu
|
||||
Bernard Derval derval@iro.umontreal.ca
|
||||
Bernhard Rosenkraenzer bero@redhat.de
|
||||
Bo Nygaard Bai bai@iesd.auc.dk
|
||||
Bob Kaehms kaehms@was.archive.org
|
||||
Bob Mende Pie mende@piecomputer.rutgers.edu
|
||||
@@ -68,23 +57,21 @@ Brian Perkins bperkins@netspace.org
|
||||
Brian R. Smith brian@cygnus.com
|
||||
Bruce Evans bde@runx.oz.au
|
||||
Bruce Jerrick bruce@cse.ogi.edu
|
||||
Bruno Haible haible@ilog.fr
|
||||
Bryan Ford baford@mit.edu
|
||||
Bruno Haible haible@ma2s2.mathematik.uni-karlsruhe.de
|
||||
Bryant Fujimoto fujimoto@denali.chem.washington.edu
|
||||
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
|
||||
Carsten Heyl heyl@nads.de
|
||||
Catrin Urbanneck cur@gppc.de
|
||||
Cesar Romani romani@ifm.uni-hamburg.de
|
||||
Chad Hurwitz churritz@cts.com
|
||||
Chance Reschke creschke@usra.edu
|
||||
Charles Fu ccwf@klab.caltech.edu
|
||||
Charles Lopes Charles.Lopes@infm.ulst.ac.uk
|
||||
Charles M. Hannum mycroft@gnu.org
|
||||
Charles M. Hannum mycroft@gnu.ai.mit.edu
|
||||
Chip Salzenberg tct!chip
|
||||
Chris Arthur csa@gnu.org
|
||||
Chris Arthur csa@gnu.ai.mit.edu
|
||||
Chris F.M. Verberne verberne@prl.philips.nl
|
||||
Chris G. Demetriou cgd@sun-lamp.cs.berkeley.edu
|
||||
Chris Hopps sycom.mi.org!ro-chp!chopps
|
||||
@@ -92,12 +79,10 @@ Chris Metcalf metcalf@catfish.lcs.mit.edu
|
||||
Chris Ransom chris@quests.com
|
||||
Christian Callsen Christian.Callsen@eng.sun.com
|
||||
Christian Kirsch ck@held.mind.de
|
||||
Christian Laubscher christian.laubscher@tiscalinet.ch
|
||||
Christian T. Dum ctd@mpe-garching.mpg.de
|
||||
Christian von Roques roques@pond.sub.org
|
||||
Christoph Litauer litauer@mailhost.uni-koblenz.de
|
||||
Christophe Colle colle@krtkg1.rug.ac.be
|
||||
Christophe Kalt Christophe.Kalt@kbcfp.com
|
||||
Christopher T. Johnson cjohnson@camelot.com
|
||||
Christopher Vickery vickery@ipc1.cs.qc.edu
|
||||
Claude Scarpelli claude@genethon.fr
|
||||
@@ -111,7 +96,7 @@ Dale R. Worley worley@world.std.com
|
||||
Dale Wiles wiles@geordi.calspan.com
|
||||
Dan Bloch dan@transarc.com
|
||||
Dan Reish dreish@izzy.net
|
||||
Daniel Hagerty hag@gnu.org
|
||||
Daniel Hagerty hag@gnu.ai.mit.edu
|
||||
Daniel Quinlan quinlan@pathname.com
|
||||
Daniel R. Guilderson d.guilderson@ma30.bull.com
|
||||
Daniel S. Barclay daniel@compass-da.com
|
||||
@@ -120,7 +105,6 @@ Danny R. Johnston danny@cs.weber.edu
|
||||
Dave Barr barr@math.psu.edu
|
||||
Dave Gentzel gentzel@nova.enet.dec.com
|
||||
Dave Gregorich dtg@ipac.caltech.edu
|
||||
David Brown davidb@davidb.org
|
||||
David J. MacKenzie djm@uunet.uu.net
|
||||
David Johnson David.W.Johnson@colorado.edu
|
||||
David K. Drum ccdavid@mizzou1.missouri.edu
|
||||
@@ -143,7 +127,7 @@ Dimitri Bougoulias opus@hol.gr
|
||||
Dimitris Fousekis dfousek@leon.nrcps.ariadne-t.gr
|
||||
Dirk Herr-Hoyman hoymand@gate.net
|
||||
Don Bennett dpb@netcom.com
|
||||
Donald B Gordon dbgordon@gnu.org
|
||||
Donald B Gordon dbgordon@gnu.ai.mit.edu
|
||||
Donald H. Locker dhl@spuf1d83.lcp.chrysler.com
|
||||
Douglas Scott doug@foxtrot.ccmrc.ucsb.edu
|
||||
Drew Sullivan drew@sni.ca
|
||||
@@ -158,7 +142,6 @@ Elmar Heeb heeb@itp.ethz.ch
|
||||
Elmer Fittery elmerf@ptw.com
|
||||
Eric Backus ericb@lsid.hp.com
|
||||
Eric Benson eb@amazon.com
|
||||
Eric Blake ebb9@byu.net
|
||||
Eric M. Boehm Eric.M.Boehm@optimumtech.com
|
||||
Eric Norum eric@ee.ualberta.ca
|
||||
Erich Stefan Boleyn erich@uruk.org
|
||||
@@ -167,15 +150,13 @@ Erik D. Frederick edf@deckard.mc.duke.edu
|
||||
Esa Karell karell@cs.helsinki.fi
|
||||
Ezra Peisach epeisach@mit.edu
|
||||
Fabio d'Alessi cars@civ.bio.unipd.it
|
||||
Frank Heckenbach frank@g-n-u.de
|
||||
Frank Koenen koenfr@lidp.com
|
||||
Franz-Werner Gergen gergen@edvulx.mpi-stuttgart.mpg.de
|
||||
François Pinard pinard@iro.umontreal.ca
|
||||
Fran<EFBFBD>ois Pinard pinard@iro.umontreal.ca
|
||||
Fritz Elfert fritz@fsun.triltsch.de
|
||||
George Chyu gschyu@ccgate.dp.beckman.com
|
||||
Gerben Wierda gerben@rna.indiv.nluug.nl
|
||||
Gerd Knorr kraxel@cs.tu-berlin.de
|
||||
Gerhard Poul gpoul@gnu.org
|
||||
Giorgio Signorini signo@chim.unifi.it
|
||||
Graham Whitted gbw@sgrail.com
|
||||
Grant McDorman grant@isgtec.com
|
||||
@@ -184,26 +165,21 @@ Greg Chung gchung@caip.rutgers.edu
|
||||
Greg Hudson ghudson@mit.edu
|
||||
Greg Maples greg@clari.net
|
||||
Greg McGary gkm@cstone.net
|
||||
Greg Schafer gschafer@zip.com.au
|
||||
Göran Uddeborg gvran@uddeborg.pp.se
|
||||
Gürkan Karaman karaman@dssgmbh.de
|
||||
G<EFBFBD>ran Uddeborg gvran@uddeborg.pp.se
|
||||
Hans Guerth 100664.3101@compuserve.com
|
||||
Hansjörg Lipp hjlipp@web.de
|
||||
Harald König koenig@tat.physik.uni-tuebingen.de
|
||||
Harald K<>nig koenig@tat.physik.uni-tuebingen.de
|
||||
Harald Milz hm@seneca.ix.de
|
||||
Heiko Schinke mdqac@biochemtech.uni-halle.de
|
||||
Heiko Schlichting heiko@fu-berlin.de
|
||||
Helmut Waitzmann Helmut.Waitzmann@web.de
|
||||
Henrik Bakman hb@csd.uu.se
|
||||
Hernan Prieto Schmidt hernan@pea.usp.br
|
||||
Hiroyuki Bessho bsh@grotto.iijnet.or.jp
|
||||
Holger Teutsch holger@hotbso.rhein-main.de
|
||||
Hugh Secker-Walker hugh@ear.mit.edu
|
||||
Hunyue Yau hunyue.yau@picksys.com
|
||||
Ian Jackson ijackson@gnu.org
|
||||
Ian Jackson ijackson@gnu.ai.mit.edu
|
||||
Ian Lance Taylor ian@cygnus.com
|
||||
Ian T. Zimmerman itz@crl.com
|
||||
Ian Turner ian@zmanda.com
|
||||
Indra Singhal indra@synoptics.com
|
||||
J. Dean Brock brock@cs.unca.edu
|
||||
J.J. Bailey jjb@jagware.bcc.com
|
||||
@@ -220,8 +196,7 @@ Jan Djarv jan.djarv@mbox200.swipnet.se
|
||||
Janice Burton r06a165@bcc25.kodak.com
|
||||
Janne Snabb snabb@niksula.hut.fi
|
||||
Jason R. Mastaler jason@webmaster.net
|
||||
Jason Armistead Jason.Armistead@otis.com
|
||||
Jay Fenlason hack@gnu.org
|
||||
Jay Fenlason hack@gnu.ai.mit.edu
|
||||
Jean-Michel Soenen soenen@lectra.fr
|
||||
Jean-Ph. Martin-Flatin syj@ecmwf.int
|
||||
Jean-loup Gailly jloup@chorus.fr
|
||||
@@ -249,16 +224,13 @@ John David Anglin dave@hiauly1.hia.nrc.ca
|
||||
John Gilmore gnu@toad.com
|
||||
John J. Szetela johns@angelo.amd.com
|
||||
John L. Chmielewski jlc@attmail.com
|
||||
John L. Males jlmales@yahoo.com
|
||||
John Oleynick juo@klinzhai.rutgers.edu
|
||||
John R. Vanderpool fish@daacdev1.stx.com
|
||||
John Rouillard rouilj@cs.umb.edu
|
||||
John Thomas McDole john.thomas.mcdole@nagra.com
|
||||
Jon Lewis jlewis@inorganic5.fdt.net
|
||||
Jonathan I. Kamens jik@cam.ov.com
|
||||
Jonathan N. Sherman sysjns@etacrs1.safb.af.mil
|
||||
Jonathan Thornburg thornbur@theory.physics.ubc.ca
|
||||
Josef Bauer Josef.Bauer@mchp.siemens.de
|
||||
Joseph E. Sacco jsacco@ssl.com
|
||||
Joshua R. Poulson jrp@plaza.ds.adp.com
|
||||
Joutsiniemi Tommi Il tj75064@cs.tut.fi
|
||||
@@ -266,18 +238,15 @@ Joy Kendall jak8@world.std.com
|
||||
Judy Ricker jricker@gdstech.grumman.com
|
||||
Juha Sarlin juha@tds.kth.se
|
||||
Jurgen Botz jbotz@orixa.mtholyoke.edu
|
||||
J<EFBFBD>rgen L<>ters jlueters@t-online.de
|
||||
J<EFBFBD>rgen Reiss reiss@psychologie.uni-wuerzburg.de
|
||||
Jyh-Shyang Wang erik@vsp.ee.nctu.edu.tw
|
||||
Jörg Schilling schilling@fokus.fraunhofer.de
|
||||
Jörg Weule weule@cs.uni-duesseldorf.de
|
||||
Jörg Weilbier gnu@weilbier.net
|
||||
Jörgen Hågg Jorgen.Hagg@axis.se
|
||||
Jörgen Weigert jw@suse.de
|
||||
Jürgen Lüters jlueters@t-online.de
|
||||
Jürgen Reiss reiss@psychologie.uni-wuerzburg.de
|
||||
J<EFBFBD>rg Weule weule@cs.uni-duesseldorf.de
|
||||
J<EFBFBD>rgen H<>gg Jorgen.Hagg@axis.se
|
||||
Kai Petzke wpp@marie.physik.tu-berlin.de
|
||||
Kai Schlichting kai@computel.com
|
||||
Karl Berry karl@cs.umb.edu
|
||||
Karl Heuer kwzh@gnu.org
|
||||
Karl Heuer kwzh@gnu.ai.mit.edu
|
||||
Karl Vogel vogelke@c-17igp.wpafb.af.mil
|
||||
Karlos Z. Smith kazen@viptx.net
|
||||
Karsten Thygesen karthy@kom.auc.dk
|
||||
@@ -297,13 +266,10 @@ Larry Creech lcreech@lonestar.rcclub.org
|
||||
Larry Schwimmer rosebud@cyclone.stanford.edu
|
||||
Laurent Caillat-Vallet caillat@noe.lyon.cemagref.fr
|
||||
Laurent Sainte-Marthe smarthe@genethon.fr
|
||||
Leland Lucius llucius@tiny.net
|
||||
Les Mikesell les@mcs.com
|
||||
Loren J. Rittle rittle@comm.mot.com
|
||||
Loïc Prylli Loic.Prylli@lip.ens-lyon.fr
|
||||
Lo<EFBFBD>c Prylli Loic.Prylli@lip.ens-lyon.fr
|
||||
Luke Mewburn lukem@connect.com.au
|
||||
Machael Stone mstone@cs.loyola.edu
|
||||
Mads Martin Joergensen mmj@suse.de
|
||||
Manfred Weichel Manfred.Weichel@mch.sni.de
|
||||
Manuel Munier Manuel.Munier@loria.fr
|
||||
Marc Boucher marc@cam.org
|
||||
@@ -317,9 +283,8 @@ Mark Kollert Mark.Kollert@oi42.kwu.siemens.de
|
||||
Mark W. Eichin eichin@cygnus.com
|
||||
Markus Kuhn mskuhn@cip.informatik.uni-erlangen.de
|
||||
Martin Bellenberg sunsoft@ifm.uni-hamburg.de
|
||||
Martin Goik goik@HDM-Stuttgart.de
|
||||
Martin Goik goma0002@fh-karlsruhe.de
|
||||
Martin Mares mj@k332.feld.cvut.cz
|
||||
Martin Simmons ZYHYLCRMZPRP@spammotel.com
|
||||
Marty Leisner leisner@eso.mc.xerox.com
|
||||
Massimo Dal Zotto dz@cs.unitn.it
|
||||
Mats Lofkvist d87-mal@nada.kth.se
|
||||
@@ -328,8 +293,7 @@ Matthew J. D'Errico doc@deathstar.lis.cch.com
|
||||
Matti Aarnio mea@utu.fi
|
||||
Max Hailperin max@nic.gac.edu
|
||||
Maxime Taksar mmt@redbrick.com
|
||||
Melissa O'Neill oneill@cs.sfu.ca
|
||||
Melissa Weisshaus melissa@gnu.org
|
||||
Melissa Weisshaus melissa@gnu.ai.mit.edu
|
||||
Michael Dietrich mdt@is.in-berlin.de
|
||||
Michael Ellis bosun@aquarius.seaoar.uvic.ca
|
||||
Michael Giddings giddings@whitewater.chem.wisc.edu
|
||||
@@ -353,12 +317,11 @@ Mike Walker M.D.Walker@larc.nasa.gov
|
||||
Milan Hodoscek milan@kihp6.ki.si
|
||||
Minh Tran-Le tranle@intellicorp.com
|
||||
Mitsuaki Masuhara masuhara@mcprv.mec.mei.co.jp
|
||||
Nate Eldredge nate@cs.hmc.edu
|
||||
Neil Faulks neil@dcs.kcl.ac.uk
|
||||
Neil Jerram nj104@cus.cam.ac.uk
|
||||
Nelson H.F. Beebe beebe@math.utah.edu
|
||||
Nick Barron nikb@cix.compulink.co.uk
|
||||
Noah Friedman friedman@gnu.org
|
||||
Noah Friedman friedman@prep.ai.mit.edu
|
||||
Noel Cragg noel@red-bean.com
|
||||
Norbert Kiesel norbert@rwthi3.informatik.rwth-aachen.de
|
||||
Olaf Schlueter olaf@toppoint.de
|
||||
@@ -391,11 +354,8 @@ Piercarlo Grandi piercarl@sabi.demon.co.uk
|
||||
Pierce Cantrell cantrell@ee.tamu.edu
|
||||
R. Kent Dybvig dyb@cadence.bloomington.in.us
|
||||
R. Scott Butler butler@prism.es.dupont.com
|
||||
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
|
||||
Ralf Wildenhues Ralf.Wildenhues@gmx.de
|
||||
Ralf S. Engelschall rse@engelschall.com
|
||||
Rainer Orth ro@thp.uni-koeln.de
|
||||
Ralf Suckow suckow@contrib.de
|
||||
Ralph Corderoy ralph@inputplus.co.uk
|
||||
Ralph Schleicher rs@purple.ul.bawue.de
|
||||
Randy Bias randyb@edge.edge.net
|
||||
Ray Dassen jdassen@wi.leidenuniv.nl
|
||||
@@ -403,11 +363,11 @@ Reuben J. Ravago reuben@asti.dost.gov.ph
|
||||
Reuben Sumner rasumner@undergrad.math.uwaterloo.ca
|
||||
Ricardo Marek ricky@ornet.co.il
|
||||
Richard Deal deal@xi.cs.fsu.edu
|
||||
Richard J. Kettlewell rjk@greenend.org.uk
|
||||
Richard J. Kettlewell richard@elmail.co.uk
|
||||
Richard Lloyd R.K.Lloyd@csc.liv.ac.uk
|
||||
Richard O'Neill richard@nexus.vnus.bc.ca
|
||||
Richard Sims rbs@acs.bu.edu
|
||||
Richard Stallman rms@gnu.org
|
||||
Richard Stallman rms@gnu.ai.mit.edu
|
||||
Richard Westerik richardw@bssi.nl
|
||||
Rick Emerson rick@ssg.com
|
||||
Rob Parry rparry@hydrolab.arsusda.gov
|
||||
@@ -426,18 +386,18 @@ Rod Buchanan rod.buchanan@kratos.co.uk
|
||||
Rod Thompson rodt@synopsys.com
|
||||
Roderich Schupp roderich@syntec.m.eunet.de
|
||||
Rodney Brown RBrown@cocam.com.au
|
||||
Roland McGrath roland@gnu.org
|
||||
Roland McGrath roland@gnu.ai.mit.edu
|
||||
Roland Schemers III schemers@vela.acs.oakland.edu
|
||||
Rolf Niepraschk niepraschk@chbrb.berlin.ptb.de
|
||||
Roman Czyborra czyborra@cs.tu-berlin.de
|
||||
Roman Gollent roman@portal.stwing.upenn.edu
|
||||
Roman Czyborra czyborra@cs.tu-berlin.de
|
||||
Ron Guilmette rfg@netcom.com
|
||||
Roy Marantz marantz@nbcs.rutgers.edu
|
||||
Russ Evans e_gs18@ub.nmh.ac.uk
|
||||
Russell Cattelan cattelan@thebarn.com
|
||||
Ryutaro Susukita susukita@pn.scphys.kyoto-u.ac.jp
|
||||
Sakai Kiyotaka ksakai@netwk.ntt-at.co.jp
|
||||
Sam Richards sam@blueskyprod.com
|
||||
Sakai Kiyotaka ksakai@netwk.ntt-at.co.jp
|
||||
Santiago Vila Doncel sanvila@unex.es
|
||||
Sarah Quady squady@warp10.keck.hawaii.edu
|
||||
Saul Lubkin lubkin@cs.rochester.edu
|
||||
@@ -450,10 +410,9 @@ Serge Granik serge@euler.berkeley.edu
|
||||
Seth Robertson seth@ctr.columbia.edu
|
||||
Sherwood Botsford sherwood@space.ualberta.ca
|
||||
Simon Wright simon.j.wright@gecm.com
|
||||
Simon Wright simon@pogner.demon.co.uk
|
||||
Sisira Jayasinghe sisira.jayasinghe@sdrc.com
|
||||
Skip Montanaro skip@mojam.com http://www.musi-cal.com/~skip/
|
||||
Solar Designer solar@openwall.com
|
||||
Skip Montanaro skip@automatrix.com
|
||||
Simon Wright simon@pogner.demon.co.uk
|
||||
Stefan Skoglund sp2stes1@ida.his.se
|
||||
Steffen Stempel stempel@ira.uka.de
|
||||
Stephen Gildea gildea@intouchsys.com
|
||||
@@ -462,14 +421,13 @@ Stephen Saroff saroff@msc.edu
|
||||
Stuart Kemp skemp@bmc.com
|
||||
Stuart Poulin stuart@indsys.com
|
||||
Sven Verdoolaege skimo@breughel.ufsia.ac.be
|
||||
Sylvain Rougier un@grolier.fr
|
||||
Sylvain ROUGIER un@grolier.fr
|
||||
Tarang Kumar Patel mombasa@ptolemy.arc.nasa.gov
|
||||
Ted Rule Ted_Rule@flextech.co.uk
|
||||
The King elvis@gnu.org
|
||||
Thomas metaf4@users.askja.de
|
||||
Thomas Bushnell n/BSG thomas@gnu.org
|
||||
The King elvis@gnu.ai.mit.edu
|
||||
Thomas Bushnell n/BSG thomas@gnu.ai.mit.edu
|
||||
Thomas K<EFBFBD>nig Thomas.Koenig@ciw.uni-karlsruhe.de
|
||||
Thomas Krebs krebs@faps.uni-erlangen.de
|
||||
Thomas König Thomas.Koenig@ciw.uni-karlsruhe.de
|
||||
Thomas M. Browder Jr. browder@use1.eglin.af.mil
|
||||
Thomas Priesner priesner@flo.sh.bosch.de
|
||||
Thomas Waas waas@echild.aiss.de
|
||||
@@ -482,45 +440,37 @@ Tim P. Starrin noid@cyborg.larc.nasa.gov
|
||||
Tim Ramsey tar@ksu.ksu.edu
|
||||
Tim Rylance tkr@puffball.demon.co.uk
|
||||
Tim Towers tzt@uniplex.co.uk
|
||||
Timothy Fossum fossum@cs.uwp.edu
|
||||
Timothy J. Lee timlee@netcom.com
|
||||
Timothy Fossum fossum@cs.uwp.edu
|
||||
Tito Flagella tito@di.unipi.it
|
||||
Todd Vierling tv@duh.org
|
||||
Tom Popovitch tpop@informix.com
|
||||
Tom Quinn trq@astro.washington.edu
|
||||
Tom Tromey tromey@drip.colorado.edu
|
||||
Tor Lillqvist tml@hemuli.tte.vtt.fi
|
||||
Torbjorn Granlund tege@sics.se
|
||||
Torkel Hasle torkel@bibsyst.no
|
||||
Torsten Lull tlupi@gppc.de
|
||||
Toshiaki Nishi toshi@sss.osa.sharp.co.jp
|
||||
Travis L. Priest T.L.Priest@larc.nasa.gov
|
||||
Troy Rudolph rudtr01@cai.com
|
||||
Tsutomu Yamada tsutomu@sra.co.jp
|
||||
Ulrich Drepper drepper@gnu.org
|
||||
Ulrich Drepper drepper@gnu.ai.mit.edu
|
||||
Van Snyder vsnyder@math.jpl.nasa.gov
|
||||
Vic Abell abe@cc.purdue.edu
|
||||
Victor J. Griswold vgris@aironet.com
|
||||
Ville Herva v@iki.fi
|
||||
Vince Del Vecchio vdelvecc@inmet.com
|
||||
W. Phillip Moore wpm@morgan.com
|
||||
Warner Losh imp@boulder.parcplace.com
|
||||
Warren Dodge warrend@sptekwv3.wv.tek.com
|
||||
Wayne Christopher wayne@icemcfd.com
|
||||
Werner Almesberger werner.almesberger@lrc.di.epfl.ch
|
||||
William Bader william@nscs.fast.net
|
||||
William Bader wbader@pluto.csee.lehigh.edu
|
||||
William J. Eaton wje@hoffman.rstnu.bcm.tmc.edu
|
||||
William Kucharski kucharsk@netcom.com
|
||||
Wojciech Polak polak@gnu.org
|
||||
Wlodzimierz Jan Martin wjm@pg.gda.pl
|
||||
Wolfgang Rupprecht wolfgang@wsrcc.com
|
||||
Wolfram Gloger Wolfram.Gloger@dent.med.uni-muenchen.de
|
||||
Wolfram Kleff bugreport@wkleff.intergenia.de
|
||||
Wolfram Wagner ww@mpi-sb.mpg.de
|
||||
Włodzimierz Jan Martin wjm@pg.gda.pl
|
||||
Yasushi Suzudo SGR00413@niftyserve.or.jp
|
||||
Yasushi Suzudo ysuzudo@mail.asiandevbank.org
|
||||
Yu-Min Liang min@taz.ho.att.com
|
||||
|
||||
|
||||
;;;; Local Variables:
|
||||
;;;; mode: Fundamental
|
||||
;;;; coding: utf-8
|
||||
;;;; End:
|
||||
maximum entropy entropy@zippy.bernstein.com
|
||||
|
||||
76
TODO
76
TODO
@@ -1,73 +1,5 @@
|
||||
Suggestions for improving GNU tar.
|
||||
From: Roesinger Eric <ROESINGE@tce.com>
|
||||
Date: Sat, 28 Jul 2001 18:43:43 -0500
|
||||
|
||||
* Incorporate fixes from major distributions, e.g., Debian GNU/Linux.
|
||||
|
||||
* Add support for restoring file time stamps to sub-second resolution,
|
||||
if the file system supports this.
|
||||
|
||||
* Add support for restoring the attributes of symbolic links, for
|
||||
OSes like FreeBSD that have the lutimes and lchmod functions.
|
||||
|
||||
* --append should bail out if the two archives are of different types.
|
||||
|
||||
* Add support for GNU private keywords in POSIX 1003.1-2001 headers,
|
||||
so that the GNU extensions (--incremental, --label and
|
||||
--multi-volume) may be used with POSIX archives.
|
||||
|
||||
* Add support for a 'pax' command that conforms to POSIX 1003.1-2001.
|
||||
This would unify paxutils with tar.
|
||||
|
||||
* Interoperate better with Joerg Schilling's star implementation.
|
||||
|
||||
* Add an option to remove files that compare successfully.
|
||||
|
||||
From: Roesinger Eric <ROESINGE@tce.com>
|
||||
Date: Sat, 28 Jul 2001 18:43:43 -0500
|
||||
|
||||
It would be useful to be able to use '--remove-files' with '--diff',
|
||||
to remove all files that compare successfully, when verifying a backup.
|
||||
|
||||
* Add tests for the new functonality.
|
||||
|
||||
* Consider this:
|
||||
|
||||
From: Dennis Pund
|
||||
Subject: TAR suggestion...
|
||||
Date: Wed, 1 May 2002 18:26:36 -0500 (EST)
|
||||
|
||||
What I would like to do is:
|
||||
|
||||
foo my.tar.gz | tar -xzOf - | tar -cMf - -L 650000 - | bar
|
||||
|
||||
where 'foo' is a program that retrieves the archive and streams it
|
||||
to stdout and bar is a program that streams the stdin to CDR.
|
||||
|
||||
(http://mail.gnu.org/archive/html/bug-gnu-utils/2002-05/msg00022.html)
|
||||
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
end:
|
||||
It would be useful to be able to use '--remove-files' with '--diff',
|
||||
to remove all files that compare successfully, when verifying a backup.
|
||||
|
||||
426
bootstrap
426
bootstrap
@@ -1,426 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Bootstrap this package from CVS.
|
||||
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Written by Paul Eggert and Sergey Poznyakoff.
|
||||
|
||||
package=tar
|
||||
|
||||
# Translation Project URL, for the registry of all projects.
|
||||
TP_URL='http://www.iro.umontreal.ca/translation/registry.cgi?domain='
|
||||
|
||||
# Ensure file names are sorted consistently across platforms.
|
||||
# Also, ensure diagnostics are in English, e.g., "wget --help" below.
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: $0 [--gnulib-srcdir=DIR][--paxutils-srcdir=DIR][--cvs-auth=AUTH-METHOD][--cvs-user=USERNAME][--no-po]
|
||||
Options are:
|
||||
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
|
||||
sources reside. Use this if you already
|
||||
have paxutils sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
|
||||
sources reside. Use this if you already
|
||||
have gnulib sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
--cvs-auth=METHOD Set the CVS access method used for downloading
|
||||
gnulib files. METHOD is one of the keywords
|
||||
accepted by cvs -d option (see info cvs
|
||||
repository).
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
--no-po Do not download po files.
|
||||
--update-po[=LANG] Update po file(s) and exit.
|
||||
|
||||
If the file \`.bootstrap' exists in the current working directory, its
|
||||
contents is read, comments and empty lines removed, shell variables expanded
|
||||
and the result is prepended to the command line options.
|
||||
|
||||
Running without arguments will suffice in most cases. It is equivalent
|
||||
to
|
||||
|
||||
./bootstrap --cvs-auth=pserver
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Read configuration file
|
||||
if [ -r .bootstrap ]; then
|
||||
echo "$0: Reading configuration file .bootstrap"
|
||||
eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
|
||||
fi
|
||||
|
||||
# Parse options.
|
||||
|
||||
DOWNLOAD_PO=yes
|
||||
for option
|
||||
do
|
||||
case $option in
|
||||
--help)
|
||||
usage
|
||||
exit;;
|
||||
--gnulib-srcdir=*)
|
||||
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
|
||||
--paxutils-srcdir=*)
|
||||
PAXUTILS_SRCDIR=`expr "$option" : '--paxutils-srcdir=\(.*\)'`;;
|
||||
--cvs-auth=*)
|
||||
CVS_AUTH=`expr "$option" : '--cvs-auth=\(.*\)'`;;
|
||||
--cvs-user=*)
|
||||
CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
|
||||
--no-po)
|
||||
DOWNLOAD_PO=no;;
|
||||
--update-po=*)
|
||||
DOWNLOAD_PO=`expr "$option" : '--update-po=\(.*\)'`;;
|
||||
--update-po)
|
||||
DOWNLOAD_PO=only;;
|
||||
*)
|
||||
echo >&2 "$0: $option: unknown option"
|
||||
exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Get translations.
|
||||
|
||||
get_translations() {
|
||||
subdir=$1
|
||||
domain=$2
|
||||
po_file=$3
|
||||
|
||||
echo "$0: getting translations into $subdir for $domain..."
|
||||
|
||||
case $po_file in
|
||||
'') (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`);;
|
||||
esac &&
|
||||
|
||||
$WGET_COMMAND -O "$subdir/$domain.html" "$TP_URL$domain" &&
|
||||
|
||||
sed -n 's|.*"http://[^"]*/translation/teams/PO/\([^/"]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\1.\2|p' <"$subdir/$domain.html" |
|
||||
sort -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
|
||||
awk -F. '
|
||||
{ if (lang && $1 != lang) print lang, ver }
|
||||
{ lang = $1; ver = substr($0, index($0, ".") + 1) }
|
||||
END { if (lang) print lang, ver }
|
||||
' |
|
||||
awk -v domain="$domain" -v po_file="$po_file" -v subdir="$subdir" '
|
||||
{
|
||||
lang = $1
|
||||
if (po_file && po_file != (lang ".po")) next
|
||||
|
||||
# Work around bugs in translations uncovered by gettext 0.15.
|
||||
# This workaround can be removed once the translations are fixed.
|
||||
if (lang == "hu" || lang == "zh_TW") next
|
||||
|
||||
ver = $2
|
||||
urlfmt = ""
|
||||
printf "$WGET_COMMAND -O %s/%s.po 'http://www.iro.umontreal.ca/translation/teams/PO/%s/%s-%s.%s.po' &&\n", subdir, lang, lang, domain, ver, lang
|
||||
}
|
||||
END { print ":" }
|
||||
' |
|
||||
sh &&
|
||||
ls "$subdir"/*.po | sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
|
||||
rm "$subdir/$domain.html"
|
||||
}
|
||||
|
||||
update_po() {
|
||||
if [ $# = 1 ]; then
|
||||
case $1 in
|
||||
*.po) POFILE=$1;;
|
||||
*) POFILE=${1}.po;;
|
||||
esac
|
||||
get_translations po $package "$POFILE"
|
||||
else
|
||||
get_translations po $package
|
||||
fi
|
||||
}
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
no) ;;
|
||||
*)
|
||||
case `wget --help` in
|
||||
*'--no-cache'*)
|
||||
no_cache='--no-cache';;
|
||||
*'--cache=on/off'*)
|
||||
no_cache='--cache=off';;
|
||||
*)
|
||||
no_cache='';;
|
||||
esac
|
||||
|
||||
WGET_COMMAND="wget -nv $no_cache"
|
||||
export WGET_COMMAND
|
||||
esac
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
only) update_po
|
||||
exit
|
||||
;;
|
||||
no|yes) ;;
|
||||
*) update_po $DOWNLOAD_PO
|
||||
exit
|
||||
esac
|
||||
|
||||
|
||||
echo "$0: Bootstrapping CVS $package..."
|
||||
|
||||
build_cvs_prefix() {
|
||||
CVS_PREFIX=:${1}:
|
||||
if [ "${2}" != - ]; then
|
||||
CVS_PREFIX=${CVS_PREFIX}${2}@
|
||||
fi
|
||||
if [ "$1" = "ext" ]; then
|
||||
if [ -z "${CVS_RSH}" ]; then
|
||||
CVS_RSH=ssh
|
||||
export CVS_RSH
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# checkout package
|
||||
checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
trap exit 1 2 13 15
|
||||
trap 'rm -fr $1; exit 1' 0
|
||||
|
||||
case "${CVS_AUTH-pserver}" in
|
||||
pserver) build_cvs_prefix pserver ${CVS_USER:-anonymous}
|
||||
;;
|
||||
gserver|server)
|
||||
build_cvs_prefix $CVS_AUTH ${CVS_USER--}
|
||||
;;
|
||||
ext) build_cvs_prefix $CVS_AUTH ${CVS_USER--}
|
||||
;;
|
||||
*) echo "$0: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
cvs -q -d ${CVS_PREFIX}cvs.sv.gnu.org:/cvsroot/$1 co $1 || exit
|
||||
|
||||
trap - 0
|
||||
fi
|
||||
}
|
||||
|
||||
gnulib_modules=
|
||||
newline='
|
||||
'
|
||||
|
||||
get_modules() {
|
||||
new_gnulib_modules=`sed '/^[ ]*#/d; /^[ ]*$/d' $*`
|
||||
case $gnulib_modules,$new_gnulib_modules in
|
||||
?*,?*) new_gnulib_modules=$newline$new_gnulib_modules;;
|
||||
esac
|
||||
gnulib_modules=$gnulib_modules$new_gnulib_modules
|
||||
}
|
||||
|
||||
# Get paxutils files
|
||||
case ${PAXUTILS_SRCDIR--} in
|
||||
-) checkout paxutils
|
||||
PAXUTILS_SRCDIR=paxutils
|
||||
esac
|
||||
|
||||
if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
|
||||
get_modules $PAXUTILS_SRCDIR/gnulib.modules
|
||||
fi
|
||||
|
||||
# copy_files srcdir dstdir
|
||||
copy_files() {
|
||||
for file in `cat $1/DISTFILES`
|
||||
do
|
||||
case $file in
|
||||
"#*") continue;;
|
||||
esac
|
||||
dst=`echo $file | sed 's^.*/^^'`
|
||||
if [ $# -eq 3 ]; then
|
||||
case $dst in
|
||||
${3}*) ;;
|
||||
*) dst=${3}$dst;;
|
||||
esac
|
||||
fi
|
||||
echo "$0: Copying file $1/$file to $2/$dst"
|
||||
cp -p $1/$file $2/$dst
|
||||
done
|
||||
}
|
||||
|
||||
copy_files ${PAXUTILS_SRCDIR}/m4 m4
|
||||
echo "$0: Creating m4/paxutils.m4"
|
||||
(echo "# This file is generated automatically. Please, do not edit."
|
||||
echo "#"
|
||||
echo "AC_DEFUN([${package}_PAXUTILS],["
|
||||
cat ${PAXUTILS_SRCDIR}/m4/DISTFILES | sed '/^#/d;s/\(.*\)\.m4/pu_\1/' | tr a-z A-Z
|
||||
echo "])") > ./m4/paxutils.m4
|
||||
|
||||
if [ -d rmt ]; then
|
||||
:
|
||||
else
|
||||
mkdir rmt
|
||||
fi
|
||||
|
||||
for dir in doc rmt lib tests
|
||||
do
|
||||
copy_files ${PAXUTILS_SRCDIR}/$dir $dir
|
||||
done
|
||||
|
||||
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
|
||||
|
||||
# Get gnulib files.
|
||||
|
||||
case ${GNULIB_SRCDIR--} in
|
||||
-) checkout gnulib
|
||||
GNULIB_SRCDIR=gnulib
|
||||
esac
|
||||
|
||||
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
|
||||
<$gnulib_tool || exit
|
||||
|
||||
get_modules gnulib.modules
|
||||
|
||||
gnulib_modules=`echo "$gnulib_modules" | sort -u`
|
||||
previous_gnulib_modules=
|
||||
while [ "$gnulib_modules" != "$previous_gnulib_modules" ]; do
|
||||
previous_gnulib_modules=$gnulib_modules
|
||||
gnulib_modules=`
|
||||
(echo "$gnulib_modules"
|
||||
for gnulib_module in $gnulib_modules; do
|
||||
$gnulib_tool --extract-dependencies $gnulib_module
|
||||
done) | sort -u
|
||||
`
|
||||
done
|
||||
|
||||
gnulib_files=`
|
||||
(for gnulib_module in $gnulib_modules; do
|
||||
$gnulib_tool --extract-filelist $gnulib_module
|
||||
done) | sort -u
|
||||
`
|
||||
|
||||
gnulib_dirs=`echo "$gnulib_files" | sed 's,/[^/]*$,,' | sort -u`
|
||||
mkdir -p $gnulib_dirs || exit
|
||||
|
||||
for gnulib_file in $gnulib_files; do
|
||||
dest=$gnulib_file
|
||||
rm -f $dest &&
|
||||
echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file" &&
|
||||
cp -p $GNULIB_SRCDIR/$gnulib_file $dest || exit
|
||||
done
|
||||
|
||||
# This suppresses a bogus diagnostic
|
||||
# "warning: macro `AM_LANGINFO_CODESET' not found in library".
|
||||
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
|
||||
sed '
|
||||
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
|
||||
AC_DEFUN([AM_INTL_SUBDIR], [])
|
||||
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
|
||||
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
|
||||
' m4/gettext.m4 >m4/gettext_gl.m4 || exit
|
||||
|
||||
echo "$0: Creating m4/gnulib.m4"
|
||||
(echo "# This file is generated automatically. Please, do not edit."
|
||||
echo "#"
|
||||
echo "AC_DEFUN([${package}_GNULIB],["
|
||||
for gnulib_module in $gnulib_modules; do
|
||||
echo "# $gnulib_module"
|
||||
$gnulib_tool --extract-autoconf-snippet $gnulib_module
|
||||
done | sed '/AM_GNU_GETTEXT/d'
|
||||
echo "])") > ./m4/gnulib.m4
|
||||
|
||||
echo "$0: Creating lib/Makefile.am"
|
||||
(echo "# This file is generated automatically. Do not edit!"
|
||||
cat lib/Makefile.tmpl
|
||||
|
||||
for gnulib_module in $gnulib_modules; do
|
||||
echo "# $gnulib_module"
|
||||
$gnulib_tool --extract-automake-snippet $gnulib_module
|
||||
done | sed "s/lib_SOURCES/lib${package}_a_SOURCES/g" ) > lib/Makefile.am
|
||||
|
||||
# Get translations.
|
||||
if test "$DOWNLOAD_PO" = "yes"; then
|
||||
update_po
|
||||
fi
|
||||
|
||||
# Reconfigure, getting other files.
|
||||
|
||||
echo "$0: autopoint --force ..."
|
||||
autopoint --force || exit
|
||||
|
||||
# We don't need intl, so remove it.
|
||||
intl_files_to_remove='
|
||||
intl
|
||||
m4/gettext.m4
|
||||
m4/glibc2.m4
|
||||
m4/intdiv0.m4
|
||||
m4/intmax.m4
|
||||
m4/lcmessage.m4
|
||||
m4/lock.m4
|
||||
m4/printf-posix.m4
|
||||
m4/visibility.m4
|
||||
'
|
||||
echo $0: rm -fr $intl_files_to_remove ...
|
||||
rm -fr $intl_files_to_remove || exit
|
||||
|
||||
|
||||
# Undo changes to gnulib files that autoreconf made.
|
||||
|
||||
for gnulib_file in $gnulib_files; do
|
||||
test ! -f $gnulib_file || cmp -s $gnulib_file $GNULIB_SRCDIR/$gnulib_file || {
|
||||
rm -f $gnulib_file &&
|
||||
echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file again" &&
|
||||
cp -p $GNULIB_SRCDIR/$gnulib_file $gnulib_file || exit
|
||||
}
|
||||
done
|
||||
|
||||
# Make sure aclocal.m4 is not older than input files.
|
||||
sleep 1
|
||||
|
||||
for command in \
|
||||
'aclocal --force -I m4' \
|
||||
'autoconf --force' \
|
||||
'autoheader --force' \
|
||||
'automake --add-missing --copy --force-missing';
|
||||
do
|
||||
echo "$0: $command ..."
|
||||
$command || exit
|
||||
done
|
||||
|
||||
|
||||
# Create gettext configuration.
|
||||
echo "$0: Creating po/Makevars from po/Makevars.template ..."
|
||||
sed '
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
|
||||
/^XGETTEXT_OPTIONS *=/{
|
||||
s/$/ \\/
|
||||
a\
|
||||
--flag=_:1:pass-c-format \\\
|
||||
--flag=N_:1:pass-c-format \\\
|
||||
--flag=error:3:c-format --flag=error_at_line:5:c-format \\\
|
||||
--flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format \\\
|
||||
--flag=argp_error:2:c-format \\\
|
||||
--flag=__argp_error:2:c-format \\\
|
||||
--flag=argp_failure:4:c-format \\\
|
||||
--flag=__argp_failure:4:c-format \\\
|
||||
--flag=argp_fmtstream_printf:2:c-format \\\
|
||||
--flag=__argp_fmtstream_printf:2:c-format
|
||||
}
|
||||
' po/Makevars.template >po/Makevars
|
||||
|
||||
|
||||
echo "$0: done. Now you can run './configure'."
|
||||
330
configure.ac
330
configure.ac
@@ -1,97 +1,153 @@
|
||||
# Configure template for GNU tar.
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
AC_INIT(src/tar.c)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.12)
|
||||
AM_INIT_AUTOMAKE(tar, 1.12)
|
||||
AC_DEFINE(_GNU_SOURCE)
|
||||
ALL_LINGUAS="de fr it ko nl no pl pt sl sv"
|
||||
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AC_INIT([GNU tar], [1.16], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
AC_PREREQ([2.60])
|
||||
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
|
||||
|
||||
gl_USE_SYSTEM_EXTENSIONS
|
||||
fp_PROG_ECHO
|
||||
test $fp_cv_prog_echo_nonl = no \
|
||||
&& echo 2>&1 "WARNING: \`echo' not powerful enough for \`make check'"
|
||||
AC_PROG_CC
|
||||
AC_EXEEXT
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_AIX
|
||||
AC_MINIX
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_YACC
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_ISC_POSIX
|
||||
AM_C_PROTOTYPES
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_CHECK_SIZEOF(unsigned long, 4)
|
||||
AC_CHECK_SIZEOF(long long, 0)
|
||||
|
||||
AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h memory.h net/errno.h \
|
||||
sgtty.h string.h stropts.h \
|
||||
sys/param.h sys/device.h sys/filio.h sys/gentape.h \
|
||||
sys/inet.h sys/io/trioctl.h \
|
||||
sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \
|
||||
unistd.h locale.h)
|
||||
AC_CHECK_HEADERS(fcntl.h limits.h linux/fd.h memory.h net/errno.h poll.h \
|
||||
sgtty.h string.h stropts.h \
|
||||
sys/buf.h sys/device.h sys/gentape.h sys/inet.h sys/io/trioctl.h sys/ioccom.h \
|
||||
sys/mtio.h sys/param.h sys/tprintf.h sys/tape.h sys/time.h sys/timeb.h \
|
||||
sys/wait.h unistd.h)
|
||||
|
||||
AC_CHECK_HEADERS([sys/buf.h], [], [],
|
||||
[#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif])
|
||||
# It seems that that many machines where <utime.h> seems to be
|
||||
# broken just require something like -D_XXX_SOURCE, where XXX might
|
||||
# be POSIX, POSIX_C, ALL, HPUX or whatever, depending on the machine.
|
||||
|
||||
AC_HEADER_SYS_WAIT
|
||||
AM_STDBOOL_H
|
||||
AC_CACHE_CHECK(for utime.h, tar_cv_header_utime_h,
|
||||
[AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utime.h>], [struct utimbuf foo],
|
||||
tar_cv_header_utime_h=yes, tar_cv_header_utime_h=no)])
|
||||
test $tar_cv_header_utime_h = yes && AC_DEFINE(HAVE_UTIME_H)
|
||||
|
||||
if test $ac_cv_header_sys_mtio_h = yes; then
|
||||
AC_CACHE_CHECK(for remote tape header files, tar_cv_header_rmt,
|
||||
[AC_TRY_CPP([
|
||||
#if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
#endif
|
||||
#include <sys/socket.h>],
|
||||
tar_cv_header_rmt=yes, tar_cv_header_rmt=no)])
|
||||
test $tar_cv_header_rmt = yes && RMT=rmt
|
||||
AC_SUBST(RMT)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK(for getgrgid declaration, tar_cv_header_getgrgid,
|
||||
[AC_EGREP_HEADER(getgrgid, grp.h,
|
||||
tar_cv_header_getgrgid=yes, tar_cv_header_getgrgid=no)])
|
||||
test $tar_cv_header_getgrgid = yes && AC_DEFINE(HAVE_GETGRGID)
|
||||
|
||||
AC_CACHE_CHECK(for getpwuid declaration, tar_cv_header_getpwuid,
|
||||
[AC_EGREP_HEADER(getpwuid, pwd.h,
|
||||
tar_cv_header_getpwuid=yes, tar_cv_header_getpwuid=no)])
|
||||
test $tar_cv_header_getpwuid = yes && AC_DEFINE(HAVE_GETPWUID)
|
||||
|
||||
AC_CACHE_CHECK(which ioctl field to test for reversed bytes,
|
||||
tar_cv_header_mtio_check_field,
|
||||
[AC_EGREP_HEADER(mt_model, sys/mtio.h,
|
||||
tar_cv_header_mtio_check_field=mt_model,
|
||||
tar_cv_header_mtio_check_field=mt_type)])
|
||||
AC_DEFINE_UNQUOTED(MTIO_CHECK_FIELD, $tar_cv_header_mtio_check_field)
|
||||
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_MAJOR
|
||||
AC_HEADER_STAT
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_MSG_CHECKING([for st_fstype string in struct stat])
|
||||
AC_CACHE_VAL(diff_cv_st_fstype_string,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/stat.h>], [struct stat s; s.st_fstype[0] = 'x';],
|
||||
diff_cv_st_fstype_string=yes,
|
||||
diff_cv_st_fstype_string=no)])
|
||||
AC_MSG_RESULT($diff_cv_st_fstype_string)
|
||||
if test $diff_cv_st_fstype_string = yes; then
|
||||
AC_DEFINE(HAVE_ST_FSTYPE_STRING, 1,
|
||||
[Define if struct stat has a char st_fstype[] member.])
|
||||
fi
|
||||
|
||||
AC_HEADER_TIME
|
||||
AC_STRUCT_ST_BLKSIZE
|
||||
AC_STRUCT_ST_BLOCKS
|
||||
AC_TYPE_SIGNAL
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_UID_T
|
||||
AC_CHECK_TYPE(major_t, , AC_DEFINE(major_t, int,
|
||||
[Type of major device numbers.]))
|
||||
AC_CHECK_TYPE(minor_t, , AC_DEFINE(minor_t, int,
|
||||
[Type of minor device numbers.]))
|
||||
AC_CHECK_TYPE(dev_t, unsigned)
|
||||
AC_CHECK_TYPE(ino_t, unsigned)
|
||||
|
||||
gt_TYPE_SSIZE_T
|
||||
AC_CHECK_FUNCS(fsync ftime getcwd isascii lchown mkfifo nap napms poll \
|
||||
select strerror strstr usleep)
|
||||
|
||||
# gnulib modules
|
||||
tar_GNULIB
|
||||
# paxutils modules
|
||||
tar_PAXUTILS
|
||||
AC_CACHE_CHECK(for mknod, tar_cv_func_mknod,
|
||||
[AC_TRY_LINK([
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>],
|
||||
[mknod (0, 0, 0)],
|
||||
tar_cv_func_mknod=yes, tar_cv_func_mknod=no)])
|
||||
test $tar_cv_func_mknod = yes && AC_DEFINE(HAVE_MKNOD)
|
||||
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink strerror symlink setlocale utimes)
|
||||
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
|
||||
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
||||
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
||||
# Whenever both -lsocket and -lnsl are needed, it seems to be always the
|
||||
# case that gethostbyname requires -lnsl. So, check -lnsl first, for it
|
||||
# to be in LIBS before the setsockopt checks are performed. *However*,
|
||||
# on SINIX-N 5.43, this is false, and gethostent seems to be a better
|
||||
# candidate. So, let's use it below instead of gethostbyname, and see.
|
||||
|
||||
AC_REPLACE_FUNCS(waitpid)
|
||||
AC_CHECK_FUNC(gethostent)
|
||||
if test $ac_cv_func_gethostent = no; then
|
||||
AC_CHECK_LIB(nsl, gethostent)
|
||||
fi
|
||||
AC_CHECK_FUNC(setsockopt)
|
||||
if test $ac_cv_func_setsockopt = no; then
|
||||
AC_CHECK_LIB(socket, setsockopt)
|
||||
fi
|
||||
|
||||
AC_FUNC_ALLOCA
|
||||
AC_FUNC_FNMATCH
|
||||
test $ac_cv_func_fnmatch_works = yes || LIBOBJS="$LIBOBJS fnmatch.o"
|
||||
AC_FUNC_VPRINTF
|
||||
AC_REPLACE_FUNCS(basename dirname execlp ftruncate memset mkdir rename rmdir)
|
||||
test "$ac_cv_func_strstr" = yes || LIBOBJS="$LIBOBJS strstr.o"
|
||||
|
||||
# The 3-argument open happens to go along with the O_* defines, which
|
||||
# are easier to check for.
|
||||
|
||||
AC_CACHE_CHECK(for 3-argument open, tar_cv_func_open3,
|
||||
[AC_TRY_COMPILE([
|
||||
#if HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif],
|
||||
[int x = O_RDONLY],
|
||||
tar_cv_func_open3=yes, tar_cv_func_open3=no)])
|
||||
if test $tar_cv_func_open3 = no; then
|
||||
AC_DEFINE(EMUL_OPEN3)
|
||||
fi
|
||||
|
||||
# `union wait' is preferrably avoided. We merely assume below
|
||||
# that if `int pid;' fails, `union wait pid;' would have worked.
|
||||
# Directly trying `union wait pid;' is seeking for trouble, as
|
||||
# some POSIX systems are offering compatibility hacks generating
|
||||
# ugly diagnostics. Also, on some systems, WEXITSTATUS exists,
|
||||
# but fails when called on `union wait' variables.
|
||||
|
||||
AC_CACHE_CHECK(for union wait, tar_cv_header_union_wait,
|
||||
[AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#endif],
|
||||
[int status; int pid; pid = wait (&status);],
|
||||
tar_cv_header_union_wait=no, tar_cv_header_union_wait=yes)])
|
||||
test $tar_cv_header_union_wait = yes && AC_DEFINE(HAVE_UNION_WAIT)
|
||||
|
||||
AC_CACHE_CHECK(for remote shell, tar_cv_path_RSH,
|
||||
[if test -n "$RSH"; then
|
||||
@@ -99,48 +155,22 @@ AC_CACHE_CHECK(for remote shell, tar_cv_path_RSH,
|
||||
else
|
||||
tar_cv_path_RSH=no
|
||||
for ac_file in /usr/ucb/rsh /usr/bin/remsh /usr/bin/rsh /usr/bsd/rsh \
|
||||
/usr/bin/nsh /usr/bin/rcmd
|
||||
/usr/bin/nsh /usr/bin/rcmd
|
||||
do
|
||||
# Prefer a non-symlink rsh to a symlink one, so that binaries built
|
||||
# on AIX 4.1.4, where /usr/ucb/rsh is a symlink to /usr/bin/rsh
|
||||
# will run on AIX 4.3.0, which has only /usr/bin/rsh.
|
||||
if test -f $ac_file; then
|
||||
if (test -h $ac_file) 2>/dev/null; then
|
||||
test $tar_cv_path_RSH = no && tar_cv_path_RSH=$ac_file
|
||||
else
|
||||
tar_cv_path_RSH=$ac_file
|
||||
break
|
||||
fi
|
||||
tar_cv_path_RSH=$ac_file
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
if test $tar_cv_path_RSH = no; then
|
||||
AC_CHECK_HEADERS(netdb.h)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED(REMOTE_SHELL, "$tar_cv_path_RSH",
|
||||
[Define to the full path of your rsh, if any.])
|
||||
AC_DEFINE_UNQUOTED(REMOTE_SHELL, "$tar_cv_path_RSH")
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for default archive format)
|
||||
|
||||
AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],
|
||||
[Set the default archive format. Allowed values are: V7, OLDGNU, USTAR, POSIX, GNU. Default is GNU])
|
||||
|
||||
if test -z "$DEFAULT_ARCHIVE_FORMAT"; then
|
||||
DEFAULT_ARCHIVE_FORMAT="GNU"
|
||||
fi
|
||||
case $DEFAULT_ARCHIVE_FORMAT in
|
||||
V7|OLDGNU|USTAR|POSIX|GNU) ;;
|
||||
*) AC_MSG_ERROR(Invalid format name);;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_ARCHIVE_FORMAT, ${DEFAULT_ARCHIVE_FORMAT}_FORMAT,
|
||||
[By default produce archives of this format])
|
||||
AC_MSG_RESULT($DEFAULT_ARCHIVE_FORMAT)
|
||||
|
||||
AC_MSG_CHECKING(for default archive)
|
||||
|
||||
AC_ARG_VAR([DEFAULT_ARCHIVE],
|
||||
[Set the name of the default archive (default: -)])
|
||||
if test -z "$DEFAULT_ARCHIVE"; then
|
||||
DEFAULT_ARCHIVE=-
|
||||
else
|
||||
@@ -151,97 +181,35 @@ else
|
||||
# FIXME: Let DEVICE_PREFIX be configured from the environment.
|
||||
# FIXME: Rearrange, here.
|
||||
case $DEFAULT_ARCHIVE in
|
||||
*[[0-7][lmh]])
|
||||
AC_DEFINE(DENSITY_LETTER, 1,
|
||||
[Define to 1 if density may be indicated by [lmh] at end of device.])
|
||||
changequote(, )dnl
|
||||
*[0-7][lmh])
|
||||
device_prefix=`echo $DEFAULT_ARCHIVE | sed 's/[0-7][lmh]$//'`
|
||||
changequote([, ])dnl
|
||||
AC_DEFINE_UNQUOTED(DEVICE_PREFIX, "$device_prefix")
|
||||
AC_DEFINE(DENSITY_LETTER)
|
||||
;;
|
||||
*[[0-7]])
|
||||
changequote(, )dnl
|
||||
*[0-7])
|
||||
device_prefix=`echo $DEFAULT_ARCHIVE | sed 's/[0-7]$//'`
|
||||
;;
|
||||
*)
|
||||
device_prefix=
|
||||
;;
|
||||
esac
|
||||
case "$device_prefix" in
|
||||
?*)
|
||||
AC_DEFINE_UNQUOTED(DEVICE_PREFIX, "$device_prefix",
|
||||
[Define to a string giving the prefix of the default device, without the part specifying the unit and density.])
|
||||
changequote([, ])dnl
|
||||
AC_DEFINE_UNQUOTED(DEVICE_PREFIX, "$device_prefix")
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_ARCHIVE, "$DEFAULT_ARCHIVE",
|
||||
[Define to a string giving the full name of the default archive file.])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_ARCHIVE, "$DEFAULT_ARCHIVE")
|
||||
AC_MSG_RESULT($DEFAULT_ARCHIVE)
|
||||
|
||||
AC_ARG_VAR([DEFAULT_BLOCKING],
|
||||
[Define default blocking factor (default: 20)])
|
||||
AC_MSG_CHECKING(for default blocking)
|
||||
DEFAULT_BLOCKING=${DEFAULT_BLOCKING-20}
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_BLOCKING, $DEFAULT_BLOCKING,
|
||||
[Define to a number giving the default blocking size for archives.])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_BLOCKING, $DEFAULT_BLOCKING)
|
||||
AC_MSG_RESULT($DEFAULT_BLOCKING)
|
||||
|
||||
AC_MSG_CHECKING(for default quoting style)
|
||||
fp_WITH_INCLUDED_MALLOC
|
||||
AM_WITH_DMALLOC
|
||||
|
||||
m4_define([QUOTING_STYLES],dnl
|
||||
[literal|shell|shell-always|c|escape|locale|clocale])
|
||||
DEFAULT_QUOTING_STYLE="escape"
|
||||
AC_ARG_VAR([DEFAULT_QUOTING_STYLE],
|
||||
[Set the default quoting style. Allowed values are: ] m4_bpatsubst(QUOTING_STYLES,[|], [[, ]]) [. Default is "escape".])
|
||||
AM_GNU_GETTEXT
|
||||
AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl)
|
||||
|
||||
case $DEFAULT_QUOTING_STYLE in
|
||||
QUOTING_STYLES) ;;
|
||||
*) AC_MSG_ERROR(Invalid quoting style);;
|
||||
esac
|
||||
AC_MSG_RESULT($DEFAULT_QUOTING_STYLE)
|
||||
DEFAULT_QUOTING_STYLE=`echo ${DEFAULT_QUOTING_STYLE}|sed 's/-/_/g'`_quoting_style
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_QUOTING_STYLE, $DEFAULT_QUOTING_STYLE,
|
||||
[Define to a default quoting style (see lib/quoteargs.c for the list)])
|
||||
|
||||
# Iconv
|
||||
AM_ICONV
|
||||
AC_CHECK_HEADERS(iconv.h)
|
||||
AC_CHECK_TYPE(iconv_t,:,
|
||||
AC_DEFINE(iconv_t, int,
|
||||
[Conversion descriptor type]),
|
||||
[
|
||||
#ifdef HAVE_ICONV_H
|
||||
# include <iconv.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
# Gettext.
|
||||
AM_GNU_GETTEXT([external], [need-formatstring-macros])
|
||||
AM_GNU_GETTEXT_VERSION([0.15])
|
||||
|
||||
# Initialize the test suite.
|
||||
AC_CONFIG_TESTDIR(tests)
|
||||
AC_CONFIG_FILES([tests/Makefile tests/atlocal]) # FIXME: tests/preset?
|
||||
AM_MISSING_PROG([AUTOM4TE], [autom4te])
|
||||
|
||||
AC_SUBST(BACKUP_LIBEXEC_SCRIPTS)
|
||||
AC_SUBST(BACKUP_SBIN_SCRIPTS)
|
||||
AC_ARG_ENABLE(backup-scripts,
|
||||
AC_HELP_STRING([--enable-backup-scripts],
|
||||
[Create and install backup and restore scripts]),
|
||||
[case $enableval in
|
||||
yes) BACKUP_LIBEXEC_SCRIPTS='$(BACKUP_LIBEXEC_SCRIPTS_LIST)'
|
||||
BACKUP_SBIN_SCRIPTS='$(BACKUP_SBIN_SCRIPTS_LIST)'
|
||||
;;
|
||||
esac])
|
||||
|
||||
AC_SUBST(BACKUP_SED_COND)
|
||||
if date +%Y-%m-%d 2>/dev/null >&2; then
|
||||
BACKUP_SED_COND='/^\#ELSE_DATE_FORMAT_OK/,/^\#ENDIF_DATE_FORMAT_OK/d;/^\#IF_DATE_FORMAT_OK/d'
|
||||
else
|
||||
BACKUP_SED_COND='/^\#IF_DATE_FORMAT_OK/,/^\#ELSE_DATE_FORMAT_OK/d;/^\#ENDIF_DATE_FORMAT_OK/d'
|
||||
fi
|
||||
|
||||
AC_OUTPUT([Makefile\
|
||||
doc/Makefile\
|
||||
lib/Makefile\
|
||||
po/Makefile.in\
|
||||
scripts/Makefile\
|
||||
rmt/Makefile\
|
||||
src/Makefile])
|
||||
AC_OUTPUT([Makefile doc/Makefile intl/Makefile lib/Makefile po/Makefile.in \
|
||||
scripts/Makefile src/Makefile tests/Makefile tests/preset],
|
||||
[sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile])
|
||||
|
||||
87
directory
87
directory
@@ -1,87 +0,0 @@
|
||||
%%comments:
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the file COPYING.
|
||||
|
||||
%%name: tar
|
||||
|
||||
%%short-description: Creates tar archives
|
||||
|
||||
%%full-description:
|
||||
GNU tar is an archiver that creates and handles file archives in various
|
||||
formats. You can use tar to create file archives, to extract files from
|
||||
previously created archives, store additional files, or update or list
|
||||
files which were already stored.
|
||||
|
||||
The program saves many files together into a single tape or disk
|
||||
archive, and can restore individual files from the archive. It
|
||||
includes multivolume support, the ability to archive sparse files,
|
||||
automatic archive compression/decompression, remote archives and
|
||||
special features that allow 'tar' to be used for incremental and full
|
||||
backups.
|
||||
|
||||
The supported archive formats are: V7 tar, GNU, ustar and POSIX (also
|
||||
known as pax interchange format). GNU tar is also able to read and
|
||||
extract 'star' archives.
|
||||
|
||||
Tar can direct its output to available devices, files, or other
|
||||
programs (using pipes); tar can even access remote devices or files
|
||||
(as archives).
|
||||
|
||||
%%category: system, backup
|
||||
|
||||
%%license: GPL
|
||||
|
||||
%%maintainer: Sergey Poznyakoff <gray@Mirddin.farlep.net>,
|
||||
Jeff Bailey <jbailey@nisa.net>,
|
||||
Paul Eggert <eggert@CS.UCLA.EDU>
|
||||
|
||||
%%updated: 21 Dec 2004
|
||||
|
||||
%%keywords: archive, backup, tar, pax
|
||||
|
||||
%%interface: Command line
|
||||
|
||||
%%programs: tar, rmt
|
||||
|
||||
%%GNU: yes
|
||||
|
||||
%%web-page: http://www.gnu.org/software/tar
|
||||
|
||||
%%doc: English user reference included
|
||||
|
||||
%%doc: English user manual in Texinfo, Dvi, Postscript, HTML, Plaintext is available from http://www.gnu.org/software/tar/manual/tar.html
|
||||
|
||||
%%developers:
|
||||
John Gilmore,
|
||||
Thomas Bushnell,
|
||||
Paul Eggert <eggert@twinsun.com>,
|
||||
Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
%%contributors: Jay Fenlason,
|
||||
Joy Kendall,
|
||||
Francois Pinard <pinard@iro.umontreal.ca>
|
||||
|
||||
%%source-tarball: ftp://ftp.gnu.org/pub/gnu/tar/tar-1.15.1.tar.gz
|
||||
%%source-info: http://savannah.gnu.org/projects/tar
|
||||
|
||||
%%repository:
|
||||
:pserver:anoncvs@subversions.gnu.org:/cvsroot/tar login,
|
||||
:pserver:anoncvs@subversions.gnu.org:/cvsroot/tar co tar,
|
||||
http://savannah.gnu.org/cvs/?group=tar,
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/tar/tar,
|
||||
|
||||
%%source-language: C
|
||||
|
||||
%%related-programs: GNU cpio
|
||||
|
||||
%%version: 1.15.1 (stable) released on 21 Dec 2004
|
||||
|
||||
%%bug-list: bug-tar@gnu.org bug-tar@gnu.org http://mail.gnu.org/mailman/listinfo/bug-tar
|
||||
|
||||
%%entry-written-by: Sergey Poznyakoff <gray@gnu.org>
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
*.stamp
|
||||
Makefile
|
||||
Makefile.in
|
||||
genfile.texi
|
||||
getdate.texi
|
||||
header.texi
|
||||
html_chapter
|
||||
html_mono
|
||||
html_node
|
||||
stamp-vti
|
||||
tar.at
|
||||
tar.ats
|
||||
tar.aux
|
||||
tar.cp
|
||||
tar.cps
|
||||
tar.dvi
|
||||
tar.ex
|
||||
tar.exs
|
||||
tar.fn
|
||||
tar.fns
|
||||
tar.html
|
||||
tar.info*
|
||||
tar.kw
|
||||
tar.kws
|
||||
tar.ky
|
||||
tar.log
|
||||
tar.op
|
||||
tar.ops
|
||||
tar.pdf
|
||||
tar.pg
|
||||
tar.pgs
|
||||
tar.ps
|
||||
tar.toc
|
||||
tar.tp
|
||||
tar.vr
|
||||
tar.vrs
|
||||
version.texi
|
||||
115
doc/Makefile.am
115
doc/Makefile.am
@@ -1,86 +1,53 @@
|
||||
# Makefile for GNU tar documentation.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006 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 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.
|
||||
|
||||
## 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.
|
||||
# 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.
|
||||
|
||||
AUTOMAKE_OPTIONS = gnits
|
||||
info_TEXINFOS = tar.texi
|
||||
tar_TEXINFOS = \
|
||||
dumpdir.texi\
|
||||
fdl.texi\
|
||||
freemanuals.texi\
|
||||
genfile.texi\
|
||||
getdate.texi\
|
||||
header.texi\
|
||||
intern.texi\
|
||||
rendition.texi\
|
||||
snapshot.texi\
|
||||
sparse.texi\
|
||||
value.texi
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed
|
||||
DISTCLEANFILES=*.info*
|
||||
|
||||
EXTRA_DIST = convtexi.pl getdate.texi header.texi
|
||||
|
||||
CLEANFILES = tmp-*
|
||||
|
||||
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
|
||||
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
# Just call `make dvi RENDITION=PROOF' if you want PROOF rendition.
|
||||
RENDITION = DISTRIB
|
||||
|
||||
MAKEINFOFLAGS=-D$(RENDITION)
|
||||
tar.info: tar.texi getdate.texi header.texi version.texi
|
||||
@echo "WARNING: \`makeinfo' will not preprocess Texinfo input properly"
|
||||
@echo " for expanding Texinfo macros, if it comes from a"
|
||||
@echo " Texinfo distribution which is earlier than version 3.7."
|
||||
cd $(srcdir) && $(MAKEINFO) -D$(RENDITION) tar.texi
|
||||
|
||||
tar.dvi: tar.texi getdate.texi header.texi version.texi
|
||||
@echo "WARNING: \`makeinfo' will not preprocess Texinfo input properly"
|
||||
@echo " for expanding Texinfo macros, if it comes from a"
|
||||
@echo " Texinfo distribution which is earlier than version 3.7."
|
||||
$(MAKEINFO) -D$(RENDITION) -Etmp-tar.tmp -otmp-tar.info \
|
||||
-I$(srcdir) tar.texi
|
||||
rm -f tmp-tar.sed tmp-tar.info*
|
||||
test $(RENDITION) = DISTRIB \
|
||||
|| echo >>tmp-tar.sed 's/^@set DISTRIB/@set $(RENDITION)/'
|
||||
test $(RENDITION) = PUBLISH \
|
||||
|| echo >>tmp-tar.sed '/^@smallbook/d'
|
||||
sed -f tmp-tar.sed tmp-tar.tmp > tmp-tar.texi
|
||||
rm -f tmp-tar.sed tmp-tar.tmp
|
||||
TEXINPUTS=$(srcdir):$$TEXINPUTS $(TEXI2DVI) tmp-tar.texi
|
||||
mv tmp-tar.dvi $@
|
||||
|
||||
header.texi: $(top_srcdir)/src/tar.h
|
||||
sed -f $(srcdir)/texify.sed $(top_srcdir)/src/tar.h \
|
||||
| expand >$@
|
||||
|
||||
master-menu: $(tar_TEXINFOS)
|
||||
emacs -batch -l mastermenu.el -f make-master-menu $(info_TEXINFOS)
|
||||
|
||||
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' \
|
||||
$(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.$$$$
|
||||
|
||||
|
||||
clean-local:
|
||||
rm -rf manual
|
||||
|
||||
GENDOCS=gendocs.sh
|
||||
|
||||
TEXI2DVI=texi2dvi -t '@set $(RENDITION)' -E
|
||||
|
||||
# Make sure you set TEXINPUTS
|
||||
# Usual value is:
|
||||
# /usr/share/texmf/pdftex/plain/misc:/usr/share/texmf/pdftex/config
|
||||
manual:
|
||||
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
|
||||
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
|
||||
$(GENDOCS) tar 'GNU tar manual'
|
||||
|
||||
sed -n '/Archive Format/,/End of Format/p' $(top_srcdir)/src/tar.h \
|
||||
| expand | sed 's/\([{}]\)/@\1/g' > $(srcdir)/header.texi
|
||||
|
||||
118
doc/convtexi.pl
Executable file
118
doc/convtexi.pl
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/usr/local/bin/perl -- # -*-Perl-*-
|
||||
eval "exec /usr/local/bin/perl -S $0 $*"
|
||||
if 0;
|
||||
|
||||
# Copy a Texinfo file, replacing @value's, @FIXME's and other gooddies.
|
||||
# Copyright <20> 1996 Free Software Foundation, Inc.
|
||||
# Fran<61>ois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
$_ = <>;
|
||||
while ($_)
|
||||
{
|
||||
if (/^\@c()$/ || /^\@c (.*)/ || /^\@(include .*)/)
|
||||
{
|
||||
if ($topseen)
|
||||
{
|
||||
print "\@format\n";
|
||||
print "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
while (/\@c (.*)/)
|
||||
{
|
||||
print "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
}
|
||||
print "\@end format\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$delay .= "\@format\n";
|
||||
$delay .= "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
while (/\@c (.*)/)
|
||||
{
|
||||
$delay .= "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
}
|
||||
$delay .= "\@end format\n";
|
||||
}
|
||||
}
|
||||
elsif (/^\@chapter /)
|
||||
{
|
||||
print;
|
||||
# print $delay;
|
||||
$delay = '';
|
||||
$topseen = 1;
|
||||
$_ = <>;
|
||||
}
|
||||
elsif (/^\@macro /)
|
||||
{
|
||||
$_ = <> while ($_ && ! /^\@end macro/);
|
||||
$_ = <>;
|
||||
}
|
||||
elsif (/^\@set ([^ ]+) (.*)/)
|
||||
{
|
||||
$set{$1} = $2;
|
||||
$_ = <>;
|
||||
}
|
||||
elsif (/^\@UNREVISED/)
|
||||
{
|
||||
print "\@quotation\n";
|
||||
print "\@emph{(This message will disappear, once this node is revised.)}\n";
|
||||
print "\@end quotation\n";
|
||||
$_ = <>;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (/\@value{([^\}]*)}/)
|
||||
{
|
||||
if (defined $set{$1})
|
||||
{
|
||||
$_ = "$`$set{$1}$'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$_ = "$`\@strong{<UNDEFINED>}$1\@strong{</UNDEFINED>}$'";
|
||||
}
|
||||
}
|
||||
while (/\@FIXME-?([a-z]*)\{/)
|
||||
{
|
||||
$tag = $1 eq '' ? 'fixme' : $1;
|
||||
$tag =~ y/a-z/A-Z/;
|
||||
print "$`\@strong{<$tag>}";
|
||||
$_ = $';
|
||||
$level = 1;
|
||||
while ($level > 0)
|
||||
{
|
||||
if (/([{}])/)
|
||||
{
|
||||
if ($1 eq '{')
|
||||
{
|
||||
$level++;
|
||||
print "$`\{";
|
||||
$_ = $';
|
||||
}
|
||||
elsif ($level > 1)
|
||||
{
|
||||
$level--;
|
||||
print "$`\}";
|
||||
$_ = $';
|
||||
}
|
||||
else
|
||||
{
|
||||
$level = 0;
|
||||
print "$`\@strong{</$tag>}";
|
||||
$_ = $';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print;
|
||||
$_ = <>;
|
||||
}
|
||||
}
|
||||
}
|
||||
print;
|
||||
$_ = <>;
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
132
doc/dumpdir.texi
132
doc/dumpdir.texi
@@ -1,132 +0,0 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c Written by Sergey Poznyakoff
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
Incremental archives keep information about contents of each
|
||||
dumped directory in special data blocks called @dfn{dumpdirs}.
|
||||
|
||||
Dumpdir is a sequence of entries of the following form:
|
||||
|
||||
@smallexample
|
||||
@var{C} @var{filename} \0
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{C} is one of the @dfn{control codes} described below,
|
||||
@var{filename} is the name of the file @var{C} operates upon, and
|
||||
@samp{\0} represents a nul character (ASCII 0). The white space
|
||||
characters were added for readability, real dumpdirs do not contain
|
||||
them.
|
||||
|
||||
Each dumpdir ends with a single nul character.
|
||||
|
||||
The following table describes control codes and their meanings:
|
||||
|
||||
@table @samp
|
||||
@item Y
|
||||
@var{filename} is contained in the archive.
|
||||
|
||||
@item N
|
||||
@var{filename} was present in the directory at the time the archive
|
||||
was made, yet it was not dumped to the archive, because it had not
|
||||
changed since the last backup.
|
||||
|
||||
@item D
|
||||
@var{filename} is a directory.
|
||||
|
||||
@item R
|
||||
This code requests renaming of the @var{filename} to the name
|
||||
specified with the following @samp{T} command.
|
||||
|
||||
@item T
|
||||
Specify target file name for @samp{R} command (see below).
|
||||
|
||||
@item X
|
||||
Specify @dfn{temporary directory} name for a rename operation (see below).
|
||||
@end table
|
||||
|
||||
Codes @samp{Y}, @samp{N} and @samp{D} require @var{filename} argument
|
||||
to be a relative file name to the directory this dumpdir describes,
|
||||
whereas codes @samp{R}, @samp{T} and @samp{X} require their argument
|
||||
to be an absolute file name.
|
||||
|
||||
The three codes @samp{R}, @samp{T} and @samp{X} specify a
|
||||
@dfn{renaming operation}. In the simplest case it is:
|
||||
|
||||
@smallexample
|
||||
R@file{source}\0T@file{dest}\0
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
which means ``rename file @file{source} to file @file{dest}''.
|
||||
|
||||
However, there are cases that require using a @dfn{temporary
|
||||
directory}. For example, consider the following scenario:
|
||||
|
||||
@enumerate 1
|
||||
@item
|
||||
Previous run dumped a directory @file{foo} which contained the
|
||||
following three directories:
|
||||
|
||||
@smallexample
|
||||
a
|
||||
b
|
||||
c
|
||||
@end smallexample
|
||||
|
||||
@item
|
||||
They were renamed @emph{cyclically}, so that:
|
||||
|
||||
@example
|
||||
@file{a} became @file{b}
|
||||
@file{b} became @file{c}
|
||||
@file{c} became @file{a}
|
||||
@end example
|
||||
|
||||
@item
|
||||
New incremental dump was made.
|
||||
@end enumerate
|
||||
|
||||
This case cannot be handled by three successive renames, since
|
||||
renaming @file{a} to @file{b} will destroy existing directory.
|
||||
To handle such case a temporary directory is required. @GNUTAR{}
|
||||
will create the following dumpdir (newlines have been added for
|
||||
readability):
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
Xfoo\0
|
||||
Rfoo/a\0T\0
|
||||
Rfoo/b\0Tfoo/c\0
|
||||
Rfoo/c\0Tfoo/a\0
|
||||
R\0Tfoo/a\0
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
The first command, @samp{Xfoo\0}, instructs the extractor to create a
|
||||
temporary directory in the directory @file{foo}. Second command,
|
||||
@samp{Rfoo/aT\0}, says ``rename file @file{foo/a} to the temporary
|
||||
directory that has just been created'' (empty file name after a
|
||||
command means use temporary directory). Third and fourth commands
|
||||
work as usual, and, finally, the last command, @samp{R\0Tfoo/a\0}
|
||||
tells tar to rename the temporary directory to @file{foo/a}.
|
||||
|
||||
The exact placement of a dumpdir in the archive depends on the
|
||||
archive format (@pxref{Formats}):
|
||||
|
||||
@itemize
|
||||
@item PAX archives
|
||||
|
||||
In PAX archives, dumpdir is stored in the extended header of the
|
||||
corresponding directory, in variable @code{GNU.dumpdir}.
|
||||
|
||||
@item GNU and old GNU archives
|
||||
|
||||
These formats implement special header type @samp{D}, which is similar
|
||||
to ustar header @samp{5} (directory), except that it precedes a data
|
||||
block containing the dumpdir.
|
||||
@end itemize
|
||||
|
||||
@c End of dumpdir.texi
|
||||
452
doc/fdl.texi
452
doc/fdl.texi
@@ -1,452 +0,0 @@
|
||||
|
||||
@node GNU Free Documentation License
|
||||
@appendixsec GNU Free Documentation License
|
||||
|
||||
@cindex FDL, GNU Free Documentation License
|
||||
@center Version 1.2, November 2002
|
||||
|
||||
@display
|
||||
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
@end display
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
PREAMBLE
|
||||
|
||||
The purpose of this License is to make a manual, textbook, or other
|
||||
functional and useful document @dfn{free} in the sense of freedom: to
|
||||
assure everyone the effective freedom to copy and redistribute it,
|
||||
with or without modifying it, either commercially or noncommercially.
|
||||
Secondarily, this License preserves for the author and publisher a way
|
||||
to get credit for their work, while not being considered responsible
|
||||
for modifications made by others.
|
||||
|
||||
This License is a kind of ``copyleft'', which means that derivative
|
||||
works of the document must themselves be free in the same sense. It
|
||||
complements the GNU General Public License, which is a copyleft
|
||||
license designed for free software.
|
||||
|
||||
We have designed this License in order to use it for manuals for free
|
||||
software, because free software needs free documentation: a free
|
||||
program should come with manuals providing the same freedoms that the
|
||||
software does. But this License is not limited to software manuals;
|
||||
it can be used for any textual work, regardless of subject matter or
|
||||
whether it is published as a printed book. We recommend this License
|
||||
principally for works whose purpose is instruction or reference.
|
||||
|
||||
@item
|
||||
APPLICABILITY AND DEFINITIONS
|
||||
|
||||
This License applies to any manual or other work, in any medium, that
|
||||
contains a notice placed by the copyright holder saying it can be
|
||||
distributed under the terms of this License. Such a notice grants a
|
||||
world-wide, royalty-free license, unlimited in duration, to use that
|
||||
work under the conditions stated herein. The ``Document'', below,
|
||||
refers to any such manual or work. Any member of the public is a
|
||||
licensee, and is addressed as ``you''. You accept the license if you
|
||||
copy, modify or distribute the work in a way requiring permission
|
||||
under copyright law.
|
||||
|
||||
A ``Modified Version'' of the Document means any work containing the
|
||||
Document or a portion of it, either copied verbatim, or with
|
||||
modifications and/or translated into another language.
|
||||
|
||||
A ``Secondary Section'' is a named appendix or a front-matter section
|
||||
of the Document that deals exclusively with the relationship of the
|
||||
publishers or authors of the Document to the Document's overall
|
||||
subject (or to related matters) and contains nothing that could fall
|
||||
directly within that overall subject. (Thus, if the Document is in
|
||||
part a textbook of mathematics, a Secondary Section may not explain
|
||||
any mathematics.) The relationship could be a matter of historical
|
||||
connection with the subject or with related matters, or of legal,
|
||||
commercial, philosophical, ethical or political position regarding
|
||||
them.
|
||||
|
||||
The ``Invariant Sections'' are certain Secondary Sections whose titles
|
||||
are designated, as being those of Invariant Sections, in the notice
|
||||
that says that the Document is released under this License. If a
|
||||
section does not fit the above definition of Secondary then it is not
|
||||
allowed to be designated as Invariant. The Document may contain zero
|
||||
Invariant Sections. If the Document does not identify any Invariant
|
||||
Sections then there are none.
|
||||
|
||||
The ``Cover Texts'' are certain short passages of text that are listed,
|
||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||
the Document is released under this License. A Front-Cover Text may
|
||||
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||||
|
||||
A ``Transparent'' copy of the Document means a machine-readable copy,
|
||||
represented in a format whose specification is available to the
|
||||
general public, that is suitable for revising the document
|
||||
straightforwardly with generic text editors or (for images composed of
|
||||
pixels) generic paint programs or (for drawings) some widely available
|
||||
drawing editor, and that is suitable for input to text formatters or
|
||||
for automatic translation to a variety of formats suitable for input
|
||||
to text formatters. A copy made in an otherwise Transparent file
|
||||
format whose markup, or absence of markup, has been arranged to thwart
|
||||
or discourage subsequent modification by readers is not Transparent.
|
||||
An image format is not Transparent if used for any substantial amount
|
||||
of text. A copy that is not ``Transparent'' is called ``Opaque''.
|
||||
|
||||
Examples of suitable formats for Transparent copies include plain
|
||||
@sc{ascii} without markup, Texinfo input format, La@TeX{} input
|
||||
format, @acronym{SGML} or @acronym{XML} using a publicly available
|
||||
@acronym{DTD}, and standard-conforming simple @acronym{HTML},
|
||||
PostScript or @acronym{PDF} designed for human modification. Examples
|
||||
of transparent image formats include @acronym{PNG}, @acronym{XCF} and
|
||||
@acronym{JPG}. Opaque formats include proprietary formats that can be
|
||||
read and edited only by proprietary word processors, @acronym{SGML} or
|
||||
@acronym{XML} for which the @acronym{DTD} and/or processing tools are
|
||||
not generally available, and the machine-generated @acronym{HTML},
|
||||
PostScript or @acronym{PDF} produced by some word processors for
|
||||
output purposes only.
|
||||
|
||||
The ``Title Page'' means, for a printed book, the title page itself,
|
||||
plus such following pages as are needed to hold, legibly, the material
|
||||
this License requires to appear in the title page. For works in
|
||||
formats which do not have any title page as such, ``Title Page'' means
|
||||
the text near the most prominent appearance of the work's title,
|
||||
preceding the beginning of the body of the text.
|
||||
|
||||
A section ``Entitled XYZ'' means a named subunit of the Document whose
|
||||
title either is precisely XYZ or contains XYZ in parentheses following
|
||||
text that translates XYZ in another language. (Here XYZ stands for a
|
||||
specific section name mentioned below, such as ``Acknowledgements'',
|
||||
``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
|
||||
of such a section when you modify the Document means that it remains a
|
||||
section ``Entitled XYZ'' according to this definition.
|
||||
|
||||
The Document may include Warranty Disclaimers next to the notice which
|
||||
states that this License applies to the Document. These Warranty
|
||||
Disclaimers are considered to be included by reference in this
|
||||
License, but only as regards disclaiming warranties: any other
|
||||
implication that these Warranty Disclaimers may have is void and has
|
||||
no effect on the meaning of this License.
|
||||
|
||||
@item
|
||||
VERBATIM COPYING
|
||||
|
||||
You may copy and distribute the Document in any medium, either
|
||||
commercially or noncommercially, provided that this License, the
|
||||
copyright notices, and the license notice saying this License applies
|
||||
to the Document are reproduced in all copies, and that you add no other
|
||||
conditions whatsoever to those of this License. You may not use
|
||||
technical measures to obstruct or control the reading or further
|
||||
copying of the copies you make or distribute. However, you may accept
|
||||
compensation in exchange for copies. If you distribute a large enough
|
||||
number of copies you must also follow the conditions in section 3.
|
||||
|
||||
You may also lend copies, under the same conditions stated above, and
|
||||
you may publicly display copies.
|
||||
|
||||
@item
|
||||
COPYING IN QUANTITY
|
||||
|
||||
If you publish printed copies (or copies in media that commonly have
|
||||
printed covers) of the Document, numbering more than 100, and the
|
||||
Document's license notice requires Cover Texts, you must enclose the
|
||||
copies in covers that carry, clearly and legibly, all these Cover
|
||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||
the back cover. Both covers must also clearly and legibly identify
|
||||
you as the publisher of these copies. The front cover must present
|
||||
the full title with all words of the title equally prominent and
|
||||
visible. You may add other material on the covers in addition.
|
||||
Copying with changes limited to the covers, as long as they preserve
|
||||
the title of the Document and satisfy these conditions, can be treated
|
||||
as verbatim copying in other respects.
|
||||
|
||||
If the required texts for either cover are too voluminous to fit
|
||||
legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||
pages.
|
||||
|
||||
If you publish or distribute Opaque copies of the Document numbering
|
||||
more than 100, you must either include a machine-readable Transparent
|
||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||
a computer-network location from which the general network-using
|
||||
public has access to download using public-standard network protocols
|
||||
a complete Transparent copy of the Document, free of added material.
|
||||
If you use the latter option, you must take reasonably prudent steps,
|
||||
when you begin distribution of Opaque copies in quantity, to ensure
|
||||
that this Transparent copy will remain thus accessible at the stated
|
||||
location until at least one year after the last time you distribute an
|
||||
Opaque copy (directly or through your agents or retailers) of that
|
||||
edition to the public.
|
||||
|
||||
It is requested, but not required, that you contact the authors of the
|
||||
Document well before redistributing any large number of copies, to give
|
||||
them a chance to provide you with an updated version of the Document.
|
||||
|
||||
@item
|
||||
MODIFICATIONS
|
||||
|
||||
You may copy and distribute a Modified Version of the Document under
|
||||
the conditions of sections 2 and 3 above, provided that you release
|
||||
the Modified Version under precisely this License, with the Modified
|
||||
Version filling the role of the Document, thus licensing distribution
|
||||
and modification of the Modified Version to whoever possesses a copy
|
||||
of it. In addition, you must do these things in the Modified Version:
|
||||
|
||||
@enumerate A
|
||||
@item
|
||||
Use in the Title Page (and on the covers, if any) a title distinct
|
||||
from that of the Document, and from those of previous versions
|
||||
(which should, if there were any, be listed in the History section
|
||||
of the Document). You may use the same title as a previous version
|
||||
if the original publisher of that version gives permission.
|
||||
|
||||
@item
|
||||
List on the Title Page, as authors, one or more persons or entities
|
||||
responsible for authorship of the modifications in the Modified
|
||||
Version, together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has fewer than five),
|
||||
unless they release you from this requirement.
|
||||
|
||||
@item
|
||||
State on the Title page the name of the publisher of the
|
||||
Modified Version, as the publisher.
|
||||
|
||||
@item
|
||||
Preserve all the copyright notices of the Document.
|
||||
|
||||
@item
|
||||
Add an appropriate copyright notice for your modifications
|
||||
adjacent to the other copyright notices.
|
||||
|
||||
@item
|
||||
Include, immediately after the copyright notices, a license notice
|
||||
giving the public permission to use the Modified Version under the
|
||||
terms of this License, in the form shown in the Addendum below.
|
||||
|
||||
@item
|
||||
Preserve in that license notice the full lists of Invariant Sections
|
||||
and required Cover Texts given in the Document's license notice.
|
||||
|
||||
@item
|
||||
Include an unaltered copy of this License.
|
||||
|
||||
@item
|
||||
Preserve the section Entitled ``History'', Preserve its Title, and add
|
||||
to it an item stating at least the title, year, new authors, and
|
||||
publisher of the Modified Version as given on the Title Page. If
|
||||
there is no section Entitled ``History'' in the Document, create one
|
||||
stating the title, year, authors, and publisher of the Document as
|
||||
given on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.
|
||||
|
||||
@item
|
||||
Preserve the network location, if any, given in the Document for
|
||||
public access to a Transparent copy of the Document, and likewise
|
||||
the network locations given in the Document for previous versions
|
||||
it was based on. These may be placed in the ``History'' section.
|
||||
You may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.
|
||||
|
||||
@item
|
||||
For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
|
||||
the Title of the section, and preserve in the section all the
|
||||
substance and tone of each of the contributor acknowledgements and/or
|
||||
dedications given therein.
|
||||
|
||||
@item
|
||||
Preserve all the Invariant Sections of the Document,
|
||||
unaltered in their text and in their titles. Section numbers
|
||||
or the equivalent are not considered part of the section titles.
|
||||
|
||||
@item
|
||||
Delete any section Entitled ``Endorsements''. Such a section
|
||||
may not be included in the Modified Version.
|
||||
|
||||
@item
|
||||
Do not retitle any existing section to be Entitled ``Endorsements'' or
|
||||
to conflict in title with any Invariant Section.
|
||||
|
||||
@item
|
||||
Preserve any Warranty Disclaimers.
|
||||
@end enumerate
|
||||
|
||||
If the Modified Version includes new front-matter sections or
|
||||
appendices that qualify as Secondary Sections and contain no material
|
||||
copied from the Document, you may at your option designate some or all
|
||||
of these sections as invariant. To do this, add their titles to the
|
||||
list of Invariant Sections in the Modified Version's license notice.
|
||||
These titles must be distinct from any other section titles.
|
||||
|
||||
You may add a section Entitled ``Endorsements'', provided it contains
|
||||
nothing but endorsements of your Modified Version by various
|
||||
parties---for example, statements of peer review or that the text has
|
||||
been approved by an organization as the authoritative definition of a
|
||||
standard.
|
||||
|
||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||
of Cover Texts in the Modified Version. Only one passage of
|
||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||
through arrangements made by) any one entity. If the Document already
|
||||
includes a cover text for the same cover, previously added by you or
|
||||
by arrangement made by the same entity you are acting on behalf of,
|
||||
you may not add another; but you may replace the old one, on explicit
|
||||
permission from the previous publisher that added the old one.
|
||||
|
||||
The author(s) and publisher(s) of the Document do not by this License
|
||||
give permission to use their names for publicity for or to assert or
|
||||
imply endorsement of any Modified Version.
|
||||
|
||||
@item
|
||||
COMBINING DOCUMENTS
|
||||
|
||||
You may combine the Document with other documents released under this
|
||||
License, under the terms defined in section 4 above for modified
|
||||
versions, provided that you include in the combination all of the
|
||||
Invariant Sections of all of the original documents, unmodified, and
|
||||
list them all as Invariant Sections of your combined work in its
|
||||
license notice, and that you preserve all their Warranty Disclaimers.
|
||||
|
||||
The combined work need only contain one copy of this License, and
|
||||
multiple identical Invariant Sections may be replaced with a single
|
||||
copy. If there are multiple Invariant Sections with the same name but
|
||||
different contents, make the title of each such section unique by
|
||||
adding at the end of it, in parentheses, the name of the original
|
||||
author or publisher of that section if known, or else a unique number.
|
||||
Make the same adjustment to the section titles in the list of
|
||||
Invariant Sections in the license notice of the combined work.
|
||||
|
||||
In the combination, you must combine any sections Entitled ``History''
|
||||
in the various original documents, forming one section Entitled
|
||||
``History''; likewise combine any sections Entitled ``Acknowledgements'',
|
||||
and any sections Entitled ``Dedications''. You must delete all
|
||||
sections Entitled ``Endorsements.''
|
||||
|
||||
@item
|
||||
COLLECTIONS OF DOCUMENTS
|
||||
|
||||
You may make a collection consisting of the Document and other documents
|
||||
released under this License, and replace the individual copies of this
|
||||
License in the various documents with a single copy that is included in
|
||||
the collection, provided that you follow the rules of this License for
|
||||
verbatim copying of each of the documents in all other respects.
|
||||
|
||||
You may extract a single document from such a collection, and distribute
|
||||
it individually under this License, provided you insert a copy of this
|
||||
License into the extracted document, and follow this License in all
|
||||
other respects regarding verbatim copying of that document.
|
||||
|
||||
@item
|
||||
AGGREGATION WITH INDEPENDENT WORKS
|
||||
|
||||
A compilation of the Document or its derivatives with other separate
|
||||
and independent documents or works, in or on a volume of a storage or
|
||||
distribution medium, is called an ``aggregate'' if the copyright
|
||||
resulting from the compilation is not used to limit the legal rights
|
||||
of the compilation's users beyond what the individual works permit.
|
||||
When the Document is included in an aggregate, this License does not
|
||||
apply to the other works in the aggregate which are not themselves
|
||||
derivative works of the Document.
|
||||
|
||||
If the Cover Text requirement of section 3 is applicable to these
|
||||
copies of the Document, then if the Document is less than one half of
|
||||
the entire aggregate, the Document's Cover Texts may be placed on
|
||||
covers that bracket the Document within the aggregate, or the
|
||||
electronic equivalent of covers if the Document is in electronic form.
|
||||
Otherwise they must appear on printed covers that bracket the whole
|
||||
aggregate.
|
||||
|
||||
@item
|
||||
TRANSLATION
|
||||
|
||||
Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section 4.
|
||||
Replacing Invariant Sections with translations requires special
|
||||
permission from their copyright holders, but you may include
|
||||
translations of some or all Invariant Sections in addition to the
|
||||
original versions of these Invariant Sections. You may include a
|
||||
translation of this License, and all the license notices in the
|
||||
Document, and any Warranty Disclaimers, provided that you also include
|
||||
the original English version of this License and the original versions
|
||||
of those notices and disclaimers. In case of a disagreement between
|
||||
the translation and the original version of this License or a notice
|
||||
or disclaimer, the original version will prevail.
|
||||
|
||||
If a section in the Document is Entitled ``Acknowledgements'',
|
||||
``Dedications'', or ``History'', the requirement (section 4) to Preserve
|
||||
its Title (section 1) will typically require changing the actual
|
||||
title.
|
||||
|
||||
@item
|
||||
TERMINATION
|
||||
|
||||
You may not copy, modify, sublicense, or distribute the Document except
|
||||
as expressly provided for under this License. Any other attempt to
|
||||
copy, modify, sublicense or distribute the Document is void, and will
|
||||
automatically terminate your rights under this License. However,
|
||||
parties who have received copies, or rights, from you under this
|
||||
License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
@item
|
||||
FUTURE REVISIONS OF THIS LICENSE
|
||||
|
||||
The Free Software Foundation may publish new, revised versions
|
||||
of the GNU Free Documentation License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns. See
|
||||
@uref{http://www.gnu.org/copyleft/}.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
License ``or any later version'' applies to it, you have the option of
|
||||
following the terms and conditions either of that specified version or
|
||||
of any later version that has been published (not as a draft) by the
|
||||
Free Software Foundation. If the Document does not specify a version
|
||||
number of this License, you may choose any version ever published (not
|
||||
as a draft) by the Free Software Foundation.
|
||||
@end enumerate
|
||||
|
||||
@page
|
||||
@appendixsubsec ADDENDUM: How to use this License for your documents
|
||||
|
||||
To use this License in a document you have written, include a copy of
|
||||
the License in the document and put the following copyright and
|
||||
license notices just after the title page:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
Copyright (C) @var{year} @var{your name}.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2
|
||||
or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
|
||||
Texts. A copy of the license is included in the section entitled ``GNU
|
||||
Free Documentation License''.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||||
replace the ``with...Texts.'' line with this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
with the Invariant Sections being @var{list their titles}, with
|
||||
the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
|
||||
being @var{list}.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections without Cover Texts, or some other
|
||||
combination of the three, merge those two alternatives to suit the
|
||||
situation.
|
||||
|
||||
If your document contains nontrivial examples of program code, we
|
||||
recommend releasing these examples in parallel under your choice of
|
||||
free software license, such as the GNU General Public License,
|
||||
to permit their use in free software.
|
||||
|
||||
@c Local Variables:
|
||||
@c ispell-local-pdict: "ispell-dict"
|
||||
@c End:
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<!-- $Id: gendocs_template,v 1.2 2005/05/15 03:59:09 eggert Exp $ -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<head>
|
||||
<title>%%TITLE%% - GNU Project - Free Software Foundation (FSF)</title>
|
||||
<meta http-equiv="content-type" content='text/html; charset=utf-8' />
|
||||
<link rel="stylesheet" type="text/css" href="/gnu.css" />
|
||||
<link rev="made" href="mailto:gray@gnu.org" />
|
||||
<link rel="icon" type="image/png" href="/graphics/gnu-head-icon.png" />
|
||||
</head>
|
||||
|
||||
<!-- This document is in XML, and xhtml 1.0 -->
|
||||
<!-- Please make sure to properly nest your tags -->
|
||||
<!-- and ensure that your final document validates -->
|
||||
<!-- consistent with W3C xhtml 1.0 and CSS standards -->
|
||||
<!-- See validator.w3.org -->
|
||||
|
||||
<body>
|
||||
|
||||
<h3>%%TITLE%%</h3>
|
||||
|
||||
<address>Free Software Foundation</address>
|
||||
<address>last updated %%DATE%%</address>
|
||||
<p>
|
||||
<a href="/graphics/gnu-head.jpg">
|
||||
<img src="/graphics/gnu-head-sm.jpg"
|
||||
alt=" [image of the head of a GNU] "
|
||||
width="129" height="122" />
|
||||
</a>
|
||||
<a href="/philosophy/gif.html">(no gifs due to patent problems)</a>
|
||||
</p>
|
||||
<hr />
|
||||
|
||||
The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="%%PACKAGE%%.html">HTML
|
||||
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
|
||||
<li><a href="html_node/index.html">HTML</a> - with one web page per
|
||||
node.</li>
|
||||
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
|
||||
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
|
||||
one web page.</li>
|
||||
<li><a href="%%PACKAGE%%_html_node.tar.gz">HTML compressed
|
||||
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per node.</li>
|
||||
<li><a href="%%PACKAGE%%-info.tar.gz">Info document
|
||||
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt">ASCII text
|
||||
(%%ASCII_SIZE%%K characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
|
||||
(%%ASCII_GZ_SIZE%%K gzipped characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
|
||||
(%%DVI_GZ_SIZE%%K characters gzipped)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.ps.gz">PostScript file
|
||||
(%%PS_GZ_SIZE%%K characters gzipped)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.pdf">PDF file
|
||||
(%%PDF_SIZE%%K characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
|
||||
(%%TEXI_TGZ_SIZE%%K characters gzipped tar file)</a></li>
|
||||
</ul>
|
||||
|
||||
<p>(This page generated by the <a
|
||||
href="%%SCRIPTURL%%">%%SCRIPTNAME%%</a> script.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0!" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
<div class="copyright">
|
||||
<p>
|
||||
Return to the <a href="/home.html">GNU Project home page</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Please send FSF & GNU inquiries to
|
||||
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
|
||||
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
|
||||
the FSF.
|
||||
<br />
|
||||
Please send broken links and other corrections (or suggestions) to
|
||||
<a href="mailto:webmasters@gnu.org"><em>webmasters@gnu.org</em></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02111, USA
|
||||
<br />
|
||||
Verbatim copying and distribution of this entire article is
|
||||
permitted in any medium, provided this notice is preserved.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Updated:
|
||||
<!-- timestamp start -->
|
||||
$Date: 2005/05/15 03:59:09 $ $Author: eggert $
|
||||
<!-- timestamp end -->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
432
doc/getdate.texi
Normal file
432
doc/getdate.texi
Normal file
@@ -0,0 +1,432 @@
|
||||
@node Date input formats
|
||||
@chapter Date input formats
|
||||
|
||||
@c Copyright 1994, 1995, 1996, 1997, 1999, 2000, 2001 Free Software
|
||||
@c Foundation, Inc.
|
||||
|
||||
@c Permission is granted to copy, distribute and/or modify this document
|
||||
@c under the terms of the GNU Free Documentation License, Version 1.1
|
||||
@c or any later version published by the Free Software Foundation;
|
||||
@c with no Invariant Sections, with no
|
||||
@c Front-Cover Texts, and with no Back-Cover Texts.
|
||||
@c A copy of the license is included in the section entitled ``GNU
|
||||
@c Free Documentation License''.
|
||||
|
||||
@cindex date input formats
|
||||
@findex getdate
|
||||
|
||||
First, a quote:
|
||||
|
||||
@quotation
|
||||
Our units of temporal measurement, from seconds on up to months, are so
|
||||
complicated, asymmetrical and disjunctive so as to make coherent mental
|
||||
reckoning in time all but impossible. Indeed, had some tyrannical god
|
||||
contrived to enslave our minds to time, to make it all but impossible
|
||||
for us to escape subjection to sodden routines and unpleasant surprises,
|
||||
he could hardly have done better than handing down our present system.
|
||||
It is like a set of trapezoidal building blocks, with no vertical or
|
||||
horizontal surfaces, like a language in which the simplest thought
|
||||
demands ornate constructions, useless particles and lengthy
|
||||
circumlocutions. Unlike the more successful patterns of language and
|
||||
science, which enable us to face experience boldly or at least
|
||||
level-headedly, our system of temporal calculation silently and
|
||||
persistently encourages our terror of time.
|
||||
|
||||
@dots{} It is as though architects had to measure length in feet, width
|
||||
in meters and height in ells; as though basic instruction manuals
|
||||
demanded a knowledge of five different languages. It is no wonder then
|
||||
that we often look into our own immediate past or future, last Tuesday
|
||||
or a week from Sunday, with feelings of helpless confusion. @dots{}
|
||||
|
||||
--- Robert Grudin, @cite{Time and the Art of Living}.
|
||||
@end quotation
|
||||
|
||||
This section describes the textual date representations that @sc{gnu}
|
||||
programs accept. These are the strings you, as a user, can supply as
|
||||
arguments to the various programs. The C interface (via the
|
||||
@code{getdate} function) is not described here.
|
||||
|
||||
@cindex beginning of time, for @sc{posix}
|
||||
@cindex epoch, for @sc{posix}
|
||||
Although the date syntax here can represent any possible time since the
|
||||
year zero, computer integers often cannot represent such a wide range of
|
||||
time. On @sc{posix} systems, the clock starts at 1970-01-01 00:00:00
|
||||
@sc{utc}: @sc{posix} does not require support for times before the
|
||||
@sc{posix} Epoch and times far in the future. Traditional Unix systems
|
||||
have 32-bit signed @code{time_t} and can represent times from 1901-12-13
|
||||
20:45:52 through 2038-01-19 03:14:07 @sc{utc}. Systems with 64-bit
|
||||
signed @code{time_t} can represent all the times in the known
|
||||
lifetime of the universe.
|
||||
|
||||
@menu
|
||||
* General date syntax:: Common rules.
|
||||
* Calendar date items:: 19 Dec 1994.
|
||||
* Time of day items:: 9:20pm.
|
||||
* Time zone items:: @sc{est}, @sc{pdt}, @sc{gmt}, ...
|
||||
* Day of week items:: Monday and others.
|
||||
* Relative items in date strings:: next tuesday, 2 years ago.
|
||||
* Pure numbers in date strings:: 19931219, 1440.
|
||||
* Authors of getdate:: Bellovin, Eggert, Salz, Berets, et al.
|
||||
@end menu
|
||||
|
||||
|
||||
@node General date syntax
|
||||
@section General date syntax
|
||||
|
||||
@cindex general date syntax
|
||||
|
||||
@cindex items in date strings
|
||||
A @dfn{date} is a string, possibly empty, containing many items
|
||||
separated by whitespace. The whitespace may be omitted when no
|
||||
ambiguity arises. The empty string means the beginning of today (i.e.,
|
||||
midnight). Order of the items is immaterial. A date string may contain
|
||||
many flavors of items:
|
||||
|
||||
@itemize @bullet
|
||||
@item calendar date items
|
||||
@item time of the day items
|
||||
@item time zone items
|
||||
@item day of the week items
|
||||
@item relative items
|
||||
@item pure numbers.
|
||||
@end itemize
|
||||
|
||||
@noindent We describe each of these item types in turn, below.
|
||||
|
||||
@cindex numbers, written-out
|
||||
@cindex ordinal numbers
|
||||
@findex first @r{in date strings}
|
||||
@findex next @r{in date strings}
|
||||
@findex last @r{in date strings}
|
||||
A few numbers may be written out in words in most contexts. This is
|
||||
most useful for specifying day of the week items or relative items (see
|
||||
below). Here is the list: @samp{first} for 1, @samp{next} for 2,
|
||||
@samp{third} for 3, @samp{fourth} for 4, @samp{fifth} for 5,
|
||||
@samp{sixth} for 6, @samp{seventh} for 7, @samp{eighth} for 8,
|
||||
@samp{ninth} for 9, @samp{tenth} for 10, @samp{eleventh} for 11 and
|
||||
@samp{twelfth} for 12. Also, @samp{last} means exactly @math{-1}.
|
||||
|
||||
@cindex months, written-out
|
||||
When a month is written this way, it is still considered to be written
|
||||
numerically, instead of being ``spelled in full''; this changes the
|
||||
allowed strings.
|
||||
|
||||
@cindex language, in dates
|
||||
In the current implementation, only English is supported for words and
|
||||
abbreviations like @samp{AM}, @samp{DST}, @samp{EST}, @samp{first},
|
||||
@samp{January}, @samp{Sunday}, @samp{tomorrow}, and @samp{year}.
|
||||
|
||||
@cindex language, in dates
|
||||
@cindex time zone item
|
||||
The output of @command{date} is not always acceptable as a date string,
|
||||
not only because of the language problem, but also because there is no
|
||||
standard meaning for time zone items like @samp{IST}. When using
|
||||
@command{date} to generate a date string intended to be parsed later,
|
||||
specify a date format that is independent of language and that does not
|
||||
use time zone items other than @samp{UTC} and @samp{Z}. Here are some
|
||||
ways to do this:
|
||||
|
||||
@example
|
||||
$ LC_ALL=C TZ=UTC0 date
|
||||
Fri Dec 15 19:48:05 UTC 2000
|
||||
$ TZ=UTC0 date +"%Y-%m-%d %H:%M:%SZ"
|
||||
2000-12-15 19:48:05Z
|
||||
$ date --iso-8601=seconds # a GNU extension
|
||||
2000-12-15T11:48:05-0800
|
||||
$ date --rfc-822 # a GNU extension
|
||||
Fri, 15 Dec 2000 11:48:05 -0800
|
||||
$ date +"%Y-%m-%d %H:%M:%S %z" # %z is a GNU extension.
|
||||
2000-12-15 11:48:05 -0800
|
||||
@end example
|
||||
|
||||
@cindex case, ignored in dates
|
||||
@cindex comments, in dates
|
||||
Alphabetic case is completely ignored in dates. Comments may be introduced
|
||||
between round parentheses, as long as included parentheses are properly
|
||||
nested. Hyphens not followed by a digit are currently ignored. Leading
|
||||
zeros on numbers are ignored.
|
||||
|
||||
|
||||
@node Calendar date items
|
||||
@section Calendar date items
|
||||
|
||||
@cindex calendar date item
|
||||
|
||||
A @dfn{calendar date item} specifies a day of the year. It is
|
||||
specified differently, depending on whether the month is specified
|
||||
numerically or literally. All these strings specify the same calendar date:
|
||||
|
||||
@example
|
||||
1972-09-24 # @sc{iso} 8601.
|
||||
72-9-24 # Assume 19xx for 69 through 99,
|
||||
# 20xx for 00 through 68.
|
||||
72-09-24 # Leading zeros are ignored.
|
||||
9/24/72 # Common U.S. writing.
|
||||
24 September 1972
|
||||
24 Sept 72 # September has a special abbreviation.
|
||||
24 Sep 72 # Three-letter abbreviations always allowed.
|
||||
Sep 24, 1972
|
||||
24-sep-72
|
||||
24sep72
|
||||
@end example
|
||||
|
||||
The year can also be omitted. In this case, the last specified year is
|
||||
used, or the current year if none. For example:
|
||||
|
||||
@example
|
||||
9/24
|
||||
sep 24
|
||||
@end example
|
||||
|
||||
Here are the rules.
|
||||
|
||||
@cindex @sc{iso} 8601 date format
|
||||
@cindex date format, @sc{iso} 8601
|
||||
For numeric months, the @sc{iso} 8601 format
|
||||
@samp{@var{year}-@var{month}-@var{day}} is allowed, where @var{year} is
|
||||
any positive number, @var{month} is a number between 01 and 12, and
|
||||
@var{day} is a number between 01 and 31. A leading zero must be present
|
||||
if a number is less than ten. If @var{year} is 68 or smaller, then 2000
|
||||
is added to it; otherwise, if @var{year} is less than 100,
|
||||
then 1900 is added to it. The construct
|
||||
@samp{@var{month}/@var{day}/@var{year}}, popular in the United States,
|
||||
is accepted. Also @samp{@var{month}/@var{day}}, omitting the year.
|
||||
|
||||
@cindex month names in date strings
|
||||
@cindex abbreviations for months
|
||||
Literal months may be spelled out in full: @samp{January},
|
||||
@samp{February}, @samp{March}, @samp{April}, @samp{May}, @samp{June},
|
||||
@samp{July}, @samp{August}, @samp{September}, @samp{October},
|
||||
@samp{November} or @samp{December}. Literal months may be abbreviated
|
||||
to their first three letters, possibly followed by an abbreviating dot.
|
||||
It is also permitted to write @samp{Sept} instead of @samp{September}.
|
||||
|
||||
When months are written literally, the calendar date may be given as any
|
||||
of the following:
|
||||
|
||||
@example
|
||||
@var{day} @var{month} @var{year}
|
||||
@var{day} @var{month}
|
||||
@var{month} @var{day} @var{year}
|
||||
@var{day}-@var{month}-@var{year}
|
||||
@end example
|
||||
|
||||
Or, omitting the year:
|
||||
|
||||
@example
|
||||
@var{month} @var{day}
|
||||
@end example
|
||||
|
||||
|
||||
@node Time of day items
|
||||
@section Time of day items
|
||||
|
||||
@cindex time of day item
|
||||
|
||||
A @dfn{time of day item} in date strings specifies the time on a given
|
||||
day. Here are some examples, all of which represent the same time:
|
||||
|
||||
@example
|
||||
20:02:0
|
||||
20:02
|
||||
8:02pm
|
||||
20:02-0500 # In @sc{est} (U.S. Eastern Standard Time).
|
||||
@end example
|
||||
|
||||
More generally, the time of the day may be given as
|
||||
@samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is
|
||||
a number between 0 and 23, @var{minute} is a number between 0 and
|
||||
59, and @var{second} is a number between 0 and 59. Alternatively,
|
||||
@samp{:@var{second}} can be omitted, in which case it is taken to
|
||||
be zero.
|
||||
|
||||
@findex am @r{in date strings}
|
||||
@findex pm @r{in date strings}
|
||||
@findex midnight @r{in date strings}
|
||||
@findex noon @r{in date strings}
|
||||
If the time is followed by @samp{am} or @samp{pm} (or @samp{a.m.}
|
||||
or @samp{p.m.}), @var{hour} is restricted to run from 1 to 12, and
|
||||
@samp{:@var{minute}} may be omitted (taken to be zero). @samp{am}
|
||||
indicates the first half of the day, @samp{pm} indicates the second
|
||||
half of the day. In this notation, 12 is the predecessor of 1:
|
||||
midnight is @samp{12am} while noon is @samp{12pm}.
|
||||
(This is the zero-oriented interpretation of @samp{12am} and @samp{12pm},
|
||||
as opposed to the old tradition derived from Latin
|
||||
which uses @samp{12m} for noon and @samp{12pm} for midnight.)
|
||||
|
||||
@cindex time zone correction
|
||||
@cindex minutes, time zone correction by
|
||||
The time may alternatively be followed by a time zone correction,
|
||||
expressed as @samp{@var{s}@var{hh}@var{mm}}, where @var{s} is @samp{+}
|
||||
or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number
|
||||
of zone minutes. When a time zone correction is given this way, it
|
||||
forces interpretation of the time relative to
|
||||
Coordinated Universal Time (@sc{utc}), overriding any previous
|
||||
specification for the time zone or the local time zone. The @var{minute}
|
||||
part of the time of the day may not be elided when a time zone correction
|
||||
is used. This is the best way to specify a time zone correction by
|
||||
fractional parts of an hour.
|
||||
|
||||
Either @samp{am}/@samp{pm} or a time zone correction may be specified,
|
||||
but not both.
|
||||
|
||||
|
||||
@node Time zone items
|
||||
@section Time zone items
|
||||
|
||||
@cindex time zone item
|
||||
|
||||
A @dfn{time zone item} specifies an international time zone, indicated
|
||||
by a small set of letters, e.g., @samp{UTC} or @samp{Z}
|
||||
for Coordinated Universal
|
||||
Time. Any included periods are ignored. By following a
|
||||
non-daylight-saving time zone by the string @samp{DST} in a separate
|
||||
word (that is, separated by some white space), the corresponding
|
||||
daylight saving time zone may be specified.
|
||||
|
||||
Time zone items other than @samp{UTC} and @samp{Z}
|
||||
are obsolescent and are not recommended, because they
|
||||
are ambiguous; for example, @samp{EST} has a different meaning in
|
||||
Australia than in the United States. Instead, it's better to use
|
||||
unambiguous numeric time zone corrections like @samp{-0500}, as
|
||||
described in the previous section.
|
||||
|
||||
|
||||
@node Day of week items
|
||||
@section Day of week items
|
||||
|
||||
@cindex day of week item
|
||||
|
||||
The explicit mention of a day of the week will forward the date
|
||||
(only if necessary) to reach that day of the week in the future.
|
||||
|
||||
Days of the week may be spelled out in full: @samp{Sunday},
|
||||
@samp{Monday}, @samp{Tuesday}, @samp{Wednesday}, @samp{Thursday},
|
||||
@samp{Friday} or @samp{Saturday}. Days may be abbreviated to their
|
||||
first three letters, optionally followed by a period. The special
|
||||
abbreviations @samp{Tues} for @samp{Tuesday}, @samp{Wednes} for
|
||||
@samp{Wednesday} and @samp{Thur} or @samp{Thurs} for @samp{Thursday} are
|
||||
also allowed.
|
||||
|
||||
@findex next @var{day}
|
||||
@findex last @var{day}
|
||||
A number may precede a day of the week item to move forward
|
||||
supplementary weeks. It is best used in expression like @samp{third
|
||||
monday}. In this context, @samp{last @var{day}} or @samp{next
|
||||
@var{day}} is also acceptable; they move one week before or after
|
||||
the day that @var{day} by itself would represent.
|
||||
|
||||
A comma following a day of the week item is ignored.
|
||||
|
||||
|
||||
@node Relative items in date strings
|
||||
@section Relative items in date strings
|
||||
|
||||
@cindex relative items in date strings
|
||||
@cindex displacement of dates
|
||||
|
||||
@dfn{Relative items} adjust a date (or the current date if none) forward
|
||||
or backward. The effects of relative items accumulate. Here are some
|
||||
examples:
|
||||
|
||||
@example
|
||||
1 year
|
||||
1 year ago
|
||||
3 years
|
||||
2 days
|
||||
@end example
|
||||
|
||||
@findex year @r{in date strings}
|
||||
@findex month @r{in date strings}
|
||||
@findex fortnight @r{in date strings}
|
||||
@findex week @r{in date strings}
|
||||
@findex day @r{in date strings}
|
||||
@findex hour @r{in date strings}
|
||||
@findex minute @r{in date strings}
|
||||
The unit of time displacement may be selected by the string @samp{year}
|
||||
or @samp{month} for moving by whole years or months. These are fuzzy
|
||||
units, as years and months are not all of equal duration. More precise
|
||||
units are @samp{fortnight} which is worth 14 days, @samp{week} worth 7
|
||||
days, @samp{day} worth 24 hours, @samp{hour} worth 60 minutes,
|
||||
@samp{minute} or @samp{min} worth 60 seconds, and @samp{second} or
|
||||
@samp{sec} worth one second. An @samp{s} suffix on these units is
|
||||
accepted and ignored.
|
||||
|
||||
@findex ago @r{in date strings}
|
||||
The unit of time may be preceded by a multiplier, given as an optionally
|
||||
signed number. Unsigned numbers are taken as positively signed. No
|
||||
number at all implies 1 for a multiplier. Following a relative item by
|
||||
the string @samp{ago} is equivalent to preceding the unit by a
|
||||
multiplier with value @math{-1}.
|
||||
|
||||
@findex day @r{in date strings}
|
||||
@findex tomorrow @r{in date strings}
|
||||
@findex yesterday @r{in date strings}
|
||||
The string @samp{tomorrow} is worth one day in the future (equivalent
|
||||
to @samp{day}), the string @samp{yesterday} is worth
|
||||
one day in the past (equivalent to @samp{day ago}).
|
||||
|
||||
@findex now @r{in date strings}
|
||||
@findex today @r{in date strings}
|
||||
@findex this @r{in date strings}
|
||||
The strings @samp{now} or @samp{today} are relative items corresponding
|
||||
to zero-valued time displacement, these strings come from the fact
|
||||
a zero-valued time displacement represents the current time when not
|
||||
otherwise changed by previous items. They may be used to stress other
|
||||
items, like in @samp{12:00 today}. The string @samp{this} also has
|
||||
the meaning of a zero-valued time displacement, but is preferred in
|
||||
date strings like @samp{this thursday}.
|
||||
|
||||
When a relative item causes the resulting date to cross a boundary
|
||||
where the clocks were adjusted, typically for daylight-saving time,
|
||||
the resulting date and time are adjusted accordingly.
|
||||
|
||||
|
||||
@node Pure numbers in date strings
|
||||
@section Pure numbers in date strings
|
||||
|
||||
@cindex pure numbers in date strings
|
||||
|
||||
The precise interpretation of a pure decimal number depends
|
||||
on the context in the date string.
|
||||
|
||||
If the decimal number is of the form @var{yyyy}@var{mm}@var{dd} and no
|
||||
other calendar date item (@pxref{Calendar date items}) appears before it
|
||||
in the date string, then @var{yyyy} is read as the year, @var{mm} as the
|
||||
month number and @var{dd} as the day of the month, for the specified
|
||||
calendar date.
|
||||
|
||||
If the decimal number is of the form @var{hh}@var{mm} and no other time
|
||||
of day item appears before it in the date string, then @var{hh} is read
|
||||
as the hour of the day and @var{mm} as the minute of the hour, for the
|
||||
specified time of the day. @var{mm} can also be omitted.
|
||||
|
||||
If both a calendar date and a time of day appear to the left of a number
|
||||
in the date string, but no relative item, then the number overrides the
|
||||
year.
|
||||
|
||||
|
||||
@node Authors of getdate
|
||||
@section Authors of @code{getdate}
|
||||
|
||||
@cindex authors of @code{getdate}
|
||||
|
||||
@cindex Bellovin, Steven M.
|
||||
@cindex Salz, Rich
|
||||
@cindex Berets, Jim
|
||||
@cindex MacKenzie, David
|
||||
@cindex Meyering, Jim
|
||||
@cindex Eggert, Paul
|
||||
@code{getdate} was originally implemented by Steven M. Bellovin
|
||||
(@email{smb@@research.att.com}) while at the University of North Carolina
|
||||
at Chapel Hill. The code was later tweaked by a couple of people on
|
||||
Usenet, then completely overhauled by Rich $alz (@email{rsalz@@bbn.com})
|
||||
and Jim Berets (@email{jberets@@bbn.com}) in August, 1990. Various
|
||||
revisions for the @sc{gnu} system were made by David MacKenzie, Jim Meyering,
|
||||
Paul Eggert and others.
|
||||
|
||||
@cindex Pinard, F.
|
||||
@cindex Berry, K.
|
||||
This chapter was originally produced by Fran@,{c}ois Pinard
|
||||
(@email{pinard@@iro.umontreal.ca}) from the @file{getdate.y} source code,
|
||||
and then edited by K.@: Berry (@email{kb@@cs.umb.edu}).
|
||||
335
doc/intern.texi
335
doc/intern.texi
@@ -1,335 +0,0 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@menu
|
||||
* Standard:: Basic Tar Format
|
||||
* Extensions:: @acronym{GNU} Extensions to the Archive Format
|
||||
* Sparse Formats:: Storing Sparse Files
|
||||
* Snapshot Files::
|
||||
* Dumpdir::
|
||||
@end menu
|
||||
|
||||
@node Standard
|
||||
@unnumberedsec Basic Tar Format
|
||||
@UNREVISED
|
||||
|
||||
While an archive may contain many files, the archive itself is a
|
||||
single ordinary file. Like any other file, an archive file can be
|
||||
written to a storage device such as a tape or disk, sent through a
|
||||
pipe or over a network, saved on the active file system, or even
|
||||
stored in another archive. An archive file is not easy to read or
|
||||
manipulate without using the @command{tar} utility or Tar mode in
|
||||
@acronym{GNU} Emacs.
|
||||
|
||||
Physically, an archive consists of a series of file entries terminated
|
||||
by an end-of-archive entry, which consists of two 512 blocks of zero
|
||||
bytes. A file
|
||||
entry usually describes one of the files in the archive (an
|
||||
@dfn{archive member}), and consists of a file header and the contents
|
||||
of the file. File headers contain file names and statistics, checksum
|
||||
information which @command{tar} uses to detect file corruption, and
|
||||
information about file types.
|
||||
|
||||
Archives are permitted to have more than one member with the same
|
||||
member name. One way this situation can occur is if more than one
|
||||
version of a file has been stored in the archive. For information
|
||||
about adding new versions of a file to an archive, see @ref{update}.
|
||||
@FIXME-xref{To learn more about having more than one archive member with the
|
||||
same name, see -backup node, when it's written.}
|
||||
|
||||
In addition to entries describing archive members, an archive may
|
||||
contain entries which @command{tar} itself uses to store information.
|
||||
@xref{label}, for an example of such an archive entry.
|
||||
|
||||
A @command{tar} archive file contains a series of blocks. Each block
|
||||
contains @code{BLOCKSIZE} bytes. Although this format may be thought
|
||||
of as being on magnetic tape, other media are often used.
|
||||
|
||||
Each file archived is represented by a header block which describes
|
||||
the file, followed by zero or more blocks which give the contents
|
||||
of the file. At the end of the archive file there are two 512-byte blocks
|
||||
filled with binary zeros as an end-of-file marker. A reasonable system
|
||||
should write such end-of-file marker at the end of an archive, but
|
||||
must not assume that such a block exists when reading an archive. In
|
||||
particular @GNUTAR{} always issues a warning if it does not encounter it.
|
||||
|
||||
The blocks may be @dfn{blocked} for physical I/O operations.
|
||||
Each record of @var{n} blocks (where @var{n} is set by the
|
||||
@option{--blocking-factor=@var{512-size}} (@option{-b @var{512-size}}) option to @command{tar}) is written with a single
|
||||
@w{@samp{write ()}} operation. On magnetic tapes, the result of
|
||||
such a write is a single record. When writing an archive,
|
||||
the last record of blocks should be written at the full size, with
|
||||
blocks after the zero block containing all zeros. When reading
|
||||
an archive, a reasonable system should properly handle an archive
|
||||
whose last record is shorter than the rest, or which contains garbage
|
||||
records after a zero block.
|
||||
|
||||
The header block is defined in C as follows. In the @GNUTAR{}
|
||||
distribution, this is part of file @file{src/tar.h}:
|
||||
|
||||
@smallexample
|
||||
@include header.texi
|
||||
@end smallexample
|
||||
|
||||
All characters in header blocks are represented by using 8-bit
|
||||
characters in the local variant of ASCII. Each field within the
|
||||
structure is contiguous; that is, there is no padding used within
|
||||
the structure. Each character on the archive medium is stored
|
||||
contiguously.
|
||||
|
||||
Bytes representing the contents of files (after the header block
|
||||
of each file) are not translated in any way and are not constrained
|
||||
to represent characters in any character set. The @command{tar} format
|
||||
does not distinguish text files from binary files, and no translation
|
||||
of file contents is performed.
|
||||
|
||||
The @code{name}, @code{linkname}, @code{magic}, @code{uname}, and
|
||||
@code{gname} are null-terminated character strings. All other fields
|
||||
are zero-filled octal numbers in ASCII. Each numeric field of width
|
||||
@var{w} contains @var{w} minus 1 digits, and a null.
|
||||
|
||||
The @code{name} field is the file name of the file, with directory names
|
||||
(if any) preceding the file name, separated by slashes.
|
||||
|
||||
@FIXME{how big a name before field overflows?}
|
||||
|
||||
The @code{mode} field provides nine bits specifying file permissions
|
||||
and three bits to specify the Set UID, Set GID, and Save Text
|
||||
(@dfn{sticky}) modes. Values for these bits are defined above.
|
||||
When special permissions are required to create a file with a given
|
||||
mode, and the user restoring files from the archive does not hold such
|
||||
permissions, the mode bit(s) specifying those special permissions
|
||||
are ignored. Modes which are not supported by the operating system
|
||||
restoring files from the archive will be ignored. Unsupported modes
|
||||
should be faked up when creating or updating an archive; e.g., the
|
||||
group permission could be copied from the @emph{other} permission.
|
||||
|
||||
The @code{uid} and @code{gid} fields are the numeric user and group
|
||||
ID of the file owners, respectively. If the operating system does
|
||||
not support numeric user or group IDs, these fields should be ignored.
|
||||
|
||||
The @code{size} field is the size of the file in bytes; linked files
|
||||
are archived with this field specified as zero. @FIXME-xref{Modifiers, in
|
||||
particular the @option{--incremental} (@option{-G}) option.}
|
||||
|
||||
The @code{mtime} field is the data modification time of the file at
|
||||
the time it was archived. It is the ASCII representation of the octal
|
||||
value of the last time the file's contents were modified, represented
|
||||
as an integer number of
|
||||
seconds since January 1, 1970, 00:00 Coordinated Universal Time.
|
||||
|
||||
The @code{chksum} field is the ASCII representation of the octal value
|
||||
of the simple sum of all bytes in the header block. Each 8-bit
|
||||
byte in the header is added to an unsigned integer, initialized to
|
||||
zero, the precision of which shall be no less than seventeen bits.
|
||||
When calculating the checksum, the @code{chksum} field is treated as
|
||||
if it were all blanks.
|
||||
|
||||
The @code{typeflag} field specifies the type of file archived. If a
|
||||
particular implementation does not recognize or permit the specified
|
||||
type, the file will be extracted as if it were a regular file. As this
|
||||
action occurs, @command{tar} issues a warning to the standard error.
|
||||
|
||||
The @code{atime} and @code{ctime} fields are used in making incremental
|
||||
backups; they store, respectively, the particular file's access and
|
||||
status change times.
|
||||
|
||||
The @code{offset} is used by the @option{--multi-volume} (@option{-M}) option, when
|
||||
making a multi-volume archive. The offset is number of bytes into
|
||||
the file that we need to restart at to continue the file on the next
|
||||
tape, i.e., where we store the location that a continued file is
|
||||
continued at.
|
||||
|
||||
The following fields were added to deal with sparse files. A file
|
||||
is @dfn{sparse} if it takes in unallocated blocks which end up being
|
||||
represented as zeros, i.e., no useful data. A test to see if a file
|
||||
is sparse is to look at the number blocks allocated for it versus the
|
||||
number of characters in the file; if there are fewer blocks allocated
|
||||
for the file than would normally be allocated for a file of that
|
||||
size, then the file is sparse. This is the method @command{tar} uses to
|
||||
detect a sparse file, and once such a file is detected, it is treated
|
||||
differently from non-sparse files.
|
||||
|
||||
Sparse files are often @code{dbm} files, or other database-type files
|
||||
which have data at some points and emptiness in the greater part of
|
||||
the file. Such files can appear to be very large when an @samp{ls
|
||||
-l} is done on them, when in truth, there may be a very small amount
|
||||
of important data contained in the file. It is thus undesirable
|
||||
to have @command{tar} think that it must back up this entire file, as
|
||||
great quantities of room are wasted on empty blocks, which can lead
|
||||
to running out of room on a tape far earlier than is necessary.
|
||||
Thus, sparse files are dealt with so that these empty blocks are
|
||||
not written to the tape. Instead, what is written to the tape is a
|
||||
description, of sorts, of the sparse file: where the holes are, how
|
||||
big the holes are, and how much data is found at the end of the hole.
|
||||
This way, the file takes up potentially far less room on the tape,
|
||||
and when the file is extracted later on, it will look exactly the way
|
||||
it looked beforehand. The following is a description of the fields
|
||||
used to handle a sparse file:
|
||||
|
||||
The @code{sp} is an array of @code{struct sparse}. Each @code{struct
|
||||
sparse} contains two 12-character strings which represent an offset
|
||||
into the file and a number of bytes to be written at that offset.
|
||||
The offset is absolute, and not relative to the offset in preceding
|
||||
array element.
|
||||
|
||||
The header can hold four of these @code{struct sparse} at the moment;
|
||||
if more are needed, they are not stored in the header.
|
||||
|
||||
The @code{isextended} flag is set when an @code{extended_header}
|
||||
is needed to deal with a file. Note that this means that this flag
|
||||
can only be set when dealing with a sparse file, and it is only set
|
||||
in the event that the description of the file will not fit in the
|
||||
allotted room for sparse structures in the header. In other words,
|
||||
an extended_header is needed.
|
||||
|
||||
The @code{extended_header} structure is used for sparse files which
|
||||
need more sparse structures than can fit in the header. The header can
|
||||
fit 4 such structures; if more are needed, the flag @code{isextended}
|
||||
gets set and the next block is an @code{extended_header}.
|
||||
|
||||
Each @code{extended_header} structure contains an array of 21
|
||||
sparse structures, along with a similar @code{isextended} flag
|
||||
that the header had. There can be an indeterminate number of such
|
||||
@code{extended_header}s to describe a sparse file.
|
||||
|
||||
@table @asis
|
||||
|
||||
@item @code{REGTYPE}
|
||||
@itemx @code{AREGTYPE}
|
||||
These flags represent a regular file. In order to be compatible
|
||||
with older versions of @command{tar}, a @code{typeflag} value of
|
||||
@code{AREGTYPE} should be silently recognized as a regular file.
|
||||
New archives should be created using @code{REGTYPE}. Also, for
|
||||
backward compatibility, @command{tar} treats a regular file whose name
|
||||
ends with a slash as a directory.
|
||||
|
||||
@item @code{LNKTYPE}
|
||||
This flag represents a file linked to another file, of any type,
|
||||
previously archived. Such files are identified in Unix by each
|
||||
file having the same device and inode number. The linked-to name is
|
||||
specified in the @code{linkname} field with a trailing null.
|
||||
|
||||
@item @code{SYMTYPE}
|
||||
This represents a symbolic link to another file. The linked-to name
|
||||
is specified in the @code{linkname} field with a trailing null.
|
||||
|
||||
@item @code{CHRTYPE}
|
||||
@itemx @code{BLKTYPE}
|
||||
These represent character special files and block special files
|
||||
respectively. In this case the @code{devmajor} and @code{devminor}
|
||||
fields will contain the major and minor device numbers respectively.
|
||||
Operating systems may map the device specifications to their own
|
||||
local specification, or may ignore the entry.
|
||||
|
||||
@item @code{DIRTYPE}
|
||||
This flag specifies a directory or sub-directory. The directory
|
||||
name in the @code{name} field should end with a slash. On systems where
|
||||
disk allocation is performed on a directory basis, the @code{size} field
|
||||
will contain the maximum number of bytes (which may be rounded to
|
||||
the nearest disk block allocation unit) which the directory may
|
||||
hold. A @code{size} field of zero indicates no such limiting. Systems
|
||||
which do not support limiting in this manner should ignore the
|
||||
@code{size} field.
|
||||
|
||||
@item @code{FIFOTYPE}
|
||||
This specifies a FIFO special file. Note that the archiving of a
|
||||
FIFO file archives the existence of this file and not its contents.
|
||||
|
||||
@item @code{CONTTYPE}
|
||||
This specifies a contiguous file, which is the same as a normal
|
||||
file except that, in operating systems which support it, all its
|
||||
space is allocated contiguously on the disk. Operating systems
|
||||
which do not allow contiguous allocation should silently treat this
|
||||
type as a normal file.
|
||||
|
||||
@item @code{A} @dots{} @code{Z}
|
||||
These are reserved for custom implementations. Some of these are
|
||||
used in the @acronym{GNU} modified format, as described below.
|
||||
|
||||
@end table
|
||||
|
||||
Other values are reserved for specification in future revisions of
|
||||
the P1003 standard, and should not be used by any @command{tar} program.
|
||||
|
||||
The @code{magic} field indicates that this archive was output in
|
||||
the P1003 archive format. If this field contains @code{TMAGIC},
|
||||
the @code{uname} and @code{gname} fields will contain the ASCII
|
||||
representation of the owner and group of the file respectively.
|
||||
If found, the user and group IDs are used rather than the values in
|
||||
the @code{uid} and @code{gid} fields.
|
||||
|
||||
For references, see ISO/IEC 9945-1:1990 or IEEE Std 1003.1-1990, pages
|
||||
169-173 (section 10.1) for @cite{Archive/Interchange File Format}; and
|
||||
IEEE Std 1003.2-1992, pages 380-388 (section 4.48) and pages 936-940
|
||||
(section E.4.48) for @cite{pax - Portable archive interchange}.
|
||||
|
||||
@node Extensions
|
||||
@unnumberedsec @acronym{GNU} Extensions to the Archive Format
|
||||
@UNREVISED
|
||||
|
||||
The @acronym{GNU} format uses additional file types to describe new types of
|
||||
files in an archive. These are listed below.
|
||||
|
||||
@table @code
|
||||
@item GNUTYPE_DUMPDIR
|
||||
@itemx 'D'
|
||||
This represents a directory and a list of files created by the
|
||||
@option{--incremental} (@option{-G}) option. The @code{size} field gives the total
|
||||
size of the associated list of files. Each file name is preceded by
|
||||
either a @samp{Y} (the file should be in this archive) or an @samp{N}.
|
||||
(The file is a directory, or is not stored in the archive.) Each file
|
||||
name is terminated by a null. There is an additional null after the
|
||||
last file name.
|
||||
|
||||
@item GNUTYPE_MULTIVOL
|
||||
@itemx 'M'
|
||||
This represents a file continued from another volume of a multi-volume
|
||||
archive created with the @option{--multi-volume} (@option{-M}) option. The original
|
||||
type of the file is not given here. The @code{size} field gives the
|
||||
maximum size of this piece of the file (assuming the volume does
|
||||
not end before the file is written out). The @code{offset} field
|
||||
gives the offset from the beginning of the file where this part of
|
||||
the file begins. Thus @code{size} plus @code{offset} should equal
|
||||
the original size of the file.
|
||||
|
||||
@item GNUTYPE_SPARSE
|
||||
@itemx 'S'
|
||||
This flag indicates that we are dealing with a sparse file. Note
|
||||
that archiving a sparse file requires special operations to find
|
||||
holes in the file, which mark the positions of these holes, along
|
||||
with the number of bytes of data to be found after the hole.
|
||||
|
||||
@item GNUTYPE_VOLHDR
|
||||
@itemx 'V'
|
||||
This file type is used to mark the volume header that was given with
|
||||
the @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) option when the archive was created. The @code{name}
|
||||
field contains the @code{name} given after the @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) option.
|
||||
The @code{size} field is zero. Only the first file in each volume
|
||||
of an archive should have this type.
|
||||
|
||||
@end table
|
||||
|
||||
You may have trouble reading a @acronym{GNU} format archive on a
|
||||
non-@acronym{GNU} system if the options @option{--incremental} (@option{-G}),
|
||||
@option{--multi-volume} (@option{-M}), @option{--sparse} (@option{-S}), or @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) were
|
||||
used when writing the archive. In general, if @command{tar} does not
|
||||
use the @acronym{GNU}-added fields of the header, other versions of
|
||||
@command{tar} should be able to read the archive. Otherwise, the
|
||||
@command{tar} program will give an error, the most likely one being a
|
||||
checksum error.
|
||||
|
||||
@node Sparse Formats
|
||||
@unnumberedsec Storing Sparse Files
|
||||
@include sparse.texi
|
||||
|
||||
@node Snapshot Files
|
||||
@unnumberedsec Format of the Incremental Snapshot Files
|
||||
@include snapshot.texi
|
||||
|
||||
@node Dumpdir
|
||||
@unnumberedsec Dumpdir
|
||||
@include dumpdir.texi
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
|
||||
|
||||
;; Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Sergey Poznyakoff
|
||||
;; Maintainer: bug-tar@gnu.org
|
||||
;; Keywords: maint, tex, docs
|
||||
|
||||
;; This file is part of GNU tar documentation suite
|
||||
|
||||
;; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file redefines texinfo-master-menu-list so that it takes into
|
||||
;; account included files.
|
||||
|
||||
;; Known bugs: @menu without previous sectioning command will inherit
|
||||
;; documentation string from the previous menu. However, since such a
|
||||
;; menu is illegal in a texinfo file, we can live with it.
|
||||
|
||||
(require 'texinfo)
|
||||
(require 'texnfo-upd)
|
||||
|
||||
(defun texinfo-master-menu-list-recursive (title)
|
||||
"Auxiliary function used by `texinfo-master-menu-list'."
|
||||
(save-excursion
|
||||
(let (master-menu-list)
|
||||
(while (re-search-forward "\\(^@menu\\|^@include\\)" nil t)
|
||||
(cond
|
||||
((string= (match-string 0) "@include")
|
||||
(skip-chars-forward " \t")
|
||||
(let ((included-name (let ((start (point)))
|
||||
(end-of-line)
|
||||
(skip-chars-backward " \t")
|
||||
(buffer-substring start (point)))))
|
||||
(end-of-line)
|
||||
(let ((prev-title (texinfo-copy-menu-title)))
|
||||
(save-excursion
|
||||
(set-buffer (find-file-noselect included-name))
|
||||
(setq master-menu-list
|
||||
(append (texinfo-master-menu-list-recursive prev-title)
|
||||
master-menu-list))))))
|
||||
(t
|
||||
(setq master-menu-list
|
||||
(cons (list
|
||||
(texinfo-copy-menu)
|
||||
(let ((menu-title (texinfo-copy-menu-title)))
|
||||
(if (string= menu-title "")
|
||||
title
|
||||
menu-title)))
|
||||
master-menu-list)))))
|
||||
master-menu-list)))
|
||||
|
||||
(defun texinfo-master-menu-list ()
|
||||
"Return a list of menu entries and header lines for the master menu,
|
||||
recursing into included files.
|
||||
|
||||
Start with the menu for chapters and indices and then find each
|
||||
following menu and the title of the node preceding that menu.
|
||||
|
||||
The master menu list has this form:
|
||||
|
||||
\(\(\(... \"entry-1-2\" \"entry-1\"\) \"title-1\"\)
|
||||
\(\(... \"entry-2-2\" \"entry-2-1\"\) \"title-2\"\)
|
||||
...\)
|
||||
|
||||
However, there does not need to be a title field."
|
||||
|
||||
(reverse (texinfo-master-menu-list-recursive "")))
|
||||
|
||||
(defun make-master-menu ()
|
||||
"Create master menu in the first Emacs argument."
|
||||
(find-file (car command-line-args-left))
|
||||
(texinfo-master-menu nil)
|
||||
(save-buffer))
|
||||
|
||||
|
||||
;;; mastermenu.el ends here
|
||||
@@ -1,90 +0,0 @@
|
||||
@c This is part of GNU tar manual.
|
||||
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
@c 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
@c See file tar.texi for copying conditions.
|
||||
|
||||
@c This file contains support for 'renditions' by Fran@,{c}ois Pinard
|
||||
@c I extended it by adding a FIXME_FOOTNOTE variable, which controls
|
||||
@c whether FIXME information should be placed in footnotes or
|
||||
@c inlined. --gray
|
||||
|
||||
@c ======================================================================
|
||||
@c This document has three levels of rendition: PUBLISH, DISTRIB or PROOF,
|
||||
@c as decided by @set symbols. The PUBLISH rendition does not show
|
||||
@c notes or marks asking for revision. Most users will prefer having more
|
||||
@c information, even if this information is not fully revised for adequacy,
|
||||
@c so DISTRIB is the default for distributions. The PROOF rendition
|
||||
@c show all marks to the point of ugliness, but is nevertheless useful to
|
||||
@c those working on the manual itself.
|
||||
@c ======================================================================
|
||||
|
||||
@c Set this symbol if you wish FIXMEs to appear in footnotes, instead
|
||||
@c of being inserted into the text.
|
||||
@c @set PROOF_FOOTNOTED
|
||||
|
||||
@ifclear PUBLISH
|
||||
@ifclear DISTRIB
|
||||
@ifclear PROOF
|
||||
@set DISTRIB
|
||||
@end ifclear
|
||||
@end ifclear
|
||||
@end ifclear
|
||||
|
||||
@ifset PUBLISH
|
||||
@set RENDITION The book, version
|
||||
@end ifset
|
||||
|
||||
@ifset DISTRIB
|
||||
@set RENDITION FTP release, version
|
||||
@end ifset
|
||||
|
||||
@ifset PROOF
|
||||
@set RENDITION Proof reading version
|
||||
@end ifset
|
||||
|
||||
@c Output marks for nodes needing revision, but not in PUBLISH rendition.
|
||||
|
||||
@macro UNREVISED
|
||||
@ifclear PUBLISH
|
||||
@quotation
|
||||
@emph{(This message will disappear, once this node revised.)}
|
||||
@end quotation
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@c Output various FIXME information only in PROOF rendition.
|
||||
|
||||
@macro FIXME{string}
|
||||
@ifset PROOF
|
||||
@ifset PROOF_FOOTNOTED
|
||||
@footnote{@strong{FIXME:} \string\}
|
||||
@end ifset
|
||||
@ifclear PROOF_FOOTNOTED
|
||||
@cartouche
|
||||
@strong{<FIXME>} \string\ @strong{</>}
|
||||
@end cartouche
|
||||
@end ifclear
|
||||
@end ifset
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-ref{string}
|
||||
@ifset PROOF
|
||||
@strong{<REF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@end macro
|
||||
|
||||
@macro FIXME-pxref{string}
|
||||
@ifset PROOF
|
||||
@strong{<PXREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-xref{string}
|
||||
@ifset PROOF
|
||||
@strong{<XREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@end macro
|
||||
|
||||
@c End of rendition.texi
|
||||
@@ -1,66 +0,0 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
@c Written by Sergey Poznyakoff
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
A @dfn{snapshot file} (or @dfn{directory file}) is created during
|
||||
incremental backups (@pxref{Incremental Dumps}). It
|
||||
contains the status of the file system at the time of the dump and is
|
||||
used to determine which files were modified since the last backup.
|
||||
|
||||
@GNUTAR{} version @value{VERSION} supports two snapshot file
|
||||
formats. The first format, called @dfn{format 0}, is the one used by
|
||||
@GNUTAR{} versions up to 1.15.1. The second format, called @dfn{format
|
||||
1} is an extended version of this format, that contains more metadata
|
||||
and allows for further extensions.
|
||||
|
||||
@samp{Format 0} snapshot file begins with a line containing a
|
||||
decimal number that represents the 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:
|
||||
|
||||
@smallexample
|
||||
[@var{nfs}]@var{dev} @var{inode} @var{name}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where optional @var{nfs} is a single plus character (@samp{+}) if this
|
||||
directory is located on an NFS-mounted partition, @var{dev} and
|
||||
@var{inode} are the device and inode numbers of the directory, and
|
||||
@var{name} is the directory name.
|
||||
|
||||
@samp{Format 1} snapshot file begins with a line specifying the
|
||||
format of the file. This line has the following structure:
|
||||
|
||||
@smallexample
|
||||
@samp{GNU tar-}@var{tar-version}@samp{-}@var{incr-format-version}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{tar-version} is the version 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}).
|
||||
|
||||
The following line contains two decimal numbers, representing the
|
||||
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.
|
||||
|
||||
Following lines contain directory metadata, one line per
|
||||
directory. The line format is:
|
||||
|
||||
@smallexample
|
||||
[@var{nfs}]@var{mtime-sec} @var{mtime-nsec} @var{dev} @var{inode} @var{name}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{mtime-sec} and @var{mtime-nsec} represent the last
|
||||
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}.
|
||||
|
||||
|
||||
@c End of snapshot.texi
|
||||
|
||||
|
||||
235
doc/sparse.texi
235
doc/sparse.texi
@@ -1,235 +0,0 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@cindex sparse formats
|
||||
@cindex sparse versions
|
||||
The notion of sparse file, and the ways of handling it from the point
|
||||
of view of @GNUTAR{} user have been described in detail in
|
||||
@ref{sparse}. This chapter describes the internal format @GNUTAR{}
|
||||
uses to store such files.
|
||||
|
||||
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
|
||||
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
|
||||
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
|
||||
2006).
|
||||
|
||||
In addition to GNU sparse format, @GNUTAR{} is able to read and
|
||||
extract sparse files archived by @command{star}.
|
||||
|
||||
The following subsections describe each format in detail.
|
||||
|
||||
@menu
|
||||
* Old GNU Format::
|
||||
* PAX 0:: PAX Format, Versions 0.0 and 0.1
|
||||
* PAX 1:: PAX Format, Version 1.0
|
||||
@end menu
|
||||
|
||||
@node Old GNU Format
|
||||
@appendixsubsec Old GNU Format
|
||||
|
||||
@cindex sparse formats, Old GNU
|
||||
@cindex Old GNU sparse format
|
||||
The format introduced some time around 1990 (v. 1.09). It was
|
||||
designed on top of standard @code{ustar} headers in such an
|
||||
unfortunate way that some of its fields overwrote fields required by
|
||||
POSIX.
|
||||
|
||||
An old GNU sparse header is designated by type @samp{S}
|
||||
(@code{GNUTYPE_SPARSE}) and has the following layout:
|
||||
|
||||
@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 345 @tab @tab N/A @tab Not used.
|
||||
@item 345 @tab 12 @tab atime @tab Number @tab @code{atime} of the file.
|
||||
@item 357 @tab 12 @tab ctime @tab Number @tab @code{ctime} of the file .
|
||||
@item 369 @tab 12 @tab offset @tab Number @tab For
|
||||
multivolume archives: the offset of the start of this volume.
|
||||
@item 381 @tab 4 @tab @tab N/A @tab Not used.
|
||||
@item 385 @tab 1 @tab @tab N/A @tab Not used.
|
||||
@item 386 @tab 96 @tab sp @tab @code{sparse_header} @tab (4 entries) File map.
|
||||
@item 482 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
|
||||
extension sparse header follows, @code{0} otherwise.
|
||||
@item 483 @tab 12 @tab realsize @tab Number @tab Real size of the file.
|
||||
@end multitable
|
||||
|
||||
Each of @code{sparse_header} object at offset 386 describes a single
|
||||
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
|
||||
@item 0 @tab 12 @tab Number @tab Offset of the
|
||||
beginning of the chunk.
|
||||
@item 12 @tab 12 @tab Number @tab Size of the chunk.
|
||||
@end multitable
|
||||
|
||||
If the member contains more than four chunks, the @code{isextended}
|
||||
field of the header has the value @code{1} and the main header is
|
||||
followed by one or more @dfn{extension headers}. Each such header has
|
||||
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.
|
||||
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
|
||||
extension sparse header follows, or @code{0} otherwise.
|
||||
@end multitable
|
||||
|
||||
A header with @code{isextended=0} ends the map.
|
||||
|
||||
@node PAX 0
|
||||
@appendixsubsec PAX Format, Versions 0.0 and 0.1
|
||||
|
||||
@cindex sparse formats, v.0.0
|
||||
There are two formats available in this branch. The version @code{0.0}
|
||||
is the initial version of sparse format used by @command{tar}
|
||||
versions 1.14--1.15.1. The sparse file map is kept in extended
|
||||
(@code{x}) PAX header variables:
|
||||
|
||||
@table @code
|
||||
@vrindex GNU.sparse.size, extended header variable
|
||||
@item GNU.sparse.size
|
||||
Real size of the stored file
|
||||
|
||||
@item GNU.sparse.numblocks
|
||||
@vrindex GNU.sparse.numblocks, extended header variable
|
||||
Number of blocks in the sparse map
|
||||
|
||||
@item GNU.sparse.offset
|
||||
@vrindex GNU.sparse.offset, extended header variable
|
||||
Offset of the data block
|
||||
|
||||
@item GNU.sparse.numbytes
|
||||
@vrindex GNU.sparse.numbytes, extended header variable
|
||||
Size of the data block
|
||||
@end table
|
||||
|
||||
The latter two variables repeat for each data block, so the overall
|
||||
structure is like this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
GNU.sparse.size=@var{size}
|
||||
GNU.sparse.numblocks=@var{numblocks}
|
||||
repeat @var{numblocks} times
|
||||
GNU.sparse.offset=@var{offset}
|
||||
GNU.sparse.numbytes=@var{numbytes}
|
||||
end repeat
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
This format presented the following two problems:
|
||||
|
||||
@enumerate 1
|
||||
@item
|
||||
Whereas the POSIX specification allows a variable to appear multiple
|
||||
times in a header, it requires that only the last occurrence be
|
||||
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
|
||||
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
|
||||
state. However, posix-aware @command{tar}s will usually ignore the
|
||||
unknown variables, which makes restoring the file more
|
||||
difficult. @xref{extracting sparse v.0.x, Extraction of sparse
|
||||
members in v.0.0 format}, for the detailed description of how to
|
||||
restore such members using non-GNU @command{tar}s.
|
||||
@end enumerate
|
||||
|
||||
@cindex sparse formats, v.0.1
|
||||
@GNUTAR{} 1.15.2 introduced sparse format version @code{0.1}, which
|
||||
attempted to solve these problems. As its predecessor, this format
|
||||
stores sparse map in the extended POSIX header. It retains
|
||||
@code{GNU.sparse.size} and @code{GNU.sparse.numblocks} variables, but
|
||||
instead of @code{GNU.sparse.offset}/@code{GNU.sparse.numbytes} pairs
|
||||
it uses a single variable:
|
||||
|
||||
@table @code
|
||||
@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}...]"
|
||||
@end table
|
||||
|
||||
To address the 2nd problem, the @code{name} field in @code{ustar}
|
||||
is replaced with a special name, constructed using the following pattern:
|
||||
|
||||
@smallexample
|
||||
%d/GNUSparseFile.%p/%f
|
||||
@end smallexample
|
||||
|
||||
@vrindex GNU.sparse.name, extended header variable
|
||||
The real name of the sparse file is stored in the variable
|
||||
@code{GNU.sparse.name}. Thus, those @command{tar} implementations
|
||||
that are not aware of GNU extensions will at least extract the files
|
||||
into separate directories, giving the user a possibility to expand it
|
||||
afterwards. @xref{extracting sparse v.0.x, Extraction of sparse
|
||||
members in v.0.1 format}, for the detailed description of how to
|
||||
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.
|
||||
|
||||
@node PAX 1
|
||||
@appendixsubsec PAX Format, Version 1.0
|
||||
|
||||
@cindex sparse formats, v.1.0
|
||||
The version @code{1.0} of sparse format was introduced with @GNUTAR{}
|
||||
1.15.92. Its main objective was to make the resulting file
|
||||
extractable with little effort even by non-posix aware @command{tar}
|
||||
implementations. Starting from this version, the extended header
|
||||
preceding a sparse member always contains the following variables that
|
||||
identify the format being used:
|
||||
|
||||
@table @code
|
||||
@item GNU.sparse.major
|
||||
@vrindex GNU.sparse.major, extended header variable
|
||||
Major version
|
||||
|
||||
@item GNU.sparse.minor
|
||||
@vrindex GNU.sparse.minor, extended header variable
|
||||
Minor version
|
||||
@end table
|
||||
|
||||
The @code{name} field in @code{ustar} header contains a special name,
|
||||
constructed using the following pattern:
|
||||
|
||||
@smallexample
|
||||
%d/GNUSparseFile.%p/%f
|
||||
@end smallexample
|
||||
|
||||
@vrindex GNU.sparse.name, extended header variable, in v.1.0
|
||||
@vrindex GNU.sparse.realsize, extended header variable
|
||||
The real name of the sparse file is stored in the variable
|
||||
@code{GNU.sparse.name}. The real size of the file is stored in the
|
||||
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
|
||||
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
|
||||
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{}.
|
||||
|
||||
10060
doc/tar.texi
10060
doc/tar.texi
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# GNU tar is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 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. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
1{s,/\*,@comment ,
|
||||
b
|
||||
}
|
||||
2,/.*\*\//{s,\*/,,;s/^/@comment/
|
||||
b
|
||||
}
|
||||
/\/* END \*\//,$d
|
||||
s/\([{}]\)/@\1/g
|
||||
s,/\*,&@r{,
|
||||
s,\*/,}&,
|
||||
@@ -1,22 +0,0 @@
|
||||
@c This is part of GNU tar manual.
|
||||
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
@c 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
@c See file tar.texi for copying conditions.
|
||||
|
||||
@macro GNUTAR
|
||||
@acronym{GNU} @command{tar}
|
||||
@end macro
|
||||
|
||||
@macro xopindex{option,text}
|
||||
@opindex \option\@r{, \text\}
|
||||
@end macro
|
||||
|
||||
@macro opsummary{option}
|
||||
@ifclear ANCHOR--\option\
|
||||
@set ANCHOR--\option\ 1
|
||||
@anchor{--\option\}
|
||||
@end ifclear
|
||||
@xopindex{\option\, summary}
|
||||
@end macro
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
# List of gnulib modules needed for GNU tar.
|
||||
# A module name per line. Empty lines and comments are ignored.
|
||||
|
||||
alloca
|
||||
argmatch
|
||||
argp
|
||||
backupfile
|
||||
closeout
|
||||
dirname
|
||||
error
|
||||
exclude
|
||||
exitfail
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
ftruncate
|
||||
full-write
|
||||
getdate
|
||||
getline
|
||||
getopt
|
||||
getpagesize
|
||||
gettext
|
||||
gettime
|
||||
hash
|
||||
human
|
||||
inttypes
|
||||
lchown
|
||||
localcharset
|
||||
memset
|
||||
mkdtemp
|
||||
modechange
|
||||
obstack
|
||||
quote
|
||||
quotearg
|
||||
rmdir
|
||||
rpmatch
|
||||
safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
setenv
|
||||
stat-time
|
||||
stdbool
|
||||
stdint
|
||||
stpcpy
|
||||
strdup
|
||||
strtol
|
||||
strtoul
|
||||
timespec
|
||||
unlinkdir
|
||||
unlocked-io
|
||||
utime
|
||||
utimens
|
||||
version-etc-fsf
|
||||
xalloc
|
||||
xalloc-die
|
||||
xgetcwd
|
||||
xstrtoumax
|
||||
232
lib/.cvsignore
232
lib/.cvsignore
@@ -1,232 +0,0 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.am
|
||||
Makefile.in
|
||||
__fpending.c
|
||||
__fpending.h
|
||||
alloca.c
|
||||
alloca.h
|
||||
alloca_.h
|
||||
allocsa.c
|
||||
allocsa.h
|
||||
allocsa.valgrind
|
||||
argmatch.c
|
||||
argmatch.h
|
||||
argp-ba.c
|
||||
argp-eexst.c
|
||||
argp-fmtstream.c
|
||||
argp-fmtstream.h
|
||||
argp-fs-xinl.c
|
||||
argp-help.c
|
||||
argp-namefrob.h
|
||||
argp-parse.c
|
||||
argp-pin.c
|
||||
argp-pv.c
|
||||
argp-pvh.c
|
||||
argp-xinl.c
|
||||
argp.h
|
||||
asnprintf.c
|
||||
at-func.c
|
||||
backupfile.c
|
||||
backupfile.h
|
||||
basename.c
|
||||
charset.alias
|
||||
chdir-long.c
|
||||
chdir-long.h
|
||||
chown.c
|
||||
close-stream.c
|
||||
close-stream.h
|
||||
closeout.c
|
||||
closeout.h
|
||||
config.charset
|
||||
configmake.h
|
||||
creat-safer.c
|
||||
dirname.c
|
||||
dirname.h
|
||||
dup-safer.c
|
||||
error.c
|
||||
error.h
|
||||
exclude.c
|
||||
exclude.h
|
||||
exit.h
|
||||
exitfail.c
|
||||
exitfail.h
|
||||
fchmodat.c
|
||||
fchown-stub.c
|
||||
fcntl--.h
|
||||
fcntl-safer.h
|
||||
fcntl.h
|
||||
fcntl_.h
|
||||
fd-safer.c
|
||||
fileblocks.c
|
||||
fnmatch.c
|
||||
fnmatch.h
|
||||
fnmatch_.h
|
||||
fnmatch_loop.c
|
||||
ftruncate.c
|
||||
full-write.c
|
||||
full-write.h
|
||||
getcwd.c
|
||||
getcwd.h
|
||||
getdate.c
|
||||
getdate.h
|
||||
getdate.y
|
||||
getdelim.c
|
||||
getdelim.h
|
||||
getline.c
|
||||
getline.h
|
||||
getopt.c
|
||||
getopt.h
|
||||
getopt1.c
|
||||
getopt_.h
|
||||
getopt_int.h
|
||||
getpagesize.h
|
||||
gettext.h
|
||||
gettime.c
|
||||
gettimeofday.c
|
||||
hash.c
|
||||
hash.h
|
||||
human.c
|
||||
human.h
|
||||
imaxtostr.c
|
||||
intprops.h
|
||||
inttostr.c
|
||||
inttostr.h
|
||||
inttypes.h
|
||||
inttypes_.h
|
||||
lchown.c
|
||||
lchown.h
|
||||
localcharset.c
|
||||
localcharset.h
|
||||
localedir.h
|
||||
lstat.c
|
||||
lstat.h
|
||||
malloc.c
|
||||
mbchar.c
|
||||
mbchar.h
|
||||
mbuiter.h
|
||||
memchr.c
|
||||
mempcpy.c
|
||||
mempcpy.h
|
||||
memrchr.c
|
||||
memrchr.h
|
||||
memset.c
|
||||
minmax.h
|
||||
mkdirat.c
|
||||
mkdtemp.c
|
||||
mkdtemp.h
|
||||
mktime.c
|
||||
modechange.c
|
||||
modechange.h
|
||||
obstack.c
|
||||
obstack.h
|
||||
offtostr.c
|
||||
open-safer.c
|
||||
openat-die.c
|
||||
openat-priv.h
|
||||
openat.c
|
||||
openat.h
|
||||
paxerror.c
|
||||
paxexit.c
|
||||
paxlib.h
|
||||
paxnames.c
|
||||
pipe-safer.c
|
||||
printf-args.c
|
||||
printf-args.h
|
||||
printf-parse.c
|
||||
printf-parse.h
|
||||
quote.c
|
||||
quote.h
|
||||
quotearg.c
|
||||
quotearg.h
|
||||
ref-add.sed
|
||||
ref-add.sin
|
||||
ref-del.sed
|
||||
ref-del.sin
|
||||
regcomp.c
|
||||
regex.c
|
||||
regex.h
|
||||
regex_internal.c
|
||||
regex_internal.h
|
||||
regexec.c
|
||||
rmdir.c
|
||||
rmt.h
|
||||
rpmatch.c
|
||||
rtapelib.c
|
||||
safe-read.c
|
||||
safe-read.h
|
||||
safe-write.c
|
||||
safe-write.h
|
||||
save-cwd.c
|
||||
save-cwd.h
|
||||
savedir.c
|
||||
savedir.h
|
||||
setenv.c
|
||||
setenv.h
|
||||
size_max.h
|
||||
stat-macros.h
|
||||
stat-time.h
|
||||
stdbool.h
|
||||
stdbool_.h
|
||||
stdint.h
|
||||
stdint_.h
|
||||
stpcpy.c
|
||||
stpcpy.h
|
||||
strcase.h
|
||||
strcasecmp.c
|
||||
strchrnul.c
|
||||
strchrnul.h
|
||||
strdup.c
|
||||
strdup.h
|
||||
stripslash.c
|
||||
strncasecmp.c
|
||||
strndup.c
|
||||
strndup.h
|
||||
strnlen.c
|
||||
strnlen.h
|
||||
strnlen1.c
|
||||
strnlen1.h
|
||||
strtoimax.c
|
||||
strtol.c
|
||||
strtoll.c
|
||||
strtoul.c
|
||||
strtoull.c
|
||||
strtoumax.c
|
||||
sysexit_.h
|
||||
sysexits.h
|
||||
system-ioctl.h
|
||||
system.h
|
||||
time_r.c
|
||||
time_r.h
|
||||
timespec.h
|
||||
umaxtostr.c
|
||||
unistd--.h
|
||||
unistd-safer.h
|
||||
unlinkdir.c
|
||||
unlinkdir.h
|
||||
unlocked-io.h
|
||||
unsetenv.c
|
||||
utime.c
|
||||
utimens.c
|
||||
utimens.h
|
||||
vasnprintf.c
|
||||
vasnprintf.h
|
||||
verify.h
|
||||
version-etc-fsf.c
|
||||
version-etc.c
|
||||
version-etc.h
|
||||
vsnprintf.c
|
||||
vsnprintf.h
|
||||
wcwidth.h
|
||||
xalloc-die.c
|
||||
xalloc.h
|
||||
xgetcwd.c
|
||||
xgetcwd.h
|
||||
xmalloc.c
|
||||
xsize.h
|
||||
xstrndup.c
|
||||
xstrndup.h
|
||||
xstrtol.c
|
||||
xstrtol.h
|
||||
xstrtoul.c
|
||||
xstrtoumax.c
|
||||
45
lib/Makefile.am
Normal file
45
lib/Makefile.am
Normal file
@@ -0,0 +1,45 @@
|
||||
# Makefile for GNU tar library.
|
||||
# Copyright (C) 1994, 1995, 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 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
AUTOMAKE_OPTIONS = gnits
|
||||
|
||||
noinst_LIBRARIES = libtar.a
|
||||
|
||||
EXTRA_DIST = \
|
||||
alloca.c fileblocks.c fnmatch.c ftruncate.c execlp.c gmalloc.c \
|
||||
memset.c mkdir.c modechange.h rename.c rmdir.c stpcpy.c strstr.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
argmatch.h backupfile.h error.h fnmatch.h getopt.h getdate.h getpagesize.h \
|
||||
pathmax.h
|
||||
|
||||
libtar_a_SOURCES = \
|
||||
argmatch.c backupfile.c error.c getdate.y getopt.c getopt1.c getversion.c \
|
||||
modechange.c msleep.c xgetcwd.c xmalloc.c xstrdup.c
|
||||
|
||||
INCLUDES = -I.. -I$(srcdir) -I../intl
|
||||
|
||||
libtar_a_LIBADD = @ALLOCA@ @LIBOBJS@
|
||||
libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
|
||||
|
||||
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
|
||||
$(srcdir)/getdate.c: getdate.y
|
||||
@echo Expect 13 shift/reduce conflicts...
|
||||
cd $(srcdir) && \
|
||||
$(YACC) $(YFLAGS) getdate.y; \
|
||||
mv -f y.tab.c getdate.c
|
||||
@@ -1,56 +0,0 @@
|
||||
# Makefile for GNU tar library. -*- Makefile -*-
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
|
||||
# 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
noinst_LIBRARIES = libtar.a
|
||||
noinst_HEADERS = system.h system-ioctl.h localedir.h rmt.h paxlib.h stdopen.h
|
||||
libtar_a_SOURCES = prepargs.c prepargs.h rtapelib.c paxerror.c paxexit.c paxnames.c stdopen.c
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
|
||||
DISTCLEANFILES = localedir.h
|
||||
localedir.h : Makefile
|
||||
echo '#define LOCALEDIR "$(localedir)"' >$@
|
||||
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
|
||||
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@
|
||||
echo "#endif" >> $@
|
||||
|
||||
rtapelib.o: localedir.h
|
||||
|
||||
libtar_a_LIBADD = $(LIBOBJS) $(ALLOCA)
|
||||
libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
|
||||
|
||||
BUILT_SOURCES =
|
||||
AM_CPPFLAGS =
|
||||
EXTRA_DIST = Makefile.tmpl
|
||||
MAINTAINERCLEANFILES =
|
||||
MOSTLYCLEANFILES =
|
||||
lib_OBJECTS = $(libtar_a_OBJECTS)
|
||||
|
||||
# Special rule for getdate
|
||||
#
|
||||
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
|
||||
$(srcdir)/getdate.c: getdate.y
|
||||
cd $(srcdir) && \
|
||||
$(YACC) $(YFLAGS) getdate.y && \
|
||||
mv -f y.tab.c getdate.c
|
||||
|
||||
SUFFIXES = .o .c .h
|
||||
CLEANFILES =
|
||||
# gnulib modules
|
||||
48
lib/alloca.c
48
lib/alloca.c
@@ -33,15 +33,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef emacs
|
||||
# include "lisp.h"
|
||||
# include "blockinput.h"
|
||||
# define xalloc_die() memory_full ()
|
||||
# ifdef EMACS_FREE
|
||||
# undef free
|
||||
# define free EMACS_FREE
|
||||
# endif
|
||||
#else
|
||||
# include <xalloc.h>
|
||||
#endif
|
||||
|
||||
/* If compiling with GCC 2, this file's not needed. */
|
||||
@@ -61,8 +53,6 @@
|
||||
you
|
||||
lose
|
||||
-- must know STACK_DIRECTION at compile-time
|
||||
/* Using #error here is not wise since this file should work for
|
||||
old and obscure compilers. */
|
||||
# endif /* STACK_DIRECTION undefined */
|
||||
# endif /* static */
|
||||
# endif /* emacs */
|
||||
@@ -77,19 +67,32 @@ long i00afunc ();
|
||||
# define ADDRESS_FUNCTION(arg) &(arg)
|
||||
# endif
|
||||
|
||||
# ifndef POINTER_TYPE
|
||||
# ifdef __STDC__
|
||||
# define POINTER_TYPE void
|
||||
# else
|
||||
# define POINTER_TYPE char
|
||||
# endif
|
||||
# if __STDC__
|
||||
typedef void *pointer;
|
||||
# else
|
||||
typedef char *pointer;
|
||||
# endif
|
||||
typedef POINTER_TYPE *pointer;
|
||||
|
||||
# ifndef NULL
|
||||
# define NULL 0
|
||||
# endif
|
||||
|
||||
/* Different portions of Emacs need to call different versions of
|
||||
malloc. The Emacs executable needs alloca to call xmalloc, because
|
||||
ordinary malloc isn't protected from input signals. On the other
|
||||
hand, the utilities in lib-src need alloca to call malloc; some of
|
||||
them are very simple, and don't have an xmalloc routine.
|
||||
|
||||
Non-Emacs programs expect this to call xmalloc.
|
||||
|
||||
Callers below should use malloc. */
|
||||
|
||||
# ifndef emacs
|
||||
# undef malloc
|
||||
# define malloc xmalloc
|
||||
# endif
|
||||
extern pointer malloc ();
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
deduced at run-time.
|
||||
@@ -166,8 +169,7 @@ static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
implementations of C, for example under Gould's UTX/32. */
|
||||
|
||||
pointer
|
||||
alloca (size)
|
||||
size_t size;
|
||||
alloca (size_t size)
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
register char *depth = ADDRESS_FUNCTION (probe);
|
||||
@@ -213,14 +215,8 @@ alloca (size)
|
||||
/* Allocate combined header + user data storage. */
|
||||
|
||||
{
|
||||
register pointer new = malloc (sizeof (header) + size);
|
||||
/* Address of header. */
|
||||
register pointer new;
|
||||
|
||||
size_t combined_size = sizeof (header) + size;
|
||||
if (combined_size < sizeof (header))
|
||||
xalloc_die ();
|
||||
|
||||
new = xmalloc (combined_size);
|
||||
|
||||
if (new == 0)
|
||||
abort();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* argmatch.c -- find a match for a string in an array
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2001, 2002, 2003 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 1990, 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
|
||||
@@ -20,33 +18,39 @@
|
||||
/* Written by David MacKenzie <djm@ai.mit.edu>
|
||||
Modified by Akim Demaille <demaille@inf.enst.fr> */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#include "argmatch.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
#if HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
#include "quotearg.h"
|
||||
#include "quote.h"
|
||||
#include "unlocked-io.h"
|
||||
|
||||
/* When reporting an invalid argument, show nonprinting characters
|
||||
by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use
|
||||
literal_quoting_style. */
|
||||
#ifndef ARGMATCH_QUOTING_STYLE
|
||||
# define ARGMATCH_QUOTING_STYLE locale_quoting_style
|
||||
# define ARGMATCH_QUOTING_STYLE escape_quoting_style
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
/* The following test is to work around the gross typo in
|
||||
systems like Sony NEWS-OS Release 4.0C, whereby EXIT_FAILURE
|
||||
is defined to 0, not 1. */
|
||||
#if !EXIT_FAILURE
|
||||
# undef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
@@ -74,6 +78,7 @@ argmatch_exit_fn argmatch_die = __argmatch_die;
|
||||
null-terminated array ARGLIST, return the index in ARGLIST
|
||||
of the matched element, else -1 if it does not match any element
|
||||
or -2 if it is ambiguous (is a prefix of more than one element).
|
||||
If SENSITIVE, comparison is case sensitive.
|
||||
|
||||
If VALLIST is none null, use it to resolve ambiguities limited to
|
||||
synonyms, i.e., for
|
||||
@@ -81,9 +86,10 @@ argmatch_exit_fn argmatch_die = __argmatch_die;
|
||||
"no", "nope" -> 1
|
||||
"y" is a valid argument, for `0', and "n" for `1'. */
|
||||
|
||||
int
|
||||
argmatch (const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize)
|
||||
static int
|
||||
__argmatch_internal (const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize,
|
||||
int case_sensitive)
|
||||
{
|
||||
int i; /* Temporary index in ARGLIST. */
|
||||
size_t arglen; /* Length of ARG. */
|
||||
@@ -95,7 +101,9 @@ argmatch (const char *arg, const char *const *arglist,
|
||||
/* Test all elements for either exact match or abbreviated matches. */
|
||||
for (i = 0; arglist[i]; i++)
|
||||
{
|
||||
if (!strncmp (arglist[i], arg, arglen))
|
||||
if (case_sensitive
|
||||
? !strncmp (arglist[i], arg, arglen)
|
||||
: !strncasecmp (arglist[i], arg, arglen))
|
||||
{
|
||||
if (strlen (arglist[i]) == arglen)
|
||||
/* Exact match found. */
|
||||
@@ -123,6 +131,22 @@ argmatch (const char *arg, const char *const *arglist,
|
||||
return matchind;
|
||||
}
|
||||
|
||||
/* argmatch - case sensitive version */
|
||||
int
|
||||
argmatch (const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize)
|
||||
{
|
||||
return __argmatch_internal (arg, arglist, vallist, valsize, 1);
|
||||
}
|
||||
|
||||
/* argcasematch - case insensitive version */
|
||||
int
|
||||
argcasematch (const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize)
|
||||
{
|
||||
return __argmatch_internal (arg, arglist, vallist, valsize, 0);
|
||||
}
|
||||
|
||||
/* Error reporting for argmatch.
|
||||
CONTEXT is a description of the type of entity that was being matched.
|
||||
VALUE is the invalid value that was given.
|
||||
@@ -131,12 +155,21 @@ argmatch (const char *arg, const char *const *arglist,
|
||||
void
|
||||
argmatch_invalid (const char *context, const char *value, int problem)
|
||||
{
|
||||
char const *format = (problem == -1
|
||||
? _("invalid argument %s for %s")
|
||||
: _("ambiguous argument %s for %s"));
|
||||
enum quoting_style saved_quoting_style;
|
||||
char const *format;
|
||||
|
||||
error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
|
||||
quote_n (1, context));
|
||||
/* Make sure to have a good quoting style to report errors.
|
||||
literal is insane here. */
|
||||
saved_quoting_style = get_quoting_style (NULL);
|
||||
set_quoting_style (NULL, ARGMATCH_QUOTING_STYLE);
|
||||
|
||||
format = (problem == -1
|
||||
? _("invalid argument `%s' for `%s'")
|
||||
: _("ambiguous argument `%s' for `%s'"));
|
||||
|
||||
error (0, 0, format, quotearg (value), context);
|
||||
|
||||
set_quoting_style (NULL, saved_quoting_style);
|
||||
}
|
||||
|
||||
/* List the valid arguments for argmatch.
|
||||
@@ -177,9 +210,12 @@ int
|
||||
__xargmatch_internal (const char *context,
|
||||
const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize,
|
||||
int case_sensitive,
|
||||
argmatch_exit_fn exit_fn)
|
||||
{
|
||||
int res = argmatch (arg, arglist, vallist, valsize);
|
||||
int res = __argmatch_internal (arg, arglist,
|
||||
vallist, valsize,
|
||||
case_sensitive);
|
||||
if (res >= 0)
|
||||
/* Success. */
|
||||
return res;
|
||||
@@ -265,12 +301,12 @@ main (int argc, const char *const *argv)
|
||||
}
|
||||
|
||||
if ((cp = getenv ("VERSION_CONTROL")))
|
||||
backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
|
||||
backup_args, backup_vals);
|
||||
backup_type = XARGCASEMATCH ("$VERSION_CONTROL", cp,
|
||||
backup_args, backup_vals);
|
||||
|
||||
if (argc == 2)
|
||||
backup_type = XARGMATCH (program_name, argv[1],
|
||||
backup_args, backup_vals);
|
||||
backup_type = XARGCASEMATCH (program_name, argv[1],
|
||||
backup_args, backup_vals);
|
||||
|
||||
printf ("The version control is `%s'\n",
|
||||
ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));
|
||||
|
||||
119
lib/error.c
119
lib/error.c
@@ -1,18 +1,22 @@
|
||||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000, 2001, 2002 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.
|
||||
Copyright (C) 1990-1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library. Its master source is NOT part of
|
||||
the C library, however. The master source lives in /gd/gnu/lib.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser 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. */
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
@@ -21,13 +25,7 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
|
||||
#include <libintl.h>
|
||||
#ifdef _LIBC
|
||||
# include <wchar.h>
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
@@ -55,10 +53,6 @@ void exit ();
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#if !_LIBC
|
||||
# include "unlocked-io.h"
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) String
|
||||
#endif
|
||||
@@ -80,7 +74,6 @@ unsigned int error_message_count;
|
||||
|
||||
# define program_name program_invocation_name
|
||||
# include <errno.h>
|
||||
# include <libio/libioP.h>
|
||||
|
||||
/* In GNU libc we want do not want to use the common name `error' directly.
|
||||
Instead make it a weak alias. */
|
||||
@@ -94,38 +87,27 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
|
||||
# define error_at_line __error_at_line
|
||||
|
||||
# ifdef USE_IN_LIBIO
|
||||
# include <libio/iolibio.h>
|
||||
# define fflush(s) INTUSE(_IO_fflush) (s)
|
||||
# undef putc
|
||||
# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
|
||||
# include <libio/iolibio.h>
|
||||
# define fflush(s) _IO_fflush (s)
|
||||
# endif
|
||||
|
||||
#else /* not _LIBC */
|
||||
|
||||
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
|
||||
# ifndef HAVE_DECL_STRERROR_R
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
char *strerror_r ();
|
||||
# endif
|
||||
|
||||
/* The calling program should define program_name and set it to the
|
||||
name of the executing program. */
|
||||
extern char *program_name;
|
||||
|
||||
# if HAVE_STRERROR_R || defined strerror_r
|
||||
# ifdef HAVE_STRERROR_R
|
||||
# define __strerror_r strerror_r
|
||||
# else
|
||||
# if HAVE_STRERROR
|
||||
# ifndef HAVE_DECL_STRERROR
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRERROR
|
||||
# ifndef strerror /* On some systems, strerror is a macro */
|
||||
char *strerror ();
|
||||
# endif
|
||||
# else
|
||||
static char *
|
||||
private_strerror (int errnum)
|
||||
private_strerror (errnum)
|
||||
int errnum;
|
||||
{
|
||||
extern char *sys_errlist[];
|
||||
extern int sys_nerr;
|
||||
@@ -136,43 +118,9 @@ private_strerror (int errnum)
|
||||
}
|
||||
# define strerror private_strerror
|
||||
# endif /* HAVE_STRERROR */
|
||||
# endif /* HAVE_STRERROR_R || defined strerror_r */
|
||||
# endif /* HAVE_STRERROR_R */
|
||||
#endif /* not _LIBC */
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s;
|
||||
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
# if STRERROR_R_CHAR_P || _LIBC
|
||||
s = __strerror_r (errnum, errbuf, sizeof errbuf);
|
||||
# else
|
||||
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
|
||||
s = errbuf;
|
||||
else
|
||||
s = 0;
|
||||
# endif
|
||||
#else
|
||||
s = strerror (errnum);
|
||||
#endif
|
||||
|
||||
#if !_LIBC
|
||||
if (! s)
|
||||
s = _("Unknown system error");
|
||||
#endif
|
||||
|
||||
#if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
__fwprintf (stderr, L": %s", s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf (stderr, ": %s", s);
|
||||
}
|
||||
|
||||
#ifdef VA_START
|
||||
static void
|
||||
@@ -229,12 +177,25 @@ error_tail (int status, int errnum, const char *message, va_list args)
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
{
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
char *s = __strerror_r (errnum, errbuf, sizeof errbuf);
|
||||
# if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L": %s", s);
|
||||
else
|
||||
# endif
|
||||
fprintf (stderr, ": %s", s);
|
||||
#else
|
||||
fprintf (stderr, ": %s", strerror (errnum));
|
||||
#endif
|
||||
}
|
||||
#if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
putwc (L'\n', stderr);
|
||||
else
|
||||
# endif
|
||||
#endif
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
@@ -291,7 +252,7 @@ error (status, errnum, message, va_alist)
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
fprintf (stderr, ": %s", strerror (errnum));
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
@@ -382,7 +343,7 @@ error_at_line (status, errnum, file_name, line_number, message, va_alist)
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
fprintf (stderr, ": %s", strerror (errnum));
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
|
||||
206
lib/exclude.c
206
lib/exclude.c
@@ -1,7 +1,5 @@
|
||||
/* exclude.c -- exclude file names
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright 1992, 1993, 1994, 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
|
||||
@@ -24,205 +22,72 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <exclude.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdio.h>
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#if HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#else
|
||||
# if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "exclude.h"
|
||||
#include "fnmatch.h"
|
||||
#include "unlocked-io.h"
|
||||
#include "xalloc.h"
|
||||
void *xmalloc PARAMS ((size_t));
|
||||
void *xrealloc PARAMS ((void *, size_t));
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
|
||||
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
|
||||
|
||||
/* Non-GNU systems lack these options, so we don't need to check them. */
|
||||
#ifndef FNM_CASEFOLD
|
||||
# define FNM_CASEFOLD 0
|
||||
#endif
|
||||
#ifndef FNM_LEADING_DIR
|
||||
# define FNM_LEADING_DIR 0
|
||||
#endif
|
||||
|
||||
verify (EXCLUDE_macros_do_not_collide_with_FNM_macros,
|
||||
(((EXCLUDE_ANCHORED | EXCLUDE_INCLUDE | EXCLUDE_WILDCARDS)
|
||||
& (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR
|
||||
| FNM_CASEFOLD))
|
||||
== 0));
|
||||
|
||||
/* An exclude pattern-options pair. The options are fnmatch options
|
||||
ORed with EXCLUDE_* options. */
|
||||
|
||||
struct patopts
|
||||
{
|
||||
char const *pattern;
|
||||
int options;
|
||||
};
|
||||
|
||||
/* An exclude list, of pattern-options pairs. */
|
||||
/* Keep track of excluded file name patterns. */
|
||||
|
||||
struct exclude
|
||||
{
|
||||
struct patopts *exclude;
|
||||
size_t exclude_alloc;
|
||||
size_t exclude_count;
|
||||
char const **exclude;
|
||||
int exclude_alloc;
|
||||
int exclude_count;
|
||||
};
|
||||
|
||||
/* Return a newly allocated and empty exclude list. */
|
||||
|
||||
struct exclude *
|
||||
new_exclude (void)
|
||||
{
|
||||
struct exclude *ex = xmalloc (sizeof *ex);
|
||||
struct exclude *ex = (struct exclude *) xmalloc (sizeof (struct exclude));
|
||||
ex->exclude_count = 0;
|
||||
ex->exclude_alloc = (1 << 6); /* This must be a power of 2. */
|
||||
ex->exclude = xmalloc (ex->exclude_alloc * sizeof ex->exclude[0]);
|
||||
ex->exclude_alloc = 64;
|
||||
ex->exclude = (char const **) xmalloc (ex->exclude_alloc * sizeof (char *));
|
||||
return ex;
|
||||
}
|
||||
|
||||
/* Free the storage associated with an exclude list. */
|
||||
|
||||
void
|
||||
free_exclude (struct exclude *ex)
|
||||
{
|
||||
free (ex->exclude);
|
||||
free (ex);
|
||||
}
|
||||
|
||||
/* Return zero if PATTERN matches F, obeying OPTIONS, except that
|
||||
(unlike fnmatch) wildcards are disabled in PATTERN. */
|
||||
|
||||
static int
|
||||
fnmatch_no_wildcards (char const *pattern, char const *f, int options)
|
||||
{
|
||||
if (! (options & FNM_LEADING_DIR))
|
||||
return ((options & FNM_CASEFOLD)
|
||||
? strcasecmp (pattern, f)
|
||||
: strcmp (pattern, f));
|
||||
else
|
||||
{
|
||||
size_t patlen = strlen (pattern);
|
||||
int r = ((options & FNM_CASEFOLD)
|
||||
? strncasecmp (pattern, f, patlen)
|
||||
: strncmp (pattern, f, patlen));
|
||||
if (! r)
|
||||
{
|
||||
r = f[patlen];
|
||||
if (r == '/')
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if EX excludes F. */
|
||||
|
||||
bool
|
||||
int
|
||||
excluded_filename (struct exclude const *ex, char const *f)
|
||||
{
|
||||
size_t exclude_count = ex->exclude_count;
|
||||
char const * const *exclude = ex->exclude;
|
||||
int exclude_count = ex->exclude_count;
|
||||
int i;
|
||||
|
||||
/* If no options are given, the default is to include. */
|
||||
if (exclude_count == 0)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
struct patopts const *exclude = ex->exclude;
|
||||
size_t i;
|
||||
for (i = 0; i < exclude_count; i++)
|
||||
if (fnmatch (exclude[i], f, 0) == 0)
|
||||
return 1;
|
||||
|
||||
/* Otherwise, the default is the opposite of the first option. */
|
||||
bool excluded = !! (exclude[0].options & EXCLUDE_INCLUDE);
|
||||
|
||||
/* Scan through the options, seeing whether they change F from
|
||||
excluded to included or vice versa. */
|
||||
for (i = 0; i < exclude_count; i++)
|
||||
{
|
||||
char const *pattern = exclude[i].pattern;
|
||||
int options = exclude[i].options;
|
||||
if (excluded == !! (options & EXCLUDE_INCLUDE))
|
||||
{
|
||||
int (*matcher) (char const *, char const *, int) =
|
||||
(options & EXCLUDE_WILDCARDS
|
||||
? fnmatch
|
||||
: fnmatch_no_wildcards);
|
||||
bool matched = ((*matcher) (pattern, f, options) == 0);
|
||||
char const *p;
|
||||
|
||||
if (! (options & EXCLUDE_ANCHORED))
|
||||
for (p = f; *p && ! matched; p++)
|
||||
if (*p == '/' && p[1] != '/')
|
||||
matched = ((*matcher) (pattern, p + 1, options) == 0);
|
||||
|
||||
excluded ^= matched;
|
||||
}
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Append to EX the exclusion PATTERN with OPTIONS. */
|
||||
|
||||
void
|
||||
add_exclude (struct exclude *ex, char const *pattern, int options)
|
||||
add_exclude (struct exclude *ex, char const *pattern)
|
||||
{
|
||||
struct patopts *patopts;
|
||||
|
||||
if (ex->exclude_alloc <= ex->exclude_count)
|
||||
{
|
||||
size_t s = 2 * ex->exclude_alloc;
|
||||
if (! (0 < s && s <= SIZE_MAX / sizeof ex->exclude[0]))
|
||||
xalloc_die ();
|
||||
ex->exclude_alloc = s;
|
||||
ex->exclude = xrealloc (ex->exclude, s * sizeof ex->exclude[0]);
|
||||
}
|
||||
ex->exclude = (char const **) xrealloc (ex->exclude,
|
||||
((ex->exclude_alloc *= 2)
|
||||
* sizeof (char *)));
|
||||
|
||||
patopts = &ex->exclude[ex->exclude_count++];
|
||||
patopts->pattern = pattern;
|
||||
patopts->options = options;
|
||||
ex->exclude[ex->exclude_count++] = pattern;
|
||||
}
|
||||
|
||||
/* Use ADD_FUNC to append to EX the patterns in FILENAME, each with
|
||||
OPTIONS. LINE_END terminates each pattern in the file. Return -1
|
||||
on failure, 0 on success. */
|
||||
|
||||
int
|
||||
add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
|
||||
struct exclude *ex, char const *filename, int options,
|
||||
char line_end)
|
||||
add_exclude_file (struct exclude *ex, char const *filename, char line_end)
|
||||
{
|
||||
bool use_stdin = filename[0] == '-' && !filename[1];
|
||||
int use_stdin = filename[0] == '-' && !filename[1];
|
||||
FILE *in;
|
||||
char *buf;
|
||||
char *p;
|
||||
char const *pattern;
|
||||
char const *lim;
|
||||
size_t buf_alloc = (1 << 10); /* This must be a power of two. */
|
||||
size_t buf_alloc = 1024;
|
||||
size_t buf_count = 0;
|
||||
int c;
|
||||
int e = 0;
|
||||
@@ -238,27 +103,22 @@ add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
|
||||
{
|
||||
buf[buf_count++] = c;
|
||||
if (buf_count == buf_alloc)
|
||||
{
|
||||
buf_alloc *= 2;
|
||||
if (! buf_alloc)
|
||||
xalloc_die ();
|
||||
buf = xrealloc (buf, buf_alloc);
|
||||
}
|
||||
buf = xrealloc (buf, buf_alloc *= 2);
|
||||
}
|
||||
|
||||
buf = xrealloc (buf, buf_count + 1);
|
||||
|
||||
if (ferror (in))
|
||||
e = errno;
|
||||
|
||||
if (!use_stdin && fclose (in) != 0)
|
||||
e = errno;
|
||||
|
||||
buf = xrealloc (buf, buf_count + 1);
|
||||
|
||||
for (pattern = p = buf, lim = buf + buf_count; p <= lim; p++)
|
||||
if (p < lim ? *p == line_end : buf < p && p[-1])
|
||||
{
|
||||
*p = '\0';
|
||||
(*add_func) (ex, pattern, options);
|
||||
add_exclude (ex, pattern);
|
||||
pattern = p + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* exclude.h -- declarations for excluding file names
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1997, 1999, 2001, 2002, 2003 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright 1992, 1993, 1994, 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
|
||||
@@ -20,24 +18,17 @@
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
/* Exclude options, which can be ORed with fnmatch options. */
|
||||
|
||||
/* Patterns must match the start of file names, instead of matching
|
||||
anywhere after a '/'. */
|
||||
#define EXCLUDE_ANCHORED (1 << 30)
|
||||
|
||||
/* Include instead of exclude. */
|
||||
#define EXCLUDE_INCLUDE (1 << 29)
|
||||
|
||||
/* '?', '*', '[', and '\\' are special in patterns. Without this
|
||||
option, these characters are ordinary and fnmatch is not used. */
|
||||
#define EXCLUDE_WILDCARDS (1 << 28)
|
||||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
struct exclude;
|
||||
|
||||
struct exclude *new_exclude (void);
|
||||
void free_exclude (struct exclude *);
|
||||
void add_exclude (struct exclude *, char const *, int);
|
||||
int add_exclude_file (void (*) (struct exclude *, char const *, int),
|
||||
struct exclude *, char const *, int, char);
|
||||
bool excluded_filename (struct exclude const *, char const *);
|
||||
struct exclude *new_exclude PARAMS ((void));
|
||||
void add_exclude PARAMS ((struct exclude *, char const *));
|
||||
int add_exclude_file PARAMS ((struct exclude *, char const *, char));
|
||||
int excluded_filename PARAMS ((struct exclude const *, char const *));
|
||||
|
||||
525
lib/fnmatch.c
525
lib/fnmatch.c
@@ -1,5 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002 Free Software Foundation, Inc.
|
||||
/* Copyright 1991, 1992, 1993, 1996, 1997, 2000 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
|
||||
@@ -11,9 +10,9 @@
|
||||
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. */
|
||||
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. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
@@ -24,362 +23,208 @@
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
# define HAVE_ALLOCA 1
|
||||
#else
|
||||
# if defined HAVE_ALLOCA_H || defined _LIBC
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
# pragma alloca
|
||||
# else
|
||||
# ifndef alloca
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! defined __builtin_expect && __GNUC__ < 3
|
||||
# define __builtin_expect(expr, expected) (expr)
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_STRING_H || defined _LIBC
|
||||
# include <string.h>
|
||||
#if defined STDC_HEADERS || !defined isascii
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# if HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
# define IN_CTYPE_DOMAIN(c) isascii (c)
|
||||
#endif
|
||||
|
||||
#if defined STDC_HEADERS || defined _LIBC
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
|
||||
|
||||
/* For platform which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
#if defined _LIBC || WIDE_CHAR_SUPPORT
|
||||
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
#endif
|
||||
|
||||
/* We need some of the locale data (the collation sequence information)
|
||||
but there is no interface to get this information in general. Therefore
|
||||
we support a correct implementation only in glibc. */
|
||||
#ifdef _LIBC
|
||||
# include "../locale/localeinfo.h"
|
||||
# include "../locale/elem-hash.h"
|
||||
# include "../locale/coll-lookup.h"
|
||||
# include <shlib-compat.h>
|
||||
|
||||
# define CONCAT(a,b) __CONCAT(a,b)
|
||||
# define mbsinit __mbsinit
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
# define fnmatch __fnmatch
|
||||
extern int fnmatch (const char *pattern, const char *string, int flags);
|
||||
#endif
|
||||
|
||||
/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
|
||||
#define NO_LEADING_PERIOD(flags) \
|
||||
((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, are not
|
||||
actually compiling the library itself, and have not detected a bug
|
||||
in the library. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
|
||||
#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
|
||||
|
||||
|
||||
# if defined STDC_HEADERS || !defined isascii
|
||||
# define ISASCII(c) 1
|
||||
# else
|
||||
# define ISASCII(c) isascii(c)
|
||||
# endif
|
||||
|
||||
# ifdef isblank
|
||||
# define ISBLANK(c) (ISASCII (c) && isblank (c))
|
||||
# else
|
||||
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
|
||||
# endif
|
||||
# ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
|
||||
# else
|
||||
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
|
||||
# endif
|
||||
|
||||
# define ISPRINT(c) (ISASCII (c) && isprint (c))
|
||||
# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
|
||||
# define ISALNUM(c) (ISASCII (c) && isalnum (c))
|
||||
# define ISALPHA(c) (ISASCII (c) && isalpha (c))
|
||||
# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
|
||||
# define ISLOWER(c) (ISASCII (c) && islower (c))
|
||||
# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
|
||||
# define ISSPACE(c) (ISASCII (c) && isspace (c))
|
||||
# define ISUPPER(c) (ISASCII (c) && isupper (c))
|
||||
# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
|
||||
|
||||
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
|
||||
|
||||
# if defined _LIBC || WIDE_CHAR_SUPPORT
|
||||
/* The GNU C library provides support for user-defined character classes
|
||||
and the functions from ISO C amendement 1. */
|
||||
# ifdef CHARCLASS_NAME_MAX
|
||||
# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
|
||||
# else
|
||||
/* This shouldn't happen but some implementation might still have this
|
||||
problem. Use a reasonable default value. */
|
||||
# define CHAR_CLASS_MAX_LENGTH 256
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define IS_CHAR_CLASS(string) __wctype (string)
|
||||
# else
|
||||
# define IS_CHAR_CLASS(string) wctype (string)
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
|
||||
# else
|
||||
# define ISWCTYPE(WC, WT) iswctype (WC, WT)
|
||||
# endif
|
||||
|
||||
# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
|
||||
/* In this case we are implementing the multibyte character handling. */
|
||||
# define HANDLE_MULTIBYTE 1
|
||||
# endif
|
||||
|
||||
# else
|
||||
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
|
||||
|
||||
# define IS_CHAR_CLASS(string) \
|
||||
(STREQ (string, "alpha") || STREQ (string, "upper") \
|
||||
|| STREQ (string, "lower") || STREQ (string, "digit") \
|
||||
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|
||||
|| STREQ (string, "space") || STREQ (string, "print") \
|
||||
|| STREQ (string, "punct") || STREQ (string, "graph") \
|
||||
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
|
||||
# endif
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
# if !defined _LIBC && !defined getenv && !HAVE_DECL_GETENV
|
||||
extern char *getenv ();
|
||||
# endif
|
||||
|
||||
# ifndef errno
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Global variable. */
|
||||
static int posixly_correct;
|
||||
|
||||
# ifndef internal_function
|
||||
/* Inside GNU libc we mark some function in a special way. In other
|
||||
environments simply ignore the marking. */
|
||||
# define internal_function
|
||||
# endif
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, nonzero if not. */
|
||||
int
|
||||
fnmatch (const char *pattern, const char *string, int flags)
|
||||
{
|
||||
register const char *p = pattern, *n = string;
|
||||
register char c;
|
||||
|
||||
/* Note that this evaluates C many times. */
|
||||
# ifdef _LIBC
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
|
||||
# else
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
# endif
|
||||
# define CHAR char
|
||||
# define UCHAR unsigned char
|
||||
# define INT int
|
||||
# define FCT internal_fnmatch
|
||||
# define EXT ext_match
|
||||
# define END end_pattern
|
||||
# define L(CS) CS
|
||||
# ifdef _LIBC
|
||||
# define BTOWC(C) __btowc (C)
|
||||
# else
|
||||
# define BTOWC(C) btowc (C)
|
||||
# endif
|
||||
# define STRLEN(S) strlen (S)
|
||||
# define STRCAT(D, S) strcat (D, S)
|
||||
# ifdef _LIBC
|
||||
# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
|
||||
# else
|
||||
# if HAVE_MEMPCPY
|
||||
# define MEMPCPY(D, S, N) mempcpy (D, S, N)
|
||||
# else
|
||||
# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
|
||||
# endif
|
||||
# endif
|
||||
# define MEMCHR(S, C, N) memchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) strcoll (S1, S2)
|
||||
# include "fnmatch_loop.c"
|
||||
#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER ((unsigned char) (c)) \
|
||||
? tolower ((unsigned char) (c)) \
|
||||
: (c))
|
||||
|
||||
|
||||
# if HANDLE_MULTIBYTE
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
|
||||
# define CHAR wchar_t
|
||||
# define UCHAR wint_t
|
||||
# define INT wint_t
|
||||
# define FCT internal_fnwmatch
|
||||
# define EXT ext_wmatch
|
||||
# define END end_wpattern
|
||||
# define L(CS) L##CS
|
||||
# define BTOWC(C) (C)
|
||||
# ifdef _LIBC
|
||||
# define STRLEN(S) __wcslen (S)
|
||||
# define STRCAT(D, S) __wcscat (D, S)
|
||||
# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
|
||||
# else
|
||||
# define STRLEN(S) wcslen (S)
|
||||
# define STRCAT(D, S) wcscat (D, S)
|
||||
# if HAVE_WMEMPCPY
|
||||
# define MEMPCPY(D, S, N) wmempcpy (D, S, N)
|
||||
# else
|
||||
# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
|
||||
# endif
|
||||
# endif
|
||||
# define MEMCHR(S, C, N) wmemchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) wcscoll (S1, S2)
|
||||
# define WIDE_CHAR_VERSION 1
|
||||
|
||||
# undef IS_CHAR_CLASS
|
||||
/* We have to convert the wide character string in a multibyte string. But
|
||||
we know that the character class names consist of alphanumeric characters
|
||||
from the portable character set, and since the wide character encoding
|
||||
for a member of the portable character set is the same code point as
|
||||
its single-byte encoding, we can use a simplified method to convert the
|
||||
string to a multibyte character string. */
|
||||
static wctype_t
|
||||
is_char_class (const wchar_t *wcs)
|
||||
{
|
||||
char s[CHAR_CLASS_MAX_LENGTH + 1];
|
||||
char *cp = s;
|
||||
|
||||
do
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
/* Test for a printable character from the portable character set. */
|
||||
# ifdef _LIBC
|
||||
if (*wcs < 0x20 || *wcs > 0x7e
|
||||
|| *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
|
||||
return (wctype_t) 0;
|
||||
# else
|
||||
switch (*wcs)
|
||||
c = FOLD (c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case L' ': case L'!': case L'"': case L'#': case L'%':
|
||||
case L'&': case L'\'': case L'(': case L')': case L'*':
|
||||
case L'+': case L',': case L'-': case L'.': case L'/':
|
||||
case L'0': case L'1': case L'2': case L'3': case L'4':
|
||||
case L'5': case L'6': case L'7': case L'8': case L'9':
|
||||
case L':': case L';': case L'<': case L'=': case L'>':
|
||||
case L'?':
|
||||
case L'A': case L'B': case L'C': case L'D': case L'E':
|
||||
case L'F': case L'G': case L'H': case L'I': case L'J':
|
||||
case L'K': case L'L': case L'M': case L'N': case L'O':
|
||||
case L'P': case L'Q': case L'R': case L'S': case L'T':
|
||||
case L'U': case L'V': case L'W': case L'X': case L'Y':
|
||||
case L'Z':
|
||||
case L'[': case L'\\': case L']': case L'^': case L'_':
|
||||
case L'a': case L'b': case L'c': case L'd': case L'e':
|
||||
case L'f': case L'g': case L'h': case L'i': case L'j':
|
||||
case L'k': case L'l': case L'm': case L'n': case L'o':
|
||||
case L'p': case L'q': case L'r': case L's': case L't':
|
||||
case L'u': case L'v': case L'w': case L'x': case L'y':
|
||||
case L'z': case L'{': case L'|': case L'}': case L'~':
|
||||
case '?':
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_FILE_NAME) && *n == '/')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
{
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
/* Trailing \ loses. */
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD (*n) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++)
|
||||
{
|
||||
if (c == '?')
|
||||
{
|
||||
/* A ? needs to match one character. */
|
||||
if (*n == '\0' || (*n == '/' && (flags & FNM_FILE_NAME)))
|
||||
/* There isn't another character; no match. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
less than three characters. */
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '\0')
|
||||
{
|
||||
if ((flags & (FNM_FILE_NAME | FNM_LEADING_DIR)) == FNM_FILE_NAME)
|
||||
for (; *n != '\0'; n++)
|
||||
if (*n == '/')
|
||||
return FNM_NOMATCH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
|
||||
c1 = FOLD (c1);
|
||||
for (--p; *n != '\0'; ++n)
|
||||
if ((c == '[' || FOLD (*n) == c1) &&
|
||||
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
|
||||
return 0;
|
||||
else if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
break;
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
case '[':
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
register int not;
|
||||
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
not = (*p == '!' || *p == '^');
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
register char cstart = c, cend = c;
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
cstart = cend = *p++;
|
||||
}
|
||||
|
||||
cstart = cend = FOLD (cstart);
|
||||
|
||||
if (c == '\0')
|
||||
/* [ (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
if ((flags & FNM_FILE_NAME) && c == '/')
|
||||
/* [/] can never match. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return FNM_NOMATCH;
|
||||
cend = FOLD (cend);
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
|
||||
goto matched;
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
if (!not)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
matched:;
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != ']')
|
||||
{
|
||||
if (c == '\0')
|
||||
/* [... (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (wctype_t) 0;
|
||||
if (c != FOLD (*n))
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Avoid overrunning the buffer. */
|
||||
if (cp == s + CHAR_CLASS_MAX_LENGTH)
|
||||
return (wctype_t) 0;
|
||||
|
||||
*cp++ = (char) *wcs++;
|
||||
++n;
|
||||
}
|
||||
while (*wcs != L'\0');
|
||||
|
||||
*cp = '\0';
|
||||
if (*n == '\0')
|
||||
return 0;
|
||||
|
||||
# ifdef _LIBC
|
||||
return __wctype (s);
|
||||
# else
|
||||
return wctype (s);
|
||||
# endif
|
||||
if ((flags & FNM_LEADING_DIR) && *n == '/')
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
return FNM_NOMATCH;
|
||||
|
||||
#undef FOLD
|
||||
}
|
||||
# define IS_CHAR_CLASS(string) is_char_class (string)
|
||||
|
||||
# include "fnmatch_loop.c"
|
||||
# endif
|
||||
|
||||
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
const char *pattern;
|
||||
const char *string;
|
||||
int flags;
|
||||
{
|
||||
# if HANDLE_MULTIBYTE
|
||||
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
|
||||
{
|
||||
mbstate_t ps;
|
||||
size_t n;
|
||||
wchar_t *wpattern;
|
||||
wchar_t *wstring;
|
||||
|
||||
/* Convert the strings into wide characters. */
|
||||
memset (&ps, '\0', sizeof (ps));
|
||||
n = mbsrtowcs (NULL, &pattern, 0, &ps);
|
||||
if (__builtin_expect (n, 0) == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
|
||||
|
||||
assert (mbsinit (&ps));
|
||||
n = mbsrtowcs (NULL, &string, 0, &ps);
|
||||
if (__builtin_expect (n, 0) == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wstring, &string, n + 1, &ps);
|
||||
|
||||
return internal_fnwmatch (wpattern, wstring, wstring + n,
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
# endif /* mbstate_t and mbsrtowcs or _LIBC. */
|
||||
|
||||
return internal_fnmatch (pattern, string, string + strlen (string),
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
|
||||
# ifdef _LIBC
|
||||
# undef fnmatch
|
||||
versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
|
||||
# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
|
||||
strong_alias (__fnmatch, __fnmatch_old)
|
||||
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* An interface to read and write that retries (if necessary) until complete.
|
||||
/* full-write.c -- an interface to write that retries after interrupts
|
||||
|
||||
Copyright (C) 1993, 1994, 1997-2003 Free Software Foundation, Inc.
|
||||
Copyright 1993, 1994, 1997, 1998, 1999, 2000, 2001 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
|
||||
@@ -14,17 +15,20 @@
|
||||
|
||||
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. */
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Written by Paul Eggert. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#ifdef FULL_READ
|
||||
# include "full-read.h"
|
||||
#else
|
||||
# include "full-write.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "full-write.h"
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
@@ -32,54 +36,32 @@
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#ifdef FULL_READ
|
||||
# include "safe-read.h"
|
||||
# define safe_rw safe_read
|
||||
# define full_rw full_read
|
||||
# undef const
|
||||
# define const /* empty */
|
||||
#else
|
||||
# include "safe-write.h"
|
||||
# define safe_rw safe_write
|
||||
# define full_rw full_write
|
||||
#endif
|
||||
/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted
|
||||
or if partial writes occur. Return the number of bytes successfully
|
||||
written, setting errno if that is less than LEN. */
|
||||
|
||||
#ifdef FULL_READ
|
||||
/* Set errno to zero upon EOF. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO 0
|
||||
#else
|
||||
/* Some buggy drivers return 0 when one tries to write beyond
|
||||
a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
|
||||
Set errno to ENOSPC so they get a sensible diagnostic. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
|
||||
#endif
|
||||
|
||||
/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
|
||||
interrupted or if a partial write(read) occurs. Return the number
|
||||
of bytes transferred.
|
||||
When writing, set errno if fewer than COUNT bytes are written.
|
||||
When reading, if fewer than COUNT bytes are read, you must examine
|
||||
errno to distinguish failure from EOF (errno == 0). */
|
||||
size_t
|
||||
full_rw (int fd, const void *buf, size_t count)
|
||||
full_write (int desc, const char *ptr, size_t len)
|
||||
{
|
||||
size_t total = 0;
|
||||
const char *ptr = buf;
|
||||
size_t total_written = 0;
|
||||
|
||||
while (count > 0)
|
||||
while (len > 0)
|
||||
{
|
||||
size_t n_rw = safe_rw (fd, ptr, count);
|
||||
if (n_rw == (size_t) -1)
|
||||
break;
|
||||
if (n_rw == 0)
|
||||
ssize_t written = write (desc, ptr, len);
|
||||
if (written <= 0)
|
||||
{
|
||||
errno = ZERO_BYTE_TRANSFER_ERRNO;
|
||||
/* Some buggy drivers return 0 when you fall off a device's end. */
|
||||
if (written == 0)
|
||||
errno = ENOSPC;
|
||||
#ifdef EINTR
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
total += n_rw;
|
||||
ptr += n_rw;
|
||||
count -= n_rw;
|
||||
total_written += written;
|
||||
ptr += written;
|
||||
len -= written;
|
||||
}
|
||||
|
||||
return total;
|
||||
return total_written;
|
||||
}
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
/* An interface to write() that writes all it is asked to write.
|
||||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
Copyright (C) 2002 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. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
|
||||
or if partial writes occur. Return the number of bytes successfully
|
||||
written, setting errno if that is less than COUNT. */
|
||||
extern size_t full_write (int fd, const void *buf, size_t count);
|
||||
size_t full_write PARAMS ((int, const char *, size_t));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%{
|
||||
/* Parse a string into an internal time stamp.
|
||||
Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright 1999, 2000 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
|
||||
@@ -27,10 +27,11 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
/* Since the code of getdate.y is not included in the Emacs executable
|
||||
itself, there is no need to #define static in this file. Even if
|
||||
the code were included in the Emacs executable, it probably
|
||||
@@ -62,9 +63,10 @@
|
||||
- Its arg may be any int or unsigned int; it need not be an unsigned char.
|
||||
- It's guaranteed to evaluate its argument exactly once.
|
||||
- It's typically faster.
|
||||
POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
|
||||
ISDIGIT_LOCALE unless it's important to use the locale's definition
|
||||
of `digit' even when the host does not conform to POSIX. */
|
||||
Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
|
||||
only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless
|
||||
it's important to use the locale's definition of `digit' even when the
|
||||
host does not conform to Posix. */
|
||||
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
|
||||
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
@@ -376,19 +378,19 @@ relunit:
|
||||
| tSNUMBER tDAY_UNIT
|
||||
{ PC.rel_day += $1.value * $2; }
|
||||
| tDAY_UNIT
|
||||
{ PC.rel_day += $1; }
|
||||
{ PC.rel_day += $1 }
|
||||
| tUNUMBER tHOUR_UNIT
|
||||
{ PC.rel_hour += $1.value * $2; }
|
||||
| tSNUMBER tHOUR_UNIT
|
||||
{ PC.rel_hour += $1.value * $2; }
|
||||
| tHOUR_UNIT
|
||||
{ PC.rel_hour += $1; }
|
||||
{ PC.rel_hour += $1 }
|
||||
| tUNUMBER tMINUTE_UNIT
|
||||
{ PC.rel_minutes += $1.value * $2; }
|
||||
| tSNUMBER tMINUTE_UNIT
|
||||
{ PC.rel_minutes += $1.value * $2; }
|
||||
| tMINUTE_UNIT
|
||||
{ PC.rel_minutes += $1; }
|
||||
{ PC.rel_minutes += $1 }
|
||||
| tUNUMBER tSEC_UNIT
|
||||
{ PC.rel_seconds += $1.value * $2; }
|
||||
| tSNUMBER tSEC_UNIT
|
||||
@@ -446,7 +448,6 @@ o_merid:
|
||||
may define-away `const'. We want the prototype for get_date to have
|
||||
the same signature as the function definition. */
|
||||
#include "getdate.h"
|
||||
#include "unlocked-io.h"
|
||||
|
||||
#ifndef gmtime
|
||||
struct tm *gmtime ();
|
||||
@@ -907,7 +908,7 @@ get_date (const char *p, const time_t *now)
|
||||
pc.local_zones_seen = 0;
|
||||
pc.zones_seen = 0;
|
||||
|
||||
#if HAVE_STRUCT_TM_TM_ZONE
|
||||
#if HAVE_TM_ZONE
|
||||
pc.local_time_zone_table[0].name = tmp->tm_zone;
|
||||
pc.local_time_zone_table[0].type = tLOCAL_ZONE;
|
||||
pc.local_time_zone_table[0].value = tmp->tm_isdst;
|
||||
|
||||
69
lib/human.c
69
lib/human.c
@@ -1,7 +1,5 @@
|
||||
/* human.c -- print human readable file size
|
||||
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000 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,19 +26,12 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
@@ -68,34 +59,16 @@ char *getenv ();
|
||||
static const char suffixes[] =
|
||||
{
|
||||
0, /* not used */
|
||||
'K', /* kibi ('k' for kilo is a special case) */
|
||||
'M', /* mega or mebi */
|
||||
'G', /* giga or gibi */
|
||||
'T', /* tera or tebi */
|
||||
'P', /* peta or pebi */
|
||||
'E', /* exa or exbi */
|
||||
'Z', /* zetta or 2**70 */
|
||||
'Y' /* yotta or 2**80 */
|
||||
'k', /* kilo */
|
||||
'M', /* Mega */
|
||||
'G', /* Giga */
|
||||
'T', /* Tera */
|
||||
'P', /* Peta */
|
||||
'E', /* Exa */
|
||||
'Z', /* Zetta */
|
||||
'Y' /* Yotta */
|
||||
};
|
||||
|
||||
/* Generate into P[-1] (and possibly P[-2]) the proper suffix for
|
||||
POWER and BASE. Return the address of the generated suffix. */
|
||||
static char *
|
||||
generate_suffix_backwards (char *p, int power, int base)
|
||||
{
|
||||
char letter = suffixes[power];
|
||||
|
||||
if (base == 1000)
|
||||
{
|
||||
*--p = 'B';
|
||||
if (power == 1)
|
||||
letter = 'k';
|
||||
}
|
||||
|
||||
*--p = letter;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* If INEXACT_STYLE is not human_round_to_even, and if easily
|
||||
possible, adjust VALUE according to the style. */
|
||||
static double
|
||||
@@ -133,7 +106,7 @@ human_readable (uintmax_t n, char *buf,
|
||||
Use INEXACT_STYLE to determine whether to take the ceiling or floor
|
||||
of any result that cannot be expressed exactly.
|
||||
|
||||
If OUTPUT_BLOCK_SIZE is negative, use a format like "127K" if
|
||||
If OUTPUT_BLOCK_SIZE is negative, use a format like "127k" if
|
||||
possible, using powers of -OUTPUT_BLOCK_SIZE; otherwise, use
|
||||
ordinary decimal format. Normally -OUTPUT_BLOCK_SIZE is either
|
||||
1000 or 1024; it must be at least 2. Most people visually process
|
||||
@@ -141,10 +114,9 @@ human_readable (uintmax_t n, char *buf,
|
||||
more prone to misinterpretation. Hence, converting to an
|
||||
abbreviated form usually improves readability. Use a suffix
|
||||
indicating which power is being used. For example, assuming
|
||||
-OUTPUT_BLOCK_SIZE is 1024, 8500 would be converted to 8.3K,
|
||||
-OUTPUT_BLOCK_SIZE is 1024, 8500 would be converted to 8.3k,
|
||||
133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller
|
||||
than -OUTPUT_BLOCK_SIZE aren't modified. If -OUTPUT_BLOCK_SIZE is
|
||||
1024, append a "B" after any size letter. */
|
||||
than -OUTPUT_BLOCK_SIZE aren't modified. */
|
||||
|
||||
char *
|
||||
human_readable_inexact (uintmax_t n, char *buf,
|
||||
@@ -214,8 +186,6 @@ human_readable_inexact (uintmax_t n, char *buf,
|
||||
sprintf (buf, "%.0f", adjust_value (inexact_style, damt));
|
||||
else
|
||||
{
|
||||
char suffix[3];
|
||||
char const *psuffix;
|
||||
double e = 1;
|
||||
power = 0;
|
||||
|
||||
@@ -228,13 +198,12 @@ human_readable_inexact (uintmax_t n, char *buf,
|
||||
|
||||
damt /= e;
|
||||
|
||||
suffix[2] = '\0';
|
||||
psuffix = generate_suffix_backwards (suffix + 2, power, base);
|
||||
sprintf (buf, "%.1f%s",
|
||||
adjust_value (inexact_style, damt), psuffix);
|
||||
if (4 + (base == 1000) < strlen (buf))
|
||||
sprintf (buf, "%.0f%s",
|
||||
adjust_value (inexact_style, damt * 10) / 10, psuffix);
|
||||
sprintf (buf, "%.1f%c", adjust_value (inexact_style, damt),
|
||||
suffixes[power]);
|
||||
if (4 < strlen (buf))
|
||||
sprintf (buf, "%.0f%c",
|
||||
adjust_value (inexact_style, damt * 10) / 10,
|
||||
suffixes[power]);
|
||||
}
|
||||
|
||||
return buf;
|
||||
@@ -260,7 +229,7 @@ human_readable_inexact (uintmax_t n, char *buf,
|
||||
}
|
||||
while (base <= amt && power < sizeof suffixes - 1);
|
||||
|
||||
p = generate_suffix_backwards (p, power, base);
|
||||
*--p = suffixes[power];
|
||||
|
||||
if (amt < 10)
|
||||
{
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
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. */
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com>. */
|
||||
|
||||
|
||||
@@ -21,15 +21,10 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "unicodeio.h"
|
||||
#include "print-copyr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include "unicodeio.h"
|
||||
#else
|
||||
# define unicode_to_mb(code, callback, error_callback, callback_arg) \
|
||||
error_callback (code, callback_arg)
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#define COPYRIGHT_SIGN 0x00A9
|
||||
|
||||
@@ -50,7 +45,7 @@ void
|
||||
print_copyright (char const *notice)
|
||||
{
|
||||
fputs ("Copyright ", stdout);
|
||||
unicode_to_mb (COPYRIGHT_SIGN, print_unicode_char, print_parenthesized_c,
|
||||
unicode_to_mb (COPYRIGHT_SIGN, print_unicode_success, print_parenthesized_c,
|
||||
stdout);
|
||||
fputc (' ', stdout);
|
||||
puts (notice);
|
||||
|
||||
645
lib/quotearg.c
645
lib/quotearg.c
@@ -1,5 +1,5 @@
|
||||
/* quotearg.c - quote arguments for output
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 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
|
||||
@@ -21,22 +21,21 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDDEF_H
|
||||
# include <stddef.h> /* For the definition of size_t on windows w/MSVC. */
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <quotearg.h>
|
||||
#include <xalloc.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(text) gettext (text)
|
||||
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
|
||||
# define ISASCII(c) 1
|
||||
#else
|
||||
# define _(text) text
|
||||
# define ISASCII(c) isascii (c)
|
||||
#endif
|
||||
#ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
|
||||
#else
|
||||
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
|
||||
#endif
|
||||
#define N_(text) text
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
@@ -44,21 +43,9 @@
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX ((unsigned char) -1)
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
# define UINT_MAX ((unsigned int) -1)
|
||||
#endif
|
||||
|
||||
#if HAVE_C_BACKSLASH_A
|
||||
# define ALERT_CHAR '\a'
|
||||
#else
|
||||
# define ALERT_CHAR '\7'
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
@@ -68,55 +55,17 @@
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_WCHAR_H
|
||||
|
||||
/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared. */
|
||||
# include <stdio.h>
|
||||
# include <time.h>
|
||||
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
#if !HAVE_MBRTOWC
|
||||
/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
|
||||
other macros are defined only for documentation and to satisfy C
|
||||
syntax. */
|
||||
# undef MB_CUR_MAX
|
||||
# define MB_CUR_MAX 1
|
||||
# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
|
||||
# define mbsinit(ps) 1
|
||||
# define iswprint(wc) ISPRINT ((unsigned char) (wc))
|
||||
#endif
|
||||
|
||||
#ifndef iswprint
|
||||
# if HAVE_WCTYPE_H
|
||||
# include <wctype.h>
|
||||
# endif
|
||||
# if !defined iswprint && !HAVE_ISWPRINT
|
||||
# define iswprint(wc) 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define INT_BITS (sizeof (int) * CHAR_BIT)
|
||||
|
||||
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) isascii(c)
|
||||
#endif
|
||||
|
||||
/* Undefine to protect against the definition in wctype.h of solaris2.6. */
|
||||
#undef ISPRINT
|
||||
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
|
||||
|
||||
struct quoting_options
|
||||
{
|
||||
/* Basic quoting style. */
|
||||
enum quoting_style style;
|
||||
|
||||
/* Quote the characters indicated by this bit vector even if the
|
||||
/* Quote the chararacters indicated by this bit vector even if the
|
||||
quoting style would not normally require them to be quoted. */
|
||||
int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
|
||||
int quote_these_too[((UCHAR_MAX + 1) / INT_BITS
|
||||
+ ((UCHAR_MAX + 1) % INT_BITS != 0))];
|
||||
};
|
||||
|
||||
/* Names of quoting styles. */
|
||||
@@ -127,21 +76,17 @@ char const *const quoting_style_args[] =
|
||||
"shell-always",
|
||||
"c",
|
||||
"escape",
|
||||
"locale",
|
||||
"clocale",
|
||||
0
|
||||
};
|
||||
|
||||
/* Correspondences to quoting style names. */
|
||||
/* Correspondances to quoting style names. */
|
||||
enum quoting_style const quoting_style_vals[] =
|
||||
{
|
||||
literal_quoting_style,
|
||||
shell_quoting_style,
|
||||
shell_always_quoting_style,
|
||||
c_quoting_style,
|
||||
escape_quoting_style,
|
||||
locale_quoting_style,
|
||||
clocale_quoting_style
|
||||
escape_quoting_style
|
||||
};
|
||||
|
||||
/* The default quoting options. */
|
||||
@@ -190,335 +135,6 @@ set_char_quoting (struct quoting_options *o, char c, int i)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* MSGID approximates a quotation mark. Return its translation if it
|
||||
has one; otherwise, return either it or "\"", depending on S. */
|
||||
static char const *
|
||||
gettext_quote (char const *msgid, enum quoting_style s)
|
||||
{
|
||||
char const *translation = _(msgid);
|
||||
if (translation == msgid && s == clocale_quoting_style)
|
||||
translation = "\"";
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
|
||||
argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
|
||||
non-quoting-style part of O to control quoting.
|
||||
Terminate the output with a null character, and return the written
|
||||
size of the output, not counting the terminating null.
|
||||
If BUFFERSIZE is too small to store the output string, return the
|
||||
value that would have been returned had BUFFERSIZE been large enough.
|
||||
If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
|
||||
|
||||
This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
|
||||
ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
|
||||
style specified by O, and O may not be null. */
|
||||
|
||||
static size_t
|
||||
quotearg_buffer_restyled (char *buffer, size_t buffersize,
|
||||
char const *arg, size_t argsize,
|
||||
enum quoting_style quoting_style,
|
||||
struct quoting_options const *o)
|
||||
{
|
||||
size_t i;
|
||||
size_t len = 0;
|
||||
char const *quote_string = 0;
|
||||
size_t quote_string_len = 0;
|
||||
int backslash_escapes = 0;
|
||||
int unibyte_locale = MB_CUR_MAX == 1;
|
||||
|
||||
#define STORE(c) \
|
||||
do \
|
||||
{ \
|
||||
if (len < buffersize) \
|
||||
buffer[len] = (c); \
|
||||
len++; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
switch (quoting_style)
|
||||
{
|
||||
case c_quoting_style:
|
||||
STORE ('"');
|
||||
backslash_escapes = 1;
|
||||
quote_string = "\"";
|
||||
quote_string_len = 1;
|
||||
break;
|
||||
|
||||
case escape_quoting_style:
|
||||
backslash_escapes = 1;
|
||||
break;
|
||||
|
||||
case locale_quoting_style:
|
||||
case clocale_quoting_style:
|
||||
{
|
||||
/* Get translations for open and closing quotation marks.
|
||||
|
||||
The message catalog should translate "`" to a left
|
||||
quotation mark suitable for the locale, and similarly for
|
||||
"'". If the catalog has no translation,
|
||||
locale_quoting_style quotes `like this', and
|
||||
clocale_quoting_style quotes "like this".
|
||||
|
||||
For example, an American English Unicode locale should
|
||||
translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
|
||||
should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
|
||||
MARK). A British English Unicode locale should instead
|
||||
translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
|
||||
U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. */
|
||||
|
||||
char const *left = gettext_quote (N_("`"), quoting_style);
|
||||
char const *right = gettext_quote (N_("'"), quoting_style);
|
||||
for (quote_string = left; *quote_string; quote_string++)
|
||||
STORE (*quote_string);
|
||||
backslash_escapes = 1;
|
||||
quote_string = right;
|
||||
quote_string_len = strlen (quote_string);
|
||||
}
|
||||
break;
|
||||
|
||||
case shell_always_quoting_style:
|
||||
STORE ('\'');
|
||||
quote_string = "'";
|
||||
quote_string_len = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize); i++)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char esc;
|
||||
|
||||
if (backslash_escapes
|
||||
&& quote_string_len
|
||||
&& i + quote_string_len <= argsize
|
||||
&& memcmp (arg + i, quote_string, quote_string_len) == 0)
|
||||
STORE ('\\');
|
||||
|
||||
c = arg[i];
|
||||
switch (c)
|
||||
{
|
||||
case '\0':
|
||||
if (backslash_escapes)
|
||||
{
|
||||
STORE ('\\');
|
||||
STORE ('0');
|
||||
STORE ('0');
|
||||
c = '0';
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
switch (quoting_style)
|
||||
{
|
||||
case shell_quoting_style:
|
||||
goto use_shell_always_quoting_style;
|
||||
|
||||
case c_quoting_style:
|
||||
if (i + 2 < argsize && arg[i + 1] == '?')
|
||||
switch (arg[i + 2])
|
||||
{
|
||||
case '!': case '\'':
|
||||
case '(': case ')': case '-': case '/':
|
||||
case '<': case '=': case '>':
|
||||
/* Escape the second '?' in what would otherwise be
|
||||
a trigraph. */
|
||||
i += 2;
|
||||
c = arg[i + 2];
|
||||
STORE ('?');
|
||||
STORE ('\\');
|
||||
STORE ('?');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ALERT_CHAR: esc = 'a'; goto c_escape;
|
||||
case '\b': esc = 'b'; goto c_escape;
|
||||
case '\f': esc = 'f'; goto c_escape;
|
||||
case '\n': esc = 'n'; goto c_and_shell_escape;
|
||||
case '\r': esc = 'r'; goto c_and_shell_escape;
|
||||
case '\t': esc = 't'; goto c_and_shell_escape;
|
||||
case '\v': esc = 'v'; goto c_escape;
|
||||
case '\\': esc = c; goto c_and_shell_escape;
|
||||
|
||||
c_and_shell_escape:
|
||||
if (quoting_style == shell_quoting_style)
|
||||
goto use_shell_always_quoting_style;
|
||||
c_escape:
|
||||
if (backslash_escapes)
|
||||
{
|
||||
c = esc;
|
||||
goto store_escape;
|
||||
}
|
||||
break;
|
||||
|
||||
case '#': case '~':
|
||||
if (i != 0)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case ' ':
|
||||
case '!': /* special in bash */
|
||||
case '"': case '$': case '&':
|
||||
case '(': case ')': case '*': case ';':
|
||||
case '<': case '>': case '[':
|
||||
case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
|
||||
case '`': case '|':
|
||||
/* A shell special character. In theory, '$' and '`' could
|
||||
be the first bytes of multibyte characters, which means
|
||||
we should check them with mbrtowc, but in practice this
|
||||
doesn't happen so it's not worth worrying about. */
|
||||
if (quoting_style == shell_quoting_style)
|
||||
goto use_shell_always_quoting_style;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
switch (quoting_style)
|
||||
{
|
||||
case shell_quoting_style:
|
||||
goto use_shell_always_quoting_style;
|
||||
|
||||
case shell_always_quoting_style:
|
||||
STORE ('\'');
|
||||
STORE ('\\');
|
||||
STORE ('\'');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%': case '+': case ',': case '-': case '.': case '/':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9': case ':': case '=':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
|
||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
||||
case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
|
||||
case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
|
||||
case 'o': case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
case '{': case '}':
|
||||
/* These characters don't cause problems, no matter what the
|
||||
quoting style is. They cannot start multibyte sequences. */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* If we have a multibyte sequence, copy it until we reach
|
||||
its end, find an error, or come back to the initial shift
|
||||
state. For C-like styles, if the sequence has
|
||||
unprintable characters, escape the whole sequence, since
|
||||
we can't easily escape single characters within it. */
|
||||
{
|
||||
/* Length of multibyte sequence found so far. */
|
||||
size_t m;
|
||||
|
||||
int printable;
|
||||
|
||||
if (unibyte_locale)
|
||||
{
|
||||
m = 1;
|
||||
printable = ISPRINT (c);
|
||||
}
|
||||
else
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
memset (&mbstate, 0, sizeof mbstate);
|
||||
|
||||
m = 0;
|
||||
printable = 1;
|
||||
if (argsize == (size_t) -1)
|
||||
argsize = strlen (arg);
|
||||
|
||||
do
|
||||
{
|
||||
wchar_t w;
|
||||
size_t bytes = mbrtowc (&w, &arg[i + m],
|
||||
argsize - (i + m), &mbstate);
|
||||
if (bytes == 0)
|
||||
break;
|
||||
else if (bytes == (size_t) -1)
|
||||
{
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
else if (bytes == (size_t) -2)
|
||||
{
|
||||
printable = 0;
|
||||
while (i + m < argsize && arg[i + m])
|
||||
m++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! iswprint (w))
|
||||
printable = 0;
|
||||
m += bytes;
|
||||
}
|
||||
}
|
||||
while (! mbsinit (&mbstate));
|
||||
}
|
||||
|
||||
if (1 < m || (backslash_escapes && ! printable))
|
||||
{
|
||||
/* Output a multibyte sequence, or an escaped
|
||||
unprintable unibyte character. */
|
||||
size_t ilim = i + m;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (backslash_escapes && ! printable)
|
||||
{
|
||||
STORE ('\\');
|
||||
STORE ('0' + (c >> 6));
|
||||
STORE ('0' + ((c >> 3) & 7));
|
||||
c = '0' + (c & 7);
|
||||
}
|
||||
if (ilim <= i + 1)
|
||||
break;
|
||||
STORE (c);
|
||||
c = arg[++i];
|
||||
}
|
||||
|
||||
goto store_c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! (backslash_escapes
|
||||
&& o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
|
||||
goto store_c;
|
||||
|
||||
store_escape:
|
||||
STORE ('\\');
|
||||
|
||||
store_c:
|
||||
STORE (c);
|
||||
}
|
||||
|
||||
if (quote_string)
|
||||
for (; *quote_string; quote_string++)
|
||||
STORE (*quote_string);
|
||||
|
||||
if (len < buffersize)
|
||||
buffer[len] = '\0';
|
||||
return len;
|
||||
|
||||
use_shell_always_quoting_style:
|
||||
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
|
||||
shell_always_quoting_style, o);
|
||||
}
|
||||
|
||||
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
|
||||
argument ARG (of size ARGSIZE), using O to control quoting.
|
||||
If O is null, use the default.
|
||||
@@ -532,67 +148,191 @@ quotearg_buffer (char *buffer, size_t buffersize,
|
||||
char const *arg, size_t argsize,
|
||||
struct quoting_options const *o)
|
||||
{
|
||||
unsigned char c;
|
||||
size_t i;
|
||||
size_t len;
|
||||
int quote_mark;
|
||||
struct quoting_options const *p = o ? o : &default_quoting_options;
|
||||
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
|
||||
p->style, p);
|
||||
enum quoting_style quoting_style = p->style;
|
||||
#define STORE(c) \
|
||||
do \
|
||||
{ \
|
||||
if (len < buffersize) \
|
||||
buffer[len] = (c); \
|
||||
len++; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
switch (quoting_style)
|
||||
{
|
||||
case shell_quoting_style:
|
||||
if (! (argsize == (size_t) -1 ? arg[0] == '\0' : argsize == 0))
|
||||
{
|
||||
switch (arg[0])
|
||||
{
|
||||
case '#': case '~':
|
||||
break;
|
||||
|
||||
default:
|
||||
len = 0;
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
if (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize)
|
||||
goto done;
|
||||
|
||||
c = arg[i];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\t': case '\n': case ' ':
|
||||
case '!': /* special in csh */
|
||||
case '"': case '$': case '&': case '\'':
|
||||
case '(': case ')': case '*': case ';':
|
||||
case '<': case '>': case '?': case '[': case '\\':
|
||||
case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
|
||||
case '`': case '|':
|
||||
goto needs_quoting;
|
||||
}
|
||||
|
||||
if (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
|
||||
goto needs_quoting;
|
||||
|
||||
STORE (c);
|
||||
}
|
||||
|
||||
needs_quoting:;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case shell_always_quoting_style:
|
||||
quote_mark = '\'';
|
||||
break;
|
||||
|
||||
case c_quoting_style:
|
||||
quote_mark = '"';
|
||||
break;
|
||||
|
||||
default:
|
||||
quote_mark = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
|
||||
if (quote_mark)
|
||||
STORE (quote_mark);
|
||||
|
||||
for (i = 0; ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize); i++)
|
||||
{
|
||||
c = arg[i];
|
||||
|
||||
switch (quoting_style)
|
||||
{
|
||||
case literal_quoting_style:
|
||||
break;
|
||||
|
||||
case shell_quoting_style:
|
||||
case shell_always_quoting_style:
|
||||
if (c == '\'')
|
||||
{
|
||||
STORE ('\'');
|
||||
STORE ('\\');
|
||||
STORE ('\'');
|
||||
}
|
||||
break;
|
||||
|
||||
case c_quoting_style:
|
||||
case escape_quoting_style:
|
||||
switch (c)
|
||||
{
|
||||
case '?': /* Do not generate trigraphs. */
|
||||
case '\\': goto store_escape;
|
||||
/* Not all C compilers know what \a means. */
|
||||
case 7 : c = 'a'; goto store_escape;
|
||||
case '\b': c = 'b'; goto store_escape;
|
||||
case '\f': c = 'f'; goto store_escape;
|
||||
case '\n': c = 'n'; goto store_escape;
|
||||
case '\r': c = 'r'; goto store_escape;
|
||||
case '\t': c = 't'; goto store_escape;
|
||||
case '\v': c = 'v'; goto store_escape;
|
||||
|
||||
case '"':
|
||||
if (quoting_style == c_quoting_style)
|
||||
goto store_escape;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!ISGRAPH (c))
|
||||
{
|
||||
STORE ('\\');
|
||||
STORE ('0' + (c >> 6));
|
||||
STORE ('0' + ((c >> 3) & 7));
|
||||
c = '0' + (c & 7);
|
||||
goto store_c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (! (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
|
||||
goto store_c;
|
||||
|
||||
store_escape:
|
||||
STORE ('\\');
|
||||
}
|
||||
|
||||
store_c:
|
||||
STORE (c);
|
||||
}
|
||||
|
||||
if (quote_mark)
|
||||
STORE (quote_mark);
|
||||
|
||||
done:
|
||||
if (len < buffersize)
|
||||
buffer[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Use storage slot N to return a quoted version of argument ARG.
|
||||
ARG is of size ARGSIZE, but if that is -1, ARG is a null-terminated string.
|
||||
/* Use storage slot N to return a quoted version of the string ARG.
|
||||
OPTIONS specifies the quoting options.
|
||||
The returned value points to static storage that can be
|
||||
reused by the next call to this function with the same value of N.
|
||||
N must be nonnegative. N is deliberately declared with type "int"
|
||||
N must be nonnegative. N is deliberately declared with type `int'
|
||||
to allow for future extensions (using negative values). */
|
||||
static char *
|
||||
quotearg_n_options (int n, char const *arg, size_t argsize,
|
||||
quotearg_n_options (int n, char const *arg,
|
||||
struct quoting_options const *options)
|
||||
{
|
||||
/* Preallocate a slot 0 buffer, so that the caller can always quote
|
||||
one small component of a "memory exhausted" message in slot 0. */
|
||||
static char slot0[256];
|
||||
static unsigned int nslots = 1;
|
||||
unsigned int n0 = n;
|
||||
struct slotvec
|
||||
static unsigned int nslots;
|
||||
static struct slotvec
|
||||
{
|
||||
size_t size;
|
||||
char *val;
|
||||
};
|
||||
static struct slotvec slotvec0 = {sizeof slot0, slot0};
|
||||
static struct slotvec *slotvec = &slotvec0;
|
||||
} *slotvec;
|
||||
|
||||
if (n < 0)
|
||||
abort ();
|
||||
|
||||
if (nslots <= n0)
|
||||
if (nslots <= n)
|
||||
{
|
||||
unsigned int n1 = n0 + 1;
|
||||
size_t s = n1 * sizeof *slotvec;
|
||||
|
||||
if (SIZE_MAX / UINT_MAX <= sizeof *slotvec
|
||||
&& n1 != s / sizeof *slotvec)
|
||||
xalloc_die ();
|
||||
|
||||
if (slotvec == &slotvec0)
|
||||
{
|
||||
slotvec = (struct slotvec *) xmalloc (sizeof *slotvec);
|
||||
*slotvec = slotvec0;
|
||||
}
|
||||
int n1 = n + 1;
|
||||
size_t s = n1 * sizeof (struct slotvec);
|
||||
if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
|
||||
abort ();
|
||||
slotvec = (struct slotvec *) xrealloc (slotvec, s);
|
||||
memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
|
||||
nslots = n1;
|
||||
memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
|
||||
nslots = n;
|
||||
}
|
||||
|
||||
{
|
||||
size_t size = slotvec[n].size;
|
||||
char *val = slotvec[n].val;
|
||||
size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
|
||||
size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
|
||||
|
||||
if (size <= qsize)
|
||||
{
|
||||
slotvec[n].size = size = qsize + 1;
|
||||
slotvec[n].val = val = xrealloc (val == slot0 ? 0 : val, size);
|
||||
quotearg_buffer (val, size, arg, argsize, options);
|
||||
slotvec[n].val = val = xrealloc (val, size);
|
||||
quotearg_buffer (val, size, arg, (size_t) -1, options);
|
||||
}
|
||||
|
||||
return val;
|
||||
@@ -600,9 +340,9 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n (int n, char const *arg)
|
||||
quotearg_n (unsigned int n, char const *arg)
|
||||
{
|
||||
return quotearg_n_options (n, arg, (size_t) -1, &default_quoting_options);
|
||||
return quotearg_n_options (n, arg, &default_quoting_options);
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -611,44 +351,13 @@ quotearg (char const *arg)
|
||||
return quotearg_n (0, arg);
|
||||
}
|
||||
|
||||
/* Return quoting options for STYLE, with no extra quoting. */
|
||||
static struct quoting_options
|
||||
quoting_options_from_style (enum quoting_style style)
|
||||
{
|
||||
struct quoting_options o;
|
||||
o.style = style;
|
||||
memset (o.quote_these_too, 0, sizeof o.quote_these_too);
|
||||
return o;
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n_style (int n, enum quoting_style s, char const *arg)
|
||||
{
|
||||
struct quoting_options const o = quoting_options_from_style (s);
|
||||
return quotearg_n_options (n, arg, (size_t) -1, &o);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n_style_mem (int n, enum quoting_style s,
|
||||
char const *arg, size_t argsize)
|
||||
{
|
||||
struct quoting_options const o = quoting_options_from_style (s);
|
||||
return quotearg_n_options (n, arg, argsize, &o);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_style (enum quoting_style s, char const *arg)
|
||||
{
|
||||
return quotearg_n_style (0, s, arg);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_char (char const *arg, char ch)
|
||||
{
|
||||
struct quoting_options options;
|
||||
options = default_quoting_options;
|
||||
set_char_quoting (&options, ch, 1);
|
||||
return quotearg_n_options (0, arg, (size_t) -1, &options);
|
||||
return quotearg_n_options (0, arg, &options);
|
||||
}
|
||||
|
||||
char *
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/* stdopen.c - ensure that the three standard file descriptors are in use
|
||||
|
||||
Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert and Jim Meyering. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "stdopen.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Try to ensure that all of the standard file numbers (0, 1, 2)
|
||||
are in use. Without this, each application would have to guard
|
||||
every call to open, dup, fopen, etc. with tests to ensure they
|
||||
don't use one of the special file numbers when opening a file.
|
||||
Return false if at least one of the file descriptors is initially
|
||||
closed and an attempt to reopen it fails. Otherwise, return true. */
|
||||
bool
|
||||
stdopen (void)
|
||||
{
|
||||
int fd;
|
||||
bool ok = true;
|
||||
|
||||
for (fd = 0; fd <= 2; fd++)
|
||||
{
|
||||
if (fcntl (fd, F_GETFD) < 0)
|
||||
{
|
||||
if (errno != EBADF)
|
||||
ok = false;
|
||||
else
|
||||
{
|
||||
static const int contrary_mode[]
|
||||
= { O_WRONLY, O_RDONLY, O_RDONLY };
|
||||
int mode = contrary_mode[fd];
|
||||
int new_fd;
|
||||
/* Open /dev/null with the contrary mode so that the typical
|
||||
read (stdin) or write (stdout, stderr) operation will fail.
|
||||
With descriptor 0, we can do even better on systems that
|
||||
have /dev/full, by opening that write-only instead of
|
||||
/dev/null. The only drawback is that a write-provoked
|
||||
failure comes with a misleading errno value, ENOSPC. */
|
||||
if (mode == O_RDONLY
|
||||
|| (new_fd = open ("/dev/full", mode) != fd))
|
||||
new_fd = open ("/dev/null", mode);
|
||||
if (new_fd != fd)
|
||||
{
|
||||
if (0 <= new_fd)
|
||||
close (new_fd);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef STDOPEN_H
|
||||
# define STDOPEN_H 1
|
||||
|
||||
# include <stdbool.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
bool stdopen (void);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
/* Convert string representation of a number into an intmax_t value.
|
||||
|
||||
Copyright (C) 1999, 2001 Free Software Foundation, Inc.
|
||||
Copyright 1999, 2001 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
|
||||
@@ -66,7 +65,7 @@ long strtol PARAMS ((char const *, char **, int));
|
||||
# ifndef HAVE_DECL_STRTOLL
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG
|
||||
# if !HAVE_DECL_STRTOLL && HAVE_UNSIGNED_LONG_LONG
|
||||
long long strtoll PARAMS ((char const *, char **, int));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
178
lib/unicodeio.c
178
lib/unicodeio.c
@@ -1,27 +1,23 @@
|
||||
/* Unicode character output to streams with locale dependent encoding.
|
||||
|
||||
Copyright (C) 2000-2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your option)
|
||||
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
|
||||
Library General Public License for more details.
|
||||
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 Library 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. */
|
||||
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 Bruno Haible <haible@clisp.cons.org>. */
|
||||
|
||||
/* Note: This file requires the locale_charset() function. See in
|
||||
libiconv-1.7/libcharset/INTEGRATE for how to obtain it. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
@@ -46,17 +42,20 @@ extern int errno;
|
||||
# include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include <error.h>
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(Text) Text
|
||||
/* Some systems, like SunOS 4, don't have EILSEQ. On these systems,
|
||||
define EILSEQ to some value other than EINVAL, because our invokers
|
||||
may want to distinguish EINVAL from EILSEQ. */
|
||||
#ifndef EILSEQ
|
||||
# define EILSEQ ENOENT
|
||||
#endif
|
||||
#ifndef ENOTSUP
|
||||
# define ENOTSUP EINVAL
|
||||
#endif
|
||||
|
||||
#if HAVE_LANGINFO_CODESET && ! USE_INCLUDED_LIBINTL
|
||||
# include <langinfo.h>
|
||||
#endif
|
||||
#define _(Text) gettext (Text)
|
||||
#define N_(Text) Text
|
||||
|
||||
/* Specification. */
|
||||
#include "unicodeio.h"
|
||||
|
||||
/* When we pass a Unicode character to iconv(), we must pass it in a
|
||||
@@ -111,17 +110,17 @@ utf8_wctomb (unsigned char *r, unsigned int wc)
|
||||
#define UTF8_NAME "UTF-8"
|
||||
|
||||
/* Converts the Unicode character CODE to its multibyte representation
|
||||
in the current locale and calls the SUCCESS callback on the resulting
|
||||
byte sequence. If an error occurs, invokes the FAILURE callback instead,
|
||||
passing it CODE and an English error string.
|
||||
Returns whatever the callback returned.
|
||||
Assumes that the locale doesn't change between two calls. */
|
||||
long
|
||||
in the current locale and calls SUCCESS on the resulting byte
|
||||
sequence. If an error occurs, invoke FAILURE instead,
|
||||
passing it CODE with errno set appropriately.
|
||||
Assumes that the locale doesn't change between two calls.
|
||||
Return whatever the SUCCESS or FAILURE returns. */
|
||||
int
|
||||
unicode_to_mb (unsigned int code,
|
||||
long (*success) PARAMS ((const char *buf, size_t buflen,
|
||||
void *callback_arg)),
|
||||
long (*failure) PARAMS ((unsigned int code, const char *msg,
|
||||
void *callback_arg)),
|
||||
int (*success) PARAMS((const char *buf, size_t buflen,
|
||||
void *callback_arg)),
|
||||
int (*failure) PARAMS((unsigned int code,
|
||||
void *callback_arg)),
|
||||
void *callback_arg)
|
||||
{
|
||||
static int initialized;
|
||||
@@ -135,8 +134,18 @@ unicode_to_mb (unsigned int code,
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
const char *charset;
|
||||
|
||||
#if USE_INCLUDED_LIBINTL
|
||||
extern const char *locale_charset PARAMS ((void));
|
||||
const char *charset = locale_charset ();
|
||||
charset = locale_charset ();
|
||||
#else
|
||||
# if HAVE_LANGINFO_CODESET
|
||||
charset = nl_langinfo (CODESET);
|
||||
# else
|
||||
charset = "";
|
||||
# endif
|
||||
#endif
|
||||
|
||||
is_utf8 = !strcmp (charset, UTF8_NAME);
|
||||
#if HAVE_ICONV
|
||||
@@ -144,32 +153,32 @@ unicode_to_mb (unsigned int code,
|
||||
{
|
||||
utf8_to_local = iconv_open (charset, UTF8_NAME);
|
||||
if (utf8_to_local == (iconv_t)(-1))
|
||||
/* For an unknown encoding, assume ASCII. */
|
||||
utf8_to_local = iconv_open ("ASCII", UTF8_NAME);
|
||||
{
|
||||
/* For an unknown encoding, assume ASCII. */
|
||||
utf8_to_local = iconv_open ("ASCII", UTF8_NAME);
|
||||
if (utf8_to_local == (iconv_t)(-1))
|
||||
return failure (code, callback_arg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
/* Test whether the utf8_to_local converter is available at all. */
|
||||
if (!is_utf8)
|
||||
{
|
||||
#if HAVE_ICONV
|
||||
if (utf8_to_local == (iconv_t)(-1))
|
||||
return failure (code, N_("iconv function not usable"), callback_arg);
|
||||
#else
|
||||
return failure (code, N_("iconv function not available"), callback_arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert the character to UTF-8. */
|
||||
count = utf8_wctomb ((unsigned char *) inbuf, code);
|
||||
if (count < 0)
|
||||
return failure (code, N_("character out of range"), callback_arg);
|
||||
|
||||
#if HAVE_ICONV
|
||||
if (!is_utf8)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return failure (code, callback_arg);
|
||||
}
|
||||
|
||||
if (is_utf8)
|
||||
{
|
||||
return success (inbuf, count, callback_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if HAVE_ICONV
|
||||
char outbuf[25];
|
||||
const char *inptr;
|
||||
size_t inbytesleft;
|
||||
@@ -192,7 +201,11 @@ unicode_to_mb (unsigned int code,
|
||||
|| (res > 0 && code != 0 && outptr - outbuf == 1 && *outbuf == '\0')
|
||||
# endif
|
||||
)
|
||||
return failure (code, NULL, callback_arg);
|
||||
{
|
||||
if (res != (size_t)(-1))
|
||||
errno = EILSEQ;
|
||||
return failure (code, callback_arg);
|
||||
}
|
||||
|
||||
/* Avoid glibc-2.1 bug and Solaris 2.7 bug. */
|
||||
# if defined _LIBICONV_VERSION \
|
||||
@@ -201,63 +214,46 @@ unicode_to_mb (unsigned int code,
|
||||
/* Get back to the initial shift state. */
|
||||
res = iconv (utf8_to_local, NULL, NULL, &outptr, &outbytesleft);
|
||||
if (res == (size_t)(-1))
|
||||
return failure (code, NULL, callback_arg);
|
||||
return failure (code, callback_arg);
|
||||
# endif
|
||||
|
||||
return success (outbuf, outptr - outbuf, callback_arg);
|
||||
}
|
||||
#else
|
||||
errno = ENOTSUP;
|
||||
return failure (code, callback_arg);
|
||||
#endif
|
||||
|
||||
/* At this point, is_utf8 is true, so no conversion is needed. */
|
||||
return success (inbuf, count, callback_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Simple success callback that outputs the converted string.
|
||||
The STREAM is passed as callback_arg. */
|
||||
long
|
||||
fwrite_success_callback (const char *buf, size_t buflen, void *callback_arg)
|
||||
int
|
||||
print_unicode_success (const char *buf, size_t buflen, void *callback_arg)
|
||||
{
|
||||
FILE *stream = (FILE *) callback_arg;
|
||||
|
||||
fwrite (buf, 1, buflen, stream);
|
||||
return 0;
|
||||
return fwrite (buf, 1, buflen, stream) == 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
/* Simple failure callback that displays an error and exits. */
|
||||
static long
|
||||
exit_failure_callback (unsigned int code, const char *msg, void *callback_arg)
|
||||
/* Simple failure callback that prints an ASCII representation, using
|
||||
the same notation as C99 strings. */
|
||||
int
|
||||
print_unicode_failure (unsigned int code, void *callback_arg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
error (1, 0, _("cannot convert U+%04X to local character set"), code);
|
||||
else
|
||||
error (1, 0, _("cannot convert U+%04X to local character set: %s"), code,
|
||||
gettext (msg));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Simple failure callback that displays a fallback representation in plain
|
||||
ASCII, using the same notation as ISO C99 strings. */
|
||||
static long
|
||||
fallback_failure_callback (unsigned int code, const char *msg, void *callback_arg)
|
||||
{
|
||||
FILE *stream = (FILE *) callback_arg;
|
||||
|
||||
if (code < 0x10000)
|
||||
fprintf (stream, "\\u%04X", code);
|
||||
else
|
||||
fprintf (stream, "\\U%08X", code);
|
||||
int e = errno;
|
||||
FILE *stream = callback_arg;
|
||||
|
||||
fprintf (stream, code < 0x10000 ? "\\u%04X" : "\\U%08X", code);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Outputs the Unicode character CODE to the output stream STREAM.
|
||||
Upon failure, exit if exit_on_error is true, otherwise output a fallback
|
||||
notation. */
|
||||
void
|
||||
print_unicode_char (FILE *stream, unsigned int code, int exit_on_error)
|
||||
Returns zero if successful, -1 (setting errno) otherwise.
|
||||
Assumes that the locale doesn't change between two calls. */
|
||||
int
|
||||
print_unicode_char (FILE *stream, unsigned int code)
|
||||
{
|
||||
unicode_to_mb (code, fwrite_success_callback,
|
||||
exit_on_error
|
||||
? exit_failure_callback
|
||||
: fallback_failure_callback,
|
||||
stream);
|
||||
return unicode_to_mb (code, print_unicode_success, print_unicode_failure,
|
||||
stream);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
/* Unicode character output to streams with locale dependent encoding.
|
||||
|
||||
Copyright (C) 2000-2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your option)
|
||||
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
|
||||
Library General Public License for more details.
|
||||
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 Library 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. */
|
||||
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. */
|
||||
|
||||
#ifndef UNICODEIO_H
|
||||
# define UNICODEIO_H
|
||||
@@ -30,15 +29,29 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Outputs the Unicode character CODE to the output stream STREAM.
|
||||
Upon failure, exit if exit_on_error is true, otherwise output a fallback
|
||||
notation. */
|
||||
extern void print_unicode_char PARAMS ((FILE *stream, unsigned int code,
|
||||
int exit_on_error));
|
||||
/* Converts the Unicode character CODE to its multibyte representation
|
||||
in the current locale and calls the CALLBACK on the resulting byte
|
||||
sequence. If an error occurs, invokes ERROR_CALLBACK instead,
|
||||
passing it CODE with errno set appropriately. Returns whatever the
|
||||
callback returns. */
|
||||
extern int unicode_to_mb
|
||||
PARAMS ((unsigned int code,
|
||||
int (*callback) PARAMS ((const char *buf, size_t buflen,
|
||||
void *callback_arg)),
|
||||
int (*error_callback) PARAMS ((unsigned int code,
|
||||
void * callback_arg)),
|
||||
void *callback_arg));
|
||||
|
||||
/* Simple success callback that outputs the converted string.
|
||||
The STREAM is passed as callback_arg. */
|
||||
extern long fwrite_success_callback PARAMS ((const char *buf, size_t buflen,
|
||||
void *callback_arg));
|
||||
/* Success callback that outputs the conversion of the character. */
|
||||
extern int print_unicode_success PARAMS((const char *buf, size_t buflen,
|
||||
void *callback_arg));
|
||||
|
||||
/* Failure callback that outputs an ASCII representation. */
|
||||
extern int print_unicode_failure PARAMS((unsigned int code,
|
||||
void *callback_arg));
|
||||
|
||||
/* Outputs the Unicode character CODE to the output stream STREAM.
|
||||
Returns -1 (setting errno) if unsuccessful. */
|
||||
extern int print_unicode_char PARAMS((FILE *stream, unsigned int code));
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,15 +14,12 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.m4
|
||||
33
m4/Makefile.am
Normal file
33
m4/Makefile.am
Normal file
@@ -0,0 +1,33 @@
|
||||
## Process this file with automake to produce Makefile.in -*-Makefile-*-
|
||||
|
||||
EXTRA_DIST = \
|
||||
c-bs-a.m4 \
|
||||
ccstdc.m4 \
|
||||
check-decl.m4 \
|
||||
codeset.m4 \
|
||||
d-ino.m4 \
|
||||
decl.m4 \
|
||||
error.m4 \
|
||||
fnmatch.m4 \
|
||||
getcwd.m4 \
|
||||
getline.m4 \
|
||||
gettext.m4 \
|
||||
glibc21.m4 \
|
||||
iconv.m4 \
|
||||
inttypes.m4 \
|
||||
jm-mktime.m4 \
|
||||
lcmessage.m4 \
|
||||
longlong.m4 \
|
||||
malloc.m4 \
|
||||
mbrtowc.m4 \
|
||||
mbstate_t.m4 \
|
||||
prereq.m4 \
|
||||
progtest.m4 \
|
||||
realloc.m4 \
|
||||
strerror_r.m4 \
|
||||
ulonglong.m4 \
|
||||
utimbuf.m4 \
|
||||
utime.m4 \
|
||||
utimes.m4 \
|
||||
xstrtoimax.m4 \
|
||||
xstrtoumax.m4
|
||||
@@ -1,4 +1,4 @@
|
||||
#serial 3
|
||||
#serial 4
|
||||
|
||||
dnl FIXME: put these prerequisite-only *.m4 files in a separate
|
||||
dnl directory -- otherwise, they'll conflict with existing files.
|
||||
@@ -6,7 +6,8 @@ dnl directory -- otherwise, they'll conflict with existing files.
|
||||
dnl These are the prerequisite macros for GNU's error.c file.
|
||||
AC_DEFUN([jm_PREREQ_ERROR],
|
||||
[
|
||||
AC_CHECK_FUNCS(strerror strerror_r vprintf doprnt)
|
||||
AC_CHECK_FUNCS(strerror vprintf doprnt)
|
||||
AC_CHECK_DECLS([strerror])
|
||||
AC_FUNC_STRERROR_R
|
||||
AC_HEADER_STDC
|
||||
])
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
#serial 1002
|
||||
#serial 1003
|
||||
# Experimental replacement for the function in the latest CVS autoconf.
|
||||
# If the compile-test says strerror_r doesn't work, then resort to a
|
||||
# `run'-test that works on BeOS and segfaults on DEC Unix.
|
||||
# Use with the error.c file in ../lib.
|
||||
|
||||
# Copyright 2001 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. */
|
||||
|
||||
undefine([AC_FUNC_STRERROR_R])
|
||||
|
||||
# AC_FUNC_STRERROR_R
|
||||
@@ -11,56 +25,35 @@ undefine([AC_FUNC_STRERROR_R])
|
||||
AC_DEFUN([AC_FUNC_STRERROR_R],
|
||||
[AC_CHECK_DECLS([strerror_r])
|
||||
AC_CHECK_FUNCS([strerror_r])
|
||||
if test $ac_cv_func_strerror_r = yes; then
|
||||
AC_CHECK_HEADERS(string.h)
|
||||
AC_CACHE_CHECK([for working strerror_r],
|
||||
ac_cv_func_strerror_r_works,
|
||||
AC_CACHE_CHECK([whether strerror_r returns char *],
|
||||
ac_cv_func_strerror_r_char_p,
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
# include <stdio.h>
|
||||
# if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# endif
|
||||
],
|
||||
[
|
||||
char buf[100];
|
||||
char x = *strerror_r (0, buf, sizeof buf);
|
||||
],
|
||||
ac_cv_func_strerror_r_works=yes,
|
||||
ac_cv_func_strerror_r_works=no
|
||||
)
|
||||
if test $ac_cv_func_strerror_r_works = no; then
|
||||
# strerror_r seems not to work, but now we have to choose between
|
||||
ac_cv_func_strerror_r_char_p=no
|
||||
if test $ac_cv_have_decl_strerror_r = yes; then
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
|
||||
[[
|
||||
char buf[100];
|
||||
char x = *strerror_r (0, buf, sizeof buf);
|
||||
char *p = strerror_r (0, buf, sizeof buf);
|
||||
]])],
|
||||
ac_cv_func_strerror_r_char_p=yes)
|
||||
else
|
||||
# strerror_r is not declared. Choose between
|
||||
# systems that have relatively inaccessible declarations for the
|
||||
# function. BeOS and DEC UNIX 4.0 fall in this category, but the
|
||||
# former has a strerror_r that returns char*, while the latter
|
||||
# has a strerror_r that returns `int'.
|
||||
# This test should segfault on the DEC system.
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include <ctype.h>
|
||||
|
||||
extern char *strerror_r ();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
char buf[100];
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
|
||||
extern char *strerror_r ();],
|
||||
[[char buf[100];
|
||||
char x = *strerror_r (0, buf, sizeof buf);
|
||||
exit (!isalpha (x));
|
||||
}
|
||||
],
|
||||
ac_cv_func_strerror_r_works=yes,
|
||||
ac_cv_func_strerror_r_works=no,
|
||||
ac_cv_func_strerror_r_works=no)
|
||||
exit (!isalpha (x));]])],
|
||||
ac_cv_func_strerror_r_char_p=yes, , :)
|
||||
fi
|
||||
])
|
||||
if test $ac_cv_func_strerror_r_works = yes; then
|
||||
AC_DEFINE(HAVE_WORKING_STRERROR_R, 1,
|
||||
[Define to 1 if `strerror_r' returns a string.])
|
||||
fi
|
||||
if test $ac_cv_func_strerror_r_char_p = yes; then
|
||||
AC_DEFINE([STRERROR_R_CHAR_P], 1,
|
||||
[Define to 1 if strerror_r returns char *.])
|
||||
fi
|
||||
])# AC_FUNC_STRERROR_R
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
index.html
|
||||
*.po
|
||||
LINGUAS
|
||||
Makefile.in.in
|
||||
Makevars
|
||||
Makevars.template
|
||||
Rules-quot
|
||||
boldquot.sed
|
||||
en@boldquot.header
|
||||
en@quot.header
|
||||
insert-header.sin
|
||||
quot.sed
|
||||
remove-potcdate.sin
|
||||
Makefile.in
|
||||
POTFILES
|
||||
Makefile
|
||||
tar.pot
|
||||
remove-potcdate.sed
|
||||
*.gmo
|
||||
*.mo
|
||||
stamp-po
|
||||
@@ -1,43 +1,14 @@
|
||||
# List of files which contain translatable strings.
|
||||
|
||||
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# Copyright 1996, 1999 Free Software Foundation, Inc.
|
||||
|
||||
# Library files
|
||||
lib/argmatch.c
|
||||
lib/argp-help.c
|
||||
lib/argp-parse.c
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
lib/human.c
|
||||
lib/obstack.c
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
lib/quotearg.c
|
||||
lib/rpmatch.c
|
||||
lib/rtapelib.c
|
||||
lib/xalloc-die.c
|
||||
lib/xmalloc.c
|
||||
|
||||
rmt/rmt.c
|
||||
|
||||
# Package source files
|
||||
src/arith.c
|
||||
src/buffer.c
|
||||
src/common.h
|
||||
src/compare.c
|
||||
@@ -49,9 +20,10 @@ src/list.c
|
||||
src/mangle.c
|
||||
src/misc.c
|
||||
src/names.c
|
||||
src/rmt.c
|
||||
src/rtapelib.c
|
||||
src/tar.c
|
||||
src/update.c
|
||||
src/xheader.c
|
||||
|
||||
# Testsuite
|
||||
# Checking tools
|
||||
tests/genfile.c
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
backup.sh
|
||||
backup
|
||||
restore
|
||||
dump-remind
|
||||
@@ -1,4 +1,5 @@
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Makefile for GNU tar scripts.
|
||||
# Copyright (C) 1994 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
|
||||
@@ -11,39 +12,9 @@
|
||||
## 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.
|
||||
## along with this program; if not, write to the Free Software Foundation,
|
||||
## Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
BACKUP_LIBEXEC_SCRIPTS_LIST=backup.sh dump-remind
|
||||
BACKUP_SBIN_SCRIPTS_LIST=backup restore
|
||||
libexec_SCRIPTS=@BACKUP_LIBEXEC_SCRIPTS@
|
||||
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=backup.sh dump-remind
|
||||
sbin_SCRIPTS=@BACKUP_SBIN_SCRIPTS@
|
||||
EXTRA_SCRIPTS=tarcat
|
||||
EXTRA_DIST=\
|
||||
backup.sh.in\
|
||||
backup.in\
|
||||
restore.in\
|
||||
dump-remind.in\
|
||||
backup-specs
|
||||
CLEANFILES=backup.sh backup restore dump-remind
|
||||
AUTOMAKE_OPTIONS = gnits
|
||||
|
||||
SED_CMD="s,\@libexecdir\@,$(libexecdir),;\
|
||||
s,\@sysconfdir\@,$(sysconfdir),;\
|
||||
s,\@PACKAGE_NAME\@,$(PACKAGE_NAME),;\
|
||||
s,\@VERSION\@,$(VERSION),;\
|
||||
s,\@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),;\
|
||||
s,\@DATE_FORMAT_OK\@,$(DATE_FORMAT_OK),;@BACKUP_SED_COND@"
|
||||
|
||||
backup.sh: $(srcdir)/backup.sh.in
|
||||
sed $(SED_CMD) $? > $@
|
||||
|
||||
backup: $(srcdir)/backup.in
|
||||
sed $(SED_CMD) $? > $@
|
||||
|
||||
restore: $(srcdir)/restore.in
|
||||
sed $(SED_CMD) $? > $@
|
||||
|
||||
dump-remind: $(srcdir)/dump-remind.in
|
||||
sed $(SED_CMD) $? > $@
|
||||
EXTRA_DIST = WARNING backup-specs dump-remind level-0 level-1 weekly.new
|
||||
|
||||
3
scripts/WARNING
Normal file
3
scripts/WARNING
Normal file
@@ -0,0 +1,3 @@
|
||||
GNU tar scripts have not been updated in a long while. make will
|
||||
not not install them. Please consider the contents of this directory
|
||||
are provided as indicative for the time being.
|
||||
@@ -1,68 +1,34 @@
|
||||
# This is a sample configuration file for GNU tar backup script.
|
||||
# See end of file for copying conditions
|
||||
# site-specific parameters for file system backup.
|
||||
|
||||
# User name or email address of the administrator of backups. A report
|
||||
# will be sent to this address when the backup terminates
|
||||
ADMINISTRATOR="root@localhost"
|
||||
# User name of administrator of backups.
|
||||
ADMINISTRATOR=backup-reports
|
||||
|
||||
# (Optional) Path to tar binary.
|
||||
TAR=/bin/tar
|
||||
# Hour at which backups are normally done.
|
||||
# This should be a number from 0 to 23.
|
||||
BACKUP_HOUR=1
|
||||
|
||||
# (Optional) Path to rsh binary or its equivalent. You may wish to
|
||||
# set it to ssh as shown in the example below, to improve security.
|
||||
# In this case you will have to use public key authentication.
|
||||
RSH=/usr/local/bin/ssh
|
||||
|
||||
# (Optional) Path to rsh binary on remote mashines. This will be
|
||||
# passed via --rsh-command option to the remote invocation of
|
||||
# tar
|
||||
RSH_COMMAND=/usr/local/bin/ssh
|
||||
|
||||
# Name of temporary file to hold volume numbers. This needs to be accessible
|
||||
# by all the machines which have filesystems to be dumped.
|
||||
VOLNO_FILE=/root/volume
|
||||
# Location of GNU tar. This must be the same for all hosts.
|
||||
TAR=/usr/local/gnubin/tar
|
||||
|
||||
# Device to use for dumping. It should be on the host
|
||||
# on which the dump scripts are run.
|
||||
TAPE_FILE=/dev/rmt0
|
||||
TAPE_FILE=/dev/nrsmt0
|
||||
|
||||
# Command to obtain status of tape drive, including error count.
|
||||
# On some tape drives there may not be such a command;
|
||||
# then simply use `TAPE_STATUS=false'.
|
||||
#
|
||||
# Might also consider
|
||||
# TAPE_STATUS="mt -f ${TAPE_FILE} status"
|
||||
# if `mts' is missing, though this alternative is rather verbose.
|
||||
TAPE_STATUS="mts -t ${TAPE_FILE}"
|
||||
|
||||
# Blocking factor to use for writing the dump.
|
||||
BLOCKING=124
|
||||
|
||||
# List of file systems to be dumped. If prefixed with a HOST:
|
||||
# the filesystem is accessed on the given HOST, unless it
|
||||
# coincides with the local machine name.
|
||||
# If a file system starts with a slash, it is handled as a local
|
||||
# one.
|
||||
BACKUP_DIRS='remote1:/etc remote1:/var/spool/crontab'
|
||||
# Alternatively, you may leave this variable unassigned, and
|
||||
# keep the list of filesystems to be dumped in file
|
||||
# $SYSCONFDIR/backup/dirs, one filesystem per line. Empty
|
||||
# lines and shell comments are allowed in this file. The location
|
||||
# of this file may be overridden using DIRLIST variable, e.g.:
|
||||
# DIRLIST=/etc/my-backup/dirlist
|
||||
|
||||
# List of individual files to be dumped.
|
||||
# These should be accesible from the machine on which the dump is run.
|
||||
BACKUP_FILES=''
|
||||
# This list may also be kept in file $SYSCONFDIR/backup/files, the
|
||||
# format of which is the same as described above. The location of
|
||||
# this file may be overridden by setting FILELIST variable:
|
||||
# FILELIST=/etc/my-backup/filelist
|
||||
|
||||
# Name of 'exclude file list'. It is searched under $SYSCONFDIR/tar-backup
|
||||
# on remote machines
|
||||
XLIST=exclude_files
|
||||
|
||||
# Default directory for storing incremental listings on remote
|
||||
# machines is $SYSCONFDIR/tar-backup. It can be overridden using
|
||||
# REMOTEBACKUPDIR variable
|
||||
|
||||
# Default directory for storing backup logs is $SYSCONFDIR/backup/log.
|
||||
# It can also be overridden via LOGPATH variable.
|
||||
|
||||
# Time to sleep between dumps of any two successive filesystems
|
||||
SLEEP_TIME=15
|
||||
# Name of temporary file to hold volume numbers. This needs to be accessible
|
||||
# by all the machines which have filesystems to be dumped.
|
||||
VOLNO_FILE=/home/gd2/dump/volnofile
|
||||
|
||||
# Script to be run when it's time to insert a new tape in for the next
|
||||
# volume. Administrators may want to tailor this script for their site.
|
||||
@@ -70,6 +36,37 @@ SLEEP_TIME=15
|
||||
# probably defined in the manual.
|
||||
#DUMP_REMIND_SCRIPT='rsh apple-gunkies /home/gd2/dump/dump-remind'
|
||||
|
||||
# List of file systems to be dumped.
|
||||
# Actually, any directory may be used, but if it has subdirectories on
|
||||
# other file systems, they are not included.
|
||||
# The host name specifies which host to run tar on.
|
||||
# It should normally be the host that actually has the file system.
|
||||
# If GNU tar is not installed on that machine, then you can specify some
|
||||
# other host which can access the file system through NFS.
|
||||
# Although these are arranged one per line, that is not mandatory.
|
||||
# It does not work to use # for comments within the string.
|
||||
|
||||
BACKUP_DIRS='
|
||||
albert:/fs/fsf
|
||||
sugar-bombs:/fs/gd
|
||||
albert:/fs/gd2
|
||||
churchy:/fs/gd3
|
||||
nutrimat:/fs/gp
|
||||
nutrimat:/fs/gp2
|
||||
albert:/fs/mailer
|
||||
placebo:/archive
|
||||
nutrimat:/fs/dist
|
||||
albert:/
|
||||
albert:/usr
|
||||
nutrimat:/
|
||||
placebo:/
|
||||
ernst:/usr1
|
||||
'
|
||||
|
||||
# List of individual files to be dumped.
|
||||
# These should be accesible from the machine on which the dump is run.
|
||||
BACKUP_FILES=''
|
||||
|
||||
# Message to display on the terminal while waiting for dump time. Usually
|
||||
# this will just be some literal text, preferably something more
|
||||
# entertaining than this. The awk script here saves some redundant
|
||||
@@ -81,20 +78,5 @@ SLEEP_MESSAGE="`awk '
|
||||
\"D O N O T T O U C H T H I S T E R M I N A L !!!!!\"
|
||||
}' /dev/null`"
|
||||
|
||||
|
||||
# Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
# eof
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright (C) 2004, 2005, 2006 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 1, 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.
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
. ${LIBDIR-@libexecdir@}/backup.sh
|
||||
|
||||
DUMP_LEVEL=0
|
||||
TIME=
|
||||
NOW=`now`
|
||||
|
||||
usage() {
|
||||
cat - <<EOF
|
||||
usage: $PROGNAME [OPTIONS] [WHEN]
|
||||
Options are:
|
||||
|
||||
-l, --level=LEVEL Do backup level LEVEL (default $DUMP_LEVEL).
|
||||
-f, --force Force backup even if today's log file already
|
||||
exists.
|
||||
-v, --verbose[=LEVEL] Set verbosity level. Default 100.
|
||||
-t, --time=TIME Wait till TIME, then do backup.
|
||||
|
||||
Informational options:
|
||||
-h, --help Display this help message.
|
||||
-V, --version Display program version.
|
||||
|
||||
Optional argument WHEN is for backward compatibility only. It has been
|
||||
superseded by --time option.
|
||||
TIME argument can be one of:
|
||||
|
||||
now -- do backup immediately.
|
||||
HH -- do backup at HH hours.
|
||||
HH:MM -- do backup at HH:MM.
|
||||
|
||||
Send bug reports to @PACKAGE_BUGREPORT@.
|
||||
EOF
|
||||
}
|
||||
|
||||
# For compatibility with previous versions, deduce the backup level
|
||||
# from the command name
|
||||
case "$PROGNAME" in
|
||||
level-[0-9]) DUMP_LEVEL=`expr $PROGNAME : 'level-\([0-9][0-9]*\)'`;;
|
||||
esac
|
||||
|
||||
for opt
|
||||
do
|
||||
if [ -z "$prev" ]; then
|
||||
option=$opt
|
||||
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
|
||||
else
|
||||
option="${prev}=$opt"
|
||||
prev=""
|
||||
optarg=$opt
|
||||
fi
|
||||
case $option in
|
||||
--l=*|--le=*|--lev=*|--leve=*|--level=*)
|
||||
DUMP_LEVEL=$optarg
|
||||
;;
|
||||
-l|--l|--le|--lev|--leve|--level)
|
||||
prev=$option
|
||||
;;
|
||||
--verb=*|--verbo=*|--verbos=*|--verbose=*)
|
||||
VERBOSE=$optarg
|
||||
;;
|
||||
-v|--verb|--verbo|--verbos|--verbose)
|
||||
VERBOSE=100
|
||||
;;
|
||||
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
|
||||
--t=*|--ti=*|--tim=*|--time=*)
|
||||
TIME=$optarg
|
||||
;;
|
||||
-t) prev=--t;;
|
||||
-t*) TIME=`expr $option : "-t\(.*\)"`;;
|
||||
--t|--ti|--tim|--time)
|
||||
prev=$option
|
||||
;;
|
||||
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "backup (@PACKAGE_NAME@) @VERSION@"
|
||||
license
|
||||
exit;;
|
||||
-h|--h|--he|--hel|--help)
|
||||
usage
|
||||
exit;;
|
||||
-f|--f|--fo|--for|--forc|--force)
|
||||
FORCE=yes
|
||||
;;
|
||||
*) if [ "x$TIME" != "x" ]; then
|
||||
bailout "Extra argument. Try $PROGNAME --help for more info."
|
||||
else
|
||||
TIME=$option
|
||||
fi;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "x$TIME" = x ]; then
|
||||
bailout "No backup time specified. Try $PROGNAME --help for more info."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
init_backup
|
||||
|
||||
# Maybe sleep until around specified or default hour.
|
||||
wait_time $TIME
|
||||
|
||||
if [ $DUMP_LEVEL -ne 0 ]; then
|
||||
PREV_LEVEL=`expr $DUMP_LEVEL - 1`
|
||||
PREV_DATE=`ls -t ${LOGPATH}/log-*-level-$PREV_LEVEL|
|
||||
head -n 1|
|
||||
sed "s,${LOGPATH}/log-\(.*\)-level.*,\1,"`
|
||||
if [ "x$PREV_DATE" = x ]; then
|
||||
bailout "Can't determine date of the previous backup"
|
||||
fi
|
||||
message 0 "Backup from $PREV_DATE to $NOW"
|
||||
fi
|
||||
|
||||
# start doing things
|
||||
|
||||
# Make sure the log file did not already exist. Create it.
|
||||
|
||||
if [ "x$FORCE" = "xyes" ]; then
|
||||
rm ${LOGFILE}
|
||||
fi
|
||||
|
||||
if [ -f "${LOGFILE}" ] ; then
|
||||
bailout "Log file ${LOGFILE} already exists."
|
||||
else
|
||||
touch "${LOGFILE}"
|
||||
fi
|
||||
message 1 "Ready for backup."
|
||||
message 10 "TAR invocation: $TAR_PART1"
|
||||
message 20 "Variables:"
|
||||
message 20 "BACKUP_DIRS=$BACKUP_DIRS"
|
||||
message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
|
||||
# The buch of commands below is run in a subshell for which all output is
|
||||
# piped through `tee' to the logfile. Doing this, instead of having
|
||||
# multiple pipelines all over the place, is cleaner and allows access to
|
||||
# the exit value from various commands more easily.
|
||||
(
|
||||
message 1 "preparing tapes"
|
||||
$MT_BEGIN "${TAPE_FILE}"
|
||||
rm -f "${VOLNO_FILE}"
|
||||
|
||||
message 1 "processing backup directories"
|
||||
|
||||
set - ${BACKUP_DIRS}
|
||||
while [ $# -ne 0 ] ; do
|
||||
date="`date`"
|
||||
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
|
||||
fs=`root_fs $fs`
|
||||
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
|
||||
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
|
||||
if [ -z "$remotehost" ]; then
|
||||
remotehost=$localhost
|
||||
fi
|
||||
|
||||
echo "Backing up ${1} at ${date}"
|
||||
message 10 "fs=$fs"
|
||||
message 10 "fsname=$fsname"
|
||||
message 10 "remotehost=$remotehost"
|
||||
if [ $DUMP_LEVEL -eq 0 ]; then
|
||||
make_level_log ${remotehost}
|
||||
else
|
||||
echo "Last `prev_level` dump on this filesystem was on $PREV_DATE"
|
||||
remote_run "${remotehost}" cp "`level_log_name ${fsname} $PREV_LEVEL`" "`level_log_name temp`"
|
||||
fi
|
||||
|
||||
${DUMP_BEGIN-:} $DUMP_LEVEL $remotehost $fs $fsname
|
||||
backup_host ${remotehost} \
|
||||
"--listed=`level_log_name temp`" \
|
||||
"--label='`print_level` backup of ${fs} on ${remotehost} at ${NOW}'" \
|
||||
-C ${fs} .
|
||||
|
||||
# `rsh' doesn't exit with the exit status of the remote command. What
|
||||
# stupid lossage. TODO: think of a reliable workaround.
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of ${1} failed." 1>&2
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
flush_level_log ${remotehost} ${fsname}
|
||||
fi
|
||||
${MT_STATUS} "$TAPE_FILE"
|
||||
${DUMP_END-:} $DUMP_LEVEL $remotehost $fs $fsname
|
||||
echo "sleeping ${SLEEP_TIME} seconds"
|
||||
sleep ${SLEEP_TIME}
|
||||
shift
|
||||
done
|
||||
|
||||
# Dump any individual files requested.
|
||||
|
||||
if [ "x${BACKUP_FILES}" != "x" ] ; then
|
||||
message 1 "processing individual files"
|
||||
|
||||
date="`date`"
|
||||
|
||||
if [ $DUMP_LEVEL -eq 0 ]; then
|
||||
make_level_log $localhost
|
||||
else
|
||||
echo "Last `prev_level` dump on this filesystem was on $PREV_DATE"
|
||||
remote_run "${localhost}" cp "`level_log_name MISC $PREV_LEVEL`" "`level_log_name temp`"
|
||||
fi
|
||||
|
||||
echo "Backing up miscellaneous files at ${date}"
|
||||
|
||||
${DUMP_BEGIN-:} $DUMP_LEVEL $localhost MISC MISC
|
||||
backup_host $localhost \
|
||||
"--listed=`level_log_name temp`"\
|
||||
"--label='`print_level` backup of miscellaneous files at ${NOW}'" \
|
||||
${BACKUP_FILES}
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of miscellaneous files failed."
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
flush_level_log $localhost MISC
|
||||
fi
|
||||
${MT_STATUS} "$TAPE_FILE"
|
||||
${DUMP_END-:} $DUMP_LEVEL $localhost MISC MISC
|
||||
else
|
||||
echo "No miscellaneous files specified"
|
||||
fi
|
||||
|
||||
message 1 "final cleanup"
|
||||
|
||||
$MT_REWIND "${TAPE_FILE}"
|
||||
$MT_OFFLINE "${TAPE_FILE}"
|
||||
echo "."
|
||||
) 2>&1 | tee -a "${LOGFILE}"
|
||||
|
||||
if test "${ADMINISTRATOR}" != NONE; then
|
||||
echo "Sending the dump log to ${ADMINISTRATOR}"
|
||||
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
|
||||
fi
|
||||
|
||||
# EOF
|
||||
@@ -1,347 +0,0 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright (C) 2004, 2005, 2006 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 1, 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.
|
||||
|
||||
PROGNAME=`basename $0`
|
||||
CONFIGPATH="$SYSCONFDIR/backup"
|
||||
REMOTEBACKUPDIR="$SYSCONFDIR/tar-backup"
|
||||
CONFIGFILE=${CONFIGPATH}/backup-specs
|
||||
DIRLIST=${CONFIGPATH}/dirs
|
||||
FILELIST=${CONFIGPATH}/files
|
||||
LOGPATH=${CONFIGPATH}/log
|
||||
|
||||
# Default functions for running various magnetic tape commands
|
||||
mt_begin() {
|
||||
$MT -f "$1" retension
|
||||
}
|
||||
|
||||
mt_rewind() {
|
||||
$MT -f "$1" rewind
|
||||
}
|
||||
|
||||
mt_offline() {
|
||||
$MT -f "$1" offl
|
||||
}
|
||||
|
||||
mt_status() {
|
||||
$MT -f "$1" status
|
||||
}
|
||||
|
||||
# The main configuration file may override any of these variables
|
||||
MT_BEGIN=mt_begin
|
||||
MT_REWIND=mt_rewind
|
||||
MT_OFFLINE=mt_offline
|
||||
MT_STATUS=mt_status
|
||||
|
||||
# Insure `mail' is in PATH.
|
||||
PATH="/usr/ucb:${PATH}"
|
||||
export PATH
|
||||
# Put startdate in the subject line of mailed report, since if it happens
|
||||
# to run longer than 24 hours (as may be the case if someone forgets to put
|
||||
# in the next volume of the tape in adequate time), the backup date won't
|
||||
# appear too misleading.
|
||||
startdate="`date`"
|
||||
here="`pwd`"
|
||||
# Save local hostname
|
||||
localhost="`hostname | sed -e 's/\..*//' | tr A-Z a-z`"
|
||||
|
||||
# Produce a diagnostic output
|
||||
message() {
|
||||
if [ "$VERBOSE" != "" ]; then
|
||||
if [ $VERBOSE -ge $1 ]; then
|
||||
shift
|
||||
echo "$@" >&2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Bail out and exit.
|
||||
bailout() {
|
||||
echo "$PROGNAME: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Return current date
|
||||
now() {
|
||||
#IF_DATE_FORMAT_OK
|
||||
date +%Y-%m-%d
|
||||
#ELSE_DATE_FORMAT_OK
|
||||
LC_ALL=C date | \
|
||||
sed 's/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
|
||||
/-[0-9]$/s/\([0-9]\)$/0\1/
|
||||
/Jan/{s/Jan/01/p;q;}
|
||||
/Feb/{s/Feb/02/p;q;}
|
||||
/Mar/{s/Mar/03/p;q;}
|
||||
/Apr/{s/Apr/04/p;q;}
|
||||
/May/{s/May/05/p;q;}
|
||||
/Jun/{s/Jun/06/p;q;}
|
||||
/Jul/{s/Jul/07/p;q;}
|
||||
/Aug/{s/Aug/08/p;q;}
|
||||
/Sep/{s/Sep/09/p;q;}
|
||||
/Oct/{s/Oct/10/p;q;}
|
||||
/Nov/{s/Nov/11/p;q;}
|
||||
/Dec/{s/Dec/12/p;q;}'
|
||||
#ENDIF_DATE_FORMAT_OK
|
||||
}
|
||||
|
||||
# Bail out if we don't have root privileges.
|
||||
test_root() {
|
||||
if [ ! -w ${ROOT_FS-/} ]; then
|
||||
bailout "The backup must be run as root or else some files will fail to be dumped."
|
||||
fi
|
||||
}
|
||||
|
||||
root_fs() {
|
||||
echo "${ROOT_FS}$1" | tr -s /
|
||||
}
|
||||
|
||||
advice() {
|
||||
echo "Directory $1 is not found." >&2
|
||||
cat >&2 <<EOF
|
||||
The following directories and files are needed for the backup to function:
|
||||
|
||||
1. Directory with configuration files and file lists:
|
||||
$CONFIGPATH
|
||||
2. Directory for backup log files
|
||||
$LOGPATH
|
||||
3. Main configuration file
|
||||
$CONFIGFILE
|
||||
|
||||
Please, create these and invoke the script again.
|
||||
EOF
|
||||
}
|
||||
|
||||
init_common() {
|
||||
# Check if the necessary directories exist
|
||||
if [ ! -d $CONFIGPATH ]; then
|
||||
advice $CONFIGPATH
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d $LOGPATH ]; then
|
||||
if mkdir $LOGPATH; then
|
||||
:
|
||||
else
|
||||
advice $LOGPATH
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
|
||||
if [ ! -r $CONFIGFILE ]; then
|
||||
echo "$PROGNAME: cannot read $CONFIGFILE. Stop." >&2
|
||||
exit 1
|
||||
fi
|
||||
. $CONFIGFILE
|
||||
|
||||
# Environment sanity check
|
||||
|
||||
test_root
|
||||
|
||||
if [ x"${ADMINISTRATOR}" = x ]; then
|
||||
bailout "ADMINISTRATOR not defined"
|
||||
fi
|
||||
|
||||
[ x"$TAR" = x ] && TAR=tar
|
||||
[ x"$SLEEP_TIME" = x ] && SLEEP_TIME=60
|
||||
|
||||
if [ x$VOLNO_FILE = x ]; then
|
||||
bailout "VOLNO_FILE not specified"
|
||||
fi
|
||||
|
||||
if [ -r $DIRLIST ]; then
|
||||
BACKUP_DIRS="$BACKUP_DIRS `cat $DIRLIST`"
|
||||
fi
|
||||
if [ -r $FILELIST ]; then
|
||||
BACKUP_FILES="$BACKUP_FILES `cat $FILELIST`"
|
||||
fi
|
||||
|
||||
if [ \( x"$BACKUP_DIRS" = x \) -a \( x"$BACKUP_FILES" = x \) ]; then
|
||||
bailout "Neither BACKUP_DIRS nor BACKUP_FILES specified"
|
||||
fi
|
||||
if [ -z "$RSH" ]; then
|
||||
RSH=rsh
|
||||
MT_RSH_OPTION=
|
||||
else
|
||||
MT_RSH_OPTION="--rsh-command=$RSH"
|
||||
fi
|
||||
if [ -z "$TAPE_FILE" ]; then
|
||||
TAPE_FILE=/dev/tape
|
||||
fi
|
||||
|
||||
# If TAPE_FILE is a remote device, update mt invocation accordingly
|
||||
: ${MT:=mt}
|
||||
case $TAPE_FILE in
|
||||
*:*) MT="$MT $MT_RSH_OPTION";;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
POSIXLY_CORRECT=1
|
||||
export POSIXLY_CORRECT
|
||||
}
|
||||
|
||||
init_backup() {
|
||||
init_common
|
||||
TAR_PART1="${TAR} -c --format=gnu --multi-volume --one-file-system --sparse --volno-file=${VOLNO_FILE}"
|
||||
if [ "x$XLIST" != x ]; then
|
||||
TAR_PART1="${TAR_PART1} \`test -r $REMOTEBACKUPDIR/$XLIST && echo \"--exclude-from $REMOTEBACKUPDIR/$XLIST\"\`"
|
||||
fi
|
||||
if [ "$RSH_COMMAND" != "" ]; then
|
||||
TAR_PART1="${TAR_PART1} --rsh-command=$RSH_COMMAND"
|
||||
fi
|
||||
if [ x$BLOCKING != x ]; then
|
||||
TAR_PART1="${TAR_PART1} --blocking=${BLOCKING}"
|
||||
fi
|
||||
|
||||
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
|
||||
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
|
||||
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
|
||||
fi
|
||||
# Set logfile name
|
||||
# Logfile name should be in the form ``log-1993-03-18-level-0''
|
||||
# They go in the directory `@sysconfdir@/log'.
|
||||
# i.e. year-month-date. This format is useful for sorting by name, since
|
||||
# logfiles are intentionally kept online for future reference.
|
||||
LOGFILE="${LOGPATH}/log-`now`-level-${DUMP_LEVEL}"
|
||||
}
|
||||
|
||||
init_restore() {
|
||||
init_common
|
||||
# FIXME: Replace --list with --extract
|
||||
TAR_PART1="${TAR} --extract --multi-volume"
|
||||
if [ "$RSH_COMMAND" != "" ]; then
|
||||
TAR_PART1="${TAR_PART1} --rsh-command=$RSH_COMMAND"
|
||||
fi
|
||||
if [ x$BLOCKING != x ]; then
|
||||
TAR_PART1="${TAR_PART1} --blocking=${BLOCKING}"
|
||||
fi
|
||||
|
||||
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
|
||||
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
|
||||
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
|
||||
fi
|
||||
LOGFILE="${LOGPATH}/restore-`now`"
|
||||
}
|
||||
|
||||
wait_time() {
|
||||
if [ "${1}" != "now" ]; then
|
||||
if [ "${1}x" != "x" ]; then
|
||||
spec="${1}"
|
||||
else
|
||||
spec="${BACKUP_HOUR}"
|
||||
fi
|
||||
|
||||
pausetime="`date | awk -v spec=\"${spec}\" '
|
||||
BEGIN {
|
||||
split(spec, time, ":")
|
||||
}
|
||||
{
|
||||
split($4, now, ":")
|
||||
diff = 3600 * (time[1] - now[1]) + 60 * (time[2] - now[2]);
|
||||
if (diff < 0)
|
||||
diff += 3600 * 24
|
||||
print diff
|
||||
}'`"
|
||||
clear
|
||||
echo "${SLEEP_MESSAGE}"
|
||||
sleep "${pausetime}"
|
||||
fi
|
||||
}
|
||||
|
||||
level_log_name() {
|
||||
echo "$REMOTEBACKUPDIR/${1}.level-${2-$DUMP_LEVEL}"
|
||||
}
|
||||
|
||||
# Prepare a temporary level logfile
|
||||
# usage: make_level_log HOSTNAME
|
||||
make_level_log() {
|
||||
if [ "z${localhost}" != "z$1" ] ; then
|
||||
$RSH "$1" mkdir $REMOTEBACKUPDIR > /dev/null 2>&1
|
||||
$RSH "$1" rm -f `level_log_name temp`
|
||||
else
|
||||
mkdir $REMOTEBACKUPDIR > /dev/null 2>&1
|
||||
rm -f `level_log_name temp`
|
||||
fi
|
||||
}
|
||||
|
||||
# Rename temporary log
|
||||
# usage: flush_level_log HOSTNAME FSNAME
|
||||
flush_level_log() {
|
||||
message 10 "RENAME: `level_log_name temp` --> `level_log_name $2`"
|
||||
if [ "z${localhost}" != "z$1" ] ; then
|
||||
$RSH "$1" mv -f `level_log_name temp` "`level_log_name $2`"
|
||||
else
|
||||
mv -f `level_log_name temp` "`level_log_name $2`"
|
||||
fi
|
||||
}
|
||||
|
||||
# Return the timestamp of the last backup.
|
||||
# usage: get_dump_time LEVEL
|
||||
get_dump_time() {
|
||||
ls -r ${LOGPATH}/log-*-level-$1 \
|
||||
| head -n 1 \
|
||||
| sed "s,.*log-\(.*\)-level-$1,\1,"
|
||||
}
|
||||
|
||||
# Do actual backup on a host
|
||||
# usage: backup_host HOSTNAME [TAR_ARGUMENTS]
|
||||
backup_host() {
|
||||
message 10 "ARGS: $@"
|
||||
rhost=$1
|
||||
shift
|
||||
if [ "z${localhost}" != "z$rhost" ] ; then
|
||||
$RSH "$rhost" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" $@
|
||||
else
|
||||
# Using `sh -c exec' causes nested quoting and shell substitution
|
||||
# to be handled here in the same way rsh handles it.
|
||||
CMD="exec ${TAR_PART1} -f \"${TAPE_FILE}\" $@"
|
||||
message 10 "CMD: $CMD"
|
||||
sh -c "$CMD"
|
||||
message 10 "RC: $?"
|
||||
fi
|
||||
}
|
||||
|
||||
print_level() {
|
||||
if [ ${1-$DUMP_LEVEL} -eq 0 ]; then
|
||||
echo "Full"
|
||||
else
|
||||
echo "Level ${1-$DUMP_LEVEL}"
|
||||
fi
|
||||
}
|
||||
|
||||
prev_level() {
|
||||
print_level `expr $DUMP_LEVEL - 1` | tr A-Z a-z
|
||||
}
|
||||
|
||||
remote_run() {
|
||||
rhost=$1
|
||||
shift
|
||||
message 10 "REMOTE $rhost: $@"
|
||||
if [ "x$rhost" != "x${localhost}" ] ; then
|
||||
$RSH "${rhost}" "$@"
|
||||
else
|
||||
$*
|
||||
fi
|
||||
}
|
||||
|
||||
license() {
|
||||
cat - <<EOF
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
EOF
|
||||
}
|
||||
34
scripts/dump-remind.in → scripts/dump-remind
Normal file → Executable file
34
scripts/dump-remind.in → scripts/dump-remind
Normal file → Executable file
@@ -13,12 +13,16 @@
|
||||
PATH="/usr/lib:/usr/local/gnubin:${PATH}"
|
||||
export PATH
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
. ${LIBPATH-@libexecdir@}/backup.sh
|
||||
# Get definition of TAPE_FILE, VOLNO_FILE, and so on.
|
||||
. /home/gd2/dump/backup-specs
|
||||
|
||||
MT_REWIND
|
||||
MT_OFFLINE
|
||||
mt -f "${TAPE_FILE}" rewind
|
||||
mt -f "${TAPE_FILE}" offl
|
||||
|
||||
volno="`cat \"${VOLNO_FILE}\" 2> /dev/null`"
|
||||
if [ $? -ne 0 ]; then
|
||||
volno=0
|
||||
fi
|
||||
|
||||
# Get a list of people to whom to mail a request for changing the tape.
|
||||
# This egregious nightmare parses the output from GNU finger which shows
|
||||
@@ -66,30 +70,30 @@ sendmail -oi -t << __EOF__
|
||||
From: `basename $0` (backup tape-changing reminder)
|
||||
To: ${recipients}
|
||||
Cc: ${ADMINISTRATOR}
|
||||
Subject: Backup needs new tape for volume ${TAR_VOLUME}
|
||||
Subject: Backup needs new tape for volume ${volno}
|
||||
Reply-To: ${ADMINISTRATOR}
|
||||
|
||||
This is an automated report from the backup script running on
|
||||
`hostname`.
|
||||
|
||||
Volume ${TAR_VOLUME} of the backup needs to be put in the tape drive.
|
||||
Usually whoever prepared the backup leaves labeled tapes on top of the
|
||||
drive itself. If there aren't any more, information about where to find
|
||||
tapes and how to label them are posted on the wall by apple-gunkies
|
||||
(unhelpfully obscured by a bookshelf). An online copy (which is probably
|
||||
more up-to-date) can also be found in ~friedman/etc/fsf/backup.how.
|
||||
Volume ${volno} of the backup needs to be put in the tape drive. Usually
|
||||
whoever prepared the backup leaves labeled tapes on top of the drive
|
||||
itself. If there aren't any more, information about where to find tapes
|
||||
and how to label them are posted on the wall by apple-gunkies (unhelpfully
|
||||
obscured by a bookshelf). An online copy (which is probably more
|
||||
up-to-date) can also be found in ~friedman/etc/fsf/backup.how.
|
||||
__EOF__
|
||||
|
||||
|
||||
echo "Please put volume ${TAR_VOLUME} in tape drive and press RETURN"
|
||||
echo "Please put volume ${volno} in tape drive and press RETURN"
|
||||
read input
|
||||
echo "Writing volume ${TAR_VOLUME}..."
|
||||
echo "Writing volume ${volno}..."
|
||||
|
||||
sendmail -oi -t << __EOF__
|
||||
From: `basename $0` (backup tape-changing reminder)
|
||||
To: ${recipients}
|
||||
Cc: ${ADMINISTRATOR}
|
||||
Subject: Volume ${TAR_VOLUME} for backup has been added
|
||||
Subject: Volume ${volno} for backup has been added
|
||||
Reply-To: ${ADMINISTRATOR}
|
||||
|
||||
This is an automated report from the backup script running on
|
||||
200
scripts/level-0
Normal file
200
scripts/level-0
Normal file
@@ -0,0 +1,200 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run this script as root on the machine that has the tape drive, to make a
|
||||
# full (level-0) dump.
|
||||
#
|
||||
# If you give `now' as an argument, the dump is done immediately.
|
||||
# Otherwise, it waits until 1am, or until the hour given as argument.
|
||||
# Specify the hour as a number from 0 to 23.
|
||||
#
|
||||
# You must edit the file `backup-specs' to set the parameters for your site.
|
||||
|
||||
# Useful for backup-specs, in case things have to be done slightly
|
||||
# differently for different dump levels.
|
||||
DUMP_LEVEL=0
|
||||
|
||||
# Insure `mail' is in PATH.
|
||||
PATH="/usr/ucb:${PATH}"
|
||||
export PATH
|
||||
|
||||
# This is not the most reliable test in the world. The following might be
|
||||
# more predictable:
|
||||
#
|
||||
# whoami="`whoami`"
|
||||
# euid="`sed -ne '/^'\"${whoami}\"':/{s/^[^:]*:[^:]*://;s/:.*//p;q;}' /etc/passwd`"
|
||||
# if [ "${euid}" != 0 ]; then ...
|
||||
#
|
||||
if [ ! -w / ]; then
|
||||
echo "The backup must be run as root or else some files will fail to be dumped."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
|
||||
. ./backup-specs
|
||||
|
||||
# Maybe sleep until around specified or default hour.
|
||||
if [ "${1}" != "now" ]; then
|
||||
if [ "${1}x" != "x" ]; then
|
||||
spec="${1}"
|
||||
else
|
||||
spec="${BACKUP_HOUR}"
|
||||
fi
|
||||
|
||||
pausetime="`date | awk '
|
||||
{
|
||||
hr = substr($4, 1, 2);
|
||||
mn = substr($4, 4, 2);
|
||||
if((hr + 0) < (spec + 0))
|
||||
print 3600 * (spec - hr) - 60 * mn;
|
||||
else
|
||||
print 3600 * (spec + (24 - hr)) - 60 * mn;
|
||||
}' spec=\"${spec}\"`"
|
||||
|
||||
clear
|
||||
echo "${SLEEP_MESSAGE}"
|
||||
sleep "${pausetime}"
|
||||
fi
|
||||
|
||||
# start doing things
|
||||
|
||||
# Put startdate in the subject line of mailed report, since if it happens
|
||||
# to run longer than 24 hours (as may be the case if someone forgets to put
|
||||
# in the next volume of the tape in adequate time), the backup date won't
|
||||
# appear too misleading.
|
||||
startdate="`date`"
|
||||
|
||||
here="`pwd`"
|
||||
|
||||
# Logfile name should be in the form ``log-1993-03-18-level-0''
|
||||
# They go in the subdirectory `log' of the current directory.
|
||||
# i.e. year-month-date. This format is useful for sorting by name, since
|
||||
# logfiles are intentionally kept online for future reference.
|
||||
LOGFILE="log/log-`date | sed -ne '
|
||||
s/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
|
||||
/-[0-9]$/s/\([0-9]\)$/0\1/
|
||||
/Jan/{s/Jan/01/p;q;}
|
||||
/Feb/{s/Feb/02/p;q;}
|
||||
/Mar/{s/Mar/03/p;q;}
|
||||
/Apr/{s/Apr/04/p;q;}
|
||||
/May/{s/May/05/p;q;}
|
||||
/Jun/{s/Jun/06/p;q;}
|
||||
/Jul/{s/Jul/07/p;q;}
|
||||
/Aug/{s/Aug/08/p;q;}
|
||||
/Sep/{s/Sep/09/p;q;}
|
||||
/Oct/{s/Oct/10/p;q;}
|
||||
/Nov/{s/Nov/11/p;q;}
|
||||
/Dec/{s/Dec/12/p;q;}'`-level-${DUMP_LEVEL}"
|
||||
|
||||
localhost="`hostname | sed -e 's/\..*//'`"
|
||||
|
||||
TAR_PART1="${TAR} -c --multi-volume --one-file-system --blocking=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
|
||||
|
||||
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
|
||||
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
|
||||
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
|
||||
fi
|
||||
|
||||
# Make sure the log file did not already exist. Create it.
|
||||
|
||||
if [ -f "${LOGFILE}" ] ; then
|
||||
echo "Log file ${LOGFILE} already exists." 1>&2
|
||||
exit 1
|
||||
else
|
||||
touch "${LOGFILE}"
|
||||
fi
|
||||
|
||||
# Most everything below here is run in a subshell for which all output is
|
||||
# piped through `tee' to the logfile. Doing this, instead of having
|
||||
# multiple pipelines all over the place, is cleaner and allows access to
|
||||
# the exit value from various commands more easily.
|
||||
(
|
||||
# Caveat: Some version of `mt' require `-t', not `-f'.
|
||||
mt -f "${TAPE_FILE}" rewind
|
||||
rm -f "${VOLNO_FILE}"
|
||||
|
||||
set - ${BACKUP_DIRS}
|
||||
while [ $# -ne 0 ] ; do
|
||||
date="`date`"
|
||||
remotehost="`echo \"${1}\" | sed -e 's/:.*$//'`"
|
||||
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
|
||||
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
|
||||
|
||||
# This filename must be absolute; it is opened on the machine that runs tar.
|
||||
TAR_PART2="--listed=/etc/tar-backup/temp.level-0"
|
||||
TAR_PART3="--label='Full backup of ${fs} on ${remotehost} at ${date}' -C ${fs} ."
|
||||
|
||||
echo "Backing up ${1} at ${date}"
|
||||
|
||||
# Actually back things up.
|
||||
|
||||
if [ "z${localhost}" != "z${remotehost}" ] ; then
|
||||
rsh "${remotehost}" mkdir /etc/tar-backup > /dev/null 2>&1
|
||||
rsh "${remotehost}" rm -f /etc/tar-backup/temp.level-0
|
||||
rsh "${remotehost}" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" ${TAR_PART2} ${TAR_PART3}
|
||||
else
|
||||
mkdir /etc/tar-backup > /dev/null 2>&1
|
||||
rm -f /etc/tar-backup/temp.level-0
|
||||
# Using `sh -c exec' causes nested quoting and shell substitution
|
||||
# to be handled here in the same way rsh handles it.
|
||||
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3}"
|
||||
fi
|
||||
|
||||
# `rsh' doesn't exit with the exit status of the remote command. What
|
||||
# stupid lossage. TODO: think of a reliable workaround.
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of ${1} failed." 1>&2
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
if [ "z${localhost}" != "z${remotehost}" ] ; then
|
||||
rsh "${remotehost}" mv -f /etc/tar-backup/temp.level-0 "/etc/tar-backup/${fsname}.level-0"
|
||||
else
|
||||
mv -f /etc/tar-backup/temp.level-0 "/etc/tar-backup/${fsname}.level-0"
|
||||
fi
|
||||
fi
|
||||
${TAPE_STATUS}
|
||||
sleep 60
|
||||
shift
|
||||
done
|
||||
|
||||
# Dump any individual files requested.
|
||||
|
||||
if [ "x${BACKUP_FILES}" != "x" ] ; then
|
||||
date="`date`"
|
||||
|
||||
TAR_PART2="--listed=/etc/tar-backup/temp.level-0"
|
||||
TAR_PART3="--label='Full backup of miscellaneous files at ${date}'"
|
||||
|
||||
mkdir /etc/tar-backup > /dev/null 2>&1
|
||||
rm -f /etc/tar-backup/temp.level-0
|
||||
|
||||
echo "Backing up miscellaneous files at ${date}"
|
||||
|
||||
# Using `sh -c exec' causes nested quoting and shell substitution
|
||||
# to be handled here in the same way rsh handles it.
|
||||
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3} ${BACKUP_FILES}"
|
||||
|
||||
# `rsh' doesn't exit with the exit status of the remote command. What
|
||||
# lossage. TODO: think of a reliable workaround.
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of miscellaneous files failed."
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
mv -f /etc/tar-backup/temp.level-0 /etc/tar-backup/misc.level-0
|
||||
fi
|
||||
${TAPE_STATUS}
|
||||
else
|
||||
echo "No miscellaneous files specified"
|
||||
fi
|
||||
|
||||
# Caveat: some versions of `mt' use `-t' instead of `-f'.
|
||||
mt -f "${TAPE_FILE}" rewind
|
||||
mt -f "${TAPE_FILE}" offl
|
||||
|
||||
) 2>&1 | tee -a "${LOGFILE}"
|
||||
|
||||
echo "Sending the dump log to ${ADMINISTRATOR}"
|
||||
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
|
||||
|
||||
# eof
|
||||
203
scripts/level-1
Normal file
203
scripts/level-1
Normal file
@@ -0,0 +1,203 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run this script as root on the machine that has the tape drive, to make a
|
||||
# level-1 dump containing all files changed since the last full dump.
|
||||
#
|
||||
# If you give `now' as an argument, the dump is done immediately.
|
||||
# Otherwise, it waits until 1am.
|
||||
#
|
||||
# You must edit the file `backup-specs' to set the parameters for your site.
|
||||
|
||||
# Useful for backup-specs, in case things have to be done slightly
|
||||
# differently for different dump levels.
|
||||
DUMP_LEVEL=1
|
||||
|
||||
# Insure `mail' is in PATH.
|
||||
PATH="/usr/ucb:${PATH}"
|
||||
export PATH
|
||||
|
||||
# This is not the most reliable test in the world. The following might be
|
||||
# more predictable:
|
||||
#
|
||||
# whoami="`whoami`"
|
||||
# euid="`sed -ne '/^'\"${whoami}\"':/{s/^[^:]*:[^:]*://;s/:.*//p;q;}' /etc/passwd`"
|
||||
# if [ "${euid}" != 0 ]; then ...
|
||||
#
|
||||
if [ ! -w / ]; then
|
||||
echo "The backup must be run as root or else some files will fail to be dumped."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
|
||||
. ./backup-specs
|
||||
|
||||
# Maybe sleep until around specified or default hour.
|
||||
if [ "z${1}" != "znow" ]; then
|
||||
if [ "${1}x" != "x" ]; then
|
||||
spec="${1}"
|
||||
else
|
||||
spec="${BACKUP_HOUR}"
|
||||
fi
|
||||
|
||||
pausetime="`date | awk '
|
||||
{
|
||||
hr = substr($4, 1, 2);
|
||||
mn = substr($4, 4, 2);
|
||||
if((hr + 0) < (spec + 0))
|
||||
print 3600 * (spec - hr) - 60 * mn;
|
||||
else
|
||||
print 3600 * (spec + (24 - hr)) - 60 * mn;
|
||||
}' spec=\"${spec}\"`"
|
||||
|
||||
clear
|
||||
echo "${SLEEP_MESSAGE}"
|
||||
sleep "${pausetime}"
|
||||
fi
|
||||
|
||||
# start doing things
|
||||
|
||||
# Put startdate in the subject line of mailed report, since if it happens
|
||||
# to run longer than 24 hours (as may be the case if someone forgets to put
|
||||
# in the next volume of the tape in adequate time), the backup date won't
|
||||
# appear too misleading.
|
||||
startdate="`date`"
|
||||
|
||||
here="`pwd`"
|
||||
|
||||
# Logfile name should be in the form ``log-1993-03-18-level-1''
|
||||
# They go in the subdirectory `log' of the current directory.
|
||||
# i.e. year-month-date. This format is useful for sorting by name, since
|
||||
# logfiles are intentionally kept online for future reference.
|
||||
LOGFILE="log/log-`date | sed -ne '
|
||||
s/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
|
||||
/-[0-9]$/s/\([0-9]\)$/0\1/
|
||||
/Jan/{s/Jan/01/p;q;}
|
||||
/Feb/{s/Feb/02/p;q;}
|
||||
/Mar/{s/Mar/03/p;q;}
|
||||
/Apr/{s/Apr/04/p;q;}
|
||||
/May/{s/May/05/p;q;}
|
||||
/Jun/{s/Jun/06/p;q;}
|
||||
/Jul/{s/Jul/07/p;q;}
|
||||
/Aug/{s/Aug/08/p;q;}
|
||||
/Sep/{s/Sep/09/p;q;}
|
||||
/Oct/{s/Oct/10/p;q;}
|
||||
/Nov/{s/Nov/11/p;q;}
|
||||
/Dec/{s/Dec/12/p;q;}'`-level-${DUMP_LEVEL}"
|
||||
|
||||
localhost="`hostname | sed -e 's/\..*//'`"
|
||||
|
||||
TAR_PART1="${TAR} -c --multi-volume --one-file-system --blocking=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
|
||||
|
||||
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
|
||||
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
|
||||
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
|
||||
fi
|
||||
|
||||
# Make sure the log file did not already exist. Create it.
|
||||
|
||||
if [ -f "${LOGFILE}" ] ; then
|
||||
echo "Log file ${LOGFILE} already exists." 1>&2
|
||||
exit 1
|
||||
else
|
||||
touch "${LOGFILE}"
|
||||
fi
|
||||
|
||||
# Most everything below here is run in a subshell for which all output is
|
||||
# piped through `tee' to the logfile. Doing this, instead of having
|
||||
# multiple pipelines all over the place, is cleaner and allows access to
|
||||
# the exit value from various commands more easily.
|
||||
(
|
||||
# Caveat: Some version of `mt' require `-t', not `-f'.
|
||||
mt -f "${TAPE_FILE}" rewind
|
||||
rm -f "${VOLNO_FILE}"
|
||||
|
||||
set - ${BACKUP_DIRS}
|
||||
while [ $# -ne 0 ] ; do
|
||||
date="`date`"
|
||||
remotehost="`echo \"${1}\" | sed -e 's/:.*$//'`"
|
||||
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
|
||||
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
|
||||
|
||||
# This filename must be absolute; it is opened on the machine that runs tar.
|
||||
TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
|
||||
TAR_PART3="--label='level 1 backup of ${fs} on ${remotehost} at ${date}' -C ${fs} ."
|
||||
|
||||
echo "Backing up ${1} at ${date}"
|
||||
echo "Last full dump on this filesystem:"
|
||||
|
||||
if [ "z${remotehost}" != "z${localhost}" ] ; then
|
||||
rsh "${remotehost}" "ls -l /etc/tar-backup/${fsname}.level-0; \
|
||||
cp /etc/tar-backup/${fsname}.level-0 /etc/tar-backup/temp.level-1"
|
||||
else
|
||||
ls -l "/etc/tar-backup/${fsname}.level-0"
|
||||
cp "/etc/tar-backup/${fsname}.level-0" /etc/tar-backup/temp.level-1
|
||||
fi
|
||||
|
||||
# Actually back things up.
|
||||
|
||||
if [ "z${remotehost}" != "z${localhost}" ] ; then
|
||||
rsh "${remotehost}" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" ${TAR_PART2} ${TAR_PART3}
|
||||
else
|
||||
# Using `sh -c exec' causes nested quoting and shell substitution
|
||||
# to be handled here in the same way rsh handles it.
|
||||
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3}"
|
||||
fi
|
||||
|
||||
# `rsh' doesn't exit with the exit status of the remote command. What
|
||||
# stupid lossage. TODO: think of a reliable workaround.
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of ${1} failed."
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
if [ "z${localhost}" != "z${remotehost}" ] ; then
|
||||
rsh "${remotehost}" mv -f /etc/tar-backup/temp.level-1 "/etc/tar-backup/${fsname}.level-1"
|
||||
else
|
||||
mv -f /etc/tar-backup/temp.level-1 "/etc/tar-backup/${fsname}.level-1"
|
||||
fi
|
||||
fi
|
||||
${TAPE_STATUS}
|
||||
sleep 60
|
||||
shift
|
||||
done
|
||||
|
||||
# Dump any individual files requested.
|
||||
|
||||
if [ "x${BACKUP_FILES}" != "x" ] ; then
|
||||
date="`date`"
|
||||
TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
|
||||
TAR_PART3="--label='Incremental backup of miscellaneous files at ${date}'"
|
||||
|
||||
echo "Backing up miscellaneous files at ${date}"
|
||||
echo "Last full dump of these files:"
|
||||
ls -l /etc/tar-backup/misc.level-0
|
||||
|
||||
rm -f /etc/tar-backup/temp.level-1
|
||||
cp /etc/tar-backup/misc.level-0 /etc/tar-backup/temp.level-1
|
||||
|
||||
# Using `sh -c exec' causes nested quoting and shell substitution
|
||||
# to be handled here in the same way rsh handles it.
|
||||
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3} ${BACKUP_FILES}"
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of miscellaneous files failed." 1>&2
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/misc.level-1
|
||||
fi
|
||||
${TAPE_STATUS}
|
||||
else
|
||||
echo "No miscellaneous files specified"
|
||||
fi
|
||||
|
||||
# Caveat: some versions of `mt' use `-t' instead of `-f'.
|
||||
mt -f "${TAPE_FILE}" rewind
|
||||
mt -f "${TAPE_FILE}" offl
|
||||
|
||||
) 2>&1 | tee -a "${LOGFILE}"
|
||||
|
||||
echo "Sending the dump log to ${ADMINISTRATOR}"
|
||||
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
|
||||
|
||||
# eof
|
||||
@@ -1,229 +0,0 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright (C) 2004, 2006 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 1, 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.
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
. ${LIBDIR-@libexecdir@}/backup.sh
|
||||
|
||||
usage() {
|
||||
cat - <<EOF
|
||||
usage: $PROGNAME [OPTIONS] [PATTERN [PATTERN...]]
|
||||
Options are:
|
||||
|
||||
-a, --all Restore all filesystems.
|
||||
-l, --level=LEVEL Start restoring from the given backup LEVEL
|
||||
(default $DUMP_LEVEL).
|
||||
-v, --verbose[=LEVEL] Set verbosity level. Default 100.
|
||||
|
||||
Informational options:
|
||||
-h, --help Display this help message.
|
||||
-V, --version Display program version.
|
||||
|
||||
Send bug reports to @PACKAGE_BUGREPORT@.
|
||||
EOF
|
||||
}
|
||||
|
||||
unset PATTERN
|
||||
DUMP_LEVEL=0
|
||||
CMDLINE="$0 $@"
|
||||
|
||||
for opt
|
||||
do
|
||||
if [ -z "$prev" ]; then
|
||||
option=$opt
|
||||
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
|
||||
else
|
||||
option="${prev}=$opt"
|
||||
prev=""
|
||||
optarg=$opt
|
||||
fi
|
||||
case $option in
|
||||
-a|--a|--al|--all)
|
||||
RESTORE_ALL=1
|
||||
;;
|
||||
--l=*|--le=*|--lev=*|--leve=*|--level=*)
|
||||
DUMP_LEVEL=$optarg
|
||||
;;
|
||||
-l|--l|--le|--lev|--leve|--level)
|
||||
prev=$option
|
||||
;;
|
||||
--verb=*|--verbo=*|--verbos=*|--verbose=*)
|
||||
VERBOSE=$optarg
|
||||
;;
|
||||
-v|--verb|--verbo|--verbos|--verbose)
|
||||
VERBOSE=100
|
||||
;;
|
||||
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
|
||||
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "restore (@PACKAGE_NAME@) @VERSION@"
|
||||
license
|
||||
exit;;
|
||||
-h|--h|--he|--hel|--help)
|
||||
usage
|
||||
exit;;
|
||||
-*) bailout "Unknown option $opt. Try $PROGNAME --help for more info.";;
|
||||
*) if [ -z "$PATTERN" ]; then
|
||||
PATTERN=$opt
|
||||
else
|
||||
PATTERN="$PATTERN|$opt"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$RESTORE_ALL" ]; then
|
||||
if [ -z "$PATTERN" ]; then
|
||||
usage
|
||||
exit;
|
||||
fi
|
||||
fi
|
||||
|
||||
init_restore
|
||||
cat > $LOGFILE <<EOF
|
||||
This file contains any messages produced by $PROGNAME.
|
||||
|
||||
It was created by GNU $PROGNAME, from @PACKAGE@ (@VERSION@).
|
||||
Invocation command line was
|
||||
|
||||
\$ $CMDLINE
|
||||
|
||||
EOF
|
||||
|
||||
restore_fs()
|
||||
{
|
||||
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
|
||||
fs=`root_fs $fs`
|
||||
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
|
||||
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
|
||||
if [ -z "$remotehost" ]; then
|
||||
remotehost=$localhost
|
||||
fi
|
||||
message 10 "fs=$fs"
|
||||
message 10 "fsname=$fsname"
|
||||
message 10 "remotehost=$remotehost"
|
||||
|
||||
LOGPAT="`level_log_name ${fsname} '[0-9]'`"
|
||||
PREFIX="`level_log_name ${fsname} ''`"
|
||||
message 10 LOGPAT=$LOGPAT
|
||||
message 10 PREFIX=$PREFIX
|
||||
LEVELS=`remote_run "${remotehost}" ls $LOGPAT |
|
||||
sed "s,$PREFIX,," | sort -n`
|
||||
message 10 "LEVELS=$LEVELS"
|
||||
|
||||
echo "Starting restore of ${1} at level $DUMP_LEVEL."
|
||||
for level in $LEVELS
|
||||
do
|
||||
if [ $level -lt $DUMP_LEVEL ]; then
|
||||
message 10 "Skipping level $level"
|
||||
continue;
|
||||
fi
|
||||
message 10 "Restoring level $level"
|
||||
|
||||
DATE=`get_dump_time $level`
|
||||
FILE="`level_log_name ${fsname} ${level}`"
|
||||
message 10 "FILE=$FILE"
|
||||
|
||||
LABEL="`print_level $level` backup of ${fs} on ${remotehost} at ${DATE}"
|
||||
${RESTORE_BEGIN-:} $level $remotehost $fs $fsname
|
||||
backup_host ${remotehost} \
|
||||
"--listed=\"$FILE\"" \
|
||||
"--label=\"$LABEL\"" \
|
||||
-C $fs
|
||||
${RESTORE_END-:} $level $remotehost $fs $fsname
|
||||
done
|
||||
}
|
||||
|
||||
restore_files()
|
||||
{
|
||||
LOGPAT="`level_log_name MISC '[0-9]'`"
|
||||
PREFIX="`level_log_name MISC ''`"
|
||||
message 10 LOGPAT=$LOGPAT
|
||||
message 10 PREFIX=$PREFIX
|
||||
LEVELS=`remote_run "${localhost}" ls $LOGPAT | sed "s,$PREFIX,," | sort -n`
|
||||
message 10 "LEVELS=$LEVELS"
|
||||
|
||||
echo "Starting restore of miscellaneous files at level $DUMP_LEVEL."
|
||||
for level in $LEVELS
|
||||
do
|
||||
if [ $level -lt $DUMP_LEVEL ]; then
|
||||
message 10 "Skipping level $level"
|
||||
continue;
|
||||
fi
|
||||
message 10 "Restoring level $level"
|
||||
|
||||
DATE=`get_dump_time $level`
|
||||
FILE="`level_log_name MISC ${level}`"
|
||||
message 10 "FILE=$FILE"
|
||||
|
||||
LABEL="`print_level $level` backup of miscellaneous files at ${DATE}"
|
||||
${RESTORE_BEGIN-:} $level $localhost MISC MISC
|
||||
backup_host ${localhost} \
|
||||
"--listed=\"$FILE\"" \
|
||||
"--label=\"$LABEL\"" \
|
||||
-C ${ROOT_FS-/} $@
|
||||
${RESTORE_END-:} $level $localhost MISC MISC
|
||||
done
|
||||
}
|
||||
|
||||
# Operation Overwiew:
|
||||
#
|
||||
# 1. Determine the time of the last backup
|
||||
# 2. Create list of incremental listings to process
|
||||
# 3. For each filesystem:
|
||||
# 3.1. Start at the requested dump level (default 0) and proceed up to
|
||||
# the last available level:
|
||||
# 3.1.1 Deduce the volume label
|
||||
# 3.1.2. Invoke [rsh] tar --listed=FILE --label=LABEL [opts] -xf $TAPE_FILE
|
||||
# 4. End
|
||||
|
||||
(message 1 "Preparing for restore"
|
||||
|
||||
message 1 "processing backup directories"
|
||||
|
||||
for dir in ${BACKUP_DIRS}
|
||||
do
|
||||
message 1 "Processing $dir"
|
||||
case $dir in
|
||||
${PATTERN-*}) restore_fs $dir;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "x${BACKUP_FILES}" != "x" ] ; then
|
||||
message 1 "processing miscellaneous files"
|
||||
if [ -z "$PATTERN" ]; then
|
||||
restore_files
|
||||
else
|
||||
RESTORE_FILES=""
|
||||
for file in ${BACKUP_FILES}
|
||||
do
|
||||
rel_file=`expr $file : '/\(.*\)'`
|
||||
case $file in
|
||||
$PATTERN) if [ -z "$RESTORE_FILES" ]; then
|
||||
RESTORE_FILES="$rel_file"
|
||||
else
|
||||
RESTORE_FILES="$RESTORE_FILES $rel_file"
|
||||
fi;;
|
||||
esac
|
||||
done
|
||||
[ -z "$RESTORE_FILES" ] || restore_files $RESTORE_FILES
|
||||
fi
|
||||
|
||||
fi) 2>&1 | tee -a "${LOGFILE}"
|
||||
|
||||
# EOF
|
||||
@@ -1,42 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Usage: tarcat volume1 volume2 ...
|
||||
# concatenates a GNU tar multi-volume archive into a single tar archive.
|
||||
# Author: Bruno Haible <bruno@clisp.org>, Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
# dump_type FILE [N]
|
||||
# Print type character from block N (default 0) of tar archive FILE
|
||||
dump_type() {
|
||||
dd if="$1" skip=${2:-0} bs=512 count=1 2>/dev/null |
|
||||
tr '\0' ' ' |
|
||||
cut -c157
|
||||
}
|
||||
|
||||
case `dump_type "$1"` in
|
||||
[gx]) PAX=1;;
|
||||
esac
|
||||
|
||||
cat "$1"
|
||||
shift
|
||||
for f
|
||||
do
|
||||
SKIP=0
|
||||
T=`dump_type "$f"`
|
||||
if [ -n "$PAX" ]; then
|
||||
if [ "$T" = "g" ]; then
|
||||
# Global extended header.... 2 blocks
|
||||
# Extended header........... 2 blocks
|
||||
# Ustar header.............. 1 block
|
||||
# FIXME: This calculation is will fail for very long file names.
|
||||
SKIP=5
|
||||
fi
|
||||
else
|
||||
if [ "$T" = "V" ]; then
|
||||
T=`dump_type "$f" 1`
|
||||
fi
|
||||
if [ "$T" = "M" ]; then
|
||||
SKIP=$(($SKIP + 1))
|
||||
fi
|
||||
fi
|
||||
dd skip=$SKIP if="$f"
|
||||
done
|
||||
|
||||
42
scripts/weekly.new
Executable file
42
scripts/weekly.new
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
# start doing things
|
||||
TOBACKUP="albert:/"
|
||||
|
||||
HOST=`hostname | sed 's/\..*//'`
|
||||
TAPEFILE=/dev/rfd0a
|
||||
LOGFILE=tar-out
|
||||
BLOCKING=20
|
||||
TAR_PART1="/usr/local/bin/tar clbfVM $BLOCKING"
|
||||
|
||||
rm -f $LOGFILE
|
||||
|
||||
mt -f $TAPEFILE rewind
|
||||
|
||||
host=`echo $TOBACKUP | sed 's/:.*$//'`;
|
||||
fs=`echo $TOBACKUP | sed 's/^.*://'`;
|
||||
date=`date`;
|
||||
fsname=`echo $TOBACKUP | sed 's/\//:/g'`
|
||||
|
||||
TAR_PART2="'Weekly backup of $fs on $host at $date' -C $fs ."
|
||||
echo Backing up $TOBACKUP at $date | tee -a $LOGFILE
|
||||
|
||||
# Actually back things up.
|
||||
|
||||
if [ $HOST != $host ] ; then
|
||||
rsh $host $TAR_PART1 $HOST:$TAPEFILE $TAR_PART2
|
||||
else
|
||||
sh -c "exec $TAR_PART1 $TAPEFILE $TAR_PART2"
|
||||
fi
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo Backup of $TOBACKUP failed. | tee -a $LOGFILE
|
||||
echo mts at time of failure | tee -a $LOGFILE
|
||||
mts -t $TAPEFILE | tee -a $LOGFILE
|
||||
# I'm assuming that the tar will have written an empty
|
||||
# file to the tape, otherwise I should do a cat here.
|
||||
else
|
||||
echo $date > $fsname.lasttar
|
||||
fi
|
||||
sleep 60;
|
||||
|
||||
mt -f $TAPEFILE rewind
|
||||
mt -f $TAPEFILE offl
|
||||
@@ -1,468 +0,0 @@
|
||||
/* xsparse - expands compressed sparse file images extracted from GNU tar
|
||||
archives.
|
||||
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
Written by Sergey Poznyakoff
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Bound on length of the string representing an off_t.
|
||||
See INT_STRLEN_BOUND in intprops.h for explanation */
|
||||
#define OFF_T_STRLEN_BOUND ((sizeof (off_t) * CHAR_BIT) * 146 / 485 + 1)
|
||||
#define OFF_T_STRSIZE_BOUND (OFF_T_STRLEN_BOUND+1)
|
||||
|
||||
#define BLOCKSIZE 512
|
||||
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
size_t numbytes;
|
||||
};
|
||||
|
||||
char *progname;
|
||||
int verbose;
|
||||
|
||||
void
|
||||
die (int code, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
fprintf (stderr, "\n");
|
||||
exit (code);
|
||||
}
|
||||
|
||||
void *
|
||||
emalloc (size_t size)
|
||||
{
|
||||
char *p = malloc (size);
|
||||
if (!p)
|
||||
die (1, "not enough memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
off_t
|
||||
string_to_off (char *p, char **endp)
|
||||
{
|
||||
off_t v = 0;
|
||||
|
||||
for (; *p; p++)
|
||||
{
|
||||
int digit = *p - '0';
|
||||
off_t x = v * 10;
|
||||
if (9 < (unsigned) digit)
|
||||
{
|
||||
if (endp)
|
||||
{
|
||||
*endp = p;
|
||||
break;
|
||||
}
|
||||
die (1, "number parse error near %s", p);
|
||||
}
|
||||
else if (x / 10 != v)
|
||||
die (1, "number out of allowed range, near %s", p);
|
||||
v = x + digit;
|
||||
if (v < 0)
|
||||
die (1, "negative number");
|
||||
}
|
||||
if (endp)
|
||||
*endp = p;
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t
|
||||
string_to_size (char *p, char **endp)
|
||||
{
|
||||
off_t v = string_to_off (p, endp);
|
||||
size_t ret = v;
|
||||
if (ret != v)
|
||||
die (1, "number too big");
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t sparse_map_size;
|
||||
struct sp_array *sparse_map;
|
||||
|
||||
void
|
||||
get_line (char *s, int size, FILE *stream)
|
||||
{
|
||||
char *p = fgets (s, size, stream);
|
||||
size_t len;
|
||||
|
||||
if (!p)
|
||||
die (1, "unexpected end of file");
|
||||
len = strlen (p);
|
||||
if (s[len - 1] != '\n')
|
||||
die (1, "buffer overflow");
|
||||
s[len - 1] = 0;
|
||||
}
|
||||
|
||||
int
|
||||
get_var (FILE *fp, char **name, char **value)
|
||||
{
|
||||
static char *buffer;
|
||||
static size_t bufsize = OFF_T_STRSIZE_BOUND;
|
||||
char *p, *q;
|
||||
|
||||
buffer = emalloc (bufsize);
|
||||
do
|
||||
{
|
||||
size_t len, s;
|
||||
|
||||
if (!fgets (buffer, bufsize, fp))
|
||||
return 0;
|
||||
len = strlen (buffer);
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
s = string_to_size (buffer, &p);
|
||||
if (*p != ' ')
|
||||
die (1, "malformed header: expected space but found %s", p);
|
||||
if (buffer[len-1] != '\n')
|
||||
{
|
||||
if (bufsize < s + 1)
|
||||
{
|
||||
bufsize = s + 1;
|
||||
buffer = realloc (buffer, bufsize);
|
||||
if (!buffer)
|
||||
die (1, "not enough memory");
|
||||
}
|
||||
if (!fgets (buffer + len, s - len + 1, fp))
|
||||
die (1, "unexpected end of file or read error");
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (memcmp (p, "GNU.sparse.", 11));
|
||||
|
||||
p += 11;
|
||||
q = strchr (p, '=');
|
||||
if (!q)
|
||||
die (1, "malformed header: expected `=' not found");
|
||||
*q++ = 0;
|
||||
q[strlen (q) - 1] = 0;
|
||||
*name = p;
|
||||
*value = q;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *outname;
|
||||
off_t outsize;
|
||||
unsigned version_major;
|
||||
unsigned version_minor;
|
||||
|
||||
void
|
||||
read_xheader (char *name)
|
||||
{
|
||||
char *kw, *val;
|
||||
FILE *fp = fopen (name, "r");
|
||||
char *expect = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
if (verbose)
|
||||
printf ("Reading extended header file\n");
|
||||
|
||||
while (get_var (fp, &kw, &val))
|
||||
{
|
||||
if (verbose)
|
||||
printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
|
||||
|
||||
if (expect && strcmp (kw, expect))
|
||||
die (1, "bad keyword sequence: expected `%s' but found `%s'",
|
||||
expect, kw);
|
||||
expect = NULL;
|
||||
if (strcmp (kw, "name") == 0)
|
||||
{
|
||||
outname = emalloc (strlen (val) + 1);
|
||||
strcpy (outname, val);
|
||||
}
|
||||
else if (strcmp (kw, "major") == 0)
|
||||
{
|
||||
version_major = string_to_size (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "minor") == 0)
|
||||
{
|
||||
version_minor = string_to_size (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "realsize") == 0
|
||||
|| strcmp (kw, "size") == 0)
|
||||
{
|
||||
outsize = string_to_off (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "numblocks") == 0)
|
||||
{
|
||||
sparse_map_size = string_to_size (val, NULL);
|
||||
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
|
||||
}
|
||||
else if (strcmp (kw, "offset") == 0)
|
||||
{
|
||||
sparse_map[i].offset = string_to_off (val, NULL);
|
||||
expect = "numbytes";
|
||||
}
|
||||
else if (strcmp (kw, "numbytes") == 0)
|
||||
{
|
||||
sparse_map[i++].numbytes = string_to_size (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "map") == 0)
|
||||
{
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
{
|
||||
sparse_map[i].offset = string_to_off (val, &val);
|
||||
if (*val != ',')
|
||||
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
|
||||
*val);
|
||||
sparse_map[i].numbytes = string_to_size (val+1, &val);
|
||||
if (*val != ',')
|
||||
{
|
||||
if (!(*val == 0 && i == sparse_map_size-1))
|
||||
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
|
||||
*val);
|
||||
}
|
||||
else
|
||||
val++;
|
||||
}
|
||||
if (*val)
|
||||
die (1, "bad GNU.sparse.map: garbage at the end");
|
||||
}
|
||||
}
|
||||
if (expect)
|
||||
die (1, "bad keyword sequence: expected `%s' not found", expect);
|
||||
if (version_major == 0 && sparse_map_size == 0)
|
||||
die (1, "size of the sparse map unknown");
|
||||
if (i != sparse_map_size)
|
||||
die (1, "not all sparse entries supplied");
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
void
|
||||
read_map (FILE *ifp)
|
||||
{
|
||||
size_t i;
|
||||
char nbuf[OFF_T_STRSIZE_BOUND];
|
||||
|
||||
if (verbose)
|
||||
printf ("Reading v.1.0 sparse map\n");
|
||||
|
||||
get_line (nbuf, sizeof nbuf, ifp);
|
||||
sparse_map_size = string_to_size (nbuf, NULL);
|
||||
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
|
||||
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
{
|
||||
get_line (nbuf, sizeof nbuf, ifp);
|
||||
sparse_map[i].offset = string_to_off (nbuf, NULL);
|
||||
get_line (nbuf, sizeof nbuf, ifp);
|
||||
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
|
||||
}
|
||||
|
||||
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
|
||||
SEEK_SET);
|
||||
}
|
||||
|
||||
void
|
||||
expand_sparse (FILE *sfp, int ofd)
|
||||
{
|
||||
size_t i;
|
||||
size_t maxbytes = 0;
|
||||
char *buffer;
|
||||
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
if (maxbytes < sparse_map[i].numbytes)
|
||||
maxbytes = sparse_map[i].numbytes;
|
||||
|
||||
for (buffer = malloc (maxbytes); !buffer; maxbytes /= 2)
|
||||
if (maxbytes == 0)
|
||||
die (1, "not enough memory");
|
||||
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
{
|
||||
size_t size = sparse_map[i].numbytes;
|
||||
|
||||
lseek (ofd, sparse_map[i].offset, SEEK_SET);
|
||||
while (size)
|
||||
{
|
||||
size_t rdsize = (size < maxbytes) ? size : maxbytes;
|
||||
if (rdsize != fread (buffer, 1, rdsize, sfp))
|
||||
die (1, "read error (%d)", errno);
|
||||
if (rdsize != write (ofd, buffer, rdsize))
|
||||
die (1, "write error (%d)", errno);
|
||||
size -= rdsize;
|
||||
}
|
||||
}
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
usage (int code)
|
||||
{
|
||||
printf ("Usage: %s [OPTIONS] infile [outfile]\n", progname);
|
||||
printf ("%s: expand sparse files extracted from GNU archives\n",
|
||||
progname);
|
||||
printf ("\nOPTIONS are:\n\n");
|
||||
printf (" -h Display this help list\n");
|
||||
printf (" -n Dry run: do nothing, print what would have been done\n");
|
||||
printf (" -v Increase verbosity level\n");
|
||||
printf (" -x FILE Parse extended header FILE\n\n");
|
||||
|
||||
exit (code);
|
||||
}
|
||||
|
||||
void
|
||||
guess_outname (char *name)
|
||||
{
|
||||
char *p;
|
||||
char *s;
|
||||
|
||||
if (name[0] == '.' && name[1] == '/')
|
||||
name += 2;
|
||||
|
||||
p = name + strlen (name) - 1;
|
||||
s = NULL;
|
||||
|
||||
for (; p > name && *p != '/'; p--)
|
||||
;
|
||||
if (*p == '/')
|
||||
s = p + 1;
|
||||
if (p != name)
|
||||
{
|
||||
for (p--; p > name && *p != '/'; p--)
|
||||
;
|
||||
}
|
||||
|
||||
if (*p != '/')
|
||||
{
|
||||
if (s)
|
||||
outname = s;
|
||||
else
|
||||
{
|
||||
outname = emalloc (4 + strlen (name));
|
||||
strcpy (outname, "../");
|
||||
strcpy (outname + 3, name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = p - name + 1;
|
||||
outname = emalloc (len + strlen (s) + 1);
|
||||
memcpy (outname, name, len);
|
||||
strcpy (outname + len, s);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int dry_run = 0;
|
||||
char *xheader_file = NULL;
|
||||
char *inname;
|
||||
FILE *ifp;
|
||||
struct stat st;
|
||||
int ofd;
|
||||
|
||||
progname = argv[0];
|
||||
while ((c = getopt (argc, argv, "hnvx:")) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'h':
|
||||
usage (0);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
xheader_file = optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
dry_run = 1;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
default:
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0 || argc > 2)
|
||||
usage (1);
|
||||
|
||||
if (xheader_file)
|
||||
read_xheader (xheader_file);
|
||||
|
||||
inname = argv[0];
|
||||
if (argv[1])
|
||||
outname = argv[1];
|
||||
|
||||
if (stat (inname, &st))
|
||||
die (1, "cannot stat %s (%d)", inname, errno);
|
||||
|
||||
ifp = fopen (inname, "r");
|
||||
if (ifp == NULL)
|
||||
die (1, "cannot open file %s (%d)", inname, errno);
|
||||
|
||||
if (!xheader_file || version_major == 1)
|
||||
read_map (ifp);
|
||||
|
||||
if (!outname)
|
||||
guess_outname (inname);
|
||||
|
||||
ofd = open (outname, O_RDWR|O_CREAT|O_TRUNC, st.st_mode);
|
||||
if (ofd == -1)
|
||||
die (1, "cannot open file %s (%d)", outname, errno);
|
||||
|
||||
if (verbose)
|
||||
printf ("Expanding file `%s' to `%s'\n", inname, outname);
|
||||
|
||||
if (dry_run)
|
||||
{
|
||||
printf ("Finished dry run\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
expand_sparse (ifp, ofd);
|
||||
|
||||
fclose (ifp);
|
||||
close (ofd);
|
||||
|
||||
if (verbose)
|
||||
printf ("Done\n");
|
||||
|
||||
if (outsize)
|
||||
{
|
||||
if (stat (outname, &st))
|
||||
die (1, "cannot stat output file %s (%d)", outname, errno);
|
||||
if (st.st_size != outsize)
|
||||
die (1, "expanded file has wrong size");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
localedir.h
|
||||
rmt
|
||||
tar
|
||||
.deps
|
||||
.gdbinit
|
||||
@@ -1,49 +1,51 @@
|
||||
# Makefile for GNU tar sources.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 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 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.
|
||||
|
||||
## 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.
|
||||
# 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.
|
||||
|
||||
AUTOMAKE_OPTIONS = gnits ansi2knr
|
||||
bin_PROGRAMS = tar
|
||||
libexec_PROGRAMS = @RMT@
|
||||
EXTRA_PROGRAMS = rmt
|
||||
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
extract.c\
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
list.c\
|
||||
mangle.c\
|
||||
misc.c\
|
||||
names.c\
|
||||
sparse.c\
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
noinst_HEADERS = arith.h common.h rmt.h system.h tar.h
|
||||
rmt_SOURCES = rmt.c
|
||||
tar_SOURCES = arith.c buffer.c compare.c create.c delete.c extract.c \
|
||||
incremen.c list.c mangle.c misc.c names.c open3.c rtapelib.c tar.c update.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
|
||||
INCLUDES = -I../intl -I$(top_srcdir)/lib
|
||||
LDADD = ../lib/libtar.a @INTLLIBS@
|
||||
localedir = $(prefix)/@DATADIRNAME@/locale
|
||||
|
||||
tar.o: ../lib/localedir.h
|
||||
tar.o: tar.c
|
||||
$(COMPILE) -DLOCALEDIR=\"$(localedir)\" -c $(srcdir)/tar.c
|
||||
|
||||
LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
|
||||
tar._o: tar._c
|
||||
@rm -f _tar.c
|
||||
@ln tar._c _tar.c
|
||||
$(COMPILE) -DLOCALEDIR=\"$(localedir)\" -c _tar.c
|
||||
@mv _tar.o $@
|
||||
@rm _tar.c
|
||||
|
||||
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
|
||||
rmt.o: rmt.c
|
||||
$(COMPILE) -DLOCALEDIR=\"$(localedir)\" -c $(srcdir)/rmt.c
|
||||
|
||||
rmt._o: rmt._c
|
||||
@rm -f _rmt.c
|
||||
@ln rmt._c _rmt.c
|
||||
$(COMPILE) -DLOCALEDIR=\"$(localedir)\" -c _rmt.c
|
||||
@mv _rmt.o $@
|
||||
@rm _rmt.c
|
||||
|
||||
122
src/arith.h
122
src/arith.h
@@ -1,5 +1,5 @@
|
||||
/* Long integers, for GNU tar.
|
||||
Copyright 1999 Free Software Foundation, Inc.
|
||||
/* Simple 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
|
||||
@@ -13,15 +13,111 @@
|
||||
|
||||
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. */
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Handle large integers for calculating big tape lengths and the
|
||||
like. In practice, double precision does for now. On the vast
|
||||
majority of machines, it counts up to 2**52 bytes without any loss
|
||||
of information, and counts up to 2**62 bytes if data are always
|
||||
blocked in 1 kB boundaries. We'll need arbitrary precision
|
||||
arithmetic anyway once we get into the 2**64 range, so there's no
|
||||
point doing anything fancy before then. */
|
||||
|
||||
#define TARLONG_FORMAT "%.0f"
|
||||
typedef double tarlong;
|
||||
/* Also, see comments at beginning of arith.c. */
|
||||
|
||||
#define BITS_PER_BYTE 8 /* number of bits in each sizeof unit */
|
||||
#define BITS_PER_TARLONG 42 /* wanted number of bits in each tarlong */
|
||||
|
||||
/* In all cases, tarlong is the proper type for a big number.
|
||||
|
||||
For simulated arithmetic, SUPERDIGIT is the base, TARLONG_FORMAT is the
|
||||
format to print a single super-digit filled with zeroes to the left, and
|
||||
BITS_PER_SUPERDIGIT is the smallest number of bits required to fully
|
||||
represent each super-digit. LONGS_PER_TARLONG says how many longs are
|
||||
required for a full tarlong, and SIZEOF_TARLONG is the size of a tarlong
|
||||
in bytes.
|
||||
|
||||
For straight compiler arithmetic, SUPERDIGIT is zero and TARLONG_FORMAT
|
||||
is the format to directly print a tarlong (without zero-filling).
|
||||
|
||||
The values of SIZEOF_LONG_LONG and SIZEOF_UNSIGNED_LONG, below, are
|
||||
obtained through the configuration process. */
|
||||
|
||||
#if BITS_PER_BYTE * SIZEOF_UNSIGNED_LONG >= BITS_PER_TARLONG
|
||||
# define SUPERDIGIT 0
|
||||
# define TARLONG_FORMAT "%uld"
|
||||
typedef unsigned long tarlong;
|
||||
#else
|
||||
# if BITS_PER_BYTE * SIZEOF_LONG_LONG >= BITS_PER_TARLONG + 1
|
||||
# define SUPERDIGIT 0
|
||||
# define TARLONG_FORMAT "%lld"
|
||||
typedef long long tarlong;
|
||||
# else
|
||||
# if BITS_PER_BYTE * SIZEOF_UNSIGNED_LONG >= 64
|
||||
# define SUPERDIGIT 1000000000L
|
||||
# define BITS_PER_SUPERDIGIT 29
|
||||
# define TARLONG_FORMAT "%09uld"
|
||||
# else
|
||||
# if BITS_PER_BYTE * SIZEOF_UNSIGNED_LONG >= 32
|
||||
# define SUPERDIGIT 10000L
|
||||
# define BITS_PER_SUPERDIGIT 14
|
||||
# define TARLONG_FORMAT "%04uld"
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SUPERDIGIT
|
||||
|
||||
# define LONGS_PER_TARLONG \
|
||||
((BITS_PER_TARLONG + BITS_PER_SUPERDIGIT - 1) / BITS_PER_SUPERDIGIT)
|
||||
# define SIZEOF_TARLONG (LONGS_PER_TARLONG * sizeof (unsigned long))
|
||||
|
||||
/* The NEC EWS 4.2 C compiler gets confused by a pointer to a typedef that
|
||||
is an array. So we wrap the array into a struct. (Pouah!) */
|
||||
|
||||
struct tarlong
|
||||
{
|
||||
unsigned long digit[LONGS_PER_TARLONG];
|
||||
};
|
||||
|
||||
typedef struct tarlong tarlong;
|
||||
|
||||
int zerop_tarlong_helper PARAMS ((unsigned long *));
|
||||
int lessp_tarlong_helper PARAMS ((unsigned long *, unsigned long *));
|
||||
void clear_tarlong_helper PARAMS ((unsigned long *));
|
||||
void add_to_tarlong_helper PARAMS ((unsigned long *, int));
|
||||
void mult_tarlong_helper PARAMS ((unsigned long *, int));
|
||||
void print_tarlong_helper PARAMS ((unsigned long *, FILE *));
|
||||
|
||||
# define zerop_tarlong(Accumulator) \
|
||||
zerop_tarlong_helper (&(Accumulator).digit[0])
|
||||
|
||||
# define lessp_tarlong(First, Second) \
|
||||
lessp_tarlong_helper (&(First).digit[0], &(Second).digit[0])
|
||||
|
||||
# define clear_tarlong(Accumulator) \
|
||||
clear_tarlong_helper (&(Accumulator).digit[0])
|
||||
|
||||
# define add_to_tarlong(Accumulator, Value) \
|
||||
add_to_tarlong_helper (&(Accumulator).digit[0], (Value))
|
||||
|
||||
# define mult_tarlong(Accumulator, Value) \
|
||||
mult_tarlong_helper (&(Accumulator).digit[0], (Value))
|
||||
|
||||
# define print_tarlong(Accumulator, File) \
|
||||
print_tarlong_helper (&(Accumulator).digit[0], (File))
|
||||
|
||||
#else /* not SUPERDIGIT */
|
||||
|
||||
# define zerop_tarlong(Accumulator) \
|
||||
((Accumulator) == 0)
|
||||
|
||||
# define lessp_tarlong(First, Second) \
|
||||
((First) < (Second))
|
||||
|
||||
# define clear_tarlong(Accumulator) \
|
||||
((Accumulator) = 0)
|
||||
|
||||
# define add_to_tarlong(Accumulator, Value) \
|
||||
((Accumulator) += (Value))
|
||||
|
||||
# define mult_tarlong(Accumulator, Value) \
|
||||
((Accumulator) *= (Value))
|
||||
|
||||
# define print_tarlong(Accumulator, File) \
|
||||
(fprintf ((File), TARLONG_FORMAT, (Accumulator)))
|
||||
|
||||
#endif /* not SUPERDIGIT */
|
||||
|
||||
2212
src/buffer.c
2212
src/buffer.c
File diff suppressed because it is too large
Load Diff
710
src/common.h
710
src/common.h
@@ -1,7 +1,5 @@
|
||||
/* Common declarations for the tar program.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 92, 93, 94, 96, 97 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
|
||||
@@ -15,7 +13,7 @@
|
||||
|
||||
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. */
|
||||
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Declare the GNU tar archive format. */
|
||||
#include "tar.h"
|
||||
@@ -29,47 +27,69 @@
|
||||
#define UNAME_FIELD_SIZE 32
|
||||
#define GNAME_FIELD_SIZE 32
|
||||
|
||||
|
||||
/* POSIX specified symbols currently unused are undefined here. */
|
||||
#undef TSUID
|
||||
#undef TSGID
|
||||
#undef TSVTX
|
||||
#undef TUREAD
|
||||
#undef TUWRITE
|
||||
#undef TUEXEC
|
||||
#undef TGREAD
|
||||
#undef TGWRITE
|
||||
#undef TGEXEC
|
||||
#undef TOREAD
|
||||
#undef TOWRITE
|
||||
#undef TOEXEC
|
||||
|
||||
/* Some various global definitions. */
|
||||
|
||||
/* Name of file to use for interacting with user. */
|
||||
#if MSDOS
|
||||
# define TTY_NAME "con"
|
||||
#else
|
||||
# define TTY_NAME "/dev/tty"
|
||||
#endif
|
||||
|
||||
/* GLOBAL is defined to empty in tar.c only, and left alone in other *.c
|
||||
/* GLOBAL is defined to empty in `tar.c' only, and left alone in other `*.c'
|
||||
modules. Here, we merely set it to "extern" if it is not already set.
|
||||
GNU tar does depend on the system loader to preset all GLOBAL variables to
|
||||
neutral (or zero) values, explicit initialization is usually not done. */
|
||||
neutral (or zero) values, explicit initialisation is usually not done. */
|
||||
#ifndef GLOBAL
|
||||
# define GLOBAL extern
|
||||
#endif
|
||||
|
||||
#define TAREXIT_SUCCESS PAXEXIT_SUCCESS
|
||||
#define TAREXIT_DIFFERS PAXEXIT_DIFFERS
|
||||
#define TAREXIT_FAILURE PAXEXIT_FAILURE
|
||||
/* Exit status for GNU tar. Let's try to keep this list as simple as
|
||||
possible. -d option strongly invites a status different for unequal
|
||||
comparison and other errors. */
|
||||
GLOBAL int exit_status;
|
||||
|
||||
|
||||
#include "arith.h"
|
||||
#include <backupfile.h>
|
||||
#include <exclude.h>
|
||||
#include <full-write.h>
|
||||
#include <modechange.h>
|
||||
#include <quote.h>
|
||||
#include <safe-read.h>
|
||||
#include <stat-time.h>
|
||||
#include <timespec.h>
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
#include <obstack.h>
|
||||
#define TAREXIT_SUCCESS 0
|
||||
#define TAREXIT_DIFFERS 1
|
||||
#define TAREXIT_FAILURE 2
|
||||
|
||||
#include <paxlib.h>
|
||||
/* Both WARN and ERROR write a message on stderr and continue processing,
|
||||
however ERROR manages so tar will exit unsuccessfully. FATAL_ERROR
|
||||
writes a message on stderr and aborts immediately, with another message
|
||||
line telling so. USAGE_ERROR works like FATAL_ERROR except that the
|
||||
other message line suggests trying --help. All four macros accept a
|
||||
single argument of the form ((0, errno, _("FORMAT"), Args...)). `errno'
|
||||
is `0' when the error is not being detected by the system. */
|
||||
|
||||
/* Log base 2 of common values. */
|
||||
#define LG_8 3
|
||||
#define LG_64 6
|
||||
#define LG_256 8
|
||||
#define WARN(Args) \
|
||||
error Args
|
||||
#define ERROR(Args) \
|
||||
(error Args, exit_status = TAREXIT_FAILURE)
|
||||
#define FATAL_ERROR(Args) \
|
||||
(error Args, error (TAREXIT_FAILURE, 0, \
|
||||
_("Error is not recoverable: exiting now")), 0)
|
||||
#define USAGE_ERROR(Args) \
|
||||
(error Args, usage (TAREXIT_FAILURE), 0)
|
||||
|
||||
/* Information gleaned from the command line. */
|
||||
|
||||
#include "arith.h"
|
||||
#include "modechange.h"
|
||||
|
||||
/* Name of this program. */
|
||||
GLOBAL const char *program_name;
|
||||
|
||||
@@ -101,12 +121,10 @@ GLOBAL char filename_terminator;
|
||||
not have _option in their name, even if their values is derived from
|
||||
option decoding, as these are especially important in tar. */
|
||||
GLOBAL int blocking_factor;
|
||||
GLOBAL size_t record_size;
|
||||
GLOBAL int record_size;
|
||||
|
||||
GLOBAL bool absolute_names_option;
|
||||
|
||||
/* Display file times in UTC */
|
||||
GLOBAL bool utc_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int absolute_names_option;
|
||||
|
||||
/* This variable tells how to interpret newer_mtime_option, below. If zero,
|
||||
files get archived if their mtime is not less than newer_mtime_option.
|
||||
@@ -114,73 +132,54 @@ GLOBAL bool utc_option;
|
||||
than newer_mtime_option. */
|
||||
GLOBAL int after_date_option;
|
||||
|
||||
enum atime_preserve
|
||||
{
|
||||
no_atime_preserve,
|
||||
replace_atime_preserve,
|
||||
system_atime_preserve
|
||||
};
|
||||
GLOBAL enum atime_preserve atime_preserve_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int atime_preserve_option;
|
||||
|
||||
GLOBAL bool backup_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int backup_option;
|
||||
|
||||
/* Type of backups being made. */
|
||||
GLOBAL enum backup_type backup_type;
|
||||
/* Boolean value. */
|
||||
GLOBAL int block_number_option;
|
||||
|
||||
GLOBAL bool block_number_option;
|
||||
|
||||
GLOBAL unsigned checkpoint_option;
|
||||
|
||||
enum checkpoint_style
|
||||
{
|
||||
checkpoint_text,
|
||||
checkpoint_dot
|
||||
};
|
||||
|
||||
GLOBAL enum checkpoint_style checkpoint_style;
|
||||
/* Boolean value. */
|
||||
GLOBAL int checkpoint_option;
|
||||
|
||||
/* Specified name of compression program, or "gzip" as implied by -z. */
|
||||
GLOBAL const char *use_compress_program_option;
|
||||
|
||||
GLOBAL bool dereference_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int dereference_option;
|
||||
|
||||
/* Print a message if not all links are dumped */
|
||||
GLOBAL int check_links_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int exclude_option;
|
||||
|
||||
/* Patterns that match file names to be excluded. */
|
||||
GLOBAL struct exclude *excluded;
|
||||
/* Specified file containing names to work on. */
|
||||
GLOBAL const char *files_from_option;
|
||||
|
||||
/* Exclude directories containing a cache directory tag. */
|
||||
GLOBAL bool exclude_caches_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int force_local_option;
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
GLOBAL gid_t group_option;
|
||||
|
||||
GLOBAL bool ignore_failed_read_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int ignore_failed_read_option;
|
||||
|
||||
GLOBAL bool ignore_zeros_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int ignore_zeros_option;
|
||||
|
||||
GLOBAL bool incremental_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int incremental_option;
|
||||
|
||||
/* Specified name of script to run at end of each tape change. */
|
||||
GLOBAL const char *info_script_option;
|
||||
|
||||
GLOBAL bool interactive_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int interactive_option;
|
||||
|
||||
/* If nonzero, extract only Nth occurrence of each named file */
|
||||
GLOBAL uintmax_t occurrence_option;
|
||||
|
||||
enum old_files
|
||||
{
|
||||
DEFAULT_OLD_FILES, /* default */
|
||||
NO_OVERWRITE_DIR_OLD_FILES, /* --no-overwrite-dir */
|
||||
OVERWRITE_OLD_FILES, /* --overwrite */
|
||||
UNLINK_FIRST_OLD_FILES, /* --unlink-first */
|
||||
KEEP_OLD_FILES, /* --keep-old-files */
|
||||
KEEP_NEWER_FILES /* --keep-newer-files */
|
||||
};
|
||||
GLOBAL enum old_files old_files_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int keep_old_files_option;
|
||||
|
||||
/* Specified file name for incremental list. */
|
||||
GLOBAL const char *listed_incremental_option;
|
||||
@@ -188,99 +187,83 @@ GLOBAL const char *listed_incremental_option;
|
||||
/* Specified mode change string. */
|
||||
GLOBAL struct mode_change *mode_option;
|
||||
|
||||
/* Initial umask, if needed for mode change string. */
|
||||
GLOBAL mode_t initial_umask;
|
||||
/* Boolean value. */
|
||||
GLOBAL int multi_volume_option;
|
||||
|
||||
GLOBAL bool multi_volume_option;
|
||||
/* The same variable hold the time, whether mtime or ctime. Just fake a
|
||||
non-existing option, for making the code clearer, elsewhere. */
|
||||
#define newer_ctime_option newer_mtime_option
|
||||
|
||||
/* Specified threshold date and time. Files having an older time stamp
|
||||
do not get archived (also see after_date_option above). */
|
||||
GLOBAL struct timespec newer_mtime_option;
|
||||
/* Specified threshold date and time. Files having a more recent timestamp
|
||||
get archived (also see after_date_option above). If left to zero, it may
|
||||
be interpreted as very low threshold, just usable as such. */
|
||||
GLOBAL time_t newer_mtime_option;
|
||||
|
||||
/* If true, override actual mtime (see below) */
|
||||
GLOBAL bool set_mtime_option;
|
||||
/* Value to be put in mtime header field instead of the actual mtime */
|
||||
GLOBAL struct timespec mtime_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int no_recurse_option;
|
||||
|
||||
/* Return true if newer_mtime_option is initialized. */
|
||||
#define NEWER_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
|
||||
/* Boolean value. */
|
||||
GLOBAL int numeric_owner_option;
|
||||
|
||||
/* Return true if the struct stat ST's M time is less than
|
||||
newer_mtime_option. */
|
||||
#define OLDER_STAT_TIME(st, m) \
|
||||
(timespec_cmp (get_stat_##m##time (&(st)), newer_mtime_option) < 0)
|
||||
|
||||
/* Likewise, for struct tar_stat_info ST. */
|
||||
#define OLDER_TAR_STAT_TIME(st, m) \
|
||||
(timespec_cmp ((st).m##time, newer_mtime_option) < 0)
|
||||
|
||||
/* Zero if there is no recursion, otherwise FNM_LEADING_DIR. */
|
||||
GLOBAL int recursion_option;
|
||||
|
||||
GLOBAL bool numeric_owner_option;
|
||||
|
||||
GLOBAL bool one_file_system_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int one_file_system_option;
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
GLOBAL uid_t owner_option;
|
||||
|
||||
GLOBAL bool recursive_unlink_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int recursive_unlink_option;
|
||||
|
||||
GLOBAL bool read_full_records_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int read_full_records_option;
|
||||
|
||||
GLOBAL bool remove_files_option;
|
||||
|
||||
/* Specified rmt command. */
|
||||
GLOBAL const char *rmt_command_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int remove_files_option;
|
||||
|
||||
/* Specified remote shell command. */
|
||||
GLOBAL const char *rsh_command_option;
|
||||
|
||||
GLOBAL bool same_order_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int same_order_option;
|
||||
|
||||
/* If positive, preserve ownership when extracting. */
|
||||
/* Boolean value. */
|
||||
GLOBAL int same_owner_option;
|
||||
|
||||
/* If positive, preserve permissions when extracting. */
|
||||
/* Boolean value. */
|
||||
GLOBAL int same_permissions_option;
|
||||
|
||||
/* When set, strip the given number of file name components from the file name
|
||||
before extracting */
|
||||
GLOBAL size_t strip_name_components;
|
||||
/* Boolean value. */
|
||||
GLOBAL int show_omitted_dirs_option;
|
||||
|
||||
GLOBAL bool show_omitted_dirs_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int sparse_option;
|
||||
|
||||
GLOBAL bool sparse_option;
|
||||
GLOBAL unsigned tar_sparse_major;
|
||||
GLOBAL unsigned tar_sparse_minor;
|
||||
|
||||
GLOBAL bool starting_file_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int starting_file_option;
|
||||
|
||||
/* Specified maximum byte length of each tape volume (multiple of 1024). */
|
||||
GLOBAL tarlong tape_length_option;
|
||||
|
||||
GLOBAL bool to_stdout_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int to_stdout_option;
|
||||
|
||||
GLOBAL bool totals_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int totals_option;
|
||||
|
||||
GLOBAL bool touch_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int touch_option;
|
||||
|
||||
GLOBAL char *to_command_option;
|
||||
GLOBAL bool ignore_command_error_option;
|
||||
|
||||
/* Restrict some potentially harmful tar options */
|
||||
GLOBAL bool restrict_option;
|
||||
|
||||
/* Return true if the extracted files are not being written to disk */
|
||||
#define EXTRACT_OVER_PIPE (to_stdout_option || to_command_option)
|
||||
/* Boolean value. */
|
||||
GLOBAL int unlink_first_option;
|
||||
|
||||
/* Count how many times the option has been set, multiple setting yields
|
||||
more verbose behavior. Value 0 means no verbosity, 1 means file name
|
||||
only, 2 means file name and all attributes. More than 2 is just like 2. */
|
||||
GLOBAL int verbose_option;
|
||||
|
||||
GLOBAL bool verify_option;
|
||||
/* Boolean value. */
|
||||
GLOBAL int verify_option;
|
||||
|
||||
/* Specified name of file containing the volume number. */
|
||||
GLOBAL const char *volno_file_option;
|
||||
@@ -294,69 +277,47 @@ GLOBAL const char *volume_label_option;
|
||||
GLOBAL int archive;
|
||||
|
||||
/* Nonzero when outputting to /dev/null. */
|
||||
GLOBAL bool dev_null_output;
|
||||
GLOBAL int dev_null_output;
|
||||
|
||||
/* Timestamps: */
|
||||
GLOBAL struct timespec start_time; /* when we started execution */
|
||||
GLOBAL struct timespec volume_start_time; /* when the current volume was
|
||||
opened*/
|
||||
GLOBAL struct timespec last_stat_time; /* when the statistics was last
|
||||
computed */
|
||||
/* Name of file for the current archive entry. */
|
||||
GLOBAL char *current_file_name;
|
||||
|
||||
GLOBAL struct tar_stat_info current_stat_info;
|
||||
/* Name of link for the current archive entry. */
|
||||
GLOBAL char *current_link_name;
|
||||
|
||||
/* List of tape drive names, number of such tape drives, allocated number,
|
||||
and current cursor in list. */
|
||||
GLOBAL const char **archive_name_array;
|
||||
GLOBAL size_t archive_names;
|
||||
GLOBAL size_t allocated_archive_names;
|
||||
GLOBAL int archive_names;
|
||||
GLOBAL int allocated_archive_names;
|
||||
GLOBAL const char **archive_name_cursor;
|
||||
|
||||
/* Output index file name. */
|
||||
GLOBAL char const *index_file_name;
|
||||
|
||||
/* Structure for keeping track of filenames and lists thereof. */
|
||||
struct name
|
||||
{
|
||||
struct name *next; /* Link to the next element */
|
||||
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) */
|
||||
struct name *next;
|
||||
short length; /* cached strlen(name) */
|
||||
char found; /* a matching file has been found */
|
||||
char firstch; /* first char is literally matched */
|
||||
char regexp; /* this name is a regexp, not literal */
|
||||
char *change_dir; /* set with the -C option */
|
||||
char *dir_contents; /* for incremental_option */
|
||||
char fake; /* dummy entry */
|
||||
char name[1];
|
||||
};
|
||||
GLOBAL struct name *namelist; /* points to first name in list */
|
||||
GLOBAL struct name *namelast; /* points to last name in list */
|
||||
|
||||
/* Obnoxious test to see if dimwit is trying to dump the archive. */
|
||||
GLOBAL dev_t ar_dev;
|
||||
GLOBAL ino_t ar_ino;
|
||||
/* Pointer to the start of the scratch space. */
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
int numbytes;
|
||||
};
|
||||
GLOBAL struct sp_array *sparsearray;
|
||||
|
||||
GLOBAL bool seekable_archive;
|
||||
|
||||
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 */
|
||||
GLOBAL bool show_transformed_names_option;
|
||||
|
||||
/* Delay setting modification times and permissions of extracted directories
|
||||
until the end of extraction. This variable helps correctly restore directory
|
||||
timestamps from archives with an unusual member order. It is automatically
|
||||
set for incremental archives. */
|
||||
GLOBAL bool delay_directory_restore_option;
|
||||
|
||||
/* Warn about implicit use of the wildcards in command line arguments.
|
||||
(Default for tar prior to 1.15.91, but changed afterwards */
|
||||
GLOBAL bool warn_regex_usage;
|
||||
/* Initial size of the sparsearray. */
|
||||
GLOBAL int sp_array_size;
|
||||
|
||||
/* Declarations for each module. */
|
||||
|
||||
@@ -374,117 +335,59 @@ extern enum access_mode access_mode;
|
||||
/* Module buffer.c. */
|
||||
|
||||
extern FILE *stdlis;
|
||||
extern bool write_archive_to_stdout;
|
||||
extern char *volume_label;
|
||||
extern char *continued_file_name;
|
||||
extern uintmax_t continued_file_size;
|
||||
extern uintmax_t continued_file_offset;
|
||||
|
||||
size_t available_space_after (union block *pointer);
|
||||
off_t current_block_ordinal (void);
|
||||
void close_archive (void);
|
||||
void closeout_volume_number (void);
|
||||
void compute_duration (void);
|
||||
union block *find_next_block (void);
|
||||
void flush_read (void);
|
||||
void flush_write (void);
|
||||
void flush_archive (void);
|
||||
void init_volume_number (void);
|
||||
void open_archive (enum access_mode mode);
|
||||
void print_total_stats (void);
|
||||
void reset_eof (void);
|
||||
void set_next_block_after (union block *block);
|
||||
void clear_read_error_count (void);
|
||||
void xclose (int fd);
|
||||
void archive_write_error (ssize_t status) __attribute__ ((noreturn));
|
||||
void archive_read_error (void);
|
||||
off_t seek_archive (off_t size);
|
||||
void set_start_time (void);
|
||||
|
||||
void mv_begin (struct tar_stat_info *st);
|
||||
void mv_end (void);
|
||||
void mv_total_size (off_t size);
|
||||
void mv_size_left (off_t size);
|
||||
extern char *save_name;
|
||||
extern long save_sizeleft;
|
||||
extern long save_totsize;
|
||||
extern int write_archive_to_stdout;
|
||||
|
||||
int available_space_after PARAMS ((union block *));
|
||||
long current_block_ordinal PARAMS ((void));
|
||||
void close_archive PARAMS ((void));
|
||||
void closeout_volume_number PARAMS ((void));
|
||||
union block *find_next_block PARAMS ((void));
|
||||
void flush_read PARAMS ((void));
|
||||
void flush_write PARAMS ((void));
|
||||
void flush_archive PARAMS ((void));
|
||||
void init_total_written PARAMS ((void));
|
||||
void init_volume_number PARAMS ((void));
|
||||
void open_archive PARAMS ((enum access_mode));
|
||||
void print_total_written PARAMS ((void));
|
||||
void reset_eof PARAMS ((void));
|
||||
void set_next_block_after PARAMS ((union block *));
|
||||
|
||||
/* Module create.c. */
|
||||
|
||||
enum dump_status
|
||||
{
|
||||
dump_status_ok,
|
||||
dump_status_short,
|
||||
dump_status_fail,
|
||||
dump_status_not_implemented
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
void write_eot (void);
|
||||
void check_links (void);
|
||||
|
||||
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
|
||||
#define MAJOR_TO_CHARS(val, where) major_to_chars (val, where, sizeof (where))
|
||||
#define MINOR_TO_CHARS(val, where) minor_to_chars (val, where, sizeof (where))
|
||||
#define MODE_TO_CHARS(val, where) mode_to_chars (val, where, sizeof (where))
|
||||
#define OFF_TO_CHARS(val, where) off_to_chars (val, where, sizeof (where))
|
||||
#define SIZE_TO_CHARS(val, where) size_to_chars (val, where, sizeof (where))
|
||||
#define TIME_TO_CHARS(val, where) time_to_chars (val, where, sizeof (where))
|
||||
#define UID_TO_CHARS(val, where) uid_to_chars (val, where, sizeof (where))
|
||||
#define UINTMAX_TO_CHARS(val, where) uintmax_to_chars (val, where, sizeof (where))
|
||||
#define UNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
|
||||
#define GNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
|
||||
|
||||
bool gid_to_chars (gid_t gid, char *buf, size_t size);
|
||||
bool major_to_chars (major_t m, char *buf, size_t size);
|
||||
bool minor_to_chars (minor_t m, char *buf, size_t size);
|
||||
bool mode_to_chars (mode_t m, char *buf, size_t size);
|
||||
bool off_to_chars (off_t off, char *buf, size_t size);
|
||||
bool size_to_chars (size_t v, char *buf, size_t size);
|
||||
bool time_to_chars (time_t t, char *buf, size_t size);
|
||||
bool uid_to_chars (uid_t uid, char *buf, size_t size);
|
||||
bool uintmax_to_chars (uintmax_t v, char *buf, size_t size);
|
||||
void string_to_chars (char const *s, char *buf, size_t size);
|
||||
void create_archive PARAMS ((void));
|
||||
void dump_file PARAMS ((char *, int, int));
|
||||
void finish_header PARAMS ((union block *));
|
||||
void to_oct PARAMS ((long, int, char *));
|
||||
void write_eot PARAMS ((void));
|
||||
|
||||
/* Module diffarch.c. */
|
||||
|
||||
extern bool now_verifying;
|
||||
extern int now_verifying;
|
||||
|
||||
void diff_archive (void);
|
||||
void diff_init (void);
|
||||
void verify_volume (void);
|
||||
void diff_archive PARAMS ((void));
|
||||
void diff_init PARAMS ((void));
|
||||
void verify_volume PARAMS ((void));
|
||||
|
||||
/* Module extract.c. */
|
||||
|
||||
void extr_init (void);
|
||||
void extract_archive (void);
|
||||
void extract_finish (void);
|
||||
bool rename_directory (char *src, char *dst);
|
||||
void extr_init PARAMS ((void));
|
||||
void extract_archive PARAMS ((void));
|
||||
void apply_delayed_set_stat PARAMS ((void));
|
||||
|
||||
/* Module delete.c. */
|
||||
|
||||
void delete_archive_members (void);
|
||||
void delete_archive_members PARAMS ((void));
|
||||
|
||||
/* Module incremen.c. */
|
||||
|
||||
char *get_directory_contents (char *dir_name, dev_t device);
|
||||
const char *append_incremental_renames (const char *dump);
|
||||
void read_directory_file (void);
|
||||
void write_directory_file (void);
|
||||
void purge_directory (char const *directory_name);
|
||||
void list_dumpdir (char *buffer, size_t size);
|
||||
void update_parent_directory (const char *name);
|
||||
|
||||
size_t dumpdir_size (const char *p);
|
||||
bool is_dumpdir (struct tar_stat_info *stat_info);
|
||||
void collect_and_sort_names PARAMS ((void));
|
||||
char *get_directory_contents PARAMS ((char *, int));
|
||||
void write_dir_file PARAMS ((void));
|
||||
void gnu_restore PARAMS ((int));
|
||||
void write_directory_file PARAMS ((void));
|
||||
|
||||
/* Module list.c. */
|
||||
|
||||
@@ -492,240 +395,77 @@ enum read_header
|
||||
{
|
||||
HEADER_STILL_UNREAD, /* for when read_header has not been called */
|
||||
HEADER_SUCCESS, /* header successfully read and checksummed */
|
||||
HEADER_SUCCESS_EXTENDED, /* likewise, but we got an extended header */
|
||||
HEADER_ZERO_BLOCK, /* zero block where header expected */
|
||||
HEADER_END_OF_FILE, /* true end of file while header expected */
|
||||
HEADER_FAILURE /* ill-formed header, or bad checksum */
|
||||
};
|
||||
|
||||
struct xheader
|
||||
{
|
||||
struct obstack *stk;
|
||||
size_t size;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
GLOBAL struct xheader extended_header;
|
||||
extern union block *current_header;
|
||||
extern struct stat current_stat;
|
||||
extern enum archive_format current_format;
|
||||
extern size_t recent_long_name_blocks;
|
||||
extern size_t recent_long_link_blocks;
|
||||
|
||||
void decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
enum archive_format *format_pointer, int do_user_group);
|
||||
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 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))
|
||||
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
|
||||
#define UINTMAX_FROM_HEADER(where) uintmax_from_header (where, sizeof (where))
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
void list_archive (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 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 tar_checksum (union block *header, bool silent);
|
||||
void skip_file (off_t size);
|
||||
void skip_member (void);
|
||||
void decode_header PARAMS ((union block *, struct stat *,
|
||||
enum archive_format *, int));
|
||||
long from_oct PARAMS ((int, char *));
|
||||
void list_archive PARAMS ((void));
|
||||
void print_for_mkdir PARAMS ((char *, int, int));
|
||||
void print_header PARAMS ((void));
|
||||
void read_and PARAMS ((void (*do_) ()));
|
||||
enum read_header read_header PARAMS ((void));
|
||||
void skip_extended_headers PARAMS ((void));
|
||||
void skip_file PARAMS ((long));
|
||||
|
||||
/* Module mangle.c. */
|
||||
|
||||
void extract_mangle (void);
|
||||
void extract_mangle PARAMS ((void));
|
||||
|
||||
/* Module misc.c. */
|
||||
|
||||
void assign_string (char **dest, const char *src);
|
||||
char *quote_copy_string (const char *str);
|
||||
int unquote_string (char *str);
|
||||
void assign_string PARAMS ((char **, const char *));
|
||||
char *quote_copy_string PARAMS ((const char *));
|
||||
int unquote_string PARAMS ((char *));
|
||||
|
||||
void code_ns_fraction (int ns, char *p);
|
||||
char const *code_timespec (struct timespec ts, char *sbuf);
|
||||
enum { BILLION = 1000000000, LOG10_BILLION = 9 };
|
||||
enum { TIMESPEC_STRSIZE_BOUND =
|
||||
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
|
||||
char *merge_sort PARAMS ((char *, int, int, int (*) (char *, char *)));
|
||||
|
||||
enum remove_option
|
||||
{
|
||||
ORDINARY_REMOVE_OPTION,
|
||||
RECURSIVE_REMOVE_OPTION,
|
||||
|
||||
/* FIXME: The following value is never used. It seems to be intended
|
||||
as a placeholder for a hypothetical option that should instruct tar
|
||||
to recursively remove subdirectories in purge_directory(),
|
||||
as opposed to the functionality of --recursive-unlink
|
||||
(RECURSIVE_REMOVE_OPTION value), which removes them in
|
||||
prepare_to_extract() phase. However, with the addition of more
|
||||
meta-info to the incremental dumps, this should become unnecessary */
|
||||
WANT_DIRECTORY_REMOVE_OPTION
|
||||
};
|
||||
int remove_any_file (const char *file_name, enum remove_option option);
|
||||
bool maybe_backup_file (const char *file_name, bool this_is_the_archive);
|
||||
void undo_last_backup (void);
|
||||
|
||||
int deref_stat (bool deref, char const *name, struct stat *buf);
|
||||
|
||||
void closeopen (void);
|
||||
int chdir_arg (char const *dir);
|
||||
void chdir_do (int dir);
|
||||
|
||||
void close_diag (char const *name);
|
||||
void open_diag (char const *name);
|
||||
void read_diag_details (char const *name, off_t offset, size_t size);
|
||||
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 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)
|
||||
__attribute__ ((noreturn));
|
||||
|
||||
pid_t xfork (void);
|
||||
void xpipe (int fd[2]);
|
||||
|
||||
void *page_aligned_alloc (void **ptr, size_t size);
|
||||
int set_file_atime (int fd, char const *file,
|
||||
struct timespec const timespec[2]);
|
||||
int is_dot_or_dotdot PARAMS ((const char *));
|
||||
int remove_any_file PARAMS ((const char *, int));
|
||||
int maybe_backup_file PARAMS ((const char *, int));
|
||||
void undo_last_backup PARAMS ((void));
|
||||
|
||||
/* Module names.c. */
|
||||
|
||||
extern struct name *gnu_list_name;
|
||||
void gid_to_gname PARAMS ((gid_t, char gname[GNAME_FIELD_SIZE]));
|
||||
int gname_to_gid PARAMS ((char gname[GNAME_FIELD_SIZE], gid_t *));
|
||||
void uid_to_uname PARAMS ((uid_t, char uname[UNAME_FIELD_SIZE]));
|
||||
int uname_to_uid PARAMS ((char uname[UNAME_FIELD_SIZE], uid_t *));
|
||||
|
||||
void gid_to_gname (gid_t gid, char **gname);
|
||||
int gname_to_gid (char const *gname, gid_t *pgid);
|
||||
void uid_to_uname (uid_t uid, char **uname);
|
||||
int uname_to_uid (char const *uname, uid_t *puid);
|
||||
void init_names PARAMS ((void));
|
||||
void name_add PARAMS ((const char *));
|
||||
void name_init PARAMS ((int, char *const *));
|
||||
void name_term PARAMS ((void));
|
||||
char *name_next PARAMS ((int change_));
|
||||
void name_close PARAMS ((void));
|
||||
void name_gather PARAMS ((void));
|
||||
void addname PARAMS ((const char *));
|
||||
int name_match PARAMS ((const char *));
|
||||
void names_notfound PARAMS ((void));
|
||||
void name_expand PARAMS ((void));
|
||||
struct name *name_scan PARAMS ((const char *));
|
||||
char *name_from_list PARAMS ((void));
|
||||
void blank_name_list PARAMS ((void));
|
||||
char *new_name PARAMS ((const char *, const char *));
|
||||
|
||||
void name_init (void);
|
||||
void name_add_name (const char *name, int matching_flags);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
bool all_names_found (struct tar_stat_info *st);
|
||||
|
||||
bool excluded_name (char const *name);
|
||||
|
||||
void add_avoided_name (char const *name);
|
||||
bool is_avoided_name (char const *name);
|
||||
bool is_individual_file (char const *name);
|
||||
|
||||
bool contains_dot_dot (char const *name);
|
||||
|
||||
#define ISFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
|
||||
(c)->found_count == occurrence_option)
|
||||
#define WASFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
|
||||
(c)->found_count >= occurrence_option)
|
||||
void add_exclude PARAMS ((char *));
|
||||
void add_exclude_file PARAMS ((const char *));
|
||||
int check_exclude PARAMS ((const char *));
|
||||
|
||||
/* Module tar.c. */
|
||||
|
||||
void usage (int);
|
||||
|
||||
int confirm (const char *message_action, const char *name);
|
||||
void request_stdin (const char *option);
|
||||
|
||||
void tar_stat_init (struct tar_stat_info *st);
|
||||
void tar_stat_destroy (struct tar_stat_info *st);
|
||||
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);
|
||||
int confirm PARAMS ((const char *, const char *));
|
||||
void request_stdin PARAMS ((const char *));
|
||||
|
||||
/* Module update.c. */
|
||||
|
||||
extern char *output_start;
|
||||
|
||||
void update_archive (void);
|
||||
|
||||
/* Module xheader.c. */
|
||||
|
||||
void xheader_decode (struct tar_stat_info *stat);
|
||||
void xheader_decode_global (void);
|
||||
void xheader_store (char const *keyword, struct tar_stat_info const *st,
|
||||
void const *data);
|
||||
void xheader_read (union block *header, size_t size);
|
||||
void xheader_write (char type, char *name, struct xheader *xhdr);
|
||||
void xheader_write_global (void);
|
||||
void xheader_finish (struct xheader *hdr);
|
||||
void xheader_destroy (struct xheader *hdr);
|
||||
char *xheader_xhdr_name (struct tar_stat_info *st);
|
||||
char *xheader_ghdr_name (void);
|
||||
void xheader_write (char type, char *name, struct xheader *xhdr);
|
||||
void xheader_write_global (void);
|
||||
void xheader_set_option (char *string);
|
||||
void xheader_string_begin (void);
|
||||
void xheader_string_add (char const *s);
|
||||
bool xheader_string_end (char const *keyword);
|
||||
bool xheader_keyword_deleted_p (const char *kw);
|
||||
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
|
||||
size_t n);
|
||||
|
||||
/* Module system.c */
|
||||
|
||||
void sys_detect_dev_null_output (void);
|
||||
void sys_save_archive_dev_ino (void);
|
||||
void sys_drain_input_pipe (void);
|
||||
void sys_wait_for_child (pid_t);
|
||||
void sys_spawn_shell (void);
|
||||
bool sys_compare_uid (struct stat *a, struct stat *b);
|
||||
bool sys_compare_gid (struct stat *a, struct stat *b);
|
||||
bool sys_file_is_archive (struct tar_stat_info *p);
|
||||
bool sys_compare_links (struct stat *link_data, struct stat *stat_data);
|
||||
int sys_truncate (int fd);
|
||||
pid_t sys_child_open_for_compress (void);
|
||||
pid_t sys_child_open_for_uncompress (void);
|
||||
size_t sys_write_archive_buffer (void);
|
||||
bool sys_get_archive_stat (void);
|
||||
int sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st);
|
||||
void sys_wait_command (void);
|
||||
int sys_exec_info_script (const char **archive_name, int volume_number);
|
||||
|
||||
/* Module compare.c */
|
||||
void report_difference (struct tar_stat_info *st, const char *message, ...);
|
||||
|
||||
/* Module sparse.c */
|
||||
bool sparse_member_p (struct tar_stat_info *st);
|
||||
bool sparse_fixup_header (struct tar_stat_info *st);
|
||||
enum dump_status sparse_dump_file (int, struct tar_stat_info *st);
|
||||
enum dump_status sparse_extract_file (int fd, struct tar_stat_info *st,
|
||||
off_t *size);
|
||||
enum dump_status sparse_skip_file (struct tar_stat_info *st);
|
||||
bool sparse_diff_file (int, struct tar_stat_info *st);
|
||||
|
||||
/* Module utf8.c */
|
||||
bool string_ascii_p (const char *str);
|
||||
bool utf8_convert (bool to_utf, char const *input, char **output);
|
||||
|
||||
/* Module transform.c */
|
||||
void set_transform_expr (const char *expr);
|
||||
bool transform_name (char **pinput);
|
||||
bool transform_name_fp (char **pinput, char *(*fun)(char *));
|
||||
|
||||
|
||||
void update_archive PARAMS ((void));
|
||||
|
||||
1004
src/compare.c
1004
src/compare.c
File diff suppressed because it is too large
Load Diff
2131
src/create.c
2131
src/create.c
File diff suppressed because it is too large
Load Diff
437
src/delete.c
437
src/delete.c
@@ -1,7 +1,5 @@
|
||||
/* Delete entries from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1992, 1994, 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
|
||||
@@ -15,96 +13,97 @@
|
||||
|
||||
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. */
|
||||
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <system-ioctl.h>
|
||||
#include "system.h"
|
||||
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
|
||||
#include "common.h"
|
||||
#include <rmt.h>
|
||||
#include "rmt.h"
|
||||
|
||||
static union block *new_record;
|
||||
static int new_blocks;
|
||||
static bool acting_as_filter;
|
||||
static union block *new_record = NULL;
|
||||
static union block *save_record = NULL;
|
||||
static int records_read = 0;
|
||||
static int new_blocks = 0;
|
||||
static int blocks_needed = 0;
|
||||
|
||||
/* FIXME: This module should not directly handle the following
|
||||
variables, instead, the interface should be cleaned up. */
|
||||
/* FIXME: This module should not directly handle the following three
|
||||
variables, instead, this should be done in buffer.c only. */
|
||||
extern union block *record_start;
|
||||
extern union block *record_end;
|
||||
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. */
|
||||
off_t records_skipped;
|
||||
/*-------------------------------------------------------------------------.
|
||||
| Move archive descriptor by COUNT records worth. If COUNT is positive we |
|
||||
| move forward, else we move negative. If its a tape, MTIOCTOP had better |
|
||||
| work. If its something else, we try to seek on it. If we can't seek, |
|
||||
| we loose! |
|
||||
`-------------------------------------------------------------------------*/
|
||||
|
||||
/* Move archive descriptor by COUNT records worth. If COUNT is
|
||||
positive we move forward, else we move negative. If it's a tape,
|
||||
MTIOCTOP had better work. If it's something else, we try to seek
|
||||
on it. If we can't seek, we lose! */
|
||||
static void
|
||||
move_archive (off_t count)
|
||||
move_archive (int count)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
{
|
||||
struct mtop operation;
|
||||
int status;
|
||||
|
||||
if (count < 0
|
||||
? (operation.mt_op = MTBSR,
|
||||
operation.mt_count = -count,
|
||||
operation.mt_count == -count)
|
||||
: (operation.mt_op = MTFSR,
|
||||
operation.mt_count = count,
|
||||
operation.mt_count == count))
|
||||
if (count > 0)
|
||||
{
|
||||
if (0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
|
||||
return;
|
||||
|
||||
if (errno == EIO
|
||||
&& 0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
|
||||
return;
|
||||
operation.mt_op = MTFSR;
|
||||
operation.mt_count = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
operation.mt_op = MTBSR;
|
||||
operation.mt_count = -count;
|
||||
}
|
||||
|
||||
if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
|
||||
status >= 0)
|
||||
return;
|
||||
|
||||
if (errno == EIO)
|
||||
if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
|
||||
status >= 0)
|
||||
return;
|
||||
}
|
||||
#endif /* MTIOCTOP */
|
||||
|
||||
{
|
||||
off_t position0 = rmtlseek (archive, (off_t) 0, SEEK_CUR);
|
||||
off_t increment = record_size * (off_t) count;
|
||||
off_t position = position0 + increment;
|
||||
off_t position = rmtlseek (archive, 0L, 1);
|
||||
|
||||
if (increment / count != record_size
|
||||
|| (position < position0) != (increment < 0)
|
||||
|| (position = position < 0 ? 0 : position,
|
||||
rmtlseek (archive, position, SEEK_SET) != position))
|
||||
seek_error_details (archive_name_array[0], position);
|
||||
position += record_size * count;
|
||||
|
||||
if (rmtlseek (archive, position, 0) != position)
|
||||
FATAL_ERROR ((0, 0, _("Could not re-position archive file")));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the record which has been filled. If MOVE_BACK_FLAG,
|
||||
backspace to where we started. */
|
||||
/*----------------------------------------------------------------.
|
||||
| Write out the record which has been filled. If MOVE_BACK_FLAG, |
|
||||
| backspace to where we started. |
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
write_record (int move_back_flag)
|
||||
{
|
||||
union block *save_record = record_start;
|
||||
save_record = record_start;
|
||||
record_start = new_record;
|
||||
|
||||
if (acting_as_filter)
|
||||
if (archive == STDIN)
|
||||
{
|
||||
archive = STDOUT_FILENO;
|
||||
archive = STDOUT;
|
||||
flush_write ();
|
||||
archive = STDIN_FILENO;
|
||||
archive = STDIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
move_archive ((records_written + records_skipped) - records_read);
|
||||
move_archive (-(records_read + 1));
|
||||
flush_write ();
|
||||
}
|
||||
|
||||
@@ -114,39 +113,19 @@ write_record (int move_back_flag)
|
||||
{
|
||||
/* Move the tape head back to where we were. */
|
||||
|
||||
if (! acting_as_filter)
|
||||
move_archive (records_read - (records_written + records_skipped));
|
||||
if (archive != STDIN)
|
||||
move_archive (records_read);
|
||||
|
||||
records_read--;
|
||||
}
|
||||
|
||||
blocks_needed = blocking_factor;
|
||||
new_blocks = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
write_recent_blocks (union block *h, size_t blocks)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < blocks; i++)
|
||||
{
|
||||
new_record[new_blocks++] = h[i];
|
||||
if (new_blocks == blocking_factor)
|
||||
write_record (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_recent_bytes (char *data, size_t bytes)
|
||||
{
|
||||
size_t blocks = bytes / BLOCKSIZE;
|
||||
size_t rest = bytes - blocks * BLOCKSIZE;
|
||||
|
||||
write_recent_blocks ((union block *)data, blocks);
|
||||
memcpy (new_record[new_blocks].buffer, data + blocks * BLOCKSIZE, rest);
|
||||
if (rest < BLOCKSIZE)
|
||||
memset (new_record[new_blocks].buffer + rest, 0, BLOCKSIZE - rest);
|
||||
new_blocks++;
|
||||
if (new_blocks == blocking_factor)
|
||||
write_record (1);
|
||||
}
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
|
||||
void
|
||||
delete_archive_members (void)
|
||||
@@ -156,17 +135,16 @@ delete_archive_members (void)
|
||||
|
||||
/* FIXME: Should clean the routine before cleaning these variables :-( */
|
||||
struct name *name;
|
||||
off_t blocks_to_skip = 0;
|
||||
off_t blocks_to_keep = 0;
|
||||
int blocks_to_skip = 0;
|
||||
int blocks_to_keep = 0;
|
||||
int kept_blocks_in_record;
|
||||
|
||||
name_gather ();
|
||||
open_archive (ACCESS_UPDATE);
|
||||
acting_as_filter = strcmp (archive_name_array[0], "-") == 0;
|
||||
|
||||
do
|
||||
while (logical_status == HEADER_STILL_UNREAD)
|
||||
{
|
||||
enum read_header status = read_header (true);
|
||||
enum read_header status = read_header ();
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -174,30 +152,19 @@ delete_archive_members (void)
|
||||
abort ();
|
||||
|
||||
case HEADER_SUCCESS:
|
||||
if ((name = name_scan (current_stat_info.file_name)) == NULL)
|
||||
if (name = name_scan (current_file_name), !name)
|
||||
{
|
||||
skip_member ();
|
||||
set_next_block_after (current_header);
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) (current_stat.st_size));
|
||||
break;
|
||||
}
|
||||
name->found_count++;
|
||||
if (!ISFOUND(name))
|
||||
{
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fall through. */
|
||||
case HEADER_SUCCESS_EXTENDED:
|
||||
logical_status = status;
|
||||
name->found = 1;
|
||||
logical_status = HEADER_SUCCESS;
|
||||
break;
|
||||
|
||||
case HEADER_ZERO_BLOCK:
|
||||
if (ignore_zeros_option)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case HEADER_END_OF_FILE:
|
||||
logical_status = HEADER_END_OF_FILE;
|
||||
break;
|
||||
@@ -211,7 +178,6 @@ delete_archive_members (void)
|
||||
/* Fall through. */
|
||||
|
||||
case HEADER_SUCCESS:
|
||||
case HEADER_SUCCESS_EXTENDED:
|
||||
case HEADER_ZERO_BLOCK:
|
||||
ERROR ((0, 0, _("Skipping to next header")));
|
||||
/* Fall through. */
|
||||
@@ -227,165 +193,144 @@ delete_archive_members (void)
|
||||
|
||||
previous_status = status;
|
||||
}
|
||||
while (logical_status == HEADER_STILL_UNREAD);
|
||||
|
||||
records_skipped = records_read - 1;
|
||||
new_record = xmalloc (record_size);
|
||||
|
||||
if (logical_status == HEADER_SUCCESS
|
||||
|| logical_status == HEADER_SUCCESS_EXTENDED)
|
||||
if (logical_status != HEADER_SUCCESS)
|
||||
{
|
||||
write_archive_to_stdout = false;
|
||||
write_eot ();
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save away blocks before this one in this record. */
|
||||
write_archive_to_stdout = 0;
|
||||
new_record = (union block *) xmalloc ((size_t) record_size);
|
||||
|
||||
new_blocks = current_block - record_start;
|
||||
if (new_blocks)
|
||||
memcpy (new_record, record_start, new_blocks * BLOCKSIZE);
|
||||
/* Save away blocks before this one in this record. */
|
||||
|
||||
if (logical_status == HEADER_SUCCESS)
|
||||
new_blocks = current_block - record_start;
|
||||
blocks_needed = blocking_factor - new_blocks;
|
||||
if (new_blocks)
|
||||
memcpy ((void *) new_record, (void *) record_start,
|
||||
(size_t) (new_blocks * BLOCKSIZE));
|
||||
|
||||
#if 0
|
||||
/* FIXME: Old code, before the goto was inserted. To be redesigned. */
|
||||
set_next_block_after (current_header);
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) (current_stat.st_size));
|
||||
#endif
|
||||
logical_status = HEADER_STILL_UNREAD;
|
||||
goto flush_file;
|
||||
|
||||
/* FIXME: Solaris 2.4 Sun cc (the ANSI one, not the old K&R) says:
|
||||
"delete.c", line 223: warning: loop not entered at top
|
||||
Reported by Bruno Haible. */
|
||||
while (1)
|
||||
{
|
||||
enum read_header status;
|
||||
|
||||
/* Fill in a record. */
|
||||
|
||||
if (current_block == record_end)
|
||||
{
|
||||
/* FIXME: Pheew! This is crufty code! */
|
||||
logical_status = HEADER_STILL_UNREAD;
|
||||
goto flush_file;
|
||||
flush_archive ();
|
||||
records_read++;
|
||||
}
|
||||
status = read_header ();
|
||||
|
||||
if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
if (status == HEADER_END_OF_FILE || status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
logical_status = HEADER_END_OF_FILE;
|
||||
memset (new_record[new_blocks].buffer, 0,
|
||||
(size_t) (BLOCKSIZE * blocks_needed));
|
||||
new_blocks += blocks_needed;
|
||||
blocks_needed = 0;
|
||||
write_record (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: Solaris 2.4 Sun cc (the ANSI one, not the old K&R) says:
|
||||
"delete.c", line 223: warning: loop not entered at top
|
||||
Reported by Bruno Haible. */
|
||||
while (1)
|
||||
if (status == HEADER_FAILURE)
|
||||
{
|
||||
enum read_header status;
|
||||
ERROR ((0, 0, _("Deleting non-header from archive")));
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fill in a record. */
|
||||
/* Found another header. */
|
||||
|
||||
if (name = name_scan (current_file_name), name)
|
||||
{
|
||||
name->found = 1;
|
||||
flush_file:
|
||||
set_next_block_after (current_header);
|
||||
blocks_to_skip = (current_stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
|
||||
while (record_end - current_block <= blocks_to_skip)
|
||||
{
|
||||
blocks_to_skip -= (record_end - current_block);
|
||||
flush_archive ();
|
||||
records_read++;
|
||||
}
|
||||
current_block += blocks_to_skip;
|
||||
blocks_to_skip = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Copy header. */
|
||||
|
||||
new_record[new_blocks] = *current_header;
|
||||
new_blocks++;
|
||||
blocks_needed--;
|
||||
blocks_to_keep
|
||||
= (current_stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
set_next_block_after (current_header);
|
||||
if (blocks_needed == 0)
|
||||
write_record (1);
|
||||
|
||||
/* Copy data. */
|
||||
|
||||
kept_blocks_in_record = record_end - current_block;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
|
||||
while (blocks_to_keep)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (current_block == record_end)
|
||||
flush_archive ();
|
||||
status = read_header (false);
|
||||
|
||||
xheader_decode (¤t_stat_info);
|
||||
|
||||
if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
if (status == HEADER_END_OF_FILE || status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
logical_status = HEADER_END_OF_FILE;
|
||||
break;
|
||||
flush_read ();
|
||||
records_read++;
|
||||
current_block = record_start;
|
||||
kept_blocks_in_record = blocking_factor;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
}
|
||||
count = kept_blocks_in_record;
|
||||
if (count > blocks_needed)
|
||||
count = blocks_needed;
|
||||
|
||||
if (status == HEADER_FAILURE)
|
||||
{
|
||||
ERROR ((0, 0, _("Deleting non-header from archive")));
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
memcpy ((void *) (new_record + new_blocks),
|
||||
(void *) current_block,
|
||||
(size_t) (count * BLOCKSIZE));
|
||||
new_blocks += count;
|
||||
blocks_needed -= count;
|
||||
current_block += count;
|
||||
blocks_to_keep -= count;
|
||||
kept_blocks_in_record -= count;
|
||||
|
||||
/* Found another header. */
|
||||
|
||||
if ((name = name_scan (current_stat_info.file_name)) != NULL)
|
||||
{
|
||||
name->found_count++;
|
||||
if (ISFOUND(name))
|
||||
{
|
||||
flush_file:
|
||||
set_next_block_after (current_header);
|
||||
blocks_to_skip = (current_stat_info.stat.st_size
|
||||
+ BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
|
||||
while (record_end - current_block <= blocks_to_skip)
|
||||
{
|
||||
blocks_to_skip -= (record_end - current_block);
|
||||
flush_archive ();
|
||||
}
|
||||
current_block += blocks_to_skip;
|
||||
blocks_to_skip = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Copy header. */
|
||||
|
||||
if (extended_header.size)
|
||||
{
|
||||
write_recent_bytes (extended_header.buffer,
|
||||
extended_header.size);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_recent_blocks (recent_long_name, recent_long_name_blocks);
|
||||
write_recent_blocks (recent_long_link, recent_long_link_blocks);
|
||||
}
|
||||
new_record[new_blocks] = *current_header;
|
||||
new_blocks++;
|
||||
blocks_to_keep
|
||||
= (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
set_next_block_after (current_header);
|
||||
if (new_blocks == blocking_factor)
|
||||
if (blocks_needed == 0)
|
||||
write_record (1);
|
||||
|
||||
/* Copy data. */
|
||||
|
||||
kept_blocks_in_record = record_end - current_block;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
|
||||
while (blocks_to_keep)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (current_block == record_end)
|
||||
{
|
||||
flush_read ();
|
||||
current_block = record_start;
|
||||
kept_blocks_in_record = blocking_factor;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
}
|
||||
count = kept_blocks_in_record;
|
||||
if (blocking_factor - new_blocks < count)
|
||||
count = blocking_factor - new_blocks;
|
||||
|
||||
if (! count)
|
||||
abort ();
|
||||
|
||||
memcpy (new_record + new_blocks, current_block, count * BLOCKSIZE);
|
||||
new_blocks += count;
|
||||
current_block += count;
|
||||
blocks_to_keep -= count;
|
||||
kept_blocks_in_record -= count;
|
||||
|
||||
if (new_blocks == blocking_factor)
|
||||
write_record (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (logical_status == HEADER_END_OF_FILE)
|
||||
{
|
||||
/* Write the end of tape. FIXME: we can't use write_eot here,
|
||||
as it gets confused when the input is at end of file. */
|
||||
|
||||
int total_zero_blocks = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int zero_blocks = blocking_factor - new_blocks;
|
||||
memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
|
||||
total_zero_blocks += zero_blocks;
|
||||
write_record (total_zero_blocks < 2);
|
||||
}
|
||||
while (total_zero_blocks < 2);
|
||||
}
|
||||
|
||||
if (! acting_as_filter && ! _isrmt (archive))
|
||||
{
|
||||
if (sys_truncate (archive))
|
||||
truncate_warn (archive_name_array[0]);
|
||||
}
|
||||
}
|
||||
free (new_record);
|
||||
|
||||
write_eot ();
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
}
|
||||
|
||||
1636
src/extract.c
1636
src/extract.c
File diff suppressed because it is too large
Load Diff
1969
src/incremen.c
1969
src/incremen.c
File diff suppressed because it is too large
Load Diff
808
src/list.c
808
src/list.c
File diff suppressed because it is too large
Load Diff
@@ -13,9 +13,9 @@
|
||||
|
||||
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. */
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include "system.h"
|
||||
#include "common.h"
|
||||
#include <quotearg.h>
|
||||
|
||||
@@ -34,7 +34,7 @@ struct mangled
|
||||
void
|
||||
extract_mangle (void)
|
||||
{
|
||||
off_t size = current_stat_info.stat.st_size;
|
||||
off_t size = current_stat.st_size;
|
||||
char *buffer = xmalloc ((size_t) (size + 1));
|
||||
char *copy = buffer;
|
||||
char *cursor = buffer;
|
||||
|
||||
870
src/misc.c
870
src/misc.c
File diff suppressed because it is too large
Load Diff
734
src/names.c
734
src/names.c
File diff suppressed because it is too large
Load Diff
576
src/rmt.c
Normal file
576
src/rmt.c
Normal file
@@ -0,0 +1,576 @@
|
||||
/* Remote connection server.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001 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. */
|
||||
|
||||
/* Copyright (C) 1983 Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms are permitted provided
|
||||
that the above copyright notice and this paragraph are duplicated in all
|
||||
such forms and that any documentation, advertising materials, and other
|
||||
materials related to such distribution and use acknowledge that the
|
||||
software was developed by the University of California, Berkeley. The
|
||||
name of the University may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
|
||||
|
||||
#include "system.h"
|
||||
#include <print-copyr.h>
|
||||
#include <localedir.h>
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
#ifndef EXIT_SUCCESS
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
|
||||
/* Maximum size of a string from the requesting program. */
|
||||
#define STRING_SIZE 64
|
||||
|
||||
/* Name of executing program. */
|
||||
const char *program_name;
|
||||
|
||||
/* File descriptor of the tape device, or negative if none open. */
|
||||
static int tape = -1;
|
||||
|
||||
/* Buffer containing transferred data, and its allocated size. */
|
||||
static char *record_buffer;
|
||||
static size_t allocated_size;
|
||||
|
||||
/* Buffer for constructing the reply. */
|
||||
static char reply_buffer[BUFSIZ];
|
||||
|
||||
/* Debugging tools. */
|
||||
|
||||
static FILE *debug_file;
|
||||
|
||||
#define DEBUG(File) \
|
||||
if (debug_file) fprintf(debug_file, File)
|
||||
|
||||
#define DEBUG1(File, Arg) \
|
||||
if (debug_file) fprintf(debug_file, File, Arg)
|
||||
|
||||
#define DEBUG2(File, Arg1, Arg2) \
|
||||
if (debug_file) fprintf(debug_file, File, Arg1, Arg2)
|
||||
|
||||
/* Return an error string, given an error number. */
|
||||
#if HAVE_STRERROR
|
||||
# ifndef strerror
|
||||
char *strerror ();
|
||||
# endif
|
||||
#else
|
||||
static char *
|
||||
private_strerror (int errnum)
|
||||
{
|
||||
extern char *sys_errlist[];
|
||||
extern int sys_nerr;
|
||||
|
||||
if (errnum > 0 && errnum <= sys_nerr)
|
||||
return _(sys_errlist[errnum]);
|
||||
return _("Unknown system error");
|
||||
}
|
||||
# define strerror private_strerror
|
||||
#endif
|
||||
|
||||
static void
|
||||
report_error_message (const char *string)
|
||||
{
|
||||
DEBUG1 ("rmtd: E 0 (%s)\n", string);
|
||||
|
||||
sprintf (reply_buffer, "E0\n%s\n", string);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
}
|
||||
|
||||
static void
|
||||
report_numbered_error (int num)
|
||||
{
|
||||
DEBUG2 ("rmtd: E %d (%s)\n", num, strerror (num));
|
||||
|
||||
sprintf (reply_buffer, "E%d\n%s\n", num, strerror (num));
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
}
|
||||
|
||||
static void
|
||||
get_string (char *string)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = 0; counter < STRING_SIZE; counter++)
|
||||
{
|
||||
if (safe_read (STDIN_FILENO, string + counter, 1) != 1)
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
if (string[counter] == '\n')
|
||||
break;
|
||||
}
|
||||
string[counter] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_record_buffer (size_t size)
|
||||
{
|
||||
if (size <= allocated_size)
|
||||
return;
|
||||
|
||||
if (record_buffer)
|
||||
free (record_buffer);
|
||||
|
||||
record_buffer = malloc (size);
|
||||
|
||||
if (! record_buffer)
|
||||
{
|
||||
DEBUG (_("rmtd: Cannot allocate buffer space\n"));
|
||||
|
||||
report_error_message (N_("Cannot allocate buffer space"));
|
||||
exit (EXIT_FAILURE); /* exit status used to be 4 */
|
||||
}
|
||||
|
||||
allocated_size = size;
|
||||
|
||||
#ifdef SO_RCVBUF
|
||||
while (size > 1024 &&
|
||||
(setsockopt (STDIN_FILENO, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *) &size, sizeof size)
|
||||
< 0))
|
||||
size -= 1024;
|
||||
#else
|
||||
/* FIXME: I do not see any purpose to the following line... Sigh! */
|
||||
size = 1 + ((size - 1) % 1024);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Decode OFLAG_STRING, which represents the 2nd argument to `open'.
|
||||
OFLAG_STRING should contain an optional integer, followed by an optional
|
||||
symbolic representation of an open flag using only '|' to separate its
|
||||
components (e.g. "O_WRONLY|O_CREAT|O_TRUNC"). Prefer the symbolic
|
||||
representation if available, falling back on the numeric
|
||||
representation, or to zero if both formats are absent.
|
||||
|
||||
This function should be the inverse of encode_oflag. The numeric
|
||||
representation is not portable from one host to another, but it is
|
||||
for backward compatibility with old-fashioned clients that do not
|
||||
emit symbolic open flags. */
|
||||
|
||||
static int
|
||||
decode_oflag (char const *oflag_string)
|
||||
{
|
||||
char *oflag_num_end;
|
||||
int numeric_oflag = strtol (oflag_string, &oflag_num_end, 10);
|
||||
int symbolic_oflag = 0;
|
||||
|
||||
oflag_string = oflag_num_end;
|
||||
while (ISSPACE ((unsigned char) *oflag_string))
|
||||
oflag_string++;
|
||||
|
||||
do
|
||||
{
|
||||
struct name_value_pair { char const *name; int value; };
|
||||
static struct name_value_pair const table[] =
|
||||
{
|
||||
#ifdef O_APPEND
|
||||
{"APPEND", O_APPEND},
|
||||
#endif
|
||||
{"CREAT", O_CREAT},
|
||||
#ifdef O_DSYNC
|
||||
{"DSYNC", O_DSYNC},
|
||||
#endif
|
||||
{"EXCL", O_EXCL},
|
||||
#ifdef O_LARGEFILE
|
||||
{"LARGEFILE", O_LARGEFILE}, /* LFS extension for opening large files */
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
{"NOCTTY", O_NOCTTY},
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
{"NONBLOCK", O_NONBLOCK},
|
||||
#endif
|
||||
{"RDONLY", O_RDONLY},
|
||||
{"RDWR", O_RDWR},
|
||||
#ifdef O_RSYNC
|
||||
{"RSYNC", O_RSYNC},
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
{"SYNC", O_SYNC},
|
||||
#endif
|
||||
{"TRUNC", O_TRUNC},
|
||||
{"WRONLY", O_WRONLY}
|
||||
};
|
||||
struct name_value_pair const *t;
|
||||
size_t s;
|
||||
|
||||
if (*oflag_string++ != 'O' || *oflag_string++ != '_')
|
||||
return numeric_oflag;
|
||||
|
||||
for (t = table;
|
||||
(strncmp (oflag_string, t->name, s = strlen (t->name)) != 0
|
||||
|| (oflag_string[s]
|
||||
&& strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
|
||||
oflag_string[s])));
|
||||
t++)
|
||||
if (t == table + sizeof table / sizeof *table - 1)
|
||||
return numeric_oflag;
|
||||
|
||||
symbolic_oflag |= t->value;
|
||||
oflag_string += s;
|
||||
}
|
||||
while (*oflag_string++ == '|');
|
||||
|
||||
return symbolic_oflag;
|
||||
}
|
||||
|
||||
static struct option const long_opts[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
{
|
||||
if (status != EXIT_SUCCESS)
|
||||
fprintf (stderr, _("Try `%s --help' for more information.\n"),
|
||||
program_name);
|
||||
else
|
||||
{
|
||||
printf (_("\
|
||||
Usage: %s [OPTION]\n\
|
||||
Manipulate a tape drive, accepting commands from a remote process.\n\
|
||||
\n\
|
||||
--version Output version info.\n\
|
||||
--help Output this help.\n"),
|
||||
program_name);
|
||||
fputs (_("\nReport bugs to <bug-tar@gnu.org>.\n"), stdout);
|
||||
}
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *const *argv)
|
||||
{
|
||||
char command;
|
||||
ssize_t status;
|
||||
|
||||
/* FIXME: Localization is meaningless, unless --help and --version are
|
||||
locally used. Localization would be best accomplished by the calling
|
||||
tar, on messages found within error packets. */
|
||||
|
||||
program_name = argv[0];
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
switch (getopt_long (argc, argv, "", long_opts, NULL))
|
||||
{
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
|
||||
case 'h':
|
||||
usage (EXIT_SUCCESS);
|
||||
|
||||
case 'v':
|
||||
{
|
||||
printf ("rmt (GNU %s) %s\n", PACKAGE, VERSION);
|
||||
print_copyright ("2001 Free Software Foundation, Inc.");
|
||||
puts (_("\
|
||||
This program comes with NO WARRANTY, to the extent permitted by law.\n\
|
||||
You may redistribute it under the terms of the GNU General Public License;\n\
|
||||
see the file named COPYING for details."));
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
case -1:
|
||||
break;
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
if (optind != argc - 1)
|
||||
usage (EXIT_FAILURE);
|
||||
debug_file = fopen (argv[optind], "w");
|
||||
if (debug_file == 0)
|
||||
{
|
||||
report_numbered_error (errno);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
setbuf (debug_file, 0);
|
||||
}
|
||||
|
||||
top:
|
||||
errno = 0;
|
||||
status = 0;
|
||||
if (safe_read (STDIN_FILENO, &command, 1) != 1)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
/* FIXME: Maybe 'H' and 'V' for --help and --version output? */
|
||||
|
||||
case 'O':
|
||||
{
|
||||
char device_string[STRING_SIZE];
|
||||
char oflag_string[STRING_SIZE];
|
||||
|
||||
get_string (device_string);
|
||||
get_string (oflag_string);
|
||||
DEBUG2 ("rmtd: O %s %s\n", device_string, oflag_string);
|
||||
|
||||
if (tape >= 0)
|
||||
close (tape);
|
||||
|
||||
tape = open (device_string, decode_oflag (oflag_string), MODE_RW);
|
||||
if (tape < 0)
|
||||
goto ioerror;
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
{
|
||||
char device_string[STRING_SIZE];
|
||||
|
||||
get_string (device_string); /* discard */
|
||||
DEBUG ("rmtd: C\n");
|
||||
|
||||
if (close (tape) < 0)
|
||||
goto ioerror;
|
||||
tape = -1;
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
char count_string[STRING_SIZE];
|
||||
char position_string[STRING_SIZE];
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
int whence;
|
||||
char *p;
|
||||
|
||||
get_string (count_string);
|
||||
get_string (position_string);
|
||||
DEBUG2 ("rmtd: L %s %s\n", count_string, position_string);
|
||||
|
||||
/* Parse count_string, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
for (p = count_string; *p == ' ' || *p == '\t'; p++)
|
||||
continue;
|
||||
|
||||
negative = *p == '-';
|
||||
p += negative || *p == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *p++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
{
|
||||
report_error_message (N_("Seek offset out of range"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
switch (atoi (position_string))
|
||||
{
|
||||
case 0: whence = SEEK_SET; break;
|
||||
case 1: whence = SEEK_CUR; break;
|
||||
case 2: whence = SEEK_END; break;
|
||||
default:
|
||||
report_error_message (N_("Seek direction out of range"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
count = lseek (tape, count, whence);
|
||||
if (count < 0)
|
||||
goto ioerror;
|
||||
|
||||
/* Convert count back to string for reply.
|
||||
We can't use sprintf, since off_t might be longer than long. */
|
||||
p = count_string + sizeof count_string;
|
||||
*--p = '\0';
|
||||
do
|
||||
*--p = '0' + (int) (count % 10);
|
||||
while ((count /= 10) != 0);
|
||||
|
||||
DEBUG1 ("rmtd: A %s\n", p);
|
||||
|
||||
sprintf (reply_buffer, "A%s\n", p);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
goto top;
|
||||
}
|
||||
|
||||
case 'W':
|
||||
{
|
||||
char count_string[STRING_SIZE];
|
||||
size_t size;
|
||||
size_t counter;
|
||||
|
||||
get_string (count_string);
|
||||
size = atol (count_string);
|
||||
DEBUG1 ("rmtd: W %s\n", count_string);
|
||||
|
||||
prepare_record_buffer (size);
|
||||
for (counter = 0; counter < size; counter += status)
|
||||
{
|
||||
status = safe_read (STDIN_FILENO, &record_buffer[counter],
|
||||
size - counter);
|
||||
if (status <= 0)
|
||||
{
|
||||
DEBUG (_("rmtd: Premature eof\n"));
|
||||
|
||||
report_error_message (N_("Premature end of file"));
|
||||
exit (EXIT_FAILURE); /* exit status used to be 2 */
|
||||
}
|
||||
}
|
||||
status = full_write (tape, record_buffer, size);
|
||||
if (status < 0)
|
||||
goto ioerror;
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'R':
|
||||
{
|
||||
char count_string[STRING_SIZE];
|
||||
size_t size;
|
||||
|
||||
get_string (count_string);
|
||||
DEBUG1 ("rmtd: R %s\n", count_string);
|
||||
|
||||
size = atol (count_string);
|
||||
prepare_record_buffer (size);
|
||||
status = safe_read (tape, record_buffer, size);
|
||||
if (status < 0)
|
||||
goto ioerror;
|
||||
sprintf (reply_buffer, "A%ld\n", (long) status);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
full_write (STDOUT_FILENO, record_buffer, status);
|
||||
goto top;
|
||||
}
|
||||
|
||||
case 'I':
|
||||
{
|
||||
char operation_string[STRING_SIZE];
|
||||
char count_string[STRING_SIZE];
|
||||
|
||||
get_string (operation_string);
|
||||
get_string (count_string);
|
||||
DEBUG2 ("rmtd: I %s %s\n", operation_string, count_string);
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
{
|
||||
struct mtop mtop;
|
||||
const char *p;
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
|
||||
/* Parse count_string, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
for (p = count_string; *p == ' ' || *p == '\t'; p++)
|
||||
continue;
|
||||
|
||||
negative = *p == '-';
|
||||
p += negative || *p == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *p++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
{
|
||||
report_error_message (N_("Seek offset out of range"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
mtop.mt_count = count;
|
||||
if (mtop.mt_count != count)
|
||||
{
|
||||
report_error_message (N_("Seek offset out of range"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
mtop.mt_op = atoi (operation_string);
|
||||
|
||||
if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
|
||||
goto ioerror;
|
||||
}
|
||||
#endif
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'S': /* status */
|
||||
{
|
||||
DEBUG ("rmtd: S\n");
|
||||
|
||||
#ifdef MTIOCGET
|
||||
{
|
||||
struct mtget operation;
|
||||
|
||||
if (ioctl (tape, MTIOCGET, (char *) &operation) < 0)
|
||||
goto ioerror;
|
||||
status = sizeof operation;
|
||||
sprintf (reply_buffer, "A%ld\n", (long) status);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
full_write (STDOUT_FILENO, (char *) &operation, sizeof operation);
|
||||
}
|
||||
#endif
|
||||
goto top;
|
||||
}
|
||||
|
||||
default:
|
||||
DEBUG1 (_("rmtd: Garbage command %c\n"), command);
|
||||
|
||||
report_error_message (N_("Garbage command"));
|
||||
exit (EXIT_FAILURE); /* exit status used to be 3 */
|
||||
}
|
||||
|
||||
respond:
|
||||
DEBUG1 ("rmtd: A %ld\n", (long) status);
|
||||
|
||||
sprintf (reply_buffer, "A%ld\n", (long) status);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
goto top;
|
||||
|
||||
ioerror:
|
||||
report_numbered_error (errno);
|
||||
goto top;
|
||||
}
|
||||
93
src/rmt.h
Normal file
93
src/rmt.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Definitions for communicating with a remote tape drive.
|
||||
Copyright 1988, 1992, 1996, 1997, 2001 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. */
|
||||
|
||||
extern char *rmt_path__;
|
||||
|
||||
int rmt_open__ PARAMS ((const char *, int, int, const char *));
|
||||
int rmt_close__ PARAMS ((int));
|
||||
ssize_t rmt_read__ PARAMS ((int, char *, size_t));
|
||||
ssize_t rmt_write__ PARAMS ((int, char *, size_t));
|
||||
off_t rmt_lseek__ PARAMS ((int, off_t, int));
|
||||
int rmt_ioctl__ PARAMS ((int, int, char *));
|
||||
|
||||
/* A filename is remote if it contains a colon not preceded by a slash,
|
||||
to take care of `/:/' which is a shorthand for `/.../<CELL-NAME>/fs'
|
||||
on machines running OSF's Distributing Computing Environment (DCE) and
|
||||
Distributed File System (DFS). However, when --force-local, a
|
||||
filename is never remote. */
|
||||
|
||||
#define _remdev(Path) \
|
||||
(!force_local_option && (rmt_path__ = strchr (Path, ':')) \
|
||||
&& rmt_path__ > (Path) && ! memchr (Path, rmt_path__ - (Path), '/'))
|
||||
|
||||
#define _isrmt(Fd) \
|
||||
((Fd) >= __REM_BIAS)
|
||||
|
||||
#define __REM_BIAS (1 << 30)
|
||||
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 01000
|
||||
#endif
|
||||
|
||||
#define rmtopen(Path, Oflag, Mode, Command) \
|
||||
(_remdev (Path) ? rmt_open__ (Path, Oflag, __REM_BIAS, Command) \
|
||||
: open (Path, Oflag, Mode))
|
||||
|
||||
#define rmtaccess(Path, Amode) \
|
||||
(_remdev (Path) ? 0 : access (Path, Amode))
|
||||
|
||||
#define rmtstat(Path, Buffer) \
|
||||
(_remdev (Path) ? (errno = EOPNOTSUPP), -1 : stat (Path, Buffer))
|
||||
|
||||
#define rmtcreat(Path, Mode, Command) \
|
||||
(_remdev (Path) \
|
||||
? rmt_open__ (Path, 1 | O_CREAT, __REM_BIAS, Command) \
|
||||
: creat (Path, Mode))
|
||||
|
||||
#define rmtlstat(Path, Buffer) \
|
||||
(_remdev (Path) ? (errno = EOPNOTSUPP), -1 : lstat (Path, Buffer))
|
||||
|
||||
#define rmtread(Fd, Buffer, Length) \
|
||||
(_isrmt (Fd) ? rmt_read__ (Fd - __REM_BIAS, Buffer, Length) \
|
||||
: safe_read (Fd, Buffer, Length))
|
||||
|
||||
#define rmtwrite(Fd, Buffer, Length) \
|
||||
(_isrmt (Fd) ? rmt_write__ (Fd - __REM_BIAS, Buffer, Length) \
|
||||
: full_write (Fd, Buffer, Length))
|
||||
|
||||
#define rmtlseek(Fd, Offset, Where) \
|
||||
(_isrmt (Fd) ? rmt_lseek__ (Fd - __REM_BIAS, Offset, Where) \
|
||||
: lseek (Fd, Offset, Where))
|
||||
|
||||
#define rmtclose(Fd) \
|
||||
(_isrmt (Fd) ? rmt_close__ (Fd - __REM_BIAS) : close (Fd))
|
||||
|
||||
#define rmtioctl(Fd, Request, Argument) \
|
||||
(_isrmt (Fd) ? rmt_ioctl__ (Fd - __REM_BIAS, Request, Argument) \
|
||||
: ioctl (Fd, Request, Argument))
|
||||
|
||||
#define rmtdup(Fd) \
|
||||
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : dup (Fd))
|
||||
|
||||
#define rmtfstat(Fd, Buffer) \
|
||||
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : fstat (Fd, Buffer))
|
||||
|
||||
#define rmtfcntl(Fd, Command, Argument) \
|
||||
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : fcntl (Fd, Command, Argument))
|
||||
|
||||
#define rmtisatty(Fd) \
|
||||
(_isrmt (Fd) ? 0 : isatty (Fd))
|
||||
718
src/rtapelib.c
Normal file
718
src/rtapelib.c
Normal file
@@ -0,0 +1,718 @@
|
||||
/* Functions for communicating with a remote tape drive.
|
||||
|
||||
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001 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. */
|
||||
|
||||
/* The man page rmt(8) for /etc/rmt documents the remote mag tape protocol
|
||||
which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
|
||||
The author of the routines I'm including originally wrote his code just
|
||||
based on the man page, and it didn't work, so he went to the rdump source
|
||||
to figure out why. The only thing he had to change was to check for the
|
||||
'F' return code in addition to the 'E', and to separate the various
|
||||
arguments with \n instead of a space. I personally don't think that this
|
||||
is much of a problem, but I wanted to point it out. -- Arnold Robbins
|
||||
|
||||
Originally written by Jeff Lee, modified some by Arnold Robbins. Redone
|
||||
as a library that can replace open, read, write, etc., by Fred Fish, with
|
||||
some additional work by Arnold Robbins. Modified to make all rmt* calls
|
||||
into macros for speed by Jay Fenlason. Use -DWITH_REXEC for rexec
|
||||
code, courtesy of Dan Kegel. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
/* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h,
|
||||
3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */
|
||||
|
||||
#ifndef EOPNOTSUPP
|
||||
# if HAVE_NET_ERRNO_H
|
||||
# include <net/errno.h>
|
||||
# endif
|
||||
# if HAVE_SYS_INET_H
|
||||
# include <sys/inet.h>
|
||||
# endif
|
||||
# ifndef EOPNOTSUPP
|
||||
# define EOPNOTSUPP EINVAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "rmt.h"
|
||||
|
||||
/* Exit status if exec errors. */
|
||||
#define EXIT_ON_EXEC_ERROR 128
|
||||
|
||||
/* FIXME: Size of buffers for reading and writing commands to rmt. */
|
||||
#define COMMAND_BUFFER_SIZE 64
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
# define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
/* FIXME: Maximum number of simultaneous remote tape connections. */
|
||||
#define MAXUNIT 4
|
||||
|
||||
#define PREAD 0 /* read file descriptor from pipe() */
|
||||
#define PWRITE 1 /* write file descriptor from pipe() */
|
||||
|
||||
/* Return the parent's read side of remote tape connection Fd. */
|
||||
#define READ_SIDE(Fd) (from_remote[Fd][PREAD])
|
||||
|
||||
/* Return the parent's write side of remote tape connection Fd. */
|
||||
#define WRITE_SIDE(Fd) (to_remote[Fd][PWRITE])
|
||||
|
||||
/* The pipes for receiving data from remote tape drives. */
|
||||
static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
/* The pipes for sending data to remote tape drives. */
|
||||
static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
/* Temporary variable used by macros in rmt.h. */
|
||||
char *rmt_path__;
|
||||
|
||||
|
||||
/* Close remote tape connection HANDLE, and reset errno to ERRNO_VALUE. */
|
||||
static void
|
||||
_rmt_shutdown (int handle, int errno_value)
|
||||
{
|
||||
close (READ_SIDE (handle));
|
||||
close (WRITE_SIDE (handle));
|
||||
READ_SIDE (handle) = -1;
|
||||
WRITE_SIDE (handle) = -1;
|
||||
errno = errno_value;
|
||||
}
|
||||
|
||||
/* Attempt to perform the remote tape command specified in BUFFER on
|
||||
remote tape connection HANDLE. Return 0 if successful, -1 on
|
||||
error. */
|
||||
static int
|
||||
do_command (int handle, const char *buffer)
|
||||
{
|
||||
/* Save the current pipe handler and try to make the request. */
|
||||
|
||||
size_t length = strlen (buffer);
|
||||
RETSIGTYPE (*pipe_handler) () = signal (SIGPIPE, SIG_IGN);
|
||||
ssize_t written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
|
||||
if (written == length)
|
||||
return 0;
|
||||
|
||||
/* Something went wrong. Close down and go home. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_status_string (int handle, char *command_buffer)
|
||||
{
|
||||
char *cursor;
|
||||
int counter;
|
||||
|
||||
/* Read the reply command line. */
|
||||
|
||||
for (counter = 0, cursor = command_buffer;
|
||||
counter < COMMAND_BUFFER_SIZE;
|
||||
counter++, cursor++)
|
||||
{
|
||||
if (safe_read (READ_SIDE (handle), cursor, 1) != 1)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
if (*cursor == '\n')
|
||||
{
|
||||
*cursor = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == COMMAND_BUFFER_SIZE)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the return status. */
|
||||
|
||||
for (cursor = command_buffer; *cursor; cursor++)
|
||||
if (*cursor != ' ')
|
||||
break;
|
||||
|
||||
if (*cursor == 'E' || *cursor == 'F')
|
||||
{
|
||||
errno = atoi (cursor + 1);
|
||||
|
||||
/* Skip the error message line. */
|
||||
|
||||
/* FIXME: there is better to do than merely ignoring error messages
|
||||
coming from the remote end. Translate them, too... */
|
||||
|
||||
{
|
||||
char character;
|
||||
|
||||
while (safe_read (READ_SIDE (handle), &character, 1) == 1)
|
||||
if (character == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
if (*cursor == 'F')
|
||||
_rmt_shutdown (handle, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for mis-synced pipes. */
|
||||
|
||||
if (*cursor != 'A')
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Got an `A' (success) response. */
|
||||
|
||||
return cursor + 1;
|
||||
}
|
||||
|
||||
/* Read and return the status from remote tape connection HANDLE. If
|
||||
an error occurred, return -1 and set errno. */
|
||||
static long
|
||||
get_status (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
return status ? atol (status) : -1L;
|
||||
}
|
||||
|
||||
static off_t
|
||||
get_status_off (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
|
||||
if (! status)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
/* Parse status, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
|
||||
for (; *status == ' ' || *status == '\t'; status++)
|
||||
continue;
|
||||
|
||||
negative = *status == '-';
|
||||
status += negative || *status == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *status++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
return -1;
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute /etc/rmt as user USER on remote system HOST using rexec.
|
||||
Return a file descriptor of a bidirectional socket for stdin and
|
||||
stdout. If USER is zero, use the current username.
|
||||
|
||||
By default, this code is not used, since it requires that the user
|
||||
have a .netrc file in his/her home directory, or that the
|
||||
application designer be willing to have rexec prompt for login and
|
||||
password info. This may be unacceptable, and .rhosts files for use
|
||||
with rsh are much more common on BSD systems. */
|
||||
static int
|
||||
_rmt_rexec (char *host, char *user)
|
||||
{
|
||||
int saved_stdin = dup (STDIN_FILENO);
|
||||
int saved_stdout = dup (STDOUT_FILENO);
|
||||
struct servent *rexecserv;
|
||||
int result;
|
||||
|
||||
/* When using cpio -o < filename, stdin is no longer the tty. But the
|
||||
rexec subroutine reads the login and the passwd on stdin, to allow
|
||||
remote execution of the command. So, reopen stdin and stdout on
|
||||
/dev/tty before the rexec and give them back their original value
|
||||
after. */
|
||||
|
||||
if (! freopen ("/dev/tty", "r", stdin))
|
||||
freopen ("/dev/null", "r", stdin);
|
||||
if (! freopen ("/dev/tty", "w", stdout))
|
||||
freopen ("/dev/null", "w", stdout);
|
||||
|
||||
if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv)
|
||||
error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available"));
|
||||
|
||||
result = rexec (&host, rexecserv->s_port, user, 0, "/etc/rmt", 0);
|
||||
if (fclose (stdin) == EOF)
|
||||
error (0, errno, _("stdin"));
|
||||
fdopen (saved_stdin, "r");
|
||||
if (fclose (stdout) == EOF)
|
||||
error (0, errno, _("stdout"));
|
||||
fdopen (saved_stdout, "w");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* WITH_REXEC */
|
||||
|
||||
/* Place into BUF a string representing OFLAG, which must be suitable
|
||||
as argument 2 of `open'. BUF must be large enough to hold the
|
||||
result. This function should generate a string that decode_oflag
|
||||
can parse. */
|
||||
static void
|
||||
encode_oflag (char *buf, int oflag)
|
||||
{
|
||||
sprintf (buf, "%d ", oflag);
|
||||
|
||||
switch (oflag & O_ACCMODE)
|
||||
{
|
||||
case O_RDONLY: strcat (buf, "O_RDONLY"); break;
|
||||
case O_RDWR: strcat (buf, "O_RDWR"); break;
|
||||
case O_WRONLY: strcat (buf, "O_WRONLY"); break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
#ifdef O_APPEND
|
||||
if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
|
||||
#endif
|
||||
if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
|
||||
#ifdef O_DSYNC
|
||||
if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
|
||||
#endif
|
||||
if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
|
||||
#ifdef O_LARGEFILE
|
||||
if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
|
||||
#endif
|
||||
#ifdef O_RSYNC
|
||||
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
|
||||
#endif
|
||||
if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
|
||||
}
|
||||
|
||||
/* Open a file (a magnetic tape device?) on the system specified in
|
||||
PATH, as the given user. PATH has the form `[USER@]HOST:FILE'.
|
||||
OPEN_MODE is O_RDONLY, O_WRONLY, etc. If successful, return the
|
||||
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
|
||||
error, return -1. */
|
||||
int
|
||||
rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
|
||||
{
|
||||
int remote_pipe_number; /* pseudo, biased file descriptor */
|
||||
char *path_copy ; /* copy of path string */
|
||||
char *remote_host; /* remote host name */
|
||||
char *remote_file; /* remote file name (often a device) */
|
||||
char *remote_user; /* remote user name */
|
||||
|
||||
/* Find an unused pair of file descriptors. */
|
||||
|
||||
for (remote_pipe_number = 0;
|
||||
remote_pipe_number < MAXUNIT;
|
||||
remote_pipe_number++)
|
||||
if (READ_SIDE (remote_pipe_number) == -1
|
||||
&& WRITE_SIDE (remote_pipe_number) == -1)
|
||||
break;
|
||||
|
||||
if (remote_pipe_number == MAXUNIT)
|
||||
{
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pull apart the system and device, and optional user. */
|
||||
|
||||
{
|
||||
char *cursor;
|
||||
|
||||
path_copy = xstrdup (path);
|
||||
remote_host = path_copy;
|
||||
remote_user = 0;
|
||||
remote_file = 0;
|
||||
|
||||
for (cursor = path_copy; *cursor; cursor++)
|
||||
switch (*cursor)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
/* Do not allow newlines in the path, since the protocol
|
||||
uses newline delimiters. */
|
||||
free (path_copy);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
case '@':
|
||||
if (!remote_user)
|
||||
{
|
||||
remote_user = remote_host;
|
||||
*cursor = '\0';
|
||||
remote_host = cursor + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (!remote_file)
|
||||
{
|
||||
*cursor = '\0';
|
||||
remote_file = cursor + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Should somewhat validate the decoding, here. */
|
||||
|
||||
if (remote_user && *remote_user == '\0')
|
||||
remote_user = 0;
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute the remote command using rexec. */
|
||||
|
||||
READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
|
||||
if (READ_SIDE (remote_pipe_number) < 0)
|
||||
{
|
||||
int e = errno;
|
||||
free (path_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);
|
||||
|
||||
#else /* not WITH_REXEC */
|
||||
{
|
||||
const char *remote_shell_basename;
|
||||
pid_t status;
|
||||
|
||||
/* Identify the remote command to be executed. */
|
||||
|
||||
if (!remote_shell)
|
||||
{
|
||||
#ifdef REMOTE_SHELL
|
||||
remote_shell = REMOTE_SHELL;
|
||||
#else
|
||||
free (path_copy);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
remote_shell_basename = base_name (remote_shell);
|
||||
|
||||
/* Set up the pipes for the `rsh' command, and fork. */
|
||||
|
||||
if (pipe (to_remote[remote_pipe_number]) == -1
|
||||
|| pipe (from_remote[remote_pipe_number]) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (path_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fork ();
|
||||
if (status == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (path_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
/* Child. */
|
||||
|
||||
close (STDIN_FILENO);
|
||||
dup (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
close (STDOUT_FILENO);
|
||||
dup (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (from_remote[remote_pipe_number][PREAD]);
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
#if !MSDOS
|
||||
setuid (getuid ());
|
||||
setgid (getgid ());
|
||||
#endif
|
||||
|
||||
if (remote_user)
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
"-l", remote_user, "/etc/rmt", (char *) 0);
|
||||
else
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
"/etc/rmt", (char *) 0);
|
||||
|
||||
/* Bad problems if we get here. */
|
||||
|
||||
/* In a previous version, _exit was used here instead of exit. */
|
||||
error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
|
||||
}
|
||||
|
||||
/* Parent. */
|
||||
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
}
|
||||
#endif /* not WITH_REXEC */
|
||||
|
||||
/* Attempt to open the tape device. */
|
||||
|
||||
{
|
||||
size_t remote_file_len = strlen (remote_file);
|
||||
char *command_buffer = xmalloc (remote_file_len + 1000);
|
||||
sprintf (command_buffer, "O%s\n", remote_file);
|
||||
encode_oflag (command_buffer + remote_file_len + 2, open_mode);
|
||||
strcat (command_buffer, "\n");
|
||||
if (do_command (remote_pipe_number, command_buffer) == -1
|
||||
|| get_status (remote_pipe_number) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (command_buffer);
|
||||
free (path_copy);
|
||||
_rmt_shutdown (remote_pipe_number, e);
|
||||
return -1;
|
||||
}
|
||||
free (command_buffer);
|
||||
}
|
||||
|
||||
free (path_copy);
|
||||
return remote_pipe_number + bias;
|
||||
}
|
||||
|
||||
/* Close remote tape connection HANDLE and shut down. Return 0 if
|
||||
successful, -1 on error. */
|
||||
int
|
||||
rmt_close__ (int handle)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (do_command (handle, "C\n") == -1)
|
||||
return -1;
|
||||
|
||||
status = get_status (handle);
|
||||
_rmt_shutdown (handle, errno);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE.
|
||||
Return the number of bytes read on success, -1 on error. */
|
||||
ssize_t
|
||||
rmt_read__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
ssize_t status, rlen;
|
||||
size_t counter;
|
||||
|
||||
sprintf (command_buffer, "R%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1
|
||||
|| (status = get_status (handle)) == -1)
|
||||
return -1;
|
||||
|
||||
for (counter = 0; counter < status; counter += rlen, buffer += rlen)
|
||||
{
|
||||
rlen = safe_read (READ_SIDE (handle), buffer, status - counter);
|
||||
if (rlen <= 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Write LENGTH bytes from BUFFER to remote tape connection HANDLE.
|
||||
Return the number of bytes written on success, -1 on error. */
|
||||
ssize_t
|
||||
rmt_write__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
RETSIGTYPE (*pipe_handler) ();
|
||||
size_t written;
|
||||
|
||||
sprintf (command_buffer, "W%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
if (written == length)
|
||||
return get_status (handle);
|
||||
|
||||
/* Write error. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Perform an imitation lseek operation on remote tape connection
|
||||
HANDLE. Return the new file offset if successful, -1 if on error. */
|
||||
off_t
|
||||
rmt_lseek__ (int handle, off_t offset, int whence)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset;
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (offset < 0)
|
||||
*--p = '-';
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET: whence = 0; break;
|
||||
case SEEK_CUR: whence = 1; break;
|
||||
case SEEK_END: whence = 2; break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
sprintf (command_buffer, "L%s\n%d\n", p, whence);
|
||||
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status_off (handle);
|
||||
}
|
||||
|
||||
/* Perform a raw tape operation on remote tape connection HANDLE.
|
||||
Return the results of the ioctl, or -1 on error. */
|
||||
int
|
||||
rmt_ioctl__ (int handle, int operation, char *argument)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
default:
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
case MTIOCTOP:
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = (((struct mtop *) argument)->mt_count < 0
|
||||
? - (uintmax_t) ((struct mtop *) argument)->mt_count
|
||||
: (uintmax_t) ((struct mtop *) argument)->mt_count);
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (((struct mtop *) argument)->mt_count < 0)
|
||||
*--p = '-';
|
||||
|
||||
/* MTIOCTOP is the easy one. Nothing is transferred in binary. */
|
||||
|
||||
sprintf (command_buffer, "I%d\n%s\n",
|
||||
((struct mtop *) argument)->mt_op, p);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status (handle);
|
||||
}
|
||||
#endif /* MTIOCTOP */
|
||||
|
||||
#ifdef MTIOCGET
|
||||
case MTIOCGET:
|
||||
{
|
||||
ssize_t status;
|
||||
ssize_t counter;
|
||||
|
||||
/* Grab the status and read it directly into the structure. This
|
||||
assumes that the status buffer is not padded and that 2 shorts
|
||||
fit in a long without any word alignment problems; i.e., the
|
||||
whole struct is contiguous. NOTE - this is probably NOT a good
|
||||
assumption. */
|
||||
|
||||
if (do_command (handle, "S") == -1
|
||||
|| (status = get_status (handle), status == -1))
|
||||
return -1;
|
||||
|
||||
for (; status > 0; status -= counter, argument += counter)
|
||||
{
|
||||
counter = safe_read (READ_SIDE (handle), argument, status);
|
||||
if (counter <= 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for byte position. mt_type (or mt_model) is a small integer
|
||||
field (normally) so we will check its magnitude. If it is larger
|
||||
than 256, we will assume that the bytes are swapped and go through
|
||||
and reverse all the bytes. */
|
||||
|
||||
if (((struct mtget *) argument)->MTIO_CHECK_FIELD < 256)
|
||||
return 0;
|
||||
|
||||
for (counter = 0; counter < status; counter += 2)
|
||||
{
|
||||
char copy = argument[counter];
|
||||
|
||||
argument[counter] = argument[counter + 1];
|
||||
argument[counter + 1] = copy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MTIOCGET */
|
||||
|
||||
}
|
||||
}
|
||||
1169
src/sparse.c
1169
src/sparse.c
File diff suppressed because it is too large
Load Diff
844
src/system.c
844
src/system.c
@@ -1,844 +0,0 @@
|
||||
/* System-dependent calls for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <getline.h>
|
||||
#include <setenv.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <rmt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if MSDOS
|
||||
|
||||
bool
|
||||
sys_get_archive_stat (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
sys_file_is_archive (struct tar_stat_info *p)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
sys_save_archive_dev_ino (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
sys_detect_dev_null_output (void)
|
||||
{
|
||||
static char const dev_null[] = "nul";
|
||||
|
||||
dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
|
||||
|| (! _isrmt (archive)));
|
||||
}
|
||||
|
||||
void
|
||||
sys_drain_input_pipe (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_for_child (pid_t child_pid)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
sys_spawn_shell (void)
|
||||
{
|
||||
spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0);
|
||||
}
|
||||
|
||||
/* stat() in djgpp's C library gives a constant number of 42 as the
|
||||
uid and gid of a file. So, comparing an FTP'ed archive just after
|
||||
unpack would fail on MSDOS. */
|
||||
|
||||
bool
|
||||
sys_compare_uid (struct stat *a, struct stat *b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
sys_compare_gid (struct stat *a, struct stat *b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
sys_compare_links (struct stat *link_data, struct stat *stat_data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
sys_truncate (int fd)
|
||||
{
|
||||
return write (fd, "", 0);
|
||||
}
|
||||
|
||||
size_t
|
||||
sys_write_archive_buffer (void)
|
||||
{
|
||||
return full_write (archive, record_start->buffer, record_size);
|
||||
}
|
||||
|
||||
/* Set ARCHIVE for writing, then compressing an archive. */
|
||||
void
|
||||
sys_child_open_for_compress (void)
|
||||
{
|
||||
FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
|
||||
}
|
||||
|
||||
/* Set ARCHIVE for uncompressing, then reading an archive. */
|
||||
void
|
||||
sys_child_open_for_uncompress (void)
|
||||
{
|
||||
FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
extern union block *record_start; /* FIXME */
|
||||
|
||||
static struct stat archive_stat; /* stat block for archive file */
|
||||
|
||||
bool
|
||||
sys_get_archive_stat (void)
|
||||
{
|
||||
return fstat (archive, &archive_stat) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
sys_file_is_archive (struct tar_stat_info *p)
|
||||
{
|
||||
return (ar_dev && p->stat.st_dev == ar_dev && p->stat.st_ino == ar_ino);
|
||||
}
|
||||
|
||||
/* Save archive file inode and device numbers */
|
||||
void
|
||||
sys_save_archive_dev_ino (void)
|
||||
{
|
||||
if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
|
||||
{
|
||||
ar_dev = archive_stat.st_dev;
|
||||
ar_ino = archive_stat.st_ino;
|
||||
}
|
||||
else
|
||||
ar_dev = 0;
|
||||
}
|
||||
|
||||
/* Detect if outputting to "/dev/null". */
|
||||
void
|
||||
sys_detect_dev_null_output (void)
|
||||
{
|
||||
static char const dev_null[] = "/dev/null";
|
||||
struct stat dev_null_stat;
|
||||
|
||||
dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
|
||||
|| (! _isrmt (archive)
|
||||
&& S_ISCHR (archive_stat.st_mode)
|
||||
&& stat (dev_null, &dev_null_stat) == 0
|
||||
&& archive_stat.st_dev == dev_null_stat.st_dev
|
||||
&& archive_stat.st_ino == dev_null_stat.st_ino));
|
||||
}
|
||||
|
||||
/* Manage to fully drain a pipe we might be reading, so to not break it on
|
||||
the producer after the EOF block. FIXME: one of these days, GNU tar
|
||||
might become clever enough to just stop working, once there is no more
|
||||
work to do, we might have to revise this area in such time. */
|
||||
|
||||
void
|
||||
sys_drain_input_pipe (void)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
if (access_mode == ACCESS_READ
|
||||
&& ! _isrmt (archive)
|
||||
&& (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
|
||||
while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
|
||||
&& r != SAFE_READ_ERROR)
|
||||
continue;
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_for_child (pid_t child_pid)
|
||||
{
|
||||
if (child_pid)
|
||||
{
|
||||
int wait_status;
|
||||
|
||||
while (waitpid (child_pid, &wait_status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (use_compress_program_option);
|
||||
break;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
ERROR ((0, 0, _("Child died with signal %d"),
|
||||
WTERMSIG (wait_status)));
|
||||
else if (WEXITSTATUS (wait_status) != 0)
|
||||
ERROR ((0, 0, _("Child returned status %d"),
|
||||
WEXITSTATUS (wait_status)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_spawn_shell (void)
|
||||
{
|
||||
pid_t child;
|
||||
const char *shell = getenv ("SHELL");
|
||||
if (! shell)
|
||||
shell = "/bin/sh";
|
||||
child = xfork ();
|
||||
if (child == 0)
|
||||
{
|
||||
execlp (shell, "-sh", "-i", (char *) 0);
|
||||
exec_fatal (shell);
|
||||
}
|
||||
else
|
||||
{
|
||||
int wait_status;
|
||||
while (waitpid (child, &wait_status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (shell);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
sys_compare_uid (struct stat *a, struct stat *b)
|
||||
{
|
||||
return a->st_uid == b->st_uid;
|
||||
}
|
||||
|
||||
bool
|
||||
sys_compare_gid (struct stat *a, struct stat *b)
|
||||
{
|
||||
return a->st_gid == b->st_gid;
|
||||
}
|
||||
|
||||
bool
|
||||
sys_compare_links (struct stat *link_data, struct stat *stat_data)
|
||||
{
|
||||
return stat_data->st_dev == link_data->st_dev
|
||||
&& stat_data->st_ino == link_data->st_ino;
|
||||
}
|
||||
|
||||
int
|
||||
sys_truncate (int fd)
|
||||
{
|
||||
off_t pos = lseek (fd, (off_t) 0, SEEK_CUR);
|
||||
return pos < 0 ? -1 : ftruncate (fd, pos);
|
||||
}
|
||||
|
||||
/* Return nonzero if NAME is the name of a regular file, or if the file
|
||||
does not exist (so it would be created as a regular file). */
|
||||
static int
|
||||
is_regular_file (const char *name)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat (name, &stbuf) == 0)
|
||||
return S_ISREG (stbuf.st_mode);
|
||||
else
|
||||
return errno == ENOENT;
|
||||
}
|
||||
|
||||
size_t
|
||||
sys_write_archive_buffer (void)
|
||||
{
|
||||
return rmtwrite (archive, record_start->buffer, record_size);
|
||||
}
|
||||
|
||||
#define PREAD 0 /* read file descriptor from pipe() */
|
||||
#define PWRITE 1 /* write file descriptor from pipe() */
|
||||
|
||||
/* Duplicate file descriptor FROM into becoming INTO.
|
||||
INTO is closed first and has to be the next available slot. */
|
||||
static void
|
||||
xdup2 (int from, int into)
|
||||
{
|
||||
if (from != into)
|
||||
{
|
||||
int status = close (into);
|
||||
|
||||
if (status != 0 && errno != EBADF)
|
||||
{
|
||||
int e = errno;
|
||||
FATAL_ERROR ((0, e, _("Cannot close")));
|
||||
}
|
||||
status = dup (from);
|
||||
if (status != into)
|
||||
{
|
||||
if (status < 0)
|
||||
{
|
||||
int e = errno;
|
||||
FATAL_ERROR ((0, e, _("Cannot dup")));
|
||||
}
|
||||
abort ();
|
||||
}
|
||||
xclose (from);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set ARCHIVE for writing, then compressing an archive. */
|
||||
pid_t
|
||||
sys_child_open_for_compress (void)
|
||||
{
|
||||
int parent_pipe[2];
|
||||
int child_pipe[2];
|
||||
pid_t grandchild_pid;
|
||||
pid_t child_pid;
|
||||
int wait_status;
|
||||
|
||||
xpipe (parent_pipe);
|
||||
child_pid = xfork ();
|
||||
|
||||
if (child_pid > 0)
|
||||
{
|
||||
/* The parent tar is still here! Just clean up. */
|
||||
|
||||
archive = parent_pipe[PWRITE];
|
||||
xclose (parent_pipe[PREAD]);
|
||||
return child_pid;
|
||||
}
|
||||
|
||||
/* The new born child tar is here! */
|
||||
|
||||
program_name = _("tar (child)");
|
||||
|
||||
xdup2 (parent_pipe[PREAD], STDIN_FILENO);
|
||||
xclose (parent_pipe[PWRITE]);
|
||||
|
||||
/* Check if we need a grandchild tar. This happens only if either:
|
||||
a) the file is to be accessed by rmt: compressor doesn't know how;
|
||||
b) the file is not a plain file. */
|
||||
|
||||
if (!_remdev (archive_name_array[0])
|
||||
&& is_regular_file (archive_name_array[0]))
|
||||
{
|
||||
if (backup_option)
|
||||
maybe_backup_file (archive_name_array[0], 1);
|
||||
|
||||
/* We don't need a grandchild tar. Open the archive and launch the
|
||||
compressor. */
|
||||
if (strcmp (archive_name_array[0], "-"))
|
||||
{
|
||||
archive = creat (archive_name_array[0], MODE_RW);
|
||||
if (archive < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
if (backup_option)
|
||||
undo_last_backup ();
|
||||
errno = saved_errno;
|
||||
open_fatal (archive_name_array[0]);
|
||||
}
|
||||
xdup2 (archive, STDOUT_FILENO);
|
||||
}
|
||||
execlp (use_compress_program_option, use_compress_program_option, NULL);
|
||||
exec_fatal (use_compress_program_option);
|
||||
}
|
||||
|
||||
/* We do need a grandchild tar. */
|
||||
|
||||
xpipe (child_pipe);
|
||||
grandchild_pid = xfork ();
|
||||
|
||||
if (grandchild_pid == 0)
|
||||
{
|
||||
/* The newborn grandchild tar is here! Launch the compressor. */
|
||||
|
||||
program_name = _("tar (grandchild)");
|
||||
|
||||
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
|
||||
xclose (child_pipe[PREAD]);
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
(char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
}
|
||||
|
||||
/* The child tar is still here! */
|
||||
|
||||
/* Prepare for reblocking the data from the compressor into the archive. */
|
||||
|
||||
xdup2 (child_pipe[PREAD], STDIN_FILENO);
|
||||
xclose (child_pipe[PWRITE]);
|
||||
|
||||
if (strcmp (archive_name_array[0], "-") == 0)
|
||||
archive = STDOUT_FILENO;
|
||||
else
|
||||
{
|
||||
archive = rmtcreat (archive_name_array[0], MODE_RW, rsh_command_option);
|
||||
if (archive < 0)
|
||||
open_fatal (archive_name_array[0]);
|
||||
}
|
||||
|
||||
/* Let's read out of the stdin pipe and write an archive. */
|
||||
|
||||
while (1)
|
||||
{
|
||||
size_t status = 0;
|
||||
char *cursor;
|
||||
size_t length;
|
||||
|
||||
/* Assemble a record. */
|
||||
|
||||
for (length = 0, cursor = record_start->buffer;
|
||||
length < record_size;
|
||||
length += status, cursor += status)
|
||||
{
|
||||
size_t size = record_size - length;
|
||||
|
||||
status = safe_read (STDIN_FILENO, cursor, size);
|
||||
if (status == SAFE_READ_ERROR)
|
||||
read_fatal (use_compress_program_option);
|
||||
if (status == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the record. */
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
/* We hit the end of the file. Write last record at
|
||||
full length, as the only role of the grandchild is
|
||||
doing proper reblocking. */
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
memset (record_start->buffer + length, 0, record_size - length);
|
||||
status = sys_write_archive_buffer ();
|
||||
if (status != record_size)
|
||||
archive_write_error (status);
|
||||
}
|
||||
|
||||
/* There is nothing else to read, break out. */
|
||||
break;
|
||||
}
|
||||
|
||||
status = sys_write_archive_buffer ();
|
||||
if (status != record_size)
|
||||
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);
|
||||
}
|
||||
|
||||
/* Set ARCHIVE for uncompressing, then reading an archive. */
|
||||
pid_t
|
||||
sys_child_open_for_uncompress (void)
|
||||
{
|
||||
int parent_pipe[2];
|
||||
int child_pipe[2];
|
||||
pid_t grandchild_pid;
|
||||
pid_t child_pid;
|
||||
int wait_status;
|
||||
|
||||
xpipe (parent_pipe);
|
||||
child_pid = xfork ();
|
||||
|
||||
if (child_pid > 0)
|
||||
{
|
||||
/* The parent tar is still here! Just clean up. */
|
||||
|
||||
archive = parent_pipe[PREAD];
|
||||
xclose (parent_pipe[PWRITE]);
|
||||
return child_pid;
|
||||
}
|
||||
|
||||
/* The newborn child tar is here! */
|
||||
|
||||
program_name = _("tar (child)");
|
||||
|
||||
xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
|
||||
xclose (parent_pipe[PREAD]);
|
||||
|
||||
/* Check if we need a grandchild tar. This happens only if either:
|
||||
a) we're reading stdin: to force unblocking;
|
||||
b) the file is to be accessed by rmt: compressor doesn't know how;
|
||||
c) the file is not a plain file. */
|
||||
|
||||
if (strcmp (archive_name_array[0], "-") != 0
|
||||
&& !_remdev (archive_name_array[0])
|
||||
&& is_regular_file (archive_name_array[0]))
|
||||
{
|
||||
/* We don't need a grandchild tar. Open the archive and lauch the
|
||||
uncompressor. */
|
||||
|
||||
archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);
|
||||
if (archive < 0)
|
||||
open_fatal (archive_name_array[0]);
|
||||
xdup2 (archive, STDIN_FILENO);
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
"-d", (char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
}
|
||||
|
||||
/* We do need a grandchild tar. */
|
||||
|
||||
xpipe (child_pipe);
|
||||
grandchild_pid = xfork ();
|
||||
|
||||
if (grandchild_pid == 0)
|
||||
{
|
||||
/* The newborn grandchild tar is here! Launch the uncompressor. */
|
||||
|
||||
program_name = _("tar (grandchild)");
|
||||
|
||||
xdup2 (child_pipe[PREAD], STDIN_FILENO);
|
||||
xclose (child_pipe[PWRITE]);
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
"-d", (char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
}
|
||||
|
||||
/* The child tar is still here! */
|
||||
|
||||
/* Prepare for unblocking the data from the archive into the
|
||||
uncompressor. */
|
||||
|
||||
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
|
||||
xclose (child_pipe[PREAD]);
|
||||
|
||||
if (strcmp (archive_name_array[0], "-") == 0)
|
||||
archive = STDIN_FILENO;
|
||||
else
|
||||
archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
|
||||
MODE_RW, rsh_command_option);
|
||||
if (archive < 0)
|
||||
open_fatal (archive_name_array[0]);
|
||||
|
||||
/* Let's read the archive and pipe it into stdout. */
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *cursor;
|
||||
size_t maximum;
|
||||
size_t count;
|
||||
size_t status;
|
||||
|
||||
clear_read_error_count ();
|
||||
|
||||
error_loop:
|
||||
status = rmtread (archive, record_start->buffer, record_size);
|
||||
if (status == SAFE_READ_ERROR)
|
||||
{
|
||||
archive_read_error ();
|
||||
goto error_loop;
|
||||
}
|
||||
if (status == 0)
|
||||
break;
|
||||
cursor = record_start->buffer;
|
||||
maximum = status;
|
||||
while (maximum)
|
||||
{
|
||||
count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
|
||||
if (full_write (STDOUT_FILENO, cursor, count) != count)
|
||||
write_error (use_compress_program_option);
|
||||
cursor += count;
|
||||
maximum -= count;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dec_to_env (char *envar, uintmax_t num)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
char *numstr;
|
||||
|
||||
numstr = STRINGIFY_BIGINT (num, buf);
|
||||
if (setenv (envar, numstr, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
time_to_env (char *envar, struct timespec t)
|
||||
{
|
||||
char buf[TIMESPEC_STRSIZE_BOUND];
|
||||
if (setenv (envar, code_timespec (t, buf), 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
oct_to_env (char *envar, unsigned long num)
|
||||
{
|
||||
char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
|
||||
|
||||
snprintf (buf, sizeof buf, "0%lo", num);
|
||||
if (setenv (envar, buf, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
str_to_env (char *envar, char const *str)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
if (setenv (envar, str, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
else
|
||||
unsetenv (envar);
|
||||
}
|
||||
|
||||
static void
|
||||
chr_to_env (char *envar, char c)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
if (setenv (envar, buf, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
stat_to_env (char *name, char type, struct tar_stat_info *st)
|
||||
{
|
||||
str_to_env ("TAR_VERSION", PACKAGE_VERSION);
|
||||
chr_to_env ("TAR_FILETYPE", type);
|
||||
oct_to_env ("TAR_MODE", st->stat.st_mode);
|
||||
str_to_env ("TAR_FILENAME", name);
|
||||
str_to_env ("TAR_REALNAME", st->file_name);
|
||||
str_to_env ("TAR_UNAME", st->uname);
|
||||
str_to_env ("TAR_GNAME", st->gname);
|
||||
time_to_env ("TAR_ATIME", st->atime);
|
||||
time_to_env ("TAR_MTIME", st->mtime);
|
||||
time_to_env ("TAR_CTIME", st->ctime);
|
||||
dec_to_env ("TAR_SIZE", st->stat.st_size);
|
||||
dec_to_env ("TAR_UID", st->stat.st_uid);
|
||||
dec_to_env ("TAR_GID", st->stat.st_gid);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 'b':
|
||||
case 'c':
|
||||
dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev));
|
||||
dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev));
|
||||
unsetenv ("TAR_LINKNAME");
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'h':
|
||||
unsetenv ("TAR_MINOR");
|
||||
unsetenv ("TAR_MAJOR");
|
||||
str_to_env ("TAR_LINKNAME", st->link_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
unsetenv ("TAR_MINOR");
|
||||
unsetenv ("TAR_MAJOR");
|
||||
unsetenv ("TAR_LINKNAME");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static pid_t pid;
|
||||
static RETSIGTYPE (*pipe_handler) (int sig);
|
||||
|
||||
int
|
||||
sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
|
||||
{
|
||||
int p[2];
|
||||
char *argv[4];
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
xclose (p[PREAD]);
|
||||
return p[PWRITE];
|
||||
}
|
||||
|
||||
/* Child */
|
||||
xdup2 (p[PREAD], STDIN_FILENO);
|
||||
xclose (p[PWRITE]);
|
||||
|
||||
stat_to_env (file_name, typechar, st);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = to_command_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv ("/bin/sh", argv);
|
||||
|
||||
exec_fatal (file_name);
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_command (void)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (pid < 0)
|
||||
return;
|
||||
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
pid = -1;
|
||||
waitpid_error (to_command_option);
|
||||
return;
|
||||
}
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
if (!ignore_command_error_option && WEXITSTATUS (status))
|
||||
ERROR ((0, 0, _("%lu: Child returned status %d"),
|
||||
(unsigned long) pid, WEXITSTATUS (status)));
|
||||
}
|
||||
else if (WIFSIGNALED (status))
|
||||
{
|
||||
WARN ((0, 0, _("%lu: Child terminated on signal %d"),
|
||||
(unsigned long) pid, WTERMSIG (status)));
|
||||
}
|
||||
else
|
||||
ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
|
||||
(unsigned long) pid));
|
||||
|
||||
pid = -1;
|
||||
}
|
||||
|
||||
int
|
||||
sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
int p[2];
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* Master */
|
||||
|
||||
int rc;
|
||||
int status;
|
||||
char *buf;
|
||||
size_t size = 0;
|
||||
FILE *fp;
|
||||
|
||||
xclose (p[PWRITE]);
|
||||
fp = fdopen (p[PREAD], "r");
|
||||
rc = getline (&buf, &size, fp);
|
||||
fclose (fp);
|
||||
|
||||
if (rc > 0 && buf[rc-1] == '\n')
|
||||
buf[--rc] = 0;
|
||||
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (info_script_option);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
if (WEXITSTATUS (status) == 0 && rc > 0)
|
||||
*archive_name = buf;
|
||||
else
|
||||
free (buf);
|
||||
return WEXITSTATUS (status);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Child */
|
||||
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
|
||||
setenv ("TAR_ARCHIVE", *archive_name, 1);
|
||||
setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
|
||||
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
|
||||
setenv ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
archive_format : current_format), 1);
|
||||
|
||||
xclose (p[PREAD]);
|
||||
xdup2 (p[PWRITE], 3);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*) info_script_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (info_script_option);
|
||||
}
|
||||
|
||||
|
||||
#endif /* not MSDOS */
|
||||
492
src/system.h
Normal file
492
src/system.h
Normal file
@@ -0,0 +1,492 @@
|
||||
/* System dependent definitions for GNU tar.
|
||||
Copyright (C) 1994, 1995, 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 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Declare alloca. AIX requires this to be the first thing in the file. */
|
||||
|
||||
#if __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
#else
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Declare a generic pointer type. */
|
||||
#if __STDC__ || defined(__TURBOC__)
|
||||
# define voidstar void *
|
||||
#else
|
||||
# define voidstar char *
|
||||
#endif
|
||||
|
||||
/* Declare ISASCII. */
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#if STDC_HEADERS
|
||||
# define ISASCII(Char) 1
|
||||
#else
|
||||
# ifdef isascii
|
||||
# define ISASCII(Char) isascii (Char)
|
||||
# else
|
||||
# if HAVE_ISASCII
|
||||
# define ISASCII(Char) isascii (Char)
|
||||
# else
|
||||
# define ISASCII(Char) 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare string and memory handling routines. Take care that an ANSI
|
||||
string.h and pre-ANSI memory.h might conflict, and that memory.h and
|
||||
strings.h conflict on some systems. */
|
||||
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
#else
|
||||
# include <strings.h>
|
||||
# ifndef strchr
|
||||
# define strchr index
|
||||
# endif
|
||||
# ifndef strrchr
|
||||
# define strrchr rindex
|
||||
# endif
|
||||
# ifndef memcpy
|
||||
# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
|
||||
# endif
|
||||
# ifndef memcmp
|
||||
# define memcmp(Src1, Src2, Num) bcmp (Src1, Src2, Num)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare errno. */
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Declare open parameters. */
|
||||
|
||||
#if HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
/* Pick only one of the next three: */
|
||||
#ifndef O_RDONLY
|
||||
# define O_RDONLY 0 /* only allow read */
|
||||
#endif
|
||||
#ifndef O_WRONLY
|
||||
# define O_WRONLY 1 /* only allow write */
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
# define O_RDWR 2 /* both are allowed */
|
||||
#endif
|
||||
/* The rest can be OR-ed in to the above: */
|
||||
#ifndef O_NDELAY
|
||||
# define O_NDELAY 4 /* don't block on opening devices */
|
||||
#endif
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 8 /* create file if needed */
|
||||
#endif
|
||||
#ifndef O_EXCL
|
||||
# define O_EXCL 16 /* file cannot already exist */
|
||||
#endif
|
||||
#ifndef O_TRUNC
|
||||
# define O_TRUNC 32 /* truncate file on open */
|
||||
#endif
|
||||
#ifndef O_APPEND
|
||||
# define O_APPEND 64 /* always write at end of file */
|
||||
#endif
|
||||
/* MS-DOG forever, with my love! */
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
/* Emulate System V 3-argument open call */
|
||||
#if EMUL_OPEN3
|
||||
# define open open3
|
||||
#endif
|
||||
|
||||
/* Declare file status routines and bits. */
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef S_ISLNK
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#if STAT_MACROS_BROKEN
|
||||
# undef S_ISBLK
|
||||
# undef S_ISCHR
|
||||
# undef S_ISDIR
|
||||
# undef S_ISFIFO
|
||||
# undef S_ISLNK
|
||||
# undef S_ISMPB
|
||||
# undef S_ISMPC
|
||||
# undef S_ISNWK
|
||||
# undef S_ISREG
|
||||
# undef S_ISSOCK
|
||||
#endif
|
||||
|
||||
/* On MSDOS, there are missing things from <sys/stat.h>. */
|
||||
#if MSDOS
|
||||
# define S_ISUID 0
|
||||
# define S_ISGID 0
|
||||
# define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG /* POSIX.1 stat stuff missing */
|
||||
# define mode_t unsigned short
|
||||
#endif
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
# define S_ISBLK(Mode) (((Mode) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
# define S_ISCHR(Mode) (((Mode) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
# define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
# define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
# define S_ISFIFO(Mode) (((Mode) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
# define S_ISLNK(Mode) (((Mode) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
# define S_ISSOCK(Mode) (((Mode) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
# define S_ISMPB(Mode) (((Mode) & S_IFMT) == S_IFMPB)
|
||||
# define S_ISMPC(Mode) (((Mode) & S_IFMT) == S_IFMPC)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
# define S_ISNWK(Mode) (((Mode) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
|
||||
#if !HAVE_MKFIFO
|
||||
# define mkfifo(Path, Mode) (mknod (Path, (Mode) | S_IFIFO, 0))
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISCTG) && defined(S_IFCTG) /* contiguous file */
|
||||
# define S_ISCTG(Mode) (((Mode) & S_IFMT) == S_IFCTG)
|
||||
#endif
|
||||
#if !defined(S_ISVTX)
|
||||
# define S_ISVTX 0001000
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* Declare make device, major and minor. Since major is a function on
|
||||
SVR4, we have to resort to GOT_MAJOR instead of just testing if
|
||||
major is #define'd. */
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
# include <sys/mkdev.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#if MAJOR_IN_SYSMACROS
|
||||
# include <sys/sysmacros.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
/* Some <sys/types.h> defines the macros. */
|
||||
#ifdef major
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# if MSDOS
|
||||
# define major(Device) (Device)
|
||||
# define minor(Device) (Device)
|
||||
# define makedev(Major, Minor) (((Major) << 8) | (Minor))
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For HP-UX before HP-UX 8, major/minor are not in <sys/sysmacros.h>. */
|
||||
#ifndef GOT_MAJOR
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# include <sys/mknod.h>
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# define major(Device) (((Device) >> 8) & 0xff)
|
||||
# define minor(Device) ((Device) & 0xff)
|
||||
# define makedev(Major, Minor) (((Major) << 8) | (Minor))
|
||||
#endif
|
||||
|
||||
#undef GOT_MAJOR
|
||||
|
||||
/* Declare directory reading routines and structures. */
|
||||
|
||||
#if __TURBOC__
|
||||
# include "msd_dir.h"
|
||||
# define NAMLEN(dirent) ((dirent)->d_namlen)
|
||||
#else
|
||||
# if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) (strlen((dirent)->d_name))
|
||||
# else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) ((dirent)->d_namlen)
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare wait status. */
|
||||
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_UNION_WAIT
|
||||
# define WAIT_T union wait
|
||||
# ifndef WTERMSIG
|
||||
# define WTERMSIG(Status) ((Status).w_termsig)
|
||||
# endif
|
||||
# ifndef WCOREDUMP
|
||||
# define WCOREDUMP(Status) ((Status).w_coredump)
|
||||
# endif
|
||||
# ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(Status) ((Status).w_retcode)
|
||||
# endif
|
||||
#else
|
||||
# define WAIT_T int
|
||||
# ifndef WTERMSIG
|
||||
# define WTERMSIG(Status) ((Status) & 0x7f)
|
||||
# endif
|
||||
# ifndef WCOREDUMP
|
||||
# define WCOREDUMP(Status) ((Status) & 0x80)
|
||||
# endif
|
||||
# ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(Status) (((Status) >> 8) & 0xff)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef WIFSTOPPED
|
||||
# define WIFSTOPPED(Status) (WTERMSIG(Status) == 0x7f)
|
||||
#endif
|
||||
#ifndef WIFSIGNALED
|
||||
# define WIFSIGNALED(Status) (WTERMSIG(Status) != 0)
|
||||
#endif
|
||||
#ifndef WIFEXITED
|
||||
# define WIFEXITED(Status) (WTERMSIG(Status) == 0)
|
||||
#endif
|
||||
|
||||
/* FIXME: It is wrong to use BLOCKSIZE for buffers when the logical block
|
||||
size is greater than 512 bytes; so ST_BLKSIZE code below, in preparation
|
||||
for some cleanup in this area, later. */
|
||||
|
||||
/* Get or fake the disk device blocksize. Usually defined by sys/param.h
|
||||
(if at all). */
|
||||
|
||||
#if !defined(DEV_BSIZE) && defined(BSIZE)
|
||||
# define DEV_BSIZE BSIZE
|
||||
#endif
|
||||
#if !defined(DEV_BSIZE) && defined(BBSIZE) /* SGI */
|
||||
# define DEV_BSIZE BBSIZE
|
||||
#endif
|
||||
#ifndef DEV_BSIZE
|
||||
# define DEV_BSIZE 4096
|
||||
#endif
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_BLKSIZE gives the
|
||||
optimal I/O blocksize for the file, in bytes. Some systems, like
|
||||
Sequents, return st_blksize of 0 on pipes. */
|
||||
|
||||
#if !HAVE_ST_BLKSIZE
|
||||
# define ST_BLKSIZE(Statbuf) DEV_BSIZE
|
||||
#else
|
||||
# define ST_BLKSIZE(Statbuf) \
|
||||
((Statbuf).st_blksize > 0 ? (Statbuf).st_blksize : DEV_BSIZE)
|
||||
#endif
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_NBLOCKS gives the
|
||||
number of 512-byte blocks in the file (including indirect blocks).
|
||||
fileblocks.c uses BSIZE. HP-UX counts st_blocks in 1024-byte units,
|
||||
this loses when mixing HP-UX and BSD filesystems with NFS. AIX PS/2
|
||||
counts st_blocks in 4K units. */
|
||||
|
||||
#if !HAVE_ST_BLOCKS
|
||||
# if defined(_POSIX_SOURCE) || !defined(BSIZE)
|
||||
# define ST_NBLOCKS(Statbuf) (((Statbuf).st_size + 512 - 1) / 512)
|
||||
# else
|
||||
# define ST_NBLOCKS(Statbuf) (st_blocks ((Statbuf).st_size))
|
||||
# endif
|
||||
#else
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_blocks * 2)
|
||||
# else
|
||||
# if defined(_AIX) && defined(_I386)
|
||||
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_blocks * 8)
|
||||
# else
|
||||
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_blocks)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
|
||||
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
|
||||
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
|
||||
seems that the rest use <sys/mtio.h>, which itself requires other files,
|
||||
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
|
||||
|
||||
#if HAVE_SYS_GENTAPE_H
|
||||
# include <sys/gentape.h>
|
||||
#else
|
||||
# if HAVE_SYS_TAPE_H
|
||||
# if HAVE_SYS_DEVICE_H
|
||||
# include <sys/device.h>
|
||||
# endif
|
||||
# if HAVE_SYS_BUF_H
|
||||
# include <sys/buf.h>
|
||||
# endif
|
||||
# if HAVE_SYS_TPRINTF_H
|
||||
# include <sys/tprintf.h>
|
||||
# endif
|
||||
# include <sys/tape.h>
|
||||
# else
|
||||
# if HAVE_SYS_MTIO_H
|
||||
# include <sys/ioctl.h>
|
||||
# if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
# endif
|
||||
# if HAVE_SYS_IO_TRIOCTL_H
|
||||
# include <sys/io/trioctl.h>
|
||||
# endif
|
||||
# include <sys/mtio.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare standard functions. */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
voidstar malloc ();
|
||||
voidstar realloc ();
|
||||
# if HAVE_GETCWD
|
||||
char *getcwd ();
|
||||
# endif
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _POSIX_VERSION
|
||||
# if MSDOS
|
||||
# include <io.h>
|
||||
# else
|
||||
off_t lseek ();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <pathmax.h>
|
||||
|
||||
#if WITH_DMALLOC
|
||||
# undef HAVE_VALLOC
|
||||
# define DMALLOC_FUNC_CHECK
|
||||
# include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
/* Prototypes for external functions. */
|
||||
|
||||
#ifndef PARAMS
|
||||
# if PROTOTYPES
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
#if !HAVE_SETLOCALE
|
||||
# define setlocale(Category, Locale)
|
||||
#endif
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define bindtextdomain(Domain, Directory)
|
||||
# define textdomain(Domain)
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
#define N_(Text) Text
|
||||
|
||||
/* Library modules. */
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#if !HAVE_STRSTR
|
||||
char *strstr PARAMS ((const char *, const char *));
|
||||
#endif
|
||||
|
||||
#if HAVE_VALLOC
|
||||
# ifndef valloc
|
||||
voidstar valloc PARAMS ((size_t));
|
||||
# endif
|
||||
#else
|
||||
# define valloc(Size) malloc (Size)
|
||||
#endif
|
||||
|
||||
voidstar xmalloc PARAMS ((size_t));
|
||||
voidstar xrealloc PARAMS ((voidstar, size_t));
|
||||
char *xstrdup PARAMS ((const char *));
|
||||
179
src/tar.h
179
src/tar.h
@@ -1,7 +1,7 @@
|
||||
/* GNU tar Archive Format description.
|
||||
|
||||
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
2000, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
|
||||
1997, 2000, 2001 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
|
||||
@@ -15,7 +15,18 @@
|
||||
|
||||
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. */
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* If OLDGNU_COMPATIBILITY is not zero, tar produces archives which, by
|
||||
default, are readable by older versions of GNU tar. This can be
|
||||
overriden by using --posix; in this case, POSIXLY_CORRECT in environment
|
||||
may be set for enforcing stricter conformance. If OLDGNU_COMPATIBILITY
|
||||
is zero or undefined, tar will eventually produces archives which, by
|
||||
default, POSIX compatible; then either using --posix or defining
|
||||
POSIXLY_CORRECT enforces stricter conformance.
|
||||
|
||||
This #define will disappear in a few years. FP, June 1995. */
|
||||
#define OLDGNU_COMPATIBILITY 1
|
||||
|
||||
/* tar Header Block, from POSIX 1003.1-1990. */
|
||||
|
||||
@@ -58,10 +69,6 @@ struct posix_header
|
||||
#define FIFOTYPE '6' /* FIFO special */
|
||||
#define CONTTYPE '7' /* reserved */
|
||||
|
||||
#define XHDTYPE 'x' /* Extended header referring to the
|
||||
next file in the archive */
|
||||
#define XGLTYPE 'g' /* Global extended header */
|
||||
|
||||
/* Bits used in the mode field, values in octal. */
|
||||
#define TSUID 04000 /* set UID on execution */
|
||||
#define TSGID 02000 /* set GID on execution */
|
||||
@@ -115,6 +122,26 @@ struct sparse
|
||||
#define SPARSES_IN_OLDGNU_HEADER 4
|
||||
#define SPARSES_IN_SPARSE_HEADER 21
|
||||
|
||||
/* The GNU extra header contains some information GNU tar needs, but not
|
||||
foreseen in POSIX header format. It is only used after a POSIX header
|
||||
(and never with old GNU headers), and immediately follows this POSIX
|
||||
header, when typeflag is a letter rather than a digit, so signaling a GNU
|
||||
extension. */
|
||||
|
||||
struct extra_header
|
||||
{ /* byte offset */
|
||||
char atime[12]; /* 0 */
|
||||
char ctime[12]; /* 12 */
|
||||
char offset[12]; /* 24 */
|
||||
char realsize[12]; /* 36 */
|
||||
char longnames[4]; /* 48 */
|
||||
char unused_pad1[68]; /* 52 */
|
||||
struct sparse sp[SPARSES_IN_EXTRA_HEADER];
|
||||
/* 120 */
|
||||
char isextended; /* 504 */
|
||||
/* 505 */
|
||||
};
|
||||
|
||||
/* Extension header for sparse files, used immediately after the GNU extra
|
||||
header, and used only if all sparse information cannot fit into that
|
||||
extra header. There might even be many such extension headers, one after
|
||||
@@ -139,17 +166,15 @@ struct sparse_header
|
||||
struct oldgnu_header
|
||||
{ /* byte offset */
|
||||
char unused_pad1[345]; /* 0 */
|
||||
char atime[12]; /* 345 Incr. archive: atime of the file */
|
||||
char ctime[12]; /* 357 Incr. archive: ctime of the file */
|
||||
char offset[12]; /* 369 Multivolume archive: the offset of
|
||||
the start of this volume */
|
||||
char longnames[4]; /* 381 Not used */
|
||||
char atime[12]; /* 345 */
|
||||
char ctime[12]; /* 357 */
|
||||
char offset[12]; /* 369 */
|
||||
char longnames[4]; /* 381 */
|
||||
char unused_pad2; /* 385 */
|
||||
struct sparse sp[SPARSES_IN_OLDGNU_HEADER];
|
||||
/* 386 */
|
||||
char isextended; /* 482 Sparse file: Extension sparse header
|
||||
follows */
|
||||
char realsize[12]; /* 483 Sparse file: Real size*/
|
||||
char isextended; /* 482 */
|
||||
char realsize[12]; /* 483 */
|
||||
/* 495 */
|
||||
};
|
||||
|
||||
@@ -160,12 +185,7 @@ struct oldgnu_header
|
||||
#define OLDGNU_MAGIC "ustar " /* 7 chars and a null */
|
||||
|
||||
/* The standards committee allows only capital A through capital Z for
|
||||
user-defined expansion. Other letters in use include:
|
||||
|
||||
'A' Solaris Access Control List
|
||||
'E' Solaris Extended Attribute File
|
||||
'I' Inode only, as in 'star'
|
||||
'X' POSIX 1003.1-2001 eXtended (VU version) */
|
||||
user-defined expansion. */
|
||||
|
||||
/* This is a dir entry that contains the names of files that were in the
|
||||
dir at the time the dump was made. */
|
||||
@@ -189,62 +209,6 @@ struct oldgnu_header
|
||||
/* This file is a tape/volume header. Ignore it on extraction. */
|
||||
#define GNUTYPE_VOLHDR 'V'
|
||||
|
||||
/* Solaris extended header */
|
||||
#define SOLARIS_XHDTYPE 'X'
|
||||
|
||||
/* J@"org Schilling star header */
|
||||
|
||||
struct star_header
|
||||
{ /* byte offset */
|
||||
char name[100]; /* 0 */
|
||||
char mode[8]; /* 100 */
|
||||
char uid[8]; /* 108 */
|
||||
char gid[8]; /* 116 */
|
||||
char size[12]; /* 124 */
|
||||
char mtime[12]; /* 136 */
|
||||
char chksum[8]; /* 148 */
|
||||
char typeflag; /* 156 */
|
||||
char linkname[100]; /* 157 */
|
||||
char magic[6]; /* 257 */
|
||||
char version[2]; /* 263 */
|
||||
char uname[32]; /* 265 */
|
||||
char gname[32]; /* 297 */
|
||||
char devmajor[8]; /* 329 */
|
||||
char devminor[8]; /* 337 */
|
||||
char prefix[131]; /* 345 */
|
||||
char atime[12]; /* 476 */
|
||||
char ctime[12]; /* 488 */
|
||||
/* 500 */
|
||||
};
|
||||
|
||||
#define SPARSES_IN_STAR_HEADER 4
|
||||
#define SPARSES_IN_STAR_EXT_HEADER 21
|
||||
|
||||
struct star_in_header
|
||||
{
|
||||
char fill[345]; /* 0 Everything that is before t_prefix */
|
||||
char prefix[1]; /* 345 t_name prefix */
|
||||
char fill2; /* 346 */
|
||||
char fill3[8]; /* 347 */
|
||||
char isextended; /* 355 */
|
||||
struct sparse sp[SPARSES_IN_STAR_HEADER]; /* 356 */
|
||||
char realsize[12]; /* 452 Actual size of the file */
|
||||
char offset[12]; /* 464 Offset of multivolume contents */
|
||||
char atime[12]; /* 476 */
|
||||
char ctime[12]; /* 488 */
|
||||
char mfill[8]; /* 500 */
|
||||
char xmagic[4]; /* 508 "tar" */
|
||||
};
|
||||
|
||||
struct star_ext_header
|
||||
{
|
||||
struct sparse sp[SPARSES_IN_STAR_EXT_HEADER];
|
||||
char isextended;
|
||||
};
|
||||
|
||||
/* END */
|
||||
|
||||
|
||||
/* tar Header Block, overall structure. */
|
||||
|
||||
/* tar files are made in basic blocks of this size. */
|
||||
@@ -255,70 +219,17 @@ enum archive_format
|
||||
DEFAULT_FORMAT, /* format to be decided later */
|
||||
V7_FORMAT, /* old V7 tar format */
|
||||
OLDGNU_FORMAT, /* GNU format as per before tar 1.12 */
|
||||
USTAR_FORMAT, /* POSIX.1-1988 (ustar) format */
|
||||
POSIX_FORMAT, /* POSIX.1-2001 format */
|
||||
STAR_FORMAT, /* Star format defined in 1994 */
|
||||
GNU_FORMAT /* Same as OLDGNU_FORMAT with one exception:
|
||||
see FIXME note for to_chars() function
|
||||
(create.c:189) */
|
||||
};
|
||||
|
||||
/* Information about a sparse file. */
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
size_t numbytes;
|
||||
};
|
||||
|
||||
struct tar_stat_info
|
||||
{
|
||||
char *orig_file_name; /* name of file read from the archive header */
|
||||
char *file_name; /* name of file for the current archive entry
|
||||
after being normalized. */
|
||||
bool had_trailing_slash; /* true if the current archive entry had a
|
||||
trailing slash before it was normalized. */
|
||||
char *link_name; /* name of link for the current archive entry. */
|
||||
|
||||
char *uname; /* user name of owner */
|
||||
char *gname; /* group name of owner */
|
||||
struct stat stat; /* regular filesystem stat */
|
||||
|
||||
/* STAT doesn't always have access, data modification, and status
|
||||
change times in a convenient form, so store them separately. */
|
||||
struct timespec atime;
|
||||
struct timespec mtime;
|
||||
struct timespec ctime;
|
||||
|
||||
off_t archive_file_size; /* Size of file as stored in the archive.
|
||||
Equals stat.st_size for non-sparse files */
|
||||
|
||||
bool is_sparse; /* Is the file sparse */
|
||||
|
||||
/* For sparse files: */
|
||||
unsigned sparse_major;
|
||||
unsigned sparse_minor;
|
||||
size_t sparse_map_avail; /* Index to the first unused element in
|
||||
sparse_map array. Zero if the file is
|
||||
not sparse */
|
||||
size_t sparse_map_size; /* Size of the sparse map */
|
||||
struct sp_array *sparse_map;
|
||||
|
||||
/* For dumpdirs */
|
||||
bool is_dumpdir; /* Is the member a dumpdir? */
|
||||
bool skipped; /* The member contents is already read
|
||||
(for GNUTYPE_DUMPDIR) */
|
||||
char *dumpdir; /* Contents of the dump directory */
|
||||
POSIX_FORMAT, /* restricted, pure POSIX format */
|
||||
GNU_FORMAT /* POSIX format with GNU extensions */
|
||||
};
|
||||
|
||||
union block
|
||||
{
|
||||
char buffer[BLOCKSIZE];
|
||||
struct posix_header header;
|
||||
struct star_header star_header;
|
||||
struct extra_header extra_header;
|
||||
struct oldgnu_header oldgnu_header;
|
||||
struct sparse_header sparse_header;
|
||||
struct star_in_header star_in_header;
|
||||
struct star_ext_header star_ext_header;
|
||||
};
|
||||
|
||||
|
||||
/* End of Format description. */
|
||||
|
||||
527
src/transform.c
527
src/transform.c
@@ -1,527 +0,0 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2006 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <regex.h>
|
||||
#include "common.h"
|
||||
|
||||
static enum transform_type
|
||||
{
|
||||
transform_none,
|
||||
transform_first,
|
||||
transform_global
|
||||
}
|
||||
transform_type = transform_none;
|
||||
static unsigned match_number = 0;
|
||||
static regex_t regex;
|
||||
static struct obstack stk;
|
||||
|
||||
enum replace_segm_type
|
||||
{
|
||||
segm_literal, /* Literal segment */
|
||||
segm_backref, /* Back-reference segment */
|
||||
segm_case_ctl /* Case control segment (GNU extension) */
|
||||
};
|
||||
|
||||
enum case_ctl_type
|
||||
{
|
||||
ctl_stop, /* Stop case conversion */
|
||||
ctl_upcase_next,/* Turn the next character to uppercase */
|
||||
ctl_locase_next,/* Turn the next character to lowercase */
|
||||
ctl_upcase, /* Turn the replacement to uppercase until ctl_stop */
|
||||
ctl_locase /* Turn the replacement to lowercase until ctl_stop */
|
||||
};
|
||||
|
||||
struct replace_segm
|
||||
{
|
||||
struct replace_segm *next;
|
||||
enum replace_segm_type type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
char *ptr;
|
||||
size_t size;
|
||||
} literal; /* type == segm_literal */
|
||||
size_t ref; /* type == segm_backref */
|
||||
enum case_ctl_type ctl; /* type == segm_case_ctl */
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Compiled replacement expression */
|
||||
static struct replace_segm *repl_head, *repl_tail;
|
||||
static size_t segm_count; /* Number of elements in the above list */
|
||||
|
||||
static struct replace_segm *
|
||||
add_segment (void)
|
||||
{
|
||||
struct replace_segm *segm = xmalloc (sizeof *segm);
|
||||
segm->next = NULL;
|
||||
if (repl_tail)
|
||||
repl_tail->next = segm;
|
||||
else
|
||||
repl_head = segm;
|
||||
repl_tail = segm;
|
||||
segm_count++;
|
||||
return segm;
|
||||
}
|
||||
|
||||
static void
|
||||
add_literal_segment (char *str, char *end)
|
||||
{
|
||||
size_t len = end - str;
|
||||
if (len)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (len + 1);
|
||||
memcpy (segm->v.literal.ptr, str, len);
|
||||
segm->v.literal.ptr[len] = 0;
|
||||
segm->v.literal.size = len;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_char_segment (int chr)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (2);
|
||||
segm->v.literal.ptr[0] = chr;
|
||||
segm->v.literal.ptr[1] = 0;
|
||||
segm->v.literal.size = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
add_backref_segment (size_t ref)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_backref;
|
||||
segm->v.ref = ref;
|
||||
}
|
||||
|
||||
static void
|
||||
add_case_ctl_segment (enum case_ctl_type ctl)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_case_ctl;
|
||||
segm->v.ctl = ctl;
|
||||
}
|
||||
|
||||
void
|
||||
set_transform_expr (const char *expr)
|
||||
{
|
||||
int delim;
|
||||
int i, j, rc;
|
||||
char *str, *beg, *cur;
|
||||
const char *p;
|
||||
int cflags = 0;
|
||||
|
||||
if (transform_type == transform_none)
|
||||
obstack_init (&stk);
|
||||
else
|
||||
{
|
||||
/* Redefinition of the transform expression */
|
||||
regfree (®ex);
|
||||
}
|
||||
|
||||
if (expr[0] != 's')
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
delim = expr[1];
|
||||
|
||||
/* Scan regular expression */
|
||||
for (i = 2; expr[i] && expr[i] != delim; i++)
|
||||
if (expr[i] == '\\' && expr[i+1])
|
||||
i++;
|
||||
|
||||
if (expr[i] != delim)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
/* Scan replacement expression */
|
||||
for (j = i + 1; expr[j] && expr[j] != delim; j++)
|
||||
if (expr[j] == '\\' && expr[j+1])
|
||||
j++;
|
||||
|
||||
if (expr[j] != delim)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
/* Check flags */
|
||||
transform_type = transform_first;
|
||||
for (p = expr + j + 1; *p; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case 'g':
|
||||
transform_type = transform_global;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
cflags |= REG_ICASE;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
cflags |= REG_EXTENDED;
|
||||
break;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
match_number = strtoul (p, (char**) &p, 0);
|
||||
p--;
|
||||
break;
|
||||
|
||||
default:
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression")));
|
||||
}
|
||||
|
||||
/* Extract and compile regex */
|
||||
str = xmalloc (i - 1);
|
||||
memcpy (str, expr + 2, i - 2);
|
||||
str[i - 2] = 0;
|
||||
|
||||
rc = regcomp (®ex, str, cflags);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
char errbuf[512];
|
||||
regerror (rc, ®ex, errbuf, sizeof (errbuf));
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
|
||||
}
|
||||
|
||||
if (str[0] == '^' || str[strlen (str) - 1] == '$')
|
||||
transform_type = transform_first;
|
||||
|
||||
free (str);
|
||||
|
||||
/* Extract and compile replacement expr */
|
||||
i++;
|
||||
str = xmalloc (j - i + 1);
|
||||
memcpy (str, expr + i, j - i);
|
||||
str[j - i] = 0;
|
||||
|
||||
for (cur = beg = str; *cur;)
|
||||
{
|
||||
if (*cur == '\\')
|
||||
{
|
||||
size_t n;
|
||||
|
||||
add_literal_segment (beg, cur);
|
||||
switch (*++cur)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
n = strtoul (cur, &cur, 10);
|
||||
if (n > regex.re_nsub)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform replacement: back reference out of range")));
|
||||
add_backref_segment (n);
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
add_char_segment ('\\');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
add_char_segment ('\a');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
add_char_segment ('\b');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
add_char_segment ('\f');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
add_char_segment ('\n');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
add_char_segment ('\r');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
add_char_segment ('\t');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
add_char_segment ('\v');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
add_char_segment ('&');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
/* Turn the replacement to lowercase until a `\U' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_locase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
/* Turn the next character to lowercase, */
|
||||
add_case_ctl_segment (ctl_locase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
/* Turn the replacement to uppercase until a `\L' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_upcase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
/* Turn the next character to uppercase, */
|
||||
add_case_ctl_segment (ctl_upcase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
/* Stop case conversion started by `\L' or `\U'. */
|
||||
add_case_ctl_segment (ctl_stop);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Try to be nice */
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = '\\';
|
||||
buf[1] = *cur;
|
||||
add_literal_segment (buf, buf + 2);
|
||||
}
|
||||
cur++;
|
||||
break;
|
||||
}
|
||||
beg = cur;
|
||||
}
|
||||
else if (*cur == '&')
|
||||
{
|
||||
add_literal_segment (beg, cur);
|
||||
add_backref_segment (0);
|
||||
beg = ++cur;
|
||||
}
|
||||
else
|
||||
cur++;
|
||||
}
|
||||
add_literal_segment (beg, cur);
|
||||
|
||||
}
|
||||
|
||||
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
|
||||
characters. Returns pointer to statically allocated storage. */
|
||||
static char *
|
||||
run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
|
||||
{
|
||||
static char *case_ctl_buffer;
|
||||
static size_t case_ctl_bufsize;
|
||||
char *p;
|
||||
|
||||
if (case_ctl_bufsize < size)
|
||||
{
|
||||
case_ctl_bufsize = size;
|
||||
case_ctl_buffer = xrealloc (case_ctl_buffer, case_ctl_bufsize);
|
||||
}
|
||||
memcpy (case_ctl_buffer, ptr, size);
|
||||
switch (case_ctl)
|
||||
{
|
||||
case ctl_upcase_next:
|
||||
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
|
||||
break;
|
||||
|
||||
case ctl_locase_next:
|
||||
case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
|
||||
break;
|
||||
|
||||
case ctl_upcase:
|
||||
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
||||
*p = toupper (*p);
|
||||
break;
|
||||
|
||||
case ctl_locase:
|
||||
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
||||
*p = tolower (*p);
|
||||
break;
|
||||
|
||||
case ctl_stop:
|
||||
break;
|
||||
}
|
||||
return case_ctl_buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
_transform_name_to_obstack (char *input)
|
||||
{
|
||||
regmatch_t *rmp;
|
||||
int rc;
|
||||
size_t nmatches = 0;
|
||||
enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
|
||||
save_ctl = ctl_stop; /* Saved case_ctl for \u and \l */
|
||||
|
||||
/* Reset case conversion after a single-char operation */
|
||||
#define CASE_CTL_RESET() if (case_ctl == ctl_upcase_next \
|
||||
|| case_ctl == ctl_locase_next) \
|
||||
{ \
|
||||
case_ctl = save_ctl; \
|
||||
save_ctl = ctl_stop; \
|
||||
}
|
||||
|
||||
if (transform_type == transform_none)
|
||||
return false;
|
||||
|
||||
rmp = xmalloc ((regex.re_nsub + 1) * sizeof (*rmp));
|
||||
|
||||
while (*input)
|
||||
{
|
||||
size_t disp;
|
||||
char *ptr;
|
||||
|
||||
rc = regexec (®ex, input, regex.re_nsub + 1, rmp, 0);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
struct replace_segm *segm;
|
||||
|
||||
disp = rmp[0].rm_eo;
|
||||
|
||||
if (rmp[0].rm_so)
|
||||
obstack_grow (&stk, input, rmp[0].rm_so);
|
||||
|
||||
nmatches++;
|
||||
if (match_number && nmatches < match_number)
|
||||
{
|
||||
obstack_grow (&stk, input, disp);
|
||||
input += disp;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (segm = repl_head; segm; segm = segm->next)
|
||||
{
|
||||
switch (segm->type)
|
||||
{
|
||||
case segm_literal: /* Literal segment */
|
||||
if (case_ctl == ctl_stop)
|
||||
ptr = segm->v.literal.ptr;
|
||||
else
|
||||
{
|
||||
ptr = run_case_conv (case_ctl,
|
||||
segm->v.literal.ptr,
|
||||
segm->v.literal.size);
|
||||
CASE_CTL_RESET();
|
||||
}
|
||||
obstack_grow (&stk, ptr, segm->v.literal.size);
|
||||
break;
|
||||
|
||||
case segm_backref: /* Back-reference segment */
|
||||
if (rmp[segm->v.ref].rm_so != -1
|
||||
&& rmp[segm->v.ref].rm_eo != -1)
|
||||
{
|
||||
size_t size = rmp[segm->v.ref].rm_eo
|
||||
- rmp[segm->v.ref].rm_so;
|
||||
ptr = input + rmp[segm->v.ref].rm_so;
|
||||
if (case_ctl != ctl_stop)
|
||||
{
|
||||
ptr = run_case_conv (case_ctl, ptr, size);
|
||||
CASE_CTL_RESET();
|
||||
}
|
||||
|
||||
obstack_grow (&stk, ptr, size);
|
||||
}
|
||||
break;
|
||||
|
||||
case segm_case_ctl:
|
||||
switch (segm->v.ctl)
|
||||
{
|
||||
case ctl_upcase_next:
|
||||
case ctl_locase_next:
|
||||
switch (save_ctl)
|
||||
{
|
||||
case ctl_stop:
|
||||
case ctl_upcase:
|
||||
case ctl_locase:
|
||||
save_ctl = case_ctl;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*FALL THROUGH*/
|
||||
|
||||
case ctl_upcase:
|
||||
case ctl_locase:
|
||||
case ctl_stop:
|
||||
case_ctl = segm->v.ctl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disp = strlen (input);
|
||||
obstack_grow (&stk, input, disp);
|
||||
}
|
||||
|
||||
input += disp;
|
||||
|
||||
if (transform_type == transform_first)
|
||||
{
|
||||
obstack_grow (&stk, input, strlen (input));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
obstack_1grow (&stk, 0);
|
||||
free (rmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name_fp (char **pinput, char *(*fun)(char *))
|
||||
{
|
||||
char *str;
|
||||
bool ret = _transform_name_to_obstack (*pinput);
|
||||
if (ret)
|
||||
{
|
||||
str = obstack_finish (&stk);
|
||||
assign_string (pinput, fun ? fun (str) : str);
|
||||
obstack_free (&stk, str);
|
||||
}
|
||||
else if (fun)
|
||||
{
|
||||
str = *pinput;
|
||||
*pinput = NULL;
|
||||
assign_string (pinput, fun (str));
|
||||
free (str);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name (char **pinput)
|
||||
{
|
||||
return transform_name_fp (pinput, NULL);
|
||||
}
|
||||
|
||||
84
src/update.c
84
src/update.c
@@ -1,7 +1,7 @@
|
||||
/* Update a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
|
||||
2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001 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
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
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. */
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Implement the 'r', 'u' and 'A' options for tar. 'A' means that the
|
||||
file names are tar files, and they should simply be appended to the end
|
||||
of the archive. No attempt is made to record the reads from the args; if
|
||||
they're on raw tape or something like that, it'll probably lose... */
|
||||
|
||||
#include <system.h>
|
||||
#include "system.h"
|
||||
#include <quotearg.h>
|
||||
#include "common.h"
|
||||
|
||||
@@ -32,32 +32,30 @@ extern union block *current_block;
|
||||
|
||||
/* We've hit the end of the old stuff, and its time to start writing new
|
||||
stuff to the tape. This involves seeking back one record and
|
||||
re-writing the current record (which has been changed).
|
||||
FIXME: Either eliminate it or move it to common.h.
|
||||
*/
|
||||
bool time_to_start_writing;
|
||||
re-writing the current record (which has been changed). */
|
||||
int time_to_start_writing;
|
||||
|
||||
/* Pointer to where we started to write in the first record we write out.
|
||||
This is used if we can't backspace the output and have to null out the
|
||||
first part of the record. */
|
||||
char *output_start;
|
||||
|
||||
/* Catenate file FILE_NAME to the archive without creating a header for it.
|
||||
/* Catenate file PATH to the archive without creating a header for it.
|
||||
It had better be a tar file or the archive is screwed. */
|
||||
static void
|
||||
append_file (char *file_name)
|
||||
append_file (char *path)
|
||||
{
|
||||
int handle = open (file_name, O_RDONLY | O_BINARY);
|
||||
int handle = open (path, O_RDONLY | O_BINARY);
|
||||
struct stat stat_data;
|
||||
|
||||
if (handle < 0)
|
||||
{
|
||||
open_error (file_name);
|
||||
open_error (path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fstat (handle, &stat_data) != 0)
|
||||
stat_error (file_name);
|
||||
stat_error (path);
|
||||
else
|
||||
{
|
||||
off_t bytes_left = stat_data.st_size;
|
||||
@@ -66,7 +64,7 @@ append_file (char *file_name)
|
||||
{
|
||||
union block *start = find_next_block ();
|
||||
size_t buffer_size = available_space_after (start);
|
||||
size_t status;
|
||||
ssize_t status;
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
if (bytes_left < buffer_size)
|
||||
@@ -78,15 +76,12 @@ append_file (char *file_name)
|
||||
}
|
||||
|
||||
status = safe_read (handle, start->buffer, buffer_size);
|
||||
if (status == SAFE_READ_ERROR)
|
||||
read_fatal_details (file_name, stat_data.st_size - bytes_left,
|
||||
if (status < 0)
|
||||
read_fatal_details (path, stat_data.st_size - bytes_left,
|
||||
buffer_size);
|
||||
if (status == 0)
|
||||
FATAL_ERROR ((0, 0,
|
||||
ngettext ("%s: File shrank by %s byte",
|
||||
"%s: File shrank by %s bytes",
|
||||
bytes_left),
|
||||
quotearg_colon (file_name),
|
||||
FATAL_ERROR ((0, 0, _("%s: File shrank by %s bytes"),
|
||||
quotearg_colon (path),
|
||||
STRINGIFY_BIGINT (bytes_left, buf)));
|
||||
|
||||
bytes_left -= status;
|
||||
@@ -96,7 +91,7 @@ append_file (char *file_name)
|
||||
}
|
||||
|
||||
if (close (handle) != 0)
|
||||
close_error (file_name);
|
||||
close_error (path);
|
||||
}
|
||||
|
||||
/* Implement the 'r' (add files to end of archive), and 'u' (add files
|
||||
@@ -106,55 +101,47 @@ void
|
||||
update_archive (void)
|
||||
{
|
||||
enum read_header previous_status = HEADER_STILL_UNREAD;
|
||||
bool found_end = false;
|
||||
int found_end = 0;
|
||||
|
||||
name_gather ();
|
||||
open_archive (ACCESS_UPDATE);
|
||||
xheader_write_global ();
|
||||
|
||||
while (!found_end)
|
||||
{
|
||||
enum read_header status = read_header (false);
|
||||
enum read_header status = read_header (0);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case HEADER_STILL_UNREAD:
|
||||
case HEADER_SUCCESS_EXTENDED:
|
||||
abort ();
|
||||
|
||||
case HEADER_SUCCESS:
|
||||
{
|
||||
struct name *name;
|
||||
|
||||
decode_header (current_header, ¤t_stat_info,
|
||||
¤t_format, 0);
|
||||
archive_format = current_format;
|
||||
|
||||
if (subcommand_option == UPDATE_SUBCOMMAND
|
||||
&& (name = name_scan (current_stat_info.file_name)) != NULL)
|
||||
&& (name = name_scan (current_file_name), name))
|
||||
{
|
||||
struct stat s;
|
||||
enum archive_format unused;
|
||||
|
||||
decode_header (current_header, ¤t_stat, &unused, 0);
|
||||
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);
|
||||
if (deref_stat (dereference_option, current_file_name, &s) == 0
|
||||
&& s.st_mtime <= current_stat.st_mtime)
|
||||
add_avoided_name (current_file_name);
|
||||
}
|
||||
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
case HEADER_ZERO_BLOCK:
|
||||
current_block = current_header;
|
||||
found_end = true;
|
||||
found_end = 1;
|
||||
break;
|
||||
|
||||
case HEADER_END_OF_FILE:
|
||||
found_end = true;
|
||||
found_end = 1;
|
||||
break;
|
||||
|
||||
case HEADER_FAILURE:
|
||||
@@ -174,34 +161,31 @@ update_archive (void)
|
||||
break;
|
||||
|
||||
case HEADER_END_OF_FILE:
|
||||
case HEADER_SUCCESS_EXTENDED:
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
xheader_destroy (&extended_header);
|
||||
previous_status = status;
|
||||
}
|
||||
|
||||
reset_eof ();
|
||||
time_to_start_writing = true;
|
||||
time_to_start_writing = 1;
|
||||
output_start = current_block->buffer;
|
||||
|
||||
{
|
||||
char *file_name;
|
||||
char *path;
|
||||
|
||||
while ((file_name = name_from_list ()) != NULL)
|
||||
while (path = name_from_list (), path)
|
||||
{
|
||||
if (excluded_name (file_name))
|
||||
if (excluded_name (path))
|
||||
continue;
|
||||
if (interactive_option && !confirm ("add", file_name))
|
||||
if (interactive_option && !confirm ("add", path))
|
||||
continue;
|
||||
if (subcommand_option == CAT_SUBCOMMAND)
|
||||
append_file (file_name);
|
||||
append_file (path);
|
||||
else
|
||||
dump_file (file_name, 1, (dev_t) 0);
|
||||
dump_file (path, 1, (dev_t) 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
98
src/utf8.c
98
src/utf8.c
@@ -1,98 +0,0 @@
|
||||
/* Charset handling for GNU tar.
|
||||
|
||||
Copyright (C) 2004 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <quotearg.h>
|
||||
#include <localcharset.h>
|
||||
#include "common.h"
|
||||
#ifdef HAVE_ICONV_H
|
||||
# include <iconv.h>
|
||||
#endif
|
||||
|
||||
#ifndef ICONV_CONST
|
||||
# define ICONV_CONST
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ICONV
|
||||
|
||||
# undef iconv_open
|
||||
# define iconv_open(tocode, fromcode) ((iconv_t) -1)
|
||||
|
||||
# undef iconv
|
||||
# define iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) ((size_t) 0)
|
||||
|
||||
# undef iconv_close
|
||||
# define iconv_close(cd) 0
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
static iconv_t conv_desc[2] = { (iconv_t) -1, (iconv_t) -1 };
|
||||
|
||||
static iconv_t
|
||||
utf8_init (bool to_utf)
|
||||
{
|
||||
if (conv_desc[(int) to_utf] == (iconv_t) -1)
|
||||
{
|
||||
if (to_utf)
|
||||
conv_desc[(int) to_utf] = iconv_open ("UTF-8", locale_charset ());
|
||||
else
|
||||
conv_desc[(int) to_utf] = iconv_open (locale_charset (), "UTF-8");
|
||||
}
|
||||
return conv_desc[(int) to_utf];
|
||||
}
|
||||
|
||||
bool
|
||||
utf8_convert (bool to_utf, char const *input, char **output)
|
||||
{
|
||||
char ICONV_CONST *ib;
|
||||
char *ob;
|
||||
size_t inlen;
|
||||
size_t outlen;
|
||||
size_t rc;
|
||||
iconv_t cd = utf8_init (to_utf);
|
||||
|
||||
if (cd == 0)
|
||||
{
|
||||
*output = xstrdup (input);
|
||||
return true;
|
||||
}
|
||||
else if (cd == (iconv_t)-1)
|
||||
return false;
|
||||
|
||||
inlen = strlen (input) + 1;
|
||||
outlen = inlen * MB_LEN_MAX + 1;
|
||||
ob = *output = xmalloc (outlen);
|
||||
ib = (char ICONV_CONST *) input;
|
||||
rc = iconv (cd, &ib, &inlen, &ob, &outlen);
|
||||
*ob = 0;
|
||||
return rc != -1;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
string_ascii_p (const char *str)
|
||||
{
|
||||
const unsigned char *p = (const unsigned char *)str;
|
||||
for (; *p; p++)
|
||||
if (*p > 127)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
1520
src/xheader.c
1520
src/xheader.c
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
*.bz2
|
||||
*.gz
|
||||
*.tar
|
||||
*.gtar
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
argcv.c
|
||||
argcv.h
|
||||
atconfig
|
||||
atlocal
|
||||
genfile
|
||||
genfile.c
|
||||
package.m4
|
||||
testsuite
|
||||
testsuite.dir
|
||||
testsuite.log
|
||||
@@ -1,157 +1,41 @@
|
||||
# Makefile for GNU tar regression tests.
|
||||
# Copyright <20> 1996, 1997 Free Software Foundation, Inc.
|
||||
# Fran<61>ois Pinard <pinard@iro.umontreal.ca>, 1988.
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
# 2006 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.
|
||||
|
||||
# François Pinard <pinard@iro.umontreal.ca>, 1988.
|
||||
# Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
|
||||
# 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.
|
||||
|
||||
## 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 star/README star/quicktest.sh
|
||||
DISTCLEANFILES = atconfig $(check_SCRIPTS)
|
||||
MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
|
||||
|
||||
## ------------ ##
|
||||
## package.m4. ##
|
||||
## ------------ ##
|
||||
|
||||
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
|
||||
{ \
|
||||
echo '# Signature of the current package.'; \
|
||||
echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
|
||||
} >$(srcdir)/package.m4
|
||||
|
||||
#
|
||||
|
||||
## ------------ ##
|
||||
## Test suite. ##
|
||||
## ------------ ##
|
||||
|
||||
TESTSUITE_AT = \
|
||||
testsuite.at\
|
||||
append.at\
|
||||
append01.at\
|
||||
append02.at\
|
||||
chtype.at\
|
||||
comprec.at\
|
||||
delete01.at\
|
||||
delete02.at\
|
||||
delete03.at\
|
||||
delete04.at\
|
||||
delete05.at\
|
||||
extrac01.at\
|
||||
extrac02.at\
|
||||
extrac03.at\
|
||||
extrac04.at\
|
||||
extrac05.at\
|
||||
extrac06.at\
|
||||
gzip.at\
|
||||
grow.at\
|
||||
incremental.at\
|
||||
incr01.at\
|
||||
incr02.at\
|
||||
incr03.at\
|
||||
incr04.at\
|
||||
indexfile.at\
|
||||
ignfail.at\
|
||||
link01.at\
|
||||
listed01.at\
|
||||
listed02.at\
|
||||
long01.at\
|
||||
longv7.at\
|
||||
lustar01.at\
|
||||
lustar02.at\
|
||||
lustar03.at\
|
||||
multiv01.at\
|
||||
multiv02.at\
|
||||
multiv03.at\
|
||||
multiv04.at\
|
||||
multiv05.at\
|
||||
old.at\
|
||||
options.at\
|
||||
options02.at\
|
||||
pipe.at\
|
||||
recurse.at\
|
||||
rename01.at\
|
||||
rename02.at\
|
||||
rename03.at\
|
||||
same-order01.at\
|
||||
same-order02.at\
|
||||
shortrec.at\
|
||||
sparse01.at\
|
||||
sparse02.at\
|
||||
sparse03.at\
|
||||
sparsemv.at\
|
||||
sparsemvp.at\
|
||||
spmvp00.at\
|
||||
spmvp01.at\
|
||||
spmvp10.at\
|
||||
truncate.at\
|
||||
update.at\
|
||||
volsize.at\
|
||||
volume.at\
|
||||
verbose.at\
|
||||
version.at\
|
||||
star/gtarfail.at\
|
||||
star/gtarfail2.at\
|
||||
star/multi-fail.at\
|
||||
star/ustar-big-2g.at\
|
||||
star/ustar-big-8g.at\
|
||||
star/pax-big-10g.at
|
||||
|
||||
TESTSUITE = $(srcdir)/testsuite
|
||||
|
||||
AUTOTEST = $(AUTOM4TE) --language=autotest
|
||||
$(TESTSUITE): package.m4 $(TESTSUITE_AT)
|
||||
$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
atconfig: $(top_builddir)/config.status
|
||||
cd $(top_builddir) && ./config.status tests/$@
|
||||
|
||||
clean-local:
|
||||
test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
|
||||
|
||||
check-local: atconfig atlocal $(TESTSUITE)
|
||||
$(SHELL) $(TESTSUITE)
|
||||
|
||||
check-full:
|
||||
FULL_TEST=1 $(MAKE) check
|
||||
|
||||
#check_SCRIPTS = tar
|
||||
|
||||
# Run the test suite on the *installed* tree.
|
||||
installcheck-local:
|
||||
$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
|
||||
|
||||
|
||||
## ------------ ##
|
||||
## genfile ##
|
||||
## ------------ ##
|
||||
# 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.
|
||||
|
||||
AUTOMAKE_OPTIONS = gnits ../src/ansi2knr
|
||||
check_PROGRAMS = genfile
|
||||
BUILT_SOURCES = preset
|
||||
|
||||
genfile_SOURCES = genfile.c argcv.c argcv.h
|
||||
TESTS = version.sh ignfail.sh extrac01.sh extrac02.sh extrac03.sh \
|
||||
old.sh volume.sh gzip.sh append.sh delete01.sh incremen.sh
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../lib -I$(top_srcdir)/src
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
|
||||
LDADD = ../lib/libtar.a $(LIBINTL) $(LIB_CLOCK_GETTIME)
|
||||
# Postponed until after the 1.12 release.
|
||||
POSTPONED_TESTS = delete02.sh
|
||||
|
||||
genfile_SOURCES = genfile.c
|
||||
EXTRA_DIST = after before preset.in $(TESTS) $(POSTPONED_TESTS)
|
||||
|
||||
DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
|
||||
INCLUDES = -I.. -I../intl -I$(top_srcdir)/src -I$(top_srcdir)/lib
|
||||
LDADD = ../lib/libtar.a @INTLLIBS@
|
||||
localedir = $(prefix)/@DATADIRNAME@/locale
|
||||
|
||||
mostlyclean:
|
||||
rm -rf tmp-*
|
||||
|
||||
$(TESTS): genfile
|
||||
|
||||
9
tests/after
Executable file
9
tests/after
Executable file
@@ -0,0 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Do common operations after a particular test.
|
||||
|
||||
cd ..
|
||||
exec 1> /dev/null
|
||||
exec 2> /dev/null
|
||||
echo $echo_n "$out$echo_c" | cmp -s - tmp-$$/stdout || exit 1
|
||||
echo $echo_n "$err$echo_c" | cmp -s - tmp-$$/stderr || exit 1
|
||||
rm -rf tmp-$$
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user