]> Zhao Yanbai Git Server - minix.git/commitdiff
Replace Minix tar with pax's tar
authorArun Thomas <arun@minix3.org>
Wed, 24 Feb 2010 11:58:10 +0000 (11:58 +0000)
committerArun Thomas <arun@minix3.org>
Wed, 24 Feb 2010 11:58:10 +0000 (11:58 +0000)
commands/pax/Makefile
commands/pax/build [deleted file]
commands/pax/cpio.1 [new file with mode: 0644]
commands/pax/options.c
commands/pax/pax.1 [new file with mode: 0644]
commands/pax/pax.c
commands/pax/pax.h
commands/pax/tar.1 [new file with mode: 0644]
commands/simple/Makefile
commands/simple/tar.c [deleted file]

index f0611b4c2b7daae1a1bcc77d81b33f05d3145394..255f70e1502be7ec65e97510eb4202bf2064e966 100644 (file)
@@ -1,21 +1,42 @@
-# Makefile for pax
+#       @(#)Makefile   8.1 (Berkeley) 5/31/93
+# $FreeBSD$
 
-CC = exec cc
-CFLAGS = -O -D_POSIX_SOURCE -DNET2_STAT=1 -D_MINIX=1
-LDFLAGS= -i
+# To install on versions prior to BSD 4.4 the following may have to be
+# defined with CFLAGS +=
+#
+# -DNET2_STAT  Use NET2 or older stat structure. The version of the
+#              stat structure is easily determined by looking at the
+#              basic type of an off_t (often defined in the file:
+#              /usr/include/sys/types.h). If off_t is a long (and is
+#              NOT A quad) then you must define NET2_STAT.
+#              This define is important, as if you do have a quad_t
+#              off_t and define NET2_STAT, pax will compile but will
+#              NOT RUN PROPERLY.
+#
+# -DNET2_FTS   Use the older NET2 fts. To identify the version,
+#              examine the file: /usr/include/fts.h. If FTS_COMFOLLOW
+#              is not defined then you must define NET2_FTS.
+#              Pax may not compile if this not (un)defined properly.
+#
+# -DNET2_REGEX Use the older regexp.h not regex.h. The regex version
+#              is determined by looking at the value returned by
+#              regexec() (man 3 regexec). If regexec return a 1 for
+#              success (and NOT a 0 for success) you have the older
+#              regex routines and must define NET2_REGEX.
+#              Pax may not compile if this not (un)defined properly.
 
-all:   pax
+PROG=   pax
+SRCS=  ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c \
+       gen_subs.c getoldopt.c options.c pat_rep.c pax.c sel_subs.c \
+       tables.c tar.c tty_subs.c fgetln.c
 
-OBJ = ar_io.o ar_subs.o buf_subs.o cache.o cpio.o file_subs.o ftree.o \
-gen_subs.o getoldopt.o options.o pat_rep.o pax.o sel_subs.o \
-tables.o tar.o tty_subs.o fgetln.o
+MAN=   pax.1 tar.1 cpio.1
 
-pax:   $(OBJ)
-       $(CC) $(LDFLAGS) -o $@ $(OBJ)
-       install -S 256k $@
+BINDIR?=/usr/bin
+LINKS+= ${BINDIR}/pax ${BINDIR}/tar
+LINKS+= ${BINDIR}/pax ${BINDIR}/cpio
 
-install: pax
-       install -cs -o bin pax /usr/bin/pax
+CFLAGS+= -O -D_POSIX_SOURCE -DNET2_STAT=1 -D_MINIX=1
+LDFLAGS+= -i
 
-clean: 
-       rm -f *.o *.bak core pax
+.include <minix.prog.mk>
diff --git a/commands/pax/build b/commands/pax/build
deleted file mode 100644 (file)
index 8f58e6d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-make
diff --git a/commands/pax/cpio.1 b/commands/pax/cpio.1
new file mode 100644 (file)
index 0000000..7ff1881
--- /dev/null
@@ -0,0 +1,304 @@
+.\"-
+.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
+.\" 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by SigmaSoft, Th. Lockert.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+.\"
+.\"    $OpenBSD: cpio.1,v 1.16 2001/05/01 17:58:01 aaron Exp $
+.\" $FreeBSD$
+.\"
+.Dd February 16, 1997
+.Dt CPIO 1
+.Os
+.Sh NAME
+.Nm cpio
+.Nd copy file archives in and out
+.Sh SYNOPSIS
+.Nm
+.Fl o
+.Op Fl aABcLvzZ
+.Op Fl C Ar bytes
+.Op Fl F Ar archive
+.Op Fl H Ar format
+.Op Fl O Ar archive
+.No < Ar name-list
+.Op No > Ar archive
+.Nm
+.Fl i
+.Op Fl bBcdfmrsStuvzZ6
+.Op Fl C Ar bytes
+.Op Fl E Ar file
+.Op Fl F Ar archive
+.Op Fl H Ar format
+.Op Fl I Ar archive
+.Op Ar pattern ...
+.Op No < Ar archive
+.Nm
+.Fl p
+.Op Fl adlLmuv
+.Ar destination-directory
+.No < Ar name-list
+.Sh DESCRIPTION
+The
+.Nm
+command copies files to and from a
+.Nm
+archive.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o
+Create an archive.
+Reads the list of files to store in the
+archive from standard input, and writes the archive on standard
+output.
+.Bl -tag -width indent
+.It Fl a
+Reset the access times on files that have been copied to the
+archive.
+.It Fl A
+Append to the specified archive.
+.It Fl B
+Set block size of output to 5120 bytes.
+.It Fl c
+Use
+.Tn ASCII
+format for
+.Nm
+header for portability.
+.It Fl C Ar bytes
+Set the block size of output to
+.Ar bytes .
+.It Fl F Ar archive
+.It Fl O Ar archive
+Use the specified file name as the archive to write to.
+.It Fl H Ar format
+Write the archive in the specified format.
+Recognized formats are:
+.Pp
+.Bl -tag -width sv4cpio -compact
+.It Cm bcpio
+Old binary
+.Nm
+format.
+.It Cm cpio
+Old octal character
+.Nm
+format.
+.It Cm sv4cpio
+.Tn SVR4
+hex
+.Nm
+format.
+.It Cm tar
+Old tar format.
+.It Cm ustar
+.Tn POSIX
+ustar format.
+.El
+.It Fl L
+Follow symbolic links.
+.It Fl v
+Be verbose about operations.
+List filenames as they are written to the archive.
+.It Fl z
+Compress archive using
+.Xr gzip 1
+format.
+.It Fl Z
+Compress archive using
+.Xr compress 1
+format.
+.El
+.It Fl i
+Restore files from an archive.
+Reads the archive file from
+standard input and extracts files matching the
+.Ar patterns
+that were specified on the command line.
+.Bl -tag -width indent
+.It Fl b
+Do byte and word swapping after reading in data from the
+archive, for restoring archives created on systems with
+a different byte order.
+.It Fl B
+Set the block size of the archive being read to 5120 bytes.
+.It Fl c
+Expect the archive headers to be in
+.Tn ASCII
+format.
+.It Fl C Ar bytes
+Read archive written with a block size of
+.Ar bytes .
+.It Fl d
+Create any intermediate directories as needed during
+restore.
+.It Fl E Ar file
+Read list of file name patterns to extract or list from
+.Ar file .
+.It Fl f
+Restore all files except those matching the
+.Ar patterns
+given on the command line.
+.It Fl F Ar archive , Fl I Ar archive
+Use the specified file as the input for the archive.
+.It Fl H Ar format
+Read an archive of the specified format.
+Recognized formats are:
+.Pp
+.Bl -tag -width sv4cpio -compact
+.It Cm bcpio
+Old binary
+.Nm
+format.
+.It Cm cpio
+Old octal character
+.Nm
+format.
+.It Cm sv4cpio
+.Tn SVR4
+hex
+.Nm
+format.
+.It Cm tar
+Old tar format.
+.It Cm ustar
+.Tn POSIX
+ustar format.
+.El
+.It Fl m
+Restore modification times on files.
+.It Fl r
+Rename restored files interactively.
+.It Fl s
+Swap bytes after reading data from the archive.
+.It Fl S
+Swap words after reading data from the archive.
+.It Fl t
+Only list the contents of the archive, no files or
+directories will be created.
+.It Fl u
+Overwrite files even when the file in the archive is
+older than the one that will be overwritten.
+.It Fl v
+Be verbose about operations.
+List filenames as they are copied in from the archive.
+.It Fl z
+Uncompress archive using
+.Xr gzip 1
+format.
+.It Fl Z
+Uncompress archive using
+.Xr compress 1
+format.
+.It Fl 6
+Process old-style
+.Nm
+format archives.
+.El
+.It Fl p
+Copy files from one location to another in a single pass.
+The list of files to copy are read from standard input and
+written out to a directory relative to the specified
+.Ar directory
+argument.
+.Bl -tag -width indent
+.It Fl a
+Reset the access times on files that have been copied.
+.It Fl d
+Create any intermediate directories as needed to write
+the files at the new location.
+.It Fl l
+When possible, link files rather than creating an
+extra copy.
+.It Fl L
+Follow symbolic links.
+.It Fl m
+Restore modification times on files.
+.It Fl u
+Overwrite files even when the original file being copied is
+older than the one that will be overwritten.
+.It Fl v
+Be verbose about operations.
+List filenames as they are copied.
+.El
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width TMPDIR
+.It Ev TMPDIR
+Path in which to store temporary files.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility will exit with one of the following values:
+.Bl -tag -width 2n
+.It 0
+All files were processed successfully.
+.It 1
+An error occurred.
+.El
+.Pp
+Whenever
+.Nm
+cannot create a file or a link when extracting an archive or cannot
+find a file while writing an archive, or cannot preserve the user
+ID, group ID, file mode, or access and modification times when the
+.Fl p
+option is specified, a diagnostic message is written to standard
+error and a non-zero exit value will be returned, but processing
+will continue.
+In the case where
+.Nm
+cannot create a link to a file,
+.Nm
+will not create a second copy of the file.
+.Pp
+If the extraction of a file from an archive is prematurely terminated
+by a signal or error,
+.Nm
+may have only partially extracted the file the user wanted.
+Additionally, the file modes of extracted files and directories may
+have incorrect file bits, and the modification and access times may
+be wrong.
+.Pp
+If the creation of an archive is prematurely terminated by a signal
+or error,
+.Nm
+may have only partially created the archive which may violate the
+specific archive format specification.
+.Sh SEE ALSO
+.Xr pax 1 ,
+.Xr tar 1
+.Sh AUTHORS
+.An Keith Muller
+at the University of California, San Diego.
+.Sh BUGS
+The
+.Fl s
+and
+.Fl S
+options are currently not implemented.
index 155d3c0ffb230089432ad786e0c8310b42104835..66e963c044b9f6fb098449981ee942d2721c21e9 100644 (file)
@@ -579,6 +579,13 @@ pax_options(int argc, char **argv)
        }
 }
 
+static void
+tar_set_action(int op)
+{
+       if (act != ERROR && act != op)
+               tar_usage();
+       act = op;
+}
 
 /*
  * tar_options()
@@ -625,7 +632,7 @@ tar_options(int argc, char **argv)
                        /*
                         * create an archive
                         */
-                       act = ARCHIVE;
+                       tar_set_action(ARCHIVE);
                        break;
                case 'e':
                        /*
@@ -691,7 +698,7 @@ tar_options(int argc, char **argv)
                        /*
                         * append to the archive
                         */
-                       act = APPND;
+                       tar_set_action(APPND);
                        break;
                case 's':
                        /*
@@ -706,7 +713,7 @@ tar_options(int argc, char **argv)
                        /*
                         * list contents of the tape
                         */
-                       act = LIST;
+                       tar_set_action(LIST);
                        break;
                case 'v':
                        /*
@@ -725,7 +732,7 @@ tar_options(int argc, char **argv)
                         * extract an archive, preserving mode,
                         * and mtime if possible.
                         */
-                       act = EXTRACT;
+                       tar_set_action(EXTRACT);
                        pmtime = 1;
                        break;
                case 'z':
@@ -812,6 +819,10 @@ tar_options(int argc, char **argv)
        argc -= optind;
        argv += optind;
 
+       /* Tar requires an action. */
+       if (act == ERROR)
+               tar_usage();
+
        /* Traditional tar behaviour (pax uses stderr unless in list mode) */
        if (fstdin == 1 && act == ARCHIVE)
                listf = stderr;
diff --git a/commands/pax/pax.1 b/commands/pax/pax.1
new file mode 100644 (file)
index 0000000..0593404
--- /dev/null
@@ -0,0 +1,1193 @@
+.\"-
+.\" Copyright (c) 1992 Keith Muller.
+.\" Copyright (c) 1992, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Keith Muller of the University of California, San Diego.
+.\"
+.\" 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.
+.\"
+.\"    @(#)pax.1       8.4 (Berkeley) 4/18/94
+.\" $FreeBSD$
+.\"
+.Dd July 3, 2004
+.Dt PAX 1
+.Os
+.Sh NAME
+.Nm pax
+.Nd read and write file archives and copy directory hierarchies
+.Sh SYNOPSIS
+.Nm
+.Op Fl cdnvz
+.Bk -words
+.Op Fl f Ar archive
+.Ek
+.Bk -words
+.Op Fl s Ar replstr
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl U Ar user
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl G Ar group
+.Ar ...\&
+.Ek
+.Bk -words
+.Oo
+.Fl T
+.Op Ar from_date
+.Op Ar ,to_date
+.Oc
+.Ar ...\&
+.Ek
+.Op Ar pattern ...\&
+.Nm
+.Fl r
+.Op Fl cdiknuvzDYZ
+.Bk -words
+.Op Fl f Ar archive
+.Ek
+.Bk -words
+.Op Fl o Ar options
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl p Ar string
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl s Ar replstr
+.Ar ...\&
+.Ek
+.Op Fl E Ar limit
+.Bk -words
+.Op Fl U Ar user
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl G Ar group
+.Ar ...\&
+.Ek
+.Bk -words
+.Oo
+.Fl T
+.Op Ar from_date
+.Op Ar ,to_date
+.Oc
+.Ar ...\&
+.Ek
+.Op Ar pattern ...\&
+.Nm
+.Fl w
+.Op Fl dituvzHLPX
+.Bk -words
+.Op Fl b Ar blocksize
+.Ek
+.Oo
+.Op Fl a
+.Op Fl f Ar archive
+.Oc
+.Bk -words
+.Op Fl x Ar format
+.Ek
+.Bk -words
+.Op Fl s Ar replstr
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl o Ar options
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl U Ar user
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl G Ar group
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl B Ar bytes
+.Ek
+.Bk -words
+.Oo
+.Fl T
+.Op Ar from_date
+.Op Ar ,to_date
+.Op Ar /[c][m]
+.Oc
+.Ar ...\&
+.Ek
+.Op Ar
+.Nm
+.Fl r
+.Fl w
+.Op Fl diklntuvDHLPXYZ
+.Bk -words
+.Op Fl p Ar string
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl s Ar replstr
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl U Ar user
+.Ar ...\&
+.Ek
+.Bk -words
+.Op Fl G Ar group
+.Ar ...\&
+.Ek
+.Bk -words
+.Oo
+.Fl T
+.Op Ar from_date
+.Op Ar ,to_date
+.Op Ar /[c][m]
+.Oc
+.Ar ...\&
+.Ek
+.Op Ar
+.Ar directory
+.Sh DESCRIPTION
+The
+.Nm
+utility will read, write, and list the members of an archive file,
+and will copy directory hierarchies.
+These operations are independent of the specific archive format,
+and support a wide variety of different archive formats.
+A list of supported archive formats can be found under the description of the
+.Fl x
+option.
+.Pp
+The presence of the
+.Fl r
+and the
+.Fl w
+options specifies which of the following functional modes
+.Nm
+will operate under:
+.Em list , read , write ,
+and
+.Em copy .
+.Bl -tag -width 6n
+.It <none>
+.Em List .
+Write to
+.Dv standard output
+a table of contents of the members of the archive file read from
+.Dv standard input ,
+whose pathnames match the specified
+.Ar patterns .
+The table of contents contains one filename per line
+and is written using single line buffering.
+.It Fl r
+.Em Read .
+Extract the members of the archive file read from the
+.Dv standard input ,
+with pathnames matching the specified
+.Ar patterns .
+The archive format and blocking is automatically determined on input.
+When an extracted file is a directory, the entire file hierarchy
+rooted at that directory is extracted.
+All extracted files are created relative to the current file hierarchy.
+The setting of ownership, access and modification times, and file mode of
+the extracted files are discussed in more detail under the
+.Fl p
+option.
+.It Fl w
+.Em Write .
+Write an archive containing the
+.Ar file
+operands to
+.Dv standard output
+using the specified archive format.
+When no
+.Ar file
+operands are specified, a list of files to copy with one per line is read from
+.Dv standard input .
+When a
+.Ar file
+operand is also a directory, the entire file hierarchy rooted
+at that directory will be included.
+.It Fl r Fl w
+.Em Copy .
+Copy the
+.Ar file
+operands to the destination
+.Ar directory .
+When no
+.Ar file
+operands are specified, a list of files to copy with one per line is read from
+the
+.Dv standard input .
+When a
+.Ar file
+operand is also a directory the entire file
+hierarchy rooted at that directory will be included.
+The effect of the
+.Em copy
+is as if the copied files were written to an archive file and then
+subsequently extracted, except that there may be hard links between
+the original and the copied files (see the
+.Fl l
+option below).
+.Pp
+.Em Warning :
+The destination
+.Ar directory
+must not be one of the
+.Ar file
+operands or a member of a file hierarchy rooted at one of the
+.Ar file
+operands.
+The result of a
+.Em copy
+under these conditions is unpredictable.
+.El
+.Pp
+While processing a damaged archive during a
+.Em read
+or
+.Em list
+operation,
+.Nm
+will attempt to recover from media defects and will search through the archive
+to locate and process the largest number of archive members possible (see the
+.Fl E
+option for more details on error handling).
+.Sh OPERANDS
+The
+.Ar directory
+operand specifies a destination directory pathname.
+If the
+.Ar directory
+operand does not exist, or it is not writable by the user,
+or it is not of type directory,
+.Nm
+will exit with a non-zero exit status.
+.Pp
+The
+.Ar pattern
+operand is used to select one or more pathnames of archive members.
+Archive members are selected using the pattern matching notation described
+by
+.Xr fnmatch 3 .
+When the
+.Ar pattern
+operand is not supplied, all members of the archive will be selected.
+When a
+.Ar pattern
+matches a directory, the entire file hierarchy rooted at that directory will
+be selected.
+When a
+.Ar pattern
+operand does not select at least one archive member,
+.Nm
+will write these
+.Ar pattern
+operands in a diagnostic message to
+.Dv standard error
+and then exit with a non-zero exit status.
+.Pp
+The
+.Ar file
+operand specifies the pathname of a file to be copied or archived.
+When a
+.Ar file
+operand does not select at least one archive member,
+.Nm
+will write these
+.Ar file
+operand pathnames in a diagnostic message to
+.Dv standard error
+and then exit with a non-zero exit status.
+.Sh OPTIONS
+The following options are supported:
+.Bl -tag -width 4n
+.It Fl r
+Read an archive file from
+.Dv standard input
+and extract the specified
+.Ar files .
+If any intermediate directories are needed in order to extract an archive
+member, these directories will be created as if
+.Xr mkdir 2
+was called with the bitwise inclusive
+.Dv OR
+of
+.Dv S_IRWXU , S_IRWXG ,
+and
+.Dv S_IRWXO
+as the mode argument.
+When the selected archive format supports the specification of linked
+files and these files cannot be linked while the archive is being extracted,
+.Nm
+will write a diagnostic message to
+.Dv standard error
+and exit with a non-zero exit status at the completion of operation.
+.It Fl w
+Write files to the
+.Dv standard output
+in the specified archive format.
+When no
+.Ar file
+operands are specified,
+.Dv standard input
+is read for a list of pathnames with one per line without any leading or
+trailing
+.Aq blanks .
+.It Fl a
+Append
+.Ar files
+to the end of an archive that was previously written.
+If an archive format is not specified with a
+.Fl x
+option, the format currently being used in the archive will be selected.
+Any attempt to append to an archive in a format different from the
+format already used in the archive will cause
+.Nm
+to exit immediately
+with a non-zero exit status.
+The blocking size used in the archive volume where writing starts
+will continue to be used for the remainder of that archive volume.
+.Pp
+.Em Warning :
+Many storage devices are not able to support the operations necessary
+to perform an append operation.
+Any attempt to append to an archive stored on such a device may damage the
+archive or have other unpredictable results.
+Tape drives in particular are more likely to not support an append operation.
+An archive stored in a regular file system file or on a disk device will
+usually support an append operation.
+.It Fl b Ar blocksize
+When
+.Em writing
+an archive,
+block the output at a positive decimal integer number of
+bytes per write to the archive file.
+The
+.Ar blocksize
+must be a multiple of 512 bytes with a maximum of 64512 bytes.
+Archives larger than 32256 bytes violate the
+.Tn POSIX
+standard and will not be portable to all systems.
+A
+.Ar blocksize
+can end with
+.Li k
+or
+.Li b
+to specify multiplication by 1024 (1K) or 512, respectively.
+A pair of
+.Ar blocksizes
+can be separated by
+.Li x
+to indicate a product.
+A specific archive device may impose additional restrictions on the size
+of blocking it will support.
+When blocking is not specified, the default
+.Ar blocksize
+is dependent on the specific archive format being used (see the
+.Fl x
+option).
+.It Fl c
+Match all file or archive members
+.Em except
+those specified by the
+.Ar pattern
+and
+.Ar file
+operands.
+.It Fl d
+Cause files of type directory being copied or archived, or archive members of
+type directory being extracted, to match only the directory file or archive
+member and not the file hierarchy rooted at the directory.
+.It Fl f Ar archive
+Specify
+.Ar archive
+as the pathname of the input or output archive, overriding the default
+.Dv standard input
+(for
+.Em list
+and
+.Em read )
+or
+.Dv standard output
+(for
+.Em write ) .
+A single archive may span multiple files and different archive devices.
+When required,
+.Nm
+will prompt for the pathname of the file or device of the next volume in the
+archive.
+.It Fl i
+Interactively rename files or archive members.
+For each archive member matching a
+.Ar pattern
+operand or each file matching a
+.Ar file
+operand,
+.Nm
+will prompt to
+.Pa /dev/tty
+giving the name of the file, its file mode and its modification time.
+The
+.Nm
+utility will then read a line from
+.Pa /dev/tty .
+If this line is blank, the file or archive member is skipped.
+If this line consists of a single period, the
+file or archive member is processed with no modification to its name.
+Otherwise, its name is replaced with the contents of the line.
+The
+.Nm
+utility will immediately exit with a non-zero exit status if
+.Dv <EOF>
+is encountered when reading a response or if
+.Pa /dev/tty
+cannot be opened for reading and writing.
+.It Fl k
+Do not overwrite existing files.
+.It Fl l
+Link files.
+(The letter ell).
+In the
+.Em copy
+mode
+.Pq Fl r w ,
+hard links are made between the source and destination file hierarchies
+whenever possible.
+.It Fl n
+Select the first archive member that matches each
+.Ar pattern
+operand.
+No more than one archive member is matched for each
+.Ar pattern .
+When members of type directory are matched, the file hierarchy rooted at that
+directory is also matched (unless
+.Fl d
+is also specified).
+.It Fl o Ar options
+Information to modify the algorithm for extracting or writing archive files
+which is specific to the archive format specified by
+.Fl x .
+In general,
+.Ar options
+take the form:
+.Cm name=value
+.It Fl p Ar string
+Specify one or more file characteristic options (privileges).
+The
+.Ar string
+option-argument is a string specifying file characteristics to be retained or
+discarded on extraction.
+The string consists of the specification characters
+.Cm a , e , m , o ,
+and
+.Cm p .
+Multiple characteristics can be concatenated within the same string
+and multiple
+.Fl p
+options can be specified.
+The meaning of the specification characters are as follows:
+.Bl -tag -width 2n
+.It Cm a
+Do not preserve file access times.
+By default, file access times are preserved whenever possible.
+.It Cm e
+.Sq Preserve everything ,
+the user ID, group ID, file mode bits,
+file access time, and file modification time.
+This is intended to be used by
+.Em root ,
+someone with all the appropriate privileges, in order to preserve all
+aspects of the files as they are recorded in the archive.
+The
+.Cm e
+flag is the sum of the
+.Cm o
+and
+.Cm p
+flags.
+.It Cm m
+Do not preserve file modification times.
+By default, file modification times are preserved whenever possible.
+.It Cm o
+Preserve the user ID and group ID.
+.It Cm p
+.Sq Preserve
+the file mode bits.
+This intended to be used by a
+.Em user
+with regular privileges who wants to preserve all aspects of the file other
+than the ownership.
+The file times are preserved by default, but two other flags are offered to
+disable this and use the time of extraction instead.
+.El
+.Pp
+In the preceding list,
+.Sq preserve
+indicates that an attribute stored in the archive is given to the
+extracted file, subject to the permissions of the invoking
+process.
+Otherwise the attribute of the extracted file is determined as
+part of the normal file creation action.
+If neither the
+.Cm e
+nor the
+.Cm o
+specification character is specified, or the user ID and group ID are not
+preserved for any reason,
+.Nm
+will not set the
+.Dv S_ISUID
+.Em ( setuid )
+and
+.Dv S_ISGID
+.Em ( setgid )
+bits of the file mode.
+If the preservation of any of these items fails for any reason,
+.Nm
+will write a diagnostic message to
+.Dv standard error .
+Failure to preserve these items will affect the final exit status,
+but will not cause the extracted file to be deleted.
+If the file characteristic letters in any of the string option-arguments are
+duplicated or conflict with each other, the one(s) given last will take
+precedence.
+For example, if
+.Dl Fl p Ar eme
+is specified, file modification times are still preserved.
+.It Fl s Ar replstr
+Modify the file or archive member names specified by the
+.Ar pattern
+or
+.Ar file
+operands according to the substitution expression
+.Ar replstr ,
+using the syntax of the
+.Xr ed 1
+utility regular expressions.
+The format of these regular expressions are:
+.Dl /old/new/[gp]
+As in
+.Xr ed 1 ,
+.Cm old
+is a basic regular expression and
+.Cm new
+can contain an ampersand (&), \\n (where n is a digit) back-references,
+or subexpression matching.
+The
+.Cm old
+string may also contain
+.Dv <newline>
+characters.
+Any non-null character can be used as a delimiter (/ is shown here).
+Multiple
+.Fl s
+expressions can be specified.
+The expressions are applied in the order they are specified on the
+command line, terminating with the first successful substitution.
+The optional trailing
+.Cm g
+continues to apply the substitution expression to the pathname substring
+which starts with the first character following the end of the last successful
+substitution.
+The first unsuccessful substitution stops the operation of the
+.Cm g
+option.
+The optional trailing
+.Cm p
+will cause the final result of a successful substitution to be written to
+.Dv standard error
+in the following format:
+.Dl <original pathname> >> <new pathname>
+File or archive member names that substitute to the empty string
+are not selected and will be skipped.
+.It Fl t
+Reset the access times of any file or directory read or accessed by
+.Nm
+to be the same as they were before being read or accessed by
+.Nm .
+.It Fl u
+Ignore files that are older (having a less recent file modification time)
+than a pre-existing file or archive member with the same name.
+During
+.Em read ,
+an archive member with the same name as a file in the file system will be
+extracted if the archive member is newer than the file.
+During
+.Em write ,
+a file system member with the same name as an archive member will be
+written to the archive if it is newer than the archive member.
+During
+.Em copy ,
+the file in the destination hierarchy is replaced by the file in the source
+hierarchy or by a link to the file in the source hierarchy if the file in
+the source hierarchy is newer.
+.It Fl v
+During a
+.Em list
+operation, produce a verbose table of contents using the format of the
+.Xr ls 1
+utility with the
+.Fl l
+option.
+For pathnames representing a hard link to a previous member of the archive,
+the output has the format:
+.Dl <ls -l listing> == <link name>
+For pathnames representing a symbolic link, the output has the format:
+.Dl <ls -l listing> => <link name>
+Where <ls -l listing> is the output format specified by the
+.Xr ls 1
+utility when used with the
+.Fl l
+option.
+Otherwise for all the other operational modes
+.Em ( read , write ,
+and
+.Em copy ) ,
+pathnames are written and flushed to
+.Dv standard error
+without a trailing
+.Dv <newline>
+as soon as processing begins on that file or
+archive member.
+The trailing
+.Dv <newline> ,
+is not buffered, and is written only after the file has been read or written.
+.It Fl x Ar format
+Specify the output archive format, with the default format being
+.Ar ustar .
+The
+.Nm
+utility currently supports the following formats:
+.Bl -tag -width "sv4cpio"
+.It Ar cpio
+The extended cpio interchange format specified in the
+.St -p1003.2
+standard.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format) which may be truncated by this format is detected by
+.Nm
+and is repaired.
+.It Ar bcpio
+The old binary cpio format.
+The default blocksize for this format is 5120 bytes.
+This format is not very portable and should not be used when other formats
+are available.
+Inode and device information about a file (used for detecting file hard links
+by this format) which may be truncated by this format is detected by
+.Nm
+and is repaired.
+.It Ar sv4cpio
+The System V release 4 cpio.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format) which may be truncated by this format is detected by
+.Nm
+and is repaired.
+.It Ar sv4crc
+The System V release 4 cpio with file crc checksums.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format) which may be truncated by this format is detected by
+.Nm
+and is repaired.
+.It Ar tar
+The old
+.Bx
+tar format as found in
+.Bx 4.3 .
+The default blocksize for this format is 10240 bytes.
+Pathnames stored by this format must be 100 characters or less in length.
+Only
+.Em regular
+files,
+.Em hard links , soft links ,
+and
+.Em directories
+will be archived (other file system types are not supported).
+For backwards compatibility with even older tar formats, a
+.Fl o
+option can be used when writing an archive to omit the storage of directories.
+This option takes the form:
+.Dl Fl o Cm write_opt=nodir
+.It Ar ustar
+The extended tar interchange format specified in the
+.St -p1003.2
+standard.
+The default blocksize for this format is 10240 bytes.
+Pathnames stored by this format must be 250 characters or less in length.
+.El
+.Pp
+The
+.Nm
+utility will detect and report any file that it is unable to store or extract
+as the result of any specific archive format restrictions.
+The individual archive formats may impose additional restrictions on use.
+Typical archive format restrictions include (but are not limited to):
+file pathname length, file size, link pathname length and the type of the file.
+.It Fl z
+Use
+.Xr gzip 1
+to compress (decompress) the archive while writing (reading).
+Incompatible with
+.Fl a .
+.It Fl B Ar bytes
+Limit the number of bytes written to a single archive volume to
+.Ar bytes .
+The
+.Ar bytes
+limit can end with
+.Li m ,
+.Li k ,
+or
+.Li b
+to specify multiplication by 1048576 (1M), 1024 (1K) or 512, respectively.
+A pair of
+.Ar bytes
+limits can be separated by
+.Li x
+to indicate a product.
+.Pp
+.Em Warning :
+Only use this option when writing an archive to a device which supports
+an end of file read condition based on last (or largest) write offset
+(such as a regular file or a tape drive).
+The use of this option with a floppy or hard disk is not recommended.
+.It Fl D
+This option is the same as the
+.Fl u
+option, except that the file inode change time is checked instead of the
+file modification time.
+The file inode change time can be used to select files whose inode information
+(e.g.\& uid, gid, etc.) is newer than a copy of the file in the destination
+.Ar directory .
+.It Fl E Ar limit
+Limit the number of consecutive read faults while trying to read a flawed
+archives to
+.Ar limit .
+With a positive
+.Ar limit ,
+.Nm
+will attempt to recover from an archive read error and will
+continue processing starting with the next file stored in the archive.
+A
+.Ar limit
+of 0 will cause
+.Nm
+to stop operation after the first read error is detected on an archive volume.
+A
+.Ar limit
+of
+.Li NONE
+will cause
+.Nm
+to attempt to recover from read errors forever.
+The default
+.Ar limit
+is a small positive number of retries.
+.Pp
+.Em Warning :
+Using this option with
+.Li NONE
+should be used with extreme caution as
+.Nm
+may get stuck in an infinite loop on a very badly flawed archive.
+.It Fl G Ar group
+Select a file based on its
+.Ar group
+name, or when starting with a
+.Cm # ,
+a numeric gid.
+A '\\' can be used to escape the
+.Cm # .
+Multiple
+.Fl G
+options may be supplied and checking stops with the first match.
+.It Fl H
+Follow only command line symbolic links while performing a physical file
+system traversal.
+.It Fl L
+Follow all symbolic links to perform a logical file system traversal.
+.It Fl P
+Do not follow symbolic links, perform a physical file system traversal.
+This is the default mode.
+.It Fl T Ar [from_date][,to_date][/[c][m]]
+Allow files to be selected based on a file modification or inode change
+time falling within a specified time range of
+.Ar from_date
+to
+.Ar to_date
+(the dates are inclusive).
+If only a
+.Ar from_date
+is supplied, all files with a modification or inode change time
+equal to or younger are selected.
+If only a
+.Ar to_date
+is supplied, all files with a modification or inode change time
+equal to or older will be selected.
+When the
+.Ar from_date
+is equal to the
+.Ar to_date ,
+only files with a modification or inode change time of exactly that
+time will be selected.
+.Pp
+When
+.Nm
+is in the
+.Em write
+or
+.Em copy
+mode, the optional trailing field
+.Ar [c][m]
+can be used to determine which file time (inode change, file modification or
+both) are used in the comparison.
+If neither is specified, the default is to use file modification time only.
+The
+.Ar m
+specifies the comparison of file modification time (the time when
+the file was last written).
+The
+.Ar c
+specifies the comparison of inode change time (the time when the file
+inode was last changed; e.g.\& a change of owner, group, mode, etc).
+When
+.Ar c
+and
+.Ar m
+are both specified, then the modification and inode change times are
+both compared.
+The inode change time comparison is useful in selecting files whose
+attributes were recently changed or selecting files which were recently
+created and had their modification time reset to an older time (as what
+happens when a file is extracted from an archive and the modification time
+is preserved).
+Time comparisons using both file times is useful when
+.Nm
+is used to create a time based incremental archive (only files that were
+changed during a specified time range will be archived).
+.Pp
+A time range is made up of six different fields and each field must contain two
+digits.
+The format is:
+.Dl [yy[mm[dd[hh]]]]mm[.ss]
+Where
+.Cm yy
+is the last two digits of the year,
+the first
+.Cm mm
+is the month (from 01 to 12),
+.Cm dd
+is the day of the month (from 01 to 31),
+.Cm hh
+is the hour of the day (from 00 to 23),
+the second
+.Cm mm
+is the minute (from 00 to 59),
+and
+.Cm ss
+is the seconds (from 00 to 59).
+The minute field
+.Cm mm
+is required, while the other fields are optional and must be added in the
+following order:
+.Dl Cm hh , dd , mm , yy .
+The
+.Cm ss
+field may be added independently of the other fields.
+Time ranges are relative to the current time, so
+.Dl Fl T Ar 1234/cm
+would select all files with a modification or inode change time
+of 12:34 PM today or later.
+Multiple
+.Fl T
+time range can be supplied and checking stops with the first match.
+.It Fl U Ar user
+Select a file based on its
+.Ar user
+name, or when starting with a
+.Cm # ,
+a numeric uid.
+A '\\' can be used to escape the
+.Cm # .
+Multiple
+.Fl U
+options may be supplied and checking stops with the first match.
+.It Fl X
+When traversing the file hierarchy specified by a pathname,
+do not descend into directories that have a different device ID.
+See the
+.Li st_dev
+field as described in
+.Xr stat 2
+for more information about device ID's.
+.It Fl Y
+This option is the same as the
+.Fl D
+option, except that the inode change time is checked using the
+pathname created after all the file name modifications have completed.
+.It Fl Z
+This option is the same as the
+.Fl u
+option, except that the modification time is checked using the
+pathname created after all the file name modifications have completed.
+.El
+.Pp
+The options that operate on the names of files or archive members
+.Fl ( c ,
+.Fl i ,
+.Fl n ,
+.Fl s ,
+.Fl u ,
+.Fl v ,
+.Fl D ,
+.Fl G ,
+.Fl T ,
+.Fl U ,
+.Fl Y ,
+and
+.Fl Z )
+interact as follows.
+.Pp
+When extracting files during a
+.Em read
+operation, archive members are
+.Sq selected ,
+based only on the user specified pattern operands as modified by the
+.Fl c ,
+.Fl n ,
+.Fl u ,
+.Fl D ,
+.Fl G ,
+.Fl T ,
+.Fl U
+options.
+Then any
+.Fl s
+and
+.Fl i
+options will modify in that order, the names of these selected files.
+Then the
+.Fl Y
+and
+.Fl Z
+options will be applied based on the final pathname.
+Finally the
+.Fl v
+option will write the names resulting from these modifications.
+.Pp
+When archiving files during a
+.Em write
+operation, or copying files during a
+.Em copy
+operation, archive members are
+.Sq selected ,
+based only on the user specified pathnames as modified by the
+.Fl n ,
+.Fl u ,
+.Fl D ,
+.Fl G ,
+.Fl T ,
+and
+.Fl U
+options (the
+.Fl D
+option only applies during a copy operation).
+Then any
+.Fl s
+and
+.Fl i
+options will modify in that order, the names of these selected files.
+Then during a
+.Em copy
+operation the
+.Fl Y
+and the
+.Fl Z
+options will be applied based on the final pathname.
+Finally the
+.Fl v
+option will write the names resulting from these modifications.
+.Pp
+When one or both of the
+.Fl u
+or
+.Fl D
+options are specified along with the
+.Fl n
+option, a file is not considered selected unless it is newer
+than the file to which it is compared.
+.Sh EXIT STATUS
+The
+.Nm
+utility will exit with one of the following values:
+.Bl -tag -width 2n
+.It 0
+All files were processed successfully.
+.It 1
+An error occurred.
+.El
+.Sh EXAMPLES
+The command:
+.Dl "pax -w -f /dev/sa0 ."
+copies the contents of the current directory to the device
+.Pa /dev/sa0 .
+.Pp
+The command:
+.Dl pax -v -f filename
+gives the verbose table of contents for an archive stored in
+.Pa filename .
+.Pp
+The following commands:
+.Dl mkdir /tmp/to
+.Dl cd /tmp/from
+.Dl pax -rw .\ /tmp/to
+will copy the entire
+.Pa /tmp/from
+directory hierarchy to
+.Pa /tmp/to .
+.Pp
+The command:
+.Dl pax -r -s ',^//*usr//*,,' -f a.pax
+reads the archive
+.Pa a.pax ,
+with all files rooted in ``/usr'' into the archive extracted relative to the
+current directory.
+.Pp
+The command:
+.Dl pax -rw -i .\ dest_dir
+can be used to interactively select the files to copy from the current
+directory to
+.Pa dest_dir .
+.Pp
+The command:
+.Dl pax -r -pe -U root -G bin -f a.pax
+will extract all files from the archive
+.Pa a.pax
+which are owned by
+.Em root
+with group
+.Em bin
+and will preserve all file permissions.
+.Pp
+The command:
+.Dl pax -r -w -v -Y -Z home /backup
+will update (and list) only those files in the destination directory
+.Pa /backup
+which are older (less recent inode change or file modification times) than
+files with the same name found in the source file tree
+.Pa home .
+.Sh DIAGNOSTICS
+Whenever
+.Nm
+cannot create a file or a link when reading an archive or cannot
+find a file when writing an archive, or cannot preserve the user ID,
+group ID, or file mode when the
+.Fl p
+option is specified, a diagnostic message is written to
+.Dv standard error
+and a non-zero exit status will be returned, but processing will continue.
+In the case where pax cannot create a link to a file,
+.Nm
+will not create a second copy of the file.
+.Pp
+If the extraction of a file from an archive is prematurely terminated by
+a signal or error,
+.Nm
+may have only partially extracted a file the user wanted.
+Additionally, the file modes of extracted files and directories
+may have incorrect file bits, and the modification and access times may be
+wrong.
+.Pp
+If the creation of an archive is prematurely terminated by a signal or error,
+.Nm
+may have only partially created the archive which may violate the specific
+archive format specification.
+.Pp
+If while doing a
+.Em copy ,
+.Nm
+detects a file is about to overwrite itself, the file is not copied,
+a diagnostic message is written to
+.Dv standard error
+and when
+.Nm
+completes it will exit with a non-zero exit status.
+.Sh SEE ALSO
+.Xr cpio 1 ,
+.Xr tar 1
+.Sh STANDARDS
+The
+.Nm
+utility is a superset of the
+.St -p1003.2
+standard.
+The options
+.Fl z ,
+.Fl B ,
+.Fl D ,
+.Fl E ,
+.Fl G ,
+.Fl H ,
+.Fl L ,
+.Fl P ,
+.Fl T ,
+.Fl U ,
+.Fl Y ,
+.Fl Z ,
+the archive formats
+.Ar bcpio ,
+.Ar sv4cpio ,
+.Ar sv4crc ,
+.Ar tar ,
+and the flawed archive handling during
+.Ar list
+and
+.Ar read
+operations are extensions to the
+.Tn POSIX
+standard.
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.4 .
+.Sh AUTHORS
+.An Keith Muller
+at the University of California, San Diego
+.Sh BUGS
+The
+.Nm
+utility does not recognize multibyte characters.
index a687d715f9af330f68273bcd51364e13f18567ff..f249a28d5a51ee661dd3e2bd3ffece5c9454808e 100644 (file)
@@ -67,7 +67,7 @@ static int gen_init(void);
 /*
  * Variables that can be accessed by any routine within pax
  */
-int    act = DEFOP;            /* read/write/append/copy */
+int    act = ERROR;            /* read/write/append/copy */
 FSUB   *frmt = NULL;           /* archive format type */
 int    cflag;                  /* match all EXCEPT pattern/file */
 int    cwdfd;                  /* starting cwd */
index f0b64ac1cd761356c4f22c9ab378a0883df86f61..afbc114df9b4052d3c3ed32e80dcd4b16cdec527 100644 (file)
 /*
  * Pax modes of operation
  */
+#define ERROR           -1      /* nothing selected */
 #define        LIST            0       /* List the file in an archive */
 #define        EXTRACT         1       /* extract the files in an archive */
 #define ARCHIVE                2       /* write a new archive */
 #define APPND          3       /* append to the end of an archive */
 #define        COPY            4       /* copy files to destination dir */
-#define DEFOP          LIST    /* if no flags default is to LIST */
 
 /*
  * Device type of the current archive volume
diff --git a/commands/pax/tar.1 b/commands/pax/tar.1
new file mode 100644 (file)
index 0000000..ff66ccb
--- /dev/null
@@ -0,0 +1,310 @@
+.\"-
+.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
+.\" 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by SigmaSoft, Th. Lockert.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+.\"
+.\"    $OpenBSD: tar.1,v 1.33 2001/05/01 17:58:01 aaron Exp $
+.\" $FreeBSD$
+.\"
+.Dd February 7, 2001
+.Dt TAR 1
+.Os
+.Sh NAME
+.Nm tar
+.Nd tape archiver
+.Sh SYNOPSIS
+.Nm
+.Sm off
+.Op Fl
+.Brq Cm crtux
+.Op Cm befhjmopqsvwyzHLOPXZ014578
+.Sm on
+.Op Ar blocksize
+.Op Ar archive
+.Op Ar replstr
+.\" XXX how to do this right?
+.Op Fl C Ar directory
+.Op Fl I Ar file
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+command creates, adds files to, or extracts files from an
+archive file in
+.Nm
+format.
+A
+.Nm
+archive is often stored on a magnetic tape, but can be
+stored equally well on a floppy, CD-ROM, or in a regular disk file.
+.Pp
+One of the following flags must be present:
+.Bl -tag -width indent
+.It Fl c
+Create new archive, or overwrite an existing archive,
+adding the specified files to it.
+.It Fl r
+Append the named new files to existing archive.
+Note that this will only work on media on which an end-of-file mark
+can be overwritten.
+.It Fl t
+List contents of archive.
+If any files are named on the
+command line, only those files will be listed.
+.It Fl u
+Alias for
+.Fl r .
+.It Fl x
+Extract files from archive.
+If any files are named on the
+command line, only those files will be extracted from the
+archive.
+If more than one copy of a file exists in the
+archive, later copies will overwrite earlier copies during
+extraction.
+The file mode and modification time are preserved
+if possible.
+The file mode is subject to modification by the
+.Xr umask 2 .
+.El
+.Pp
+In addition to the flags mentioned above, any of the following
+flags may be used:
+.Bl -tag -width indent
+.It Fl b Ar "blocking factor"
+Set blocking factor to use for the archive, with 512 byte blocks.
+The default is 20, the maximum is 126.
+Archives with a blocking factor larger 63 violate the
+.Tn POSIX
+standard and will not be portable to all systems.
+.It Fl e
+Stop after first error.
+.It Fl f Ar archive
+Filename where the archive is stored.
+Defaults to
+.Pa /dev/sa0 .
+.It Fl h
+Follow symbolic links as if they were normal files
+or directories.
+.It Fl j
+Compress archives using
+.Xr bzip2 1 .
+.It Fl m
+Do not preserve modification time.
+.It Fl O
+Write old-style
+.Pq non- Ns Tn POSIX
+archives.
+.It Fl o
+Do not write directory information that the older (V7) style
+.Nm
+is unable to decode.
+This implies the
+.Fl O
+flag.
+.It Fl p
+Preserve user and group ID as well as file mode regardless of
+the current
+.Xr umask 2 .
+The setuid and setgid bits are only preserved if the user is
+the superuser.
+Only meaningful in conjunction with the
+.Fl x
+flag.
+.It Fl q
+Select the first archive member that matches each
+.Ar pattern
+operand.
+No more than one archive member is matched for each
+.Ar pattern .
+When members of type directory are matched, the file hierarchy rooted at that
+directory is also matched.
+.It Fl s Ar replstr
+Modify the file or archive member names specified by the
+.Ar pattern
+or
+.Ar file
+operands according to the substitution expression
+.Ar replstr ,
+using the syntax of the
+.Xr ed 1
+utility regular expressions.
+The format of these regular expressions are:
+.Dl /old/new/[gp]
+As in
+.Xr ed 1 ,
+.Cm old
+is a basic regular expression and
+.Cm new
+can contain an ampersand
+.Pq Ql & ,
+.Li \e Ns Ar n
+(where
+.Ar n
+is a digit) back-references,
+or subexpression matching.
+The
+.Cm old
+string may also contain newline characters.
+Any non-null character can be used as a delimiter
+.Ql ( /
+is shown here).
+Multiple
+.Fl s
+expressions can be specified.
+The expressions are applied in the order they are specified on the
+command line, terminating with the first successful substitution.
+The optional trailing
+.Cm g
+continues to apply the substitution expression to the pathname substring
+which starts with the first character following the end of the last successful
+substitution.
+The first unsuccessful substitution stops the operation of the
+.Cm g
+option.
+The optional trailing
+.Cm p
+will cause the final result of a successful substitution to be written to
+standard error
+in the following format:
+.Pp
+.Dl <original pathname> >> <new pathname>
+.Pp
+File or archive member names that substitute to the empty string
+are not selected and will be skipped.
+.It Fl v
+Verbose operation mode.
+.It Fl w
+Interactively rename files.
+This option causes
+.Nm
+to prompt the user for the filename to use when storing or
+extracting files in an archive.
+.It Fl y
+Compress archives using
+.Xr bzip2 1 .
+.It Fl z
+Compress archive using
+.Xr gzip 1 .
+.It Fl C Ar directory
+This is a positional argument which sets the working directory for the
+following files.
+When extracting, files will be extracted into
+the specified directory; when creating, the specified files will be matched
+from the directory.
+.It Fl H
+Follow symlinks given on command line only.
+.It Fl L
+Follow all symlinks.
+.It Fl P
+Do not strip leading slashes
+.Pq Ql /
+from pathnames.
+The default is to strip leading slashes.
+.It Fl I Ar file
+This is a positional argument which reads the names of files to
+archive or extract from the given file, one per line.
+.It Fl X
+Do not cross mount points in the file system.
+.It Fl Z
+Compress archive using
+.Xr compress 1 .
+.El
+.Pp
+The options
+.Op Fl 014578
+can be used to select one of the compiled-in backup devices,
+.Pa /dev/rst Ns Ar N .
+.Sh ENVIRONMENT
+.Bl -tag -width TMPDIR
+.It Ev TMPDIR
+Path in which to store temporary files.
+.It Ev TAPE
+Default tape device to use instead of
+.Pa /dev/sa0 .
+.El
+.Sh FILES
+.Bl -tag -width "/dev/sa0"
+.It Pa /dev/sa0
+default archive name
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility will exit with one of the following values:
+.Bl -tag -width 2n
+.It 0
+All files were processed successfully.
+.It 1
+An error occurred.
+.El
+.Pp
+Whenever
+.Nm
+cannot create a file or a link when extracting an archive or cannot
+find a file while writing an archive, or cannot preserve the user
+ID, group ID, file mode, or access and modification times when the
+.Fl p
+option is specified, a diagnostic message is written to standard
+error and a non-zero exit value will be returned, but processing
+will continue.
+In the case where
+.Nm
+cannot create a link to a file,
+.Nm
+will not create a second copy of the file.
+.Pp
+If the extraction of a file from an archive is prematurely terminated
+by a signal or error,
+.Nm
+may have only partially extracted the file the user wanted.
+Additionally, the file modes of extracted files and directories may
+have incorrect file bits, and the modification and access times may
+be wrong.
+.Pp
+If the creation of an archive is prematurely terminated by a signal
+or error,
+.Nm
+may have only partially created the archive which may violate the
+specific archive format specification.
+.Sh COMPATIBILITY
+The
+.Fl L
+flag is not portable to other versions of
+.Nm
+where it may have a different meaning.
+.Sh SEE ALSO
+.Xr cpio 1 ,
+.Xr pax 1
+.Sh HISTORY
+A
+.Nm
+command first appeared in
+.At v7 .
+.Sh AUTHORS
+.An Keith Muller
+at the University of California, San Diego.
index f1d7327c3572de8a22111b979daa3bc81d4b7b18..df2e3defd3e4af71eac89d34f5636192a1179d8e 100644 (file)
@@ -180,7 +180,6 @@ ALL = \
        synctree \
        sysenv \
        tail \
-       tar \
        tcpd \
        tcpdp \
        tcpstat \
@@ -775,10 +774,6 @@ tail:      tail.c
        $(CCLD) -o $@ $<
        @install -S 16kw $@
 
-tar:   tar.c
-       $(CCLD) -o $@ $<
-       @install -S 256kw $@
-
 tcpd:  tcpd.c
        $(CCLD) -o $@ -DPARANOID=0 tcpd.c
        @install -S 8kw $@
@@ -1075,7 +1070,6 @@ install:  \
        /usr/bin/sysenv \
        /bin/sysenv \
        /usr/bin/tail \
-       /usr/bin/tar \
        /usr/bin/tcpd \
        /usr/bin/tcpdp \
        /usr/bin/tcpstat \
@@ -1603,9 +1597,6 @@ install:  \
 /usr/bin/tail: tail
        install -cs -o bin $> $@
 
-/usr/bin/tar:  tar
-       install -cs -o bin $> $@
-
 /usr/bin/tcpd: tcpd
        install -cs -o bin $> $@
 
diff --git a/commands/simple/tar.c b/commands/simple/tar.c
deleted file mode 100644 (file)
index 0ee0474..0000000
+++ /dev/null
@@ -1,1109 +0,0 @@
-/* tar - tape archiver                 Author: Michiel Huisjes */
-
-/* Usage: tar [cxt][vo][F][f] tapefile [files]
- *
- * attempt to make tar to conform to POSIX 1003.1
- * disclaimer: based on an old (1986) POSIX draft.
- * Klamer Schutte, 20/9/89
- *
- * Changes:
- *  Changed to handle the original minix-tar format.   KS 22/9/89
- *  Changed to handle BSD4.3 tar format.               KS 22/9/89
- *  Conform to current umask if not super-user.                KS 22/9/89
- *  Update usage message to show f option              KS 22/9/89
- *
- *
- * 1)  tar will back itself up, should check archive inode num(&dev) and
-  then check the target inode number. In verbose mode, issue
-  warning, in all cases ignore target.
-  marks@mgse           Mon Sep 25 10:38:58 CDT 1989
-       added global varaibles, made changes to main() and add_file();
-  maks@mgse Mon Sep 25 12:09:20 CDT 1989
-
-   2)  tar will not notice that a file has changed size while it was being
-  backed up. should issue warning.
-  marks@mgse           Mon Sep 25 10:38:58 CDT 1989
-
-   3)  the 'f' option was not documented in usage[].
-  marks@mgse           Mon Sep 25 12:03:20 CDT 1989
-       changed both usage[] defines. Why are there two (one is commented out)?
-       ( deleted by me (was done twice) -- KS, 2/10/89 )
- *
- *  changed stat on tar_fd to an fstat                         KS 2/10/89
- *  deleted mkfifo() code -- belongs in libc.a                 KS 2/10/89
- *  made ar_dev default to -1 : an illegal device              KS 2/10/89
- *  made impossible to chown if normal user                    KS 2/10/89
- *  if names in owner fields not known use numirical values    KS 2/10/89
- *  creat with mask 666 -- use umask if to liberal             KS 2/10/89
- *  allow to make directories as ../directory                  KS 2/10/89
- *  allow tmagic field to end with a space (instead of \0)     KS 2/10/89
- *  correct usage of tmagic field                              KS 3/10/89
- *  made mkdir() to return a value if directory == "."         KS 3/10/89
- *  made lint complains less (On a BSD 4.3 system)             KS 3/10/89
- *  use of directory(3) routines                               KS 3/10/89
- *  deleted use of d_namlen selector of struct dirent          KS 18/10/89
- *  support mknod4(2)                                          EC 7/7/90
- *  forget inodes when link count expires                      EC 6/4/91
- *  don't remember directories *twice*!
- *  added 'p' flag to ignore umask for normal user             KJB 6/10/92
- *  mknod4(2) out                                              KJB 30/10/94
- *  added 'D' flag to not recurse into directories             KJB 19/12/94
- *  status output to stdout unless 'tar cvf -'                 KJB 3/5/97
- *
- * Bugs:
- *  verbose mode is not reporting consistent
- *  code needs cleanup
- *  prefix field is not used
- *  timestamp of a directory will not be correct if there are files to be
- *  unpacked in the directory
- *     (add you favorite bug here (or two (or three (or ...))))
-*/
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#include <tar.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <utime.h>
-#include <sys/wait.h>
-#include <stdio.h>             /* need NULL */
-#include <errno.h>
-
-#define        POSIX_COMP              /* POSIX compatible */
-#define DIRECT_3               /* use directory(3) routines */
-
-#ifdef DIRECT_3
-#ifndef BSD
-/* To all minix users: i am sorry, developed this piece of code on a
- * BSD system. KS 18/10/89 */
-#include <dirent.h>
-#define        direct  dirent          /* stupid BSD non-POSIX compatible name! */
-#else                          /* BSD */
-#include <sys/dir.h>
-#include <dir.h>
-#endif                         /* BSD */
-#endif                         /* DIRECT_3 */
-
-#ifdef S_IFIFO
-#define        HAVE_FIFO               /* have incorporated Simon Pooles' changes */
-#endif
-#ifdef S_IFLNK
-#define HAVE_SYMLINK
-#endif
-
-typedef char BOOL;
-#define TRUE   1
-#define FALSE  0
-
-#define STRING_SIZE    256     /* string buffer size */
-#define HEADER_SIZE    TBLOCK
-#define NAME_SIZE      NAMSIZ
-/* #define BLOCK_BOUNDARY       20 -- not in POSIX ! */
-
-typedef union hblock HEADER;
-
-/* Make the MINIX member names overlap to the POSIX names */
-#define        m_name          name
-#define m_mode         mode
-#define m_uid          uid
-#define m_gid          gid
-#define m_size         size
-#define        m_time          mtime
-#define        m_checksum      chksum
-#define        m_linked        typeflag
-#define        m_link          linkname
-#define        hdr_block       dummy
-#define        m               header
-#define        member          dbuf
-
-#if 0                          /* original structure -- see tar.h for new
-                        * structure */
-typedef union {
-  char hdr_block[HEADER_SIZE];
-  struct m {
-       char m_name[NAME_SIZE];
-       char m_mode[8];
-       char m_uid[8];
-       char m_gid[8];
-       char m_size[12];
-       char m_time[12];
-       char m_checksum[8];
-       char m_linked;
-       char m_link[NAME_SIZE];
-  } member;
-} HEADER;
-
-#endif
-
-/* Structure used to note links */
-struct link {
-  ino_t ino;
-  dev_t dev;
-  nlink_t nlink;
-  struct link *next;
-  char name[1];
-} *link_top = NULL;
-
-HEADER header;
-
-#define INT_TYPE       (sizeof(header.member.m_uid))
-#define LONG_TYPE      (sizeof(header.member.m_size))
-
-#define NIL_HEADER     ((HEADER *) 0)
-#define NIL_PTR                ((char *) 0)
-#define TBLOCK_SIZE    TBLOCK
-
-#define flush()                print(NIL_PTR)
-
-BOOL show_fl, creat_fl, ext_fl;
-
-int tar_fd;
-/* Char usage[] = "Usage: tar [cxt] tarfile [files]."; */
-char usage[] = "Usage: tar [cxt][vo][F][f] tarfile [files].";
-char io_buffer[TBLOCK_SIZE];
-char path[NAME_SIZE];
-char pathname[NAME_SIZE];
-int force_flag = 0;
-#ifdef ORIGINAL_DEFAULTS
-int chown_flag = 1;
-int verbose_flag = 1;
-#else
-int chown_flag = 0;
-int verbose_flag = 0;
-#endif
-int norec_flag = 0;
-
-/* Make sure we don't tar ourselves. marks@mgse Mon Sep 25 12:06:28 CDT 1989 */
-ino_t ar_inode;                        /* archive inode number  */
-dev_t ar_dev;                  /* archive device number */
-
-int total_blocks;
-int u_mask;                    /* one's complement of current umask */
-
-#define block_size()   (int) ((convert(header.member.m_size, LONG_TYPE) \
-  + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE)
-
-_PROTOTYPE(int main, (int argc, char **argv));
-_PROTOTYPE(void error, (char *s1, char *s2));
-_PROTOTYPE(BOOL get_header, (void));
-_PROTOTYPE(void tarfile, (void));
-_PROTOTYPE(void skip_entry, (void));
-_PROTOTYPE(void extract, (char *file));
-_PROTOTYPE(void delete, (char *file));
-_PROTOTYPE(void do_chown, (char *file));
-_PROTOTYPE(void timestamp, (char *file));
-_PROTOTYPE(void copy, (char *file, int from, int to, long bytes));
-_PROTOTYPE(long convert, (char str[], int type));
-_PROTOTYPE(int checksum, (void));
-_PROTOTYPE(int is_dir, (char *file));
-_PROTOTYPE(char *path_name, (char *file));
-_PROTOTYPE(void add_path, (char *name));
-_PROTOTYPE(void add_file, (char *file));
-_PROTOTYPE(void verb_print, (char *s1, char *s2));
-_PROTOTYPE(void add_close, (int fd));
-_PROTOTYPE(int add_open, (char *file, struct stat * st));
-_PROTOTYPE(void make_header, (char *file, struct stat * st));
-_PROTOTYPE(void is_added, (struct stat * st, char *file));
-_PROTOTYPE(void is_deleted, (struct stat * st));
-_PROTOTYPE(char *is_linked, (struct stat * st));
-_PROTOTYPE(void clear_header, (void));
-_PROTOTYPE(void adjust_boundary, (void));
-_PROTOTYPE(void mread, (int fd, char *address, int bytes));
-_PROTOTYPE(void mwrite, (int fd, char *address, int bytes));
-_PROTOTYPE(int bread, (int fd, char *address, int bytes));
-_PROTOTYPE(int bwrite, (int fd, char *address, int bytes));
-_PROTOTYPE(void print, (char *str));
-_PROTOTYPE(char *num_out, (long number));
-_PROTOTYPE(void string_print, (char *buffer, char *fmt,...));
-
-void error(s1, s2)
-char *s1, *s2;
-{
-  string_print(NIL_PTR, "%s %s\n", s1, s2 ? s2 : "");
-  flush();
-  exit(1);
-}
-
-int main(argc, argv)
-int argc;
-register char *argv[];
-{
-  register char *mem_name;
-  register char *ptr;
-  struct stat st;
-  int i;
-
-  if (argc < 3) error(usage, NIL_PTR);
-
-  for (ptr = argv[1]; *ptr; ptr++) {
-       /* Ignore - as first char */
-       if(*ptr == '-' && ptr == argv[1]) continue;
-       switch (*ptr) {
-           case 'c':   creat_fl = TRUE;        break;
-           case 'x':   ext_fl = TRUE;  break;
-           case 't':   show_fl = TRUE; break;
-           case 'v':           /* verbose output  -Dal */
-               verbose_flag = !verbose_flag;
-               break;
-           case 'o':           /* chown/chgrp files  -Dal */
-               chown_flag = TRUE;
-               break;
-           case 'F':           /* IGNORE ERRORS  -Dal */
-               force_flag = TRUE;
-               break;
-           case 'f':           /* standard U*IX usage -KS */
-               break;
-           case 'p':           /* restore file modes right, ignore umask. */
-               (void) umask(0);
-               break;
-           case 'D':           /* do not recursively add directories. */
-               norec_flag = TRUE;
-               break;
-           default:    error(usage, NIL_PTR);
-       }
-  }
-
-  if (creat_fl + ext_fl + show_fl != 1) error(usage, NIL_PTR);
-
-  if (strcmp(argv[2], "-") == 0)/* only - means stdin/stdout - KS */
-       tar_fd = creat_fl ? 1 : 0;      /* '-' means used
-                                        * stdin/stdout  -Dal */
-  else
-       tar_fd = creat_fl ? creat(argv[2], 0666) : open(argv[2], O_RDONLY);
-
-  if (tar_fd < 0) error("Cannot open ", argv[2]);
-
-  if (geteuid()) {             /* check if super-user */
-       int save_umask;
-       save_umask = umask(0);
-       u_mask = ~save_umask;
-       umask(save_umask);
-       chown_flag = TRUE;      /* normal user can't chown */
-  } else
-       u_mask = ~0;            /* don't restrict if 'privileged utility' */
-
-  ar_dev = -1;                 /* impossible device nr */
-  if (creat_fl) {
-       if (tar_fd > 1 && fstat(tar_fd, &st) < 0)
-               error("Can't stat ", argv[2]);  /* will never be here,
-                                                * right? */
-       else {                  /* get archive inode & device    */
-               ar_inode = st.st_ino;   /* save files inode      */
-               ar_dev = st.st_dev;     /* save files device     */
-       }                       /* marks@mgse Mon Sep 25 11:30:45 CDT 1989 */
-
-       for (i = 3; i < argc; i++) {
-               add_file(argv[i]);
-               path[0] = '\0';
-       }
-       adjust_boundary();
-  } else if (ext_fl) {
-       /* Extraction code moved here from tarfile() MSP */
-       while (get_header()) {
-               mem_name = header.member.m_name;
-               if (is_dir(mem_name)) {
-                       for (ptr = mem_name; *ptr; ptr++);
-                       *(ptr - 1) = '\0';
-                       header.dbuf.typeflag = '5';
-               }
-               for (i = 3; i < argc; i++)
-                       if (!strncmp(argv[i], mem_name, strlen(argv[i])))
-                               break;
-               if (argc == 3 || (i < argc)) {
-                       extract(mem_name);
-               } else if (header.dbuf.typeflag == '0' ||
-                          header.dbuf.typeflag == 0 ||
-                          header.dbuf.typeflag == ' ')
-                       skip_entry();
-               flush();
-       }
-  } else
-       tarfile();              /* tarfile() justs prints info. now MSP */
-
-  flush();
-  return(0);
-}
-
-BOOL get_header()
-{
-  register int check;
-
-  mread(tar_fd, (char *) &header, sizeof(header));
-  if (header.member.m_name[0] == '\0') return FALSE;
-
-  if (force_flag)              /* skip checksum verification  -Dal */
-       return TRUE;
-
-  check = (int) convert(header.member.m_checksum, INT_TYPE);
-
-  if (check != checksum()) error("Tar: header checksum error.", NIL_PTR);
-
-  return TRUE;
-}
-
-/* Tarfile() just lists info about archive now; as of the t flag. */
-/* Extraction has been moved into main() as that needs access to argv[] */
-
-void tarfile()
-{
-  register char *mem_name;
-
-  while (get_header()) {
-       mem_name = header.member.m_name;
-       string_print(NIL_PTR, "%s%s", mem_name,
-                    (verbose_flag ? " " : "\n"));
-       switch (header.dbuf.typeflag) {
-           case '1':
-               verb_print("linked to", header.dbuf.linkname);
-               break;
-           case '2':
-               verb_print("symbolic link to", header.dbuf.linkname);
-               break;
-           case '6':   verb_print("", "fifo"); break;
-           case '3':
-           case '4':
-               if (verbose_flag) {
-                       char sizebuf[TSIZLEN + 1];
-
-                       strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
-                       sizebuf[TSIZLEN] = 0;
-                       string_print(NIL_PTR,
-                             "%s special file major %s minor %s\n",
-                                    (header.dbuf.typeflag == '3' ?
-                                     "character" : "block"),
-                                    header.dbuf.devmajor,
-                                    header.dbuf.devminor,
-                                    sizebuf);
-               }
-               break;
-           case '0':           /* official POSIX */
-           case 0:             /* also mentioned in POSIX */
-           case ' ':           /* ofetn used */
-               if (!is_dir(mem_name)) {
-                       if (verbose_flag)
-                               string_print(NIL_PTR, "%d tape blocks\n",
-                                            block_size());
-                       skip_entry();
-                       break;
-               } else          /* FALL TROUGH */
-           case '5':
-                       verb_print("", "directory");
-               break;
-           default:
-               string_print(NIL_PTR, "not recogised item %d\n",
-                            header.dbuf.typeflag);
-       }
-       flush();
-  }
-}
-
-void skip_entry()
-{
-  register int blocks = block_size();
-
-  while (blocks--) (void) bread(tar_fd, io_buffer, TBLOCK_SIZE);
-}
-
-void extract(file)
-register char *file;
-{
-  register int fd, r;
-  char *pd1, *pd2;             /* walk thru failed directory path */
-
-  switch (header.dbuf.typeflag) {
-      case '1':                        /* Link */
-       delete(file);
-       if (link(header.member.m_link, file) < 0)
-               string_print(NIL_PTR, "Cannot link %s to %s: %s\n",
-                            header.member.m_link, file, strerror(errno));
-       else if (verbose_flag)
-               string_print(NIL_PTR, "Linked %s to %s\n",
-                            header.member.m_link, file);
-       return;
-      case '5':                        /* directory */
-       if (!(file[0] == '.' && file[1] == '\0')) delete(file);
-       if ((file[0] == '.' && file[1] == '\0') || mkdir(file, 0700) == 0) {
-               do_chown(file);
-               verb_print("created directory", file);
-       } else {
-               string_print(NIL_PTR, "Can't make directory %s: %s\n",
-                               file, strerror(errno));
-       }
-       return;
-      case '3':                        /* character special */
-      case '4':                        /* block special */
-       {
-               int dmajor, dminor, mode;
-
-               dmajor = (int) convert(header.dbuf.devmajor, INT_TYPE);
-               dminor = (int) convert(header.dbuf.devminor, INT_TYPE);
-               mode = (header.dbuf.typeflag == '3' ? S_IFCHR : S_IFBLK);
-               delete(file);
-               if (mknod(file, mode, (dmajor << 8 | dminor)) == 0) {
-                       if (verbose_flag) string_print(NIL_PTR,
-                                    "made %s special file major %s minor %s\n",
-                                     (header.dbuf.typeflag == '3' ?
-                                      "character" : "block"),
-                                            header.dbuf.devmajor,
-                                            header.dbuf.devminor);
-                       do_chown(file);
-               }
-               else 
-               {
-                       string_print(NIL_PTR,
-                                    "cannot make %s special file major %s minor %s: %s\n",
-                                     (header.dbuf.typeflag == '3' ?
-                                      "character" : "block"),
-                                            header.dbuf.devmajor,
-                                            header.dbuf.devminor,
-                                            strerror(errno));
-               }
-               return;
-       }
-      case '2':                        /* symbolic link */
-#ifdef HAVE_SYMLINK
-       delete(file);
-       if (symlink(header.member.m_link, file) < 0)
-               string_print(NIL_PTR, "Cannot make symbolic link %s to %s: %s\n",
-                            header.member.m_link, file, strerror(errno));
-       else if (verbose_flag)
-               string_print(NIL_PTR, "Symbolic link %s to %s\n",
-                            header.member.m_link, file);
-       return;
-#endif
-      case '7':                        /* contiguous file -- what is this (KS) */
-       print("Not implemented file type\n");
-       return;                 /* not implemented, but break out */
-#ifdef HAVE_FIFO
-      case '6':                        /* fifo */
-       delete(file);
-       if (mkfifo(file, 0) == 0) {     /* is chmod'ed in do_chown */
-               do_chown(file);
-               verb_print("made fifo", file);
-       } else
-               string_print(NIL_PTR, "Can't make fifo %s: %s\n",
-                       file, strerror(errno));
-       return;
-#endif
-  }
-
-  /* Create regular file.  If failure, try to make missing directories. */
-  if ((fd = creat(file, 0600)) < 0) {
-       pd1 = file;
-       while ((pd2 = index(pd1, '/')) > (char *) 0) {
-               *pd2 = '\0';
-               if (access(file, 1) < 0)
-                       if (mkdir(file, 0777) < 0) {
-                               string_print(NIL_PTR, "Cannot mkdir %s: %s\n",
-                                       file, strerror(errno));
-                               return;
-                       } else
-                               string_print(NIL_PTR, "Made directory %s\n", file);
-               *pd2 = '/';
-               pd1 = ++pd2;
-       }
-       if ((fd = creat(file, 0600)) < 0) {
-               string_print(NIL_PTR, "Cannot create %s: %s\n",
-                       file, strerror(errno));
-               return;
-       }
-  }
-  copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
-  (void) close(fd);
-
-  do_chown(file);
-}
-
-void delete(file)
-char *file;
-{
-  /* remove a file or an empty directory */
-  struct stat stbuf;
-
-  if (stat(file, &stbuf) < 0) return;
-
-  if (S_ISDIR(stbuf.st_mode)) (void) rmdir(file); else (void) unlink(file);
-  /* leave error reporting to the create following soon. */
-}
-
-void do_chown(file)
-char *file;
-{
-  int uid = -1, gid = -1;      /* these are illegal ??? -- KS */
-
-  if (!chown_flag) {           /* set correct owner and group  -Dal */
-       if (header.dbuf.magic[TMAGLEN] == ' ')
-               header.dbuf.magic[TMAGLEN] = '\0';      /* some tars out there
-                                                        * ... */
-       if (strncmp(TMAGIC, header.dbuf.magic, (size_t) TMAGLEN)) {
-               struct passwd *pwd;
-               struct group *grp;
-
-               pwd = getpwnam(header.dbuf.uname);
-               if (pwd != NULL) uid = pwd->pw_uid;
-               grp = getgrnam(header.dbuf.gname);
-               if (grp != NULL) gid = grp->gr_gid;
-       }
-       if (uid == -1) uid = (int) convert(header.member.m_uid, INT_TYPE);
-       if (gid == -1) gid = (int) convert(header.member.m_gid, INT_TYPE);
-       if((gid_t)gid < 0) gid = 0;
-       chown(file, uid, gid);
-  }
-  chmod(file, u_mask & (int) convert(header.member.m_mode, INT_TYPE));
-
-  /* Should there be a timestamp if the chown failes? -- KS */
-  timestamp(file);
-
-}
-
-void timestamp(file)
-char *file;
-{
-  struct utimbuf buf;
-
-  buf.modtime = buf.actime = convert(header.dbuf.mtime, LONG_TYPE);
-  utime(file, &buf);
-}
-
-void copy(file, from, to, bytes)
-char *file;
-int from, to;
-register long bytes;
-{
-  register int rest;
-  int blocks = (int) ((bytes + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE);
-
-  if (verbose_flag)
-       string_print(NIL_PTR, "%s, %d tape blocks\n", file, blocks);
-
-  while (blocks--) {
-       (void) bread(from, io_buffer, TBLOCK_SIZE);
-       rest = (bytes > (long) TBLOCK_SIZE) ? TBLOCK_SIZE : (int) bytes;
-       mwrite(to, io_buffer, (to == tar_fd) ? TBLOCK_SIZE : rest);
-       bytes -= (long) rest;
-  }
-}
-
-long convert(str, type)
-char str[];
-int type;
-{
-  register long ac = 0L;
-  register int i;
-
-  for (i = 0; i < type; i++) {
-       if (str[i] >= '0' && str[i] <= '7') {
-               ac <<= 3;
-               ac += (long) (str[i] - '0');
-       }
-  }
-
-  return ac;
-}
-
-int checksum()
-{
-  register char *ptr = header.member.m_checksum;
-  register int ac = 0;
-
-  while (ptr < &header.member.m_checksum[INT_TYPE]) *ptr++ = ' ';
-
-  ptr = header.hdr_block;
-  while (ptr < &header.hdr_block[TBLOCK_SIZE]) ac += *ptr++;
-
-  return ac;
-}
-
-int is_dir(file)
-register char *file;
-{
-  while (*file++ != '\0');
-
-  return(*(file - 2) == '/');
-}
-
-
-char *path_name(file)
-register char *file;
-{
-
-  string_print(pathname, "%s%s", path, file);
-  return pathname;
-}
-
-void add_path(name)
-register char *name;
-{
-  register char *path_ptr = path;
-
-  while (*path_ptr) path_ptr++;
-
-  if (name == NIL_PTR) {
-       while (*path_ptr-- != '/');
-       while (*path_ptr != '/' && path_ptr != path) path_ptr--;
-       if (*path_ptr == '/') path_ptr++;
-       *path_ptr = '\0';
-  } else {
-       while (*name) {
-               if (path_ptr == &path[NAME_SIZE])
-                       error("Pathname too long", NIL_PTR);
-               *path_ptr++ = *name++;
-       }
-       *path_ptr++ = '/';
-       *path_ptr = '\0';
-  }
-}
-
-/*
- *     add a file to the archive
-*/
-void add_file(file)
-register char *file;
-{
-  struct stat st;
-  char *linkname;
-  register int fd = -1;
-  char namebuf[16];            /* -Dal */
-  char cwd[129];               /* -KS */
-
-#ifdef HAVE_SYMLINK
-  if (lstat(file, &st) < 0) {
-#else
-  if (stat(file, &st) < 0) {
-#endif
-       string_print(NIL_PTR, "%s: %s\n", file, strerror(errno));
-       return;
-  }
-  if (st.st_dev == ar_dev && st.st_ino == ar_inode) {
-       string_print(NIL_PTR, "Cannot tar current archive file (%s)\n", file);
-       return;
-  }                            /* marks@mgse Mon Sep 25 12:06:28 CDT 1989 */
-  if ((fd = add_open(file, &st)) < 0) {
-       string_print(NIL_PTR, "Cannot open %s\n", file);
-       return;
-  }
-  make_header(path_name(file), &st);
-  if ((linkname = is_linked(&st)) != NULL) {
-       strncpy(header.dbuf.linkname, linkname, (size_t) NAMSIZ);
-       header.dbuf.typeflag = '1';
-       if (verbose_flag) string_print(NIL_PTR, "linked %s to %s\n",
-                            header.dbuf.linkname, file);
-       string_print(header.member.m_checksum, "%I ", checksum());
-       mwrite(tar_fd, (char *) &header, sizeof(header));
-  } else {
-       is_added(&st, file);
-       switch (st.st_mode & S_IFMT) {
-           case S_IFREG:
-               header.dbuf.typeflag = '0';
-               string_print(header.member.m_checksum, "%I ", checksum());
-               mwrite(tar_fd, (char *) &header, sizeof(header));
-               copy(path_name(file), fd, tar_fd, (long) st.st_size);
-               break;
-           case S_IFDIR:
-               header.dbuf.typeflag = '5';
-               string_print(header.member.m_checksum, "%I ", checksum());
-               mwrite(tar_fd, (char *) &header, sizeof(header));
-               verb_print("read directory", file);
-               if (norec_flag) break;
-               if (NULL == getcwd(cwd, (int) sizeof cwd))
-                       string_print(NIL_PTR, "Error: cannot getcwd()\n");
-               else if (chdir(file) < 0)
-                       string_print(NIL_PTR, "Cannot chdir to %s: %s\n",
-                               file, strerror(errno));
-               else {
-                       add_path(file);
-#ifdef DIRECT_3
-                       {
-                               DIR *dirp;
-                               struct direct *dp;
-                               struct stat dst;
-
-                               add_close(fd);
-                               fd= 0;
-                               dirp = opendir(".");
-                               while (NULL != (dp = readdir(dirp)))
-                                       if (strcmp(dp->d_name, ".") == 0)
-                                               is_linked(&st);
-                                       else if (strcmp(dp->d_name, "..") == 0) {
-                                               if (stat("..", &dst) == 0)
-                                                       is_linked(&dst);
-                                       } else {
-                                               strcpy(namebuf, dp->d_name);
-                                               add_file(namebuf);
-                                       }
-                               closedir(dirp);
-                       }
-#else
-                       {
-                               int i;
-                               struct direct dir;
-                               struct stat dst;
-
-                               for (i = 0; i < 2; i++) {       /* . and .. */
-                                       mread(fd, &dir, sizeof(dir));
-                                       if (strcmp(dir.d_name, ".") == 0)
-                                               is_linked(&st);
-                                       else if (strcmp(dir.d_name, "..") == 0) {
-                                               if (stat("..", &dst) == 0)
-                                                       is_linked(&dst);
-                                       } else
-                                               break;
-                               }
-                               while (bread(fd, &dir, sizeof(dir)) == sizeof(dir))
-                                       if (dir.d_ino) {
-                                               strncpy(namebuf, dir.d_name,
-                                                  (size_t) DIRSIZ);
-                                               namebuf[DIRSIZ] = '\0';
-                                               add_file(namebuf);
-                                       }
-                       }
-#endif
-                       chdir(cwd);
-                       add_path(NIL_PTR);
-                       *file = 0;
-               }
-               break;
-#ifdef HAVE_SYMLINK
-           case S_IFLNK:
-               {
-                       int i;
-
-                       header.dbuf.typeflag = '2';
-                       verb_print("read symlink", file);
-                       i = readlink(file,
-                                    header.dbuf.linkname,
-                                 sizeof(header.dbuf.linkname) - 1);
-                       if (i < 0) {
-                               string_print(NIL_PTR,
-                                       "Cannot read symbolic link %s: %s\n",
-                                       file, strerror(errno));
-                               return;
-                       }
-                       header.dbuf.linkname[i] = 0;
-                       string_print(header.member.m_checksum, "%I ", checksum());
-                       mwrite(tar_fd, (char *) &header, sizeof(header));
-                       break;
-               }
-#endif
-#ifdef HAVE_FIFO
-           case S_IFIFO:
-               header.dbuf.typeflag = '6';
-               verb_print("read fifo", file);
-               string_print(header.member.m_checksum, "%I ", checksum());
-               mwrite(tar_fd, (char *) &header, sizeof(header));
-               break;
-#endif
-           case S_IFBLK:
-               header.dbuf.typeflag = '4';
-               if (verbose_flag) {
-                       char sizebuf[TSIZLEN + 1];
-
-                       strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
-                       sizebuf[TSIZLEN] = 0;
-                       string_print(NIL_PTR,
-                        "read block device %s major %s minor %s\n",
-                                    file, header.dbuf.devmajor, header.dbuf.devminor, sizebuf);
-               }
-               string_print(header.member.m_checksum, "%I ", checksum());
-               mwrite(tar_fd, (char *) &header, sizeof(header));
-               break;
-           case S_IFCHR:
-               header.dbuf.typeflag = '3';
-               if (verbose_flag) string_print(NIL_PTR,
-                                    "read character device %s major %s minor %s\n",
-                                    file, header.dbuf.devmajor, header.dbuf.devminor);
-               string_print(header.member.m_checksum, "%I ", checksum());
-               mwrite(tar_fd, (char *) &header, sizeof(header));
-               break;
-           default:
-               is_deleted(&st);
-               string_print(NIL_PTR, "Tar: %s unknown file type. Not added.\n", file);
-               *file = 0;
-       }
-  }
-
-  flush();
-  add_close(fd);
-}
-
-void verb_print(s1, s2)
-char *s1, *s2;
-{
-  if (verbose_flag) string_print(NIL_PTR, "%s: %s\n", s1, s2);
-}
-
-void add_close(fd)
-int fd;
-{
-  if (fd != 0) close(fd);
-}
-
-/*
- *     open file 'file' to be added to archive, return file descriptor
-*/
-int add_open(file, st)
-char *file;
-struct stat *st;
-{
-  int fd;
-  if (((st->st_mode & S_IFMT) != S_IFREG) &&
-      ((st->st_mode & S_IFMT) != S_IFDIR))
-       return 0;
-  fd = open(file, O_RDONLY);
-  if (fd == -1)
-       fprintf(stderr, "open failed: %s\n", strerror(errno));
-  return fd;
-}
-
-void make_header(file, st)
-char *file;
-register struct stat *st;
-{
-  register char *ptr = header.member.m_name;
-  struct passwd *pwd;
-  struct group *grp;
-
-  clear_header();
-
-  while (*ptr++ = *file++);
-
-  if ((st->st_mode & S_IFMT) == S_IFDIR) {     /* fixed test  -Dal */
-       *(ptr - 1) = '/';
-  }
-  string_print(header.member.m_mode, "%I ", st->st_mode & 07777);
-  string_print(header.member.m_uid, "%I ", st->st_uid);
-  string_print(header.member.m_gid, "%I ", st->st_gid);
-  if ((st->st_mode & S_IFMT) == S_IFREG)
-       string_print(header.member.m_size, "%L ", st->st_size);
-  else
-       strncpy(header.dbuf.size, "0", (size_t) TSIZLEN);
-  string_print(header.member.m_time, "%L ", st->st_mtime);
-  strncpy(header.dbuf.magic, TMAGIC, (size_t) TMAGLEN);
-  header.dbuf.version[0] = 0;
-  header.dbuf.version[1] = 0;
-  pwd = getpwuid(st->st_uid);
-  strncpy(header.dbuf.uname,
-       (pwd != NULL ? pwd->pw_name : "nobody"), TUNMLEN);
-  grp = getgrgid(st->st_gid);
-  strncpy(header.dbuf.gname,
-       (grp != NULL ? grp->gr_name : "nobody"), TGNMLEN);
-  if (st->st_mode & (S_IFBLK | S_IFCHR)) {
-       string_print(header.dbuf.devmajor, "%I ", (st->st_rdev >> 8));
-       string_print(header.dbuf.devminor, "%I ", (st->st_rdev & 0xFF));
-  }
-  header.dbuf.prefix[0] = 0;
-}
-
-void is_added(st, file)
-struct stat *st;
-char *file;
-{
-  struct link *new;
-  char *name;
-
-  if ((*file == 0) || (st->st_nlink == 1)) return;
-  name = path_name(file);
-  new = (struct link *) malloc(sizeof(struct link) + strlen(name));
-  if (new == NULL) {
-       print("Out of memory\n");
-       return;
-  }
-  new->next = link_top;
-  new->dev = st->st_dev;
-  new->ino = st->st_ino;
-  new->nlink = st->st_nlink - 1;
-  strcpy(new->name, name);
-  link_top = new;
-}
-
-void is_deleted(st)
-struct stat *st;
-{
-  struct link *old;
-
-  if ((old = link_top) != NULL) {
-       link_top = old->next;
-       free(old);
-  }
-}
-
-char *is_linked(st)
-struct stat *st;
-{
-  struct link *cur = link_top;
-  struct link **pre = &link_top;
-  static char name[NAMSIZ];
-
-  while (cur != NULL)
-       if ((cur->dev != st->st_dev) || (cur->ino != st->st_ino)) {
-               pre = &cur->next;
-               cur = cur->next;
-       } else {
-               if (--cur->nlink == 0) {
-                       *pre = cur->next;
-                       strncpy(name, cur->name, NAMSIZ);
-                       return name;
-               }
-               return cur->name;
-       }
-  return NULL;
-}
-
-void clear_header()
-{
-  register char *ptr = header.hdr_block;
-
-  while (ptr < &header.hdr_block[TBLOCK_SIZE]) *ptr++ = '\0';
-}
-
-void adjust_boundary()
-{
-  clear_header();
-  mwrite(tar_fd, (char *) &header, sizeof(header));
-#ifndef POSIX_COMP
-  while (total_blocks++ < BLOCK_BOUNDARY)
-       mwrite(tar_fd, (char *) &header, sizeof(header));
-#else
-  mwrite(tar_fd, (char *) &header, sizeof(header));
-#endif
-  (void) close(tar_fd);
-}
-
-void mread(fd, address, bytes)
-int fd, bytes;
-char *address;
-{
-  if (bread(fd, address, bytes) != bytes) error("Tar: read error.", NIL_PTR);
-}
-
-void mwrite(fd, address, bytes)
-int fd, bytes;
-char *address;
-{
-  if (bwrite(fd, address, bytes) != bytes) error("Tar: write error.", NIL_PTR);
-
-  total_blocks++;
-}
-
-int bread(fd, address, bytes)
-int fd, bytes;
-char *address;
-{
-  int n = 0, r;
-
-  while (n < bytes) {
-       if ((r = read(fd, address + n, bytes - n)) <= 0) {
-               if (r < 0) return r;
-               break;
-       }
-       n += r;
-  }
-  return n;
-}
-
-int bwrite(fd, address, bytes)
-int fd, bytes;
-char *address;
-{
-  int n = 0, r;
-
-  while (n < bytes) {
-       if ((r = write(fd, address + n, bytes - n)) <= 0) {
-               if (r < 0) return r;
-               break;
-       }
-       n += r;
-  }
-  return n;
-}
-
-char output[TBLOCK_SIZE];
-void print(str)
-register char *str;
-{
-  int fd = (tar_fd == 1 ? 2 : 1);
-  static int indx = 0;
-
-  if (str == NIL_PTR) {
-       write(fd, output, indx);
-       indx = 0;
-       return;
-  }
-  while (*str) {
-       output[indx++] = *str++;
-       if (indx == TBLOCK_SIZE) {
-               write(fd, output, TBLOCK_SIZE);
-               indx = 0;
-       }
-  }
-}
-
-char *num_out(number)
-register long number;
-{
-  static char num_buf[12];
-  register int i;
-
-  for (i = 11; i--;) {
-       num_buf[i] = (number & 07) + '0';
-       number >>= 3;
-  }
-
-  return num_buf;
-}
-
-/*VARARGS2*/
-#if __STDC__
-void string_print(char *buffer, char *fmt,...)
-#else
-void string_print(buffer, fmt)
-char *buffer;
-char *fmt;
-#endif
-{
-  va_list args;
-  register char *buf_ptr;
-  char *scan_ptr;
-  char buf[STRING_SIZE];
-  BOOL pr_fl, i;
-
-  if (pr_fl = (buffer == NIL_PTR)) buffer = buf;
-
-  va_start(args, fmt);
-  buf_ptr = buffer;
-  while (*fmt) {
-       if (*fmt == '%') {
-               fmt++;
-               switch (*fmt++) {
-                   case 's':
-                       scan_ptr = (char *) (va_arg(args, char *));
-                       break;
-                   case 'I':
-                       scan_ptr = num_out((long) (va_arg(args, int)));
-                       for (i = 0; i < 5; i++) scan_ptr++;
-                       break;
-                   case 'L':
-                       scan_ptr = num_out((long) va_arg(args, long));
-                       break;
-                   case 'd':
-                       scan_ptr = num_out((long) va_arg(args, int));
-                       while (*scan_ptr == '0') scan_ptr++;
-                       scan_ptr--;
-                       break;
-                   default:    scan_ptr = "";
-               }
-               while (*buf_ptr++ = *scan_ptr++);
-               buf_ptr--;
-       } else
-               *buf_ptr++ = *fmt++;
-  }
-  *buf_ptr = '\0';
-
-  if (pr_fl) print(buffer);
-  va_end(args);
-}