new command: bsdtar.

This commit is contained in:
Ben Gras 2010-07-13 19:28:09 +00:00
parent 470ab03b86
commit ba759ef03e
73 changed files with 15490 additions and 1 deletions

View file

@ -4,7 +4,7 @@
SUBDIR= aal add_route adduser advent arp ash at autil awk \ SUBDIR= aal add_route adduser advent arp ash at autil awk \
backup badblocks banner basename bigmake binpackage \ backup badblocks banner basename bigmake binpackage \
binpackages binsizes bzip2 bzip2recover cal calendar \ binpackages binsizes bsdtar bzip2 bzip2recover cal calendar \
cat cawf cd cdprobe checkhier chmem \ cat cawf cd cdprobe checkhier chmem \
chmod chown chroot ci cksum cleantmp clear cmp co \ chmod chown chroot ci cksum cleantmp clear cmp co \
comm compress cp crc cron crontab cut datasizes date \ comm compress cp crc cron crontab cut datasizes date \

19
commands/bsdtar/Makefile Normal file
View file

@ -0,0 +1,19 @@
.include <bsd.own.mk>
PROG= bsdtar
SRCS= bsdtar.c \
cmdline.c \
getdate.c \
read.c \
subst.c \
tree.c \
util.c \
write.c
.include "${.CURDIR}/libarchive_fe/Makefile.inc"
DPADD+= ${LIBARCHIVE} ${LIBZ} ${LIBBZ2}
LDADD+= -larchive -lbz2 -lz
CPPFLAGS+= -DHAVE_CONFIG_H
CPPFLAGS+= -I${.CURDIR} -I${.CURDIR}/libarchive_fe
.include <bsd.prog.mk>

921
commands/bsdtar/bsdtar.1 Normal file
View file

@ -0,0 +1,921 @@
.\" Copyright (c) 2003-2007 Tim Kientzle
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.46 2008/12/06 07:37:55 kientzle Exp $
.\"
.Dd Oct 12, 2009
.Dt BSDTAR 1
.Os
.Sh NAME
.Nm tar
.Nd manipulate tape archives
.Sh SYNOPSIS
.Nm
.Op Ar bundled-flags Ao args Ac
.Op Ao Ar file Ac | Ao Ar pattern Ac ...
.Nm
.Brq Fl c
.Op Ar options
.Op Ar files | Ar directories
.Nm
.Brq Fl r | Fl u
.Fl f Ar archive-file
.Op Ar options
.Op Ar files | Ar directories
.Nm
.Brq Fl t | Fl x
.Op Ar options
.Op Ar patterns
.Sh DESCRIPTION
.Nm
creates and manipulates streaming archive files.
This implementation can extract from tar, pax, cpio, zip, jar, ar,
and ISO 9660 cdrom images and can create tar, pax, cpio, ar,
and shar archives.
.Pp
The first synopsis form shows a
.Dq bundled
option word.
This usage is provided for compatibility with historical implementations.
See COMPATIBILITY below for details.
.Pp
The other synopsis forms show the preferred usage.
The first option to
.Nm
is a mode indicator from the following list:
.Bl -tag -compact -width indent
.It Fl c
Create a new archive containing the specified items.
.It Fl r
Like
.Fl c ,
but new entries are appended to the archive.
Note that this only works on uncompressed archives stored in regular files.
The
.Fl f
option is required.
.It Fl t
List archive contents to stdout.
.It Fl u
Like
.Fl r ,
but new entries are added only if they have a modification date
newer than the corresponding entry in the archive.
Note that this only works on uncompressed archives stored in regular files.
The
.Fl f
option is required.
.It Fl x
Extract to disk from the archive.
If a file with the same name appears more than once in the archive,
each copy will be extracted, with later copies overwriting (replacing)
earlier copies.
.El
.Pp
In
.Fl c ,
.Fl r ,
or
.Fl u
mode, each specified file or directory is added to the
archive in the order specified on the command line.
By default, the contents of each directory are also archived.
.Pp
In extract or list mode, the entire command line
is read and parsed before the archive is opened.
The pathnames or patterns on the command line indicate
which items in the archive should be processed.
Patterns are shell-style globbing patterns as
documented in
.Xr tcsh 1 .
.Sh OPTIONS
Unless specifically stated otherwise, options are applicable in
all operating modes.
.Bl -tag -width indent
.It Cm @ Ns Pa archive
(c and r mode only)
The specified archive is opened and the entries
in it will be appended to the current archive.
As a simple example,
.Dl Nm Fl c Fl f Pa - Pa newfile Cm @ Ns Pa original.tar
writes a new archive to standard output containing a file
.Pa newfile
and all of the entries from
.Pa original.tar .
In contrast,
.Dl Nm Fl c Fl f Pa - Pa newfile Pa original.tar
creates a new archive with only two entries.
Similarly,
.Dl Nm Fl czf Pa - Fl -format Cm pax Cm @ Ns Pa -
reads an archive from standard input (whose format will be determined
automatically) and converts it into a gzip-compressed
pax-format archive on stdout.
In this way,
.Nm
can be used to convert archives from one format to another.
.It Fl b Ar blocksize
Specify the block size, in 512-byte records, for tape drive I/O.
As a rule, this argument is only needed when reading from or writing
to tape drives, and usually not even then as the default block size of
20 records (10240 bytes) is very common.
.It Fl C Ar directory
In c and r mode, this changes the directory before adding
the following files.
In x mode, change directories after opening the archive
but before extracting entries from the archive.
.It Fl -check-links
(c and r modes only)
Issue a warning message unless all links to each file are archived.
.It Fl -chroot
(x mode only)
.Fn chroot
to the current directory after processing any
.Fl C
options and before extracting any files.
.It Fl -exclude Ar pattern
Do not process files or directories that match the
specified pattern.
Note that exclusions take precedence over patterns or filenames
specified on the command line.
.It Fl -format Ar format
(c, r, u mode only)
Use the specified format for the created archive.
Supported formats include
.Dq cpio ,
.Dq pax ,
.Dq shar ,
and
.Dq ustar .
Other formats may also be supported; see
.Xr libarchive-formats 5
for more information about currently-supported formats.
In r and u modes, when extending an existing archive, the format specified
here must be compatible with the format of the existing archive on disk.
.It Fl f Ar file
Read the archive from or write the archive to the specified file.
The filename can be
.Pa -
for standard input or standard output.
If not specified, the default tape device will be used.
(On
.Fx ,
the default tape device is
.Pa /dev/sa0 . )
.It Fl H
(c and r mode only)
Symbolic links named on the command line will be followed; the
target of the link will be archived, not the link itself.
.It Fl h
(c and r mode only)
Synonym for
.Fl L .
.It Fl I
Synonym for
.Fl T .
.It Fl -include Ar pattern
Process only files or directories that match the specified pattern.
Note that exclusions specified with
.Fl -exclude
take precedence over inclusions.
If no inclusions are explicitly specified, all entries are processed by
default.
The
.Fl -include
option is especially useful when filtering archives.
For example, the command
.Dl Nm Fl c Fl f Pa new.tar Fl -include='*foo*' Cm @ Ns Pa old.tgz
creates a new archive
.Pa new.tar
containing only the entries from
.Pa old.tgz
containing the string
.Sq foo .
.It Fl j
(c mode only)
Compress the resulting archive with
.Xr bzip2 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
.Nm tar
implementations, this implementation recognizes bzip2 compression
automatically when reading archives.
.It Fl k
(x mode only)
Do not overwrite existing files.
In particular, if a file appears more than once in an archive,
later copies will not overwrite earlier copies.
.It Fl -keep-newer-files
(x mode only)
Do not overwrite existing files that are newer than the
versions appearing in the archive being extracted.
.It Fl L
(c and r mode only)
All symbolic links will be followed.
Normally, symbolic links are archived as such.
With this option, the target of the link will be archived instead.
.It Fl l
This is a synonym for the
.Fl -check-links
option.
.It Fl m
(x mode only)
Do not extract modification time.
By default, the modification time is set to the time stored in the archive.
.It Fl n
(c, r, u modes only)
Do not recursively archive the contents of directories.
.It Fl -newer Ar date
(c, r, u modes only)
Only include files and directories newer than the specified date.
This compares ctime entries.
.It Fl -newer-mtime Ar date
(c, r, u modes only)
Like
.Fl -newer ,
except it compares mtime entries instead of ctime entries.
.It Fl -newer-than Pa file
(c, r, u modes only)
Only include files and directories newer than the specified file.
This compares ctime entries.
.It Fl -newer-mtime-than Pa file
(c, r, u modes only)
Like
.Fl -newer-than ,
except it compares mtime entries instead of ctime entries.
.It Fl -nodump
(c and r modes only)
Honor the nodump file flag by skipping this file.
.It Fl -null
(use with
.Fl I ,
.Fl T ,
or
.Fl X )
Filenames or patterns are separated by null characters,
not by newlines.
This is often used to read filenames output by the
.Fl print0
option to
.Xr find 1 .
.It Fl -numeric-owner
(x mode only)
Ignore symbolic user and group names when restoring archives to disk,
only numeric uid and gid values will be obeyed.
.It Fl O
(x, t modes only)
In extract (-x) mode, files will be written to standard out rather than
being extracted to disk.
In list (-t) mode, the file listing will be written to stderr rather than
the usual stdout.
.It Fl o
(x mode)
Use the user and group of the user running the program rather
than those specified in the archive.
Note that this has no significance unless
.Fl p
is specified, and the program is being run by the root user.
In this case, the file modes and flags from
the archive will be restored, but ACLs or owner information in
the archive will be discarded.
.It Fl o
(c, r, u mode)
A synonym for
.Fl -format Ar ustar
.It Fl -one-file-system
(c, r, and u modes)
Do not cross mount points.
.It Fl -options Ar options
Select optional behaviors for particular modules.
The argument is a text string containing comma-separated
keywords and values.
These are passed to the modules that handle particular
formats to control how those formats will behave.
Each option has one of the following forms:
.Bl -tag -compact -width indent
.It Ar key=value
The key will be set to the specified value in every module that supports it.
Modules that do not support this key will ignore it.
.It Ar key
The key will be enabled in every module that supports it.
This is equivalent to
.Ar key Ns Cm =1 .
.It Ar !key
The key will be disabled in every module that supports it.
.It Ar module:key=value , Ar module:key , Ar module:!key
As above, but the corresponding key and value will be provided
only to modules whose name matches
.Ar module .
.El
The currently supported modules and keys are:
.Bl -tag -compact -width indent
.It Cm iso9660:joliet
Support Joliet extensions.
This is enabled by default, use
.Cm !joliet
or
.Cm iso9660:!joliet
to disable.
.It Cm iso9660:rockridge
Support Rock Ridge extensions.
This is enabled by default, use
.Cm !rockridge
or
.Cm iso9660:!rockridge
to disable.
.It Cm gzip:compression-level
A decimal integer from 0 to 9 specifying the gzip compression level.
.It Cm xz:compression-level
A decimal integer from 0 to 9 specifying the xz compression level.
.It Cm mtree: Ns Ar keyword
The mtree writer module allows you to specify which mtree keywords
will be included in the output.
Supported keywords include:
.Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent ,
.Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 ,
.Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname .
The default is equivalent to:
.Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname .
.It Cm mtree:all
Enables all of the above keywords.
You can also use
.Cm mtree:!all
to disable all keywords.
.It Cm mtree:use-set
Enable generation of
.Cm /set
lines in the output.
.It Cm mtree:indent
Produce human-readable output by indenting options and splitting lines
to fit into 80 columns.
.It Cm zip:compression Ns = Ns Ar type
Use
.Ar type
as compression method.
Supported values are store (uncompressed) and deflate (gzip algorithm).
.El
If a provided option is not supported by any module, that
is a fatal error.
.It Fl P
Preserve pathnames.
By default, absolute pathnames (those that begin with a /
character) have the leading slash removed both when creating archives
and extracting from them.
Also,
.Nm
will refuse to extract archive entries whose pathnames contain
.Pa ..
or whose target directory would be altered by a symlink.
This option suppresses these behaviors.
.It Fl p
(x mode only)
Preserve file permissions.
Attempt to restore the full permissions, including owner, file modes, file
flags and ACLs, if available, for each item extracted from the archive.
By default, newly-created files are owned by the user running
.Nm ,
the file mode is restored for newly-created regular files, and
all other types of entries receive default permissions.
If
.Nm
is being run by root, the default is to restore the owner unless the
.Fl o
option is also specified.
.It Fl q ( Fl -fast-read )
(x and t mode only)
Extract or list only the first archive entry that matches each pattern
or filename operand.
Exit as soon as each specified pattern or filename has been matched.
By default, the archive is always read to the very end, since
there can be multiple entries with the same name and, by convention,
later entries overwrite earlier entries.
This option is provided as a performance optimization.
.It Fl S
(x mode only)
Extract files as sparse files.
For every block on disk, check first if it contains only NULL bytes and seek
over it otherwise.
This works similiar to the conv=sparse option of dd.
.It Fl -strip-components Ar count
(x mode only)
Remove the specified number of leading path elements.
Pathnames with fewer elements will be silently skipped.
Note that the pathname is edited after checking inclusion/exclusion patterns
but before security checks.
.It Fl s Ar pattern
Modify file or archive member names according to
.Pa pattern .
The pattern has the format
.Ar /old/new/ Ns Op gps
where
.Ar old
is a basic regular expression,
.Ar new
is the replacement string of the matched part,
and the optional trailing letters modify
how the replacement is handled.
If
.Ar old
is not matched, the pattern is skipped.
Within
.Ar new ,
~ is substituted with the match, \1 to \9 with the content of
the corresponding captured group.
The optional trailing g specifies that matching should continue
after the matched part and stopped on the first unmatched pattern.
The optional trailing s specifies that the pattern applies to the value
of symbolic links.
The optional trailing p specifies that after a successful substitution
the original path name and the new path name should be printed to
standard error.
.It Fl T Ar filename
In x or t mode,
.Nm
will read the list of names to be extracted from
.Pa filename .
In c mode,
.Nm
will read names to be archived from
.Pa filename .
The special name
.Dq -C
on a line by itself will cause the current directory to be changed to
the directory specified on the following line.
Names are terminated by newlines unless
.Fl -null
is specified.
Note that
.Fl -null
also disables the special handling of lines containing
.Dq -C .
.It Fl U
(x mode only)
Unlink files before creating them.
Without this option,
.Nm
overwrites existing files, which preserves existing hardlinks.
With this option, existing hardlinks will be broken, as will any
symlink that would affect the location of an extracted file.
.It Fl -use-compress-program Ar program
Pipe the input (in x or t mode) or the output (in c mode) through
.Pa program
instead of using the builtin compression support.
.It Fl v
Produce verbose output.
In create and extract modes,
.Nm
will list each file name as it is read from or written to
the archive.
In list mode,
.Nm
will produce output similar to that of
.Xr ls 1 .
Additional
.Fl v
options will provide additional detail.
.It Fl -version
Print version of
.Nm
and
.Nm libarchive ,
and exit.
.It Fl w
Ask for confirmation for every action.
.It Fl X Ar filename
Read a list of exclusion patterns from the specified file.
See
.Fl -exclude
for more information about the handling of exclusions.
.It Fl y
(c mode only)
Compress the resulting archive with
.Xr bzip2 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
.Nm tar
implementations, this implementation recognizes bzip2 compression
automatically when reading archives.
.It Fl z
(c mode only)
Compress the resulting archive with
.Xr gzip 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
.Nm tar
implementations, this implementation recognizes gzip compression
automatically when reading archives.
.It Fl Z
(c mode only)
Compress the resulting archive with
.Xr compress 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
.Nm tar
implementations, this implementation recognizes compress compression
automatically when reading archives.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm :
.Bl -tag -width ".Ev BLOCKSIZE"
.It Ev LANG
The locale to use.
See
.Xr environ 7
for more information.
.It Ev TAPE
The default tape device.
The
.Fl f
option overrides this.
.It Ev TZ
The timezone to use when displaying dates.
See
.Xr environ 7
for more information.
.El
.Sh FILES
.Bl -tag -width ".Ev BLOCKSIZE"
.It Pa /dev/sa0
The default tape device, if not overridden by the
.Ev TAPE
environment variable or the
.Fl f
option.
.El
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
The following creates a new archive
called
.Ar file.tar.gz
that contains two files
.Ar source.c
and
.Ar source.h :
.Dl Nm Fl czf Pa file.tar.gz Pa source.c Pa source.h
.Pp
To view a detailed table of contents for this
archive:
.Dl Nm Fl tvf Pa file.tar.gz
.Pp
To extract all entries from the archive on
the default tape drive:
.Dl Nm Fl x
.Pp
To examine the contents of an ISO 9660 cdrom image:
.Dl Nm Fl tf Pa image.iso
.Pp
To move file hierarchies, invoke
.Nm
as
.Dl Nm Fl cf Pa - Fl C Pa srcdir\ . | Nm Fl xpf Pa - Fl C Pa destdir
or more traditionally
.Dl cd srcdir \&; Nm Fl cf Pa -\ . | ( cd destdir \&; Nm Fl xpf Pa - )
.Pp
In create mode, the list of files and directories to be archived
can also include directory change instructions of the form
.Cm -C Ns Pa foo/baz
and archive inclusions of the form
.Cm @ Ns Pa archive-file .
For example, the command line
.Dl Nm Fl c Fl f Pa new.tar Pa foo1 Cm @ Ns Pa old.tgz Cm -C Ns Pa /tmp Pa foo2
will create a new archive
.Pa new.tar .
.Nm
will read the file
.Pa foo1
from the current directory and add it to the output archive.
It will then read each entry from
.Pa old.tgz
and add those entries to the output archive.
Finally, it will switch to the
.Pa /tmp
directory and add
.Pa foo2
to the output archive.
.Pp
An input file in
.Xr mtree 5
format can be used to create an output archive with arbitrary ownership,
permissions, or names that differ from existing data on disk:
.Pp
.Dl $ cat input.mtree
.Dl #mtree
.Dl usr/bin uid=0 gid=0 mode=0755 type=dir
.Dl usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls
.Dl $ tar -cvf output.tar @input.mtree
.Pp
The
.Fl -newer
and
.Fl -newer-mtime
switches accept a variety of common date and time specifications, including
.Dq 12 Mar 2005 7:14:29pm ,
.Dq 2005-03-12 19:14 ,
.Dq 5 minutes ago ,
and
.Dq 19:14 PST May 1 .
.Pp
The
.Fl -options
argument can be used to control various details of archive generation
or reading.
For example, you can generate mtree output which only contains
.Cm type , Cm time ,
and
.Cm uid
keywords:
.Dl Nm Fl cf Pa file.tar Fl -format=mtree Fl -options='!all,type,time,uid' Pa dir
or you can set the compression level used by gzip or xz compression:
.Dl Nm Fl czf Pa file.tar Fl -options='compression-level=9' .
For more details, see the explanation of the
.Fn archive_read_set_options
and
.Fn archive_write_set_options
API calls that are described in
.Xr archive_read 3
and
.Xr archive_write 3 .
.Sh COMPATIBILITY
The bundled-arguments format is supported for compatibility
with historic implementations.
It consists of an initial word (with no leading - character) in which
each character indicates an option.
Arguments follow as separate words.
The order of the arguments must match the order
of the corresponding characters in the bundled command word.
For example,
.Dl Nm Cm tbf 32 Pa file.tar
specifies three flags
.Cm t ,
.Cm b ,
and
.Cm f .
The
.Cm b
and
.Cm f
flags both require arguments,
so there must be two additional items
on the command line.
The
.Ar 32
is the argument to the
.Cm b
flag, and
.Ar file.tar
is the argument to the
.Cm f
flag.
.Pp
The mode options c, r, t, u, and x and the options
b, f, l, m, o, v, and w comply with SUSv2.
.Pp
For maximum portability, scripts that invoke
.Nm tar
should use the bundled-argument format above, should limit
themselves to the
.Cm c ,
.Cm t ,
and
.Cm x
modes, and the
.Cm b ,
.Cm f ,
.Cm m ,
.Cm v ,
and
.Cm w
options.
.Pp
Additional long options are provided to improve compatibility with other
tar implementations.
.Sh SECURITY
Certain security issues are common to many archiving programs, including
.Nm .
In particular, carefully-crafted archives can request that
.Nm
extract files to locations outside of the target directory.
This can potentially be used to cause unwitting users to overwrite
files they did not intend to overwrite.
If the archive is being extracted by the superuser, any file
on the system can potentially be overwritten.
There are three ways this can happen.
Although
.Nm
has mechanisms to protect against each one,
savvy users should be aware of the implications:
.Bl -bullet -width indent
.It
Archive entries can have absolute pathnames.
By default,
.Nm
removes the leading
.Pa /
character from filenames before restoring them to guard against this problem.
.It
Archive entries can have pathnames that include
.Pa ..
components.
By default,
.Nm
will not extract files containing
.Pa ..
components in their pathname.
.It
Archive entries can exploit symbolic links to restore
files to other directories.
An archive can restore a symbolic link to another directory,
then use that link to restore a file into that directory.
To guard against this,
.Nm
checks each extracted path for symlinks.
If the final path element is a symlink, it will be removed
and replaced with the archive entry.
If
.Fl U
is specified, any intermediate symlink will also be unconditionally removed.
If neither
.Fl U
nor
.Fl P
is specified,
.Nm
will refuse to extract the entry.
.El
To protect yourself, you should be wary of any archives that
come from untrusted sources.
You should examine the contents of an archive with
.Dl Nm Fl tf Pa filename
before extraction.
You should use the
.Fl k
option to ensure that
.Nm
will not overwrite any existing files or the
.Fl U
option to remove any pre-existing files.
You should generally not extract archives while running with super-user
privileges.
Note that the
.Fl P
option to
.Nm
disables the security checks above and allows you to extract
an archive while preserving any absolute pathnames,
.Pa ..
components, or symlinks to other directories.
.Sh SEE ALSO
.Xr bzip2 1 ,
.Xr compress 1 ,
.Xr cpio 1 ,
.Xr gzip 1 ,
.Xr mt 1 ,
.Xr pax 1 ,
.Xr shar 1 ,
.Xr libarchive 3 ,
.Xr libarchive-formats 5 ,
.Xr tar 5
.Sh STANDARDS
There is no current POSIX standard for the tar command; it appeared
in
.St -p1003.1-96
but was dropped from
.St -p1003.1-2001 .
The options used by this implementation were developed by surveying a
number of existing tar implementations as well as the old POSIX specification
for tar and the current POSIX specification for pax.
.Pp
The ustar and pax interchange file formats are defined by
.St -p1003.1-2001
for the pax command.
.Sh HISTORY
A
.Nm tar
command appeared in Seventh Edition Unix, which was released in January, 1979.
There have been numerous other implementations,
many of which extended the file format.
John Gilmore's
.Nm pdtar
public-domain implementation (circa November, 1987)
was quite influential, and formed the basis of GNU tar.
GNU tar was included as the standard system tar
in
.Fx
beginning with
.Fx 1.0 .
.Pp
This is a complete re-implementation based on the
.Xr libarchive 3
library.
.Sh BUGS
This program follows
.St -p1003.1-96
for the definition of the
.Fl l
option.
Note that GNU tar prior to version 1.15 treated
.Fl l
as a synonym for the
.Fl -one-file-system
option.
.Pp
The
.Fl C Pa dir
option may differ from historic implementations.
.Pp
All archive output is written in correctly-sized blocks, even
if the output is being compressed.
Whether or not the last output block is padded to a full
block size varies depending on the format and the
output device.
For tar and cpio formats, the last block of output is padded
to a full block size if the output is being
written to standard output or to a character or block device such as
a tape drive.
If the output is being written to a regular file, the last block
will not be padded.
Many compressors, including
.Xr gzip 1
and
.Xr bzip2 1 ,
complain about the null padding when decompressing an archive created by
.Nm ,
although they still extract it correctly.
.Pp
The compression and decompression is implemented internally, so
there may be insignificant differences between the compressed output
generated by
.Dl Nm Fl czf Pa - file
and that generated by
.Dl Nm Fl cf Pa - file | Nm gzip
.Pp
The default should be to read and write archives to the standard I/O paths,
but tradition (and POSIX) dictates otherwise.
.Pp
The
.Cm r
and
.Cm u
modes require that the archive be uncompressed
and located in a regular file on disk.
Other archives can be modified using
.Cm c
mode with the
.Pa @archive-file
extension.
.Pp
To archive a file called
.Pa @foo
or
.Pa -foo
you must specify it as
.Pa ./@foo
or
.Pa ./-foo ,
respectively.
.Pp
In create mode, a leading
.Pa ./
is always removed.
A leading
.Pa /
is stripped unless the
.Fl P
option is specified.
.Pp
There needs to be better support for file selection on both create
and extract.
.Pp
There is not yet any support for multi-volume archives or for archiving
sparse files.
.Pp
Converting between dissimilar archive formats (such as tar and cpio) using the
.Cm @ Ns Pa -
convention can cause hard link information to be lost.
(This is a consequence of the incompatible ways that different archive
formats store hardlink information.)
.Pp
There are alternative long options for many of the short options that
are deliberately not documented.

734
commands/bsdtar/bsdtar.c Normal file
View file

@ -0,0 +1,734 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bsdtar_platform.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.93 2008/11/08 04:43:24 kientzle Exp $");
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_ZLIB_H
#include <zlib.h>
#endif
#include "bsdtar.h"
#include "err.h"
/*
* Per POSIX.1-1988, tar defaults to reading/writing archives to/from
* the default tape device for the system. Pick something reasonable here.
*/
#ifdef __linux
#define _PATH_DEFTAPE "/dev/st0"
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#define _PATH_DEFTAPE "\\\\.\\tape0"
#endif
#ifndef _PATH_DEFTAPE
#define _PATH_DEFTAPE "/dev/tape"
#endif
#ifdef __MINGW32__
int _CRT_glob = 0; /* Disable broken CRT globbing. */
#endif
static struct bsdtar *_bsdtar;
#if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1))
static volatile int siginfo_occurred;
static void
siginfo_handler(int sig)
{
(void)sig; /* UNUSED */
siginfo_occurred = 1;
}
int
need_report(void)
{
int r = siginfo_occurred;
siginfo_occurred = 0;
return (r);
}
#else
int
need_report(void)
{
return (0);
}
#endif
/* External function to parse a date/time string */
time_t get_date(time_t, const char *);
static void long_help(void);
static void only_mode(struct bsdtar *, const char *opt,
const char *valid);
static void set_mode(struct bsdtar *, char opt);
static void version(void);
/* A basic set of security flags to request from libarchive. */
#define SECURITY \
(ARCHIVE_EXTRACT_SECURE_SYMLINKS \
| ARCHIVE_EXTRACT_SECURE_NODOTDOT)
int
main(int argc, char **argv)
{
struct bsdtar *bsdtar, bsdtar_storage;
int opt, t;
char option_o;
char possible_help_request;
char buff[16];
time_t now;
/*
* Use a pointer for consistency, but stack-allocated storage
* for ease of cleanup.
*/
_bsdtar = bsdtar = &bsdtar_storage;
memset(bsdtar, 0, sizeof(*bsdtar));
bsdtar->fd = -1; /* Mark as "unused" */
option_o = 0;
#if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1))
{ /* Catch SIGINFO and SIGUSR1, if they exist. */
struct sigaction sa;
sa.sa_handler = siginfo_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
#ifdef SIGINFO
if (sigaction(SIGINFO, &sa, NULL))
lafe_errc(1, errno, "sigaction(SIGINFO) failed");
#endif
#ifdef SIGUSR1
/* ... and treat SIGUSR1 the same way as SIGINFO. */
if (sigaction(SIGUSR1, &sa, NULL))
lafe_errc(1, errno, "sigaction(SIGUSR1) failed");
#endif
}
#endif
/* Need lafe_progname before calling lafe_warnc. */
if (*argv == NULL)
lafe_progname = "bsdtar";
else {
#if defined(_WIN32) && !defined(__CYGWIN__)
lafe_progname = strrchr(*argv, '\\');
#else
lafe_progname = strrchr(*argv, '/');
#endif
if (lafe_progname != NULL)
lafe_progname++;
else
lafe_progname = *argv;
}
time(&now);
#if HAVE_SETLOCALE
if (setlocale(LC_ALL, "") == NULL)
lafe_warnc(0, "Failed to set default locale");
#endif
#if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER)
bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd');
#endif
possible_help_request = 0;
/* Look up uid of current user for future reference */
bsdtar->user_uid = geteuid();
/* Default: open tape drive. */
bsdtar->filename = getenv("TAPE");
if (bsdtar->filename == NULL)
bsdtar->filename = _PATH_DEFTAPE;
/* Default: preserve mod time on extract */
bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME;
/* Default: Perform basic security checks. */
bsdtar->extract_flags |= SECURITY;
#ifndef _WIN32
/* On POSIX systems, assume --same-owner and -p when run by
* the root user. This doesn't make any sense on Windows. */
if (bsdtar->user_uid == 0) {
/* --same-owner */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
/* -p */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
}
#endif
bsdtar->argv = argv;
bsdtar->argc = argc;
/*
* Comments following each option indicate where that option
* originated: SUSv2, POSIX, GNU tar, star, etc. If there's
* no such comment, then I don't know of anyone else who
* implements that option.
*/
while ((opt = bsdtar_getopt(bsdtar)) != -1) {
switch (opt) {
case 'B': /* GNU tar */
/* libarchive doesn't need this; just ignore it. */
break;
case 'b': /* SUSv2 */
t = atoi(bsdtar->optarg);
if (t <= 0 || t > 8192)
lafe_errc(1, 0,
"Argument to -b is out of range (1..8192)");
bsdtar->bytes_per_block = 512 * t;
break;
case 'C': /* GNU tar */
set_chdir(bsdtar, bsdtar->optarg);
break;
case 'c': /* SUSv2 */
set_mode(bsdtar, opt);
break;
case OPTION_CHECK_LINKS: /* GNU tar */
bsdtar->option_warn_links = 1;
break;
case OPTION_CHROOT: /* NetBSD */
bsdtar->option_chroot = 1;
break;
case OPTION_EXCLUDE: /* GNU tar */
if (lafe_exclude(&bsdtar->matching, bsdtar->optarg))
lafe_errc(1, 0,
"Couldn't exclude %s\n", bsdtar->optarg);
break;
case OPTION_FORMAT: /* GNU tar, others */
bsdtar->create_format = bsdtar->optarg;
break;
case OPTION_OPTIONS:
bsdtar->option_options = bsdtar->optarg;
break;
case 'f': /* SUSv2 */
bsdtar->filename = bsdtar->optarg;
if (strcmp(bsdtar->filename, "-") == 0)
bsdtar->filename = NULL;
break;
case 'H': /* BSD convention */
bsdtar->symlink_mode = 'H';
break;
case 'h': /* Linux Standards Base, gtar; synonym for -L */
bsdtar->symlink_mode = 'L';
/* Hack: -h by itself is the "help" command. */
possible_help_request = 1;
break;
case OPTION_HELP: /* GNU tar, others */
long_help();
exit(0);
break;
case 'I': /* GNU tar */
/*
* TODO: Allow 'names' to come from an archive,
* not just a text file. Design a good UI for
* allowing names and mode/owner to be read
* from an archive, with contents coming from
* disk. This can be used to "refresh" an
* archive or to design archives with special
* permissions without having to create those
* permissions on disk.
*/
bsdtar->names_from_file = bsdtar->optarg;
break;
case OPTION_INCLUDE:
/*
* Noone else has the @archive extension, so
* noone else needs this to filter entries
* when transforming archives.
*/
if (lafe_include(&bsdtar->matching, bsdtar->optarg))
lafe_errc(1, 0,
"Failed to add %s to inclusion list",
bsdtar->optarg);
break;
case 'j': /* GNU tar */
if (bsdtar->create_compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
bsdtar->create_compression);
bsdtar->create_compression = opt;
break;
case 'J': /* GNU tar 1.21 and later */
if (bsdtar->create_compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
bsdtar->create_compression);
bsdtar->create_compression = opt;
break;
case 'k': /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE;
break;
case OPTION_KEEP_NEWER_FILES: /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
break;
case 'L': /* BSD convention */
bsdtar->symlink_mode = 'L';
break;
case 'l': /* SUSv2 and GNU tar beginning with 1.16 */
/* GNU tar 1.13 used -l for --one-file-system */
bsdtar->option_warn_links = 1;
break;
case OPTION_LZMA:
if (bsdtar->create_compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
bsdtar->create_compression);
bsdtar->create_compression = opt;
break;
case 'm': /* SUSv2 */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME;
break;
case 'n': /* GNU tar */
bsdtar->option_no_subdirs = 1;
break;
/*
* Selecting files by time:
* --newer-?time='date' Only files newer than 'date'
* --newer-?time-than='file' Only files newer than time
* on specified file (useful for incremental backups)
* TODO: Add corresponding "older" options to reverse these.
*/
case OPTION_NEWER_CTIME: /* GNU tar */
bsdtar->newer_ctime_sec = get_date(now, bsdtar->optarg);
break;
case OPTION_NEWER_CTIME_THAN:
{
struct stat st;
if (stat(bsdtar->optarg, &st) != 0)
lafe_errc(1, 0,
"Can't open file %s", bsdtar->optarg);
bsdtar->newer_ctime_sec = st.st_ctime;
bsdtar->newer_ctime_nsec =
ARCHIVE_STAT_CTIME_NANOS(&st);
}
break;
case OPTION_NEWER_MTIME: /* GNU tar */
bsdtar->newer_mtime_sec = get_date(now, bsdtar->optarg);
break;
case OPTION_NEWER_MTIME_THAN:
{
struct stat st;
if (stat(bsdtar->optarg, &st) != 0)
lafe_errc(1, 0,
"Can't open file %s", bsdtar->optarg);
bsdtar->newer_mtime_sec = st.st_mtime;
bsdtar->newer_mtime_nsec =
ARCHIVE_STAT_MTIME_NANOS(&st);
}
break;
case OPTION_NODUMP: /* star */
bsdtar->option_honor_nodump = 1;
break;
case OPTION_NO_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM;
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL;
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR;
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS;
break;
case OPTION_NULL: /* GNU tar */
bsdtar->option_null++;
break;
case OPTION_NUMERIC_OWNER: /* GNU tar */
bsdtar->option_numeric_owner++;
break;
case 'O': /* GNU tar */
bsdtar->option_stdout = 1;
break;
case 'o': /* SUSv2 and GNU conflict here, but not fatally */
option_o = 1; /* Record it and resolve it later. */
break;
case OPTION_ONE_FILE_SYSTEM: /* GNU tar */
bsdtar->option_dont_traverse_mounts = 1;
break;
#if 0
/*
* The common BSD -P option is not necessary, since
* our default is to archive symlinks, not follow
* them. This is convenient, as -P conflicts with GNU
* tar anyway.
*/
case 'P': /* BSD convention */
/* Default behavior, no option necessary. */
break;
#endif
case 'P': /* GNU tar */
bsdtar->extract_flags &= ~SECURITY;
bsdtar->option_absolute_paths = 1;
break;
case 'p': /* GNU tar, star */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
break;
case OPTION_POSIX: /* GNU tar */
bsdtar->create_format = "pax";
break;
case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */
bsdtar->option_fast_read = 1;
break;
case 'r': /* SUSv2 */
set_mode(bsdtar, opt);
break;
case 'S': /* NetBSD pax-as-tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE;
break;
case 's': /* NetBSD pax-as-tar */
#if HAVE_REGEX_H
add_substitution(bsdtar, bsdtar->optarg);
#else
lafe_warnc(0,
"-s is not supported by this version of bsdtar");
usage();
#endif
break;
case OPTION_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
break;
case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */
bsdtar->strip_components = atoi(bsdtar->optarg);
break;
case 'T': /* GNU tar */
bsdtar->names_from_file = bsdtar->optarg;
break;
case 't': /* SUSv2 */
set_mode(bsdtar, opt);
bsdtar->verbose++;
break;
case OPTION_TOTALS: /* GNU tar */
bsdtar->option_totals++;
break;
case 'U': /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK;
bsdtar->option_unlink_first = 1;
break;
case 'u': /* SUSv2 */
set_mode(bsdtar, opt);
break;
case 'v': /* SUSv2 */
bsdtar->verbose++;
break;
case OPTION_VERSION: /* GNU convention */
version();
break;
#if 0
/*
* The -W longopt feature is handled inside of
* bsdtar_getopt(), so -W is not available here.
*/
case 'W': /* Obscure GNU convention. */
break;
#endif
case 'w': /* SUSv2 */
bsdtar->option_interactive = 1;
break;
case 'X': /* GNU tar */
if (lafe_exclude_from_file(&bsdtar->matching, bsdtar->optarg))
lafe_errc(1, 0,
"failed to process exclusions from file %s",
bsdtar->optarg);
break;
case 'x': /* SUSv2 */
set_mode(bsdtar, opt);
break;
case 'y': /* FreeBSD version of GNU tar */
if (bsdtar->create_compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
bsdtar->create_compression);
bsdtar->create_compression = opt;
break;
case 'Z': /* GNU tar */
if (bsdtar->create_compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
bsdtar->create_compression);
bsdtar->create_compression = opt;
break;
case 'z': /* GNU tar, star, many others */
if (bsdtar->create_compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
bsdtar->create_compression);
bsdtar->create_compression = opt;
break;
case OPTION_USE_COMPRESS_PROGRAM:
bsdtar->compress_program = bsdtar->optarg;
break;
default:
usage();
}
}
/*
* Sanity-check options.
*/
/* If no "real" mode was specified, treat -h as --help. */
if ((bsdtar->mode == '\0') && possible_help_request) {
long_help();
exit(0);
}
/* Otherwise, a mode is required. */
if (bsdtar->mode == '\0')
lafe_errc(1, 0,
"Must specify one of -c, -r, -t, -u, -x");
/* Check boolean options only permitted in certain modes. */
if (bsdtar->option_dont_traverse_mounts)
only_mode(bsdtar, "--one-file-system", "cru");
if (bsdtar->option_fast_read)
only_mode(bsdtar, "--fast-read", "xt");
if (bsdtar->option_honor_nodump)
only_mode(bsdtar, "--nodump", "cru");
if (option_o > 0) {
switch (bsdtar->mode) {
case 'c':
/*
* In GNU tar, -o means "old format." The
* "ustar" format is the closest thing
* supported by libarchive.
*/
bsdtar->create_format = "ustar";
/* TODO: bsdtar->create_format = "v7"; */
break;
case 'x':
/* POSIX-compatible behavior. */
bsdtar->option_no_owner = 1;
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
default:
only_mode(bsdtar, "-o", "xc");
break;
}
}
if (bsdtar->option_no_subdirs)
only_mode(bsdtar, "-n", "cru");
if (bsdtar->option_stdout)
only_mode(bsdtar, "-O", "xt");
if (bsdtar->option_unlink_first)
only_mode(bsdtar, "-U", "x");
if (bsdtar->option_warn_links)
only_mode(bsdtar, "--check-links", "cr");
/* Check other parameters only permitted in certain modes. */
if (bsdtar->create_compression != '\0') {
strcpy(buff, "-?");
buff[1] = bsdtar->create_compression;
only_mode(bsdtar, buff, "cxt");
}
if (bsdtar->create_format != NULL)
only_mode(bsdtar, "--format", "cru");
if (bsdtar->symlink_mode != '\0') {
strcpy(buff, "-?");
buff[1] = bsdtar->symlink_mode;
only_mode(bsdtar, buff, "cru");
}
if (bsdtar->strip_components != 0)
only_mode(bsdtar, "--strip-components", "xt");
switch(bsdtar->mode) {
case 'c':
tar_mode_c(bsdtar);
break;
case 'r':
tar_mode_r(bsdtar);
break;
case 't':
tar_mode_t(bsdtar);
break;
case 'u':
tar_mode_u(bsdtar);
break;
case 'x':
tar_mode_x(bsdtar);
break;
}
lafe_cleanup_exclusions(&bsdtar->matching);
#if HAVE_REGEX_H
cleanup_substitution(bsdtar);
#endif
if (bsdtar->return_value != 0)
lafe_warnc(0,
"Error exit delayed from previous errors.");
return (bsdtar->return_value);
}
static void
set_mode(struct bsdtar *bsdtar, char opt)
{
if (bsdtar->mode != '\0' && bsdtar->mode != opt)
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt, bsdtar->mode);
bsdtar->mode = opt;
}
/*
* Verify that the mode is correct.
*/
static void
only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes)
{
if (strchr(valid_modes, bsdtar->mode) == NULL)
lafe_errc(1, 0,
"Option %s is not permitted in mode -%c",
opt, bsdtar->mode);
}
void
usage(void)
{
const char *p;
p = lafe_progname;
fprintf(stderr, "Usage:\n");
fprintf(stderr, " List: %s -tf <archive-filename>\n", p);
fprintf(stderr, " Extract: %s -xf <archive-filename>\n", p);
fprintf(stderr, " Create: %s -cf <archive-filename> [filenames...]\n", p);
fprintf(stderr, " Help: %s --help\n", p);
exit(1);
}
static void
version(void)
{
printf("bsdtar %s - %s\n",
BSDTAR_VERSION_STRING,
archive_version());
exit(0);
}
static const char *long_help_msg =
"First option must be a mode specifier:\n"
" -c Create -r Add/Replace -t List -u Update -x Extract\n"
"Common Options:\n"
" -b # Use # 512-byte records per I/O block\n"
" -f <filename> Location of archive (default " _PATH_DEFTAPE ")\n"
" -v Verbose\n"
" -w Interactive\n"
"Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n"
" <file>, <dir> add these items to archive\n"
" -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n"
" --format {ustar|pax|cpio|shar} Select archive format\n"
" --exclude <pattern> Skip files that match pattern\n"
" -C <dir> Change to <dir> before processing remaining files\n"
" @<archive> Add entries from <archive> to output\n"
"List: %p -t [options] [<patterns>]\n"
" <patterns> If specified, list only entries that match\n"
"Extract: %p -x [options] [<patterns>]\n"
" <patterns> If specified, extract only entries that match\n"
" -k Keep (don't overwrite) existing files\n"
" -m Don't restore modification times\n"
" -O Write entries to stdout, don't restore to disk\n"
" -p Restore permissions (including ACLs, owner, file flags)\n";
/*
* Note that the word 'bsdtar' will always appear in the first line
* of output.
*
* In particular, /bin/sh scripts that need to test for the presence
* of bsdtar can use the following template:
*
* if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \
* echo bsdtar; else echo not bsdtar; fi
*/
static void
long_help(void)
{
const char *prog;
const char *p;
prog = lafe_progname;
fflush(stderr);
p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : "";
printf("%s%s: manipulate archive files\n", prog, p);
for (p = long_help_msg; *p != '\0'; p++) {
if (*p == '%') {
if (p[1] == 'p') {
fputs(prog, stdout);
p++;
} else
putchar('%');
} else
putchar(*p);
}
version();
}

165
commands/bsdtar/bsdtar.h Normal file
View file

@ -0,0 +1,165 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.37 2008/12/06 07:37:14 kientzle Exp $
*/
#include "bsdtar_platform.h"
#include <stdio.h>
#include "matching.h"
#define DEFAULT_BYTES_PER_BLOCK (20*512)
/*
* The internal state for the "bsdtar" program.
*
* Keeping all of the state in a structure like this simplifies memory
* leak testing (at exit, anything left on the heap is suspect). A
* pointer to this structure is passed to most bsdtar internal
* functions.
*/
struct bsdtar {
/* Options */
const char *filename; /* -f filename */
const char *create_format; /* -F format */
char *pending_chdir; /* -C dir */
const char *names_from_file; /* -T file */
time_t newer_ctime_sec; /* --newer/--newer-than */
long newer_ctime_nsec; /* --newer/--newer-than */
time_t newer_mtime_sec; /* --newer-mtime */
long newer_mtime_nsec; /* --newer-mtime-than */
int bytes_per_block; /* -b block_size */
int verbose; /* -v */
int extract_flags; /* Flags for extract operation */
int strip_components; /* Remove this many leading dirs */
char mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */
char symlink_mode; /* H or L, per BSD conventions */
char create_compression; /* j, y, or z */
const char *compress_program;
char option_absolute_paths; /* -P */
char option_chroot; /* --chroot */
char option_dont_traverse_mounts; /* --one-file-system */
char option_fast_read; /* --fast-read */
const char *option_options; /* --options */
char option_honor_nodump; /* --nodump */
char option_interactive; /* -w */
char option_no_owner; /* -o */
char option_no_subdirs; /* -n */
char option_null; /* --null */
char option_numeric_owner; /* --numeric-owner */
char option_stdout; /* -O */
char option_totals; /* --totals */
char option_unlink_first; /* -U */
char option_warn_links; /* --check-links */
char day_first; /* show day before month in -tv output */
/* If >= 0, then close this when done. */
int fd;
/* Miscellaneous state information */
int argc;
char **argv;
const char *optarg;
size_t gs_width; /* For 'list_item' in read.c */
size_t u_width; /* for 'list_item' in read.c */
uid_t user_uid; /* UID running this program */
int return_value; /* Value returned by main() */
char warned_lead_slash; /* Already displayed warning */
char next_line_is_dir; /* Used for -C parsing in -cT */
/*
* Data for various subsystems. Full definitions are located in
* the file where they are used.
*/
struct archive *diskreader; /* for write.c */
struct archive_entry_linkresolver *resolver; /* for write.c */
struct archive_dir *archive_dir; /* for write.c */
struct name_cache *gname_cache; /* for write.c */
char *buff; /* for write.c */
struct lafe_matching *matching; /* for matching.c */
struct security *security; /* for read.c */
struct name_cache *uname_cache; /* for write.c */
struct siginfo_data *siginfo; /* for siginfo.c */
struct substitution *substitution; /* for subst.c */
};
/* Fake short equivalents for long options that otherwise lack them. */
enum {
OPTION_CHECK_LINKS = 1,
OPTION_CHROOT,
OPTION_EXCLUDE,
OPTION_FORMAT,
OPTION_OPTIONS,
OPTION_HELP,
OPTION_INCLUDE,
OPTION_KEEP_NEWER_FILES,
OPTION_LZMA,
OPTION_NEWER_CTIME,
OPTION_NEWER_CTIME_THAN,
OPTION_NEWER_MTIME,
OPTION_NEWER_MTIME_THAN,
OPTION_NODUMP,
OPTION_NO_SAME_OWNER,
OPTION_NO_SAME_PERMISSIONS,
OPTION_NULL,
OPTION_NUMERIC_OWNER,
OPTION_ONE_FILE_SYSTEM,
OPTION_POSIX,
OPTION_SAME_OWNER,
OPTION_STRIP_COMPONENTS,
OPTION_TOTALS,
OPTION_USE_COMPRESS_PROGRAM,
OPTION_VERSION
};
int bsdtar_getopt(struct bsdtar *);
void do_chdir(struct bsdtar *);
int edit_pathname(struct bsdtar *, struct archive_entry *);
int need_report(void);
int pathcmp(const char *a, const char *b);
void safe_fprintf(FILE *, const char *fmt, ...);
void set_chdir(struct bsdtar *, const char *newdir);
#ifndef __minix
const char *tar_i64toa(int64_t);
#else
/* This is not really 64itoa, but it is simpler to do this than replace
* tar_i64toa everywhere
*/
const char *tar_i64toa(int32_t);
#endif
void tar_mode_c(struct bsdtar *bsdtar);
void tar_mode_r(struct bsdtar *bsdtar);
void tar_mode_t(struct bsdtar *bsdtar);
void tar_mode_u(struct bsdtar *bsdtar);
void tar_mode_x(struct bsdtar *bsdtar);
void usage(void);
int yes(const char *fmt, ...);
#if HAVE_REGEX_H
void add_substitution(struct bsdtar *, const char *);
int apply_substitution(struct bsdtar *, const char *, char **, int);
void cleanup_substitution(struct bsdtar *);
#endif

View file

@ -0,0 +1,132 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $
*/
/*
* This header is the first thing included in any of the bsdtar
* source files. As far as possible, platform-specific issues should
* be dealt with here and not within individual source files.
*/
#ifndef BSDTAR_PLATFORM_H_INCLUDED
#define BSDTAR_PLATFORM_H_INCLUDED
#if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H
#else
/* Not having a config.h of some sort is a serious problem. */
#include "config.h"
#endif
/* Get a real definition for __FBSDID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#ifdef HAVE_LIBARCHIVE
/* If we're using the platform libarchive, include system headers. */
#include <archive.h>
#include <archive_entry.h>
#else
/* Otherwise, include user headers. */
#include "archive.h"
#include "archive_entry.h"
#endif
#ifdef HAVE_LIBACL
#include <acl/libacl.h>
#endif
/*
* Include "dirent.h" (or it's equivalent on several different platforms).
*
* This is slightly modified from the GNU autoconf recipe.
* In particular, FreeBSD includes d_namlen in it's dirent structure,
* so my configure script includes an explicit test for the d_namlen
* field.
*/
#if HAVE_DIRENT_H
# include <dirent.h>
# if HAVE_DIRENT_D_NAMLEN
# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen
# else
# define DIRENT_NAMLEN(dirent) strlen((dirent)->d_name)
# endif
#else
# define dirent direct
# define DIRENT_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
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctimespec.tv_nsec
#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtimespec.tv_nsec
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctim.tv_nsec
#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtim.tv_nsec
#elif HAVE_STRUCT_STAT_ST_MTIME_N
#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctime_n
#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtime_n
#elif HAVE_STRUCT_STAT_ST_UMTIME
#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_uctime * 1000
#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_umtime * 1000
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctime_usec * 1000
#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtime_usec * 1000
#else
#define ARCHIVE_STAT_CTIME_NANOS(st) (0)
#define ARCHIVE_STAT_MTIME_NANOS(st) (0)
#endif
/* How to mark functions that don't return. */
/* This facilitates use of some newer static code analysis tools. */
#undef __LA_DEAD
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
#define __LA_DEAD __attribute__((__noreturn__))
#else
#define __LA_DEAD
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "bsdtar_windows.h"
#endif
#endif /* !BSDTAR_PLATFORM_H_INCLUDED */

381
commands/bsdtar/cmdline.c Normal file
View file

@ -0,0 +1,381 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Command line parser for tar.
*/
#include "bsdtar_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "bsdtar.h"
#include "err.h"
/*
* Short options for tar. Please keep this sorted.
*/
static const char *short_options
= "Bb:C:cf:HhI:JjkLlmnOoPpqrSs:T:tUuvW:wX:xyZz";
/*
* Long options for tar. Please keep this list sorted.
*
* The symbolic names for options that lack a short equivalent are
* defined in bsdtar.h. Also note that so far I've found no need
* to support optional arguments to long options. That would be
* a small change to the code below.
*/
static struct option {
const char *name;
int required; /* 1 if this option requires an argument. */
int equivalent; /* Equivalent short option. */
} tar_longopts[] = {
{ "absolute-paths", 0, 'P' },
{ "append", 0, 'r' },
{ "block-size", 1, 'b' },
{ "bunzip2", 0, 'j' },
{ "bzip", 0, 'j' },
{ "bzip2", 0, 'j' },
{ "cd", 1, 'C' },
{ "check-links", 0, OPTION_CHECK_LINKS },
{ "chroot", 0, OPTION_CHROOT },
{ "compress", 0, 'Z' },
{ "confirmation", 0, 'w' },
{ "create", 0, 'c' },
{ "dereference", 0, 'L' },
{ "directory", 1, 'C' },
{ "exclude", 1, OPTION_EXCLUDE },
{ "exclude-from", 1, 'X' },
{ "extract", 0, 'x' },
{ "fast-read", 0, 'q' },
{ "file", 1, 'f' },
{ "files-from", 1, 'T' },
{ "format", 1, OPTION_FORMAT },
{ "options", 1, OPTION_OPTIONS },
{ "gunzip", 0, 'z' },
{ "gzip", 0, 'z' },
{ "help", 0, OPTION_HELP },
{ "include", 1, OPTION_INCLUDE },
{ "interactive", 0, 'w' },
{ "insecure", 0, 'P' },
{ "keep-newer-files", 0, OPTION_KEEP_NEWER_FILES },
{ "keep-old-files", 0, 'k' },
{ "list", 0, 't' },
{ "lzma", 0, OPTION_LZMA },
{ "modification-time", 0, 'm' },
{ "newer", 1, OPTION_NEWER_CTIME },
{ "newer-ctime", 1, OPTION_NEWER_CTIME },
{ "newer-ctime-than", 1, OPTION_NEWER_CTIME_THAN },
{ "newer-mtime", 1, OPTION_NEWER_MTIME },
{ "newer-mtime-than", 1, OPTION_NEWER_MTIME_THAN },
{ "newer-than", 1, OPTION_NEWER_CTIME_THAN },
{ "nodump", 0, OPTION_NODUMP },
{ "norecurse", 0, 'n' },
{ "no-recursion", 0, 'n' },
{ "no-same-owner", 0, OPTION_NO_SAME_OWNER },
{ "no-same-permissions", 0, OPTION_NO_SAME_PERMISSIONS },
{ "null", 0, OPTION_NULL },
{ "numeric-owner", 0, OPTION_NUMERIC_OWNER },
{ "one-file-system", 0, OPTION_ONE_FILE_SYSTEM },
{ "posix", 0, OPTION_POSIX },
{ "preserve-permissions", 0, 'p' },
{ "read-full-blocks", 0, 'B' },
{ "same-owner", 0, OPTION_SAME_OWNER },
{ "same-permissions", 0, 'p' },
{ "strip-components", 1, OPTION_STRIP_COMPONENTS },
{ "to-stdout", 0, 'O' },
{ "totals", 0, OPTION_TOTALS },
{ "uncompress", 0, 'Z' },
{ "unlink", 0, 'U' },
{ "unlink-first", 0, 'U' },
{ "update", 0, 'u' },
{ "use-compress-program", 1, OPTION_USE_COMPRESS_PROGRAM },
{ "verbose", 0, 'v' },
{ "version", 0, OPTION_VERSION },
{ "xz", 0, 'J' },
{ NULL, 0, 0 }
};
/*
* This getopt implementation has two key features that common
* getopt_long() implementations lack. Apart from those, it's a
* straightforward option parser, considerably simplified by not
* needing to support the wealth of exotic getopt_long() features. It
* has, of course, been shamelessly tailored for bsdtar. (If you're
* looking for a generic getopt_long() implementation for your
* project, I recommend Gregory Pietsch's public domain getopt_long()
* implementation.) The two additional features are:
*
* Old-style tar arguments: The original tar implementation treated
* the first argument word as a list of single-character option
* letters. All arguments follow as separate words. For example,
* tar xbf 32 /dev/tape
* Here, the "xbf" is three option letters, "32" is the argument for
* "b" and "/dev/tape" is the argument for "f". We support this usage
* if the first command-line argument does not begin with '-'. We
* also allow regular short and long options to follow, e.g.,
* tar xbf 32 /dev/tape -P --format=pax
*
* -W long options: There's an obscure GNU convention (only rarely
* supported even there) that allows "-W option=argument" as an
* alternative way to support long options. This was supported in
* early bsdtar as a way to access long options on platforms that did
* not support getopt_long() and is preserved here for backwards
* compatibility. (Of course, if I'd started with a custom
* command-line parser from the beginning, I would have had normal
* long option support on every platform so that hack wouldn't have
* been necessary. Oh, well. Some mistakes you just have to live
* with.)
*
* TODO: We should be able to use this to pull files and intermingled
* options (such as -C) from the command line in write mode. That
* will require a little rethinking of the argument handling in
* bsdtar.c.
*
* TODO: If we want to support arbitrary command-line options from -T
* input (as GNU tar does), we may need to extend this to handle option
* words from sources other than argv/arc. I'm not really sure if I
* like that feature of GNU tar, so it's certainly not a priority.
*/
int
bsdtar_getopt(struct bsdtar *bsdtar)
{
enum { state_start = 0, state_old_tar, state_next_word,
state_short, state_long };
static int state = state_start;
static char *opt_word;
const struct option *popt, *match = NULL, *match2 = NULL;
const char *p, *long_prefix = "--";
size_t optlength;
int opt = '?';
int required = 0;
bsdtar->optarg = NULL;
/* First time through, initialize everything. */
if (state == state_start) {
/* Skip program name. */
++bsdtar->argv;
--bsdtar->argc;
if (*bsdtar->argv == NULL)
return (-1);
/* Decide between "new style" and "old style" arguments. */
if (bsdtar->argv[0][0] == '-') {
state = state_next_word;
} else {
state = state_old_tar;
opt_word = *bsdtar->argv++;
--bsdtar->argc;
}
}
/*
* We're parsing old-style tar arguments
*/
if (state == state_old_tar) {
/* Get the next option character. */
opt = *opt_word++;
if (opt == '\0') {
/* New-style args can follow old-style. */
state = state_next_word;
} else {
/* See if it takes an argument. */
p = strchr(short_options, opt);
if (p == NULL)
return ('?');
if (p[1] == ':') {
bsdtar->optarg = *bsdtar->argv;
if (bsdtar->optarg == NULL) {
lafe_warnc(0,
"Option %c requires an argument",
opt);
return ('?');
}
++bsdtar->argv;
--bsdtar->argc;
}
}
}
/*
* We're ready to look at the next word in argv.
*/
if (state == state_next_word) {
/* No more arguments, so no more options. */
if (bsdtar->argv[0] == NULL)
return (-1);
/* Doesn't start with '-', so no more options. */
if (bsdtar->argv[0][0] != '-')
return (-1);
/* "--" marks end of options; consume it and return. */
if (strcmp(bsdtar->argv[0], "--") == 0) {
++bsdtar->argv;
--bsdtar->argc;
return (-1);
}
/* Get next word for parsing. */
opt_word = *bsdtar->argv++;
--bsdtar->argc;
if (opt_word[1] == '-') {
/* Set up long option parser. */
state = state_long;
opt_word += 2; /* Skip leading '--' */
} else {
/* Set up short option parser. */
state = state_short;
++opt_word; /* Skip leading '-' */
}
}
/*
* We're parsing a group of POSIX-style single-character options.
*/
if (state == state_short) {
/* Peel next option off of a group of short options. */
opt = *opt_word++;
if (opt == '\0') {
/* End of this group; recurse to get next option. */
state = state_next_word;
return bsdtar_getopt(bsdtar);
}
/* Does this option take an argument? */
p = strchr(short_options, opt);
if (p == NULL)
return ('?');
if (p[1] == ':')
required = 1;
/* If it takes an argument, parse that. */
if (required) {
/* If arg is run-in, opt_word already points to it. */
if (opt_word[0] == '\0') {
/* Otherwise, pick up the next word. */
opt_word = *bsdtar->argv;
if (opt_word == NULL) {
lafe_warnc(0,
"Option -%c requires an argument",
opt);
return ('?');
}
++bsdtar->argv;
--bsdtar->argc;
}
if (opt == 'W') {
state = state_long;
long_prefix = "-W "; /* For clearer errors. */
} else {
state = state_next_word;
bsdtar->optarg = opt_word;
}
}
}
/* We're reading a long option, including -W long=arg convention. */
if (state == state_long) {
/* After this long option, we'll be starting a new word. */
state = state_next_word;
/* Option name ends at '=' if there is one. */
p = strchr(opt_word, '=');
if (p != NULL) {
optlength = (size_t)(p - opt_word);
bsdtar->optarg = (char *)(uintptr_t)(p + 1);
} else {
optlength = strlen(opt_word);
}
/* Search the table for an unambiguous match. */
for (popt = tar_longopts; popt->name != NULL; popt++) {
/* Short-circuit if first chars don't match. */
if (popt->name[0] != opt_word[0])
continue;
/* If option is a prefix of name in table, record it.*/
if (strncmp(opt_word, popt->name, optlength) == 0) {
match2 = match; /* Record up to two matches. */
match = popt;
/* If it's an exact match, we're done. */
if (strlen(popt->name) == optlength) {
match2 = NULL; /* Forget the others. */
break;
}
}
}
/* Fail if there wasn't a unique match. */
if (match == NULL) {
lafe_warnc(0,
"Option %s%s is not supported",
long_prefix, opt_word);
return ('?');
}
if (match2 != NULL) {
lafe_warnc(0,
"Ambiguous option %s%s (matches --%s and --%s)",
long_prefix, opt_word, match->name, match2->name);
return ('?');
}
/* We've found a unique match; does it need an argument? */
if (match->required) {
/* Argument required: get next word if necessary. */
if (bsdtar->optarg == NULL) {
bsdtar->optarg = *bsdtar->argv;
if (bsdtar->optarg == NULL) {
lafe_warnc(0,
"Option %s%s requires an argument",
long_prefix, match->name);
return ('?');
}
++bsdtar->argv;
--bsdtar->argc;
}
} else {
/* Argument forbidden: fail if there is one. */
if (bsdtar->optarg != NULL) {
lafe_warnc(0,
"Option %s%s does not allow an argument",
long_prefix, match->name);
return ('?');
}
}
return (match->equivalent);
}
return (opt);
}

763
commands/bsdtar/config.h Normal file
View file

@ -0,0 +1,763 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Version number of bsdcpio */
#define BSDCPIO_VERSION_STRING "2.8.3"
/* Version number of bsdtar */
#define BSDTAR_VERSION_STRING "2.8.3"
/* Define to 1 if you have the `acl_create_entry' function. */
/* #undef HAVE_ACL_CREATE_ENTRY */
/* Define to 1 if you have the `acl_get_link' function. */
/* #undef HAVE_ACL_GET_LINK */
/* Define to 1 if you have the `acl_get_link_np' function. */
/* #undef HAVE_ACL_GET_LINK_NP */
/* Define to 1 if you have the `acl_get_perm' function. */
/* #undef HAVE_ACL_GET_PERM */
/* Define to 1 if you have the `acl_get_perm_np' function. */
/* #undef HAVE_ACL_GET_PERM_NP */
/* Define to 1 if you have the `acl_init' function. */
/* #undef HAVE_ACL_INIT */
/* Define to 1 if you have the <acl/libacl.h> header file. */
/* #undef HAVE_ACL_LIBACL_H */
/* Define to 1 if the system has the type `acl_permset_t'. */
/* #undef HAVE_ACL_PERMSET_T */
/* Define to 1 if you have the `acl_set_fd' function. */
/* #undef HAVE_ACL_SET_FD */
/* Define to 1 if you have the `acl_set_fd_np' function. */
/* #undef HAVE_ACL_SET_FD_NP */
/* Define to 1 if you have the `acl_set_file' function. */
/* #undef HAVE_ACL_SET_FILE */
/* True for systems with POSIX ACL support */
/* #undef HAVE_ACL_USER */
/* Define to 1 if you have the <attr/xattr.h> header file. */
/* #undef HAVE_ATTR_XATTR_H */
/* Define to 1 if you have the <bzlib.h> header file. */
#define HAVE_BZLIB_H 1
/* Define to 1 if you have the `chflags' function. */
/* #undef HAVE_CHFLAGS */
/* Define to 1 if you have the `chown' function. */
#define HAVE_CHOWN 1
/* Define to 1 if you have the `chroot' function. */
#define HAVE_CHROOT 1
/* Define to 1 if you have the <ctype.h> header file. */
#define HAVE_CTYPE_H 1
/* Define to 1 if you have the `cygwin_conv_path' function. */
/* #undef HAVE_CYGWIN_CONV_PATH */
/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
don't. */
#define HAVE_DECL_INT64_MAX 0
/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
don't. */
#define HAVE_DECL_INT64_MIN 0
/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
don't. */
#define HAVE_DECL_SIZE_MAX 1
/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
don't. */
#define HAVE_DECL_SSIZE_MAX 1
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
don't. */
#define HAVE_DECL_STRERROR_R 0
/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
don't. */
#define HAVE_DECL_UINT32_MAX 1
/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
don't. */
#define HAVE_DECL_UINT64_MAX 0
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#define HAVE_DIRENT_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#define HAVE_DOPRNT 1
/* Define to 1 if nl_langinfo supports D_MD_ORDER */
/* #undef HAVE_D_MD_ORDER */
/* A possible errno value for invalid file format errors */
/* #undef HAVE_EFTYPE */
/* A possible errno value for invalid file format errors */
#define HAVE_EILSEQ 1
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the <expat.h> header file. */
/* #undef HAVE_EXPAT_H */
/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
/* #undef HAVE_EXT2FS_EXT2_FS_H */
/* Define to 1 if you have the `extattr_get_file' function. */
/* #undef HAVE_EXTATTR_GET_FILE */
/* Define to 1 if you have the `extattr_list_file' function. */
/* #undef HAVE_EXTATTR_LIST_FILE */
/* Define to 1 if you have the `extattr_set_fd' function. */
/* #undef HAVE_EXTATTR_SET_FD */
/* Define to 1 if you have the `extattr_set_file' function. */
/* #undef HAVE_EXTATTR_SET_FILE */
/* Define to 1 if you have the `fchdir' function. */
#define HAVE_FCHDIR 1
/* Define to 1 if you have the `fchflags' function. */
/* #undef HAVE_FCHFLAGS */
/* Define to 1 if you have the `fchmod' function. */
#define HAVE_FCHMOD 1
/* Define to 1 if you have the `fchown' function. */
#define HAVE_FCHOWN 1
/* Define to 1 if you have the `fcntl' function. */
#define HAVE_FCNTL 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `fork' function. */
#define HAVE_FORK 1
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
/* #undef HAVE_FSEEKO */
/* Define to 1 if you have the `fsetxattr' function. */
/* #undef HAVE_FSETXATTR */
/* Define to 1 if you have the `fstat' function. */
#define HAVE_FSTAT 1
/* Define to 1 if you have the `ftruncate' function. */
#define HAVE_FTRUNCATE 1
/* Define to 1 if you have the `futimens' function. */
/* #undef HAVE_FUTIMENS */
/* Define to 1 if you have the `futimes' function. */
/* #undef HAVE_FUTIMES */
/* Define to 1 if you have the `geteuid' function. */
#define HAVE_GETEUID 1
/* Define to 1 if you have the `getgrgid_r' function. */
/* #undef HAVE_GETGRGID_R */
/* Define to 1 if you have the `getgrnam_r' function. */
/* #undef HAVE_GETGRNAM_R */
/* Define to 1 if you have the `getpid' function. */
#define HAVE_GETPID 1
/* Define to 1 if you have the `getpwnam_r' function. */
/* #undef HAVE_GETPWNAM_R */
/* Define to 1 if you have the `getpwuid_r' function. */
/* #undef HAVE_GETPWUID_R */
/* Define to 1 if you have the `getxattr' function. */
/* #undef HAVE_GETXATTR */
/* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1
/* Define to 1 if the system has the type `intmax_t'. */
#define HAVE_INTMAX_T 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <io.h> header file. */
/* #undef HAVE_IO_H */
/* Define to 1 if you have the <langinfo.h> header file. */
/* #undef HAVE_LANGINFO_H */
/* Define to 1 if you have the `lchflags' function. */
/* #undef HAVE_LCHFLAGS */
/* Define to 1 if you have the `lchmod' function. */
/* #undef HAVE_LCHMOD */
/* Define to 1 if you have the `lchown' function. */
/* #undef HAVE_LCHOWN */
/* Define to 1 if you have the `lgetxattr' function. */
/* #undef HAVE_LGETXATTR */
/* Define to 1 if you have the `acl' library (-lacl). */
/* #undef HAVE_LIBACL */
/* Define to 1 if you have the `attr' library (-lattr). */
/* #undef HAVE_LIBATTR */
/* Define to 1 if you have the `bz2' library (-lbz2). */
#define HAVE_LIBBZ2 1
/* Define to 1 if you have the `expat' library (-lexpat). */
/* #undef HAVE_LIBEXPAT */
/* Define to 1 if you have the `lzma' library (-llzma). */
/* #undef HAVE_LIBLZMA */
/* Define to 1 if you have the `lzmadec' library (-llzmadec). */
/* #undef HAVE_LIBLZMADEC */
/* Define to 1 if you have the `xml2' library (-lxml2). */
/* #undef HAVE_LIBXML2 */
/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
/* #undef HAVE_LIBXML_XMLREADER_H */
/* Define to 1 if you have the `z' library (-lz). */
#define HAVE_LIBZ 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the `link' function. */
#define HAVE_LINK 1
/* Define to 1 if you have the <linux/fs.h> header file. */
/* #undef HAVE_LINUX_FS_H */
/* Define to 1 if you have the `listxattr' function. */
/* #undef HAVE_LISTXATTR */
/* Define to 1 if you have the `llistxattr' function. */
/* #undef HAVE_LLISTXATTR */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if the system has the type `long long int'. */
/* #undef HAVE_LONG_LONG_INT */
/* Define to 1 if you have the `lsetxattr' function. */
/* #undef HAVE_LSETXATTR */
/* Define to 1 if you have the `lstat' function. */
#define HAVE_LSTAT 1
/* Define to 1 if `lstat' has the bug that it succeeds when given the
zero-length file name argument. */
/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
/* Define to 1 if you have the `lutimes' function. */
/* #undef HAVE_LUTIMES */
/* Define to 1 if you have the <lzmadec.h> header file. */
/* #undef HAVE_LZMADEC_H */
/* Define to 1 if you have the <lzma.h> header file. */
/* #undef HAVE_LZMA_H */
/* Define to 1 if you have the `MD5Init' function. */
/* #undef HAVE_MD5INIT */
/* Define to 1 if you have the <md5.h> header file. */
/* #undef HAVE_MD5_H */
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H */
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the `mkdir' function. */
#define HAVE_MKDIR 1
/* Define to 1 if you have the `mkfifo' function. */
#define HAVE_MKFIFO 1
/* Define to 1 if you have the `mknod' function. */
#define HAVE_MKNOD 1
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
/* Define to 1 if you have the `nl_langinfo' function. */
/* #undef HAVE_NL_LANGINFO */
/* Define to 1 if you have the <openssl/md5.h> header file. */
/* #undef HAVE_OPENSSL_MD5_H */
/* Define to 1 if you have the <openssl/ripemd.h> header file. */
/* #undef HAVE_OPENSSL_RIPEMD_H */
/* Define to 1 if your openssl has the `SHA256_Init' function. */
/* #undef HAVE_OPENSSL_SHA256_INIT */
/* Define to 1 if your openssl has the `SHA384_Init' function. */
/* #undef HAVE_OPENSSL_SHA384_INIT */
/* Define to 1 if your openssl has the `SHA512_Init' function. */
/* #undef HAVE_OPENSSL_SHA512_INIT */
/* Define to 1 if you have the <openssl/sha.h> header file. */
/* #undef HAVE_OPENSSL_SHA_H */
/* Define to 1 if you have the <paths.h> header file. */
/* #undef HAVE_PATHS_H */
/* Define to 1 if you have the `pipe' function. */
#define HAVE_PIPE 1
/* Define to 1 if you have the `poll' function. */
/* #undef HAVE_POLL */
/* Define to 1 if you have the <poll.h> header file. */
/* #undef HAVE_POLL_H */
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define to 1 if you have the `readlink' function. */
#define HAVE_READLINK 1
/* Define to 1 if you have the <regex.h> header file. */
#define HAVE_REGEX_H 1
/* Define to 1 if you have the <ripemd.h> header file. */
/* #undef HAVE_RIPEMD_H */
/* Define to 1 if you have the `RMD160Init' function. */
/* #undef HAVE_RMD160INIT */
/* Define to 1 if you have the <rmd160.h> header file. */
/* #undef HAVE_RMD160_H */
/* Define to 1 if you have the `select' function. */
#define HAVE_SELECT 1
/* Define to 1 if you have the `setenv' function. */
#define HAVE_SETENV 1
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the `SHA1Init' function. */
/* #undef HAVE_SHA1INIT */
/* Define to 1 if you have the <sha1.h> header file. */
/* #undef HAVE_SHA1_H */
/* Define to 1 if you have the `SHA256Init' function. */
/* #undef HAVE_SHA256INIT */
/* Define to 1 if you have the <sha256.h> header file. */
/* #undef HAVE_SHA256_H */
/* Define to 1 if you have the `SHA256_Init' function. */
/* #undef HAVE_SHA256_INIT */
/* Define to 1 if you have the <sha2.h> header file. */
/* #undef HAVE_SHA2_H */
/* Define to 1 if you have the `SHA384Init' function. */
/* #undef HAVE_SHA384INIT */
/* Define to 1 if you have the `SHA384_Init' function. */
/* #undef HAVE_SHA384_INIT */
/* Define to 1 if you have the `SHA512Init' function. */
/* #undef HAVE_SHA512INIT */
/* Define to 1 if you have the `SHA512_Init' function. */
/* #undef HAVE_SHA512_INIT */
/* Define to 1 if you have the <sha.h> header file. */
/* #undef HAVE_SHA_H */
/* Define to 1 if you have the `sigaction' function. */
#define HAVE_SIGACTION 1
/* Define to 1 if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the `strerror_r' function. */
/* #undef HAVE_STRERROR_R */
/* Define to 1 if you have the `strftime' function. */
#define HAVE_STRFTIME 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncpy_s' function. */
/* #undef HAVE_STRNCPY_S */
/* Define to 1 if you have the `strrchr' function. */
#define HAVE_STRRCHR 1
/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */
/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC */
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */
/* Define to 1 if `st_flags' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_FLAGS */
/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC */
/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_MTIME_USEC */
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */
/* Define to 1 if `st_umtime' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_UMTIME */
/* Define to 1 if you have the `symlink' function. */
#define HAVE_SYMLINK 1
/* Define to 1 if you have the <sys/acl.h> header file. */
/* #undef HAVE_SYS_ACL_H */
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_DIR_H */
/* Define to 1 if you have the <sys/extattr.h> header file. */
/* #undef HAVE_SYS_EXTATTR_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/mkdev.h> header file. */
/* #undef HAVE_SYS_MKDEV_H */
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_NDIR_H */
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/poll.h> header file. */
/* #undef HAVE_SYS_POLL_H */
/* Define to 1 if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/utime.h> header file. */
/* #undef HAVE_SYS_UTIME_H */
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#define HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <sys/xattr.h> header file. */
/* #undef HAVE_SYS_XATTR_H */
/* Define to 1 if you have the `timegm' function. */
#define HAVE_TIMEGM 1
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
/* Define to 1 if you have the `tzset' function. */
#define HAVE_TZSET 1
/* Define to 1 if the system has the type `uintmax_t'. */
#define HAVE_UINTMAX_T 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `unsetenv' function. */
#define HAVE_UNSETENV 1
/* Define to 1 if the system has the type `unsigned long long'. */
/* #undef HAVE_UNSIGNED_LONG_LONG */
/* Define to 1 if the system has the type `unsigned long long int'. */
/* #undef HAVE_UNSIGNED_LONG_LONG_INT */
/* Define to 1 if you have the `utime' function. */
#define HAVE_UTIME 1
/* Define to 1 if you have the `utimensat' function. */
/* #undef HAVE_UTIMENSAT */
/* Define to 1 if you have the `utimes' function. */
/* #undef HAVE_UTIMES */
/* Define to 1 if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
/* Define to 1 if you have the `vfork' function. */
/* #undef HAVE_VFORK */
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the <wchar.h> header file. */
#define HAVE_WCHAR_H 1
/* Define to 1 if the system has the type `wchar_t'. */
#define HAVE_WCHAR_T 1
/* Define to 1 if you have the `wcrtomb' function. */
/* #undef HAVE_WCRTOMB */
/* Define to 1 if you have the `wcscpy' function. */
#define HAVE_WCSCPY 1
/* Define to 1 if you have the `wcslen' function. */
#define HAVE_WCSLEN 1
/* Define to 1 if you have the `wctomb' function. */
#define HAVE_WCTOMB 1
/* Define to 1 if you have the <wctype.h> header file. */
/* #undef HAVE_WCTYPE_H */
/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */
/* Define to 1 if you have the `wmemcmp' function. */
#define HAVE_WMEMCMP 1
/* Define to 1 if you have the `wmemcpy' function. */
#define HAVE_WMEMCPY 1
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* Version number of libarchive as a single integer */
#define LIBARCHIVE_VERSION_NUMBER "2008003"
/* Version number of libarchive */
#define LIBARCHIVE_VERSION_STRING "2.8.3"
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
*/
/* #undef MAJOR_IN_MKDEV */
/* Define to 1 if `major', `minor', and `makedev' are declared in
<sysmacros.h>. */
/* #undef MAJOR_IN_SYSMACROS */
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "libarchive"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "kientzle@freebsd.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libarchive"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libarchive 2.8.3"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libarchive"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.8.3"
/* The size of `wchar_t', as computed by sizeof. */
#define SIZEOF_WCHAR_T 1
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if strerror_r returns char *. */
/* #undef STRERROR_R_CHAR_P */
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Version number of package */
#define VERSION "2.8.3"
/* Define to '0x0500' for Windows 2000 APIs. */
/* #undef WINVER */
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to 1 if on MINIX. */
#define _MINIX 1
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#define _POSIX_1_SOURCE 2
/* Define to 1 if you need to in order for `stat' and other things to work. */
#define _POSIX_SOURCE 1
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT64_T */
/* Define to '0x0500' for Windows 2000 APIs. */
/* #undef _WIN32_WINNT */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to match typeof st_gid field of struct stat if <sys/types.h> doesn't
define. */
/* #undef gid_t */
/* Define to `unsigned long' if <sys/types.h> does not define. */
#define id_t unsigned long
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef int64_t */
/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
not define. */
/* #undef intmax_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef mode_t */
/* Define to `long long' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to match typeof st_uid field of struct stat if <sys/types.h> doesn't
define. */
/* #undef uid_t */
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint64_t */
/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
do not define. */
/* #undef uintmax_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef uintptr_t */

1037
commands/bsdtar/getdate.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
.PATH: ${.CURDIR}/libarchive_fe
SRCS+= err.c \
line_reader.c \
matching.c \
pathmatch.c

View file

@ -0,0 +1,74 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lafe_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "err.h"
const char *lafe_progname;
static void
lafe_vwarnc(int code, const char *fmt, va_list ap)
{
fprintf(stderr, "%s: ", lafe_progname);
vfprintf(stderr, fmt, ap);
if (code != 0)
fprintf(stderr, ": %s", strerror(code));
fprintf(stderr, "\n");
}
void
lafe_warnc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
lafe_vwarnc(code, fmt, ap);
va_end(ap);
}
void
lafe_errc(int eval, int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
lafe_vwarnc(code, fmt, ap);
va_end(ap);
exit(eval);
}

View file

@ -0,0 +1,41 @@
/*-
* Copyright (c) 2009 Joerg Sonnenberger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LAFE_ERR_H
#define LAFE_ERR_H
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
#define __LA_DEAD __attribute__((__noreturn__))
#else
#define __LA_DEAD
#endif
extern const char *lafe_progname;
void lafe_warnc(int code, const char *fmt, ...);
void lafe_errc(int eval, int code, const char *fmt, ...) __LA_DEAD;
#endif

View file

@ -0,0 +1,55 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/usr.bin/cpio/cpio_platform.h,v 1.2 2008/12/06 07:15:42 kientzle Exp $
*/
/*
* This header is the first thing included in any of the libarchive_fe
* source files. As far as possible, platform-specific issues should
* be dealt with here and not within individual source files.
*/
#ifndef LAFE_PLATFORM_H_INCLUDED
#define LAFE_PLATFORM_H_INCLUDED
#if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H
#else
/* Read config.h or die trying. */
#include "config.h"
#endif
/* Get a real definition for __FBSDID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#endif

View file

@ -0,0 +1,171 @@
/*-
* Copyright (c) 2008 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lafe_platform.h"
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "err.h"
#include "line_reader.h"
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
#define strdup _strdup
#endif
/*
* Read lines from file and do something with each one. If option_null
* is set, lines are terminated with zero bytes; otherwise, they're
* terminated with newlines.
*
* This uses a self-sizing buffer to handle arbitrarily-long lines.
*/
struct lafe_line_reader {
FILE *f;
char *buff, *buff_end, *line_start, *line_end, *p;
char *pathname;
size_t buff_length;
int nullSeparator; /* Lines separated by null, not CR/CRLF/etc. */
int ret;
};
struct lafe_line_reader *
lafe_line_reader(const char *pathname, int nullSeparator)
{
struct lafe_line_reader *lr;
lr = calloc(1, sizeof(*lr));
if (lr == NULL)
lafe_errc(1, ENOMEM, "Can't open %s", pathname);
lr->nullSeparator = nullSeparator;
lr->pathname = strdup(pathname);
if (strcmp(pathname, "-") == 0)
lr->f = stdin;
else
lr->f = fopen(pathname, "r");
if (lr->f == NULL)
lafe_errc(1, errno, "Couldn't open %s", pathname);
lr->buff_length = 8192;
lr->buff = malloc(lr->buff_length);
if (lr->buff == NULL)
lafe_errc(1, ENOMEM, "Can't read %s", pathname);
lr->line_start = lr->line_end = lr->buff_end = lr->buff;
return (lr);
}
const char *
lafe_line_reader_next(struct lafe_line_reader *lr)
{
size_t bytes_wanted, bytes_read, new_buff_size;
char *line_start, *p;
for (;;) {
/* If there's a line in the buffer, return it immediately. */
while (lr->line_end < lr->buff_end) {
if (lr->nullSeparator) {
if (*lr->line_end == '\0') {
line_start = lr->line_start;
lr->line_start = lr->line_end + 1;
lr->line_end = lr->line_start;
return (line_start);
}
} else if (*lr->line_end == '\x0a' || *lr->line_end == '\x0d') {
*lr->line_end = '\0';
line_start = lr->line_start;
lr->line_start = lr->line_end + 1;
lr->line_end = lr->line_start;
if (line_start[0] != '\0')
return (line_start);
}
lr->line_end++;
}
/* If we're at end-of-file, process the final data. */
if (lr->f == NULL) {
/* If there's more text, return one last line. */
if (lr->line_end > lr->line_start) {
*lr->line_end = '\0';
line_start = lr->line_start;
lr->line_start = lr->line_end + 1;
lr->line_end = lr->line_start;
return (line_start);
}
/* Otherwise, we're done. */
return (NULL);
}
/* Buffer only has part of a line. */
if (lr->line_start > lr->buff) {
/* Move a leftover fractional line to the beginning. */
memmove(lr->buff, lr->line_start,
lr->buff_end - lr->line_start);
lr->buff_end -= lr->line_start - lr->buff;
lr->line_end -= lr->line_start - lr->buff;
lr->line_start = lr->buff;
} else {
/* Line is too big; enlarge the buffer. */
new_buff_size = lr->buff_length * 2;
if (new_buff_size <= lr->buff_length)
lafe_errc(1, ENOMEM,
"Line too long in %s", lr->pathname);
lr->buff_length = new_buff_size;
p = realloc(lr->buff, new_buff_size);
if (p == NULL)
lafe_errc(1, ENOMEM,
"Line too long in %s", lr->pathname);
lr->buff_end = p + (lr->buff_end - lr->buff);
lr->line_end = p + (lr->line_end - lr->buff);
lr->line_start = lr->buff = p;
}
/* Get some more data into the buffer. */
bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
lr->buff_end += bytes_read;
if (ferror(lr->f))
lafe_errc(1, errno, "Can't read %s", lr->pathname);
if (feof(lr->f)) {
if (lr->f != stdin)
fclose(lr->f);
lr->f = NULL;
}
}
}
void
lafe_line_reader_free(struct lafe_line_reader *lr)
{
free(lr->buff);
free(lr->pathname);
free(lr);
}

View file

@ -0,0 +1,35 @@
/*-
* Copyright (c) 2009 Joerg Sonnenberger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LAFE_LINE_READER_H
#define LAFE_LINE_READER_H
struct lafe_line_reader;
struct lafe_line_reader *lafe_line_reader(const char *, int nullSeparator);
const char *lafe_line_reader_next(struct lafe_line_reader *);
void lafe_line_reader_free(struct lafe_line_reader *);
#endif

View file

@ -0,0 +1,284 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lafe_platform.h"
__FBSDID("$FreeBSD: src/usr.bin/cpio/matching.c,v 1.2 2008/06/21 02:20:20 kientzle Exp $");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "err.h"
#include "line_reader.h"
#include "matching.h"
#include "pathmatch.h"
struct match {
struct match *next;
int matches;
char pattern[1];
};
struct lafe_matching {
struct match *exclusions;
int exclusions_count;
struct match *inclusions;
int inclusions_count;
int inclusions_unmatched_count;
};
static void add_pattern(struct match **list, const char *pattern);
static void initialize_matching(struct lafe_matching **);
static int match_exclusion(struct match *, const char *pathname);
static int match_inclusion(struct match *, const char *pathname);
/*
* The matching logic here needs to be re-thought. I started out to
* try to mimic gtar's matching logic, but it's not entirely
* consistent. In particular 'tar -t' and 'tar -x' interpret patterns
* on the command line as anchored, but --exclude doesn't.
*/
/*
* Utility functions to manage exclusion/inclusion patterns
*/
int
lafe_exclude(struct lafe_matching **matching, const char *pattern)
{
if (*matching == NULL)
initialize_matching(matching);
add_pattern(&((*matching)->exclusions), pattern);
(*matching)->exclusions_count++;
return (0);
}
int
lafe_exclude_from_file(struct lafe_matching **matching, const char *pathname)
{
struct lafe_line_reader *lr;
const char *p;
int ret = 0;
lr = lafe_line_reader(pathname, 0);
while ((p = lafe_line_reader_next(lr)) != NULL) {
if (lafe_exclude(matching, p) != 0)
ret = -1;
}
lafe_line_reader_free(lr);
return (ret);
}
int
lafe_include(struct lafe_matching **matching, const char *pattern)
{
if (*matching == NULL)
initialize_matching(matching);
add_pattern(&((*matching)->inclusions), pattern);
(*matching)->inclusions_count++;
(*matching)->inclusions_unmatched_count++;
return (0);
}
int
lafe_include_from_file(struct lafe_matching **matching, const char *pathname,
int nullSeparator)
{
struct lafe_line_reader *lr;
const char *p;
int ret = 0;
lr = lafe_line_reader(pathname, nullSeparator);
while ((p = lafe_line_reader_next(lr)) != NULL) {
if (lafe_include(matching, p) != 0)
ret = -1;
}
lafe_line_reader_free(lr);
return (ret);
}
static void
add_pattern(struct match **list, const char *pattern)
{
struct match *match;
size_t len;
len = strlen(pattern);
match = malloc(sizeof(*match) + len + 1);
if (match == NULL)
lafe_errc(1, errno, "Out of memory");
strcpy(match->pattern, pattern);
/* Both "foo/" and "foo" should match "foo/bar". */
if (len && match->pattern[len - 1] == '/')
match->pattern[strlen(match->pattern)-1] = '\0';
match->next = *list;
*list = match;
match->matches = 0;
}
int
lafe_excluded(struct lafe_matching *matching, const char *pathname)
{
struct match *match;
struct match *matched;
if (matching == NULL)
return (0);
/* Exclusions take priority */
for (match = matching->exclusions; match != NULL; match = match->next){
if (match_exclusion(match, pathname))
return (1);
}
/* Then check for inclusions */
matched = NULL;
for (match = matching->inclusions; match != NULL; match = match->next){
if (match_inclusion(match, pathname)) {
/*
* If this pattern has never been matched,
* then we're done.
*/
if (match->matches == 0) {
match->matches++;
matching->inclusions_unmatched_count--;
return (0);
}
/*
* Otherwise, remember the match but keep checking
* in case we can tick off an unmatched pattern.
*/
matched = match;
}
}
/*
* We didn't find a pattern that had never been matched, but
* we did find a match, so count it and exit.
*/
if (matched != NULL) {
matched->matches++;
return (0);
}
/* If there were inclusions, default is to exclude. */
if (matching->inclusions != NULL)
return (1);
/* No explicit inclusions, default is to match. */
return (0);
}
/*
* This is a little odd, but it matches the default behavior of
* gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
*
*/
static int
match_exclusion(struct match *match, const char *pathname)
{
return (lafe_pathmatch(match->pattern,
pathname,
PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
}
/*
* Again, mimic gtar: inclusions are always anchored (have to match
* the beginning of the path) even though exclusions are not anchored.
*/
static int
match_inclusion(struct match *match, const char *pathname)
{
#if 0
return (lafe_pathmatch(match->pattern, pathname, 0));
#else
return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
#endif
}
void
lafe_cleanup_exclusions(struct lafe_matching **matching)
{
struct match *p, *q;
if (*matching == NULL)
return;
for (p = (*matching)->inclusions; p != NULL; ) {
q = p;
p = p->next;
free(q);
}
for (p = (*matching)->exclusions; p != NULL; ) {
q = p;
p = p->next;
free(q);
}
free(*matching);
*matching = NULL;
}
static void
initialize_matching(struct lafe_matching **matching)
{
*matching = calloc(sizeof(**matching), 1);
if (*matching == NULL)
lafe_errc(1, errno, "No memory");
}
int
lafe_unmatched_inclusions(struct lafe_matching *matching)
{
if (matching == NULL)
return (0);
return (matching->inclusions_unmatched_count);
}
int
lafe_unmatched_inclusions_warn(struct lafe_matching *matching, const char *msg)
{
struct match *p;
if (matching == NULL)
return (0);
for (p = matching->inclusions; p != NULL; p = p->next) {
if (p->matches == 0)
lafe_warnc(0, "%s: %s", p->pattern, msg);
}
return (matching->inclusions_unmatched_count);
}

View file

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef MATCHING_H
#define MATCHING_H
struct lafe_matching;
int lafe_exclude(struct lafe_matching **matching, const char *pattern);
int lafe_exclude_from_file(struct lafe_matching **matching,
const char *pathname);
int lafe_include(struct lafe_matching **matching, const char *pattern);
int lafe_include_from_file(struct lafe_matching **matching,
const char *pathname, int nullSeparator);
int lafe_excluded(struct lafe_matching *, const char *pathname);
void lafe_cleanup_exclusions(struct lafe_matching **);
int lafe_unmatched_inclusions(struct lafe_matching *);
int lafe_unmatched_inclusions_warn(struct lafe_matching *, const char *msg);
#endif

View file

@ -0,0 +1,255 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lafe_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "pathmatch.h"
/*
* Check whether a character 'c' is matched by a list specification [...]:
* * Leading '!' negates the class.
* * <char>-<char> is a range of characters
* * \<char> removes any special meaning for <char>
*
* Some interesting boundary cases:
* a-d-e is one range (a-d) followed by two single characters - and e.
* \a-\d is same as a-d
* a\-d is three single characters: a, d, -
* Trailing - is not special (so [a-] is two characters a and -).
* Initial - is not special ([a-] is same as [-a] is same as [\\-a])
* This function never sees a trailing \.
* [] always fails
* [!] always succeeds
*/
static int
pm_list(const char *start, const char *end, const char c, int flags)
{
const char *p = start;
char rangeStart = '\0', nextRangeStart;
int match = 1, nomatch = 0;
/* This will be used soon... */
(void)flags; /* UNUSED */
/* If this is a negated class, return success for nomatch. */
if (*p == '!' && p < end) {
match = 0;
nomatch = 1;
++p;
}
while (p < end) {
nextRangeStart = '\0';
switch (*p) {
case '-':
/* Trailing or initial '-' is not special. */
if ((rangeStart == '\0') || (p == end - 1)) {
if (*p == c)
return (match);
} else {
char rangeEnd = *++p;
if (rangeEnd == '\\')
rangeEnd = *++p;
if ((rangeStart <= c) && (c <= rangeEnd))
return (match);
}
break;
case '\\':
++p;
/* Fall through */
default:
if (*p == c)
return (match);
nextRangeStart = *p; /* Possible start of range. */
}
rangeStart = nextRangeStart;
++p;
}
return (nomatch);
}
/*
* If s is pointing to "./", ".//", "./././" or the like, skip it.
*/
static const char *
pm_slashskip(const char *s) {
while ((*s == '/')
|| (s[0] == '.' && s[1] == '/')
|| (s[0] == '.' && s[1] == '\0'))
++s;
return (s);
}
static int
pm(const char *p, const char *s, int flags)
{
const char *end;
/*
* Ignore leading './', './/', '././', etc.
*/
if (s[0] == '.' && s[1] == '/')
s = pm_slashskip(s + 1);
if (p[0] == '.' && p[1] == '/')
p = pm_slashskip(p + 1);
for (;;) {
switch (*p) {
case '\0':
if (s[0] == '/') {
if (flags & PATHMATCH_NO_ANCHOR_END)
return (1);
/* "dir" == "dir/" == "dir/." */
s = pm_slashskip(s);
}
return (*s == '\0');
case '?':
/* ? always succeds, unless we hit end of 's' */
if (*s == '\0')
return (0);
break;
case '*':
/* "*" == "**" == "***" ... */
while (*p == '*')
++p;
/* Trailing '*' always succeeds. */
if (*p == '\0')
return (1);
while (*s) {
if (lafe_pathmatch(p, s, flags))
return (1);
++s;
}
return (0);
case '[':
/*
* Find the end of the [...] character class,
* ignoring \] that might occur within the class.
*/
end = p + 1;
while (*end != '\0' && *end != ']') {
if (*end == '\\' && end[1] != '\0')
++end;
++end;
}
if (*end == ']') {
/* We found [...], try to match it. */
if (!pm_list(p + 1, end, *s, flags))
return (0);
p = end; /* Jump to trailing ']' char. */
break;
} else
/* No final ']', so just match '['. */
if (*p != *s)
return (0);
break;
case '\\':
/* Trailing '\\' matches itself. */
if (p[1] == '\0') {
if (*s != '\\')
return (0);
} else {
++p;
if (*p != *s)
return (0);
}
break;
case '/':
if (*s != '/' && *s != '\0')
return (0);
/* Note: pattern "/\./" won't match "/";
* pm_slashskip() correctly stops at backslash. */
p = pm_slashskip(p);
s = pm_slashskip(s);
if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END))
return (1);
--p; /* Counteract the increment below. */
--s;
break;
case '$':
/* '$' is special only at end of pattern and only
* if PATHMATCH_NO_ANCHOR_END is specified. */
if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
/* "dir" == "dir/" == "dir/." */
return (*pm_slashskip(s) == '\0');
}
/* Otherwise, '$' is not special. */
/* FALL THROUGH */
default:
if (*p != *s)
return (0);
break;
}
++p;
++s;
}
}
/* Main entry point. */
int
lafe_pathmatch(const char *p, const char *s, int flags)
{
/* Empty pattern only matches the empty string. */
if (p == NULL || *p == '\0')
return (s == NULL || *s == '\0');
/* Leading '^' anchors the start of the pattern. */
if (*p == '^') {
++p;
flags &= ~PATHMATCH_NO_ANCHOR_START;
}
if (*p == '/' && *s != '/')
return (0);
/* Certain patterns and file names anchor implicitly. */
if (*p == '*' || *p == '/' || *p == '/') {
while (*p == '/')
++p;
while (*s == '/')
++s;
return (pm(p, s, flags));
}
/* If start is unanchored, try to match start of each path element. */
if (flags & PATHMATCH_NO_ANCHOR_START) {
for ( ; s != NULL; s = strchr(s, '/')) {
if (*s == '/')
s++;
if (pm(p, s, flags))
return (1);
}
return (0);
}
/* Default: Match from beginning. */
return (pm(p, s, flags));
}

View file

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef LAFE_PATHMATCH_H
#define LAFE_PATHMATCH_H
/* Don't anchor at beginning unless the pattern starts with "^" */
#define PATHMATCH_NO_ANCHOR_START 1
/* Don't anchor at end unless the pattern ends with "$" */
#define PATHMATCH_NO_ANCHOR_END 2
/* Note that "^" and "$" are not special unless you set the corresponding
* flag above. */
int lafe_pathmatch(const char *p, const char *s, int flags);
#endif

440
commands/bsdtar/read.c Normal file
View file

@ -0,0 +1,440 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bsdtar_platform.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.40 2008/08/21 06:41:14 kientzle Exp $");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "bsdtar.h"
#include "err.h"
struct progress_data {
struct bsdtar *bsdtar;
struct archive *archive;
struct archive_entry *entry;
};
static void list_item_verbose(struct bsdtar *, FILE *,
struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode);
void
tar_mode_t(struct bsdtar *bsdtar)
{
read_archive(bsdtar, 't');
if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0)
bsdtar->return_value = 1;
}
void
tar_mode_x(struct bsdtar *bsdtar)
{
read_archive(bsdtar, 'x');
if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0)
bsdtar->return_value = 1;
}
static void
progress_func(void *cookie)
{
struct progress_data *progress_data = cookie;
struct bsdtar *bsdtar = progress_data->bsdtar;
struct archive *a = progress_data->archive;
struct archive_entry *entry = progress_data->entry;
#ifndef __minix
uint64_t comp, uncomp;
#else
size_t comp, uncomp;
#endif
if (!need_report())
return;
if (bsdtar->verbose)
fprintf(stderr, "\n");
if (a != NULL) {
comp = archive_position_compressed(a);
uncomp = archive_position_uncompressed(a);
fprintf(stderr,
"In: %s bytes, compression %d%%;",
tar_i64toa(comp), (int)((uncomp - comp) * 100 / uncomp));
fprintf(stderr, " Out: %d files, %s bytes\n",
archive_file_count(a), tar_i64toa(uncomp));
}
if (entry != NULL) {
safe_fprintf(stderr, "Current: %s",
archive_entry_pathname(entry));
fprintf(stderr, " (%s bytes)\n",
tar_i64toa(archive_entry_size(entry)));
}
}
/*
* Handle 'x' and 't' modes.
*/
static void
read_archive(struct bsdtar *bsdtar, char mode)
{
struct progress_data progress_data;
FILE *out;
struct archive *a;
struct archive_entry *entry;
const struct stat *st;
int r;
while (*bsdtar->argv) {
lafe_include(&bsdtar->matching, *bsdtar->argv);
bsdtar->argv++;
}
if (bsdtar->names_from_file != NULL)
lafe_include_from_file(&bsdtar->matching,
bsdtar->names_from_file, bsdtar->option_null);
a = archive_read_new();
if (bsdtar->compress_program != NULL)
archive_read_support_compression_program(a, bsdtar->compress_program);
else
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
lafe_errc(1, 0, "%s", archive_error_string(a));
if (archive_read_open_file(a, bsdtar->filename,
bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
DEFAULT_BYTES_PER_BLOCK))
lafe_errc(1, 0, "Error opening archive: %s",
archive_error_string(a));
do_chdir(bsdtar);
if (mode == 'x') {
/* Set an extract callback so that we can handle SIGINFO. */
progress_data.bsdtar = bsdtar;
progress_data.archive = a;
archive_read_extract_set_progress_callback(a, progress_func,
&progress_data);
}
if (mode == 'x' && bsdtar->option_chroot) {
#if HAVE_CHROOT
if (chroot(".") != 0)
lafe_errc(1, errno, "Can't chroot to \".\"");
#else
lafe_errc(1, 0,
"chroot isn't supported on this platform");
#endif
}
for (;;) {
/* Support --fast-read option */
if (bsdtar->option_fast_read &&
lafe_unmatched_inclusions(bsdtar->matching) == 0)
break;
r = archive_read_next_header(a, &entry);
progress_data.entry = entry;
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
lafe_warnc(0, "%s", archive_error_string(a));
if (r <= ARCHIVE_WARN)
bsdtar->return_value = 1;
if (r == ARCHIVE_RETRY) {
/* Retryable error: try again */
lafe_warnc(0, "Retrying...");
continue;
}
if (r == ARCHIVE_FATAL)
break;
if (bsdtar->option_numeric_owner) {
archive_entry_set_uname(entry, NULL);
archive_entry_set_gname(entry, NULL);
}
/*
* Exclude entries that are too old.
*/
st = archive_entry_stat(entry);
if (bsdtar->newer_ctime_sec > 0) {
if (st->st_ctime < bsdtar->newer_ctime_sec)
continue; /* Too old, skip it. */
if (st->st_ctime == bsdtar->newer_ctime_sec
&& ARCHIVE_STAT_CTIME_NANOS(st)
<= bsdtar->newer_ctime_nsec)
continue; /* Too old, skip it. */
}
if (bsdtar->newer_mtime_sec > 0) {
if (st->st_mtime < bsdtar->newer_mtime_sec)
continue; /* Too old, skip it. */
if (st->st_mtime == bsdtar->newer_mtime_sec
&& ARCHIVE_STAT_MTIME_NANOS(st)
<= bsdtar->newer_mtime_nsec)
continue; /* Too old, skip it. */
}
/*
* Note that pattern exclusions are checked before
* pathname rewrites are handled. This gives more
* control over exclusions, since rewrites always lose
* information. (For example, consider a rewrite
* s/foo[0-9]/foo/. If we check exclusions after the
* rewrite, there would be no way to exclude foo1/bar
* while allowing foo2/bar.)
*/
if (lafe_excluded(bsdtar->matching, archive_entry_pathname(entry)))
continue; /* Excluded by a pattern test. */
if (mode == 't') {
/* Perversely, gtar uses -O to mean "send to stderr"
* when used with -t. */
out = bsdtar->option_stdout ? stderr : stdout;
/*
* TODO: Provide some reasonable way to
* preview rewrites. gtar always displays
* the unedited path in -t output, which means
* you cannot easily preview rewrites.
*/
if (bsdtar->verbose < 2)
safe_fprintf(out, "%s",
archive_entry_pathname(entry));
else
list_item_verbose(bsdtar, out, entry);
fflush(out);
r = archive_read_data_skip(a);
if (r == ARCHIVE_WARN) {
fprintf(out, "\n");
lafe_warnc(0, "%s",
archive_error_string(a));
}
if (r == ARCHIVE_RETRY) {
fprintf(out, "\n");
lafe_warnc(0, "%s",
archive_error_string(a));
}
if (r == ARCHIVE_FATAL) {
fprintf(out, "\n");
lafe_warnc(0, "%s",
archive_error_string(a));
bsdtar->return_value = 1;
break;
}
fprintf(out, "\n");
} else {
/* Note: some rewrite failures prevent extraction. */
if (edit_pathname(bsdtar, entry))
continue; /* Excluded by a rewrite failure. */
if (bsdtar->option_interactive &&
!yes("extract '%s'", archive_entry_pathname(entry)))
continue;
/*
* Format here is from SUSv2, including the
* deferred '\n'.
*/
if (bsdtar->verbose) {
safe_fprintf(stderr, "x %s",
archive_entry_pathname(entry));
fflush(stderr);
}
/* TODO siginfo_printinfo(bsdtar, 0); */
if (bsdtar->option_stdout)
r = archive_read_data_into_fd(a, 1);
else
r = archive_read_extract(a, entry,
bsdtar->extract_flags);
if (r != ARCHIVE_OK) {
if (!bsdtar->verbose)
safe_fprintf(stderr, "%s",
archive_entry_pathname(entry));
safe_fprintf(stderr, ": %s",
archive_error_string(a));
if (!bsdtar->verbose)
fprintf(stderr, "\n");
bsdtar->return_value = 1;
}
if (bsdtar->verbose)
fprintf(stderr, "\n");
if (r == ARCHIVE_FATAL)
break;
}
}
r = archive_read_close(a);
if (r != ARCHIVE_OK)
lafe_warnc(0, "%s", archive_error_string(a));
if (r <= ARCHIVE_WARN)
bsdtar->return_value = 1;
if (bsdtar->verbose > 2)
fprintf(stdout, "Archive Format: %s, Compression: %s\n",
archive_format_name(a), archive_compression_name(a));
archive_read_finish(a);
}
/*
* Display information about the current file.
*
* The format here roughly duplicates the output of 'ls -l'.
* This is based on SUSv2, where 'tar tv' is documented as
* listing additional information in an "unspecified format,"
* and 'pax -l' is documented as using the same format as 'ls -l'.
*/
static void
list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
{
char tmp[100];
size_t w;
const char *p;
const char *fmt;
time_t tim;
static time_t now;
/*
* We avoid collecting the entire list in memory at once by
* listing things as we see them. However, that also means we can't
* just pre-compute the field widths. Instead, we start with guesses
* and just widen them as necessary. These numbers are completely
* arbitrary.
*/
if (!bsdtar->u_width) {
bsdtar->u_width = 6;
bsdtar->gs_width = 13;
}
if (!now)
time(&now);
fprintf(out, "%s %d ",
archive_entry_strmode(entry),
archive_entry_nlink(entry));
/* Use uname if it's present, else uid. */
p = archive_entry_uname(entry);
if ((p == NULL) || (*p == '\0')) {
sprintf(tmp, "%lu ",
(unsigned long)archive_entry_uid(entry));
p = tmp;
}
w = strlen(p);
if (w > bsdtar->u_width)
bsdtar->u_width = w;
fprintf(out, "%-*s ", (int)bsdtar->u_width, p);
/* Use gname if it's present, else gid. */
p = archive_entry_gname(entry);
if (p != NULL && p[0] != '\0') {
fprintf(out, "%s", p);
w = strlen(p);
} else {
sprintf(tmp, "%lu",
(unsigned long)archive_entry_gid(entry));
w = strlen(tmp);
fprintf(out, "%s", tmp);
}
/*
* Print device number or file size, right-aligned so as to make
* total width of group and devnum/filesize fields be gs_width.
* If gs_width is too small, grow it.
*/
if (archive_entry_filetype(entry) == AE_IFCHR
|| archive_entry_filetype(entry) == AE_IFBLK) {
sprintf(tmp, "%lu,%lu",
(unsigned long)archive_entry_rdevmajor(entry),
(unsigned long)archive_entry_rdevminor(entry));
} else {
strcpy(tmp, tar_i64toa(archive_entry_size(entry)));
}
if (w + strlen(tmp) >= bsdtar->gs_width)
bsdtar->gs_width = w+strlen(tmp)+1;
fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp);
/* Format the time using 'ls -l' conventions. */
tim = archive_entry_mtime(entry);
#define HALF_YEAR (time_t)365 * 86400 / 2
#if defined(_WIN32) && !defined(__CYGWIN__)
#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */
#else
#define DAY_FMT "%e" /* Day number without leading zeros */
#endif
if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
fmt = bsdtar->day_first ? DAY_FMT " %b %Y" : "%b " DAY_FMT " %Y";
else
fmt = bsdtar->day_first ? DAY_FMT " %b %H:%M" : "%b " DAY_FMT " %H:%M";
strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
fprintf(out, " %s ", tmp);
safe_fprintf(out, "%s", archive_entry_pathname(entry));
/* Extra information for links. */
if (archive_entry_hardlink(entry)) /* Hard link */
safe_fprintf(out, " link to %s",
archive_entry_hardlink(entry));
else if (archive_entry_symlink(entry)) /* Symbolic link */
safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
}

289
commands/bsdtar/subst.c Normal file
View file

@ -0,0 +1,289 @@
/*-
* Copyright (c) 2008 Joerg Sonnenberger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bsdtar_platform.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/subst.c,v 1.4 2008/06/15 10:08:16 kientzle Exp $");
#if HAVE_REGEX_H
#include "bsdtar.h"
#include <errno.h>
#include <regex.h>
#include <stdlib.h>
#include <string.h>
#ifndef REG_BASIC
#define REG_BASIC 0
#endif
#include "err.h"
struct subst_rule {
struct subst_rule *next;
regex_t re;
char *result;
unsigned int global:1, print:1, symlink:1;
};
struct substitution {
struct subst_rule *first_rule, *last_rule;
};
static void
init_substitution(struct bsdtar *bsdtar)
{
struct substitution *subst;
bsdtar->substitution = subst = malloc(sizeof(*subst));
if (subst == NULL)
lafe_errc(1, errno, "Out of memory");
subst->first_rule = subst->last_rule = NULL;
}
void
add_substitution(struct bsdtar *bsdtar, const char *rule_text)
{
struct subst_rule *rule;
struct substitution *subst;
const char *end_pattern, *start_subst;
char *pattern;
int r;
if ((subst = bsdtar->substitution) == NULL) {
init_substitution(bsdtar);
subst = bsdtar->substitution;
}
rule = malloc(sizeof(*rule));
if (rule == NULL)
lafe_errc(1, errno, "Out of memory");
rule->next = NULL;
if (subst->last_rule == NULL)
subst->first_rule = rule;
else
subst->last_rule->next = rule;
subst->last_rule = rule;
if (*rule_text == '\0')
lafe_errc(1, 0, "Empty replacement string");
end_pattern = strchr(rule_text + 1, *rule_text);
if (end_pattern == NULL)
lafe_errc(1, 0, "Invalid replacement string");
pattern = malloc(end_pattern - rule_text);
if (pattern == NULL)
lafe_errc(1, errno, "Out of memory");
memcpy(pattern, rule_text + 1, end_pattern - rule_text - 1);
pattern[end_pattern - rule_text - 1] = '\0';
if ((r = regcomp(&rule->re, pattern, REG_BASIC)) != 0) {
char buf[80];
regerror(r, &rule->re, buf, sizeof(buf));
lafe_errc(1, 0, "Invalid regular expression: %s", buf);
}
free(pattern);
start_subst = end_pattern + 1;
end_pattern = strchr(start_subst, *rule_text);
if (end_pattern == NULL)
lafe_errc(1, 0, "Invalid replacement string");
rule->result = malloc(end_pattern - start_subst + 1);
if (rule->result == NULL)
lafe_errc(1, errno, "Out of memory");
memcpy(rule->result, start_subst, end_pattern - start_subst);
rule->result[end_pattern - start_subst] = '\0';
rule->global = 0;
rule->print = 0;
rule->symlink = 0;
while (*++end_pattern) {
switch (*end_pattern) {
case 'g':
case 'G':
rule->global = 1;
break;
case 'p':
case 'P':
rule->print = 1;
break;
case 's':
case 'S':
rule->symlink = 1;
break;
default:
lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern);
}
}
}
static void
realloc_strncat(char **str, const char *append, size_t len)
{
char *new_str;
size_t old_len;
if (*str == NULL)
old_len = 0;
else
old_len = strlen(*str);
new_str = malloc(old_len + len + 1);
if (new_str == NULL)
lafe_errc(1, errno, "Out of memory");
memcpy(new_str, *str, old_len);
memcpy(new_str + old_len, append, len);
new_str[old_len + len] = '\0';
free(*str);
*str = new_str;
}
static void
realloc_strcat(char **str, const char *append)
{
char *new_str;
size_t old_len;
if (*str == NULL)
old_len = 0;
else
old_len = strlen(*str);
new_str = malloc(old_len + strlen(append) + 1);
if (new_str == NULL)
lafe_errc(1, errno, "Out of memory");
memcpy(new_str, *str, old_len);
strcpy(new_str + old_len, append);
free(*str);
*str = new_str;
}
int
apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int symlink_only)
{
const char *path = name;
regmatch_t matches[10];
size_t i, j;
struct subst_rule *rule;
struct substitution *subst;
int c, got_match, print_match;
*result = NULL;
if ((subst = bsdtar->substitution) == NULL)
return 0;
got_match = 0;
print_match = 0;
for (rule = subst->first_rule; rule != NULL; rule = rule->next) {
if (symlink_only && !rule->symlink)
continue;
if (regexec(&rule->re, name, 10, matches, 0))
continue;
got_match = 1;
print_match |= rule->print;
realloc_strncat(result, name, matches[0].rm_so);
for (i = 0, j = 0; rule->result[i] != '\0'; ++i) {
if (rule->result[i] == '~') {
realloc_strncat(result, rule->result + j, i - j);
realloc_strncat(result, name, matches[0].rm_eo);
j = i + 1;
continue;
}
if (rule->result[i] != '\\')
continue;
++i;
c = rule->result[i];
switch (c) {
case '~':
case '\\':
realloc_strncat(result, rule->result + j, i - j - 1);
j = i;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
realloc_strncat(result, rule->result + j, i - j - 1);
if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
free(*result);
*result = NULL;
return -1;
}
realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so);
j = i + 1;
break;
default:
/* Just continue; */
break;
}
}
realloc_strcat(result, rule->result + j);
name += matches[0].rm_eo;
if (!rule->global)
break;
}
if (got_match)
realloc_strcat(result, name);
if (print_match)
fprintf(stderr, "%s >> %s\n", path, *result);
return got_match;
}
void
cleanup_substitution(struct bsdtar *bsdtar)
{
struct subst_rule *rule;
struct substitution *subst;
if ((subst = bsdtar->substitution) == NULL)
return;
while ((rule = subst->first_rule) != NULL) {
subst->first_rule = rule->next;
free(rule->result);
free(rule);
}
free(subst);
}
#endif /* HAVE_REGEX_H */

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1,67 @@
############################################
#
# How to build bsdtar_test
#
############################################
IF(ENABLE_TAR AND ENABLE_TEST)
SET(bsdtar_test_SOURCES
../getdate.c
main.c
test.h
test_0.c
test_basic.c
test_copy.c
test_empty_mtree.c
test_getdate.c
test_help.c
test_option_T_upper.c
test_option_q.c
test_option_r.c
test_option_s.c
test_patterns.c
test_stdio.c
test_strip_components.c
test_symlink_dir.c
test_version.c
test_windows.c
)
IF(WIN32 AND NOT CYGWIN)
LIST(APPEND bsdtar_test_SOURCES ../bsdtar_windows.c)
LIST(APPEND bsdtar_test_SOURCES ../bsdtar_windows.h)
ENDIF(WIN32 AND NOT CYGWIN)
#
# Register target
#
ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES})
SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H)
#
# Generate list.h by grepping DEFINE_TEST() lines out of the C sources.
#
GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h
${CMAKE_CURRENT_LIST_FILE} ${bsdtar_test_SOURCES})
SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
${CMAKE_CURRENT_BINARY_DIR})
# list.h has a line DEFINE_TEST(testname) for every
# test. We can use that to define the tests for cmake by
# defining a DEFINE_TEST macro and reading list.h in.
MACRO (DEFINE_TEST _testname)
ADD_TEST_28(
NAME bsdtar_${_testname}
COMMAND bsdtar_test -vv
-p $<TARGET_FILE:bsdtar>
-r ${CMAKE_CURRENT_SOURCE_DIR}
${_testname})
ENDMACRO (DEFINE_TEST _testname)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_bsdtar_test
COMMAND bsdtar_test -p ${BSDTAR} -r ${CMAKE_CURRENT_SOURCE_DIR})
ADD_DEPENDENCIES(run_bsdtar_test bsdtar)
ADD_DEPENDENCIES(run_all_tests run_bsdtar_test)
ENDIF (ENABLE_TAR AND ENABLE_TEST)

75
commands/bsdtar/test/config.sh Executable file
View file

@ -0,0 +1,75 @@
#
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/config.sh,v 1.2 2007/03/11 19:33:45 kientzle Exp $
THISDIR=`cd \`dirname $0\`;/bin/pwd`
# TESTDIR defaults to /tmp/bsdtar- + the name of the script
if [ -z "$TESTDIR" ]; then
TESTDIR=/tmp/bsdtar-`echo $0 | sed -e 's|.*/||' -e 's|\.sh||' -e 's/[^a-z0-9_-]/_/g'`
fi
# Find bsdtar
# The first three paths here are the usual locations of a bsdtar
# that has just been built. The remaining paths might find a bsdtar
# installed on the local system somewhere.
if [ -z "$BSDTAR" ]; then
for T in "$THISDIR/../bsdtar" "$THISDIR/../../bsdtar" \
"/usr/obj`dirname $THISDIR`/bsdtar" "/usr/local/bin/bsdtar" \
"/usr/bin/bsdtar" "/usr/bin/tar" "bsdtar" "tar"
do
if ( /bin/sh -c "$T --version" | grep "bsdtar" ) >/dev/null 2>&1; then
BSDTAR="$T"
break
fi
done
fi
# Find GNU tar
if [ -z "$GTAR" ]; then
for T in gtar gnutar tar /usr/local/bin/gtar* /usr/local/bin/gnutar* /usr/bin/gtar* /usr/bin/gnutar*
do
if ( /bin/sh -c "$T --version" | grep "GNU tar" ) >/dev/null 2>&1; then
GTAR="$T"
break
fi
done
fi
# Find CPIO
if [ -z "$CPIO" ]; then
CPIO=cpio
fi
echo BSDTAR=$BSDTAR '('`$BSDTAR --version`')'
echo GTAR=$GTAR '('`$GTAR --version | head -n 1`')'
echo CPIO=$CPIO '('`$CPIO --version`')'
# Remove and recreate the directory we'll use for these tests
rm -rf $TESTDIR
mkdir -p $TESTDIR || exit 1
cd $TESTDIR || exit 1
echo TESTDIR=$TESTDIR

View file

@ -0,0 +1,16 @@
DEFINE_TEST(test_0)
DEFINE_TEST(test_basic)
DEFINE_TEST(test_copy)
DEFINE_TEST(test_empty_mtree)
DEFINE_TEST(test_getdate)
DEFINE_TEST(test_help)
DEFINE_TEST(test_option_T_upper)
DEFINE_TEST(test_option_q)
DEFINE_TEST(test_option_r)
DEFINE_TEST(test_option_s)
DEFINE_TEST(test_patterns)
DEFINE_TEST(test_stdio)
DEFINE_TEST(test_strip_components)
DEFINE_TEST(test_symlink_dir)
DEFINE_TEST(test_version)
DEFINE_TEST(test_windows)

2226
commands/bsdtar/test/main.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-acl.sh,v 1.1 2007/03/11 10:36:42 kientzle Exp $
# Exercise copying of ACLs
echo "ACL handling"
# Basic test configuration
TESTDIR=/mnt/da0/acl-test
. `dirname $0`/config.sh
# Create some files with ACLs
mkdir original
cd original
touch a
chmod 664 a
setfacl -m user:bin:rw- -m group:78:r-x a \
|| echo XXX failed to set access ACL on a XXX
mkdir d
chmod 775 d
setfacl -m user:daemon:rw- -m group:78:r-x d \
|| echo XXX failed to set access ACL on d XXX
setfacl -d -m user::rw- -m group::rw- -m other::rw- -m group:79:r-- d \
|| echo XXX failed to set default ACL on d XXX
cd ..
# Copy the dir with -p
echo " -p preserves ACLs"
mkdir copy
(cd original && ${BSDTAR} -cf - .) | (cd copy; ${BSDTAR} -xpf -)
# Verify the ACLs
cd copy
if [ "user::rw- user:bin:rw- group::rw- group:78:r-x mask::rwx other::r--" \
= "`echo \`getfacl -q a\``" ]; then
# It matches!!
else
echo XXX a has wrong ACL XXX `getfacl -q a`
fi
if [ "user::rwx user:daemon:rw- group::rwx group:78:r-x mask::rwx other::r-x" \
= "`echo \`getfacl -q d\``" ]; then
# It matches!!
else
echo XXX d has wrong ACL XXX `getfacl -q d`
fi
if [ "user::rw- group::rw- group:79:r-- mask::rw- other::rw-" \
= "`echo \`getfacl -q -d d\``" ]; then
# It matches!!
else
echo XXX d has wrong ACL XXX `getfacl -q -d d`
fi

View file

@ -0,0 +1,432 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-basic.sh,v 1.5 2007/04/18 04:35:17 kientzle Exp $
# Generate a dir tree with various data and copy it using
# a variety of tools and flags. This mostly checks that
# we can read archives we write and those written by gtar
# and cpio.
echo "Basic archiving/copy interoperability tests"
# Basic configuration
. `dirname $0`/config.sh
# We need some files to archive; generate some random files and files
# with very long names and other special attributes
mkdir -p original
cd original
# Create some long files with random text data
for f in f0 f1 f2 f3 f4 f5 f6 f7 f8 f9; do
dd if=/dev/urandom bs=1k count=100 2>/dev/null | od > $f
done
# A sparse file
dd if=/dev/zero of=sparse bs=1 count=1 oseek=100000 2>/dev/null
# Files with long names
touch a
touch ab
touch abc
touch abcd
touch abcde
touch abcdef
touch abcdefg
touch abcdefgh
touch abcdefghi
touch abcdefghij
touch abcdefghijk
touch abcdefghijkl
touch abcdefghijklm
touch abcdefghijklmn
touch abcdefghijklmno
touch abcdefghijklmnop
touch abcdefghijklmnopq
touch abcdefghijklmnopqr
touch abcdefghijklmnopqrs
touch abcdefghijklmnopqrst
touch abcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy
touch abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
# A file with a long pathname
mkdir -p 1abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
cd ..
# Basic test of archiving/dearchiving
echo " bsdtar -c | bsdtar -x"
mkdir copy-default
(cd original && ${BSDTAR} -cf - .) | (cd copy-default; ${BSDTAR} -xf -)
(diff -r original copy-default || echo XXX FAILED XXX 1>&2) | head
# Exercise gzip compression (test compressed output with gunzip -t
echo " bsdtar -cz | gunzip -t"
(cd original && ${BSDTAR} -czf - .) | gunzip -tq
# Ensure our compression works with gunzip program
echo " bsdtar -cz | gunzip | bsdtar -x"
mkdir copy-gzip2
(cd original && ${BSDTAR} -czf - .) | gunzip -q | (cd copy-gzip2; ${BSDTAR} -xf -)
(diff -r original copy-gzip2 || echo XXX FAILED XXX 1>&2) | head
# Ensure our decompression works with gzip program
echo " bsdtar -c | gzip | bsdtar -x"
mkdir copy-gunzip
(cd original && ${BSDTAR} -cf - .) | gzip | (cd copy-gunzip; ${BSDTAR} -xf -)
(diff -r original copy-gunzip || echo XXX FAILED XXX 1>&2) | head
# Ensure our gzip compression/decompression work with each other
echo " bsdtar -cz | bsdtar -x"
mkdir copy-gzip-gunzip
(cd original && ${BSDTAR} -czf - .) | (cd copy-gzip-gunzip; ${BSDTAR} -xf -)
(diff -r original copy-gzip-gunzip || echo XXX FAILED XXX 1>&2) | head
# Ensure our decompression works with bzip2 program
echo " bsdtar -c | bzip2 | bsdtar -x"
mkdir copy-bunzip
(cd original && ${BSDTAR} -cf - .) | bzip2 | (cd copy-bunzip; ${BSDTAR} -xf -)
(diff -r original copy-bunzip || echo XXX FAILED XXX 1>&2) | head
# Ensure our compression works with bunzip2 program
echo " bsdtar -cy | bunzip2 | bsdtar -x"
mkdir copy-bzip2
(cd original && ${BSDTAR} -cyf - .) | bunzip2 -q | (cd copy-bzip2; ${BSDTAR} -xf -)
(diff -r original copy-bzip2 || echo XXX FAILED XXX 1>&2) | head
# Ensure our bzip2 compression/decompression work with each other
echo " bsdtar -cy | bsdtar -x"
mkdir copy-bzip2-bunzip2
(cd original && ${BSDTAR} -cyf - .) | (cd copy-bzip2-bunzip2; ${BSDTAR} -xf -)
(diff -r original copy-bzip2-bunzip2 || echo XXX FAILED XXX 1>&2) | head
# Ensure that archive listing works
echo " bsdtar -c | bsdtar -t"
(cd original && find .) | sort > list-original
(cd original && ${BSDTAR} -cf - .) | ${BSDTAR} -tf - | sed 's|/$||' | sort > list-default
(diff list-original list-default || echo XXX FAILED XXX 1>&2) | head
# Ensure that listing of deflated archives works
echo " bsdtar -cz | bsdtar -t"
(cd original && ${BSDTAR} -czf - .) | ${BSDTAR} -tf - | sed 's|/$||' | sort > list-gzip
(diff list-original list-gzip || echo XXX FAILED XXX 1>&2) | head
# Ensure that listing of bzip2ed archives works
echo " bsdtar -cy | bsdtar -t"
(cd original && ${BSDTAR} -cyf - .) | ${BSDTAR} -tf - | sed 's|/$||' | sort > list-bzip2
(diff list-original list-bzip2 || echo XXX FAILED XXX 1>&2) | head
# Filtering exercises different areas of the library.
echo " Convert tar archive to a tar archive"
mkdir filter-tar-tar
(cd original && ${BSDTAR} -cf - .) | ${BSDTAR} -cf - @- | (cd filter-tar-tar; ${BSDTAR} -xf -)
(diff -r original filter-tar-tar || echo XXX FAILED XXX 1>&2) | head
# Make sure that reading and writing a tar archive doesn't change it.
echo " bsdtar -cf- @- | cmp"
(cd original && ${BSDTAR} -cf - .) > original.tar
${BSDTAR} -cf - @- < original.tar | cmp - original.tar || echo XXX FAILED XXX
# Filtering as format conversion
echo " Convert tar archive to cpio archive"
mkdir filter-tar-cpio
(cd original && ${BSDTAR} -cf - .) | ${BSDTAR} -cf - --format=cpio @- | (cd filter-tar-cpio; ${BSDTAR} -xf -)
(diff -r original filter-tar-cpio || echo XXX FAILED XXX 1>&2) | head
# Test basic --include selection logic
echo " Convert tar to cpio with selection"
mkdir filter-tar-selected
(cd original && ${BSDTAR} -cf - .) | ${BSDTAR} -cf - --format=cpio --include=./f3 @- | (cd filter-tar-selected; ${BSDTAR} -xf -)
(diff -r original/f3 filter-tar-selected/f3 || echo XXX FAILED XXX 1>&2) | head
# Should be no files in copy except for 'f3'
(cd filter-tar-selected ; ls | grep -v f3 | grep .) && echo XXX FAILED XXX
# Test --include with wildcards
echo " Convert tar to cpio selecting with wildcards"
mkdir filter-tar-selected2
(cd original && ${BSDTAR} -cf - .) | ${BSDTAR} -cf - --format=cpio --include='./f*' @- | (cd filter-tar-selected2; ${BSDTAR} -xf -)
for f in f1 f2 f3 f4 f5 f6 f7 f8 f9; do
(diff -r original/$f filter-tar-selected2/$f || echo XXX FAILED XXX 1>&2) | head
done
# Should be no files in copy except for 'f[0-9]'
(cd filter-tar-selected2 ; ls | grep -v 'f[0-9]' | grep .) && echo XXX FAILED XXX
# Check read/write of basic odc cpio format
echo " bsdtar -c --format=cpio | bsdtar -x"
mkdir copy-cpio
(cd original && ${BSDTAR} -cf - --format cpio .) | (cd copy-cpio; ${BSDTAR} -xf -)
(diff -r original copy-cpio || echo XXX FAILED XXX 1>&2) | head
# Ensure we can read gtar archives
echo " gtar -c | bsdtar -x"
mkdir copy-gtar
(cd original && ${GTAR} -cf - .) | (cd copy-gtar; ${BSDTAR} -xf -)
(diff -r original copy-gtar || echo XXX FAILED XXX 1>&2) | head
# Ensure we can read svr4crc cpio archives
echo " cpio -H crc | bsdtar -x"
mkdir copy-svr4crc
(cd original && find . | ${CPIO} -o -H crc 2>/dev/null) | (cd copy-svr4crc; ${BSDTAR} -xf -)
(diff -r original copy-svr4crc || echo XXX FAILED XXX 1>&2) | head
# Ensure we generate proper shar output
echo " bsdtar -c --format=shar | /bin/sh"
mkdir copy-shar
(cd original && ${BSDTAR} -cf - --format=shar --exclude=sparse .) | (cd copy-shar; /bin/sh >/dev/null)
(diff -r --exclude=sparse original copy-shar || echo XXX FAILED XXX 1>&2) | head
# Check that -u (update) picks up no new files
echo " bsdtar -u doesn't pick up unchanged files"
(cd original && ${BSDTAR} -cf ../test-u.tar -b 1 .)
cp test-u.tar test-u1.tar
(cd original && ${BSDTAR} -uf ../test-u1.tar .)
(diff test-u.tar test-u1.tar || echo XXX FAILED XXX 1>&2) | head
# Check that -u (update) does pick up actual changed files
echo " bsdtar -u does pick up changed files"
(cd original && echo hello >>f0)
cp test-u.tar test-u2.tar
(cd original && ${BSDTAR} -uf ../test-u2.tar .)
# All this really tests is that the archive did change.
cmp -s test-u.tar test-u2.tar && echo XXX FAILED XXX
# Now, unpack the archive and verify the contents (including the change to f0)
mkdir copy-u-test2
(cd copy-u-test2 && ${BSDTAR} -xf ../test-u2.tar)
(diff -r original copy-u-test2 || echo XXX FAILED XXX 1>&2) | head

View file

@ -0,0 +1,60 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-deep-dir.sh,v 1.1 2007/03/11 10:36:42 kientzle Exp $
# Stress the deep directory logic; the actual depth here seems to
# be limited by the shell. This should be restructured to get around
# that limit (possibly by using perl to build the deep tree?)
echo Deep directory tests
# Basic test configuration
. `dirname $0`/config.sh
# Create a deep dir (shell seems to be limited by PATH_MAX)
mkdir original
cd original
I=0
while [ $I -lt 200 ]
do
mkdir a$I
cd a$I
I=$(($I + 1))
done
while [ $I -gt 0 ] ; do cd ..; I=$(($I - 1)); done
cd ..
# Copy this using bsdtar
echo " tar -c | tar -x"
mkdir copy
(cd original; ${BSDTAR} -cf - .) | (cd copy; ${BSDTAR} -xf -)
diff -r original copy || echo XXX FAILURE XXX
# Copy gtar->bsdtar
echo " gtar -c | tar -x"
mkdir copy-gtar
(cd original; ${GTAR} -cf - .) | (cd copy-gtar; ${BSDTAR} -xf -)
diff -r original copy-gtar || echo XXX FAILURE XXX
cd ..

View file

@ -0,0 +1,74 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-flags.sh,v 1.1 2007/03/11 10:36:42 kientzle Exp $
# Exercise copying of file flags
echo "File Flag handling"
# Basic test configuration
. `dirname $0`/config.sh
# Create some files with various flags set
mkdir original
FLAGS='uchg opaque nodump uappnd'
for f in $FLAGS; do
touch original/test.$f
chflags $f original/test.$f
done
#ls -ol ${TESTDIR}/original
# Copy the dir with -p
echo " -p preserves flags"
mkdir copy
(cd original && ${BSDTAR} -cf - .) | (cd copy; ${BSDTAR} -xpf -)
# Verify that the flags are set
for f in $FLAGS; do
[ "$f" = `ls -ol copy/test.$f | awk '{print $5}'` ] \
|| echo XXX FAIL: $f not preserved with -p XXX
done
#ls -ol ${TESTDIR}/copy
# Copy the dir without -p
echo " flags omitted without -p"
mkdir copy2
(cd original && ${BSDTAR} -cf - .) | (cd copy2; ${BSDTAR} -xf -)
# Verify that the flags are not set
for f in $FLAGS; do
[ "$f" = `ls -ol copy2/test.$f | awk '{print $5}'` ] \
&& echo XXX FAIL: $f copied without -p XXX
done
#ls -ol ${TESTDIR}/copy2
# Strip off the flags so we can clean this directory on the next test
for f in $FLAGS; do
if [ $f = 'nodump' ]; then
chflags dump original/test.$f
chflags dump copy/test.$f
else
chflags no$f original/test.$f
chflags no$f copy/test.$f
fi
done
cd ..

View file

@ -0,0 +1,52 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-nodump.sh,v 1.1 2007/03/11 10:36:42 kientzle Exp $
# Test that archiving obeys the 'nodump' flag
echo "Verify 'nodump'"
# Basic test configuration
. `dirname $0`/config.sh
# Create some sample files, 'b' is marked nodump
mkdir original
cd original
touch a
touch b
touch c
# 'chflags' on FreeBSD, 'chattr' on Linux
( chflags nodump b || chattr +d b ) >/dev/null 2>&1 || echo XXX NO chflags/chattr command XXX
# Copy files with --nodump
cd ..
mkdir copy
(cd original && ${BSDTAR} -cf - --nodump .) | (cd copy; ${BSDTAR} -xf -)
# Verify that 'b' wasn't copied
echo " File marked nodump wasn't copied"
if [ -e copy/b ] ; then echo XXX Copied nodump file XXX; fi
echo " File not marked nodump was copied"
if [ \! -e copy/a ] ; then echo XXX Failed to copy non-nodump file a XXX; fi
diff -r --exclude=b original copy || echo XXX FAILURE XXX
cd ..

View file

@ -0,0 +1,51 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-overwrite.sh,v 1.1 2007/03/11 10:36:42 kientzle Exp $
echo "Test overwrite avoidance"
. `dirname $0`/config.sh
# Create a file with some data.
# This ensures that test.tar actually has some data in it
# by the time tar tries to add it to itself.
dd if=/dev/urandom of=a bs=1k count=100 >/dev/null 2>&1
# Now try to implicitly add archive to itself
${BSDTAR} -cf test.tar . || echo XXX FAILED XXX
# Create another file
dd if=/dev/urandom of=b bs=1k count=100 >/dev/null 2>&1
# Try again.
${BSDTAR} -cf test.tar . || echo XXX FAILED XXX
# Extract the archive and check that the two files got archived, despite the warning
mkdir compare
cd compare
${BSDTAR} -xf ../test.tar
cmp a ../a || echo XXX a didn't archive correctly XXX
cmp b ../b || echo XXX b didn't archive correctly XXX
# TODO: Test overwrite avoidance on extract

View file

@ -0,0 +1,40 @@
#!/bin/sh
# Copyright (c) 2007 Tim Kientzle
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD: src/usr.bin/tar/test/test-utf8.sh,v 1.1 2007/03/11 10:36:42 kientzle Exp $
echo "Test UTF8 filenames"
. `dirname $0`/config.sh
# Create some files with names in UTF8
export LC_ALL=en_US.UTF-8
touch "Greek: Γειά σας"
touch "Hebrew: שלום"
touch "Russian: Здравствуйте!"
touch "Japanese: <20><><EFBFBD><EFBFBD><EFBFBD>, コンニチハ"
touch "Chinese: <20><>"
tar -cf test.tar .
# TODO: Verify the resulting archive

289
commands/bsdtar/test/test.h Normal file
View file

@ -0,0 +1,289 @@
/*
* Copyright (c) 2003-2006 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/usr.bin/tar/test/test.h,v 1.4 2008/08/21 07:04:57 kientzle Exp $
*/
/* Every test program should #include "test.h" as the first thing. */
/*
* The goal of this file (and the matching test.c) is to
* simplify the very repetitive test-*.c test programs.
*/
#if defined(HAVE_CONFIG_H)
/* Most POSIX platforms use the 'configure' script to build config.h */
#include "config.h"
#elif defined(__FreeBSD__)
/* Building as part of FreeBSD system requires a pre-built config.h. */
#include "config_freebsd.h"
#elif defined(_WIN32) && !defined(__CYGWIN__)
/* Win32 can't run the 'configure' script. */
#include "config_windows.h"
#else
/* Warn if the library hasn't been (automatically or manually) configured. */
#error Oops: No config.h and no pre-built configuration in test.h.
#endif
#include <sys/types.h> /* Windows requires this before sys/stat.h */
#include <sys/stat.h>
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#define dirent direct
#endif
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_IO_H
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <wchar.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
/*
* System-specific tweaks. We really want to minimize these
* as much as possible, since they make it harder to understand
* the mainline code.
*/
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "../bsdtar_windows.h"
#if !defined(__BORLANDC__)
#define strdup _strdup
#endif
#define LOCALE_DE "deu"
#else
#define LOCALE_DE "de_DE.UTF-8"
#endif
/* Visual Studio */
#ifdef _MSC_VER
#define snprintf sprintf_s
#endif
/* Cygwin */
#if defined(__CYGWIN__)
/* Cygwin-1.7.x is lazy about populating nlinks, so don't
* expect it to be accurate. */
# define NLINKS_INACCURATE_FOR_DIRS
#endif
/* Haiku OS */
#if defined(__HAIKU__)
/* Haiku has typedefs in stdint.h (needed for int64_t) */
#include <stdint.h>
#endif
/* Get a real definition for __FBSDID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
/*
* Redefine DEFINE_TEST for use in defining the test functions.
*/
#undef DEFINE_TEST
#define DEFINE_TEST(name) void name(void); void name(void)
/* An implementation of the standard assert() macro */
#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
/* chdir() and error if it fails */
#define assertChdir(path) \
assertion_chdir(__FILE__, __LINE__, path)
/* Assert two integers are the same. Reports value of each one if not. */
#define assertEqualInt(v1,v2) \
assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* Assert two strings are the same. Reports value of each one if not. */
#define assertEqualString(v1,v2) \
assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but v1 and v2 are wchar_t * */
#define assertEqualWString(v1,v2) \
assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but raw blocks of bytes. */
#define assertEqualMem(v1, v2, l) \
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
/* Assert two files are the same; allow printf-style expansion of second name.
* See below for comments about variable arguments here...
*/
#define assertEqualFile \
assertion_setup(__FILE__, __LINE__);assertion_equal_file
/* Assert that a file is empty; supports printf-style arguments. */
#define assertEmptyFile \
assertion_setup(__FILE__, __LINE__);assertion_empty_file
/* Assert that a file is not empty; supports printf-style arguments. */
#define assertNonEmptyFile \
assertion_setup(__FILE__, __LINE__);assertion_non_empty_file
#define assertFileAtime(pathname, sec, nsec) \
assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileAtimeRecent(pathname) \
assertion_file_atime_recent(__FILE__, __LINE__, pathname)
#define assertFileBirthtime(pathname, sec, nsec) \
assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileBirthtimeRecent(pathname) \
assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
/* Assert that a file exists; supports printf-style arguments. */
#define assertFileExists \
assertion_setup(__FILE__, __LINE__);assertion_file_exists
/* Assert that a file exists; supports printf-style arguments. */
#define assertFileNotExists \
assertion_setup(__FILE__, __LINE__);assertion_file_not_exists
/* Assert that file contents match a string; supports printf-style arguments. */
#define assertFileContents \
assertion_setup(__FILE__, __LINE__);assertion_file_contents
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
#define assertFileNLinks(pathname, nlinks) \
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
#define assertTextFileContents \
assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
#define assertFileContainsLinesAnyOrder(pathname, lines) \
assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
#define assertIsHardlink(path1, path2) \
assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsNotHardlink(path1, path2) \
assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsReg(pathname, mode) \
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
#define assertIsSymlink(pathname, contents) \
assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
/* Create a directory, report error if it fails. */
#define assertMakeDir(dirname, mode) \
assertion_make_dir(__FILE__, __LINE__, dirname, mode)
#define assertMakeFile(path, mode, contents) \
assertion_make_file(__FILE__, __LINE__, path, mode, contents)
#define assertMakeHardlink(newfile, oldfile) \
assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
#define assertMakeSymlink(newfile, linkto) \
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
#define assertUmask(mask) \
assertion_umask(__FILE__, __LINE__, mask)
/*
* This would be simple with C99 variadic macros, but I don't want to
* require that. Instead, I insert a function call before each
* skipping() call to pass the file and line information down. Crude,
* but effective.
*/
#define skipping \
assertion_setup(__FILE__, __LINE__);test_skipping
/* Function declarations. These are defined in test_utility.c. */
void failure(const char *fmt, ...);
int assertion_assert(const char *, int, int, const char *, void *);
int assertion_chdir(const char *, int, const char *);
int assertion_empty_file(const char *, ...);
int assertion_equal_file(const char *, const char *, ...);
int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int assertion_file_atime(const char *, int, const char *, long, long);
int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
int assertion_file_contents(const void *, int, const char *, ...);
int assertion_file_exists(const char *, ...);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
int assertion_file_not_exists(const char *, ...);
int assertion_file_size(const char *, int, const char *, long);
int assertion_is_dir(const char *, int, const char *, int);
int assertion_is_hardlink(const char *, int, const char *, const char *);
int assertion_is_not_hardlink(const char *, int, const char *, const char *);
int assertion_is_reg(const char *, int, const char *, int);
int assertion_is_symlink(const char *, int, const char *, const char *);
int assertion_make_dir(const char *, int, const char *, int);
int assertion_make_file(const char *, int, const char *, int, const char *);
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
int assertion_make_symlink(const char *, int, const char *newpath, const char *);
int assertion_non_empty_file(const char *, ...);
int assertion_text_file_contents(const char *buff, const char *f);
int assertion_umask(const char *, int, int);
void assertion_setup(const char *, int);
void test_skipping(const char *fmt, ...);
/* Like sprintf, then system() */
int systemf(const char * fmt, ...);
/* Delay until time() returns a value after this. */
void sleepUntilAfter(time_t);
/* Return true if this platform can create symlinks. */
int canSymlink(void);
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
/* Return true if this platform can run the "gunzip" program. */
int canGunzip(void);
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
/*
* Special interfaces for program test harness.
*/
/* Pathname of exe to be tested. */
const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;

View file

@ -0,0 +1,67 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_0.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
/*
* This first test does basic sanity checks on the environment. For
* most of these, we just exit on failure.
*/
#if !defined(_WIN32) || defined(__CYGWIN__)
#define DEV_NULL "/dev/null"
#else
#define DEV_NULL "NUL"
#endif
DEFINE_TEST(test_0)
{
struct stat st;
failure("File %s does not exist?!", testprog);
if (!assertEqualInt(0, stat(testprogfile, &st)))
exit(1);
failure("%s is not executable?!", testprog);
if (!assert((st.st_mode & 0111) != 0))
exit(1);
/*
* Try to succesfully run the program; this requires that
* we know some option that will succeed.
*/
if (0 == systemf("%s --version >" DEV_NULL, testprog)) {
/* This worked. */
} else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) {
/* This worked. */
} else {
failure("Unable to successfully run any of the following:\n"
" * %s --version\n"
" * %s -W version\n",
testprog, testprog);
assert(0);
}
/* TODO: Ensure that our reference files are available. */
}

View file

@ -0,0 +1,115 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_basic.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
static void
basic_tar(const char *target, const char *pack_options,
const char *unpack_options, const char *flist)
{
int r;
assertMakeDir(target, 0775);
/* Use the tar program to create an archive. */
r = systemf("%s cf - %s %s >%s/archive 2>%s/pack.err", testprog, pack_options, flist, target, target);
failure("Error invoking %s cf -", testprog, pack_options);
assertEqualInt(r, 0);
assertChdir(target);
/* Verify that nothing went to stderr. */
assertEmptyFile("pack.err");
/*
* Use tar to unpack the archive into another directory.
*/
r = systemf("%s xf archive %s >unpack.out 2>unpack.err", testprog, unpack_options);
failure("Error invoking %s xf archive %s", testprog, unpack_options);
assertEqualInt(r, 0);
/* Verify that nothing went to stderr. */
assertEmptyFile("unpack.err");
/*
* Verify unpacked files.
*/
/* Regular file with 2 links. */
assertIsReg("file", -1);
assertFileSize("file", 10);
failure("%s", target);
assertFileNLinks("file", 2);
/* Another name for the same file. */
assertIsReg("linkfile", -1);
assertFileSize("linkfile", 10);
assertFileNLinks("linkfile", 2);
assertIsHardlink("file", "linkfile");
/* Symlink */
if (canSymlink())
assertIsSymlink("symlink", "file");
/* dir */
assertIsDir("dir", 0775);
assertChdir("..");
}
DEFINE_TEST(test_basic)
{
FILE *f;
const char *flist;
assertUmask(0);
/* File with 10 bytes content. */
f = fopen("file", "wb");
assert(f != NULL);
assertEqualInt(10, fwrite("123456789", 1, 10, f));
fclose(f);
/* hardlink to above file. */
assertMakeHardlink("linkfile", "file");
assertIsHardlink("file", "linkfile");
/* Symlink to above file. */
if (canSymlink())
assertMakeSymlink("symlink", "file");
/* Directory. */
assertMakeDir("dir", 0775);
if (canSymlink())
flist = "file linkfile symlink dir";
else
flist = "file linkfile dir";
/* Archive/dearchive with a variety of options. */
basic_tar("copy", "", "", flist);
/* tar doesn't handle cpio symlinks correctly */
/* basic_tar("copy_odc", "--format=odc", ""); */
basic_tar("copy_ustar", "--format=ustar", "", flist);
}

View file

@ -0,0 +1,372 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_copy.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $");
#if defined(__CYGWIN__)
# include <limits.h>
# include <sys/cygwin.h>
#endif
/*
* Try to figure out how deep we can go in our tests. Assumes that
* the first call to this function has the longest starting cwd (which
* is currently "<testdir>/original"). This is mostly to work around
* limits in our Win32 support.
*
* Background: On Posix systems, PATH_MAX is merely a limit on the
* length of the string passed into a system call. By repeatedly
* calling chdir(), you can work with arbitrarily long paths on such
* systems. In contrast, Win32 APIs apply PATH_MAX limits to the full
* absolute path, so the permissible length of a system call argument
* varies with the cwd. Some APIs actually enforce limits
* significantly less than PATH_MAX to ensure that you can create
* files within the current working directory. The Win32 limits also
* apply to Cygwin before 1.7.
*
* Someday, I want to convert the Win32 support to use newer
* wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX
* instead of the rather anemic 260 character limit of the older
* system calls. Then we can drop this mess (unless we want to
* continue to special-case Cygwin 1.5 and earlier).
*/
static int
compute_loop_max(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
static int LOOP_MAX = 0;
char buf[MAX_PATH];
size_t cwdlen;
if (LOOP_MAX == 0) {
assert(_getcwd(buf, MAX_PATH) != NULL);
cwdlen = strlen(buf);
/* 12 characters = length of 8.3 filename */
/* 4 characters = length of "/../" used in symlink tests */
/* 1 character = length of extra "/" separator */
LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1;
}
return LOOP_MAX;
#elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH)
static int LOOP_MAX = 0;
if (LOOP_MAX == 0) {
char wbuf[PATH_MAX];
char pbuf[PATH_MAX];
size_t wcwdlen;
size_t pcwdlen;
size_t cwdlen;
assert(getcwd(pbuf, PATH_MAX) != NULL);
pcwdlen = strlen(pbuf);
cygwin_conv_to_full_win32_path(pbuf, wbuf);
wcwdlen = strlen(wbuf);
cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen);
/* Cygwin helper needs an extra few characters. */
LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4;
}
return LOOP_MAX;
#else
/* cygwin-1.7 ends up here, along with "normal" unix */
return 200; /* restore pre-r278 depth */
#endif
}
/* filenames[i] is a distinctive filename of length i. */
/* To simplify interpreting failures, each filename ends with a
* decimal integer which is the length of the filename. E.g., A
* filename ending in "_92" is 92 characters long. To detect errors
* which drop or misplace characters, the filenames use a repeating
* "abcdefghijklmnopqrstuvwxyz..." pattern. */
static char *filenames[201];
static void
compute_filenames(void)
{
char buff[250];
size_t i,j;
filenames[0] = strdup("");
filenames[1] = strdup("1");
filenames[2] = strdup("a2");
for (i = 3; i < sizeof(filenames)/sizeof(filenames[0]); ++i) {
/* Fill with "abcdefghij..." */
for (j = 0; j < i; ++j)
buff[j] = 'a' + (j % 26);
buff[j--] = '\0';
/* Work from the end to fill in the number portion. */
buff[j--] = '0' + (i % 10);
if (i > 9) {
buff[j--] = '0' + ((i / 10) % 10);
if (i > 99)
buff[j--] = '0' + (i / 100);
}
buff[j] = '_';
/* Guard against obvious screwups in the above code. */
assertEqualInt(strlen(buff), i);
filenames[i] = strdup(buff);
}
}
static void
create_tree(void)
{
char buff[260];
char buff2[260];
int i;
int LOOP_MAX;
compute_filenames();
/* Log that we'll be omitting some checks. */
if (!canSymlink()) {
skipping("Symlink checks");
}
assertMakeDir("original", 0775);
assertEqualInt(0, chdir("original"));
LOOP_MAX = compute_loop_max();
assertMakeDir("f", 0775);
assertMakeDir("l", 0775);
assertMakeDir("m", 0775);
assertMakeDir("s", 0775);
assertMakeDir("d", 0775);
for (i = 1; i < LOOP_MAX; i++) {
failure("Internal sanity check failed: i = %d", i);
assert(filenames[i] != NULL);
sprintf(buff, "f/%s", filenames[i]);
assertMakeFile(buff, 0777, buff);
/* Create a link named "l/abcdef..." to the above. */
sprintf(buff2, "l/%s", filenames[i]);
assertMakeHardlink(buff2, buff);
/* Create a link named "m/abcdef..." to the above. */
sprintf(buff2, "m/%s", filenames[i]);
assertMakeHardlink(buff2, buff);
if (canSymlink()) {
/* Create a symlink named "s/abcdef..." to the above. */
sprintf(buff, "s/%s", filenames[i]);
sprintf(buff2, "../f/%s", filenames[i]);
failure("buff=\"%s\" buff2=\"%s\"", buff, buff2);
assertMakeSymlink(buff, buff2);
}
/* Create a dir named "d/abcdef...". */
buff[0] = 'd';
failure("buff=\"%s\"", buff);
assertMakeDir(buff, 0775);
}
assertEqualInt(0, chdir(".."));
}
#define LIMIT_NONE 200
#define LIMIT_USTAR 100
static void
verify_tree(size_t limit)
{
char name1[260];
char name2[260];
size_t i, LOOP_MAX;
LOOP_MAX = compute_loop_max();
/* Generate the names we know should be there and verify them. */
for (i = 1; i < LOOP_MAX; i++) {
/* Verify a file named "f/abcdef..." */
sprintf(name1, "f/%s", filenames[i]);
if (i <= limit) {
assertFileExists(name1);
assertFileContents(name1, strlen(name1), name1);
}
sprintf(name2, "l/%s", filenames[i]);
if (i + 2 <= limit) {
/* Verify hardlink "l/abcdef..." */
assertIsHardlink(name1, name2);
/* Verify hardlink "m/abcdef..." */
name2[0] = 'm';
assertIsHardlink(name1, name2);
}
if (canSymlink()) {
/* Verify symlink "s/abcdef..." */
sprintf(name1, "s/%s", filenames[i]);
sprintf(name2, "../f/%s", filenames[i]);
if (strlen(name2) <= limit)
assertIsSymlink(name1, name2);
}
/* Verify dir "d/abcdef...". */
sprintf(name1, "d/%s", filenames[i]);
if (i + 1 <= limit) { /* +1 for trailing slash */
if (assertIsDir(name1, -1)) {
/* TODO: opendir/readdir this
* directory and make sure
* it's empty.
*/
}
}
}
#if !defined(_WIN32) || defined(__CYGWIN__)
{
const char *dp;
/* Now make sure nothing is there that shouldn't be. */
for (dp = "dflms"; *dp != '\0'; ++dp) {
DIR *d;
struct dirent *de;
char dir[2];
dir[0] = *dp; dir[1] = '\0';
d = opendir(dir);
failure("Unable to open dir '%s'", dir);
if (!assert(d != NULL))
continue;
while ((de = readdir(d)) != NULL) {
char *p = de->d_name;
if (p[0] == '.')
continue;
switch(dp[0]) {
case 'l': case 'm': case 'd':
failure("strlen(p)=%d", strlen(p));
assert(strlen(p) < limit);
assertEqualString(p,
filenames[strlen(p)]);
break;
case 'f': case 's':
failure("strlen(p)=%d", strlen(p));
assert(strlen(p) < limit + 1);
assertEqualString(p,
filenames[strlen(p)]);
break;
default:
failure("File %s shouldn't be here", p);
assert(0);
}
}
closedir(d);
}
}
#endif
}
static void
copy_basic(void)
{
int r;
/* NOTE: for proper operation on cygwin-1.5 and windows, the
* length of the name of the directory below, "plain", must be
* less than or equal to the lengthe of the name of the original
* directory, "original" This restriction derives from the
* extremely limited pathname lengths on those platforms.
*/
assertMakeDir("plain", 0775);
assertEqualInt(0, chdir("plain"));
/*
* Use the tar program to create an archive.
*/
r = systemf("%s cf archive -C ../original f d l m s >pack.out 2>pack.err",
testprog);
failure("Error invoking \"%s cf\"", testprog);
assertEqualInt(r, 0);
/* Verify that nothing went to stdout or stderr. */
assertEmptyFile("pack.err");
assertEmptyFile("pack.out");
/*
* Use tar to unpack the archive into another directory.
*/
r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog);
failure("Error invoking %s xf archive", testprog);
assertEqualInt(r, 0);
/* Verify that nothing went to stdout or stderr. */
assertEmptyFile("unpack.err");
assertEmptyFile("unpack.out");
verify_tree(LIMIT_NONE);
assertEqualInt(0, chdir(".."));
}
static void
copy_ustar(void)
{
const char *target = "ustar";
int r;
/* NOTE: for proper operation on cygwin-1.5 and windows, the
* length of the name of the directory below, "ustar", must be
* less than or equal to the lengthe of the name of the original
* directory, "original" This restriction derives from the
* extremely limited pathname lengths on those platforms.
*/
assertMakeDir(target, 0775);
assertEqualInt(0, chdir(target));
/*
* Use the tar program to create an archive.
*/
r = systemf("%s cf archive --format=ustar -C ../original f d l m s >pack.out 2>pack.err",
testprog);
failure("Error invoking \"%s cf archive --format=ustar\"", testprog);
assertEqualInt(r, 0);
/* Verify that nothing went to stdout. */
assertEmptyFile("pack.out");
/* Stderr is non-empty, since there are a bunch of files
* with filenames too long to archive. */
/*
* Use tar to unpack the archive into another directory.
*/
r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog);
failure("Error invoking %s xf archive", testprog);
assertEqualInt(r, 0);
/* Verify that nothing went to stdout or stderr. */
assertEmptyFile("unpack.err");
assertEmptyFile("unpack.out");
verify_tree(LIMIT_USTAR);
assertEqualInt(0, chdir("../.."));
}
DEFINE_TEST(test_copy)
{
assertUmask(0);
create_tree(); /* Create sample files in "original" dir. */
/* Test simple "tar -c | tar -x" pipeline copy. */
copy_basic();
/* Same, but constrain to ustar format. */
copy_ustar();
}

View file

@ -0,0 +1,45 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* Regression test: We used to get a bogus error message when we
* asked tar to copy entries out of an empty archive. See
* Issue 51 on libarchive.googlecode.com for details.
*/
DEFINE_TEST(test_empty_mtree)
{
int r;
assertMakeFile("test1.mtree", 0777, "#mtree\n");
r = systemf("%s cf test1.tar @test1.mtree >test1.out 2>test1.err",
testprog);
failure("Error invoking %s cf", testprog);
assertEqualInt(r, 0);
assertEmptyFile("test1.out");
assertEmptyFile("test1.err");
}

View file

@ -0,0 +1,80 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_getdate.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
#include <time.h>
/*
* Verify that the getdate() function works.
*/
time_t get_date(time_t, const char *);
DEFINE_TEST(test_getdate)
{
time_t now = time(NULL);
assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0);
assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138);
assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980);
assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000);
assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460);
/* It's important that we handle ctime() format. */
assertEqualInt(get_date(now, "Sun Feb 22 17:38:26 PST 2009"),
1235353106);
/* Basic relative offsets. */
/* If we use the actual current time as the reference, then
* these tests break around DST changes, so it's actually
* important to use a specific reference time here. */
assertEqualInt(get_date(0, "tomorrow"), 24 * 60 * 60);
assertEqualInt(get_date(0, "yesterday"), - 24 * 60 * 60);
assertEqualInt(get_date(0, "now + 1 hour"), 60 * 60);
assertEqualInt(get_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60);
/* Repeat the above for a different start time. */
now = 1231113600; /* Jan 5, 2009 00:00 UTC */
assertEqualInt(get_date(0, "Jan 5, 2009 00:00 UTC"), now);
assertEqualInt(get_date(now, "tomorrow"), now + 24 * 60 * 60);
assertEqualInt(get_date(now, "yesterday"), now - 24 * 60 * 60);
assertEqualInt(get_date(now, "now + 1 hour"), now + 60 * 60);
assertEqualInt(get_date(now, "now + 1 hour + 1 minute"),
now + 60 * 60 + 60);
assertEqualInt(get_date(now, "tomorrow 5:16am UTC"),
now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60);
assertEqualInt(get_date(now, "UTC 5:16am tomorrow"),
now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60);
/* Jan 5, 2009 was a Monday. */
assertEqualInt(get_date(now, "monday UTC"), now);
assertEqualInt(get_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60);
assertEqualInt(get_date(now, "tuesday UTC"), now + 24 * 60 * 60);
/* "next tuesday" is one week after "tuesday" */
assertEqualInt(get_date(now, "UTC next tuesday"),
now + 8 * 24 * 60 * 60);
/* "last tuesday" is one week before "tuesday" */
assertEqualInt(get_date(now, "last tuesday UTC"),
now - 6 * 24 * 60 * 60);
/* TODO: Lots more tests here. */
}

View file

@ -0,0 +1,84 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_help.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
/*
* Test that "--help", "-h", and "-W help" options all work and
* generate reasonable output.
*/
static int
in_first_line(const char *p, const char *substring)
{
size_t l = strlen(substring);
while (*p != '\0' && *p != '\n') {
if (memcmp(p, substring, l) == 0)
return (1);
++p;
}
return (0);
}
DEFINE_TEST(test_help)
{
int r;
char *p;
size_t plen;
/* Exercise --help option. */
r = systemf("%s --help >help.stdout 2>help.stderr", testprog);
assertEqualInt(r, 0);
failure("--help should generate nothing to stderr.");
assertEmptyFile("help.stderr");
/* Help message should start with name of program. */
p = slurpfile(&plen, "help.stdout");
failure("Help output should be long enough.");
assert(plen >= 6);
failure("First line of help output should contain 'bsdtar': %s", p);
assert(in_first_line(p, "bsdtar"));
/*
* TODO: Extend this check to further verify that --help output
* looks approximately right.
*/
free(p);
/* -h option should generate the same output. */
r = systemf("%s -h >h.stdout 2>h.stderr", testprog);
assertEqualInt(r, 0);
failure("-h should generate nothing to stderr.");
assertEmptyFile("h.stderr");
failure("stdout should be same for -h and --help");
assertEqualFile("h.stdout", "help.stdout");
/* -W help should be another synonym. */
r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog);
assertEqualInt(r, 0);
failure("-W help should generate nothing to stderr.");
assertEmptyFile("Whelp.stderr");
failure("stdout should be same for -W help and --help");
assertEqualFile("Whelp.stdout", "help.stdout");
}

View file

@ -0,0 +1,188 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_T.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $");
static int
touch(const char *fn, int fail)
{
FILE *f = fopen(fn, "w");
if (fail) {
failure("Couldn't create file '%s', errno=%d (%s)\n",
fn, errno, strerror(errno));
if (!assert(f != NULL))
return (0); /* Failure. */
} else {
if (f == NULL)
return (0); /* Soft failure. */
}
fclose(f);
return (1); /* Success */
}
DEFINE_TEST(test_option_T_upper)
{
FILE *f;
int r;
struct stat st;
int gnarlyFilesSupported;
/* Create a simple dir heirarchy; bail if anything fails. */
if (!assertMakeDir("d1", 0755)) return;
if (!assertMakeDir("d1/d2", 0755)) return;
if (!touch("f", 1)) return;
if (!touch("d1/f1", 1)) return;
if (!touch("d1/f2", 1)) return;
if (!touch("d1/d2/f3", 1)) return;
if (!touch("d1/d2/f4", 1)) return;
if (!touch("d1/d2/f5", 1)) return;
if (!touch("d1/d2/f6", 1)) return;
/* Some platforms don't permit such things; just skip it. */
gnarlyFilesSupported = touch("d1/d2/f\x0a", 0);
/* Populate a file list */
f = fopen("filelist", "w+");
if (!assert(f != NULL))
return;
/* Use a variety of text line endings. */
fprintf(f, "f\x0d"); /* CR */
fprintf(f, "d1/f1\x0d\x0a"); /* CRLF */
fprintf(f, "d1/d2/f4\x0a"); /* NL */
fprintf(f, "d1/d2/f6"); /* EOF */
fclose(f);
/* Populate a second file list */
f = fopen("filelist2", "w+");
if (!assert(f != NULL))
return;
/* Use null-terminated names. */
fprintf(f, "d1/d2/f3");
fwrite("\0", 1, 1, f);
fprintf(f, "d1/d2/f5");
fwrite("\0", 1, 1, f);
if (gnarlyFilesSupported) {
fprintf(f, "d1/d2/f\x0a");
fwrite("\0", 1, 1, f);
}
fclose(f);
/* Use -c -T to archive up the files. */
r = systemf("%s -c -f test1.tar -T filelist > test1.out 2> test1.err",
testprog);
assert(r == 0);
assertEmptyFile("test1.out");
assertEmptyFile("test1.err");
/* Use -x -T to dearchive the files */
if (!assertMakeDir("test1", 0755)) return;
systemf("%s -x -f test1.tar -T filelist -C test1"
" > test1b.out 2> test1b.err", testprog);
assertEmptyFile("test1b.out");
assertEmptyFile("test1b.err");
/* Verify the files were extracted. */
assertFileExists("test1/f");
assertFileExists("test1/d1/f1");
assertFileNotExists("test1/d1/f2");
assertFileNotExists("test1/d1/d2/f3");
assertFileExists("test1/d1/d2/f4");
assertFileNotExists("test1/d1/d2/f5");
assertFileExists("test1/d1/d2/f6");
if (gnarlyFilesSupported) {
assertFileNotExists("test1/d1/d2/f\x0a");
}
/* Use -r -T to add more files to the archive. */
systemf("%s -r -f test1.tar --null -T filelist2 > test2.out 2> test2.err",
testprog);
assertEmptyFile("test2.out");
assertEmptyFile("test2.err");
/* Use -x without -T to dearchive the files (ensure -r worked) */
if (!assertMakeDir("test3", 0755)) return;
systemf("%s -x -f test1.tar -C test3"
" > test3.out 2> test3.err", testprog);
assertEmptyFile("test3.out");
assertEmptyFile("test3.err");
/* Verify the files were extracted.*/
assertFileExists("test3/f");
assertFileExists("test3/d1/f1");
assertFileNotExists("test3/d1/f2");
assertFileExists("test3/d1/d2/f3");
assertFileExists("test3/d1/d2/f4");
assertFileExists("test3/d1/d2/f5");
assertFileExists("test3/d1/d2/f6");
if (gnarlyFilesSupported) {
assertFileExists("test3/d1/d2/f\x0a");
}
/* Use -x -T to dearchive the files (verify -x -T together) */
if (!assertMakeDir("test2", 0755)) return;
systemf("%s -x -f test1.tar -T filelist -C test2"
" > test2b.out 2> test2b.err", testprog);
assertEmptyFile("test2b.out");
assertEmptyFile("test2b.err");
/* Verify the files were extracted.*/
assertFileExists("test2/f");
assertFileExists("test2/d1/f1");
assertFileNotExists("test2/d1/f2");
assertFileNotExists("test2/d1/d2/f3");
assertFileExists("test2/d1/d2/f4");
assertFileNotExists("test2/d1/d2/f5");
assertFileExists("test2/d1/d2/f6");
if (gnarlyFilesSupported) {
assertFileNotExists("test2/d1/d2/f\x0a");
}
assertMakeDir("test4", 0755);
assertMakeDir("test4_out", 0755);
assertMakeDir("test4_out2", 0755);
assertMakeDir("test4/d1", 0755);
assertEqualInt(1, touch("test4/d1/foo", 0));
/* Does bsdtar support -s option ? */
systemf("%s -cf - -s /foo/bar/ test4/d1/foo > check.out 2> check.err",
testprog);
assertEqualInt(0, stat("check.err", &st));
if (st.st_size == 0) {
systemf("%s -cf - -s /foo/bar/ test4/d1/foo | %s -xf - -C test4_out",
testprog, testprog);
assertEmptyFile("test4_out/test4/d1/bar");
systemf("%s -cf - -s /d1/d2/ test4/d1/foo | %s -xf - -C test4_out",
testprog, testprog);
assertEmptyFile("test4_out/test4/d2/foo");
systemf("%s -cf - -s ,test4/d1/foo,, test4/d1/foo | %s -tvf - > test4.lst",
testprog, testprog);
assertEmptyFile("test4.lst");
systemf("%s -cf - test4/d1/foo | %s -xf - -s /foo/bar/ -C test4_out2",
testprog, testprog);
assertEmptyFile("test4_out2/test4/d1/bar");
} else {
skipping("bsdtar does not support -s option on this platform");
}
/* TODO: Include some use of -C directory-changing within the filelist. */
/* I'm pretty sure -C within the filelist is broken on extract. */
}

View file

@ -0,0 +1,129 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_q.c,v 1.3 2008/08/22 01:35:08 kientzle Exp $");
DEFINE_TEST(test_option_q)
{
FILE *f;
int r;
/*
* Create an archive with several different versions of the
* same files. By default, the last version will overwrite
* any earlier versions. The -q/--fast-read option will
* stop early, so we can verify -q/--fast-read by seeing
* which version of each file actually ended up being
* extracted. This also exercises -r mode, since that's
* what we use to build up the test archive.
*/
f = fopen("foo", "w");
assert(f != NULL);
fprintf(f, "foo1");
fclose(f);
assertEqualInt(0, systemf("%s -cf archive.tar foo", testprog));
f = fopen("foo", "w");
assert(f != NULL);
fprintf(f, "foo2");
fclose(f);
assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog));
f = fopen("bar", "w");
assert(f != NULL);
fprintf(f, "bar1");
fclose(f);
assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog));
f = fopen("foo", "w");
assert(f != NULL);
fprintf(f, "foo3");
fclose(f);
assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog));
f = fopen("bar", "w");
assert(f != NULL);
fprintf(f, "bar2");
fclose(f);
assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog));
/*
* Now, try extracting from the test archive with various
* combinations of -q.
*/
/* Test 1: -q foo should only extract the first foo. */
assertMakeDir("test1", 0755);
assertChdir("test1");
r = systemf("%s -xf ../archive.tar -q foo >test.out 2>test.err",
testprog);
failure("Fatal error trying to use -q option");
if (!assertEqualInt(0, r))
return;
assertFileContents("foo1", 4, "foo");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
assertChdir("..");
/* Test 2: -q foo bar should extract up to the first bar. */
assertMakeDir("test2", 0755);
assertChdir("test2");
assertEqualInt(0,
systemf("%s -xf ../archive.tar -q foo bar >test.out 2>test.err", testprog));
assertFileContents("foo2", 4, "foo");
assertFileContents("bar1", 4, "bar");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
assertChdir("..");
/* Test 3: Same as test 2, but use --fast-read spelling. */
assertMakeDir("test3", 0755);
assertChdir("test3");
assertEqualInt(0,
systemf("%s -xf ../archive.tar --fast-read foo bar >test.out 2>test.err", testprog));
assertFileContents("foo2", 4, "foo");
assertFileContents("bar1", 4, "bar");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
assertChdir("..");
/* Test 4: Without -q, should extract everything. */
assertMakeDir("test4", 0755);
assertChdir("test4");
assertEqualInt(0,
systemf("%s -xf ../archive.tar foo bar >test.out 2>test.err", testprog));
assertFileContents("foo3", 4, "foo");
assertFileContents("bar2", 4, "bar");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
assertChdir("..");
}

View file

@ -0,0 +1,117 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* Also see test_option_q for additional validation of -r support.
*/
DEFINE_TEST(test_option_r)
{
char buff[15];
char *p0, *p1;
size_t s;
FILE *f;
int r;
/* Create a file */
f = fopen("f1", "w");
if (!assert(f != NULL))
return;
assertEqualInt(3, fwrite("abc", 1, 3, f));
fclose(f);
/* Archive that one file. */
r = systemf("%s cf archive.tar --format=ustar f1 >step1.out 2>step1.err", testprog);
failure("Error invoking %s cf archive.tar f1", testprog);
assertEqualInt(r, 0);
/* Verify that nothing went to stdout or stderr. */
assertEmptyFile("step1.out");
assertEmptyFile("step1.err");
/* Do some basic validation of the constructed archive. */
p0 = slurpfile(&s, "archive.tar");
if (!assert(p0 != NULL))
return;
if (!assert(s >= 2048)) {
free(p0);
return;
}
assertEqualMem(p0 + 0, "f1", 3);
assertEqualMem(p0 + 512, "abc", 3);
assertEqualMem(p0 + 1024, "\0\0\0\0\0\0\0\0", 8);
assertEqualMem(p0 + 1536, "\0\0\0\0\0\0\0\0", 8);
/* Edit that file */
f = fopen("f1", "w");
if (!assert(f != NULL))
return;
assertEqualInt(3, fwrite("123", 1, 3, f));
fclose(f);
/* Update the archive. */
r = systemf("%s rf archive.tar --format=ustar f1 >step2.out 2>step2.err", testprog);
failure("Error invoking %s rf archive.tar f1", testprog);
assertEqualInt(r, 0);
/* Verify that nothing went to stdout or stderr. */
assertEmptyFile("step2.out");
assertEmptyFile("step2.err");
/* Do some basic validation of the constructed archive. */
p1 = slurpfile(&s, "archive.tar");
if (!assert(p1 != NULL)) {
free(p0);
return;
}
assert(s >= 3072);
/* Verify first entry is unchanged. */
assertEqualMem(p0, p1, 1024);
/* Verify that second entry is correct. */
assertEqualMem(p1 + 1024, "f1", 3);
assertEqualMem(p1 + 1536, "123", 3);
/* Verify end-of-archive marker. */
assertEqualMem(p1 + 2048, "\0\0\0\0\0\0\0\0", 8);
assertEqualMem(p1 + 2560, "\0\0\0\0\0\0\0\0", 8);
free(p0);
free(p1);
/* Unpack both items */
assertMakeDir("step3", 0775);
assertChdir("step3");
r = systemf("%s xf ../archive.tar", testprog);
failure("Error invoking %s xf archive.tar", testprog);
assertEqualInt(r, 0);
/* Verify that the second one overwrote the first. */
f = fopen("f1", "r");
if (assert(f != NULL)) {
assertEqualInt(3, fread(buff, 1, 3, f));
assertEqualMem(buff, "123", 3);
fclose(f);
}
}

View file

@ -0,0 +1,107 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_T.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $");
static int
mkfile(const char *fn, const char *contents)
{
FILE *f = fopen(fn, "w");
failure("Couldn't create file '%s', errno=%d (%s)\n",
fn, errno, strerror(errno));
if (!assert(f != NULL))
return (1); /* Failure. */
if (contents != NULL)
assertEqualInt(strlen(contents),
fwrite(contents, 1, strlen(contents), f));
assertEqualInt(0, fclose(f));
return (0); /* Success */
}
DEFINE_TEST(test_option_s)
{
struct stat st;
/* Create a sample file heirarchy. */
assertMakeDir("in", 0755);
assertMakeDir("in/d1", 0755);
assertEqualInt(0, mkfile("in/d1/foo", "foo"));
assertEqualInt(0, mkfile("in/d1/bar", "bar"));
/* Does bsdtar support -s option ? */
systemf("%s -cf - -s /foo/bar/ in/d1/foo > NUL 2> check.err",
testprog);
assertEqualInt(0, stat("check.err", &st));
if (st.st_size != 0) {
skipping("%s does not support -s option on this platform",
testprog);
return;
}
/*
* Test 1: Filename substitution when creating archives.
*/
assertMakeDir("test1", 0755);
systemf("%s -cf - -s /foo/bar/ in/d1/foo | %s -xf - -C test1",
testprog, testprog);
assertFileContents("foo", 3, "test1/in/d1/bar");
systemf("%s -cf - -s /d1/d2/ in/d1/foo | %s -xf - -C test1",
testprog, testprog);
assertFileContents("foo", 3, "test1/in/d2/foo");
/*
* Test 2: Basic substitution when extracting archive.
*/
assertMakeDir("test2", 0755);
systemf("%s -cf - in/d1/foo | %s -xf - -s /foo/bar/ -C test2",
testprog, testprog);
assertFileContents("foo", 3, "test2/in/d1/bar");
/*
* Test 3: Files with empty names shouldn't be archived.
*/
systemf("%s -cf - -s ,in/d1/foo,, in/d1/foo | %s -tvf - > in.lst",
testprog, testprog);
assertEmptyFile("in.lst");
/*
* Test 4: Multiple substitutions when extracting archive.
*/
assertMakeDir("test4", 0755);
systemf("%s -cf - in/d1/foo in/d1/bar | %s -xf - -s /foo/bar/ -s }bar}baz} -C test4",
testprog, testprog);
assertFileContents("foo", 3, "test4/in/d1/bar");
assertFileContents("bar", 3, "test4/in/d1/baz");
/*
* Test 5: Name-switching substitutions when extracting archive.
*/
assertMakeDir("test5", 0755);
systemf("%s -cf - in/d1/foo in/d1/bar | %s -xf - -s /foo/bar/ -s }bar}foo} -C test5",
testprog, testprog);
assertFileContents("foo", 3, "test5/in/d1/bar");
assertFileContents("bar", 3, "test5/in/d1/foo");
}

View file

@ -0,0 +1,184 @@
/*-
* Copyright (c) 2009 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_patterns.c,v 1.6 2008/08/21 22:28:00 kientzle Exp $");
DEFINE_TEST(test_patterns)
{
FILE *f;
int r;
const char *reffile2 = "test_patterns_2.tar";
const char *reffile3 = "test_patterns_3.tar";
const char *reffile4 = "test_patterns_4.tar";
const char *tar2aExpected[] = {
"/tmp/foo/bar/",
"/tmp/foo/bar/baz",
NULL
};
/*
* Test basic command-line pattern handling.
*/
/*
* Test 1: Files on the command line that don't get matched
* didn't produce an error.
*
* John Baldwin reported this problem in PR bin/121598
*/
f = fopen("foo", "w");
assert(f != NULL);
fclose(f);
r = systemf("%s cfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog);
assertEqualInt(r, 0);
r = systemf("%s xv --no-same-owner -f tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog);
failure("tar should return non-zero because a file was given on the command line that's not in the archive");
assert(r != 0);
/*
* Test 2: Check basic matching of full paths that start with /
*/
extract_reference_file(reffile2);
r = systemf("%s tf %s /tmp/foo/bar > tar2a.out 2> tar2a.err",
testprog, reffile2);
assertEqualInt(r, 0);
assertFileContainsLinesAnyOrder("tar2a.out", tar2aExpected);
assertEmptyFile("tar2a.err");
/*
* Test 3 archive has some entries starting with '/' and some not.
*/
extract_reference_file(reffile3);
/* Test 3a: Pattern tmp/foo/bar should not match /tmp/foo/bar */
r = systemf("%s x --no-same-owner -f %s tmp/foo/bar > tar3a.out 2> tar3a.err",
testprog, reffile3);
assert(r != 0);
assertEmptyFile("tar3a.out");
/* Test 3b: Pattern /tmp/foo/baz should not match tmp/foo/baz */
assertNonEmptyFile("tar3a.err");
/* Again, with the '/' */
r = systemf("%s x --no-same-owner -f %s /tmp/foo/baz > tar3b.out 2> tar3b.err",
testprog, reffile3);
assert(r != 0);
assertEmptyFile("tar3b.out");
assertNonEmptyFile("tar3b.err");
/* Test 3c: ./tmp/foo/bar should not match /tmp/foo/bar */
r = systemf("%s x --no-same-owner -f %s ./tmp/foo/bar > tar3c.out 2> tar3c.err",
testprog, reffile3);
assert(r != 0);
assertEmptyFile("tar3c.out");
assertNonEmptyFile("tar3c.err");
/* Test 3d: ./tmp/foo/baz should match tmp/foo/baz */
r = systemf("%s x --no-same-owner -f %s ./tmp/foo/baz > tar3d.out 2> tar3d.err",
testprog, reffile3);
assertEqualInt(r, 0);
assertEmptyFile("tar3d.out");
assertEmptyFile("tar3d.err");
assertFileExists("tmp/foo/baz/bar");
/*
* Test 4 archive has some entries starting with windows drive letters
* such as 'c:\', '//./c:/' or '//?/c:/'.
*/
extract_reference_file(reffile4);
r = systemf("%s x --no-same-owner -f %s -C tmp > tar4.out 2> tar4.err",
testprog, reffile4);
assert(r != 0);
assertEmptyFile("tar4.out");
assertNonEmptyFile("tar4.err");
for (r = 1; r <= 54; r++) {
char file_a[] = "tmp/fileXX";
char file_b1[] = "tmp/server/share/fileXX";
char file_b2[] = "tmp/server\\share\\fileXX";
char file_c[] = "tmp/../fileXX";
char *filex;
int xsize;
switch (r) {
case 15: case 18:
/*
* Including server and share names.
* //?/UNC/server/share/file15
* //?/unc/server/share/file18
*/
filex = file_b1;
xsize = sizeof(file_b1);
break;
case 35: case 38: case 52:
/*
* Including server and share names.
* \\?\UNC\server\share\file35
* \\?\unc\server\share\file38
* \/?/uNc/server\share\file52
*/
filex = file_b2;
xsize = sizeof(file_b2);
break;
default:
filex = file_a;
xsize = sizeof(file_a);
break;
}
filex[xsize-3] = '0' + r / 10;
filex[xsize-2] = '0' + r % 10;
switch (r) {
case 5: case 6: case 17: case 20: case 25:
case 26: case 37: case 40: case 43: case 54:
/*
* Not extracted patterns.
* D:../file05
* c:../../file06
* //?/UNC/../file17
* //?/unc/../file20
* z:..\file25
* c:..\..\file26
* \\?\UNC\..\file37
* \\?\unc\..\file40
* c:../..\file43
* \/?\UnC\../file54
*/
assertFileNotExists(filex);
filex = file_c;
xsize = sizeof(file_c);
filex[xsize-3] = '0' + r / 10;
filex[xsize-2] = '0' + r % 10;
assertFileNotExists(filex);
break;
default:
/* Extracted patterns. */
assertFileExists(filex);
break;
}
}
}

View file

@ -0,0 +1,231 @@
begin 644 test_patterns_2.tar
M+W1M<"]F;V\O````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#<U-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P,#`P,#`P
M(#$Q,#4Q,C$R-C4V(#`Q,C0T,0`@-0``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
M````````````````````````````````````=VAE96P`````````````````
M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````O=&UP+V9O;R]B87(O````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````,#`P-S4U(``P,#$W-3`@`#`P
M,#`P,"``,#`P,#`P,#`P,#`@,3$P-3$R,3(V-3,@,#$S,C`R`"`U````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````'5S=&%R`#`P=&EM``````````````````````````````````````!W
M:&5E;````````````````````````````````````#`P,#`P,"``,#`P,#`P
M(```````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````"]T;7`O9F]O+V)A
M>@``````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`V-#0@`#`P,3<U,"``,#`P,#`P(``P,#`P,#`P,#`P,"`Q,3`U,3(Q,C8U
M-B`P,3,Q,C8`(#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#!T:6T`````````````````
M`````````````````````'=H965L````````````````````````````````
M````,#`P,#`P(``P,#`P,#`@````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````+W1M<"]F;V\O8F%R+V)A>@``````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#8T-"``,#`Q-S4P(``P,#`P,#`@`#`P,#`P
M,#`P,#`P(#$Q,#4Q,C$R-C4S(#`Q,S8V-P`@,```````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<@`P
M,'1I;0``````````````````````````````````````=VAE96P`````````
M```````````````````````````P,#`P,#`@`#`P,#`P,"``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
9````````````````````````````````````
`
end

View file

@ -0,0 +1,231 @@
begin 644 test_patterns_3.tar
M+W1M<"]F;V\O8F%R+P``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#<U-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P,#`P,#`P
M(#$Q,#4S,C`W-34R(#`Q,S(P-@`@-0``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
M````````````````````````````````````=VAE96P`````````````````
M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````O=&UP+V9O;R]B87(O8F%Z+P``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````,#`P-S4U(``P,#$W-3`@`#`P
M,#`P,"``,#`P,#`P,#`P,#`@,3$P-3,R,#<U-3(@,#$S-S8R`"`U````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````'5S=&%R`#`P=&EM``````````````````````````````````````!W
M:&5E;````````````````````````````````````#`P,#`P,"``,#`P,#`P
M(```````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````'1M<"]F;V\O8F%Z
M+P``````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`W-34@`#`P,3<U,"``,#`P,#`P(``P,#`P,#`P,#`P,"`Q,3`U,S(P-S4V
M,"`P,3,Q,S8`(#4`````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#!T:6T`````````````````
M`````````````````````'=H965L````````````````````````````````
M````,#`P,#`P(``P,#`P,#`@````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````=&UP+V9O;R]B87HO8F%R+P``````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#<U-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P
M,#`P,#`P(#$Q,#4S,C`W-38P(#`Q,S<P,@`@-0``````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<@`P
M,'1I;0``````````````````````````````````````=VAE96P`````````
M```````````````````````````P,#`P,#`@`#`P,#`P,"``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
9````````````````````````````````````
`
end

View file

@ -0,0 +1,641 @@
begin 644 test_patterns_4.tar
M+V9I;&4P,0``````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P
M(#$Q,34P-C<T-C0R(#`Q,#,S-@`@,```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````O+BXO9FEL93`R````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P
M,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$P-34R`"`P````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````'5S=&%R`#`P````````````````````````````````````````````
M`````````````````````````````````````````#`P,#`P,"``,#`P,#`P
M(```````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````"\N+B\N+B]F:6QE
M,#,`````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T
M,B`P,3`W-C8`(#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#``````````````````````
M````````````````````````````````````````````````````````````
M````,#`P,#`P(``P,#`P,#`@````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````8SHO9FEL93`T````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P
M,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,#4W-@`@,```````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<@`P
M,```````````````````````````````````````````````````````````
M```````````````````````````P,#`P,#`@`#`P,#`P,"``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````!$.BXN+V9I;&4P-0``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````,#`P-C0T(``P,#$W
M-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$P-C<T`"`P
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````'5S=&%R`#`P````````````````````````````````````
M`````````````````````````````````````````````````#`P,#`P,"``
M,#`P,#`P(```````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````&,Z+BXO
M+BXO9FEL93`V````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U
M,#8W-#8T,B`P,3$Q-#<`(#``````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````=7-T87(`,#``````````````
M````````````````````````````````````````````````````````````
M````````````,#`P,#`P(``P,#`P,#`@````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````0SHO+BXO9FEL93`W````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@
M`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,#<U-``@,```````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````````````!U
M<W1A<@`P,```````````````````````````````````````````````````
M```````````````````````````````````P,#`P,#`@`#`P,#`P,"``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````!A.B\N+B\N+B]F:6QE,#@`
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````,#`P-C0T
M(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q
M,C(V`"`P````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````'5S=&%R`#`P````````````````````````````
M`````````````````````````````````````````````````````````#`P
M,#`P,"``,#`P,#`P(```````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`"\O+B]C.B]F:6QE,#D`````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P
M,"`Q,3$U,#8W-#8T,B`P,3$P-S8`(#``````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````=7-T87(`,#``````
M````````````````````````````````````````````````````````````
M````````````````````,#`P,#`P(``P,#`P,#`@````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````+R\N+T,Z+RXN+V9I;&4Q,```````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P
M,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,3(T,0`@,```````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````!U<W1A<@`P,```````````````````````````````````````````
M```````````````````````````````````````````P,#`P,#`@`#`P,#`P
M,"``````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````````O+S\O8SHO9FEL
M93$Q````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V
M-#(@,#$Q,3$P`"`P````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````'5S=&%R`#`P````````````````````
M````````````````````````````````````````````````````````````
M`````#`P,#`P,"``,#`P,#`P(```````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````"\O/R]#.B\N+B]F:6QE,3(`````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P
M,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$R-C0`(#``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````=7-T87(`
M,#``````````````````````````````````````````````````````````
M````````````````````````````,#`P,#`P(``P,#`P,#`@````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````+R\O+V,Z+V9I;&4Q,P``````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````#`P,#8T-"``,#`Q
M-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,3`W,@`@
M,```````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````!U<W1A<@`P,```````````````````````````````````
M```````````````````````````````````````````````````P,#`P,#`@
M`#`P,#`P,"``````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````O+R\O
M0SHO+R\O+V9I;&4Q-```````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q
M-3`V-S0V-#(@,#$Q,S(W`"`P````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````'5S=&%R`#`P````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`P,"``,#`P,#`P(```````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````"\O/R]53D,O<V5R=F5R+W-H87)E+V9I;&4Q-0``````
M````````````````````````````````````````````````````````````
M```````````````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q
M(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3,V,S4`(#``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M=7-T87(`,#``````````````````````````````````````````````````
M````````````````````````````````````,#`P,#`P(``P,#`P,#`@````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````+R\_+U5.0R]F:6QE,38`
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````#`P,#8T
M-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q
M,3(R-@`@,```````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````!U<W1A<@`P,```````````````````````````
M```````````````````````````````````````````````````````````P
M,#`P,#`@`#`P,#`P,"``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```O+S\O54Y#+RXN+V9I;&4Q-P``````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P
M,#`@,3$Q-3`V-S0V-#(@,#$Q-#0R`"`P````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````'5S=&%R`#`P````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#`P,"``,#`P,#`P(```````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````"\O/R]U;F,O<V5R=F5R+W-H87)E+V9I;&4Q
M.```````````````````````````````````````````````````````````
M```````````````````````````````````````P,#`V-#0@`#`P,3<U,2``
M,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,30P,#``(#``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````=7-T87(`,#``````````````````````````````````````````
M````````````````````````````````````````````,#`P,#`P(``P,#`P
M,#`@````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````+R\_+W5N8R]F
M:6QE,3D`````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T
M-C0R(#`Q,3,W,0`@,```````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````!U<W1A<@`P,```````````````````
M````````````````````````````````````````````````````````````
M```````P,#`P,#`@`#`P,#`P,"``````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````O+S\O=6YC+RXN+V9I;&4R,```````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P
M,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q-3<T`"`P````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````'5S=&%R
M`#`P````````````````````````````````````````````````````````
M`````````````````````````````#`P,#`P,"``,#`P,#`P(```````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````%QF:6QE,C$`````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````````P,#`V-#0@`#`P
M,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3`T,34`
M(#``````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````=7-T87(`,#``````````````````````````````````
M````````````````````````````````````````````````````,#`P,#`P
M(``P,#`P,#`@````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````7"XN
M7&9I;&4R,@``````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q
M,34P-C<T-C0R(#`Q,#<P-@`@,```````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````!U<W1A<@`P,```````````
M````````````````````````````````````````````````````````````
M```````````````P,#`P,#`@`#`P,#`P,"``````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````!<+BY<+BY<9FEL93(S````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U
M,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,3<W`"`P````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`'5S=&%R`#`P````````````````````````````````````````````````
M`````````````````````````````````````#`P,#`P,"``,#`P,#`P(```
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````$,Z7&9I;&4R-```````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````P,#`V
M-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P
M,3`V,34`(#``````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````=7-T87(`,#``````````````````````````
M````````````````````````````````````````````````````````````
M,#`P,#`P(``P,#`P,#`@````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````>CHN+EQF:6QE,C4`````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P
M,#`P(#$Q,34P-C<T-C0R(#`Q,3`T,0`@,```````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````!U<W1A<@`P,```
M````````````````````````````````````````````````````````````
M```````````````````````P,#`P,#`@`#`P,#`P,"``````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````!C.BXN7"XN7&9I;&4R-@``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````,#`P-C0T(``P,#$W-3$@
M`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,S`S`"`P````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````'5S=&%R`#`P````````````````````````````````````````
M`````````````````````````````````````````````#`P,#`P,"``,#`P
M,#`P(```````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````%HZ7"XN7&9I
M;&4R-P``````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W
M-#8T,B`P,3$Q,S<`(#``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````=7-T87(`,#``````````````````
M````````````````````````````````````````````````````````````
M````````,#`P,#`P(``P,#`P,#`@````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````0SI<+BY<+BY<9FEL93(X````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P
M,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,30P,0`@,```````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````````!U<W1A
M<@`P,```````````````````````````````````````````````````````
M```````````````````````````````P,#`P,#`@`#`P,#`P,"``````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````!<7"Y<8SI<9FEL93(Y````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````,#`P-C0T(``P
M,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,S8T
M`"`P````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````'5S=&%R`#`P````````````````````````````````
M`````````````````````````````````````````````````````#`P,#`P
M,"``,#`P,#`P(```````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````%Q<
M+EQ#.EPN+EQF:6QE,S``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q
M,3$U,#8W-#8T,B`P,3$V,#0`(#``````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````=7-T87(`,#``````````
M````````````````````````````````````````````````````````````
M````````````````,#`P,#`P(``P,#`P,#`@````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````7%P_7&,Z7&9I;&4S,0``````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W
M-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,3,W-@`@,```````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``!U<W1A<@`P,```````````````````````````````````````````````
M```````````````````````````````````````P,#`P,#`@`#`P,#`P,"``
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!<7#]<1#I<+BY<9FEL
M93,R````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````,#`P
M-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@
M,#$Q-C,P`"`P````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````'5S=&%R`#`P````````````````````````
M````````````````````````````````````````````````````````````
M`#`P,#`P,"``,#`P,#`P(```````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````%Q<7%QC.EQF:6QE,S,`````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P
M,#`P,"`Q,3$U,#8W-#8T,B`P,3$T,S4`(#``````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````=7-T87(`,#``
M````````````````````````````````````````````````````````````
M````````````````````````,#`P,#`P(``P,#`P,#`@````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````7%Q<7$,Z7%Q<7%QF:6QE,S0`````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````#`P,#8T-"``,#`Q-S4Q
M(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,C$U-@`@,```
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````!U<W1A<@`P,```````````````````````````````````````
M```````````````````````````````````````````````P,#`P,#`@`#`P
M,#`P,"``````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!<7#]<54Y#
M7'-E<G9E<EQS:&%R95QF:6QE,S4`````````````````````````````````
M````````````````````````````````````````````````````````````
M````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V
M-S0V-#(@,#$T,C4U`"`P````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````'5S=&%R`#`P````````````````
M````````````````````````````````````````````````````````````
M`````````#`P,#`P,"``,#`P,#`P(```````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````%Q</UQ53D-<9FEL93,V````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P
M,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$U,30`(#``````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````=7-T
M87(`,#``````````````````````````````````````````````````````
M````````````````````````````````,#`P,#`P(``P,#`P,#`@````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````7%P_7%5.0UPN+EQF:6QE,S<`
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````#`P,#8T-"``
M,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,C`P
M-0`@,```````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````!U<W1A<@`P,```````````````````````````````
M```````````````````````````````````````````````````````P,#`P
M,#`@`#`P,#`P,"``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````````````!<
M7#]<=6YC7'-E<G9E<EQS:&%R95QF:6QE,S@`````````````````````````
M````````````````````````````````````````````````````````````
M````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@
M,3$Q-3`V-S0V-#(@,#$T-#(P`"`P````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````'5S=&%R`#`P````````
M````````````````````````````````````````````````````````````
M`````````````````#`P,#`P,"``,#`P,#`P(```````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````%Q</UQU;F-<9FEL93,Y````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q
M-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$V-3<`(#``````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````=7-T87(`,#``````````````````````````````````````````````
M````````````````````````````````````````,#`P,#`P(``P,#`P,#`@
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````7%P_7'5N8UPN+EQF
M:6QE-#``````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````#`P
M,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R
M(#`Q,C$S-P`@,```````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````!U<W1A<@`P,```````````````````````
M````````````````````````````````````````````````````````````
M```P,#`P,#`@`#`P,#`P,"``````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````!<+BXO9FEL930Q````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P
M,#`P,#`@,3$Q-3`V-S0V-#(@,#$P-C,R`"`P````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````'5S=&%R`#`P
M````````````````````````````````````````````````````````````
M`````````````````````````#`P,#`P,"``,#`P,#`P(```````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````%PN+B\N+EQF:6QE-#(`````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````P,#`V-#0@`#`P,3<U
M,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$Q,C,`(#``
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````=7-T87(`,#``````````````````````````````````````
M````````````````````````````````````````````````,#`P,#`P(``P
M,#`P,#`@````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````8SHN+B\N
M+EQF:6QE-#,`````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P
M-C<T-C0R(#`Q,3(R-0`@,```````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````!U<W1A<@`P,```````````````
M````````````````````````````````````````````````````````````
M```````````P,#`P,#`@`#`P,#`P,"``````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````!#.B\N+EQF:6QE-#0`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``
M,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,#,R`"`P````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````'5S
M=&%R`#`P````````````````````````````````````````````````````
M`````````````````````````````````#`P,#`P,"``,#`P,#`P(```````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````$0Z7"XN+RXN7&9I;&4T-0``
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````````````P,#`V-#0@
M`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$S
M,C0`(#``````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````=7-T87(`,#``````````````````````````````
M````````````````````````````````````````````````````````,#`P
M,#`P(``P,#`P,#`@````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M7"\N+V,Z7&9I;&4T-@``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P
M(#$Q,34P-C<T-C0R(#`Q,3(S,0`@,```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````!<7"XO0SI<+BY<9FEL930W````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P
M,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q-3,W`"`P````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````'5S=&%R`#`P````````````````````````````````````````````
M`````````````````````````````````````````#`P,#`P,"``,#`P,#`P
M(```````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````%PO/UQC.B]F:6QE
M-#@`````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T
M,B`P,3$R-30`(#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#``````````````````````
M````````````````````````````````````````````````````````````
M````,#`P,#`P(``P,#`P,#`@````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````7%P_+T0Z+RXN7&9I;&4T.0``````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P
M,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,34P-@`@,```````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<@`P
M,```````````````````````````````````````````````````````````
M```````````````````````````P,#`P,#`@`#`P,#`P,"``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````!<+R]<1#I<9FEL934P````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````,#`P-C0T(``P,#$W
M-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,C0S`"`P
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````'5S=&%R`#`P````````````````````````````````````
M`````````````````````````````````````````````````#`P,#`P,"``
M,#`P,#`P(```````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````%Q<+R]C
M.EPO+UQ<9FEL934Q````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U
M,#8W-#8T,B`P,3$W,S$`(#``````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````=7-T87(`,#``````````````
M````````````````````````````````````````````````````````````
M````````````,#`P,#`P(``P,#`P,#`@````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````7"\_+W5.8R]S97)V97)<<VAA<F5<9FEL934R````````
M````````````````````````````````````````````````````````````
M`````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@
M`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q-#$T-0`@,```````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````````````!U
M<W1A<@`P,```````````````````````````````````````````````````
M```````````````````````````````````P,#`P,#`@`#`P,#`P,"``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````!<7#\O54YC7&9I;&4U,P``
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````,#`P-C0T
M(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q
M-#<V`"`P````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````'5S=&%R`#`P````````````````````````````
M`````````````````````````````````````````````````````````#`P
M,#`P,"``,#`P,#`P(```````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`%PO/UQ5;D-<+BXO9FEL934T````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P
M,"`Q,3$U,#8W-#8T,B`P,3$W,3(`(#``````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````=7-T87(`,#``````
M````````````````````````````````````````````````````````````
M````````````````````,#`P,#`P(``P,#`P,#`@````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
'````````````
`
end

View file

@ -0,0 +1,125 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_stdio.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
DEFINE_TEST(test_stdio)
{
FILE *filelist;
char *p;
size_t s;
int r;
assertUmask(0);
/*
* Create a couple of files on disk.
*/
/* File */
assertMakeFile("f", 0755, "abc");
/* Link to above file. */
assertMakeHardlink("l", "f");
/* Create file list (text mode here) */
filelist = fopen("filelist", "w");
assert(filelist != NULL);
fprintf(filelist, "f\n");
fprintf(filelist, "l\n");
fclose(filelist);
/*
* Archive/dearchive with a variety of options, verifying
* stdio paths.
*/
/* 'cf' should generate no output unless there's an error. */
r = systemf("%s cf archive f l >cf.out 2>cf.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("cf.out");
assertEmptyFile("cf.err");
/* 'cvf' should generate file list on stderr, empty stdout. */
r = systemf("%s cvf archive f l >cvf.out 2>cvf.err", testprog);
assertEqualInt(r, 0);
failure("'cv' writes filenames to stderr, nothing to stdout (SUSv2)\n"
"Note that GNU tar writes the file list to stdout by default.");
assertEmptyFile("cvf.out");
/* TODO: Verify cvf.err has file list in SUSv2-prescribed format. */
/* 'cvf -' should generate file list on stderr, archive on stdout. */
r = systemf("%s cvf - f l >cvf-.out 2>cvf-.err", testprog);
assertEqualInt(r, 0);
failure("cvf - should write archive to stdout");
/* TODO: Verify cvf-.out has archive. */
failure("cvf - should write file list to stderr (SUSv2)");
/* TODO: Verify cvf-.err has verbose file list. */
/* 'tf' should generate file list on stdout, empty stderr. */
r = systemf("%s tf archive >tf.out 2>tf.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("tf.err");
failure("'t' mode should write results to stdout");
/* TODO: Verify tf.out has file list. */
/* 'tvf' should generate file list on stdout, empty stderr. */
r = systemf("%s tvf archive >tvf.out 2>tvf.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("tvf.err");
failure("'tv' mode should write results to stdout");
/* TODO: Verify tvf.out has file list. */
/* 'tvf -' uses stdin, file list on stdout, empty stderr. */
r = systemf("%s tvf - < archive >tvf-.out 2>tvf-.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("tvf-.err");
/* TODO: Verify tvf-.out has file list. */
/* Basic 'xf' should generate no output on stdout or stderr. */
r = systemf("%s xf archive >xf.out 2>xf.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("xf.err");
assertEmptyFile("xf.out");
/* 'xvf' should generate list on stderr, empty stdout. */
r = systemf("%s xvf archive >xvf.out 2>xvf.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("xvf.out");
/* TODO: Verify xvf.err */
/* 'xvOf' should generate list on stderr, file contents on stdout. */
r = systemf("%s xvOf archive >xvOf.out 2>xvOf.err", testprog);
assertEqualInt(r, 0);
/* Verify xvOf.out is the file contents */
p = slurpfile(&s, "xvOf.out");
assert(s = 3);
assertEqualMem(p, "abc", 3);
/* TODO: Verify xvf.err */
/* 'xvf -' should generate list on stderr, empty stdout. */
r = systemf("%s xvf - < archive >xvf-.out 2>xvf-.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("xvf-.out");
/* TODO: Verify xvf-.err */
}

View file

@ -0,0 +1,109 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_strip_components.c,v 1.2 2008/11/10 05:24:13 kientzle Exp $");
static int
touch(const char *fn)
{
FILE *f = fopen(fn, "w");
failure("Couldn't create file '%s', errno=%d (%s)\n",
fn, errno, strerror(errno));
if (!assert(f != NULL))
return (0); /* Failure. */
fclose(f);
return (1); /* Success */
}
DEFINE_TEST(test_strip_components)
{
assertMakeDir("d0", 0755);
assertChdir("d0");
assertMakeDir("d1", 0755);
assertMakeDir("d1/d2", 0755);
assertMakeDir("d1/d2/d3", 0755);
assertEqualInt(1, touch("d1/d2/f1"));
assertMakeHardlink("l1", "d1/d2/f1");
assertMakeHardlink("d1/l2", "d1/d2/f1");
if (canSymlink()) {
assertMakeSymlink("s1", "d1/d2/f1");
assertMakeSymlink("d1/s2", "d2/f1");
}
assertChdir("..");
assertEqualInt(0, systemf("%s -cf test.tar d0", testprog));
assertMakeDir("target", 0755);
assertEqualInt(0, systemf("%s -x -C target --strip-components 2 "
"-f test.tar", testprog));
failure("d0/ is too short and should not get restored");
assertFileNotExists("target/d0");
failure("d0/d1/ is too short and should not get restored");
assertFileNotExists("target/d1");
failure("d0/d1/s2 is a symlink to something that won't be extracted");
/* If platform supports symlinks, target/s2 is a broken symlink. */
/* If platform does not support symlink, target/s2 doesn't exist. */
assertFileNotExists("target/s2");
if (canSymlink())
assertIsSymlink("target/s2", "d2/f1");
failure("d0/d1/d2 should be extracted");
assertIsDir("target/d2", -1);
/*
* This next is a complicated case. d0/l1, d0/d1/l2, and
* d0/d1/d2/f1 are all hardlinks to the same file; d0/l1 can't
* be extracted with --strip-components=2 and the other two
* can. Remember that tar normally stores the first file with
* a body and the other as hardlink entries to the first
* appearance. So the final result depends on the order in
* which these three names get archived. If d0/l1 is first,
* none of the three can be restored. If either of the longer
* names are first, then the two longer ones can both be
* restored.
*
* The tree-walking code used by bsdtar always visits files
* before subdirectories, so bsdtar's behavior is fortunately
* deterministic: d0/l1 will always get stored first and the
* other two will be stored as hardlinks to d0/l1. Since
* d0/l1 can't be extracted, none of these three will be
* extracted.
*
* It may be worth extending this test to force a particular
* archiving order so as to exercise both of the cases described
* above.
*
* Of course, this is all totally different for cpio and newc
* formats because the hardlink management is different.
* TODO: Rename this to test_strip_components_tar and create
* parallel tests for cpio and newc formats.
*/
failure("d0/l1 is too short and should not get restored");
assertFileNotExists("target/l1");
failure("d0/d1/l2 is a hardlink to file whose name was too short");
assertFileNotExists("target/l2");
failure("d0/d1/d2/f1 is a hardlink to file whose name was too short");
assertFileNotExists("target/d2/f1");
}

View file

@ -0,0 +1,160 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_symlink_dir.c,v 1.1 2008/09/14 02:16:04 kientzle Exp $");
/*
* tar -x -P should follow existing symlinks for dirs, but not other
* content. Plain tar -x should remove symlinks when they're in the
* way of a dir extraction.
*/
static int
mkfile(const char *name, int mode, const char *contents, size_t size)
{
FILE *f = fopen(name, "wb");
size_t written;
(void)mode; /* UNUSED */
if (f == NULL)
return (-1);
written = fwrite(contents, 1, size, f);
fclose(f);
if (size != written)
return (-1);
return (0);
}
DEFINE_TEST(test_symlink_dir)
{
assertUmask(0);
assertMakeDir("source", 0755);
assertEqualInt(0, mkfile("source/file", 0755, "a", 1));
assertEqualInt(0, mkfile("source/file2", 0755, "ab", 2));
assertMakeDir("source/dir", 0755);
assertMakeDir("source/dir/d", 0755);
assertEqualInt(0, mkfile("source/dir/f", 0755, "abc", 3));
assertMakeDir("source/dir2", 0755);
assertMakeDir("source/dir2/d2", 0755);
assertEqualInt(0, mkfile("source/dir2/f2", 0755, "abcd", 4));
assertMakeDir("source/dir3", 0755);
assertMakeDir("source/dir3/d3", 0755);
assertEqualInt(0, mkfile("source/dir3/f3", 0755, "abcde", 5));
assertEqualInt(0,
systemf("%s -cf test.tar -C source dir dir2 dir3 file file2",
testprog));
/*
* Extract with -x and without -P.
*/
assertMakeDir("dest1", 0755);
/* "dir" is a symlink to an existing "dest1/real_dir" */
assertMakeDir("dest1/real_dir", 0755);
if (canSymlink()) {
assertMakeSymlink("dest1/dir", "real_dir");
/* "dir2" is a symlink to a non-existing "real_dir2" */
assertMakeSymlink("dest1/dir2", "real_dir2");
} else {
skipping("some symlink checks");
}
/* "dir3" is a symlink to an existing "non_dir3" */
assertEqualInt(0, mkfile("dest1/non_dir3", 0755, "abcdef", 6));
if (canSymlink())
assertMakeSymlink("dest1/dir3", "non_dir3");
/* "file" is a symlink to existing "real_file" */
assertEqualInt(0, mkfile("dest1/real_file", 0755, "abcdefg", 7));
if (canSymlink()) {
assertMakeSymlink("dest1/file", "real_file");
/* "file2" is a symlink to non-existing "real_file2" */
assertMakeSymlink("dest1/file2", "real_file2");
}
assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog));
/* dest1/dir symlink should be replaced */
failure("symlink to dir was followed when it shouldn't be");
assertIsDir("dest1/dir", -1);
/* dest1/dir2 symlink should be replaced */
failure("Broken symlink wasn't replaced with dir");
assertIsDir("dest1/dir2", -1);
/* dest1/dir3 symlink should be replaced */
failure("Symlink to non-dir wasn't replaced with dir");
assertIsDir("dest1/dir3", -1);
/* dest1/file symlink should be replaced */
failure("Symlink to existing file should be replaced");
assertIsReg("dest1/file", -1);
/* dest1/file2 symlink should be replaced */
failure("Symlink to non-existing file should be replaced");
assertIsReg("dest1/file2", -1);
/*
* Extract with both -x and -P
*/
assertMakeDir("dest2", 0755);
/* "dir" is a symlink to existing "real_dir" */
assertMakeDir("dest2/real_dir", 0755);
if (canSymlink())
assertMakeSymlink("dest2/dir", "real_dir");
/* "dir2" is a symlink to a non-existing "real_dir2" */
if (canSymlink())
assertMakeSymlink("dest2/dir2", "real_dir2");
/* "dir3" is a symlink to an existing "non_dir3" */
assertEqualInt(0, mkfile("dest2/non_dir3", 0755, "abcdefgh", 8));
if (canSymlink())
assertMakeSymlink("dest2/dir3", "non_dir3");
/* "file" is a symlink to existing "real_file" */
assertEqualInt(0, mkfile("dest2/real_file", 0755, "abcdefghi", 9));
if (canSymlink())
assertMakeSymlink("dest2/file", "real_file");
/* "file2" is a symlink to non-existing "real_file2" */
if (canSymlink())
assertMakeSymlink("dest2/file2", "real_file2");
assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog));
/* dest2/dir symlink should be followed */
if (canSymlink()) {
assertIsSymlink("dest2/dir", "real_dir");
assertIsDir("dest2/real_dir", -1);
}
/* Contents of 'dir' should be restored */
assertIsDir("dest2/dir/d", -1);
assertIsReg("dest2/dir/f", -1);
assertFileSize("dest2/dir/f", 3);
/* dest2/dir2 symlink should be removed */
failure("Broken symlink wasn't replaced with dir");
assertIsDir("dest2/dir2", -1);
/* dest2/dir3 symlink should be removed */
failure("Symlink to non-dir wasn't replaced with dir");
assertIsDir("dest2/dir3", -1);
/* dest2/file symlink should be removed;
* even -P shouldn't follow symlinks for files */
failure("Symlink to existing file should be removed");
assertIsReg("dest2/file", -1);
/* dest2/file2 symlink should be removed */
failure("Symlink to non-existing file should be removed");
assertIsReg("dest2/file2", -1);
}

View file

@ -0,0 +1,97 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_version.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
/*
* Test that --version option works and generates reasonable output.
*/
DEFINE_TEST(test_version)
{
int r;
char *p, *q;
size_t s;
r = systemf("%s --version >version.stdout 2>version.stderr", testprog);
if (r != 0)
r = systemf("%s -W version >version.stdout 2>version.stderr",
testprog);
failure("Unable to run either %s --version or %s -W version",
testprog, testprog);
if (!assert(r == 0))
return;
/* --version should generate nothing to stdout. */
assertEmptyFile("version.stderr");
/* Verify format of version message. */
q = p = slurpfile(&s, "version.stdout");
/* Version message should start with name of program, then space. */
assert(s > 6);
failure("Version must start with 'bsdtar': ``%s''", p);
if (!assertEqualMem(q, "bsdtar ", 7))
return;
q += 7; s -= 7;
/* Version number is a series of digits and periods. */
while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
++q;
--s;
}
/* Version number terminated by space. */
failure("No space after bsdtar version: ``%s''", p);
assert(s > 1);
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
failure("No space after bsdtar version: ``%s''", p);
assert(*q == ' ');
++q; --s;
/* Separator. */
failure("No `-' between bsdtar and libarchive versions: ``%s''", p);
assertEqualMem(q, "- ", 2);
q += 2; s -= 2;
/* libarchive name and version number */
failure("Not long enough for libarchive version: ``%s''", p);
assert(s > 11);
failure("Libarchive version must start with `libarchive': ``%s''", p);
assertEqualMem(q, "libarchive ", 11);
q += 11; s -= 11;
/* Version number is a series of digits and periods. */
while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
++q;
--s;
}
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
/* All terminated by end-of-line. */
assert(s >= 1);
/* Skip an optional CR character (e.g., Windows) */
failure("Version output must end with \\n or \\r\\n");
if (*q == '\r') { ++q; --s; }
assertEqualMem(q, "\n", 1);
free(p);
}

View file

@ -0,0 +1,323 @@
/*-
* Copyright (c) 2009 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
static void
mkfile(const char *name)
{
FILE *f;
f = fopen(name, "wb");
assert(f != NULL);
assertEqualInt(5, fwrite("01234", 1, 5, f));
fclose(f);
}
static void
mkfullpath(char **path1, char **path2, const char *tpath, int type)
{
char *fp1 = NULL, *fp2 = NULL, *p1 = NULL, *p2 = NULL;
size_t l;
/*
* Get full path name of "tpath"
*/
l = GetFullPathNameA(tpath, 0, NULL, NULL);
assert(0 != l);
fp1 = malloc(l);
assert(NULL != fp1);
fp2 = malloc(l*2);
assert(NULL != fp2);
l = GetFullPathNameA(tpath, l, fp1, NULL);
if ((type & 0x01) == 0) {
for (p1 = fp1; *p1 != '\0'; p1++)
if (*p1 == '\\')
*p1 = '/';
}
switch(type) {
case 0: /* start with "/" */
case 1: /* start with "\" */
/* strip "c:" */
memmove(fp1, fp1 + 2, l - 2);
fp1[l -2] = '\0';
p1 = fp1 + 1;
break;
case 2: /* start with "c:/" */
case 3: /* start with "c:\" */
p1 = fp1 + 3;
break;
case 4: /* start with "//./c:/" */
case 5: /* start with "\\.\c:\" */
case 6: /* start with "//?/c:/" */
case 7: /* start with "\\?\c:\" */
p1 = malloc(l + 4 + 1);
assert(NULL != p1);
if (type & 0x1)
memcpy(p1, "\\\\.\\", 4);
else
memcpy(p1, "//./", 4);
if (type == 6 || type == 7)
p1[2] = '?';
memcpy(p1 + 4, fp1, l);
p1[l + 4] = '\0';
free(fp1);
fp1 = p1;
p1 = fp1 + 7;
break;
}
/*
* Strip leading drive names and converting "\" to "\\"
*/
p2 = fp2;
while (*p1 != '\0') {
if (*p1 == '\\')
*p2 = '/';
else
*p2 = *p1;
++p1;
++p2;
}
*p2++ = '\r';
*p2++ = '\n';
*p2 = '\0';
*path1 = fp1;
*path2 = fp2;
}
static const char *list1[] = {"aaa/", "aaa/file1", "aaa/xxa/", "aaa/xxb/",
"aaa/zzc/", "aaa/zzc/file1", "aaa/xxb/file1", "aaa/xxa/file1",
"aab/", "aac/", "abb/", "abc/", "abd/", NULL};
static const char *list2[] = {"bbb/", "bbb/file1", "bbb/xxa/", "bbb/xxb/",
"bbb/zzc/", "bbb/zzc/file1", "bbb/xxb/file1", "bbb/xxa/file1", "bbc/",
"bbd/", "bcc/", "bcd/", "bce/", NULL};
static const char *list3[] = {"aac/", "abc/", "bbc/", "bcc/", "ccc/", NULL};
static const char *list4[] = {"fff/abca", "fff/acca", NULL};
static const char *list5[] = {"aaa/file1", "aaa/xxa/", "aaa/xxa/file1",
"aaa/xxb/", "aaa/xxb/file1", "aaa/zzc/", "aaa/zzc/file1", NULL};
static const char *list6[] = {"fff/abca", "fff/acca", "aaa/xxa/",
"aaa/xxa/file1", "aaa/xxb/", "aaa/xxb/file1", NULL};
#endif /* _WIN32 && !__CYGWIN__ */
DEFINE_TEST(test_windows)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
char *fp1, *fp2;
/*
* Preparre tests.
* Create directories and files.
*/
assertMakeDir("tmp", 0775);
assertChdir("tmp");
assertMakeDir("aaa", 0775);
assertMakeDir("aaa/xxa", 0775);
assertMakeDir("aaa/xxb", 0775);
assertMakeDir("aaa/zzc", 0775);
mkfile("aaa/file1");
mkfile("aaa/xxa/file1");
mkfile("aaa/xxb/file1");
mkfile("aaa/zzc/file1");
assertMakeDir("aab", 0775);
assertMakeDir("aac", 0775);
assertMakeDir("abb", 0775);
assertMakeDir("abc", 0775);
assertMakeDir("abd", 0775);
assertMakeDir("bbb", 0775);
assertMakeDir("bbb/xxa", 0775);
assertMakeDir("bbb/xxb", 0775);
assertMakeDir("bbb/zzc", 0775);
mkfile("bbb/file1");
mkfile("bbb/xxa/file1");
mkfile("bbb/xxb/file1");
mkfile("bbb/zzc/file1");
assertMakeDir("bbc", 0775);
assertMakeDir("bbd", 0775);
assertMakeDir("bcc", 0775);
assertMakeDir("bcd", 0775);
assertEqualInt(0, _mkdir("bce"));
assertEqualInt(0, _mkdir("ccc"));
assertEqualInt(0, _mkdir("fff"));
mkfile("fff/aaaa");
mkfile("fff/abba");
mkfile("fff/abca");
mkfile("fff/acba");
mkfile("fff/acca");
/*
* Test1: Command line pattern matching.
*/
assertEqualInt(0,
systemf("%s -cf ../archive1.tar a*", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive1.tar > ../list1", testprog));
assertFileContainsLinesAnyOrder("../list1", list1);
assertEqualInt(0,
systemf("%s -cf ../archive2.tar b*", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive2.tar > ../list2", testprog));
assertFileContainsLinesAnyOrder("../list2", list2);
assertEqualInt(0,
systemf("%s -cf ../archive3.tar ??c", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive3.tar > ../list3", testprog));
assertFileContainsLinesAnyOrder("../list3", list3);
assertEqualInt(0,
systemf("%s -cf ../archive3b.tar *c", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive3b.tar > ../list3b", testprog));
assertFileContainsLinesAnyOrder("../list3b", list3);
assertEqualInt(0,
systemf("%s -cf ../archive4.tar fff/a?ca", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive4.tar > ../list4", testprog));
assertFileContainsLinesAnyOrder("../list4", list4);
assertEqualInt(0,
systemf("%s -cf ../archive5.tar aaa\\*", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive5.tar > ../list5", testprog));
assertFileContainsLinesAnyOrder("../list5", list5);
assertEqualInt(0,
systemf("%s -cf ../archive6.tar fff\\a?ca aaa\\xx*", testprog));
assertEqualInt(0,
systemf("%s -tf ../archive6.tar > ../list6", testprog));
assertFileContainsLinesAnyOrder("../list6", list6);
/*
* Test2: Archive the file start with drive letters.
*/
/* Test2a: start with "/" */
mkfullpath(&fp1, &fp2, "aaa/file1", 0);
assertEqualInt(0,
systemf("%s -cf ../archive10.tar %s > ../out10 2> ../err10",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive10.tar > ../list10", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list10");
free(fp1);
free(fp2);
/* Test2b: start with "\" */
mkfullpath(&fp1, &fp2, "aaa/file1", 1);
assertEqualInt(0,
systemf("%s -cf ../archive11.tar %s > ../out11 2> ../err11",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive11.tar > ../list11", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list11");
free(fp1);
free(fp2);
/* Test2c: start with "c:/" */
mkfullpath(&fp1, &fp2, "aaa/file1", 2);
assertEqualInt(0,
systemf("%s -cf ../archive12.tar %s > ../out12 2> ../err12",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive12.tar > ../list12", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list12");
free(fp1);
free(fp2);
/* Test2d: start with "c:\" */
mkfullpath(&fp1, &fp2, "aaa/file1", 3);
assertEqualInt(0,
systemf("%s -cf ../archive13.tar %s > ../out13 2> ../err13",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive13.tar > ../list13", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list13");
free(fp1);
free(fp2);
/* Test2e: start with "//./c:/" */
mkfullpath(&fp1, &fp2, "aaa/file1", 4);
assertEqualInt(0,
systemf("%s -cf ../archive14.tar %s > ../out14 2> ../err14",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive14.tar > ../list14", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list14");
free(fp1);
free(fp2);
/* Test2f: start with "\\.\c:\" */
mkfullpath(&fp1, &fp2, "aaa/file1", 5);
assertEqualInt(0,
systemf("%s -cf ../archive15.tar %s > ../out15 2> ../err15",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive15.tar > ../list15", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list15");
free(fp1);
free(fp2);
/* Test2g: start with "//?/c:/" */
mkfullpath(&fp1, &fp2, "aaa/file1", 6);
failure("fp1=%s, fp2=%s", fp1, fp2);
assertEqualInt(0,
systemf("%s -cf ../archive16.tar %s > ../out16 2> ../err16",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive16.tar > ../list16", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list16");
free(fp1);
free(fp2);
/* Test2h: start with "\\?\c:\" */
mkfullpath(&fp1, &fp2, "aaa/file1", 7);
failure("fp1=%s, fp2=%s", fp1, fp2);
assertEqualInt(0,
systemf("%s -cf ../archive17.tar %s > ../out17 2> ../err17",
testprog, fp1));
assertEqualInt(0,
systemf("%s -tf ../archive17.tar > ../list17", testprog));
/* Check drive letters have been stripped. */
assertFileContents(fp2, strlen(fp2), "../list17");
free(fp1);
free(fp2);
#else
skipping("Windows specific test");
#endif /* _WIN32 && !__CYGWIN__ */
}

821
commands/bsdtar/tree.c Normal file
View file

@ -0,0 +1,821 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* This is a new directory-walking system that addresses a number
* of problems I've had with fts(3). In particular, it has no
* pathname-length limits (other than the size of 'int'), handles
* deep logical traversals, uses considerably less memory, and has
* an opaque interface (easier to modify in the future).
*
* Internally, it keeps a single list of "tree_entry" items that
* represent filesystem objects that require further attention.
* Non-directories are not kept in memory: they are pulled from
* readdir(), returned to the client, then freed as soon as possible.
* Any directory entry to be traversed gets pushed onto the stack.
*
* There is surprisingly little information that needs to be kept for
* each item on the stack. Just the name, depth (represented here as the
* string length of the parent directory's pathname), and some markers
* indicating how to get back to the parent (via chdir("..") for a
* regular dir or via fchdir(2) for a symlink).
*/
#include "bsdtar_platform.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/tree.c,v 1.9 2008/11/27 05:49:52 kientzle Exp $");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if defined(HAVE_WINDOWS_H) && !defined(__CYGWIN__)
#include <windows.h>
#endif
#include "tree.h"
/*
* TODO:
* 1) Loop checking.
* 3) Arbitrary logical traversals by closing/reopening intermediate fds.
*/
struct tree_entry {
int depth;
struct tree_entry *next;
struct tree_entry *parent;
char *name;
size_t dirname_length;
dev_t dev;
ino_t ino;
int flags;
/* How to return back to the parent of a symlink. */
#ifdef HAVE_FCHDIR
int symlink_parent_fd;
#elif defined(_WIN32) && !defined(__CYGWIN__)
char *symlink_parent_path;
#else
#error fchdir function required.
#endif
};
/* Definitions for tree_entry.flags bitmap. */
#define isDir 1 /* This entry is a regular directory. */
#define isDirLink 2 /* This entry is a symbolic link to a directory. */
#define needsFirstVisit 4 /* This is an initial entry. */
#define needsDescent 8 /* This entry needs to be previsited. */
#define needsOpen 16 /* This is a directory that needs to be opened. */
#define needsAscent 32 /* This entry needs to be postvisited. */
/*
* On Windows, "first visit" is handled as a pattern to be handed to
* _findfirst(). This is consistent with Windows conventions that
* file patterns are handled within the application. On Posix,
* "first visit" is just returned to the client.
*/
/*
* Local data for this package.
*/
struct tree {
struct tree_entry *stack;
struct tree_entry *current;
#if defined(HAVE_WINDOWS_H) && !defined(__CYGWIN__)
HANDLE d;
BY_HANDLE_FILE_INFORMATION fileInfo;
#define INVALID_DIR_HANDLE INVALID_HANDLE_VALUE
WIN32_FIND_DATA _findData;
WIN32_FIND_DATA *findData;
#else
DIR *d;
#define INVALID_DIR_HANDLE NULL
struct dirent *de;
#endif
int flags;
int visit_type;
int tree_errno; /* Error code from last failed operation. */
/* Dynamically-sized buffer for holding path */
char *buff;
size_t buff_length;
const char *basename; /* Last path element */
size_t dirname_length; /* Leading dir length */
size_t path_length; /* Total path length */
int depth;
int openCount;
int maxOpenCount;
struct stat lst;
struct stat st;
};
/* Definitions for tree.flags bitmap. */
#define hasStat 16 /* The st entry is valid. */
#define hasLstat 32 /* The lst entry is valid. */
#define hasFileInfo 64 /* The Windows fileInfo entry is valid. */
#if defined(_WIN32) && !defined(__CYGWIN__)
static int
tree_dir_next_windows(struct tree *t, const char *pattern);
#else
static int
tree_dir_next_posix(struct tree *t);
#endif
#ifdef HAVE_DIRENT_D_NAMLEN
/* BSD extension; avoids need for a strlen() call. */
#define D_NAMELEN(dp) (dp)->d_namlen
#else
#define D_NAMELEN(dp) (strlen((dp)->d_name))
#endif
#include <stdio.h>
void
tree_dump(struct tree *t, FILE *out)
{
char buff[300];
struct tree_entry *te;
fprintf(out, "\tdepth: %d\n", t->depth);
fprintf(out, "\tbuff: %s\n", t->buff);
fprintf(out, "\tpwd: %s\n", getcwd(buff, sizeof(buff)));
fprintf(out, "\tbasename: %s\n", t->basename);
fprintf(out, "\tstack:\n");
for (te = t->stack; te != NULL; te = te->next) {
fprintf(out, "\t\t%s%d:\"%s\" %s%s%s%s%s%s\n",
t->current == te ? "*" : " ",
te->depth,
te->name,
te->flags & needsFirstVisit ? "V" : "",
te->flags & needsDescent ? "D" : "",
te->flags & needsOpen ? "O" : "",
te->flags & needsAscent ? "A" : "",
te->flags & isDirLink ? "L" : "",
(t->current == te && t->d) ? "+" : ""
);
}
}
/*
* Add a directory path to the current stack.
*/
static void
tree_push(struct tree *t, const char *path)
{
struct tree_entry *te;
te = malloc(sizeof(*te));
memset(te, 0, sizeof(*te));
te->next = t->stack;
te->parent = t->current;
if (te->parent)
te->depth = te->parent->depth + 1;
t->stack = te;
#ifdef HAVE_FCHDIR
te->symlink_parent_fd = -1;
te->name = strdup(path);
#elif defined(_WIN32) && !defined(__CYGWIN__)
te->symlink_parent_path = NULL;
te->name = strdup(path);
#endif
te->flags = needsDescent | needsOpen | needsAscent;
te->dirname_length = t->dirname_length;
}
/*
* Append a name to the current dir path.
*/
static void
tree_append(struct tree *t, const char *name, size_t name_length)
{
char *p;
size_t size_needed;
if (t->buff != NULL)
t->buff[t->dirname_length] = '\0';
/* Strip trailing '/' from name, unless entire name is "/". */
while (name_length > 1 && name[name_length - 1] == '/')
name_length--;
/* Resize pathname buffer as needed. */
size_needed = name_length + 1 + t->dirname_length;
if (t->buff_length < size_needed) {
if (t->buff_length < 1024)
t->buff_length = 1024;
while (t->buff_length < size_needed)
t->buff_length *= 2;
t->buff = realloc(t->buff, t->buff_length);
}
if (t->buff == NULL)
abort();
p = t->buff + t->dirname_length;
t->path_length = t->dirname_length + name_length;
/* Add a separating '/' if it's needed. */
if (t->dirname_length > 0 && p[-1] != '/') {
*p++ = '/';
t->path_length ++;
}
#if HAVE_STRNCPY_S
strncpy_s(p, t->buff_length - (p - t->buff), name, name_length);
#else
strncpy(p, name, name_length);
#endif
p[name_length] = '\0';
t->basename = p;
}
/*
* Open a directory tree for traversal.
*/
struct tree *
tree_open(const char *path)
{
#ifdef HAVE_FCHDIR
struct tree *t;
t = malloc(sizeof(*t));
memset(t, 0, sizeof(*t));
/* First item is set up a lot like a symlink traversal. */
tree_push(t, path);
t->stack->flags = needsFirstVisit | isDirLink | needsAscent;
t->stack->symlink_parent_fd = open(".", O_RDONLY);
t->openCount++;
t->d = INVALID_DIR_HANDLE;
return (t);
#elif defined(_WIN32) && !defined(__CYGWIN__)
struct tree *t;
char *cwd = _getcwd(NULL, 0);
char *pathname = strdup(path), *p, *base;
if (pathname == NULL)
abort();
for (p = pathname; *p != '\0'; ++p) {
if (*p == '\\')
*p = '/';
}
base = pathname;
t = malloc(sizeof(*t));
memset(t, 0, sizeof(*t));
/* First item is set up a lot like a symlink traversal. */
/* printf("Looking for wildcard in %s\n", path); */
/* TODO: wildcard detection here screws up on \\?\c:\ UNC names */
if (strchr(base, '*') || strchr(base, '?')) {
// It has a wildcard in it...
// Separate the last element.
p = strrchr(base, '/');
if (p != NULL) {
*p = '\0';
chdir(base);
tree_append(t, base, p - base);
t->dirname_length = t->path_length;
base = p + 1;
}
}
tree_push(t, base);
free(pathname);
t->stack->flags = needsFirstVisit | isDirLink | needsAscent;
t->stack->symlink_parent_path = cwd;
t->d = INVALID_DIR_HANDLE;
return (t);
#endif
}
/*
* We've finished a directory; ascend back to the parent.
*/
static int
tree_ascend(struct tree *t)
{
struct tree_entry *te;
int r = 0;
te = t->stack;
t->depth--;
if (te->flags & isDirLink) {
#ifdef HAVE_FCHDIR
if (fchdir(te->symlink_parent_fd) != 0) {
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
}
close(te->symlink_parent_fd);
#elif defined(_WIN32) && !defined(__CYGWIN__)
if (SetCurrentDirectory(te->symlink_parent_path) == 0) {
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
}
free(te->symlink_parent_path);
te->symlink_parent_path = NULL;
#endif
t->openCount--;
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
if (SetCurrentDirectory("..") == 0) {
#else
if (chdir("..") != 0) {
#endif
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
}
}
return (r);
}
/*
* Pop the working stack.
*/
static void
tree_pop(struct tree *t)
{
struct tree_entry *te;
if (t->buff)
t->buff[t->dirname_length] = '\0';
if (t->stack == t->current && t->current != NULL)
t->current = t->current->parent;
te = t->stack;
t->stack = te->next;
t->dirname_length = te->dirname_length;
if (t->buff) {
t->basename = t->buff + t->dirname_length;
while (t->basename[0] == '/')
t->basename++;
}
free(te->name);
free(te);
}
/*
* Get the next item in the tree traversal.
*/
int
tree_next(struct tree *t)
{
int r;
/* If we're called again after a fatal error, that's an API
* violation. Just crash now. */
if (t->visit_type == TREE_ERROR_FATAL) {
fprintf(stderr, "Unable to continue traversing"
" directory heirarchy after a fatal error.");
abort();
}
while (t->stack != NULL) {
/* If there's an open dir, get the next entry from there. */
if (t->d != INVALID_DIR_HANDLE) {
#if defined(_WIN32) && !defined(__CYGWIN__)
r = tree_dir_next_windows(t, NULL);
#else
r = tree_dir_next_posix(t);
#endif
if (r == 0)
continue;
return (r);
}
if (t->stack->flags & needsFirstVisit) {
#if defined(_WIN32) && !defined(__CYGWIN__)
char *d = t->stack->name;
t->stack->flags &= ~needsFirstVisit;
if (strchr(d, '*') || strchr(d, '?')) {
r = tree_dir_next_windows(t, d);
if (r == 0)
continue;
return (r);
}
// Not a pattern, handle it as-is...
#endif
/* Top stack item needs a regular visit. */
t->current = t->stack;
tree_append(t, t->stack->name, strlen(t->stack->name));
/* t->dirname_length = t->path_length; */
/* tree_pop(t); */
t->stack->flags &= ~needsFirstVisit;
return (t->visit_type = TREE_REGULAR);
} else if (t->stack->flags & needsDescent) {
/* Top stack item is dir to descend into. */
t->current = t->stack;
tree_append(t, t->stack->name, strlen(t->stack->name));
t->stack->flags &= ~needsDescent;
/* If it is a link, set up fd for the ascent. */
if (t->stack->flags & isDirLink) {
#ifdef HAVE_FCHDIR
t->stack->symlink_parent_fd = open(".", O_RDONLY);
t->openCount++;
if (t->openCount > t->maxOpenCount)
t->maxOpenCount = t->openCount;
#elif defined(_WIN32) && !defined(__CYGWIN__)
t->stack->symlink_parent_path = _getcwd(NULL, 0);
#endif
}
t->dirname_length = t->path_length;
#if defined(_WIN32) && !defined(__CYGWIN__)
if (t->path_length == 259 || !SetCurrentDirectory(t->stack->name) != 0)
#else
if (chdir(t->stack->name) != 0)
#endif
{
/* chdir() failed; return error */
tree_pop(t);
t->tree_errno = errno;
return (t->visit_type = TREE_ERROR_DIR);
}
t->depth++;
return (t->visit_type = TREE_POSTDESCENT);
} else if (t->stack->flags & needsOpen) {
t->stack->flags &= ~needsOpen;
#if defined(_WIN32) && !defined(__CYGWIN__)
r = tree_dir_next_windows(t, "*");
#else
r = tree_dir_next_posix(t);
#endif
if (r == 0)
continue;
return (r);
} else if (t->stack->flags & needsAscent) {
/* Top stack item is dir and we're done with it. */
r = tree_ascend(t);
tree_pop(t);
t->visit_type = r != 0 ? r : TREE_POSTASCENT;
return (t->visit_type);
} else {
/* Top item on stack is dead. */
tree_pop(t);
t->flags &= ~hasLstat;
t->flags &= ~hasStat;
}
}
return (t->visit_type = 0);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
static int
tree_dir_next_windows(struct tree *t, const char *pattern)
{
const char *name;
size_t namelen;
int r;
for (;;) {
if (pattern != NULL) {
t->d = FindFirstFile(pattern, &t->_findData);
if (t->d == INVALID_DIR_HANDLE) {
r = tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
t->tree_errno = errno;
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
return (t->visit_type);
}
t->findData = &t->_findData;
pattern = NULL;
} else if (!FindNextFile(t->d, &t->_findData)) {
FindClose(t->d);
t->d = INVALID_DIR_HANDLE;
t->findData = NULL;
return (0);
}
name = t->findData->cFileName;
namelen = strlen(name);
t->flags &= ~hasLstat;
t->flags &= ~hasStat;
if (name[0] == '.' && name[1] == '\0')
continue;
if (name[0] == '.' && name[1] == '.' && name[2] == '\0')
continue;
tree_append(t, name, namelen);
return (t->visit_type = TREE_REGULAR);
}
}
#else
static int
tree_dir_next_posix(struct tree *t)
{
int r;
const char *name;
size_t namelen;
if (t->d == NULL) {
if ((t->d = opendir(".")) == NULL) {
r = tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
t->tree_errno = errno;
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
return (t->visit_type);
}
}
for (;;) {
t->de = readdir(t->d);
if (t->de == NULL) {
closedir(t->d);
t->d = INVALID_DIR_HANDLE;
return (0);
}
name = t->de->d_name;
namelen = D_NAMELEN(t->de);
t->flags &= ~hasLstat;
t->flags &= ~hasStat;
if (name[0] == '.' && name[1] == '\0')
continue;
if (name[0] == '.' && name[1] == '.' && name[2] == '\0')
continue;
tree_append(t, name, namelen);
return (t->visit_type = TREE_REGULAR);
}
}
#endif
/*
* Return error code.
*/
int
tree_errno(struct tree *t)
{
return (t->tree_errno);
}
/*
* Called by the client to mark the directory just returned from
* tree_next() as needing to be visited.
*/
void
tree_descend(struct tree *t)
{
if (t->visit_type != TREE_REGULAR)
return;
if (tree_current_is_physical_dir(t)) {
tree_push(t, t->basename);
t->stack->flags |= isDir;
} else if (tree_current_is_dir(t)) {
tree_push(t, t->basename);
t->stack->flags |= isDirLink;
}
}
/*
* Get the stat() data for the entry just returned from tree_next().
*/
const struct stat *
tree_current_stat(struct tree *t)
{
if (!(t->flags & hasStat)) {
if (stat(tree_current_access_path(t), &t->st) != 0)
return NULL;
t->flags |= hasStat;
}
return (&t->st);
}
#if defined(HAVE_WINDOWS_H) && !defined(__CYGWIN__)
const BY_HANDLE_FILE_INFORMATION *
tree_current_file_information(struct tree *t)
{
if (!(t->flags & hasFileInfo)) {
HANDLE h = CreateFile(tree_current_access_path(t),
0, 0, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
if (h == INVALID_HANDLE_VALUE)
return NULL;
if (!GetFileInformationByHandle(h, &t->fileInfo)) {
CloseHandle(h);
return NULL;
}
CloseHandle(h);
t->flags |= hasFileInfo;
}
return (&t->fileInfo);
}
#endif
/*
* Get the lstat() data for the entry just returned from tree_next().
*/
const struct stat *
tree_current_lstat(struct tree *t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
return (tree_current_stat(t));
#else
if (!(t->flags & hasLstat)) {
if (lstat(tree_current_access_path(t), &t->lst) != 0)
return NULL;
t->flags |= hasLstat;
}
return (&t->lst);
#endif
}
/*
* Test whether current entry is a dir or link to a dir.
*/
int
tree_current_is_dir(struct tree *t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
if (t->findData)
return (t->findData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
if (tree_current_file_information(t))
return (t->fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
return (0);
#else
const struct stat *st;
/*
* If we already have lstat() info, then try some
* cheap tests to determine if this is a dir.
*/
if (t->flags & hasLstat) {
/* If lstat() says it's a dir, it must be a dir. */
if (S_ISDIR(tree_current_lstat(t)->st_mode))
return 1;
/* Not a dir; might be a link to a dir. */
/* If it's not a link, then it's not a link to a dir. */
if (!S_ISLNK(tree_current_lstat(t)->st_mode))
return 0;
/*
* It's a link, but we don't know what it's a link to,
* so we'll have to use stat().
*/
}
st = tree_current_stat(t);
/* If we can't stat it, it's not a dir. */
if (st == NULL)
return 0;
/* Use the definitive test. Hopefully this is cached. */
return (S_ISDIR(st->st_mode));
#endif
}
/*
* Test whether current entry is a physical directory. Usually, we
* already have at least one of stat() or lstat() in memory, so we
* use tricks to try to avoid an extra trip to the disk.
*/
int
tree_current_is_physical_dir(struct tree *t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
if (tree_current_is_physical_link(t))
return (0);
return (tree_current_is_dir(t));
#else
const struct stat *st;
/*
* If stat() says it isn't a dir, then it's not a dir.
* If stat() data is cached, this check is free, so do it first.
*/
if ((t->flags & hasStat)
&& (!S_ISDIR(tree_current_stat(t)->st_mode)))
return 0;
/*
* Either stat() said it was a dir (in which case, we have
* to determine whether it's really a link to a dir) or
* stat() info wasn't available. So we use lstat(), which
* hopefully is already cached.
*/
st = tree_current_lstat(t);
/* If we can't stat it, it's not a dir. */
if (st == NULL)
return 0;
/* Use the definitive test. Hopefully this is cached. */
return (S_ISDIR(st->st_mode));
#endif
}
/*
* Test whether current entry is a symbolic link.
*/
int
tree_current_is_physical_link(struct tree *t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
#ifndef IO_REPARSE_TAG_SYMLINK
/* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
#define IO_REPARSE_TAG_SYMLINK 0xA000000CL
#endif
if (t->findData)
return ((t->findData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
&& (t->findData->dwReserved0 == IO_REPARSE_TAG_SYMLINK));
return (0);
#else
const struct stat *st = tree_current_lstat(t);
if (st == NULL)
return 0;
return (S_ISLNK(st->st_mode));
#endif
}
/*
* Return the access path for the entry just returned from tree_next().
*/
const char *
tree_current_access_path(struct tree *t)
{
return (t->basename);
}
/*
* Return the full path for the entry just returned from tree_next().
*/
const char *
tree_current_path(struct tree *t)
{
return (t->buff);
}
/*
* Return the length of the path for the entry just returned from tree_next().
*/
size_t
tree_current_pathlen(struct tree *t)
{
return (t->path_length);
}
/*
* Return the nesting depth of the entry just returned from tree_next().
*/
int
tree_current_depth(struct tree *t)
{
return (t->depth);
}
/*
* Terminate the traversal and release any resources.
*/
void
tree_close(struct tree *t)
{
/* Release anything remaining in the stack. */
while (t->stack != NULL)
tree_pop(t);
free(t->buff);
/* TODO: Ensure that premature close() resets cwd */
#if 0
#ifdef HAVE_FCHDIR
if (t->initialDirFd >= 0) {
int s = fchdir(t->initialDirFd);
(void)s; /* UNUSED */
close(t->initialDirFd);
t->initialDirFd = -1;
}
#elif defined(_WIN32) && !defined(__CYGWIN__)
if (t->initialDir != NULL) {
SetCurrentDir(t->initialDir);
free(t->initialDir);
t->initialDir = NULL;
}
#endif
#endif
free(t);
}

141
commands/bsdtar/tree.h Normal file
View file

@ -0,0 +1,141 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/usr.bin/tar/tree.h,v 1.4 2008/11/27 05:49:52 kientzle Exp $
*/
/*-
* A set of routines for traversing directory trees.
* Similar in concept to the fts library, but with a few
* important differences:
* * Uses less memory. In particular, fts stores an entire directory
* in memory at a time. This package only keeps enough subdirectory
* information in memory to track the traversal. Information
* about non-directories is discarded as soon as possible.
* * Supports very deep logical traversals. The fts package
* uses "non-chdir" approach for logical traversals. This
* package does use a chdir approach for logical traversals
* and can therefore handle pathnames much longer than PATH_MAX.
* * Supports deep physical traversals "out of the box."
* Due to the memory optimizations above, there's no need to
* limit dir names to 32k.
*/
#include <sys/stat.h>
#include <stdio.h>
struct tree;
/* Initiate/terminate a tree traversal. */
struct tree *tree_open(const char * /* pathname */);
void tree_close(struct tree *);
/*
* tree_next() returns Zero if there is no next entry, non-zero if
* there is. Note that directories are visited three times.
* Directories are always visited first as part of enumerating their
* parent; that is a "regular" visit. If tree_descend() is invoked at
* that time, the directory is added to a work list and will
* subsequently be visited two more times: once just after descending
* into the directory ("postdescent") and again just after ascending
* back to the parent ("postascent").
*
* TREE_ERROR_DIR is returned if the descent failed (because the
* directory couldn't be opened, for instance). This is returned
* instead of TREE_POSTDESCENT/TREE_POSTASCENT. TREE_ERROR_DIR is not a
* fatal error, but it does imply that the relevant subtree won't be
* visited. TREE_ERROR_FATAL is returned for an error that left the
* traversal completely hosed. Right now, this is only returned for
* chdir() failures during ascent.
*/
#define TREE_REGULAR 1
#define TREE_POSTDESCENT 2
#define TREE_POSTASCENT 3
#define TREE_ERROR_DIR -1
#define TREE_ERROR_FATAL -2
int tree_next(struct tree *);
/* Errno value associated with the last traversal error. */
int tree_errno(struct tree *);
/*
* Request that current entry be visited. If you invoke it on every
* directory, you'll get a physical traversal. This is ignored if the
* current entry isn't a directory or a link to a directory. So, if
* you invoke this on every returned path, you'll get a full logical
* traversal.
*/
void tree_descend(struct tree *);
/*
* Return information about the current entry.
*/
/* Current depth in the traversal. */
int tree_current_depth(struct tree *);
/*
* The current full pathname, length of the full pathname, and a name
* that can be used to access the file. Because tree does use chdir
* extensively, the access path is almost never the same as the full
* current path.
*
* TODO: Flesh out this interface to provide other information. In
* particular, Windows can provide file size, mode, and some permission
* information without invoking stat() at all.
*
* TODO: On platforms that support it, use openat()-style operations
* to eliminate the chdir() operations entirely while still supporting
* arbitrarily deep traversals. This makes access_path troublesome to
* support, of course, which means we'll need a rich enough interface
* that clients can function without it. (In particular, we'll need
* tree_current_open() that returns an open file descriptor.)
*
* TODO: Provide tree_current_archive_entry().
*/
const char *tree_current_path(struct tree *);
size_t tree_current_pathlen(struct tree *);
const char *tree_current_access_path(struct tree *);
/*
* Request the lstat() or stat() data for the current path. Since the
* tree package needs to do some of this anyway, and caches the
* results, you should take advantage of it here if you need it rather
* than make a redundant stat() or lstat() call of your own.
*/
const struct stat *tree_current_stat(struct tree *);
const struct stat *tree_current_lstat(struct tree *);
/* The following functions use tricks to avoid a certain number of
* stat()/lstat() calls. */
/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
int tree_current_is_physical_dir(struct tree *);
/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */
int tree_current_is_physical_link(struct tree *);
/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
int tree_current_is_dir(struct tree *);
/* For testing/debugging: Dump the internal status to the given filehandle. */
void tree_dump(struct tree *, FILE *);

577
commands/bsdtar/util.c Normal file
View file

@ -0,0 +1,577 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bsdtar_platform.h"
__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.23 2008/12/15 06:00:25 kientzle Exp $");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* Linux doesn't define mode_t, etc. in sys/stat.h. */
#endif
#include <ctype.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_WCTYPE_H
#include <wctype.h>
#else
/* If we don't have wctype, we need to hack up some version of iswprint(). */
#define iswprint isprint
#endif
#include "bsdtar.h"
#include "err.h"
static size_t bsdtar_expand_char(char *, size_t, char);
static const char *strip_components(const char *path, int elements);
#if defined(_WIN32) && !defined(__CYGWIN__)
#define read _read
#endif
/* TODO: Hack up a version of mbtowc for platforms with no wide
* character support at all. I think the following might suffice,
* but it needs careful testing.
* #if !HAVE_MBTOWC
* #define mbtowc(wcp, p, n) ((*wcp = *p), 1)
* #endif
*/
/*
* Print a string, taking care with any non-printable characters.
*
* Note that we use a stack-allocated buffer to receive the formatted
* string if we can. This is partly performance (avoiding a call to
* malloc()), partly out of expedience (we have to call vsnprintf()
* before malloc() anyway to find out how big a buffer we need; we may
* as well point that first call at a small local buffer in case it
* works), but mostly for safety (so we can use this to print messages
* about out-of-memory conditions).
*/
void
safe_fprintf(FILE *f, const char *fmt, ...)
{
char fmtbuff_stack[256]; /* Place to format the printf() string. */
char outbuff[256]; /* Buffer for outgoing characters. */
char *fmtbuff_heap; /* If fmtbuff_stack is too small, we use malloc */
char *fmtbuff; /* Pointer to fmtbuff_stack or fmtbuff_heap. */
int fmtbuff_length;
int length, n;
va_list ap;
const char *p;
unsigned i;
wchar_t wc;
char try_wc;
/* Use a stack-allocated buffer if we can, for speed and safety. */
fmtbuff_heap = NULL;
fmtbuff_length = sizeof(fmtbuff_stack);
fmtbuff = fmtbuff_stack;
/* Try formatting into the stack buffer. */
va_start(ap, fmt);
length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap);
va_end(ap);
/* If the result was too large, allocate a buffer on the heap. */
if (length >= fmtbuff_length) {
fmtbuff_length = length+1;
fmtbuff_heap = malloc(fmtbuff_length);
/* Reformat the result into the heap buffer if we can. */
if (fmtbuff_heap != NULL) {
fmtbuff = fmtbuff_heap;
va_start(ap, fmt);
length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap);
va_end(ap);
} else {
/* Leave fmtbuff pointing to the truncated
* string in fmtbuff_stack. */
length = sizeof(fmtbuff_stack) - 1;
}
}
/* Note: mbrtowc() has a cleaner API, but mbtowc() seems a bit
* more portable, so we use that here instead. */
n = mbtowc(NULL, NULL, 1); /* Reset the shift state. */
/* Write data, expanding unprintable characters. */
p = fmtbuff;
i = 0;
try_wc = 1;
while (*p != '\0') {
/* Convert to wide char, test if the wide
* char is printable in the current locale. */
if (try_wc && (n = mbtowc(&wc, p, length)) != -1) {
length -= n;
if (iswprint(wc) && wc != L'\\') {
/* Printable, copy the bytes through. */
while (n-- > 0)
outbuff[i++] = *p++;
} else {
/* Not printable, format the bytes. */
while (n-- > 0)
i += (unsigned)bsdtar_expand_char(
outbuff, i, *p++);
}
} else {
/* After any conversion failure, don't bother
* trying to convert the rest. */
i += (unsigned)bsdtar_expand_char(outbuff, i, *p++);
try_wc = 0;
}
/* If our output buffer is full, dump it and keep going. */
if (i > (sizeof(outbuff) - 20)) {
outbuff[i] = '\0';
fprintf(f, "%s", outbuff);
i = 0;
}
}
outbuff[i] = '\0';
fprintf(f, "%s", outbuff);
/* If we allocated a heap-based formatting buffer, free it now. */
if (fmtbuff_heap != NULL)
free(fmtbuff_heap);
}
/*
* Render an arbitrary sequence of bytes into printable ASCII characters.
*/
static size_t
bsdtar_expand_char(char *buff, size_t offset, char c)
{
size_t i = offset;
if (isprint((unsigned char)c) && c != '\\')
buff[i++] = c;
else {
buff[i++] = '\\';
switch (c) {
case '\a': buff[i++] = 'a'; break;
case '\b': buff[i++] = 'b'; break;
case '\f': buff[i++] = 'f'; break;
case '\n': buff[i++] = 'n'; break;
#if '\r' != '\n'
/* On some platforms, \n and \r are the same. */
case '\r': buff[i++] = 'r'; break;
#endif
case '\t': buff[i++] = 't'; break;
case '\v': buff[i++] = 'v'; break;
case '\\': buff[i++] = '\\'; break;
default:
sprintf(buff + i, "%03o", 0xFF & (int)c);
i += 3;
}
}
return (i - offset);
}
int
yes(const char *fmt, ...)
{
char buff[32];
char *p;
ssize_t l;
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, " (y/N)? ");
fflush(stderr);
l = read(2, buff, sizeof(buff) - 1);
if (l <= 0)
return (0);
buff[l] = 0;
for (p = buff; *p != '\0'; p++) {
if (isspace((unsigned char)*p))
continue;
switch(*p) {
case 'y': case 'Y':
return (1);
case 'n': case 'N':
return (0);
default:
return (0);
}
}
return (0);
}
/*-
* The logic here for -C <dir> attempts to avoid
* chdir() as long as possible. For example:
* "-C /foo -C /bar file" needs chdir("/bar") but not chdir("/foo")
* "-C /foo -C bar file" needs chdir("/foo/bar")
* "-C /foo -C bar /file1" does not need chdir()
* "-C /foo -C bar /file1 file2" needs chdir("/foo/bar") before file2
*
* The only correct way to handle this is to record a "pending" chdir
* request and combine multiple requests intelligently until we
* need to process a non-absolute file. set_chdir() adds the new dir
* to the pending list; do_chdir() actually executes any pending chdir.
*
* This way, programs that build tar command lines don't have to worry
* about -C with non-existent directories; such requests will only
* fail if the directory must be accessed.
*
* TODO: Make this handle Windows paths correctly.
*/
void
set_chdir(struct bsdtar *bsdtar, const char *newdir)
{
if (newdir[0] == '/') {
/* The -C /foo -C /bar case; dump first one. */
free(bsdtar->pending_chdir);
bsdtar->pending_chdir = NULL;
}
if (bsdtar->pending_chdir == NULL)
/* Easy case: no previously-saved dir. */
bsdtar->pending_chdir = strdup(newdir);
else {
/* The -C /foo -C bar case; concatenate */
char *old_pending = bsdtar->pending_chdir;
size_t old_len = strlen(old_pending);
bsdtar->pending_chdir = malloc(old_len + strlen(newdir) + 2);
if (old_pending[old_len - 1] == '/')
old_pending[old_len - 1] = '\0';
if (bsdtar->pending_chdir != NULL)
sprintf(bsdtar->pending_chdir, "%s/%s",
old_pending, newdir);
free(old_pending);
}
if (bsdtar->pending_chdir == NULL)
lafe_errc(1, errno, "No memory");
}
void
do_chdir(struct bsdtar *bsdtar)
{
if (bsdtar->pending_chdir == NULL)
return;
if (chdir(bsdtar->pending_chdir) != 0) {
lafe_errc(1, 0, "could not chdir to '%s'\n",
bsdtar->pending_chdir);
}
free(bsdtar->pending_chdir);
bsdtar->pending_chdir = NULL;
}
static const char *
strip_components(const char *p, int elements)
{
/* Skip as many elements as necessary. */
while (elements > 0) {
switch (*p++) {
case '/':
#if defined(_WIN32) && !defined(__CYGWIN__)
case '\\': /* Support \ path sep on Windows ONLY. */
#endif
elements--;
break;
case '\0':
/* Path is too short, skip it. */
return (NULL);
}
}
/* Skip any / characters. This handles short paths that have
* additional / termination. This also handles the case where
* the logic above stops in the middle of a duplicate //
* sequence (which would otherwise get converted to an
* absolute path). */
for (;;) {
switch (*p) {
case '/':
#if defined(_WIN32) && !defined(__CYGWIN__)
case '\\': /* Support \ path sep on Windows ONLY. */
#endif
++p;
break;
case '\0':
return (NULL);
default:
return (p);
}
}
}
/*
* Handle --strip-components and any future path-rewriting options.
* Returns non-zero if the pathname should not be extracted.
*
* TODO: Support pax-style regex path rewrites.
*/
int
edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
{
const char *name = archive_entry_pathname(entry);
#if HAVE_REGEX_H
char *subst_name;
int r;
#endif
#if HAVE_REGEX_H
r = apply_substitution(bsdtar, name, &subst_name, 0);
if (r == -1) {
lafe_warnc(0, "Invalid substitution, skipping entry");
return 1;
}
if (r == 1) {
archive_entry_copy_pathname(entry, subst_name);
if (*subst_name == '\0') {
free(subst_name);
return -1;
} else
free(subst_name);
name = archive_entry_pathname(entry);
}
if (archive_entry_hardlink(entry)) {
r = apply_substitution(bsdtar, archive_entry_hardlink(entry), &subst_name, 1);
if (r == -1) {
lafe_warnc(0, "Invalid substitution, skipping entry");
return 1;
}
if (r == 1) {
archive_entry_copy_hardlink(entry, subst_name);
free(subst_name);
}
}
if (archive_entry_symlink(entry) != NULL) {
r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1);
if (r == -1) {
lafe_warnc(0, "Invalid substitution, skipping entry");
return 1;
}
if (r == 1) {
archive_entry_copy_symlink(entry, subst_name);
free(subst_name);
}
}
#endif
/* Strip leading dir names as per --strip-components option. */
if (bsdtar->strip_components > 0) {
const char *linkname = archive_entry_hardlink(entry);
name = strip_components(name, bsdtar->strip_components);
if (name == NULL)
return (1);
if (linkname != NULL) {
linkname = strip_components(linkname,
bsdtar->strip_components);
if (linkname == NULL)
return (1);
archive_entry_copy_hardlink(entry, linkname);
}
}
/* By default, don't write or restore absolute pathnames. */
if (!bsdtar->option_absolute_paths) {
const char *rp, *p = name;
int slashonly = 1;
/* Remove leading "//./" or "//?/" or "//?/UNC/"
* (absolute path prefixes used by Windows API) */
if ((p[0] == '/' || p[0] == '\\') &&
(p[1] == '/' || p[1] == '\\') &&
(p[2] == '.' || p[2] == '?') &&
(p[3] == '/' || p[3] == '\\'))
{
if (p[2] == '?' &&
(p[4] == 'U' || p[4] == 'u') &&
(p[5] == 'N' || p[5] == 'n') &&
(p[6] == 'C' || p[6] == 'c') &&
(p[7] == '/' || p[7] == '\\'))
p += 8;
else
p += 4;
slashonly = 0;
}
do {
rp = p;
/* Remove leading drive letter from archives created
* on Windows. */
if (((p[0] >= 'a' && p[0] <= 'z') ||
(p[0] >= 'A' && p[0] <= 'Z')) &&
p[1] == ':') {
p += 2;
slashonly = 0;
}
/* Remove leading "/../", "//", etc. */
while (p[0] == '/' || p[0] == '\\') {
if (p[1] == '.' && p[2] == '.' &&
(p[3] == '/' || p[3] == '\\')) {
p += 3; /* Remove "/..", leave "/"
* for next pass. */
slashonly = 0;
} else
p += 1; /* Remove "/". */
}
} while (rp != p);
if (p != name && !bsdtar->warned_lead_slash) {
/* Generate a warning the first time this happens. */
if (slashonly)
lafe_warnc(0,
"Removing leading '%c' from member names",
name[0]);
else
lafe_warnc(0,
"Removing leading drive letter from "
"member names");
bsdtar->warned_lead_slash = 1;
}
/* Special case: Stripping everything yields ".". */
if (*p == '\0')
name = ".";
else
name = p;
} else {
/* Strip redundant leading '/' characters. */
while (name[0] == '/' && name[1] == '/')
name++;
}
/* Safely replace name in archive_entry. */
if (name != archive_entry_pathname(entry)) {
char *q = strdup(name);
archive_entry_copy_pathname(entry, q);
free(q);
}
return (0);
}
/*
* It would be nice to just use printf() for formatting large numbers,
* but the compatibility problems are quite a headache. Hence the
* following simple utility function.
*/
#ifndef __minix
const char *
tar_i64toa(int64_t n0)
{
static char buff[24];
int64_t n = n0 < 0 ? -n0 : n0;
char *p = buff + sizeof(buff);
*--p = '\0';
do {
*--p = '0' + (int)(n % 10);
n /= 10;
} while (n > 0);
if (n0 < 0)
*--p = '-';
return p;
}
#else
const char *
tar_i64toa(int32_t n0)
{
static char buff[24];
int32_t n = n0 < 0 ? -n0 : n0;
char *p = buff + sizeof(buff);
*--p = '\0';
do {
*--p = '0' + (int)(n % 10);
n /= 10;
} while (n > 0);
if (n0 < 0)
*--p = '-';
return p;
}
#endif
/*
* Like strcmp(), but try to be a little more aware of the fact that
* we're comparing two paths. Right now, it just handles leading
* "./" and trailing '/' specially, so that "a/b/" == "./a/b"
*
* TODO: Make this better, so that "./a//b/./c/" == "a/b/c"
* TODO: After this works, push it down into libarchive.
* TODO: Publish the path normalization routines in libarchive so
* that bsdtar can normalize paths and use fast strcmp() instead
* of this.
*
* Note: This is currently only used within write.c, so should
* not handle \ path separators.
*/
int
pathcmp(const char *a, const char *b)
{
/* Skip leading './' */
if (a[0] == '.' && a[1] == '/' && a[2] != '\0')
a += 2;
if (b[0] == '.' && b[1] == '/' && b[2] != '\0')
b += 2;
/* Find the first difference, or return (0) if none. */
while (*a == *b) {
if (*a == '\0')
return (0);
a++;
b++;
}
/*
* If one ends in '/' and the other one doesn't,
* they're the same.
*/
if (a[0] == '/' && a[1] == '\0' && b[0] == '\0')
return (0);
if (a[0] == '\0' && b[0] == '/' && b[1] == '\0')
return (0);
/* They're really different, return the correct sign. */
return (*(const unsigned char *)a - *(const unsigned char *)b);
}

1180
commands/bsdtar/write.c Normal file

File diff suppressed because it is too large Load diff