summaryrefslogtreecommitdiff
path: root/libarchive/libarchive-2.4.17/tar
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2008-06-08 11:04:43 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2008-06-08 11:04:43 +0200
commit16f738ecee689c6feb2acb7e4ef4d9bb4144ae7d (patch)
tree3d22f54f7298f81b18ed66d05a62fa8bfab359ab /libarchive/libarchive-2.4.17/tar
downloadtuxcmd-modules-0.6.36.tar.xz
Diffstat (limited to 'libarchive/libarchive-2.4.17/tar')
-rw-r--r--libarchive/libarchive-2.4.17/tar/bsdtar.1760
-rw-r--r--libarchive/libarchive-2.4.17/tar/bsdtar.c931
-rw-r--r--libarchive/libarchive-2.4.17/tar/bsdtar.h124
-rw-r--r--libarchive/libarchive-2.4.17/tar/bsdtar_platform.h150
-rw-r--r--libarchive/libarchive-2.4.17/tar/getdate.c1370
-rw-r--r--libarchive/libarchive-2.4.17/tar/getdate.y811
-rw-r--r--libarchive/libarchive-2.4.17/tar/matching.c421
-rw-r--r--libarchive/libarchive-2.4.17/tar/read.c358
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/main.c766
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/config.sh75
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-acl.sh76
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-basic.sh432
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-deep-dir.sh60
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-flags.sh74
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-nodump.sh52
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-overwrite.sh51
-rwxr-xr-xlibarchive/libarchive-2.4.17/tar/test/old/test-utf8.sh40
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test.h144
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test_basic.c158
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test_copy.c279
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test_getdate.c38
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test_help.c81
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test_stdio.c124
-rw-r--r--libarchive/libarchive-2.4.17/tar/test/test_version.c73
-rw-r--r--libarchive/libarchive-2.4.17/tar/tree.c542
-rw-r--r--libarchive/libarchive-2.4.17/tar/tree.h115
-rw-r--r--libarchive/libarchive-2.4.17/tar/util.c437
-rw-r--r--libarchive/libarchive-2.4.17/tar/write.c1550
28 files changed, 10092 insertions, 0 deletions
diff --git a/libarchive/libarchive-2.4.17/tar/bsdtar.1 b/libarchive/libarchive-2.4.17/tar/bsdtar.1
new file mode 100644
index 0000000..ec22160
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/bsdtar.1
@@ -0,0 +1,760 @@
+.\" 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.37 2008/01/22 07:23:44 kientzle Exp $
+.\"
+.Dd April 13, 2004
+.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 | directories
+.Nm
+.Brq Fl r | Fl u
+.Fl f Ar archive-file
+.Op Ar options
+.Op Ar files | 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 ( Fl W Cm check-links )
+(c and r modes only)
+Issue a warning message unless all links to each file are archived.
+.It Fl -exclude Ar pattern ( Fl W Cm exclude Ns = Ns 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 ( Fl W Cm format Ns = Ns Ar format )
+(c 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.
+.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 -fast-read ( Fl W Cm 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 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 ( Fl W Cm include Ns = Ns 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 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 ( Fl W Cm newer Ns = Ns 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 ( Fl W Cm newer-mtime Ns = Ns 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 ( Fl W Cm newer-than Ns = Ns 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 ( Fl W Cm newer-mtime-than Ns = Ns Pa file )
+(c, r, u modes only)
+Like
+.Fl -newer-than ,
+except it compares mtime entries instead of ctime entries.
+.It Fl -nodump ( Fl W Cm nodump )
+(c and r modes only)
+Honor the nodump file flag by skipping this file.
+.It Fl -null ( Fl W Cm 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 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 only)
+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 -one-file-system ( Fl W Cm one-file-system )
+(c, r, and u modes)
+Do not cross mount points.
+.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 -strip-components Ar count ( Fl W Cm strip-components Ns = Ns Ar count )
+(x and t 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 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 W Ar longopt=value
+Long options (preceded by
+.Fl - )
+are only supported directly on systems that have the
+.Xr getopt_long 3
+function.
+The
+.Fl W
+option can be used to access long options on systems that
+do not support this function.
+.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.
+.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
+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 .
+.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
+On systems that support getopt_long(), additional long options
+are available 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 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.
diff --git a/libarchive/libarchive-2.4.17/tar/bsdtar.c b/libarchive/libarchive-2.4.17/tar/bsdtar.c
new file mode 100644
index 0000000..fbc66c1
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/bsdtar.c
@@ -0,0 +1,931 @@
+/*-
+ * 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/bsdtar.c,v 1.79 2008/01/22 07:23:44 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_GETOPT_LONG
+#include <getopt.h>
+#else
+struct option {
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+#define no_argument 0
+#define required_argument 1
+#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
+#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"
+
+#if !HAVE_DECL_OPTARG
+extern int optarg;
+#endif
+
+#if !HAVE_DECL_OPTIND
+extern int optind;
+#endif
+
+/*
+ * 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
+
+#ifndef _PATH_DEFTAPE
+#define _PATH_DEFTAPE "/dev/tape"
+#endif
+
+/* External function to parse a date/time string (from getdate.y) */
+time_t get_date(const char *);
+
+static int bsdtar_getopt(struct bsdtar *, const char *optstring,
+ const struct option **poption);
+static void long_help(struct bsdtar *);
+static void only_mode(struct bsdtar *, const char *opt,
+ const char *valid);
+static char ** rewrite_argv(struct bsdtar *,
+ int *argc, char ** src_argv,
+ const char *optstring);
+static void set_mode(struct bsdtar *, char opt);
+static void version(void);
+
+/*
+ * The leading '+' here forces the GNU version of getopt() (as well as
+ * both the GNU and BSD versions of getopt_long) to stop at the first
+ * non-option. Otherwise, GNU getopt() permutes the arguments and
+ * screws up -C processing.
+ */
+static const char *tar_opts = "+Bb:C:cf:HhI:jkLlmnOoPprtT:UuvW:wX:xyZz";
+
+/*
+ * Most of these long options are deliberately not documented. They
+ * are provided only to make life easier for people who also use GNU tar.
+ * The only long options documented in the manual page are the ones
+ * with no corresponding short option, such as --exclude, --nodump,
+ * and --fast-read.
+ *
+ * On systems that lack getopt_long, long options can be specified
+ * using -W longopt and -W longopt=value, e.g. "-W nodump" is the same
+ * as "--nodump" and "-W exclude=pattern" is the same as "--exclude
+ * pattern". This does not rely the GNU getopt() "W;" extension, so
+ * should work correctly on any system with a POSIX-compliant getopt().
+ */
+
+/* Fake short equivalents for long options that otherwise lack them. */
+enum {
+ OPTION_CHECK_LINKS=1,
+ OPTION_EXCLUDE,
+ OPTION_FAST_READ,
+ OPTION_FORMAT,
+ OPTION_HELP,
+ OPTION_INCLUDE,
+ 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_ONE_FILE_SYSTEM,
+ OPTION_POSIX,
+ OPTION_STRIP_COMPONENTS,
+ OPTION_TOTALS,
+ OPTION_USE_COMPRESS_PROGRAM,
+ OPTION_VERSION
+};
+
+/*
+ * If you add anything, be very careful to keep this list properly
+ * sorted, as the -W logic relies on it.
+ */
+static const struct option tar_longopts[] = {
+ { "absolute-paths", no_argument, NULL, 'P' },
+ { "append", no_argument, NULL, 'r' },
+ { "block-size", required_argument, NULL, 'b' },
+ { "bunzip2", no_argument, NULL, 'j' },
+ { "bzip", no_argument, NULL, 'j' },
+ { "bzip2", no_argument, NULL, 'j' },
+ { "cd", required_argument, NULL, 'C' },
+ { "check-links", no_argument, NULL, OPTION_CHECK_LINKS },
+ { "confirmation", no_argument, NULL, 'w' },
+ { "create", no_argument, NULL, 'c' },
+ { "dereference", no_argument, NULL, 'L' },
+ { "directory", required_argument, NULL, 'C' },
+ { "exclude", required_argument, NULL, OPTION_EXCLUDE },
+ { "exclude-from", required_argument, NULL, 'X' },
+ { "extract", no_argument, NULL, 'x' },
+ { "fast-read", no_argument, NULL, OPTION_FAST_READ },
+ { "file", required_argument, NULL, 'f' },
+ { "files-from", required_argument, NULL, 'T' },
+ { "format", required_argument, NULL, OPTION_FORMAT },
+ { "gunzip", no_argument, NULL, 'z' },
+ { "gzip", no_argument, NULL, 'z' },
+ { "help", no_argument, NULL, OPTION_HELP },
+ { "include", required_argument, NULL, OPTION_INCLUDE },
+ { "interactive", no_argument, NULL, 'w' },
+ { "keep-old-files", no_argument, NULL, 'k' },
+ { "list", no_argument, NULL, 't' },
+ { "modification-time", no_argument, NULL, 'm' },
+ { "newer", required_argument, NULL, OPTION_NEWER_CTIME },
+ { "newer-ctime", required_argument, NULL, OPTION_NEWER_CTIME },
+ { "newer-ctime-than", required_argument, NULL, OPTION_NEWER_CTIME_THAN },
+ { "newer-mtime", required_argument, NULL, OPTION_NEWER_MTIME },
+ { "newer-mtime-than", required_argument, NULL, OPTION_NEWER_MTIME_THAN },
+ { "newer-than", required_argument, NULL, OPTION_NEWER_CTIME_THAN },
+ { "nodump", no_argument, NULL, OPTION_NODUMP },
+ { "norecurse", no_argument, NULL, 'n' },
+ { "no-recursion", no_argument, NULL, 'n' },
+ { "no-same-owner", no_argument, NULL, OPTION_NO_SAME_OWNER },
+ { "no-same-permissions",no_argument, NULL, OPTION_NO_SAME_PERMISSIONS },
+ { "null", no_argument, NULL, OPTION_NULL },
+ { "one-file-system", no_argument, NULL, OPTION_ONE_FILE_SYSTEM },
+ { "posix", no_argument, NULL, OPTION_POSIX },
+ { "preserve-permissions", no_argument, NULL, 'p' },
+ { "read-full-blocks", no_argument, NULL, 'B' },
+ { "same-permissions", no_argument, NULL, 'p' },
+ { "strip-components", required_argument, NULL, OPTION_STRIP_COMPONENTS },
+ { "to-stdout", no_argument, NULL, 'O' },
+ { "totals", no_argument, NULL, OPTION_TOTALS },
+ { "unlink", no_argument, NULL, 'U' },
+ { "unlink-first", no_argument, NULL, 'U' },
+ { "update", no_argument, NULL, 'u' },
+ { "use-compress-program",
+ required_argument, NULL, OPTION_USE_COMPRESS_PROGRAM },
+ { "verbose", no_argument, NULL, 'v' },
+ { "version", no_argument, NULL, OPTION_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+/* 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;
+ const struct option *option;
+ int opt, t;
+ char option_o;
+ char possible_help_request;
+ char buff[16];
+
+ /*
+ * Use a pointer for consistency, but stack-allocated storage
+ * for ease of cleanup.
+ */
+ bsdtar = &bsdtar_storage;
+ memset(bsdtar, 0, sizeof(*bsdtar));
+ bsdtar->fd = -1; /* Mark as "unused" */
+ option_o = 0;
+
+ /* Need bsdtar->progname before calling bsdtar_warnc. */
+ if (*argv == NULL)
+ bsdtar->progname = "bsdtar";
+ else {
+ bsdtar->progname = strrchr(*argv, '/');
+ if (bsdtar->progname != NULL)
+ bsdtar->progname++;
+ else
+ bsdtar->progname = *argv;
+ }
+
+ if (setlocale(LC_ALL, "") == NULL)
+ bsdtar_warnc(bsdtar, 0, "Failed to set default locale");
+#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;
+
+ /* Defaults for root user: */
+ 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;
+ }
+
+ /* Rewrite traditional-style tar arguments, if used. */
+ argv = rewrite_argv(bsdtar, &argc, argv, tar_opts);
+
+ bsdtar->argv = argv;
+ bsdtar->argc = argc;
+
+ /* Process all remaining arguments now. */
+ /*
+ * 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, tar_opts, &option)) != -1) {
+ switch (opt) {
+ case 'B': /* GNU tar */
+ /* libarchive doesn't need this; just ignore it. */
+ break;
+ case 'b': /* SUSv2 */
+ t = atoi(optarg);
+ if (t <= 0 || t > 1024)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Argument to -b is out of range (1..1024)");
+ bsdtar->bytes_per_block = 512 * t;
+ break;
+ case 'C': /* GNU tar */
+ set_chdir(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_EXCLUDE: /* GNU tar */
+ if (exclude(bsdtar, optarg))
+ bsdtar_errc(bsdtar, 1, 0,
+ "Couldn't exclude %s\n", optarg);
+ break;
+ case OPTION_FORMAT: /* GNU tar, others */
+ bsdtar->create_format = optarg;
+ break;
+ case 'f': /* SUSv2 */
+ bsdtar->filename = optarg;
+ if (strcmp(bsdtar->filename, "-") == 0)
+ bsdtar->filename = NULL;
+ break;
+ case OPTION_FAST_READ: /* GNU tar */
+ bsdtar->option_fast_read = 1;
+ 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(bsdtar);
+ 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 = optarg;
+ break;
+ case OPTION_INCLUDE:
+ /*
+ * Noone else has the @archive extension, so
+ * noone else needs this to filter entries
+ * when transforming archives.
+ */
+ if (include(bsdtar, optarg))
+ bsdtar_errc(bsdtar, 1, 0,
+ "Failed to add %s to inclusion list",
+ optarg);
+ break;
+ case 'j': /* GNU tar */
+#if HAVE_LIBBZ2
+ if (bsdtar->create_compression != '\0')
+ bsdtar_errc(bsdtar, 1, 0,
+ "Can't specify both -%c and -%c", opt,
+ bsdtar->create_compression);
+ bsdtar->create_compression = opt;
+#else
+ bsdtar_warnc(bsdtar, 0, "-j compression not supported by this version of bsdtar");
+ usage(bsdtar);
+#endif
+ break;
+ case 'k': /* GNU tar */
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE;
+ 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 '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(optarg);
+ break;
+ case OPTION_NEWER_CTIME_THAN:
+ {
+ struct stat st;
+ if (stat(optarg, &st) != 0)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Can't open file %s", 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(optarg);
+ break;
+ case OPTION_NEWER_MTIME_THAN:
+ {
+ struct stat st;
+ if (stat(optarg, &st) != 0)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Can't open file %s", 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 '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 'r': /* SUSv2 */
+ set_mode(bsdtar, opt);
+ break;
+ case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */
+ bsdtar->strip_components = atoi(optarg);
+ break;
+ case 'T': /* GNU tar */
+ bsdtar->names_from_file = 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_getop(), so -W is not available here.
+ */
+ case 'W': /* Obscure, but useful GNU convention. */
+ break;
+#endif
+ case 'w': /* SUSv2 */
+ bsdtar->option_interactive = 1;
+ break;
+ case 'X': /* GNU tar */
+ if (exclude_from_file(bsdtar, optarg))
+ bsdtar_errc(bsdtar, 1, 0,
+ "failed to process exclusions from file %s",
+ optarg);
+ break;
+ case 'x': /* SUSv2 */
+ set_mode(bsdtar, opt);
+ break;
+ case 'y': /* FreeBSD version of GNU tar */
+#if HAVE_LIBBZ2
+ if (bsdtar->create_compression != '\0')
+ bsdtar_errc(bsdtar, 1, 0,
+ "Can't specify both -%c and -%c", opt,
+ bsdtar->create_compression);
+ bsdtar->create_compression = opt;
+#else
+ bsdtar_warnc(bsdtar, 0, "-y compression not supported by this version of bsdtar");
+ usage(bsdtar);
+#endif
+ break;
+ case 'Z': /* GNU tar */
+ if (bsdtar->create_compression != '\0')
+ bsdtar_errc(bsdtar, 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 HAVE_LIBZ
+ if (bsdtar->create_compression != '\0')
+ bsdtar_errc(bsdtar, 1, 0,
+ "Can't specify both -%c and -%c", opt,
+ bsdtar->create_compression);
+ bsdtar->create_compression = opt;
+#else
+ bsdtar_warnc(bsdtar, 0, "-z compression not supported by this version of bsdtar");
+ usage(bsdtar);
+#endif
+ break;
+ case OPTION_USE_COMPRESS_PROGRAM:
+ bsdtar->compress_program = optarg;
+ break;
+ default:
+ usage(bsdtar);
+ }
+ }
+
+ /*
+ * Sanity-check options.
+ */
+
+ /* If no "real" mode was specified, treat -h as --help. */
+ if ((bsdtar->mode == '\0') && possible_help_request) {
+ long_help(bsdtar);
+ exit(0);
+ }
+
+ /* Otherwise, a mode is required. */
+ if (bsdtar->mode == '\0')
+ bsdtar_errc(bsdtar, 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 == 'Z' && bsdtar->mode == 'c') {
+ bsdtar_warnc(bsdtar, 0, ".Z compression not supported");
+ usage(bsdtar);
+ }
+ 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", "c");
+ 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");
+
+ bsdtar->argc -= optind;
+ bsdtar->argv += optind;
+
+ 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;
+ }
+
+ cleanup_exclusions(bsdtar);
+ if (bsdtar->return_value != 0)
+ bsdtar_warnc(bsdtar, 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)
+ bsdtar_errc(bsdtar, 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)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Option %s is not permitted in mode -%c",
+ opt, bsdtar->mode);
+}
+
+
+/*-
+ * Convert traditional tar arguments into new-style.
+ * For example,
+ * tar tvfb file.tar 32 --exclude FOO
+ * will be converted to
+ * tar -t -v -f file.tar -b 32 --exclude FOO
+ *
+ * This requires building a new argv array. The initial bundled word
+ * gets expanded into a new string that looks like "-t\0-v\0-f\0-b\0".
+ * The new argv array has pointers into this string intermingled with
+ * pointers to the existing arguments. Arguments are moved to
+ * immediately follow their options.
+ *
+ * The optstring argument here is the same one passed to getopt(3).
+ * It is used to determine which option letters have trailing arguments.
+ */
+char **
+rewrite_argv(struct bsdtar *bsdtar, int *argc, char **src_argv,
+ const char *optstring)
+{
+ char **new_argv, **dest_argv;
+ const char *p;
+ char *src, *dest;
+
+ if (src_argv[0] == NULL ||
+ src_argv[1] == NULL || src_argv[1][0] == '-')
+ return (src_argv);
+
+ *argc += strlen(src_argv[1]) - 1;
+ new_argv = malloc((*argc + 1) * sizeof(new_argv[0]));
+ if (new_argv == NULL)
+ bsdtar_errc(bsdtar, 1, errno, "No Memory");
+
+ dest_argv = new_argv;
+ *dest_argv++ = *src_argv++;
+
+ dest = malloc(strlen(*src_argv) * 3);
+ if (dest == NULL)
+ bsdtar_errc(bsdtar, 1, errno, "No memory");
+ for (src = *src_argv++; *src != '\0'; src++) {
+ *dest_argv++ = dest;
+ *dest++ = '-';
+ *dest++ = *src;
+ *dest++ = '\0';
+ /* If option takes an argument, insert that into the list. */
+ for (p = optstring; p != NULL && *p != '\0'; p++) {
+ if (*p != *src)
+ continue;
+ if (p[1] != ':') /* No arg required, done. */
+ break;
+ if (*src_argv == NULL) /* No arg available? Error. */
+ bsdtar_errc(bsdtar, 1, 0,
+ "Option %c requires an argument",
+ *src);
+ *dest_argv++ = *src_argv++;
+ break;
+ }
+ }
+
+ /* Copy remaining arguments, including trailing NULL. */
+ while ((*dest_argv++ = *src_argv++) != NULL)
+ ;
+
+ return (new_argv);
+}
+
+void
+usage(struct bsdtar *bsdtar)
+{
+ const char *p;
+
+ p = bsdtar->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);
+#ifdef HAVE_GETOPT_LONG
+ fprintf(stderr, " Help: %s --help\n", p);
+#else
+ fprintf(stderr, " Help: %s -h\n", p);
+#endif
+ exit(1);
+}
+
+static void
+version(void)
+{
+ printf("bsdtar %s - %s\n",
+ BSDTAR_VERSION_STRING,
+ archive_version());
+ exit(1);
+}
+
+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 Compress archive with gzip/bzip2\n"
+ " --format {ustar|pax|cpio|shar} Select archive format\n"
+#ifdef HAVE_GETOPT_LONG
+ " --exclude <pattern> Skip files that match pattern\n"
+#else
+ " -W exclude=<pattern> Skip files that match pattern\n"
+#endif
+ " -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(struct bsdtar *bsdtar)
+{
+ const char *prog;
+ const char *p;
+
+ prog = bsdtar->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();
+}
+
+static int
+bsdtar_getopt(struct bsdtar *bsdtar, const char *optstring,
+ const struct option **poption)
+{
+ char *p, *q;
+ const struct option *option;
+ int opt;
+ int option_index;
+ size_t option_length;
+
+ option_index = -1;
+ *poption = NULL;
+
+#ifdef HAVE_GETOPT_LONG
+ opt = getopt_long(bsdtar->argc, bsdtar->argv, optstring,
+ tar_longopts, &option_index);
+ if (option_index > -1)
+ *poption = tar_longopts + option_index;
+#else
+ opt = getopt(bsdtar->argc, bsdtar->argv, optstring);
+#endif
+
+ /* Support long options through -W longopt=value */
+ if (opt == 'W') {
+ p = optarg;
+ q = strchr(optarg, '=');
+ if (q != NULL) {
+ option_length = (size_t)(q - p);
+ optarg = q + 1;
+ } else {
+ option_length = strlen(p);
+ optarg = NULL;
+ }
+ option = tar_longopts;
+ while (option->name != NULL &&
+ (strlen(option->name) < option_length ||
+ strncmp(p, option->name, option_length) != 0 )) {
+ option++;
+ }
+
+ if (option->name != NULL) {
+ *poption = option;
+ opt = option->val;
+
+ /* If the first match was exact, we're done. */
+ if (strncmp(p, option->name, strlen(option->name)) == 0) {
+ while (option->name != NULL)
+ option++;
+ } else {
+ /* Check if there's another match. */
+ option++;
+ while (option->name != NULL &&
+ (strlen(option->name) < option_length ||
+ strncmp(p, option->name, option_length) != 0)) {
+ option++;
+ }
+ }
+ if (option->name != NULL)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Ambiguous option %s "
+ "(matches both %s and %s)",
+ p, (*poption)->name, option->name);
+
+ if ((*poption)->has_arg == required_argument
+ && optarg == NULL)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Option \"%s\" requires argument", p);
+ } else {
+ opt = '?';
+ /* TODO: Set up a fake 'struct option' for
+ * error reporting... ? ? ? */
+ }
+ }
+
+ return (opt);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/bsdtar.h b/libarchive/libarchive-2.4.17/tar/bsdtar.h
new file mode 100644
index 0000000..fb10678
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/bsdtar.h
@@ -0,0 +1,124 @@
+/*-
+ * 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.29 2008/01/02 00:21:27 kientzle Exp $
+ */
+
+#include "bsdtar_platform.h"
+#include <stdio.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_dont_traverse_mounts; /* --one-file-system */
+ char option_fast_read; /* --fast-read */
+ 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_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 */
+ struct archive *archive;
+ const char *progname;
+ int argc;
+ char **argv;
+ 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_dir *archive_dir; /* for write.c */
+ struct name_cache *gname_cache; /* for write.c */
+ struct links_cache *links_cache; /* for write.c */
+ struct matching *matching; /* for matching.c */
+ struct security *security; /* for read.c */
+ struct name_cache *uname_cache; /* for write.c */
+};
+
+void bsdtar_errc(struct bsdtar *, int _eval, int _code,
+ const char *fmt, ...);
+void bsdtar_warnc(struct bsdtar *, int _code, const char *fmt, ...);
+void cleanup_exclusions(struct bsdtar *);
+void do_chdir(struct bsdtar *);
+int edit_pathname(struct bsdtar *, struct archive_entry *);
+int exclude(struct bsdtar *, const char *pattern);
+int exclude_from_file(struct bsdtar *, const char *pathname);
+int excluded(struct bsdtar *, const char *pathname);
+int include(struct bsdtar *, const char *pattern);
+int include_from_file(struct bsdtar *, const char *pathname);
+int pathcmp(const char *a, const char *b);
+int process_lines(struct bsdtar *bsdtar, const char *pathname,
+ int (*process)(struct bsdtar *, const char *));
+void safe_fprintf(FILE *, const char *fmt, ...);
+void set_chdir(struct bsdtar *, const char *newdir);
+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);
+int unmatched_inclusions(struct bsdtar *bsdtar);
+void usage(struct bsdtar *);
+int yes(const char *fmt, ...);
+
diff --git a/libarchive/libarchive-2.4.17/tar/bsdtar_platform.h b/libarchive/libarchive-2.4.17/tar/bsdtar_platform.h
new file mode 100644
index 0000000..ccb9d3c
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/bsdtar_platform.h
@@ -0,0 +1,150 @@
+/*-
+ * 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.25 2008/01/02 00:23:00 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
+#elif defined(HAVE_CONFIG_H)
+/* Most POSIX platforms use the 'configure' script to build config.h */
+#include "../config.h"
+#else
+/* Warn if bsdtar hasn't been (automatically or manually) configured. */
+#error Oops: No config.h and no built-in configuration in bsdtar_platform.h.
+#endif /* !HAVE_CONFIG_H */
+
+/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
+#ifdef __FreeBSD__
+#include <sys/cdefs.h> /* For __FBSDID */
+#else
+/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+#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
+
+/*
+ * Does this platform have complete-looking POSIX-style ACL support,
+ * including some variant of the acl_get_perm() function (which was
+ * omitted from the POSIX.1e draft)?
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_PERMSET_T && HAVE_ACL_USER
+#if HAVE_ACL_GET_PERM || HAVE_ACL_GET_PERM_NP
+#define HAVE_POSIX_ACL 1
+#endif
+#endif
+
+#ifdef HAVE_LIBACL
+#include <acl/libacl.h>
+#endif
+
+#if HAVE_ACL_GET_PERM
+#define ACL_GET_PERM acl_get_perm
+#else
+#if HAVE_ACL_GET_PERM_NP
+#define ACL_GET_PERM acl_get_perm_np
+#endif
+#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
+
+
+/*
+ * We need to be able to display a filesize using printf(). The type
+ * and format string here must be compatible with one another and
+ * large enough for any file.
+ */
+#if HAVE_UINTMAX_T
+#define BSDTAR_FILESIZE_TYPE uintmax_t
+#define BSDTAR_FILESIZE_PRINTF "%ju"
+#else
+#if HAVE_UNSIGNED_LONG_LONG
+#define BSDTAR_FILESIZE_TYPE unsigned long long
+#define BSDTAR_FILESIZE_PRINTF "%llu"
+#else
+#define BSDTAR_FILESIZE_TYPE unsigned long
+#define BSDTAR_FILESIZE_PRINTF "%lu"
+#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
+#else
+#if 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
+#else
+#define ARCHIVE_STAT_CTIME_NANOS(st) (0)
+#define ARCHIVE_STAT_MTIME_NANOS(st) (0)
+#endif
+#endif
+
+#endif /* !BSDTAR_PLATFORM_H_INCLUDED */
diff --git a/libarchive/libarchive-2.4.17/tar/getdate.c b/libarchive/libarchive-2.4.17/tar/getdate.c
new file mode 100644
index 0000000..31a0dfe
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/getdate.c
@@ -0,0 +1,1370 @@
+#include <stdlib.h>
+#ifndef lint
+#ifdef __unused
+__unused
+#endif
+static char const
+yyrcsid[] = "$FreeBSD: src/usr.bin/yacc/skeleton.c,v 1.37 2003/02/12 18:03:55 davidc Exp $";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYLEX yylex()
+#define YYEMPTY -1
+#define yyclearin (yychar=(YYEMPTY))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING() (yyerrflag!=0)
+#if defined(__cplusplus) || __STDC__
+static int yygrowstack(void);
+#else
+static int yygrowstack();
+#endif
+#define YYPREFIX "yy"
+#line 2 "getdate.y"
+/*
+ * March 2005: Further modified and simplified by Tim Kientzle:
+ * Eliminate minutes-based calculations (just do everything in
+ * seconds), have lexer only recognize unsigned integers (handle '+'
+ * and '-' characters in grammar), combine tables into one table with
+ * explicit abbreviation notes, do am/pm adjustments in the grammar
+ * (eliminate some state variables and post-processing). Among other
+ * things, these changes eliminated two shift/reduce conflicts. (Went
+ * from 10 to 8.)
+ * All of Tim Kientzle's changes to this file are public domain.
+ */
+
+/*
+** Originally written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#ifdef __FreeBSD__
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/tar/getdate.y,v 1.9 2007/07/20 01:27:50 kientzle Exp $");
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int yyparse(void);
+static int yylex(void);
+static int yyerror(const char *);
+
+time_t get_date(char *);
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am or pm.
+*/
+enum { tAM, tPM };
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+#line 92 "getdate.y"
+typedef union {
+ time_t Number;
+} YYSTYPE;
+#line 117 "getdate.c"
+#define YYERRCODE 256
+#define tAGO 257
+#define tDAY 258
+#define tDAYZONE 259
+#define tAMPM 260
+#define tMONTH 261
+#define tMONTH_UNIT 262
+#define tSEC_UNIT 263
+#define tUNUMBER 264
+#define tZONE 265
+#define tDST 266
+const short yylhs[] = { -1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 8, 8, 3, 3, 3, 5, 5,
+ 5, 4, 4, 4, 4, 4, 4, 4, 4, 6,
+ 6, 9, 9, 9, 9, 9, 9, 9, 9, 7,
+};
+const short yylen[] = { 2,
+ 0, 2, 1, 1, 1, 1, 1, 1, 2, 1,
+ 2, 3, 3, 3, 5, 1, 1, 2, 1, 2,
+ 2, 3, 5, 5, 5, 2, 4, 2, 3, 2,
+ 1, 3, 3, 2, 1, 3, 3, 2, 1, 1,
+};
+const short yydefred[] = { 1,
+ 0, 0, 17, 0, 39, 35, 0, 0, 0, 0,
+ 2, 3, 4, 5, 6, 7, 8, 0, 0, 20,
+ 0, 21, 9, 0, 38, 34, 0, 0, 0, 18,
+ 0, 0, 11, 0, 0, 30, 0, 29, 0, 0,
+ 0, 0, 37, 33, 36, 32, 12, 13, 27, 0,
+ 0, 0, 0, 25, 24, 15, 23,
+};
+const short yydgoto[] = { 1,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19,
+};
+const short yysindex[] = { 0,
+ -43, -40, 0, -259, 0, 0, -35, -252, -253, -248,
+ 0, 0, 0, 0, 0, 0, 0, -30, -237, 0,
+ -23, 0, 0, -242, 0, 0, -258, -240, -238, 0,
+ -255, -244, 0, -236, -235, 0, -234, 0, -18, -14,
+ -26, -13, 0, 0, 0, 0, 0, 0, 0, -229,
+ -228, -227, -226, 0, 0, 0, 0,
+};
+const short yyrindex[] = { 0,
+ 0, 9, 0, 0, 0, 0, 64, 17, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 57, 25, 0,
+ 33, 0, 0, 49, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 41, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const short yygindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+#define YYTABLESIZE 329
+const short yytable[] = { 9,
+ 14, 10, 39, 20, 21, 40, 43, 44, 19, 27,
+ 31, 29, 34, 30, 35, 32, 16, 45, 46, 36,
+ 37, 38, 28, 41, 31, 42, 50, 47, 48, 49,
+ 51, 52, 26, 53, 54, 55, 56, 57, 0, 0,
+ 22, 0, 0, 14, 0, 14, 0, 0, 28, 0,
+ 0, 19, 0, 19, 0, 0, 10, 0, 0, 16,
+ 0, 16, 0, 40, 0, 0, 0, 31, 0, 31,
+ 0, 0, 0, 0, 0, 26, 0, 26, 0, 0,
+ 0, 0, 0, 22, 0, 22, 0, 0, 0, 0,
+ 0, 28, 0, 28, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 40, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 3, 0, 4, 5, 6,
+ 7, 8, 22, 0, 23, 24, 25, 26, 0, 33,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 14, 14,
+ 14, 14, 14, 14, 14, 14, 19, 19, 0, 19,
+ 19, 19, 19, 19, 16, 16, 0, 16, 16, 16,
+ 16, 16, 31, 31, 0, 31, 31, 31, 31, 31,
+ 26, 26, 0, 26, 26, 26, 26, 26, 22, 22,
+ 0, 22, 22, 22, 22, 22, 28, 28, 0, 28,
+ 28, 28, 0, 28, 10, 10, 0, 10, 10, 10,
+ 10, 10, 40, 0, 0, 0, 0, 40, 40,
+};
+const short yycheck[] = { 43,
+ 0, 45, 261, 44, 264, 264, 262, 263, 0, 45,
+ 264, 47, 43, 266, 45, 264, 0, 262, 263, 257,
+ 44, 264, 58, 264, 0, 264, 45, 264, 264, 264,
+ 45, 58, 0, 47, 264, 264, 264, 264, -1, -1,
+ 0, -1, -1, 43, -1, 45, -1, -1, 0, -1,
+ -1, 43, -1, 45, -1, -1, 0, -1, -1, 43,
+ -1, 45, -1, 0, -1, -1, -1, 43, -1, 45,
+ -1, -1, -1, -1, -1, 43, -1, 45, -1, -1,
+ -1, -1, -1, 43, -1, 45, -1, -1, -1, -1,
+ -1, 43, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 258, 259, -1, 261, 262, 263,
+ 264, 265, 258, -1, 260, 261, 262, 263, -1, 260,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 258, 259,
+ 260, 261, 262, 263, 264, 265, 258, 259, -1, 261,
+ 262, 263, 264, 265, 258, 259, -1, 261, 262, 263,
+ 264, 265, 258, 259, -1, 261, 262, 263, 264, 265,
+ 258, 259, -1, 261, 262, 263, 264, 265, 258, 259,
+ -1, 261, 262, 263, 264, 265, 258, 259, -1, 261,
+ 262, 263, -1, 265, 258, 259, -1, 261, 262, 263,
+ 264, 265, 259, -1, -1, -1, -1, 264, 265,
+};
+#define YYFINAL 1
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 266
+#if YYDEBUG
+const char * const yyname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,"'+'","','","'-'",0,"'/'",0,0,0,0,0,0,0,0,0,0,"':'",0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"tAGO","tDAY",
+"tDAYZONE","tAMPM","tMONTH","tMONTH_UNIT","tSEC_UNIT","tUNUMBER","tZONE","tDST",
+};
+const char * const yyrule[] = {
+"$accept : spec",
+"spec :",
+"spec : spec item",
+"item : time",
+"item : zone",
+"item : date",
+"item : day",
+"item : rel",
+"item : number",
+"time : tUNUMBER tAMPM",
+"time : bare_time",
+"time : bare_time tAMPM",
+"time : bare_time '+' tUNUMBER",
+"time : bare_time '-' tUNUMBER",
+"bare_time : tUNUMBER ':' tUNUMBER",
+"bare_time : tUNUMBER ':' tUNUMBER ':' tUNUMBER",
+"zone : tZONE",
+"zone : tDAYZONE",
+"zone : tZONE tDST",
+"day : tDAY",
+"day : tDAY ','",
+"day : tUNUMBER tDAY",
+"date : tUNUMBER '/' tUNUMBER",
+"date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
+"date : tUNUMBER '-' tUNUMBER '-' tUNUMBER",
+"date : tUNUMBER '-' tMONTH '-' tUNUMBER",
+"date : tMONTH tUNUMBER",
+"date : tMONTH tUNUMBER ',' tUNUMBER",
+"date : tUNUMBER tMONTH",
+"date : tUNUMBER tMONTH tUNUMBER",
+"rel : relunit tAGO",
+"rel : relunit",
+"relunit : '-' tUNUMBER tSEC_UNIT",
+"relunit : '+' tUNUMBER tSEC_UNIT",
+"relunit : tUNUMBER tSEC_UNIT",
+"relunit : tSEC_UNIT",
+"relunit : '-' tUNUMBER tMONTH_UNIT",
+"relunit : '+' tUNUMBER tMONTH_UNIT",
+"relunit : tUNUMBER tMONTH_UNIT",
+"relunit : tMONTH_UNIT",
+"number : tUNUMBER",
+};
+#endif
+#if YYDEBUG
+#include <stdio.h>
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+#define YYINITSTACKSIZE 200
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short *yyss;
+short *yysslim;
+YYSTYPE *yyvs;
+int yystacksize;
+#line 328 "getdate.y"
+
+static struct TABLE {
+ size_t abbrev;
+ const char *name;
+ int type;
+ time_t value;
+} const TimeWords[] = {
+ /* am/pm */
+ { 0, "am", tAMPM, tAM },
+ { 0, "pm", tAMPM, tPM },
+
+ /* Month names. */
+ { 3, "january", tMONTH, 1 },
+ { 3, "february", tMONTH, 2 },
+ { 3, "march", tMONTH, 3 },
+ { 3, "april", tMONTH, 4 },
+ { 3, "may", tMONTH, 5 },
+ { 3, "june", tMONTH, 6 },
+ { 3, "july", tMONTH, 7 },
+ { 3, "august", tMONTH, 8 },
+ { 3, "september", tMONTH, 9 },
+ { 3, "october", tMONTH, 10 },
+ { 3, "november", tMONTH, 11 },
+ { 3, "december", tMONTH, 12 },
+
+ /* Days of the week. */
+ { 2, "sunday", tDAY, 0 },
+ { 3, "monday", tDAY, 1 },
+ { 2, "tuesday", tDAY, 2 },
+ { 3, "wednesday", tDAY, 3 },
+ { 2, "thursday", tDAY, 4 },
+ { 2, "friday", tDAY, 5 },
+ { 2, "saturday", tDAY, 6 },
+
+ /* Timezones: Offsets are in minutes. */
+ { 0, "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { 0, "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { 0, "utc", tZONE, HOUR( 0) },
+ { 0, "wet", tZONE, HOUR( 0) }, /* Western European */
+ { 0, "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { 0, "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { 0, "at", tZONE, HOUR( 2) }, /* Azores */
+ /* { 0, "bst", tZONE, HOUR( 3) }, */ /* Brazil Standard: Conflict */
+ /* { 0, "gst", tZONE, HOUR( 3) }, */ /* Greenland Standard: Conflict*/
+ { 0, "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
+ { 0, "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
+ { 0, "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
+ { 0, "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { 0, "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { 0, "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { 0, "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { 0, "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { 0, "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { 0, "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { 0, "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { 0, "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { 0, "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { 0, "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { 0, "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { 0, "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { 0, "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { 0, "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { 0, "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { 0, "nt", tZONE, HOUR(11) }, /* Nome */
+ { 0, "idlw", tZONE, HOUR(12) }, /* Intl Date Line West */
+ { 0, "cet", tZONE, -HOUR(1) }, /* Central European */
+ { 0, "met", tZONE, -HOUR(1) }, /* Middle European */
+ { 0, "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { 0, "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { 0, "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { 0, "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { 0, "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { 0, "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { 0, "eet", tZONE, -HOUR(2) }, /* Eastern Eur, USSR Zone 1 */
+ { 0, "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+ { 0, "it", tZONE, -HOUR(3)-30 },/* Iran */
+ { 0, "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { 0, "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+ { 0, "ist", tZONE, -HOUR(5)-30 },/* Indian Standard */
+ { 0, "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+ /* { 0, "nst", tZONE, -HOUR(6.5) }, */ /* North Sumatra: Conflict */
+ /* { 0, "sst", tZONE, -HOUR(7) }, */ /* So Sumatra, USSR 6: Conflict */
+ { 0, "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { 0, "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+ { 0, "jt", tZONE, -HOUR(7)-30 },/* Java (3pm in Cronusland!)*/
+ { 0, "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { 0, "jst", tZONE, -HOUR(9) }, /* Japan Std, USSR Zone 8 */
+ { 0, "cast", tZONE, -HOUR(9)-30 },/* Central Australian Std */
+ { 0, "cadt", tDAYZONE, -HOUR(9)-30 },/* Central Australian Daylt */
+ { 0, "east", tZONE, -HOUR(10) }, /* Eastern Australian Std */
+ { 0, "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylt */
+ { 0, "gst", tZONE, -HOUR(10) }, /* Guam Std, USSR Zone 9 */
+ { 0, "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { 0, "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { 0, "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { 0, "idle", tZONE, -HOUR(12) }, /* Intl Date Line East */
+
+ { 0, "dst", tDST, 0 },
+
+ /* Time units. */
+ { 4, "years", tMONTH_UNIT, 12 },
+ { 5, "months", tMONTH_UNIT, 1 },
+ { 9, "fortnights", tSEC_UNIT, 14 * 24 * 60 * 60 },
+ { 4, "weeks", tSEC_UNIT, 7 * 24 * 60 * 60 },
+ { 3, "days", tSEC_UNIT, 1 * 24 * 60 * 60 },
+ { 4, "hours", tSEC_UNIT, 60 * 60 },
+ { 3, "minutes", tSEC_UNIT, 60 },
+ { 3, "seconds", tSEC_UNIT, 1 },
+
+ /* Relative-time words. */
+ { 0, "tomorrow", tSEC_UNIT, 1 * 24 * 60 * 60 },
+ { 0, "yesterday", tSEC_UNIT, -1 * 24 * 60 * 60 },
+ { 0, "today", tSEC_UNIT, 0 },
+ { 0, "now", tSEC_UNIT, 0 },
+ { 0, "last", tUNUMBER, -1 },
+ { 0, "this", tSEC_UNIT, 0 },
+ { 0, "next", tUNUMBER, 2 },
+ { 0, "first", tUNUMBER, 1 },
+ { 0, "1st", tUNUMBER, 1 },
+/* { 0, "second", tUNUMBER, 2 }, */
+ { 0, "2nd", tUNUMBER, 2 },
+ { 0, "third", tUNUMBER, 3 },
+ { 0, "3rd", tUNUMBER, 3 },
+ { 0, "fourth", tUNUMBER, 4 },
+ { 0, "4th", tUNUMBER, 4 },
+ { 0, "fifth", tUNUMBER, 5 },
+ { 0, "5th", tUNUMBER, 5 },
+ { 0, "sixth", tUNUMBER, 6 },
+ { 0, "seventh", tUNUMBER, 7 },
+ { 0, "eighth", tUNUMBER, 8 },
+ { 0, "ninth", tUNUMBER, 9 },
+ { 0, "tenth", tUNUMBER, 10 },
+ { 0, "eleventh", tUNUMBER, 11 },
+ { 0, "twelfth", tUNUMBER, 12 },
+ { 0, "ago", tAGO, 1 },
+
+ /* Military timezones. */
+ { 0, "a", tZONE, HOUR( 1) },
+ { 0, "b", tZONE, HOUR( 2) },
+ { 0, "c", tZONE, HOUR( 3) },
+ { 0, "d", tZONE, HOUR( 4) },
+ { 0, "e", tZONE, HOUR( 5) },
+ { 0, "f", tZONE, HOUR( 6) },
+ { 0, "g", tZONE, HOUR( 7) },
+ { 0, "h", tZONE, HOUR( 8) },
+ { 0, "i", tZONE, HOUR( 9) },
+ { 0, "k", tZONE, HOUR( 10) },
+ { 0, "l", tZONE, HOUR( 11) },
+ { 0, "m", tZONE, HOUR( 12) },
+ { 0, "n", tZONE, HOUR(- 1) },
+ { 0, "o", tZONE, HOUR(- 2) },
+ { 0, "p", tZONE, HOUR(- 3) },
+ { 0, "q", tZONE, HOUR(- 4) },
+ { 0, "r", tZONE, HOUR(- 5) },
+ { 0, "s", tZONE, HOUR(- 6) },
+ { 0, "t", tZONE, HOUR(- 7) },
+ { 0, "u", tZONE, HOUR(- 8) },
+ { 0, "v", tZONE, HOUR(- 9) },
+ { 0, "w", tZONE, HOUR(-10) },
+ { 0, "x", tZONE, HOUR(-11) },
+ { 0, "y", tZONE, HOUR(-12) },
+ { 0, "z", tZONE, HOUR( 0) },
+
+ /* End of table. */
+ { 0, NULL, 0, 0 }
+};
+
+
+
+
+/* ARGSUSED */
+static int
+yyerror(const char *s)
+{
+ (void)s;
+ return 0;
+}
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds)
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+}
+
+
+/* Year is either
+ * A number from 0 to 99, which means a year from 1970 to 2069, or
+ * The actual year (>=100). */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds, DSTMODE DSTmode)
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
+ I'm too lazy to try to check for time_t overflow in another way. */
+ if (Year < EPOCH || Year > 2038
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ Julian = Day - 1;
+ for (i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ DSTmaybe));
+}
+
+static int
+yylex(void)
+{
+ char c;
+ char buff[64];
+
+ for ( ; ; ) {
+ while (isspace((unsigned char)*yyInput))
+ yyInput++;
+
+ /* Skip parenthesized comments. */
+ if (*yyInput == '(') {
+ int Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ continue;
+ }
+
+ /* Try the next token in the word table first. */
+ /* This allows us to match "2nd", for example. */
+ {
+ char *src = yyInput;
+ const struct TABLE *tp;
+ unsigned i = 0;
+
+ /* Force to lowercase and strip '.' characters. */
+ while (*src != '\0'
+ && (isalnum((unsigned char)*src) || *src == '.')
+ && i < sizeof(buff)-1) {
+ if (*src != '.') {
+ if (isupper((unsigned char)*src))
+ buff[i++] = tolower((unsigned char)*src);
+ else
+ buff[i++] = *src;
+ }
+ src++;
+ }
+ buff[i++] = '\0';
+
+ /*
+ * Find the first match. If the word can be
+ * abbreviated, make sure we match at least
+ * the minimum abbreviation.
+ */
+ for (tp = TimeWords; tp->name; tp++) {
+ size_t abbrev = tp->abbrev;
+ if (abbrev == 0)
+ abbrev = strlen(tp->name);
+ if (strlen(buff) >= abbrev
+ && strncmp(tp->name, buff, strlen(buff))
+ == 0) {
+ /* Skip over token. */
+ yyInput = src;
+ /* Return the match. */
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ }
+
+ /*
+ * Not in the word table, maybe it's a number. Note:
+ * Because '-' and '+' have other special meanings, I
+ * don't deal with signed numbers here.
+ */
+ if (isdigit((unsigned char)(c = *yyInput))) {
+ for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ return (tUNUMBER);
+ }
+
+ return (*yyInput++);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(char *p)
+{
+ struct tm *tm;
+ struct tm gmt, *gmt_ptr;
+ time_t Start;
+ time_t tod;
+ time_t nowtime;
+ long tzone;
+
+ memset(&gmt, 0, sizeof(gmt));
+ yyInput = p;
+
+ (void)time (&nowtime);
+
+ gmt_ptr = gmtime (&nowtime);
+ if (gmt_ptr != NULL) {
+ /* Copy, in case localtime and gmtime use the same buffer. */
+ gmt = *gmt_ptr;
+ }
+
+ if (! (tm = localtime (&nowtime)))
+ return -1;
+
+ if (gmt_ptr != NULL)
+ tzone = difftm (&gmt, tm) / 60;
+ else
+ /* This system doesn't understand timezones; fake it. */
+ tzone = 0;
+ if(tm->tm_isdst)
+ tzone += 60;
+
+ yyYear = tm->tm_year + 1900;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = tzone;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1
+ || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear,
+ yyHour, yyMinutes, yySeconds, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ } else {
+ Start = nowtime;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's
+ * distinguishable from the error return value. (Alternately
+ * could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(int argc, char **argv)
+{
+ time_t d;
+
+ while (*++argv != NULL) {
+ (void)printf("Input: %s\n", *argv);
+ d = get_date(*argv);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("Output: %s\n", ctime(&d));
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
+#line 814 "getdate.c"
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack()
+{
+ int newsize, i;
+ short *newss;
+ YYSTYPE *newvs;
+
+ if ((newsize = yystacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return -1;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+ i = yyssp - yyss;
+ newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
+ (short *)malloc(newsize * sizeof *newss);
+ if (newss == NULL)
+ return -1;
+ yyss = newss;
+ yyssp = newss + i;
+ newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
+ (YYSTYPE *)malloc(newsize * sizeof *newvs);
+ if (newvs == NULL)
+ return -1;
+ yyvs = newvs;
+ yyvsp = newvs + i;
+ yystacksize = newsize;
+ yysslim = yyss + newsize - 1;
+ return 0;
+}
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+
+#ifndef YYPARSE_PARAM
+#if defined(__cplusplus) || __STDC__
+#define YYPARSE_PARAM_ARG void
+#define YYPARSE_PARAM_DECL
+#else /* ! ANSI-C/C++ */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* ANSI-C/C++ */
+#else /* YYPARSE_PARAM */
+#ifndef YYPARSE_PARAM_TYPE
+#define YYPARSE_PARAM_TYPE void *
+#endif
+#if defined(__cplusplus) || __STDC__
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM_TYPE YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* ! ANSI-C/C++ */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL YYPARSE_PARAM_TYPE YYPARSE_PARAM;
+#endif /* ANSI-C/C++ */
+#endif /* ! YYPARSE_PARAM */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+ YYPARSE_PARAM_DECL
+{
+ int yym, yyn, yystate;
+#if YYDEBUG
+ const char *yys;
+
+ if ((yys = getenv("YYDEBUG")))
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ if (yyss == NULL && yygrowstack()) goto yyoverflow;
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate])) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, shifting to state %d\n",
+ YYPREFIX, yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yysslim && yygrowstack())
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+#if defined(lint) || defined(__GNUC__)
+ goto yynewerror;
+#endif
+yynewerror:
+ yyerror("syntax error");
+#if defined(lint) || defined(__GNUC__)
+ goto yyerrlab;
+#endif
+yyerrlab:
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yysslim && yygrowstack())
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: error recovery discarding state %d\n",
+ YYPREFIX, *yyssp);
+#endif
+ if (yyssp <= yyss) goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == 0) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+ YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1-yym];
+ switch (yyn)
+ {
+case 3:
+#line 108 "getdate.y"
+{ yyHaveTime++; }
+break;
+case 4:
+#line 109 "getdate.y"
+{ yyHaveZone++; }
+break;
+case 5:
+#line 110 "getdate.y"
+{ yyHaveDate++; }
+break;
+case 6:
+#line 111 "getdate.y"
+{ yyHaveDay++; }
+break;
+case 7:
+#line 112 "getdate.y"
+{ yyHaveRel++; }
+break;
+case 9:
+#line 116 "getdate.y"
+{
+ /* "7am" */
+ yyHour = yyvsp[-1].Number;
+ if (yyHour == 12)
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ if (yyvsp[0].Number == tPM)
+ yyHour += 12;
+ }
+break;
+case 10:
+#line 126 "getdate.y"
+{
+ /* "7:12:18" "19:17" */
+ }
+break;
+case 11:
+#line 129 "getdate.y"
+{
+ /* "7:12pm", "12:20:13am" */
+ if (yyHour == 12)
+ yyHour = 0;
+ if (yyvsp[0].Number == tPM)
+ yyHour += 12;
+ }
+break;
+case 12:
+#line 136 "getdate.y"
+{
+ /* "7:14+0700" */
+ yyDSTmode = DSToff;
+ yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
+ }
+break;
+case 13:
+#line 141 "getdate.y"
+{
+ /* "19:14:12-0530" */
+ yyDSTmode = DSToff;
+ yyTimezone = + (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
+ }
+break;
+case 14:
+#line 148 "getdate.y"
+{
+ yyHour = yyvsp[-2].Number;
+ yyMinutes = yyvsp[0].Number;
+ yySeconds = 0;
+ }
+break;
+case 15:
+#line 153 "getdate.y"
+{
+ yyHour = yyvsp[-4].Number;
+ yyMinutes = yyvsp[-2].Number;
+ yySeconds = yyvsp[0].Number;
+ }
+break;
+case 16:
+#line 160 "getdate.y"
+{
+ yyTimezone = yyvsp[0].Number;
+ yyDSTmode = DSToff;
+ }
+break;
+case 17:
+#line 164 "getdate.y"
+{
+ yyTimezone = yyvsp[0].Number;
+ yyDSTmode = DSTon;
+ }
+break;
+case 18:
+#line 168 "getdate.y"
+{
+ yyTimezone = yyvsp[-1].Number;
+ yyDSTmode = DSTon;
+ }
+break;
+case 19:
+#line 174 "getdate.y"
+{
+ yyDayOrdinal = 1;
+ yyDayNumber = yyvsp[0].Number;
+ }
+break;
+case 20:
+#line 178 "getdate.y"
+{
+ /* "tue," "wednesday," */
+ yyDayOrdinal = 1;
+ yyDayNumber = yyvsp[-1].Number;
+ }
+break;
+case 21:
+#line 183 "getdate.y"
+{
+ /* "second tues" "3 wed" */
+ yyDayOrdinal = yyvsp[-1].Number;
+ yyDayNumber = yyvsp[0].Number;
+ }
+break;
+case 22:
+#line 190 "getdate.y"
+{
+ /* "1/15" */
+ yyMonth = yyvsp[-2].Number;
+ yyDay = yyvsp[0].Number;
+ }
+break;
+case 23:
+#line 195 "getdate.y"
+{
+ if (yyvsp[-4].Number >= 13) {
+ /* First number is big: 2004/01/29, 99/02/17 */
+ yyYear = yyvsp[-4].Number;
+ yyMonth = yyvsp[-2].Number;
+ yyDay = yyvsp[0].Number;
+ } else if ((yyvsp[0].Number >= 13) || (yyvsp[-2].Number >= 13)) {
+ /* Last number is big: 01/07/98 */
+ /* Middle number is big: 01/29/04 */
+ yyMonth = yyvsp[-4].Number;
+ yyDay = yyvsp[-2].Number;
+ yyYear = yyvsp[0].Number;
+ } else {
+ /* No significant clues: 02/03/04 */
+ yyMonth = yyvsp[-4].Number;
+ yyDay = yyvsp[-2].Number;
+ yyYear = yyvsp[0].Number;
+ }
+ }
+break;
+case 24:
+#line 214 "getdate.y"
+{
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = yyvsp[-4].Number;
+ yyMonth = yyvsp[-2].Number;
+ yyDay = yyvsp[0].Number;
+ }
+break;
+case 25:
+#line 220 "getdate.y"
+{
+ if (yyvsp[-4].Number > 31) {
+ /* e.g. 1992-Jun-17 */
+ yyYear = yyvsp[-4].Number;
+ yyMonth = yyvsp[-2].Number;
+ yyDay = yyvsp[0].Number;
+ } else {
+ /* e.g. 17-JUN-1992. */
+ yyDay = yyvsp[-4].Number;
+ yyMonth = yyvsp[-2].Number;
+ yyYear = yyvsp[0].Number;
+ }
+ }
+break;
+case 26:
+#line 233 "getdate.y"
+{
+ /* "May 3" */
+ yyMonth = yyvsp[-1].Number;
+ yyDay = yyvsp[0].Number;
+ }
+break;
+case 27:
+#line 238 "getdate.y"
+{
+ /* "June 17, 2001" */
+ yyMonth = yyvsp[-3].Number;
+ yyDay = yyvsp[-2].Number;
+ yyYear = yyvsp[0].Number;
+ }
+break;
+case 28:
+#line 244 "getdate.y"
+{
+ /* "12 Sept" */
+ yyDay = yyvsp[-1].Number;
+ yyMonth = yyvsp[0].Number;
+ }
+break;
+case 29:
+#line 249 "getdate.y"
+{
+ /* "12 Sept 1997" */
+ yyDay = yyvsp[-2].Number;
+ yyMonth = yyvsp[-1].Number;
+ yyYear = yyvsp[0].Number;
+ }
+break;
+case 30:
+#line 257 "getdate.y"
+{
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+break;
+case 32:
+#line 264 "getdate.y"
+{
+ /* "-3 hours" */
+ yyRelSeconds -= yyvsp[-1].Number * yyvsp[0].Number;
+ }
+break;
+case 33:
+#line 268 "getdate.y"
+{
+ /* "+1 minute" */
+ yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
+ }
+break;
+case 34:
+#line 272 "getdate.y"
+{
+ /* "1 day" */
+ yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
+ }
+break;
+case 35:
+#line 276 "getdate.y"
+{
+ /* "hour" */
+ yyRelSeconds += yyvsp[0].Number;
+ }
+break;
+case 36:
+#line 280 "getdate.y"
+{
+ /* "-3 months" */
+ yyRelMonth -= yyvsp[-1].Number * yyvsp[0].Number;
+ }
+break;
+case 37:
+#line 284 "getdate.y"
+{
+ /* "+5 years" */
+ yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
+ }
+break;
+case 38:
+#line 288 "getdate.y"
+{
+ /* "2 years" */
+ yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
+ }
+break;
+case 39:
+#line 292 "getdate.y"
+{
+ /* "6 months" */
+ yyRelMonth += yyvsp[0].Number;
+ }
+break;
+case 40:
+#line 298 "getdate.y"
+{
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = yyvsp[0].Number;
+ else {
+ if(yyvsp[0].Number>10000) {
+ /* "20040301" */
+ yyHaveDate++;
+ yyDay= (yyvsp[0].Number)%100;
+ yyMonth= (yyvsp[0].Number/100)%100;
+ yyYear = yyvsp[0].Number/10000;
+ }
+ else {
+ /* "513" is same as "5:13" */
+ yyHaveTime++;
+ if (yyvsp[0].Number < 100) {
+ yyHour = yyvsp[0].Number;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = yyvsp[0].Number / 100;
+ yyMinutes = yyvsp[0].Number % 100;
+ }
+ yySeconds = 0;
+ }
+ }
+ }
+break;
+#line 1315 "getdate.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+ if (yyssp >= yysslim && yygrowstack())
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ return (1);
+yyaccept:
+ return (0);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/getdate.y b/libarchive/libarchive-2.4.17/tar/getdate.y
new file mode 100644
index 0000000..3253f6d
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/getdate.y
@@ -0,0 +1,811 @@
+%{
+/*
+ * March 2005: Further modified and simplified by Tim Kientzle:
+ * Eliminate minutes-based calculations (just do everything in
+ * seconds), have lexer only recognize unsigned integers (handle '+'
+ * and '-' characters in grammar), combine tables into one table with
+ * explicit abbreviation notes, do am/pm adjustments in the grammar
+ * (eliminate some state variables and post-processing). Among other
+ * things, these changes eliminated two shift/reduce conflicts. (Went
+ * from 10 to 8.)
+ * All of Tim Kientzle's changes to this file are public domain.
+ */
+
+/*
+** Originally written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#ifdef __FreeBSD__
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/tar/getdate.y,v 1.9 2007/07/20 01:27:50 kientzle Exp $");
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int yyparse(void);
+static int yylex(void);
+static int yyerror(const char *);
+
+time_t get_date(char *);
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am or pm.
+*/
+enum { tAM, tPM };
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+%}
+
+%union {
+ time_t Number;
+}
+
+%token tAGO tDAY tDAYZONE tAMPM tMONTH tMONTH_UNIT tSEC_UNIT tUNUMBER
+%token tZONE tDST
+
+%type <Number> tDAY tDAYZONE tMONTH tMONTH_UNIT
+%type <Number> tSEC_UNIT tUNUMBER tZONE tAMPM
+
+%%
+
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time { yyHaveTime++; }
+ | zone { yyHaveZone++; }
+ | date { yyHaveDate++; }
+ | day { yyHaveDay++; }
+ | rel { yyHaveRel++; }
+ | number
+ ;
+
+time : tUNUMBER tAMPM {
+ /* "7am" */
+ yyHour = $1;
+ if (yyHour == 12)
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ if ($2 == tPM)
+ yyHour += 12;
+ }
+ | bare_time {
+ /* "7:12:18" "19:17" */
+ }
+ | bare_time tAMPM {
+ /* "7:12pm", "12:20:13am" */
+ if (yyHour == 12)
+ yyHour = 0;
+ if ($2 == tPM)
+ yyHour += 12;
+ }
+ | bare_time '+' tUNUMBER {
+ /* "7:14+0700" */
+ yyDSTmode = DSToff;
+ yyTimezone = - ($3 % 100 + ($3 / 100) * 60);
+ }
+ | bare_time '-' tUNUMBER {
+ /* "19:14:12-0530" */
+ yyDSTmode = DSToff;
+ yyTimezone = + ($3 % 100 + ($3 / 100) * 60);
+ }
+ ;
+
+bare_time : tUNUMBER ':' tUNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ }
+ ;
+
+zone : tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ | tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ /* "tue," "wednesday," */
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ /* "second tues" "3 wed" */
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ /* "1/15" */
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ if ($1 >= 13) {
+ /* First number is big: 2004/01/29, 99/02/17 */
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ } else if (($5 >= 13) || ($3 >= 13)) {
+ /* Last number is big: 01/07/98 */
+ /* Middle number is big: 01/29/04 */
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ } else {
+ /* No significant clues: 02/03/04 */
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ }
+ | tUNUMBER '-' tUNUMBER '-' tUNUMBER {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ }
+ | tUNUMBER '-' tMONTH '-' tUNUMBER {
+ if ($1 > 31) {
+ /* e.g. 1992-Jun-17 */
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ } else {
+ /* e.g. 17-JUN-1992. */
+ yyDay = $1;
+ yyMonth = $3;
+ yyYear = $5;
+ }
+ }
+ | tMONTH tUNUMBER {
+ /* "May 3" */
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ /* "June 17, 2001" */
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ /* "12 Sept" */
+ yyDay = $1;
+ yyMonth = $2;
+ }
+ | tUNUMBER tMONTH tUNUMBER {
+ /* "12 Sept 1997" */
+ yyDay = $1;
+ yyMonth = $2;
+ yyYear = $3;
+ }
+ ;
+
+rel : relunit tAGO {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+ | relunit
+ ;
+
+relunit : '-' tUNUMBER tSEC_UNIT {
+ /* "-3 hours" */
+ yyRelSeconds -= $2 * $3;
+ }
+ | '+' tUNUMBER tSEC_UNIT {
+ /* "+1 minute" */
+ yyRelSeconds += $2 * $3;
+ }
+ | tUNUMBER tSEC_UNIT {
+ /* "1 day" */
+ yyRelSeconds += $1 * $2;
+ }
+ | tSEC_UNIT {
+ /* "hour" */
+ yyRelSeconds += $1;
+ }
+ | '-' tUNUMBER tMONTH_UNIT {
+ /* "-3 months" */
+ yyRelMonth -= $2 * $3;
+ }
+ | '+' tUNUMBER tMONTH_UNIT {
+ /* "+5 years" */
+ yyRelMonth += $2 * $3;
+ }
+ | tUNUMBER tMONTH_UNIT {
+ /* "2 years" */
+ yyRelMonth += $1 * $2;
+ }
+ | tMONTH_UNIT {
+ /* "6 months" */
+ yyRelMonth += $1;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
+ else {
+ if($1>10000) {
+ /* "20040301" */
+ yyHaveDate++;
+ yyDay= ($1)%100;
+ yyMonth= ($1/100)%100;
+ yyYear = $1/10000;
+ }
+ else {
+ /* "513" is same as "5:13" */
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ }
+ }
+ }
+ ;
+
+
+%%
+
+static struct TABLE {
+ size_t abbrev;
+ const char *name;
+ int type;
+ time_t value;
+} const TimeWords[] = {
+ /* am/pm */
+ { 0, "am", tAMPM, tAM },
+ { 0, "pm", tAMPM, tPM },
+
+ /* Month names. */
+ { 3, "january", tMONTH, 1 },
+ { 3, "february", tMONTH, 2 },
+ { 3, "march", tMONTH, 3 },
+ { 3, "april", tMONTH, 4 },
+ { 3, "may", tMONTH, 5 },
+ { 3, "june", tMONTH, 6 },
+ { 3, "july", tMONTH, 7 },
+ { 3, "august", tMONTH, 8 },
+ { 3, "september", tMONTH, 9 },
+ { 3, "october", tMONTH, 10 },
+ { 3, "november", tMONTH, 11 },
+ { 3, "december", tMONTH, 12 },
+
+ /* Days of the week. */
+ { 2, "sunday", tDAY, 0 },
+ { 3, "monday", tDAY, 1 },
+ { 2, "tuesday", tDAY, 2 },
+ { 3, "wednesday", tDAY, 3 },
+ { 2, "thursday", tDAY, 4 },
+ { 2, "friday", tDAY, 5 },
+ { 2, "saturday", tDAY, 6 },
+
+ /* Timezones: Offsets are in minutes. */
+ { 0, "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { 0, "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { 0, "utc", tZONE, HOUR( 0) },
+ { 0, "wet", tZONE, HOUR( 0) }, /* Western European */
+ { 0, "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { 0, "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { 0, "at", tZONE, HOUR( 2) }, /* Azores */
+ /* { 0, "bst", tZONE, HOUR( 3) }, */ /* Brazil Standard: Conflict */
+ /* { 0, "gst", tZONE, HOUR( 3) }, */ /* Greenland Standard: Conflict*/
+ { 0, "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
+ { 0, "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
+ { 0, "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
+ { 0, "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { 0, "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { 0, "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { 0, "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { 0, "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { 0, "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { 0, "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { 0, "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { 0, "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { 0, "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { 0, "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { 0, "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { 0, "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { 0, "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { 0, "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { 0, "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { 0, "nt", tZONE, HOUR(11) }, /* Nome */
+ { 0, "idlw", tZONE, HOUR(12) }, /* Intl Date Line West */
+ { 0, "cet", tZONE, -HOUR(1) }, /* Central European */
+ { 0, "met", tZONE, -HOUR(1) }, /* Middle European */
+ { 0, "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { 0, "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { 0, "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { 0, "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { 0, "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { 0, "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { 0, "eet", tZONE, -HOUR(2) }, /* Eastern Eur, USSR Zone 1 */
+ { 0, "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+ { 0, "it", tZONE, -HOUR(3)-30 },/* Iran */
+ { 0, "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { 0, "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+ { 0, "ist", tZONE, -HOUR(5)-30 },/* Indian Standard */
+ { 0, "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+ /* { 0, "nst", tZONE, -HOUR(6.5) }, */ /* North Sumatra: Conflict */
+ /* { 0, "sst", tZONE, -HOUR(7) }, */ /* So Sumatra, USSR 6: Conflict */
+ { 0, "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { 0, "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+ { 0, "jt", tZONE, -HOUR(7)-30 },/* Java (3pm in Cronusland!)*/
+ { 0, "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { 0, "jst", tZONE, -HOUR(9) }, /* Japan Std, USSR Zone 8 */
+ { 0, "cast", tZONE, -HOUR(9)-30 },/* Central Australian Std */
+ { 0, "cadt", tDAYZONE, -HOUR(9)-30 },/* Central Australian Daylt */
+ { 0, "east", tZONE, -HOUR(10) }, /* Eastern Australian Std */
+ { 0, "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylt */
+ { 0, "gst", tZONE, -HOUR(10) }, /* Guam Std, USSR Zone 9 */
+ { 0, "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { 0, "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { 0, "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { 0, "idle", tZONE, -HOUR(12) }, /* Intl Date Line East */
+
+ { 0, "dst", tDST, 0 },
+
+ /* Time units. */
+ { 4, "years", tMONTH_UNIT, 12 },
+ { 5, "months", tMONTH_UNIT, 1 },
+ { 9, "fortnights", tSEC_UNIT, 14 * 24 * 60 * 60 },
+ { 4, "weeks", tSEC_UNIT, 7 * 24 * 60 * 60 },
+ { 3, "days", tSEC_UNIT, 1 * 24 * 60 * 60 },
+ { 4, "hours", tSEC_UNIT, 60 * 60 },
+ { 3, "minutes", tSEC_UNIT, 60 },
+ { 3, "seconds", tSEC_UNIT, 1 },
+
+ /* Relative-time words. */
+ { 0, "tomorrow", tSEC_UNIT, 1 * 24 * 60 * 60 },
+ { 0, "yesterday", tSEC_UNIT, -1 * 24 * 60 * 60 },
+ { 0, "today", tSEC_UNIT, 0 },
+ { 0, "now", tSEC_UNIT, 0 },
+ { 0, "last", tUNUMBER, -1 },
+ { 0, "this", tSEC_UNIT, 0 },
+ { 0, "next", tUNUMBER, 2 },
+ { 0, "first", tUNUMBER, 1 },
+ { 0, "1st", tUNUMBER, 1 },
+/* { 0, "second", tUNUMBER, 2 }, */
+ { 0, "2nd", tUNUMBER, 2 },
+ { 0, "third", tUNUMBER, 3 },
+ { 0, "3rd", tUNUMBER, 3 },
+ { 0, "fourth", tUNUMBER, 4 },
+ { 0, "4th", tUNUMBER, 4 },
+ { 0, "fifth", tUNUMBER, 5 },
+ { 0, "5th", tUNUMBER, 5 },
+ { 0, "sixth", tUNUMBER, 6 },
+ { 0, "seventh", tUNUMBER, 7 },
+ { 0, "eighth", tUNUMBER, 8 },
+ { 0, "ninth", tUNUMBER, 9 },
+ { 0, "tenth", tUNUMBER, 10 },
+ { 0, "eleventh", tUNUMBER, 11 },
+ { 0, "twelfth", tUNUMBER, 12 },
+ { 0, "ago", tAGO, 1 },
+
+ /* Military timezones. */
+ { 0, "a", tZONE, HOUR( 1) },
+ { 0, "b", tZONE, HOUR( 2) },
+ { 0, "c", tZONE, HOUR( 3) },
+ { 0, "d", tZONE, HOUR( 4) },
+ { 0, "e", tZONE, HOUR( 5) },
+ { 0, "f", tZONE, HOUR( 6) },
+ { 0, "g", tZONE, HOUR( 7) },
+ { 0, "h", tZONE, HOUR( 8) },
+ { 0, "i", tZONE, HOUR( 9) },
+ { 0, "k", tZONE, HOUR( 10) },
+ { 0, "l", tZONE, HOUR( 11) },
+ { 0, "m", tZONE, HOUR( 12) },
+ { 0, "n", tZONE, HOUR(- 1) },
+ { 0, "o", tZONE, HOUR(- 2) },
+ { 0, "p", tZONE, HOUR(- 3) },
+ { 0, "q", tZONE, HOUR(- 4) },
+ { 0, "r", tZONE, HOUR(- 5) },
+ { 0, "s", tZONE, HOUR(- 6) },
+ { 0, "t", tZONE, HOUR(- 7) },
+ { 0, "u", tZONE, HOUR(- 8) },
+ { 0, "v", tZONE, HOUR(- 9) },
+ { 0, "w", tZONE, HOUR(-10) },
+ { 0, "x", tZONE, HOUR(-11) },
+ { 0, "y", tZONE, HOUR(-12) },
+ { 0, "z", tZONE, HOUR( 0) },
+
+ /* End of table. */
+ { 0, NULL, 0, 0 }
+};
+
+
+
+
+/* ARGSUSED */
+static int
+yyerror(const char *s)
+{
+ (void)s;
+ return 0;
+}
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds)
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+}
+
+
+/* Year is either
+ * A number from 0 to 99, which means a year from 1970 to 2069, or
+ * The actual year (>=100). */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds, DSTMODE DSTmode)
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
+ I'm too lazy to try to check for time_t overflow in another way. */
+ if (Year < EPOCH || Year > 2038
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ Julian = Day - 1;
+ for (i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ DSTmaybe));
+}
+
+static int
+yylex(void)
+{
+ char c;
+ char buff[64];
+
+ for ( ; ; ) {
+ while (isspace((unsigned char)*yyInput))
+ yyInput++;
+
+ /* Skip parenthesized comments. */
+ if (*yyInput == '(') {
+ int Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ continue;
+ }
+
+ /* Try the next token in the word table first. */
+ /* This allows us to match "2nd", for example. */
+ {
+ char *src = yyInput;
+ const struct TABLE *tp;
+ unsigned i = 0;
+
+ /* Force to lowercase and strip '.' characters. */
+ while (*src != '\0'
+ && (isalnum((unsigned char)*src) || *src == '.')
+ && i < sizeof(buff)-1) {
+ if (*src != '.') {
+ if (isupper((unsigned char)*src))
+ buff[i++] = tolower((unsigned char)*src);
+ else
+ buff[i++] = *src;
+ }
+ src++;
+ }
+ buff[i++] = '\0';
+
+ /*
+ * Find the first match. If the word can be
+ * abbreviated, make sure we match at least
+ * the minimum abbreviation.
+ */
+ for (tp = TimeWords; tp->name; tp++) {
+ size_t abbrev = tp->abbrev;
+ if (abbrev == 0)
+ abbrev = strlen(tp->name);
+ if (strlen(buff) >= abbrev
+ && strncmp(tp->name, buff, strlen(buff))
+ == 0) {
+ /* Skip over token. */
+ yyInput = src;
+ /* Return the match. */
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ }
+
+ /*
+ * Not in the word table, maybe it's a number. Note:
+ * Because '-' and '+' have other special meanings, I
+ * don't deal with signed numbers here.
+ */
+ if (isdigit((unsigned char)(c = *yyInput))) {
+ for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ return (tUNUMBER);
+ }
+
+ return (*yyInput++);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(char *p)
+{
+ struct tm *tm;
+ struct tm gmt, *gmt_ptr;
+ time_t Start;
+ time_t tod;
+ time_t nowtime;
+ long tzone;
+
+ memset(&gmt, 0, sizeof(gmt));
+ yyInput = p;
+
+ (void)time (&nowtime);
+
+ gmt_ptr = gmtime (&nowtime);
+ if (gmt_ptr != NULL) {
+ /* Copy, in case localtime and gmtime use the same buffer. */
+ gmt = *gmt_ptr;
+ }
+
+ if (! (tm = localtime (&nowtime)))
+ return -1;
+
+ if (gmt_ptr != NULL)
+ tzone = difftm (&gmt, tm) / 60;
+ else
+ /* This system doesn't understand timezones; fake it. */
+ tzone = 0;
+ if(tm->tm_isdst)
+ tzone += 60;
+
+ yyYear = tm->tm_year + 1900;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = tzone;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1
+ || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear,
+ yyHour, yyMinutes, yySeconds, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ } else {
+ Start = nowtime;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's
+ * distinguishable from the error return value. (Alternately
+ * could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(int argc, char **argv)
+{
+ time_t d;
+
+ while (*++argv != NULL) {
+ (void)printf("Input: %s\n", *argv);
+ d = get_date(*argv);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("Output: %s\n", ctime(&d));
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/libarchive/libarchive-2.4.17/tar/matching.c b/libarchive/libarchive-2.4.17/tar/matching.c
new file mode 100644
index 0000000..f0ca0c9
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/matching.c
@@ -0,0 +1,421 @@
+/*-
+ * 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/matching.c,v 1.11 2007/03/11 10:36:42 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 "bsdtar.h"
+
+struct match {
+ struct match *next;
+ int matches;
+ char pattern[1];
+};
+
+struct matching {
+ struct match *exclusions;
+ int exclusions_count;
+ struct match *inclusions;
+ int inclusions_count;
+ int inclusions_unmatched_count;
+};
+
+
+static void add_pattern(struct bsdtar *, struct match **list,
+ const char *pattern);
+static int bsdtar_fnmatch(const char *p, const char *s);
+static void initialize_matching(struct bsdtar *);
+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
+exclude(struct bsdtar *bsdtar, const char *pattern)
+{
+ struct matching *matching;
+
+ if (bsdtar->matching == NULL)
+ initialize_matching(bsdtar);
+ matching = bsdtar->matching;
+ add_pattern(bsdtar, &(matching->exclusions), pattern);
+ matching->exclusions_count++;
+ return (0);
+}
+
+int
+exclude_from_file(struct bsdtar *bsdtar, const char *pathname)
+{
+ return (process_lines(bsdtar, pathname, &exclude));
+}
+
+int
+include(struct bsdtar *bsdtar, const char *pattern)
+{
+ struct matching *matching;
+
+ if (bsdtar->matching == NULL)
+ initialize_matching(bsdtar);
+ matching = bsdtar->matching;
+ add_pattern(bsdtar, &(matching->inclusions), pattern);
+ matching->inclusions_count++;
+ matching->inclusions_unmatched_count++;
+ return (0);
+}
+
+int
+include_from_file(struct bsdtar *bsdtar, const char *pathname)
+{
+ return (process_lines(bsdtar, pathname, &include));
+}
+
+static void
+add_pattern(struct bsdtar *bsdtar, struct match **list, const char *pattern)
+{
+ struct match *match;
+
+ match = malloc(sizeof(*match) + strlen(pattern) + 1);
+ if (match == NULL)
+ bsdtar_errc(bsdtar, 1, errno, "Out of memory");
+ if (pattern[0] == '/')
+ pattern++;
+ strcpy(match->pattern, pattern);
+ /* Both "foo/" and "foo" should match "foo/bar". */
+ if (match->pattern[strlen(match->pattern)-1] == '/')
+ match->pattern[strlen(match->pattern)-1] = '\0';
+ match->next = *list;
+ *list = match;
+ match->matches = 0;
+}
+
+
+int
+excluded(struct bsdtar *bsdtar, const char *pathname)
+{
+ struct matching *matching;
+ struct match *match;
+ struct match *matched;
+
+ matching = bsdtar->matching;
+ 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'
+ *
+ */
+int
+match_exclusion(struct match *match, const char *pathname)
+{
+ const char *p;
+
+ if (*match->pattern == '*' || *match->pattern == '/')
+ return (bsdtar_fnmatch(match->pattern, pathname) == 0);
+
+ for (p = pathname; p != NULL; p = strchr(p, '/')) {
+ if (*p == '/')
+ p++;
+ if (bsdtar_fnmatch(match->pattern, p) == 0)
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Again, mimic gtar: inclusions are always anchored (have to match
+ * the beginning of the path) even though exclusions are not anchored.
+ */
+int
+match_inclusion(struct match *match, const char *pathname)
+{
+ return (bsdtar_fnmatch(match->pattern, pathname) == 0);
+}
+
+void
+cleanup_exclusions(struct bsdtar *bsdtar)
+{
+ struct match *p, *q;
+
+ if (bsdtar->matching) {
+ p = bsdtar->matching->inclusions;
+ while (p != NULL) {
+ q = p;
+ p = p->next;
+ free(q);
+ }
+ p = bsdtar->matching->exclusions;
+ while (p != NULL) {
+ q = p;
+ p = p->next;
+ free(q);
+ }
+ free(bsdtar->matching);
+ }
+}
+
+static void
+initialize_matching(struct bsdtar *bsdtar)
+{
+ bsdtar->matching = malloc(sizeof(*bsdtar->matching));
+ if (bsdtar->matching == NULL)
+ bsdtar_errc(bsdtar, 1, errno, "No memory");
+ memset(bsdtar->matching, 0, sizeof(*bsdtar->matching));
+}
+
+int
+unmatched_inclusions(struct bsdtar *bsdtar)
+{
+ struct matching *matching;
+
+ matching = bsdtar->matching;
+ if (matching == NULL)
+ return (0);
+ return (matching->inclusions_unmatched_count);
+}
+
+
+
+#if defined(HAVE_FNMATCH) && defined(HAVE_FNM_LEADING_DIR)
+
+/* Use system fnmatch() if it suits our needs. */
+/* On Linux, _GNU_SOURCE must be defined to get FNM_LEADING_DIR. */
+#define _GNU_SOURCE
+#include <fnmatch.h>
+static int
+bsdtar_fnmatch(const char *pattern, const char *string)
+{
+ return (fnmatch(pattern, string, FNM_LEADING_DIR));
+}
+
+#else
+/*
+ * The following was hacked from BSD C library
+ * code: src/lib/libc/gen/fnmatch.c,v 1.15 2002/02/01
+ *
+ * In particular, most of the flags were ripped out: this always
+ * behaves like FNM_LEADING_DIR is set and other flags specified
+ * by POSIX are unset.
+ *
+ * Normally, I would not conditionally compile something like this: If
+ * I have to support it anyway, everyone may as well use it. ;-)
+ * However, the full POSIX spec for fnmatch() includes a lot of
+ * advanced character handling that I'm not ready to put in here, so
+ * it's probably best if people use a local version when it's available.
+ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+static int
+bsdtar_fnmatch(const char *pattern, const char *string)
+{
+ const char *saved_pattern;
+ int negate, matched;
+ char c;
+
+ for (;;) {
+ switch (c = *pattern++) {
+ case '\0':
+ if (*string == '/' || *string == '\0')
+ return (0);
+ return (1);
+ case '?':
+ if (*string == '\0')
+ return (1);
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*')
+ c = *++pattern;
+
+ /* Optimize for pattern with * at end. */
+ if (c == '\0')
+ return (0);
+
+ /* General case, use recursion. */
+ while (*string != '\0') {
+ if (!bsdtar_fnmatch(pattern, string))
+ return (0);
+ ++string;
+ }
+ return (1);
+ case '[':
+ if (*string == '\0')
+ return (1);
+ saved_pattern = pattern;
+ if (*pattern == '!' || *pattern == '^') {
+ negate = 1;
+ ++pattern;
+ } else
+ negate = 0;
+ matched = 0;
+ c = *pattern++;
+ do {
+ if (c == '\\')
+ c = *pattern++;
+ if (c == '\0') {
+ pattern = saved_pattern;
+ c = '[';
+ goto norm;
+ }
+ if (*pattern == '-') {
+ char c2 = *(pattern + 1);
+ if (c2 == '\0') {
+ pattern = saved_pattern;
+ c = '[';
+ goto norm;
+ }
+ if (c2 == ']') {
+ /* [a-] is not a range. */
+ if (c == *string
+ || '-' == *string)
+ matched = 1;
+ pattern ++;
+ } else {
+ if (c <= *string
+ && *string <= c2)
+ matched = 1;
+ pattern += 2;
+ }
+ } else if (c == *string)
+ matched = 1;
+ c = *pattern++;
+ } while (c != ']');
+ if (matched == negate)
+ return (1);
+ ++string;
+ break;
+ case '\\':
+ if ((c = *pattern++) == '\0') {
+ c = '\\';
+ --pattern;
+ }
+ /* FALLTHROUGH */
+ default:
+ norm:
+ if (c != *string)
+ return (1);
+ string++;
+ break;
+ }
+ }
+ /* NOTREACHED */
+}
+
+#endif
diff --git a/libarchive/libarchive-2.4.17/tar/read.c b/libarchive/libarchive-2.4.17/tar/read.c
new file mode 100644
index 0000000..edda317
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/read.c
@@ -0,0 +1,358 @@
+/*-
+ * 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.35 2008/01/02 00:21:27 kientzle Exp $");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef MAJOR_IN_MKDEV
+#include <sys/mkdev.h>
+#elif defined(MAJOR_IN_SYSMACROS)
+#include <sys/sysmacros.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
+#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"
+
+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');
+}
+
+void
+tar_mode_x(struct bsdtar *bsdtar)
+{
+ read_archive(bsdtar, 'x');
+}
+
+/*
+ * Handle 'x' and 't' modes.
+ */
+static void
+read_archive(struct bsdtar *bsdtar, char mode)
+{
+ FILE *out;
+ struct archive *a;
+ struct archive_entry *entry;
+ const struct stat *st;
+ int r;
+
+ while (*bsdtar->argv) {
+ include(bsdtar, *bsdtar->argv);
+ bsdtar->argv++;
+ }
+
+ if (bsdtar->names_from_file != NULL)
+ include_from_file(bsdtar, bsdtar->names_from_file);
+
+ 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_read_open_file(a, bsdtar->filename,
+ bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
+ DEFAULT_BYTES_PER_BLOCK))
+ bsdtar_errc(bsdtar, 1, 0, "Error opening archive: %s",
+ archive_error_string(a));
+
+ do_chdir(bsdtar);
+ for (;;) {
+ /* Support --fast-read option */
+ if (bsdtar->option_fast_read &&
+ unmatched_inclusions(bsdtar) == 0)
+ break;
+
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r < ARCHIVE_OK)
+ bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ if (r <= ARCHIVE_WARN)
+ bsdtar->return_value = 1;
+ if (r == ARCHIVE_RETRY) {
+ /* Retryable error: try again */
+ bsdtar_warnc(bsdtar, 0, "Retrying...");
+ continue;
+ }
+ if (r == ARCHIVE_FATAL)
+ break;
+
+ /*
+ * 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 (excluded(bsdtar, archive_entry_pathname(entry)))
+ continue; /* Excluded by a pattern test. */
+
+ /*
+ * Modify the pathname as requested by the user. We
+ * do this for -t as well to give users a way to
+ * preview the effects of their rewrites. We also do
+ * this before extraction security checks (including
+ * leading '/' removal). Note that some rewrite
+ * failures prevent extraction.
+ */
+ if (edit_pathname(bsdtar, entry))
+ continue; /* Excluded by a rewrite failure. */
+
+ if (mode == 't') {
+ /* Perversely, gtar uses -O to mean "send to stderr"
+ * when used with -t. */
+ out = bsdtar->option_stdout ? stderr : stdout;
+
+ 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");
+ bsdtar_warnc(bsdtar, 0, "%s",
+ archive_error_string(a));
+ }
+ if (r == ARCHIVE_RETRY) {
+ fprintf(out, "\n");
+ bsdtar_warnc(bsdtar, 0, "%s",
+ archive_error_string(a));
+ }
+ if (r == ARCHIVE_FATAL) {
+ fprintf(out, "\n");
+ bsdtar_warnc(bsdtar, 0, "%s",
+ archive_error_string(a));
+ bsdtar->return_value = 1;
+ break;
+ }
+ fprintf(out, "\n");
+ } else {
+ 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);
+ }
+ 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;
+ }
+ }
+
+ 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)
+{
+ const struct stat *st;
+ char tmp[100];
+ size_t w;
+ const char *p;
+ const char *fmt;
+ time_t tim;
+ static time_t now;
+
+ st = archive_entry_stat(entry);
+
+ /*
+ * 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),
+ (int)(st->st_nlink));
+
+ /* Use uname if it's present, else uid. */
+ p = archive_entry_uname(entry);
+ if ((p == NULL) || (*p == '\0')) {
+ sprintf(tmp, "%lu ", (unsigned long)st->st_uid);
+ 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)st->st_gid);
+ 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 (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+ sprintf(tmp, "%lu,%lu",
+ (unsigned long)major(st->st_rdev),
+ (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */
+ } else {
+ /*
+ * Note the use of platform-dependent macros to format
+ * the filesize here. We need the format string and the
+ * corresponding type for the cast.
+ */
+ sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
+ (BSDTAR_FILESIZE_TYPE)st->st_size);
+ }
+ 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 = (time_t)st->st_mtime;
+ if (abs(tim - now) > (365/2)*86400)
+ fmt = bsdtar->day_first ? "%e %b %Y" : "%b %e %Y";
+ else
+ fmt = bsdtar->day_first ? "%e %b %R" : "%b %e %R";
+ 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 (S_ISLNK(st->st_mode)) /* Symbolic link */
+ safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/main.c b/libarchive/libarchive-2.4.17/tar/test/main.c
new file mode 100644
index 0000000..263e2cb
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/main.c
@@ -0,0 +1,766 @@
+/*
+ * 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 same file is used pretty much verbatim for all test harnesses.
+ *
+ * The next line is used to define various environment variables, etc.
+ *
+ * The tar and cpio test harnesses are identical except for this line;
+ * the libarchive test harness omits some code that is needed only for
+ * testing standalone executables.
+ */
+#define PROGRAM "BSDTAR"
+
+/*
+ * Various utility routines useful for test programs.
+ * Each test program is linked against this file.
+ */
+#include <errno.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * "list.h" is simply created by "grep DEFINE_TEST"; it has
+ * a line like
+ * DEFINE_TEST(test_function)
+ * for each test.
+ * Include it here with a suitable DEFINE_TEST to declare all of the
+ * test functions.
+ */
+#undef DEFINE_TEST
+#define DEFINE_TEST(name) void name(void);
+#include "list.h"
+
+/* Interix doesn't define these in a standard header. */
+#if __INTERIX__
+extern char *optarg;
+extern int optind;
+#endif
+
+/* Default is to crash and try to force a core dump on failure. */
+static int dump_on_failure = 1;
+/* Default is to print some basic information about each test. */
+static int quiet_flag = 0;
+/* Cumulative count of component failures. */
+static int failures = 0;
+/* Cumulative count of skipped component tests. */
+static int skips = 0;
+/* Cumulative count of assertions. */
+static int assertions = 0;
+
+/*
+ * My own implementation of the standard assert() macro emits the
+ * message in the same format as GCC (file:line: message).
+ * It also includes some additional useful information.
+ * This makes it a lot easier to skim through test failures in
+ * Emacs. ;-)
+ *
+ * It also supports a few special features specifically to simplify
+ * test harnesses:
+ * failure(fmt, args) -- Stores a text string that gets
+ * printed if the following assertion fails, good for
+ * explaining subtle tests.
+ */
+static char msg[4096];
+
+/*
+ * For each test source file, we remember how many times each
+ * failure was reported.
+ */
+static const char *failed_filename;
+static struct line {
+ int line;
+ int count;
+} failed_lines[1000];
+
+/*
+ * Count this failure; return the number of previous failures.
+ */
+static int
+previous_failures(const char *filename, int line)
+{
+ unsigned int i;
+ int count;
+
+ if (failed_filename == NULL || strcmp(failed_filename, filename) != 0)
+ memset(failed_lines, 0, sizeof(failed_lines));
+ failed_filename = filename;
+
+ for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
+ if (failed_lines[i].line == line) {
+ count = failed_lines[i].count;
+ failed_lines[i].count++;
+ return (count);
+ }
+ if (failed_lines[i].line == 0) {
+ failed_lines[i].line = line;
+ failed_lines[i].count = 1;
+ return (0);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Copy arguments into file-local variables.
+ */
+static const char *test_filename;
+static int test_line;
+static void *test_extra;
+void test_setup(const char *filename, int line)
+{
+ test_filename = filename;
+ test_line = line;
+}
+
+/*
+ * Inform user that we're skipping a test.
+ */
+void
+test_skipping(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (previous_failures(test_filename, test_line))
+ return;
+
+ va_start(ap, fmt);
+ fprintf(stderr, " *** SKIPPING: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ ++skips;
+}
+
+/* Common handling of failed tests. */
+static void
+report_failure(void *extra)
+{
+ if (msg[0] != '\0') {
+ fprintf(stderr, " Description: %s\n", msg);
+ msg[0] = '\0';
+ }
+
+ (void)extra; /* UNUSED */
+
+ if (dump_on_failure) {
+ fprintf(stderr,
+ " *** forcing core dump so failure can be debugged ***\n");
+ *(char *)(NULL) = 0;
+ exit(1);
+ }
+}
+
+/*
+ * Summarize repeated failures in the just-completed test file.
+ * The reports above suppress multiple failures from the same source
+ * line; this reports on any tests that did fail multiple times.
+ */
+static int
+summarize_comparator(const void *a0, const void *b0)
+{
+ const struct line *a = a0, *b = b0;
+ if (a->line == 0 && b->line == 0)
+ return (0);
+ if (a->line == 0)
+ return (1);
+ if (b->line == 0)
+ return (-1);
+ return (a->line - b->line);
+}
+
+static void
+summarize(void)
+{
+ unsigned int i;
+
+ qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]),
+ sizeof(failed_lines[0]), summarize_comparator);
+ for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
+ if (failed_lines[i].line == 0)
+ break;
+ if (failed_lines[i].count > 1)
+ fprintf(stderr, "%s:%d: Failed %d times\n",
+ failed_filename, failed_lines[i].line,
+ failed_lines[i].count);
+ }
+ /* Clear the failure history for the next file. */
+ memset(failed_lines, 0, sizeof(failed_lines));
+}
+
+/* Set up a message to display only after a test fails. */
+void
+failure(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vsprintf(msg, fmt, ap);
+ va_end(ap);
+}
+
+/* Generic assert() just displays the failed condition. */
+void
+test_assert(const char *file, int line, int value, const char *condition, void *extra)
+{
+ ++assertions;
+ if (value) {
+ msg[0] = '\0';
+ return;
+ }
+ failures ++;
+ if (previous_failures(file, line))
+ return;
+ fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
+ fprintf(stderr, " Condition: %s\n", condition);
+ report_failure(extra);
+}
+
+/* assertEqualInt() displays the values of the two integers. */
+void
+test_assert_equal_int(const char *file, int line,
+ int v1, const char *e1, int v2, const char *e2, void *extra)
+{
+ ++assertions;
+ if (v1 == v2) {
+ msg[0] = '\0';
+ return;
+ }
+ failures ++;
+ if (previous_failures(file, line))
+ return;
+ fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n",
+ file, line);
+ fprintf(stderr, " %s=%d\n", e1, v1);
+ fprintf(stderr, " %s=%d\n", e2, v2);
+ report_failure(extra);
+}
+
+/* assertEqualString() displays the values of the two strings. */
+void
+test_assert_equal_string(const char *file, int line,
+ const char *v1, const char *e1,
+ const char *v2, const char *e2,
+ void *extra)
+{
+ ++assertions;
+ if (v1 == NULL || v2 == NULL) {
+ if (v1 == v2) {
+ msg[0] = '\0';
+ return;
+ }
+ } else if (strcmp(v1, v2) == 0) {
+ msg[0] = '\0';
+ return;
+ }
+ failures ++;
+ if (previous_failures(file, line))
+ return;
+ fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n",
+ file, line);
+ fprintf(stderr, " %s = \"%s\"\n", e1, v1);
+ fprintf(stderr, " %s = \"%s\"\n", e2, v2);
+ report_failure(extra);
+}
+
+static void wcsdump(const wchar_t *w)
+{
+ if (w == NULL) {
+ fprintf(stderr, "(null)");
+ return;
+ }
+ fprintf(stderr, "\"");
+ while (*w != L'\0') {
+ unsigned int c = *w++;
+ if (c >= 32 && c < 127)
+ fprintf(stderr, "%c", c);
+ else if (c < 256)
+ fprintf(stderr, "\\x%02X", c);
+ else if (c < 0x10000)
+ fprintf(stderr, "\\u%04X", c);
+ else
+ fprintf(stderr, "\\U%08X", c);
+ }
+ fprintf(stderr, "\"");
+}
+
+/* assertEqualWString() displays the values of the two strings. */
+void
+test_assert_equal_wstring(const char *file, int line,
+ const wchar_t *v1, const char *e1,
+ const wchar_t *v2, const char *e2,
+ void *extra)
+{
+ ++assertions;
+ if (v1 == NULL) {
+ if (v2 == NULL) {
+ msg[0] = '\0';
+ return (1);
+ }
+ } else if (v2 == NULL) {
+ if (v1 == NULL) {
+ msg[0] = '\0';
+ return (1);
+ }
+ } else if (wcscmp(v1, v2) == 0) {
+ msg[0] = '\0';
+ return;
+ }
+ failures ++;
+ if (previous_failures(file, line))
+ return;
+ fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n",
+ file, line);
+ fprintf(stderr, " %s = ", e1);
+ wcsdump(v1);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " %s = ", e2);
+ wcsdump(v2);
+ fprintf(stderr, "\n");
+ report_failure(extra);
+}
+
+/*
+ * Pretty standard hexdump routine. As a bonus, if ref != NULL, then
+ * any bytes in p that differ from ref will be highlighted with '_'
+ * before and after the hex value.
+ */
+static void
+hexdump(const char *p, const char *ref, size_t l, size_t offset)
+{
+ size_t i, j;
+ char sep;
+
+ for(i=0; i < l; i+=16) {
+ fprintf(stderr, "%04x", i + offset);
+ sep = ' ';
+ for (j = 0; j < 16 && i + j < l; j++) {
+ if (ref != NULL && p[i + j] != ref[i + j])
+ sep = '_';
+ fprintf(stderr, "%c%02x", sep, p[i+j]);
+ if (ref != NULL && p[i + j] == ref[i + j])
+ sep = ' ';
+ }
+ for (; j < 16; j++) {
+ fprintf(stderr, "%c ", sep);
+ sep = ' ';
+ }
+ fprintf(stderr, "%c", sep);
+ for (j=0; j < 16 && i + j < l; j++) {
+ int c = p[i + j];
+ if (c >= ' ' && c <= 126)
+ fprintf(stderr, "%c", c);
+ else
+ fprintf(stderr, ".");
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+/* assertEqualMem() displays the values of the two memory blocks. */
+/* TODO: For long blocks, hexdump the first bytes that actually differ. */
+void
+test_assert_equal_mem(const char *file, int line,
+ const char *v1, const char *e1,
+ const char *v2, const char *e2,
+ size_t l, const char *ld, void *extra)
+{
+ ++assertions;
+ if (v1 == NULL || v2 == NULL) {
+ if (v1 == v2) {
+ msg[0] = '\0';
+ return;
+ }
+ } else if (memcmp(v1, v2, l) == 0) {
+ msg[0] = '\0';
+ return;
+ }
+ failures ++;
+ if (previous_failures(file, line))
+ return;
+ fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n",
+ file, line);
+ fprintf(stderr, " size %s = %d\n", ld, (int)l);
+ fprintf(stderr, " Dump of %s\n", e1);
+ hexdump(v1, v2, l < 32 ? l : 32, 0);
+ fprintf(stderr, " Dump of %s\n", e2);
+ hexdump(v2, v1, l < 32 ? l : 32, 0);
+ fprintf(stderr, "\n");
+ report_failure(extra);
+}
+
+void
+test_assert_empty_file(const char *f1fmt, ...)
+{
+ char f1[1024];
+ struct stat st;
+ va_list ap;
+
+ va_start(ap, f1fmt);
+ vsprintf(f1, f1fmt, ap);
+ va_end(ap);
+
+ if (stat(f1, &st) != 0) {
+ fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1);
+ report_failure(NULL);
+ } else if (st.st_size > 0) {
+ fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1);
+ fprintf(stderr, " File size: %d\n", (int)st.st_size);
+ report_failure(NULL);
+ }
+}
+
+/* assertEqualFile() asserts that two files have the same contents. */
+/* TODO: hexdump the first bytes that actually differ. */
+void
+test_assert_equal_file(const char *f1, const char *f2pattern, ...)
+{
+ char f2[1024];
+ va_list ap;
+ char buff1[1024];
+ char buff2[1024];
+ int fd1, fd2;
+ int n1, n2;
+
+ va_start(ap, f2pattern);
+ vsprintf(f2, f2pattern, ap);
+ va_end(ap);
+
+ fd1 = open(f1, O_RDONLY);
+ fd2 = open(f2, O_RDONLY);
+ for (;;) {
+ n1 = read(fd1, buff1, sizeof(buff1));
+ n2 = read(fd2, buff2, sizeof(buff2));
+ if (n1 != n2)
+ break;
+ if (n1 == 0 && n2 == 0)
+ return;
+ if (memcmp(buff1, buff2, n1) != 0)
+ break;
+ }
+ fprintf(stderr, "%s:%d: Files are not identical\n", test_filename, test_line);
+ fprintf(stderr, " file1=\"%s\"\n", f1);
+ fprintf(stderr, " file2=\"%s\"\n", f2);
+ report_failure(test_extra);
+}
+
+
+/*
+ * Call standard system() call, but build up the command line using
+ * sprintf() conventions.
+ */
+int
+systemf(const char *fmt, ...)
+{
+ char buff[8192];
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ vsprintf(buff, fmt, ap);
+ r = system(buff);
+ va_end(ap);
+ return (r);
+}
+
+/*
+ * Slurp a file into memory for ease of comparison and testing.
+ * Returns size of file in 'sizep' if non-NULL, null-terminates
+ * data in memory for ease of use.
+ */
+char *
+slurpfile(size_t * sizep, const char *fmt, ...)
+{
+ char filename[8192];
+ struct stat st;
+ va_list ap;
+ char *p;
+ ssize_t bytes_read;
+ int fd;
+ int r;
+
+ va_start(ap, fmt);
+ vsprintf(filename, fmt, ap);
+ va_end(ap);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ /* Note: No error; non-existent file is okay here. */
+ return (NULL);
+ }
+ r = fstat(fd, &st);
+ if (r != 0) {
+ fprintf(stderr, "Can't stat file %s\n", filename);
+ close(fd);
+ return (NULL);
+ }
+ p = malloc(st.st_size + 1);
+ if (p == NULL) {
+ fprintf(stderr, "Can't allocate %ld bytes of memory to read file %s\n", (long int)st.st_size, filename);
+ close(fd);
+ return (NULL);
+ }
+ bytes_read = read(fd, p, st.st_size);
+ if (bytes_read < st.st_size) {
+ fprintf(stderr, "Can't read file %s\n", filename);
+ close(fd);
+ free(p);
+ return (NULL);
+ }
+ p[st.st_size] = '\0';
+ if (sizep != NULL)
+ *sizep = (size_t)st.st_size;
+ close(fd);
+ return (p);
+}
+
+/*
+ * "list.h" is automatically generated; it just has a lot of lines like:
+ * DEFINE_TEST(function_name)
+ * It's used above to declare all of the test functions.
+ * We reuse it here to define a list of all tests (functions and names).
+ */
+#undef DEFINE_TEST
+#define DEFINE_TEST(n) { n, #n },
+struct { void (*func)(void); const char *name; } tests[] = {
+ #include "list.h"
+};
+
+/*
+ * Each test is run in a private work dir. Those work dirs
+ * do have consistent and predictable names, in case a group
+ * of tests need to collaborate. However, there is no provision
+ * for requiring that tests run in a certain order.
+ */
+static int test_run(int i, const char *tmpdir)
+{
+ int failures_before = failures;
+
+ if (!quiet_flag)
+ printf("%d: %s\n", i, tests[i].name);
+ /*
+ * Always explicitly chdir() in case the last test moved us to
+ * a strange place.
+ */
+ if (chdir(tmpdir)) {
+ fprintf(stderr,
+ "ERROR: Couldn't chdir to temp dir %s\n",
+ tmpdir);
+ exit(1);
+ }
+ /* Create a temp directory for this specific test. */
+ if (mkdir(tests[i].name, 0755)) {
+ fprintf(stderr,
+ "ERROR: Couldn't create temp dir ``%s''\n",
+ tests[i].name);
+ exit(1);
+ }
+ /* Chdir() to that work directory. */
+ if (chdir(tests[i].name)) {
+ fprintf(stderr,
+ "ERROR: Couldn't chdir to temp dir ``%s''\n",
+ tests[i].name);
+ exit(1);
+ }
+ /* Run the actual test. */
+ (*tests[i].func)();
+ /* Summarize the results of this test. */
+ summarize();
+ /* Return appropriate status. */
+ return (failures == failures_before ? 0 : 1);
+}
+
+static void usage(const char *program)
+{
+ static const int limit = sizeof(tests) / sizeof(tests[0]);
+ int i;
+
+ printf("Usage: %s [options] <test> <test> ...\n", program);
+ printf("Default is to run all tests.\n");
+ printf("Otherwise, specify the numbers of the tests you wish to run.\n");
+ printf("Options:\n");
+ printf(" -k Keep running after failures.\n");
+ printf(" Default: Core dump after any failure.\n");
+ printf(" -p <path> Path to executable to be tested.\n");
+ printf(" Default: path taken from " PROGRAM " environment variable.\n");
+ printf(" -q Quiet.\n");
+ printf(" -r <dir> Path to dir containing reference files.\n");
+ printf(" Default: Current directory.\n");
+ printf("Available tests:\n");
+ for (i = 0; i < limit; i++)
+ printf(" %d: %s\n", i, tests[i].name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ static const int limit = sizeof(tests) / sizeof(tests[0]);
+ int i, tests_run = 0, tests_failed = 0, opt;
+ time_t now;
+ char *refdir_alloc = NULL;
+ char *progname, *p;
+ char tmpdir[256];
+ char tmpdir_timestamp[256];
+
+ /*
+ * Name of this program, used to build root of our temp directory
+ * tree.
+ */
+ progname = p = argv[0];
+ while (*p != '\0') {
+ if (*p == '/')
+ progname = p + 1;
+ ++p;
+ }
+
+ /* Get the target program from environment, if available. */
+ testprog = getenv(PROGRAM);
+
+ /* Allow -k to be controlled through the environment. */
+ if (getenv(PROGRAM "_KEEP_GOING") != NULL)
+ dump_on_failure = 0;
+
+ /* Get the directory holding test files from environment. */
+ refdir = getenv(PROGRAM "_TEST_FILES");
+
+ /*
+ * Parse options.
+ */
+ while ((opt = getopt(argc, argv, "kp:qr:")) != -1) {
+ switch (opt) {
+ case 'k':
+ dump_on_failure = 0;
+ break;
+ case 'p':
+ testprog = optarg;
+ break;
+ case 'q':
+ quiet_flag++;
+ break;
+ case 'r':
+ refdir = optarg;
+ break;
+ case '?':
+ default:
+ usage(progname);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Sanity-check that our options make sense.
+ */
+ if (testprog == NULL)
+ usage(progname);
+
+
+ /*
+ * Create a temp directory for the following tests.
+ * Include the time the tests started as part of the name,
+ * to make it easier to track the results of multiple tests.
+ */
+ now = time(NULL);
+ for (i = 0; i < 1000; i++) {
+ strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
+ "%Y-%m-%dT%H.%M.%S",
+ localtime(&now));
+ sprintf(tmpdir, "/tmp/%s.%s-%03d", progname, tmpdir_timestamp, i);
+ if (mkdir(tmpdir,0755) == 0)
+ break;
+ if (errno == EEXIST)
+ continue;
+ fprintf(stderr, "ERROR: Unable to create temp directory %s\n",
+ tmpdir);
+ exit(1);
+ }
+
+ /*
+ * If the user didn't specify a directory for locating
+ * reference files, use the current directory for that.
+ */
+ if (refdir == NULL) {
+ systemf("/bin/pwd > %s/refdir", tmpdir);
+ refdir = refdir_alloc = slurpfile(NULL, "%s/refdir", tmpdir);
+ p = refdir + strlen(refdir);
+ while (p[-1] == '\n') {
+ --p;
+ *p = '\0';
+ }
+ }
+
+ /*
+ * Banner with basic information.
+ */
+ if (!quiet_flag) {
+ printf("Running tests in: %s\n", tmpdir);
+ printf("Reference files will be read from: %s\n", refdir);
+ printf("Running tests on: %s\n", testprog);
+ }
+
+ /*
+ * Run some or all of the individual tests.
+ */
+ if (argc == 0) {
+ /* Default: Run all tests. */
+ for (i = 0; i < limit; i++) {
+ if (test_run(i, tmpdir))
+ tests_failed++;
+ tests_run++;
+ }
+ } else {
+ while (*(argv) != NULL) {
+ i = atoi(*argv);
+ if (**argv < '0' || **argv > '9' || i < 0 || i >= limit) {
+ printf("*** INVALID Test %s\n", *argv);
+ usage(progname);
+ } else {
+ if (test_run(i, tmpdir))
+ tests_failed++;
+ tests_run++;
+ }
+ argv++;
+ }
+ }
+
+ /*
+ * Report summary statistics.
+ */
+ if (!quiet_flag) {
+ printf("\n");
+ printf("%d of %d tests reported failures\n",
+ tests_failed, tests_run);
+ printf(" Total of %d assertions checked.\n", assertions);
+ printf(" Total of %d assertions failed.\n", failures);
+ printf(" Total of %d assertions skipped.\n", skips);
+ }
+
+ free(refdir_alloc);
+
+ return (tests_failed);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/config.sh b/libarchive/libarchive-2.4.17/tar/test/old/config.sh
new file mode 100755
index 0000000..2d884f8
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/config.sh
@@ -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
+
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-acl.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-acl.sh
new file mode 100755
index 0000000..818607d
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-acl.sh
@@ -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
+
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-basic.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-basic.sh
new file mode 100755
index 0000000..0564bc7
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-basic.sh
@@ -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
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-deep-dir.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-deep-dir.sh
new file mode 100755
index 0000000..22cf1c8
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-deep-dir.sh
@@ -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 ..
+
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-flags.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-flags.sh
new file mode 100755
index 0000000..bfbf542
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-flags.sh
@@ -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 ..
+
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-nodump.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-nodump.sh
new file mode 100755
index 0000000..1d21b49
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-nodump.sh
@@ -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 ..
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-overwrite.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-overwrite.sh
new file mode 100755
index 0000000..b920890
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-overwrite.sh
@@ -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
diff --git a/libarchive/libarchive-2.4.17/tar/test/old/test-utf8.sh b/libarchive/libarchive-2.4.17/tar/test/old/test-utf8.sh
new file mode 100755
index 0000000..c1b18a6
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/old/test-utf8.sh
@@ -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: �����, コンニチハ"
+touch "Chinese: ��"
+
+tar -cf test.tar .
+
+# TODO: Verify the resulting archive \ No newline at end of file
diff --git a/libarchive/libarchive-2.4.17/tar/test/test.h b/libarchive/libarchive-2.4.17/tar/test/test.h
new file mode 100644
index 0000000..a19d44c
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test.h
@@ -0,0 +1,144 @@
+/*
+ * 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/lib/libarchive/test/test.h,v 1.6 2007/07/14 17:52:01 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.
+ */
+
+#define _FILE_OFFSET_BITS 64
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#ifdef USE_DMALLOC
+#include <dmalloc.h>
+#endif
+
+#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)
+/* 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
+
+/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
+#ifdef __FreeBSD__
+#include <sys/cdefs.h> /* For __FBSDID */
+#else
+#define __FBSDID(a) /* null */
+#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) test_assert(__FILE__, __LINE__, (e), #e, NULL)
+
+/* Assert two integers are the same. Reports value of each one if not. */
+#define assertEqualInt(v1,v2) \
+ test_assert_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) \
+ test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* As above, but v1 and v2 are wchar_t * */
+#define assertEqualWString(v1,v2) \
+ test_assert_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* As above, but raw blocks of bytes. */
+#define assertEqualMem(v1, v2, l) \
+ test_assert_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 \
+ test_setup(__FILE__, __LINE__);test_assert_equal_file
+/* Assert that a file is empty; supports printf-style arguments. */
+#define assertEmptyFile \
+ test_setup(__FILE__, __LINE__);test_assert_empty_file
+
+/*
+ * 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 \
+ test_setup(__FILE__, __LINE__);test_skipping
+
+/* Function declarations. These are defined in test_utility.c. */
+void failure(const char *fmt, ...);
+void test_setup(const char *, int);
+void test_skipping(const char *fmt, ...);
+void test_assert(const char *, int, int, const char *, void *);
+void test_assert_empty_file(const char *, ...);
+void test_assert_equal_file(const char *, const char *, ...);
+void test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *);
+void test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
+void test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
+void test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *);
+
+/* Like sprintf, then system() */
+int systemf(const char * fmt, ...);
+
+/* 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, ...);
+
+/*
+ * Global vars
+ */
+
+/* Directory holding reference files. */
+char *refdir;
+
+/*
+ * Special interfaces for bsdtar test harness.
+ */
+
+/* Pathname of exe to be tested. */
+char *testprog;
+
diff --git a/libarchive/libarchive-2.4.17/tar/test/test_basic.c b/libarchive/libarchive-2.4.17/tar/test/test_basic.c
new file mode 100644
index 0000000..50be289
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test_basic.c
@@ -0,0 +1,158 @@
+/*-
+ * 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$");
+
+
+static void
+basic_tar(const char *target, const char *pack_options, const char *unpack_options)
+{
+ struct stat st, st2;
+ char buff[128];
+ int r;
+
+ assertEqualInt(0, mkdir(target, 0775));
+
+ /* Use the tar program to create an archive. */
+ r = systemf("%s cf - %s `cat filelist` >%s/archive 2>%s/pack.err", testprog, pack_options, target, target);
+ failure("Error invoking %s cf -", testprog, pack_options);
+ assertEqualInt(r, 0);
+
+ chdir(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. */
+ r = lstat("file", &st);
+ failure("Failed to stat file %s/file, errno=%d", target, errno);
+ assertEqualInt(r, 0);
+ if (r == 0) {
+ assert(S_ISREG(st.st_mode));
+ assertEqualInt(0644, st.st_mode & 0777);
+ assertEqualInt(10, st.st_size);
+ failure("file %s/file", target);
+ assertEqualInt(2, st.st_nlink);
+ }
+
+ /* Another name for the same file. */
+ r = lstat("linkfile", &st2);
+ failure("Failed to stat file %s/linkfile, errno=%d", target, errno);
+ assertEqualInt(r, 0);
+ if (r == 0) {
+ assert(S_ISREG(st2.st_mode));
+ assertEqualInt(0644, st2.st_mode & 0777);
+ assertEqualInt(10, st2.st_size);
+ failure("file %s/linkfile", target);
+ assertEqualInt(2, st2.st_nlink);
+ /* Verify that the two are really hardlinked. */
+ assertEqualInt(st.st_dev, st2.st_dev);
+ failure("%s/linkfile and %s/file aren't really hardlinks", target, target);
+ assertEqualInt(st.st_ino, st2.st_ino);
+ }
+
+ /* Symlink */
+ r = lstat("symlink", &st);
+ failure("Failed to stat file %s/symlink, errno=%d", target, errno);
+ assertEqualInt(r, 0);
+ if (r == 0) {
+ failure("symlink should be a symlink; actual mode is %o",
+ st.st_mode);
+ assert(S_ISLNK(st.st_mode));
+ if (S_ISLNK(st.st_mode)) {
+ r = readlink("symlink", buff, sizeof(buff));
+ assertEqualInt(r, 4);
+ buff[r] = '\0';
+ assertEqualString(buff, "file");
+ }
+ }
+
+ /* dir */
+ r = lstat("dir", &st);
+ if (r == 0) {
+ assertEqualInt(r, 0);
+ assert(S_ISDIR(st.st_mode));
+ assertEqualInt(0775, st.st_mode & 0777);
+ }
+
+ chdir("..");
+}
+
+DEFINE_TEST(test_basic)
+{
+ int fd;
+ int filelist;
+ int oldumask;
+
+ oldumask = umask(0);
+
+ /*
+ * Create an assortment of files on disk.
+ */
+ filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
+
+ /* File with 10 bytes content. */
+ fd = open("file", O_CREAT | O_WRONLY, 0644);
+ assert(fd >= 0);
+ assertEqualInt(10, write(fd, "123456789", 10));
+ close(fd);
+ write(filelist, "file\n", 5);
+
+ /* hardlink to above file. */
+ assertEqualInt(0, link("file", "linkfile"));
+ write(filelist, "linkfile\n", 9);
+
+ /* Symlink to above file. */
+ assertEqualInt(0, symlink("file", "symlink"));
+ write(filelist, "symlink\n", 8);
+
+ /* Directory. */
+ assertEqualInt(0, mkdir("dir", 0775));
+ write(filelist, "dir\n", 4);
+ /* All done. */
+ close(filelist);
+
+ /* Archive/dearchive with a variety of options. */
+ basic_tar("copy", "", "");
+ /* tar doesn't handle cpio symlinks correctly */
+ /* basic_tar("copy_odc", "--format=odc", ""); */
+ basic_tar("copy_ustar", "--format=ustar", "");
+
+ umask(oldumask);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/test_copy.c b/libarchive/libarchive-2.4.17/tar/test/test_copy.c
new file mode 100644
index 0000000..83fbd76
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test_copy.c
@@ -0,0 +1,279 @@
+/*-
+ * 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$");
+
+static void
+create_tree(void)
+{
+ char buff[260];
+ char buff2[260];
+ int i;
+ int fd;
+
+ assertEqualInt(0, mkdir("original", 0775));
+ chdir("original");
+
+ buff[0] = 'f';
+ buff[1] = '_';
+ for (i = 0; i < 200; i++) {
+ /* Create a file named "f_abcdef..." */
+ buff[i + 2] = 'a' + (i % 26);
+ buff[i + 3] = '\0';
+ fd = open(buff, O_CREAT | O_WRONLY, 0644);
+ assert(fd >= 0);
+ assertEqualInt(i + 3, write(fd, buff, strlen(buff)));
+ close(fd);
+
+ /* Create a link named "l_abcdef..." to the above. */
+ strcpy(buff2, buff);
+ buff2[0] = 'l';
+ assertEqualInt(0, link(buff, buff2));
+
+ /* Create a link named "m_abcdef..." to the above. */
+ strcpy(buff2, buff);
+ buff2[0] = 'm';
+ assertEqualInt(0, link(buff, buff2));
+
+ /* Create a symlink named "s_abcdef..." to the above. */
+ buff2[0] = 's';
+ assertEqualInt(0, symlink(buff, buff2));
+
+ /* Create a dir named "d_abcdef...". */
+ buff2[0] = 'd';
+ assertEqualInt(0, mkdir(buff2, 0775));
+ }
+
+ chdir("..");
+}
+
+#define LIMIT_NONE 0
+#define LIMIT_USTAR 1
+
+static void
+verify_tree(int limit)
+{
+ struct stat st, st2;
+ char buff[260];
+ char buff2[260];
+ int i, r;
+ int fd;
+ int len;
+ const char *p;
+ DIR *d;
+ struct dirent *de;
+
+ /* Generate the names we know should be there and verify them. */
+ for (i = 0; i < 200; i++) {
+ /* Verify a file named "f_abcdef..." */
+ buff[0] = 'f';
+ buff[1] = '_';
+ buff[i + 2] = 'a' + (i % 26);
+ buff[i + 3] = '\0';
+ if (limit != LIMIT_USTAR || strlen(buff) <= 100) {
+ fd = open(buff, O_RDONLY);
+ failure("Couldn't open \"%s\": %s",
+ buff, strerror(errno));
+ assert(fd >= 0);
+ len = read(fd, buff2, i + 10);
+ close(fd);
+ assertEqualInt(len, i + 3);
+ /* Verify contents of 'buff2' */
+ buff2[len] = '\0';
+ assertEqualString(buff, buff2);
+ /* stat() file and get dev/ino for next check */
+ assertEqualInt(0, lstat(buff, &st));
+ }
+
+ /*
+ * ustar allows 100 chars for links, and we have
+ * "original/" as part of the name, so the link
+ * names here can't exceed 91 chars.
+ */
+ if (limit != LIMIT_USTAR || strlen(buff) <= 91) {
+ /* Verify hardlink "l_abcdef..." */
+ buff[0] = 'l';
+ assertEqualInt(0, (r = lstat(buff, &st2)));
+ if (r == 0) {
+ assertEqualInt(st2.st_dev, st.st_dev);
+ assertEqualInt(st2.st_ino, st.st_ino);
+ }
+
+ /* Verify hardlink "m_abcdef..." */
+ buff[0] = 'm';
+ assertEqualInt(0, (r = lstat(buff, &st2)));
+ if (r == 0) {
+ assertEqualInt(st2.st_dev, st.st_dev);
+ assertEqualInt(st2.st_ino, st.st_ino);
+ }
+ }
+
+ /*
+ * Symlink text doesn't include the 'original/' prefix,
+ * so the limit here is 100 characters.
+ */
+ /* Verify symlink "s_abcdef..." */
+ buff[0] = 's';
+ if (limit != LIMIT_USTAR || strlen(buff) <= 100) {
+ /* This is a symlink. */
+ assertEqualInt(0, lstat(buff, &st2));
+ assert(S_ISLNK(st2.st_mode));
+ /* This is a symlink to the file above. */
+ assertEqualInt(0, stat(buff, &st2));
+ assertEqualInt(st2.st_dev, st.st_dev);
+ assertEqualInt(st2.st_ino, st.st_ino);
+ }
+
+ /* Verify dir "d_abcdef...". */
+ buff[0] = 'd';
+ if (limit != LIMIT_USTAR || strlen(buff) <= 100) {
+ /* This is a dir. */
+ assertEqualInt(0, lstat(buff, &st2));
+ assert(S_ISDIR(st2.st_mode));
+ /* TODO: opendir/readdir this directory and
+ * make sure it's empty.
+ */
+ }
+ }
+
+ /* Now make sure nothing is there that shouldn't be. */
+ d = opendir(".");
+ while ((de = readdir(d)) != NULL) {
+ p = de->d_name;
+ switch(p[0]) {
+ case 'l': case 'm':
+ if (limit == LIMIT_USTAR)
+ assert(strlen(p) <= 91);
+ case 'd': case 'f': case 's':
+ if (limit == LIMIT_USTAR)
+ assert(strlen(p) <= 100);
+ /* Our files have very particular filename patterns. */
+ assert(p[1] == '_' && p[2] == 'a');
+ assert(p[2] == 'a');
+ p += 2;
+ for (i = 0; p[i] != '\0' && i < 200; i++)
+ assert(p[i] == 'a' + (i % 26));
+ assert(p[i] == '\0');
+ break;
+ case '.':
+ assert(p[1] == '\0' || (p[1] == '.' && p[2] == '\0'));
+ break;
+ default:
+ failure("File %s shouldn't be here", p);
+ assert(0);
+ }
+
+ }
+ closedir(d);
+}
+
+static void
+copy_basic(void)
+{
+ int r;
+
+ assertEqualInt(0, mkdir("plain", 0775));
+ chdir("plain");
+
+ /*
+ * Use the tar program to create an archive.
+ */
+ r = systemf("%s cf archive -C .. original >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");
+
+ chdir("original");
+ verify_tree(LIMIT_NONE);
+ chdir("../..");
+}
+
+static void
+copy_ustar(void)
+{
+ const char *target = "ustar";
+ int r;
+
+ assertEqualInt(0, mkdir(target, 0775));
+ chdir(target);
+
+ /*
+ * Use the tar program to create an archive.
+ */
+ r = systemf("%s cf archive --format=ustar -C .. original >pack.out 2>pack.err",
+ testprog);
+ failure("Error invoking \"%s cf\"", testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify that nothing went to stdout. */
+ 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");
+
+ chdir("original");
+ verify_tree(LIMIT_USTAR);
+ chdir("../..");
+}
+
+DEFINE_TEST(test_copy)
+{
+ int oldumask;
+
+ oldumask = umask(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();
+
+ umask(oldumask);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/test_getdate.c b/libarchive/libarchive-2.4.17/tar/test/test_getdate.c
new file mode 100644
index 0000000..7ed447b
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test_getdate.c
@@ -0,0 +1,38 @@
+/*-
+ * 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$");
+
+/*
+ * Verify that the getdate() function works.
+ */
+
+time_t get_date(const char *);
+
+DEFINE_TEST(test_getdate)
+{
+ assertEqualInt(0, get_date("Jan 1, 1970 UTC"));
+ /* TODO: Lots more tests here. */
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/test_help.c b/libarchive/libarchive-2.4.17/tar/test/test_help.c
new file mode 100644
index 0000000..c547dbc
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test_help.c
@@ -0,0 +1,81 @@
+/*-
+ * 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$");
+
+/*
+ * 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);
+ 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);
+ 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);
+ 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");
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/test_stdio.c b/libarchive/libarchive-2.4.17/tar/test/test_stdio.c
new file mode 100644
index 0000000..2d24ae3
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test_stdio.c
@@ -0,0 +1,124 @@
+/*-
+ * 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$");
+
+DEFINE_TEST(test_stdio)
+{
+ int fd;
+ int filelist;
+ int oldumask;
+ int r;
+
+ oldumask = umask(0);
+
+ /*
+ * Create a couple of files on disk.
+ */
+ filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
+ /* File */
+ fd = open("f", O_CREAT | O_WRONLY, 0644);
+ assert(fd >= 0);
+ write(fd, "f\n", 2);
+ close(fd);
+ write(filelist, "f\n", 2);
+ /* Link to above file. */
+ assertEqualInt(0, link("f", "l"));
+ write(filelist, "l\n", 2);
+ close(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);
+ /* TODO: Verify xvOf.out */
+ /* 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 */
+
+ umask(oldumask);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/test/test_version.c b/libarchive/libarchive-2.4.17/tar/test/test_version.c
new file mode 100644
index 0000000..5ac6f88
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/test/test_version.c
@@ -0,0 +1,73 @@
+/*-
+ * 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$");
+
+/*
+ * 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);
+ /* --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);
+ assertEqualMem(q, "bsdtar ", 7);
+ 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. */
+ assert(s > 1);
+ assert(*q == ' ');
+ ++q; --s;
+ /* Separator. */
+ assertEqualMem(q, "- ", 2);
+ q += 2; s -= 2;
+ /* libarchive name and version number */
+ assert(s > 11);
+ 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;
+ }
+ /* All terminated by a newline. */
+ assert(s >= 1);
+ assertEqualMem(q, "\n", 1);
+ free(p);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/tree.c b/libarchive/libarchive-2.4.17/tar/tree.c
new file mode 100644
index 0000000..23e64e3
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/tree.c
@@ -0,0 +1,542 @@
+/*-
+ * 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.8 2007/03/11 10:36:42 kientzle Exp $");
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.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
+
+#include "tree.h"
+
+/*
+ * TODO:
+ * 1) Loop checking.
+ * 3) Arbitrary logical traversals by closing/reopening intermediate fds.
+ */
+
+struct tree_entry {
+ struct tree_entry *next;
+ struct tree_entry *parent;
+ char *name;
+ size_t dirname_length;
+ dev_t dev;
+ ino_t ino;
+ int fd;
+ int flags;
+};
+
+/* 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 needsPreVisit 4 /* This entry needs to be previsited. */
+#define needsPostVisit 8 /* This entry needs to be postvisited. */
+
+/*
+ * Local data for this package.
+ */
+struct tree {
+ struct tree_entry *stack;
+ struct tree_entry *current;
+ DIR *d;
+ int initialDirFd;
+ int flags;
+ int visit_type;
+ int tree_errno; /* Error code from last failed operation. */
+
+ char *buff;
+ const char *basename;
+ size_t buff_length;
+ size_t path_length;
+ size_t dirname_length;
+
+ int depth;
+ int openCount;
+ int maxOpenCount;
+
+ struct stat lst;
+ struct stat st;
+};
+
+/* Definitions for tree.flags bitmap. */
+#define needsReturn 8 /* Marks first entry as not having been returned yet. */
+#define hasStat 16 /* The st entry is set. */
+#define hasLstat 32 /* The lst entry is set. */
+
+
+#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
+
+#if 0
+#include <stdio.h>
+void
+tree_dump(struct tree *t, FILE *out)
+{
+ struct tree_entry *te;
+
+ fprintf(out, "\tdepth: %d\n", t->depth);
+ fprintf(out, "\tbuff: %s\n", t->buff);
+ fprintf(out, "\tpwd: "); fflush(stdout); system("pwd");
+ fprintf(out, "\taccess: %s\n", t->basename);
+ fprintf(out, "\tstack:\n");
+ for (te = t->stack; te != NULL; te = te->next) {
+ fprintf(out, "\t\tte->name: %s%s%s\n", te->name,
+ te->flags & needsPreVisit ? "" : " *",
+ t->current == te ? " (current)" : "");
+ }
+}
+#endif
+
+/*
+ * 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;
+ t->stack = te;
+ te->fd = -1;
+ te->name = strdup(path);
+ te->flags = needsPreVisit | needsPostVisit;
+ te->dirname_length = t->dirname_length;
+}
+
+/*
+ * Append a name to the current path.
+ */
+static void
+tree_append(struct tree *t, const char *name, size_t name_length)
+{
+ char *p;
+
+ 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. */
+ while (name_length + 1 + t->dirname_length >= t->buff_length) {
+ t->buff_length *= 2;
+ if (t->buff_length < 1024)
+ t->buff_length = 1024;
+ t->buff = realloc(t->buff, t->buff_length);
+ }
+ 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 ++;
+ }
+ strncpy(p, name, name_length);
+ p[name_length] = '\0';
+ t->basename = p;
+}
+
+/*
+ * Open a directory tree for traversal.
+ */
+struct tree *
+tree_open(const char *path)
+{
+ struct tree *t;
+
+ t = malloc(sizeof(*t));
+ memset(t, 0, sizeof(*t));
+ tree_append(t, path, strlen(path));
+ t->initialDirFd = open(".", O_RDONLY);
+ /*
+ * During most of the traversal, items are set up and then
+ * returned immediately from tree_next(). That doesn't work
+ * for the very first entry, so we set a flag for this special
+ * case.
+ */
+ t->flags = needsReturn;
+ return (t);
+}
+
+/*
+ * We've finished a directory; ascend back to the parent.
+ */
+static void
+tree_ascend(struct tree *t)
+{
+ struct tree_entry *te;
+
+ te = t->stack;
+ t->depth--;
+ if (te->flags & isDirLink) {
+ fchdir(te->fd);
+ close(te->fd);
+ t->openCount--;
+ } else {
+ chdir("..");
+ }
+}
+
+/*
+ * Pop the working stack.
+ */
+static void
+tree_pop(struct tree *t)
+{
+ struct tree_entry *te;
+
+ 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;
+ t->basename = t->buff + t->dirname_length;
+ /* Special case: starting dir doesn't skip leading '/'. */
+ if (t->dirname_length > 0)
+ t->basename++;
+ free(te->name);
+ free(te);
+}
+
+/*
+ * Get the next item in the tree traversal.
+ */
+int
+tree_next(struct tree *t)
+{
+ struct dirent *de = NULL;
+
+ /* Handle the startup case by returning the initial entry. */
+ if (t->flags & needsReturn) {
+ t->flags &= ~needsReturn;
+ return (t->visit_type = TREE_REGULAR);
+ }
+
+ while (t->stack != NULL) {
+ /* If there's an open dir, get the next entry from there. */
+ while (t->d != NULL) {
+ de = readdir(t->d);
+ if (de == NULL) {
+ closedir(t->d);
+ t->d = NULL;
+ } else if (de->d_name[0] == '.'
+ && de->d_name[1] == '\0') {
+ /* Skip '.' */
+ } else if (de->d_name[0] == '.'
+ && de->d_name[1] == '.'
+ && de->d_name[2] == '\0') {
+ /* Skip '..' */
+ } else {
+ /*
+ * Append the path to the current path
+ * and return it.
+ */
+ tree_append(t, de->d_name, D_NAMELEN(de));
+ t->flags &= ~hasLstat;
+ t->flags &= ~hasStat;
+ return (t->visit_type = TREE_REGULAR);
+ }
+ }
+
+ /* If the current dir needs to be visited, set it up. */
+ if (t->stack->flags & needsPreVisit) {
+ t->current = t->stack;
+ tree_append(t, t->stack->name, strlen(t->stack->name));
+ t->stack->flags &= ~needsPreVisit;
+ /* If it is a link, set up fd for the ascent. */
+ if (t->stack->flags & isDirLink) {
+ t->stack->fd = open(".", O_RDONLY);
+ t->openCount++;
+ if (t->openCount > t->maxOpenCount)
+ t->maxOpenCount = t->openCount;
+ }
+ t->dirname_length = t->path_length;
+ if (chdir(t->stack->name) != 0) {
+ /* chdir() failed; return error */
+ tree_pop(t);
+ t->tree_errno = errno;
+ return (t->visit_type = TREE_ERROR_DIR);
+ }
+ t->depth++;
+ t->d = opendir(".");
+ if (t->d == NULL) {
+ tree_ascend(t); /* Undo "chdir" */
+ tree_pop(t);
+ t->tree_errno = errno;
+ return (t->visit_type = TREE_ERROR_DIR);
+ }
+ t->flags &= ~hasLstat;
+ t->flags &= ~hasStat;
+ t->basename = ".";
+ return (t->visit_type = TREE_POSTDESCENT);
+ }
+
+ /* We've done everything necessary for the top stack entry. */
+ if (t->stack->flags & needsPostVisit) {
+ tree_ascend(t);
+ tree_pop(t);
+ t->flags &= ~hasLstat;
+ t->flags &= ~hasStat;
+ return (t->visit_type = TREE_POSTASCENT);
+ }
+ }
+ return (t->visit_type = 0);
+}
+
+/*
+ * 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(t->basename, &t->st) != 0)
+ return NULL;
+ t->flags |= hasStat;
+ }
+ return (&t->st);
+}
+
+/*
+ * Get the lstat() data for the entry just returned from tree_next().
+ */
+const struct stat *
+tree_current_lstat(struct tree *t)
+{
+ if (!(t->flags & hasLstat)) {
+ if (lstat(t->basename, &t->lst) != 0)
+ return NULL;
+ t->flags |= hasLstat;
+ }
+ return (&t->lst);
+}
+
+/*
+ * Test whether current entry is a dir or link to a dir.
+ */
+int
+tree_current_is_dir(struct tree *t)
+{
+ 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));
+}
+
+/*
+ * 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)
+{
+ 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));
+}
+
+/*
+ * Test whether current entry is a symbolic link.
+ */
+int
+tree_current_is_physical_link(struct tree *t)
+{
+ const struct stat *st = tree_current_lstat(t);
+ if (st == NULL)
+ return 0;
+ return (S_ISLNK(st->st_mode));
+}
+
+/*
+ * 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);
+ if (t->buff)
+ free(t->buff);
+ /* chdir() back to where we started. */
+ if (t->initialDirFd >= 0) {
+ fchdir(t->initialDirFd);
+ close(t->initialDirFd);
+ t->initialDirFd = -1;
+ }
+ free(t);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/tree.h b/libarchive/libarchive-2.4.17/tar/tree.h
new file mode 100644
index 0000000..a32a15f
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/tree.h
@@ -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.
+ *
+ * $FreeBSD: src/usr.bin/tar/tree.h,v 1.3 2007/01/09 08:12:17 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 potentially visited three times. The first
+ * time as "regular" file. If tree_descend() is invoked at that time,
+ * the directory is added to a work list and will be visited two more
+ * times: once just after descending into the directory and again
+ * just after ascending back to the parent.
+ *
+ * TREE_ERROR is returned if the descent failed (because the
+ * directory couldn't be opened, for instance). This is returned
+ * instead of TREE_PREVISIT/TREE_POSTVISIT.
+ */
+#define TREE_REGULAR 1
+#define TREE_POSTDESCENT 2
+#define TREE_POSTASCENT 3
+#define TREE_ERROR_DIR -1
+int tree_next(struct tree *);
+
+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.
+ */
+
+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.
+ */
+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 tests may use mechanisms much faster than stat()/lstat(). */
+/* "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 *);
diff --git a/libarchive/libarchive-2.4.17/tar/util.c b/libarchive/libarchive-2.4.17/tar/util.c
new file mode 100644
index 0000000..68ff8d8
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/util.c
@@ -0,0 +1,437 @@
+/*-
+ * 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.18 2008/01/02 00:21:27 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_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 "bsdtar.h"
+
+static void bsdtar_vwarnc(struct bsdtar *, int code,
+ const char *fmt, va_list ap);
+
+/*
+ * Print a string, taking care with any non-printable characters.
+ */
+
+void
+safe_fprintf(FILE *f, const char *fmt, ...)
+{
+ char *buff;
+ char *buff_heap;
+ int buff_length;
+ int length;
+ va_list ap;
+ char *p;
+ unsigned i;
+ char buff_stack[256];
+ char copy_buff[256];
+
+ /* Use a stack-allocated buffer if we can, for speed and safety. */
+ buff_heap = NULL;
+ buff_length = sizeof(buff_stack);
+ buff = buff_stack;
+
+ va_start(ap, fmt);
+ length = vsnprintf(buff, buff_length, fmt, ap);
+ va_end(ap);
+ /* If the result is too large, allocate a buffer on the heap. */
+ if (length >= buff_length) {
+ buff_length = length+1;
+ buff_heap = malloc(buff_length);
+ /* Failsafe: use the truncated string if malloc fails. */
+ if (buff_heap != NULL) {
+ buff = buff_heap;
+ va_start(ap, fmt);
+ length = vsnprintf(buff, buff_length, fmt, ap);
+ va_end(ap);
+ }
+ }
+
+ /* Write data, expanding unprintable characters. */
+ p = buff;
+ i = 0;
+ while (*p != '\0') {
+ unsigned char c = *p++;
+
+ if (isprint(c) && c != '\\')
+ copy_buff[i++] = c;
+ else {
+ copy_buff[i++] = '\\';
+ switch (c) {
+ case '\a': copy_buff[i++] = 'a'; break;
+ case '\b': copy_buff[i++] = 'b'; break;
+ case '\f': copy_buff[i++] = 'f'; break;
+ case '\n': copy_buff[i++] = 'n'; break;
+#if '\r' != '\n'
+ /* On some platforms, \n and \r are the same. */
+ case '\r': copy_buff[i++] = 'r'; break;
+#endif
+ case '\t': copy_buff[i++] = 't'; break;
+ case '\v': copy_buff[i++] = 'v'; break;
+ case '\\': copy_buff[i++] = '\\'; break;
+ default:
+ sprintf(copy_buff + i, "%03o", c);
+ i += 3;
+ }
+ }
+
+ /* If our temp buffer is full, dump it and keep going. */
+ if (i > (sizeof(copy_buff) - 8)) {
+ copy_buff[i++] = '\0';
+ fprintf(f, "%s", copy_buff);
+ i = 0;
+ }
+ }
+ copy_buff[i++] = '\0';
+ fprintf(f, "%s", copy_buff);
+
+ /* If we allocated a heap-based buffer, free it now. */
+ if (buff_heap != NULL)
+ free(buff_heap);
+}
+
+static void
+bsdtar_vwarnc(struct bsdtar *bsdtar, int code, const char *fmt, va_list ap)
+{
+ fprintf(stderr, "%s: ", bsdtar->progname);
+ vfprintf(stderr, fmt, ap);
+ if (code != 0)
+ fprintf(stderr, ": %s", strerror(code));
+ fprintf(stderr, "\n");
+}
+
+void
+bsdtar_warnc(struct bsdtar *bsdtar, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ bsdtar_vwarnc(bsdtar, code, fmt, ap);
+ va_end(ap);
+}
+
+void
+bsdtar_errc(struct bsdtar *bsdtar, int eval, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ bsdtar_vwarnc(bsdtar, code, fmt, ap);
+ va_end(ap);
+ exit(eval);
+}
+
+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));
+ if (l <= 0)
+ return (0);
+ buff[l] = 0;
+
+ for (p = buff; *p != '\0'; p++) {
+ if (isspace(0xff & (int)*p))
+ continue;
+ switch(*p) {
+ case 'y': case 'Y':
+ return (1);
+ case 'n': case 'N':
+ return (0);
+ default:
+ return (0);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * 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.
+ * If the "process" function returns non-zero for any line, this
+ * function will return non-zero after attempting to process all
+ * remaining lines.
+ */
+int
+process_lines(struct bsdtar *bsdtar, const char *pathname,
+ int (*process)(struct bsdtar *, const char *))
+{
+ FILE *f;
+ char *buff, *buff_end, *line_start, *line_end, *p;
+ size_t buff_length, bytes_read, bytes_wanted;
+ int separator;
+ int ret;
+
+ separator = bsdtar->option_null ? '\0' : '\n';
+ ret = 0;
+
+ if (strcmp(pathname, "-") == 0)
+ f = stdin;
+ else
+ f = fopen(pathname, "r");
+ if (f == NULL)
+ bsdtar_errc(bsdtar, 1, errno, "Couldn't open %s", pathname);
+ buff_length = 8192;
+ buff = malloc(buff_length);
+ if (buff == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read %s", pathname);
+ line_start = line_end = buff_end = buff;
+ for (;;) {
+ /* Get some more data into the buffer. */
+ bytes_wanted = buff + buff_length - buff_end;
+ bytes_read = fread(buff_end, 1, bytes_wanted, f);
+ buff_end += bytes_read;
+ /* Process all complete lines in the buffer. */
+ while (line_end < buff_end) {
+ if (*line_end == separator) {
+ *line_end = '\0';
+ if ((*process)(bsdtar, line_start) != 0)
+ ret = -1;
+ line_start = line_end + 1;
+ line_end = line_start;
+ } else
+ line_end++;
+ }
+ if (feof(f))
+ break;
+ if (ferror(f))
+ bsdtar_errc(bsdtar, 1, errno,
+ "Can't read %s", pathname);
+ if (line_start > buff) {
+ /* Move a leftover fractional line to the beginning. */
+ memmove(buff, line_start, buff_end - line_start);
+ buff_end -= line_start - buff;
+ line_end -= line_start - buff;
+ line_start = buff;
+ } else {
+ /* Line is too big; enlarge the buffer. */
+ p = realloc(buff, buff_length *= 2);
+ if (p == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM,
+ "Line too long in %s", pathname);
+ buff_end = p + (buff_end - buff);
+ line_end = p + (line_end - buff);
+ line_start = buff = p;
+ }
+ }
+ /* At end-of-file, handle the final line. */
+ if (line_end > line_start) {
+ *line_end = '\0';
+ if ((*process)(bsdtar, line_start) != 0)
+ ret = -1;
+ }
+ free(buff);
+ if (f != stdin)
+ fclose(f);
+ return (ret);
+}
+
+/*-
+ * 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.
+ */
+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)
+ bsdtar_errc(bsdtar, 1, errno, "No memory");
+}
+
+void
+do_chdir(struct bsdtar *bsdtar)
+{
+ if (bsdtar->pending_chdir == NULL)
+ return;
+
+ if (chdir(bsdtar->pending_chdir) != 0) {
+ bsdtar_errc(bsdtar, 1, 0, "could not chdir to '%s'\n",
+ bsdtar->pending_chdir);
+ }
+ free(bsdtar->pending_chdir);
+ bsdtar->pending_chdir = NULL;
+}
+
+/*
+ * 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);
+
+ /* Strip leading dir names as per --strip-components option. */
+ if (bsdtar->strip_components > 0) {
+ int r = bsdtar->strip_components;
+ const char *p = name;
+
+ while (r > 0) {
+ switch (*p++) {
+ case '/':
+ r--;
+ name = p;
+ break;
+ case '\0':
+ /* Path is too short, skip it. */
+ return (1);
+ }
+ }
+ }
+
+ /* Strip redundant leading '/' characters. */
+ while (name[0] == '/' && name[1] == '/')
+ name++;
+
+ /* Strip leading '/' unless user has asked us not to. */
+ if (name[0] == '/' && !bsdtar->option_absolute_paths) {
+ /* Generate a warning the first time this happens. */
+ if (!bsdtar->warned_lead_slash) {
+ bsdtar_warnc(bsdtar, 0,
+ "Removing leading '/' from member names");
+ bsdtar->warned_lead_slash = 1;
+ }
+ name++;
+ /* Special case: Stripping leading '/' from "/" yields ".". */
+ if (*name == '\0')
+ 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);
+}
+
+/*
+ * 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.
+ */
+
+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);
+}
diff --git a/libarchive/libarchive-2.4.17/tar/write.c b/libarchive/libarchive-2.4.17/tar/write.c
new file mode 100644
index 0000000..3b8cc51
--- /dev/null
+++ b/libarchive/libarchive-2.4.17/tar/write.c
@@ -0,0 +1,1550 @@
+/*-
+ * 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/write.c,v 1.64 2008/02/19 05:27:17 kientzle Exp $");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_EXT2FS_EXT2_FS_H
+#include <ext2fs/ext2_fs.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h> /* for Linux file flags */
+#endif
+#ifdef HAVE_LINUX_EXT2_FS_H
+#include <linux/ext2_fs.h> /* for Linux file flags */
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "bsdtar.h"
+#include "tree.h"
+
+/* Fixed size of uname/gname caches. */
+#define name_cache_size 101
+
+static const char * const NO_NAME = "(noname)";
+
+/* Initial size of link cache. */
+#define links_cache_initial_size 1024
+
+struct archive_dir_entry {
+ struct archive_dir_entry *next;
+ time_t mtime_sec;
+ int mtime_nsec;
+ char *name;
+};
+
+struct archive_dir {
+ struct archive_dir_entry *head, *tail;
+};
+
+struct links_cache {
+ unsigned long number_entries;
+ size_t number_buckets;
+ struct links_entry **buckets;
+};
+
+struct links_entry {
+ struct links_entry *next;
+ struct links_entry *previous;
+ int links;
+ dev_t dev;
+ ino_t ino;
+ char *name;
+};
+
+struct name_cache {
+ int probes;
+ int hits;
+ size_t size;
+ struct {
+ id_t id;
+ const char *name;
+ } cache[name_cache_size];
+};
+
+static void add_dir_list(struct bsdtar *bsdtar, const char *path,
+ time_t mtime_sec, int mtime_nsec);
+static int append_archive(struct bsdtar *, struct archive *,
+ struct archive *ina);
+static int append_archive_filename(struct bsdtar *,
+ struct archive *, const char *fname);
+static void archive_names_from_file(struct bsdtar *bsdtar,
+ struct archive *a);
+static int archive_names_from_file_helper(struct bsdtar *bsdtar,
+ const char *line);
+static int copy_file_data(struct bsdtar *bsdtar,
+ struct archive *a, struct archive *ina);
+static void create_cleanup(struct bsdtar *);
+static void free_buckets(struct bsdtar *, struct links_cache *);
+static void free_cache(struct name_cache *cache);
+static const char * lookup_gname(struct bsdtar *bsdtar, gid_t gid);
+static int lookup_gname_helper(struct bsdtar *bsdtar,
+ const char **name, id_t gid);
+static void lookup_hardlink(struct bsdtar *,
+ struct archive_entry *entry, const struct stat *);
+static const char * lookup_uname(struct bsdtar *bsdtar, uid_t uid);
+static int lookup_uname_helper(struct bsdtar *bsdtar,
+ const char **name, id_t uid);
+static int new_enough(struct bsdtar *, const char *path,
+ const struct stat *);
+static void setup_acls(struct bsdtar *, struct archive_entry *,
+ const char *path);
+static void setup_xattrs(struct bsdtar *, struct archive_entry *,
+ const char *path);
+static void test_for_append(struct bsdtar *);
+static void write_archive(struct archive *, struct bsdtar *);
+static void write_entry(struct bsdtar *, struct archive *,
+ const struct stat *, const char *pathname,
+ const char *accpath);
+static int write_file_data(struct bsdtar *, struct archive *,
+ int fd);
+static void write_hierarchy(struct bsdtar *, struct archive *,
+ const char *);
+
+void
+tar_mode_c(struct bsdtar *bsdtar)
+{
+ struct archive *a;
+ int r;
+
+ if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
+ bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");
+
+ a = archive_write_new();
+
+ /* Support any format that the library supports. */
+ if (bsdtar->create_format == NULL) {
+ r = archive_write_set_format_pax_restricted(a);
+ bsdtar->create_format = "pax restricted";
+ } else {
+ r = archive_write_set_format_by_name(a, bsdtar->create_format);
+ }
+ if (r != ARCHIVE_OK) {
+ fprintf(stderr, "Can't use format %s: %s\n",
+ bsdtar->create_format,
+ archive_error_string(a));
+ usage(bsdtar);
+ }
+
+ /*
+ * If user explicitly set the block size, then assume they
+ * want the last block padded as well. Otherwise, use the
+ * default block size and accept archive_write_open_file()'s
+ * default padding decisions.
+ */
+ if (bsdtar->bytes_per_block != 0) {
+ archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
+ archive_write_set_bytes_in_last_block(a,
+ bsdtar->bytes_per_block);
+ } else
+ archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
+
+ if (bsdtar->compress_program) {
+ archive_write_set_compression_program(a, bsdtar->compress_program);
+ } else {
+ switch (bsdtar->create_compression) {
+ case 0:
+ archive_write_set_compression_none(a);
+ break;
+#ifdef HAVE_LIBBZ2
+ case 'j': case 'y':
+ archive_write_set_compression_bzip2(a);
+ break;
+#endif
+#ifdef HAVE_LIBZ
+ case 'z':
+ archive_write_set_compression_gzip(a);
+ break;
+#endif
+ default:
+ bsdtar_errc(bsdtar, 1, 0,
+ "Unrecognized compression option -%c",
+ bsdtar->create_compression);
+ }
+ }
+
+ r = archive_write_open_file(a, bsdtar->filename);
+ if (r != ARCHIVE_OK)
+ bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
+
+ write_archive(a, bsdtar);
+
+ if (bsdtar->option_totals) {
+ fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n",
+ (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a));
+ }
+
+ archive_write_finish(a);
+}
+
+/*
+ * Same as 'c', except we only support tar or empty formats in
+ * uncompressed files on disk.
+ */
+void
+tar_mode_r(struct bsdtar *bsdtar)
+{
+ off_t end_offset;
+ int format;
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
+
+ /* Sanity-test some arguments and the file. */
+ test_for_append(bsdtar);
+
+ format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
+
+ bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT, 0666);
+ if (bsdtar->fd < 0)
+ bsdtar_errc(bsdtar, 1, errno,
+ "Cannot open %s", bsdtar->filename);
+
+ a = archive_read_new();
+ archive_read_support_compression_all(a);
+ archive_read_support_format_tar(a);
+ archive_read_support_format_gnutar(a);
+ r = archive_read_open_fd(a, bsdtar->fd, 10240);
+ if (r != ARCHIVE_OK)
+ bsdtar_errc(bsdtar, 1, archive_errno(a),
+ "Can't read archive %s: %s", bsdtar->filename,
+ archive_error_string(a));
+ while (0 == archive_read_next_header(a, &entry)) {
+ if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
+ archive_read_finish(a);
+ close(bsdtar->fd);
+ bsdtar_errc(bsdtar, 1, 0,
+ "Cannot append to compressed archive.");
+ }
+ /* Keep going until we hit end-of-archive */
+ format = archive_format(a);
+ }
+
+ end_offset = archive_read_header_position(a);
+ archive_read_finish(a);
+
+ /* Re-open archive for writing */
+ a = archive_write_new();
+ archive_write_set_compression_none(a);
+ /*
+ * Set the format to be used for writing. To allow people to
+ * extend empty files, we need to allow them to specify the format,
+ * which opens the possibility that they will specify a format that
+ * doesn't match the existing format. Hence, the following bit
+ * of arcane ugliness.
+ */
+
+ if (bsdtar->create_format != NULL) {
+ /* If the user requested a format, use that, but ... */
+ archive_write_set_format_by_name(a,
+ bsdtar->create_format);
+ /* ... complain if it's not compatible. */
+ format &= ARCHIVE_FORMAT_BASE_MASK;
+ if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
+ && format != ARCHIVE_FORMAT_EMPTY) {
+ bsdtar_errc(bsdtar, 1, 0,
+ "Format %s is incompatible with the archive %s.",
+ bsdtar->create_format, bsdtar->filename);
+ }
+ } else {
+ /*
+ * Just preserve the current format, with a little care
+ * for formats that libarchive can't write.
+ */
+ if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
+ /* TODO: When gtar supports pax, use pax restricted. */
+ format = ARCHIVE_FORMAT_TAR_USTAR;
+ if (format == ARCHIVE_FORMAT_EMPTY)
+ format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
+ archive_write_set_format(a, format);
+ }
+ lseek(bsdtar->fd, end_offset, SEEK_SET); /* XXX check return val XXX */
+ archive_write_open_fd(a, bsdtar->fd); /* XXX check return val XXX */
+
+ write_archive(a, bsdtar); /* XXX check return val XXX */
+
+ if (bsdtar->option_totals) {
+ fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n",
+ (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a));
+ }
+
+ archive_write_finish(a);
+ close(bsdtar->fd);
+ bsdtar->fd = -1;
+}
+
+void
+tar_mode_u(struct bsdtar *bsdtar)
+{
+ off_t end_offset;
+ struct archive *a;
+ struct archive_entry *entry;
+ int format;
+ struct archive_dir_entry *p;
+ struct archive_dir archive_dir;
+
+ bsdtar->archive_dir = &archive_dir;
+ memset(&archive_dir, 0, sizeof(archive_dir));
+
+ format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
+
+ /* Sanity-test some arguments and the file. */
+ test_for_append(bsdtar);
+
+ bsdtar->fd = open(bsdtar->filename, O_RDWR);
+ if (bsdtar->fd < 0)
+ bsdtar_errc(bsdtar, 1, errno,
+ "Cannot open %s", bsdtar->filename);
+
+ a = archive_read_new();
+ archive_read_support_compression_all(a);
+ archive_read_support_format_tar(a);
+ archive_read_support_format_gnutar(a);
+ if (archive_read_open_fd(a, bsdtar->fd,
+ bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
+ DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
+ bsdtar_errc(bsdtar, 1, 0,
+ "Can't open %s: %s", bsdtar->filename,
+ archive_error_string(a));
+ }
+
+ /* Build a list of all entries and their recorded mod times. */
+ while (0 == archive_read_next_header(a, &entry)) {
+ if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
+ archive_read_finish(a);
+ close(bsdtar->fd);
+ bsdtar_errc(bsdtar, 1, 0,
+ "Cannot append to compressed archive.");
+ }
+ add_dir_list(bsdtar, archive_entry_pathname(entry),
+ archive_entry_mtime(entry),
+ archive_entry_mtime_nsec(entry));
+ /* Record the last format determination we see */
+ format = archive_format(a);
+ /* Keep going until we hit end-of-archive */
+ }
+
+ end_offset = archive_read_header_position(a);
+ archive_read_finish(a);
+
+ /* Re-open archive for writing. */
+ a = archive_write_new();
+ archive_write_set_compression_none(a);
+ /*
+ * Set format to same one auto-detected above, except that
+ * we don't write GNU tar format, so use ustar instead.
+ */
+ if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
+ format = ARCHIVE_FORMAT_TAR_USTAR;
+ archive_write_set_format(a, format);
+ if (bsdtar->bytes_per_block != 0) {
+ archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
+ archive_write_set_bytes_in_last_block(a,
+ bsdtar->bytes_per_block);
+ } else
+ archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
+ lseek(bsdtar->fd, end_offset, SEEK_SET);
+ ftruncate(bsdtar->fd, end_offset);
+ archive_write_open_fd(a, bsdtar->fd);
+
+ write_archive(a, bsdtar);
+
+ if (bsdtar->option_totals) {
+ fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n",
+ (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a));
+ }
+
+ archive_write_finish(a);
+ close(bsdtar->fd);
+ bsdtar->fd = -1;
+
+ while (bsdtar->archive_dir->head != NULL) {
+ p = bsdtar->archive_dir->head->next;
+ free(bsdtar->archive_dir->head->name);
+ free(bsdtar->archive_dir->head);
+ bsdtar->archive_dir->head = p;
+ }
+ bsdtar->archive_dir->tail = NULL;
+}
+
+
+/*
+ * Write user-specified files/dirs to opened archive.
+ */
+static void
+write_archive(struct archive *a, struct bsdtar *bsdtar)
+{
+ const char *arg;
+
+ if (bsdtar->names_from_file != NULL)
+ archive_names_from_file(bsdtar, a);
+
+ while (*bsdtar->argv) {
+ arg = *bsdtar->argv;
+ if (arg[0] == '-' && arg[1] == 'C') {
+ arg += 2;
+ if (*arg == '\0') {
+ bsdtar->argv++;
+ arg = *bsdtar->argv;
+ if (arg == NULL) {
+ bsdtar_warnc(bsdtar, 1, 0,
+ "Missing argument for -C");
+ bsdtar->return_value = 1;
+ return;
+ }
+ }
+ set_chdir(bsdtar, arg);
+ } else {
+ if (*arg != '/' && (arg[0] != '@' || arg[1] != '/'))
+ do_chdir(bsdtar); /* Handle a deferred -C */
+ if (*arg == '@') {
+ if (append_archive_filename(bsdtar, a,
+ arg + 1) != 0)
+ break;
+ } else
+ write_hierarchy(bsdtar, a, arg);
+ }
+ bsdtar->argv++;
+ }
+
+ create_cleanup(bsdtar);
+ if (archive_write_close(a)) {
+ bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ bsdtar->return_value = 1;
+ }
+}
+
+/*
+ * Archive names specified in file.
+ *
+ * Unless --null was specified, a line containing exactly "-C" will
+ * cause the next line to be a directory to pass to chdir(). If
+ * --null is specified, then a line "-C" is just another filename.
+ */
+void
+archive_names_from_file(struct bsdtar *bsdtar, struct archive *a)
+{
+ bsdtar->archive = a;
+
+ bsdtar->next_line_is_dir = 0;
+ process_lines(bsdtar, bsdtar->names_from_file,
+ archive_names_from_file_helper);
+ if (bsdtar->next_line_is_dir)
+ bsdtar_errc(bsdtar, 1, errno,
+ "Unexpected end of filename list; "
+ "directory expected after -C");
+}
+
+static int
+archive_names_from_file_helper(struct bsdtar *bsdtar, const char *line)
+{
+ if (bsdtar->next_line_is_dir) {
+ set_chdir(bsdtar, line);
+ bsdtar->next_line_is_dir = 0;
+ } else if (!bsdtar->option_null && strcmp(line, "-C") == 0)
+ bsdtar->next_line_is_dir = 1;
+ else {
+ if (*line != '/')
+ do_chdir(bsdtar); /* Handle a deferred -C */
+ write_hierarchy(bsdtar, bsdtar->archive, line);
+ }
+ return (0);
+}
+
+/*
+ * Copy from specified archive to current archive. Returns non-zero
+ * for write errors (which force us to terminate the entire archiving
+ * operation). If there are errors reading the input archive, we set
+ * bsdtar->return_value but return zero, so the overall archiving
+ * operation will complete and return non-zero.
+ */
+static int
+append_archive_filename(struct bsdtar *bsdtar, struct archive *a,
+ const char *filename)
+{
+ struct archive *ina;
+ int rc;
+
+ if (strcmp(filename, "-") == 0)
+ filename = NULL; /* Library uses NULL for stdio. */
+
+ ina = archive_read_new();
+ archive_read_support_format_all(ina);
+ archive_read_support_compression_all(ina);
+ if (archive_read_open_file(ina, filename, 10240)) {
+ bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(ina));
+ bsdtar->return_value = 1;
+ return (0);
+ }
+
+ rc = append_archive(bsdtar, a, ina);
+
+ if (archive_errno(ina)) {
+ bsdtar_warnc(bsdtar, 0, "Error reading archive %s: %s",
+ filename, archive_error_string(ina));
+ bsdtar->return_value = 1;
+ }
+ archive_read_finish(ina);
+
+ return (rc);
+}
+
+static int
+append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
+{
+ struct archive_entry *in_entry;
+ int e;
+
+ while (0 == archive_read_next_header(ina, &in_entry)) {
+ if (!new_enough(bsdtar, archive_entry_pathname(in_entry),
+ archive_entry_stat(in_entry)))
+ continue;
+ if (excluded(bsdtar, archive_entry_pathname(in_entry)))
+ continue;
+ if (bsdtar->option_interactive &&
+ !yes("copy '%s'", archive_entry_pathname(in_entry)))
+ continue;
+ if (bsdtar->verbose)
+ safe_fprintf(stderr, "a %s",
+ archive_entry_pathname(in_entry));
+
+ e = archive_write_header(a, in_entry);
+ if (e != ARCHIVE_OK) {
+ if (!bsdtar->verbose)
+ bsdtar_warnc(bsdtar, 0, "%s: %s",
+ archive_entry_pathname(in_entry),
+ archive_error_string(a));
+ else
+ fprintf(stderr, ": %s", archive_error_string(a));
+ }
+ if (e == ARCHIVE_FATAL)
+ exit(1);
+
+ if (e >= ARCHIVE_WARN)
+ if (copy_file_data(bsdtar, a, ina))
+ exit(1);
+
+ if (bsdtar->verbose)
+ fprintf(stderr, "\n");
+ }
+
+ /* Note: If we got here, we saw no write errors, so return success. */
+ return (0);
+}
+
+/* Helper function to copy data between archives. */
+static int
+copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
+{
+ char buff[64*1024];
+ ssize_t bytes_read;
+ ssize_t bytes_written;
+
+ bytes_read = archive_read_data(ina, buff, sizeof(buff));
+ while (bytes_read > 0) {
+ bytes_written = archive_write_data(a, buff, bytes_read);
+ if (bytes_written < bytes_read) {
+ bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ return (-1);
+ }
+ bytes_read = archive_read_data(ina, buff, sizeof(buff));
+ }
+
+ return (0);
+}
+
+/*
+ * Add the file or dir hierarchy named by 'path' to the archive
+ */
+static void
+write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
+{
+ struct tree *tree;
+ char symlink_mode = bsdtar->symlink_mode;
+ dev_t first_dev = 0;
+ int dev_recorded = 0;
+ int tree_ret;
+#ifdef __linux
+ int fd, r;
+ unsigned long fflags;
+#endif
+
+ tree = tree_open(path);
+
+ if (!tree) {
+ bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path);
+ bsdtar->return_value = 1;
+ return;
+ }
+
+ while ((tree_ret = tree_next(tree))) {
+ const char *name = tree_current_path(tree);
+ const struct stat *st = NULL, *lst = NULL;
+ int descend;
+
+ if (tree_ret == TREE_ERROR_DIR)
+ bsdtar_warnc(bsdtar, errno, "%s: Couldn't visit directory", name);
+ if (tree_ret != TREE_REGULAR)
+ continue;
+ lst = tree_current_lstat(tree);
+ if (lst == NULL) {
+ /* Couldn't lstat(); must not exist. */
+ bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
+
+ /*
+ * Report an error via the exit code if the failed
+ * path is a prefix of what the user provided via
+ * the command line. (Testing for string equality
+ * here won't work due to trailing '/' characters.)
+ */
+ if (memcmp(name, path, strlen(name)) == 0)
+ bsdtar->return_value = 1;
+
+ continue;
+ }
+ if (S_ISLNK(lst->st_mode))
+ st = tree_current_stat(tree);
+ /* Default: descend into any dir or symlink to dir. */
+ /* We'll adjust this later on. */
+ descend = 0;
+ if ((st != NULL) && S_ISDIR(st->st_mode))
+ descend = 1;
+ if ((lst != NULL) && S_ISDIR(lst->st_mode))
+ descend = 1;
+
+ /*
+ * If user has asked us not to cross mount points,
+ * then don't descend into into a dir on a different
+ * device.
+ */
+ if (!dev_recorded) {
+ first_dev = lst->st_dev;
+ dev_recorded = 1;
+ }
+ if (bsdtar->option_dont_traverse_mounts) {
+ if (lst != NULL && lst->st_dev != first_dev)
+ descend = 0;
+ }
+
+ /*
+ * If this file/dir is flagged "nodump" and we're
+ * honoring such flags, skip this file/dir.
+ */
+#ifdef HAVE_CHFLAGS
+ if (bsdtar->option_honor_nodump &&
+ (lst->st_flags & UF_NODUMP))
+ continue;
+#endif
+
+#ifdef __linux
+ /*
+ * Linux has a nodump flag too but to read it
+ * we have to open() the file/dir and do an ioctl on it...
+ */
+ if (bsdtar->option_honor_nodump &&
+ ((fd = open(name, O_RDONLY|O_NONBLOCK)) >= 0) &&
+ ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &fflags)),
+ close(fd), r) >= 0 &&
+ (fflags & EXT2_NODUMP_FL))
+ continue;
+#endif
+
+ /*
+ * If this file/dir is excluded by a filename
+ * pattern, skip it.
+ */
+ if (excluded(bsdtar, name))
+ continue;
+
+ /*
+ * If the user vetoes this file/directory, skip it.
+ */
+ if (bsdtar->option_interactive &&
+ !yes("add '%s'", name))
+ continue;
+
+ /*
+ * If this is a dir, decide whether or not to recurse.
+ */
+ if (bsdtar->option_no_subdirs)
+ descend = 0;
+
+ /*
+ * Distinguish 'L'/'P'/'H' symlink following.
+ */
+ switch(symlink_mode) {
+ case 'H':
+ /* 'H': After the first item, rest like 'P'. */
+ symlink_mode = 'P';
+ /* 'H': First item (from command line) like 'L'. */
+ /* FALLTHROUGH */
+ case 'L':
+ /* 'L': Do descend through a symlink to dir. */
+ /* 'L': Archive symlink to file as file. */
+ lst = tree_current_stat(tree);
+ /* If stat fails, we have a broken symlink;
+ * in that case, archive the link as such. */
+ if (lst == NULL)
+ lst = tree_current_lstat(tree);
+ break;
+ default:
+ /* 'P': Don't descend through a symlink to dir. */
+ if (!S_ISDIR(lst->st_mode))
+ descend = 0;
+ /* 'P': Archive symlink to file as symlink. */
+ /* lst = tree_current_lstat(tree); */
+ break;
+ }
+
+ if (descend)
+ tree_descend(tree);
+
+ /*
+ * Write the entry. Note that write_entry() handles
+ * pathname editing and newness testing.
+ */
+ write_entry(bsdtar, a, lst, name,
+ tree_current_access_path(tree));
+ }
+ tree_close(tree);
+}
+
+/*
+ * Add a single filesystem object to the archive.
+ */
+static void
+write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st,
+ const char *pathname, const char *accpath)
+{
+ struct archive_entry *entry;
+ int e;
+ int fd;
+#ifdef __linux
+ int r;
+ unsigned long stflags;
+#endif
+ static char linkbuffer[PATH_MAX+1];
+
+ fd = -1;
+ entry = archive_entry_new();
+
+ archive_entry_set_pathname(entry, pathname);
+
+ /*
+ * Rewrite the pathname to be archived. If rewrite
+ * fails, skip the entry.
+ */
+ if (edit_pathname(bsdtar, entry))
+ goto abort;
+
+ /*
+ * In -u mode, check that the file is newer than what's
+ * already in the archive; in all modes, obey --newerXXX flags.
+ */
+ if (!new_enough(bsdtar, archive_entry_pathname(entry), st))
+ goto abort;
+
+ if (!S_ISDIR(st->st_mode) && (st->st_nlink > 1))
+ lookup_hardlink(bsdtar, entry, st);
+
+ /* Display entry as we process it. This format is required by SUSv2. */
+ if (bsdtar->verbose)
+ safe_fprintf(stderr, "a %s", archive_entry_pathname(entry));
+
+ /* Read symbolic link information. */
+ if ((st->st_mode & S_IFMT) == S_IFLNK) {
+ int lnklen;
+
+ lnklen = readlink(accpath, linkbuffer, PATH_MAX);
+ if (lnklen < 0) {
+ if (!bsdtar->verbose)
+ bsdtar_warnc(bsdtar, errno,
+ "%s: Couldn't read symbolic link",
+ pathname);
+ else
+ safe_fprintf(stderr,
+ ": Couldn't read symbolic link: %s",
+ strerror(errno));
+ goto cleanup;
+ }
+ linkbuffer[lnklen] = 0;
+ archive_entry_set_symlink(entry, linkbuffer);
+ }
+
+ /* Look up username and group name. */
+ archive_entry_set_uname(entry, lookup_uname(bsdtar, st->st_uid));
+ archive_entry_set_gname(entry, lookup_gname(bsdtar, st->st_gid));
+
+#ifdef HAVE_CHFLAGS
+ if (st->st_flags != 0)
+ archive_entry_set_fflags(entry, st->st_flags, 0);
+#endif
+
+#ifdef __linux
+ if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) &&
+ ((fd = open(accpath, O_RDONLY|O_NONBLOCK)) >= 0) &&
+ ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags)), close(fd), (fd = -1), r) >= 0 &&
+ stflags) {
+ archive_entry_set_fflags(entry, stflags, 0);
+ }
+#endif
+
+ archive_entry_copy_stat(entry, st);
+ setup_acls(bsdtar, entry, accpath);
+ setup_xattrs(bsdtar, entry, accpath);
+
+ /*
+ * If it's a regular file (and non-zero in size) make sure we
+ * can open it before we start to write. In particular, note
+ * that we can always archive a zero-length file, even if we
+ * can't read it.
+ */
+ if (S_ISREG(st->st_mode) && st->st_size > 0) {
+ fd = open(accpath, O_RDONLY);
+ if (fd < 0) {
+ if (!bsdtar->verbose)
+ bsdtar_warnc(bsdtar, errno, "%s: could not open file", pathname);
+ else
+ fprintf(stderr, ": %s", strerror(errno));
+ goto cleanup;
+ }
+ }
+
+ /* Non-regular files get archived with zero size. */
+ if (!S_ISREG(st->st_mode))
+ archive_entry_set_size(entry, 0);
+
+ e = archive_write_header(a, entry);
+ if (e != ARCHIVE_OK) {
+ if (!bsdtar->verbose)
+ bsdtar_warnc(bsdtar, 0, "%s: %s", pathname,
+ archive_error_string(a));
+ else
+ fprintf(stderr, ": %s", archive_error_string(a));
+ }
+
+ if (e == ARCHIVE_FATAL)
+ exit(1);
+
+ /*
+ * If we opened a file earlier, write it out now. Note that
+ * the format handler might have reset the size field to zero
+ * to inform us that the archive body won't get stored. In
+ * that case, just skip the write.
+ */
+ if (e >= ARCHIVE_WARN && fd >= 0 && archive_entry_size(entry) > 0)
+ if (write_file_data(bsdtar, a, fd))
+ exit(1);
+
+cleanup:
+ if (bsdtar->verbose)
+ fprintf(stderr, "\n");
+
+abort:
+ if (fd >= 0)
+ close(fd);
+
+ if (entry != NULL)
+ archive_entry_free(entry);
+}
+
+
+/* Helper function to copy file to archive, with stack-allocated buffer. */
+static int
+write_file_data(struct bsdtar *bsdtar, struct archive *a, int fd)
+{
+ char buff[64*1024];
+ ssize_t bytes_read;
+ ssize_t bytes_written;
+
+ /* XXX TODO: Allocate buffer on heap and store pointer to
+ * it in bsdtar structure; arrange cleanup as well. XXX */
+
+ bytes_read = read(fd, buff, sizeof(buff));
+ while (bytes_read > 0) {
+ bytes_written = archive_write_data(a, buff, bytes_read);
+ if (bytes_written < 0) {
+ /* Write failed; this is bad */
+ bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ return (-1);
+ }
+ if (bytes_written < bytes_read) {
+ /* Write was truncated; warn but continue. */
+ bsdtar_warnc(bsdtar, 0,
+ "Truncated write; file may have grown while being archived.");
+ return (0);
+ }
+ bytes_read = read(fd, buff, sizeof(buff));
+ }
+ return 0;
+}
+
+
+static void
+create_cleanup(struct bsdtar *bsdtar)
+{
+ /* Free inode->pathname map used for hardlink detection. */
+ if (bsdtar->links_cache != NULL) {
+ free_buckets(bsdtar, bsdtar->links_cache);
+ free(bsdtar->links_cache);
+ bsdtar->links_cache = NULL;
+ }
+
+ free_cache(bsdtar->uname_cache);
+ bsdtar->uname_cache = NULL;
+ free_cache(bsdtar->gname_cache);
+ bsdtar->gname_cache = NULL;
+}
+
+
+static void
+free_buckets(struct bsdtar *bsdtar, struct links_cache *links_cache)
+{
+ size_t i;
+
+ if (links_cache->buckets == NULL)
+ return;
+
+ for (i = 0; i < links_cache->number_buckets; i++) {
+ while (links_cache->buckets[i] != NULL) {
+ struct links_entry *lp = links_cache->buckets[i]->next;
+ if (bsdtar->option_warn_links)
+ bsdtar_warnc(bsdtar, 0, "Missing links to %s",
+ links_cache->buckets[i]->name);
+ if (links_cache->buckets[i]->name != NULL)
+ free(links_cache->buckets[i]->name);
+ free(links_cache->buckets[i]);
+ links_cache->buckets[i] = lp;
+ }
+ }
+ free(links_cache->buckets);
+ links_cache->buckets = NULL;
+}
+
+static void
+lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const struct stat *st)
+{
+ struct links_cache *links_cache;
+ struct links_entry *le, **new_buckets;
+ int hash;
+ size_t i, new_size;
+
+ /* If necessary, initialize the links cache. */
+ links_cache = bsdtar->links_cache;
+ if (links_cache == NULL) {
+ bsdtar->links_cache = malloc(sizeof(struct links_cache));
+ if (bsdtar->links_cache == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM,
+ "No memory for hardlink detection.");
+ links_cache = bsdtar->links_cache;
+ memset(links_cache, 0, sizeof(struct links_cache));
+ links_cache->number_buckets = links_cache_initial_size;
+ links_cache->buckets = malloc(links_cache->number_buckets *
+ sizeof(links_cache->buckets[0]));
+ if (links_cache->buckets == NULL) {
+ bsdtar_errc(bsdtar, 1, ENOMEM,
+ "No memory for hardlink detection.");
+ }
+ for (i = 0; i < links_cache->number_buckets; i++)
+ links_cache->buckets[i] = NULL;
+ }
+
+ /* If the links cache overflowed and got flushed, don't bother. */
+ if (links_cache->buckets == NULL)
+ return;
+
+ /* If the links cache is getting too full, enlarge the hash table. */
+ if (links_cache->number_entries > links_cache->number_buckets * 2)
+ {
+ new_size = links_cache->number_buckets * 2;
+ new_buckets = malloc(new_size * sizeof(struct links_entry *));
+
+ if (new_buckets != NULL) {
+ memset(new_buckets, 0,
+ new_size * sizeof(struct links_entry *));
+ for (i = 0; i < links_cache->number_buckets; i++) {
+ while (links_cache->buckets[i] != NULL) {
+ /* Remove entry from old bucket. */
+ le = links_cache->buckets[i];
+ links_cache->buckets[i] = le->next;
+
+ /* Add entry to new bucket. */
+ hash = (le->dev ^ le->ino) % new_size;
+
+ if (new_buckets[hash] != NULL)
+ new_buckets[hash]->previous =
+ le;
+ le->next = new_buckets[hash];
+ le->previous = NULL;
+ new_buckets[hash] = le;
+ }
+ }
+ free(links_cache->buckets);
+ links_cache->buckets = new_buckets;
+ links_cache->number_buckets = new_size;
+ } else {
+ free_buckets(bsdtar, links_cache);
+ bsdtar_warnc(bsdtar, ENOMEM,
+ "No more memory for recording hard links");
+ bsdtar_warnc(bsdtar, 0,
+ "Remaining links will be dumped as full files");
+ }
+ }
+
+ /* Try to locate this entry in the links cache. */
+ hash = ( st->st_dev ^ st->st_ino ) % links_cache->number_buckets;
+ for (le = links_cache->buckets[hash]; le != NULL; le = le->next) {
+ if (le->dev == st->st_dev && le->ino == st->st_ino) {
+ archive_entry_copy_hardlink(entry, le->name);
+
+ /*
+ * Decrement link count each time and release
+ * the entry if it hits zero. This saves
+ * memory and is necessary for proper -l
+ * implementation.
+ */
+ if (--le->links <= 0) {
+ if (le->previous != NULL)
+ le->previous->next = le->next;
+ if (le->next != NULL)
+ le->next->previous = le->previous;
+ if (le->name != NULL)
+ free(le->name);
+ if (links_cache->buckets[hash] == le)
+ links_cache->buckets[hash] = le->next;
+ links_cache->number_entries--;
+ free(le);
+ }
+
+ return;
+ }
+ }
+
+ /* Add this entry to the links cache. */
+ le = malloc(sizeof(struct links_entry));
+ if (le != NULL)
+ le->name = strdup(archive_entry_pathname(entry));
+ if ((le == NULL) || (le->name == NULL)) {
+ free_buckets(bsdtar, links_cache);
+ bsdtar_warnc(bsdtar, ENOMEM,
+ "No more memory for recording hard links");
+ bsdtar_warnc(bsdtar, 0,
+ "Remaining hard links will be dumped as full files");
+ if (le != NULL)
+ free(le);
+ return;
+ }
+ if (links_cache->buckets[hash] != NULL)
+ links_cache->buckets[hash]->previous = le;
+ links_cache->number_entries++;
+ le->next = links_cache->buckets[hash];
+ le->previous = NULL;
+ links_cache->buckets[hash] = le;
+ le->dev = st->st_dev;
+ le->ino = st->st_ino;
+ le->links = st->st_nlink - 1;
+}
+
+#ifdef HAVE_POSIX_ACL
+static void setup_acl(struct bsdtar *bsdtar,
+ struct archive_entry *entry, const char *accpath,
+ int acl_type, int archive_entry_acl_type);
+
+static void
+setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const char *accpath)
+{
+ archive_entry_acl_clear(entry);
+
+ setup_acl(bsdtar, entry, accpath,
+ ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ /* Only directories can have default ACLs. */
+ if (S_ISDIR(archive_entry_mode(entry)))
+ setup_acl(bsdtar, entry, accpath,
+ ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+}
+
+static void
+setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const char *accpath, int acl_type, int archive_entry_acl_type)
+{
+ acl_t acl;
+ acl_tag_t acl_tag;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ int s, ae_id, ae_tag, ae_perm;
+ const char *ae_name;
+
+ /* Retrieve access ACL from file. */
+ acl = acl_get_file(accpath, acl_type);
+ if (acl != NULL) {
+ s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
+ while (s == 1) {
+ ae_id = -1;
+ ae_name = NULL;
+
+ acl_get_tag_type(acl_entry, &acl_tag);
+ if (acl_tag == ACL_USER) {
+ ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
+ ae_name = lookup_uname(bsdtar, ae_id);
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ } else if (acl_tag == ACL_GROUP) {
+ ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
+ ae_name = lookup_gname(bsdtar, ae_id);
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ } else if (acl_tag == ACL_MASK) {
+ ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+ } else if (acl_tag == ACL_USER_OBJ) {
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ } else if (acl_tag == ACL_GROUP_OBJ) {
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ } else if (acl_tag == ACL_OTHER) {
+ ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+ } else {
+ /* Skip types that libarchive can't support. */
+ continue;
+ }
+
+ acl_get_permset(acl_entry, &acl_permset);
+ ae_perm = 0;
+ /*
+ * acl_get_perm() is spelled differently on different
+ * platforms; see bsdtar_platform.h for details.
+ */
+ if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
+ ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ if (ACL_GET_PERM(acl_permset, ACL_READ))
+ ae_perm |= ARCHIVE_ENTRY_ACL_READ;
+ if (ACL_GET_PERM(acl_permset, ACL_WRITE))
+ ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+
+ archive_entry_acl_add_entry(entry,
+ archive_entry_acl_type, ae_perm, ae_tag,
+ ae_id, ae_name);
+
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ }
+ acl_free(acl);
+ }
+}
+#else
+static void
+setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const char *accpath)
+{
+ (void)bsdtar;
+ (void)entry;
+ (void)accpath;
+}
+#endif
+
+#if HAVE_LISTXATTR && HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR
+
+static void
+setup_xattr(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const char *accpath, const char *name)
+{
+ size_t size;
+ void *value = NULL;
+ char symlink_mode = bsdtar->symlink_mode;
+
+ if (symlink_mode == 'H')
+ size = getxattr(accpath, name, NULL, 0);
+ else
+ size = lgetxattr(accpath, name, NULL, 0);
+
+ if (size == -1) {
+ bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute");
+ return;
+ }
+
+ if (size > 0 && (value = malloc(size)) == NULL) {
+ bsdtar_errc(bsdtar, 1, errno, "Out of memory");
+ return;
+ }
+
+ if (symlink_mode == 'H')
+ size = getxattr(accpath, name, value, size);
+ else
+ size = lgetxattr(accpath, name, value, size);
+
+ if (size == -1) {
+ bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute");
+ return;
+ }
+
+ archive_entry_xattr_add_entry(entry, name, value, size);
+
+ free(value);
+}
+
+/*
+ * Linux extended attribute support
+ */
+static void
+setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const char *accpath)
+{
+ char *list, *p;
+ size_t list_size;
+ char symlink_mode = bsdtar->symlink_mode;
+
+ if (symlink_mode == 'H')
+ list_size = listxattr(accpath, NULL, 0);
+ else
+ list_size = llistxattr(accpath, NULL, 0);
+
+ if (list_size == -1) {
+ bsdtar_warnc(bsdtar, errno,
+ "Couldn't list extended attributes");
+ return;
+ } else if (list_size == 0)
+ return;
+
+ if ((list = malloc(list_size)) == NULL) {
+ bsdtar_errc(bsdtar, 1, errno, "Out of memory");
+ return;
+ }
+
+ if (symlink_mode == 'H')
+ list_size = listxattr(accpath, list, list_size);
+ else
+ list_size = llistxattr(accpath, list, list_size);
+
+ if (list_size == -1) {
+ bsdtar_warnc(bsdtar, errno,
+ "Couldn't list extended attributes");
+ free(list);
+ return;
+ }
+
+ for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
+ if (strncmp(p, "system.", 7) == 0 ||
+ strncmp(p, "xfsroot.", 8) == 0)
+ continue;
+
+ setup_xattr(bsdtar, entry, accpath, p);
+ }
+
+ free(list);
+}
+
+#else
+
+/*
+ * Generic (stub) extended attribute support.
+ */
+static void
+setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry,
+ const char *accpath)
+{
+ (void)bsdtar; /* UNUSED */
+ (void)entry; /* UNUSED */
+ (void)accpath; /* UNUSED */
+}
+
+#endif
+
+static void
+free_cache(struct name_cache *cache)
+{
+ size_t i;
+
+ if (cache != NULL) {
+ for (i = 0; i < cache->size; i++) {
+ if (cache->cache[i].name != NULL &&
+ cache->cache[i].name != NO_NAME)
+ free((void *)(uintptr_t)cache->cache[i].name);
+ }
+ free(cache);
+ }
+}
+
+/*
+ * Lookup uid/gid from uname/gname, return NULL if no match.
+ */
+static const char *
+lookup_name(struct bsdtar *bsdtar, struct name_cache **name_cache_variable,
+ int (*lookup_fn)(struct bsdtar *, const char **, id_t), id_t id)
+{
+ struct name_cache *cache;
+ const char *name;
+ int slot;
+
+
+ if (*name_cache_variable == NULL) {
+ *name_cache_variable = malloc(sizeof(struct name_cache));
+ if (*name_cache_variable == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM, "No more memory");
+ memset(*name_cache_variable, 0, sizeof(struct name_cache));
+ (*name_cache_variable)->size = name_cache_size;
+ }
+
+ cache = *name_cache_variable;
+ cache->probes++;
+
+ slot = id % cache->size;
+ if (cache->cache[slot].name != NULL) {
+ if (cache->cache[slot].id == id) {
+ cache->hits++;
+ if (cache->cache[slot].name == NO_NAME)
+ return (NULL);
+ return (cache->cache[slot].name);
+ }
+ if (cache->cache[slot].name != NO_NAME)
+ free((void *)(uintptr_t)cache->cache[slot].name);
+ cache->cache[slot].name = NULL;
+ }
+
+ if (lookup_fn(bsdtar, &name, id) == 0) {
+ if (name == NULL || name[0] == '\0') {
+ /* Cache the negative response. */
+ cache->cache[slot].name = NO_NAME;
+ cache->cache[slot].id = id;
+ } else {
+ cache->cache[slot].name = strdup(name);
+ if (cache->cache[slot].name != NULL) {
+ cache->cache[slot].id = id;
+ return (cache->cache[slot].name);
+ }
+ /*
+ * Conveniently, NULL marks an empty slot, so
+ * if the strdup() fails, we've just failed to
+ * cache it. No recovery necessary.
+ */
+ }
+ }
+ return (NULL);
+}
+
+static const char *
+lookup_uname(struct bsdtar *bsdtar, uid_t uid)
+{
+ return (lookup_name(bsdtar, &bsdtar->uname_cache,
+ &lookup_uname_helper, (id_t)uid));
+}
+
+static int
+lookup_uname_helper(struct bsdtar *bsdtar, const char **name, id_t id)
+{
+ struct passwd *pwent;
+
+ (void)bsdtar; /* UNUSED */
+
+ errno = 0;
+ pwent = getpwuid((uid_t)id);
+ if (pwent == NULL) {
+ *name = NULL;
+ if (errno != 0)
+ bsdtar_warnc(bsdtar, errno, "getpwuid(%d) failed", id);
+ return (errno);
+ }
+
+ *name = pwent->pw_name;
+ return (0);
+}
+
+static const char *
+lookup_gname(struct bsdtar *bsdtar, gid_t gid)
+{
+ return (lookup_name(bsdtar, &bsdtar->gname_cache,
+ &lookup_gname_helper, (id_t)gid));
+}
+
+static int
+lookup_gname_helper(struct bsdtar *bsdtar, const char **name, id_t id)
+{
+ struct group *grent;
+
+ (void)bsdtar; /* UNUSED */
+
+ errno = 0;
+ grent = getgrgid((gid_t)id);
+ if (grent == NULL) {
+ *name = NULL;
+ if (errno != 0)
+ bsdtar_warnc(bsdtar, errno, "getgrgid(%d) failed", id);
+ return (errno);
+ }
+
+ *name = grent->gr_name;
+ return (0);
+}
+
+/*
+ * Test if the specified file is new enough to include in the archive.
+ */
+int
+new_enough(struct bsdtar *bsdtar, const char *path, const struct stat *st)
+{
+ struct archive_dir_entry *p;
+
+ /*
+ * If this file/dir is excluded by a time comparison, skip it.
+ */
+ if (bsdtar->newer_ctime_sec > 0) {
+ if (st->st_ctime < bsdtar->newer_ctime_sec)
+ return (0); /* Too old, skip it. */
+ if (st->st_ctime == bsdtar->newer_ctime_sec
+ && ARCHIVE_STAT_CTIME_NANOS(st)
+ <= bsdtar->newer_ctime_nsec)
+ return (0); /* Too old, skip it. */
+ }
+ if (bsdtar->newer_mtime_sec > 0) {
+ if (st->st_mtime < bsdtar->newer_mtime_sec)
+ return (0); /* Too old, skip it. */
+ if (st->st_mtime == bsdtar->newer_mtime_sec
+ && ARCHIVE_STAT_MTIME_NANOS(st)
+ <= bsdtar->newer_mtime_nsec)
+ return (0); /* Too old, skip it. */
+ }
+
+ /*
+ * In -u mode, we only write an entry if it's newer than
+ * what was already in the archive.
+ */
+ if (bsdtar->archive_dir != NULL &&
+ bsdtar->archive_dir->head != NULL) {
+ for (p = bsdtar->archive_dir->head; p != NULL; p = p->next) {
+ if (pathcmp(path, p->name)==0)
+ return (p->mtime_sec < st->st_mtime ||
+ (p->mtime_sec == st->st_mtime &&
+ p->mtime_nsec
+ < ARCHIVE_STAT_MTIME_NANOS(st)));
+ }
+ }
+
+ /* If the file wasn't rejected, include it. */
+ return (1);
+}
+
+/*
+ * Add an entry to the dir list for 'u' mode.
+ *
+ * XXX TODO: Make this fast.
+ */
+static void
+add_dir_list(struct bsdtar *bsdtar, const char *path,
+ time_t mtime_sec, int mtime_nsec)
+{
+ struct archive_dir_entry *p;
+
+ /*
+ * Search entire list to see if this file has appeared before.
+ * If it has, override the timestamp data.
+ */
+ p = bsdtar->archive_dir->head;
+ while (p != NULL) {
+ if (strcmp(path, p->name)==0) {
+ p->mtime_sec = mtime_sec;
+ p->mtime_nsec = mtime_nsec;
+ return;
+ }
+ p = p->next;
+ }
+
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read archive directory");
+
+ p->name = strdup(path);
+ if (p->name == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read archive directory");
+ p->mtime_sec = mtime_sec;
+ p->mtime_nsec = mtime_nsec;
+ p->next = NULL;
+ if (bsdtar->archive_dir->tail == NULL) {
+ bsdtar->archive_dir->head = bsdtar->archive_dir->tail = p;
+ } else {
+ bsdtar->archive_dir->tail->next = p;
+ bsdtar->archive_dir->tail = p;
+ }
+}
+
+void
+test_for_append(struct bsdtar *bsdtar)
+{
+ struct stat s;
+
+ if (*bsdtar->argv == NULL)
+ bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");
+ if (bsdtar->filename == NULL)
+ bsdtar_errc(bsdtar, 1, 0, "Cannot append to stdout.");
+
+ if (bsdtar->create_compression != 0)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Cannot append to %s with compression", bsdtar->filename);
+
+ if (stat(bsdtar->filename, &s) != 0)
+ return;
+
+ if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode))
+ bsdtar_errc(bsdtar, 1, 0,
+ "Cannot append to %s: not a regular file.",
+ bsdtar->filename);
+}