diff --git a/commands/pax/Makefile b/commands/pax/Makefile index f0611b4c2..255f70e15 100644 --- a/commands/pax/Makefile +++ b/commands/pax/Makefile @@ -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 diff --git a/commands/pax/build b/commands/pax/build deleted file mode 100644 index 8f58e6df9..000000000 --- a/commands/pax/build +++ /dev/null @@ -1 +0,0 @@ -make diff --git a/commands/pax/cpio.1 b/commands/pax/cpio.1 new file mode 100644 index 000000000..7ff188122 --- /dev/null +++ b/commands/pax/cpio.1 @@ -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. diff --git a/commands/pax/options.c b/commands/pax/options.c index 155d3c0ff..66e963c04 100644 --- a/commands/pax/options.c +++ b/commands/pax/options.c @@ -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 index 000000000..059340446 --- /dev/null +++ b/commands/pax/pax.1 @@ -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 +.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 +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 +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 >> +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 == +For pathnames representing a symbolic link, the output has the format: +.Dl => +Where 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 +as soon as processing begins on that file or +archive member. +The trailing +.Dv , +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. diff --git a/commands/pax/pax.c b/commands/pax/pax.c index a687d715f..f249a28d5 100644 --- a/commands/pax/pax.c +++ b/commands/pax/pax.c @@ -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 */ diff --git a/commands/pax/pax.h b/commands/pax/pax.h index f0b64ac1c..afbc114df 100644 --- a/commands/pax/pax.h +++ b/commands/pax/pax.h @@ -56,12 +56,12 @@ /* * 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 index 000000000..ff66ccbef --- /dev/null +++ b/commands/pax/tar.1 @@ -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 >> +.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. diff --git a/commands/simple/Makefile b/commands/simple/Makefile index f1d7327c3..df2e3defd 100644 --- a/commands/simple/Makefile +++ b/commands/simple/Makefile @@ -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 index 0ee047444..000000000 --- a/commands/simple/tar.c +++ /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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* need NULL */ -#include - -#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 -#define direct dirent /* stupid BSD non-POSIX compatible name! */ -#else /* BSD */ -#include -#include -#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); -}