-# 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>
--- /dev/null
+.\"-
+.\" 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.
}
}
+static void
+tar_set_action(int op)
+{
+ if (act != ERROR && act != op)
+ tar_usage();
+ act = op;
+}
/*
* tar_options()
/*
* create an archive
*/
- act = ARCHIVE;
+ tar_set_action(ARCHIVE);
break;
case 'e':
/*
/*
* append to the archive
*/
- act = APPND;
+ tar_set_action(APPND);
break;
case 's':
/*
/*
* list contents of the tape
*/
- act = LIST;
+ tar_set_action(LIST);
break;
case 'v':
/*
* extract an archive, preserving mode,
* and mtime if possible.
*/
- act = EXTRACT;
+ tar_set_action(EXTRACT);
pmtime = 1;
break;
case 'z':
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;
--- /dev/null
+.\"-
+.\" 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.
/*
* 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 */
/*
* 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
--- /dev/null
+.\"-
+.\" 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.
synctree \
sysenv \
tail \
- tar \
tcpd \
tcpdp \
tcpstat \
$(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 $@
/usr/bin/sysenv \
/bin/sysenv \
/usr/bin/tail \
- /usr/bin/tar \
/usr/bin/tcpd \
/usr/bin/tcpdp \
/usr/bin/tcpstat \
/usr/bin/tail: tail
install -cs -o bin $> $@
-/usr/bin/tar: tar
- install -cs -o bin $> $@
-
/usr/bin/tcpd: tcpd
install -cs -o bin $> $@
+++ /dev/null
-/* 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);
-}