[comp.sources.atari.st] v02i053: gnutar -- GNU's version of UNIX "tar" part07/08

koreth%panarthea.ebay@sun.com (Steven Grimm) (07/20/89)

Submitted-by: 7103_300@uwovax.uwo.ca (Eric R. Smith)
Posting-number: Volume 2, Issue 53
Archive-name: gnutar/part07

#!/bin/sh
# this is part 7 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file TAR.TEX continued
#
CurArch=7
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file TAR.TEX"
sed 's/^X//' << 'SHAR_EOF' >> TAR.TEX
X
X@item -C @var{dir}
XThe @samp{-C} option causes @code{tar} to change into the the
Xdirectory @var{dir} before continuing.  This option is usually
Xinterspersed with the files @code{tar} is to work on.  For example,
X
X@example 
Xtar -c iggy ziggy -C baz melvin
X@end example
X
X@noindent
Xwill place the files @file{iggy} and @file{ziggy} from the current
Xdirectory on the tape, followed by the file @file{melvin} from the
Xdirectory @file{baz}.  This option is especially useful when you have
Xseveral widely separated files that you want to store in the same
Xdirectory in the archive.
X
XNote that the file @file{melvin} is recorded in the archive under the
Xprecise name @file{melvin}, @emph{not} @file{baz/melvin}.  Thus, the
Xarchive will contain three files that all appear to have come from the
Xsame directory; if the archive is extracted with plain @samp{tar -x},
Xall three files will be created in the current directory.
X
XContrast this with the command
X
X@example
Xtar -c iggy ziggy bar/melvin
X@end example
X
X@noindent
Xwhich records the third file in the archive under the name @file{bar/melvin}
Xso that, if plain @samp{tar -x} is used, the third file will be created
Xin a subdirectory named @file{bar}.
X
X@item -M
XThe @samp{-M} option causes @code{tar} to write a @dfn{multi-volume}
Xarchive--one that may be larger than will fit on the medium used to
Xhold it.
X
XWhen this option is used, @code{tar} will not abort when it cannot
Xread or write any more data.  Instead, it will ask you to prepare a
Xnew volume.  If the archive is on a magnetic tape, you should change
Xtapes now; if the archive is on a floppy disk, you should change
Xdisks, etc.
X
XEach volume of a multi-volume archive is an independent tar archive,
Xcomplete in itself.  For example, you can list or extract any volume
Xalone (just don't specify @samp{-M}).  However, if one file in the
Xarchive is split across volumes, the only way to extract it
Xsuccessfully is with a multi-volume extract command (@samp{-xM})
Xstarting on or before the volume where the file begins.
X
X@item -N @var{date}
XThis option causes @code{tar} to only work on files whose modification
Xor inode-changed times are newer than the @var{date} given.  The main
Xuse is for creating an archive; then only new files are written.  If
Xextracting, only newer files are extracted.
X
XRemember that the entire date argument should be quoted if it contains
Xany spaces.
X
XThe date is parsed using @code{getdate}.
X
X@item -R
XIf @samp{-R} is used, @code{tar} prints, along with every message it
Xwould normally produce, the record number within the archive where
Xthe message occurred.  This option is especially useful when reading
Xdamaged archives, since it helps pinpoint the damaged sections.
X
XThis can also be useful when making a log of a file-system backup tape,
Xsince the results allow you to find the file you want to retrieve
Xon several backup tapes and choose the tape where the file appears
Xearliest (closest to the front of the tape).
X
X@item -T @var{filename}
XInstead of taking the list of files to work on from the command
Xline, the list of files to work on is read from the file
X@var{filename}.  If @var{filename} is given as @samp{-}, the list is
Xread from standard input.  Note that using both @samp{-T -} and
X@samp{-f -} will not work unless you are using the @samp{-c} command.
X
X@item -v
XThis option causes @code{tar} to be verbose about the actions it is
Xtaking.
X
XNormally, the @samp{-t} command to list an archive prints
Xjust the file names (one per line) and the other commands are silent.
X
X@samp{-tv} prints a full line of information about each file, like the
Xoutput of @samp{ls -l}.  @samp{-v} with any other command (aside from
X@samp{-t}) prints just the name of each file operated on.
X
XThe output from @samp{-v} appears on the standard output except when
Xcreating or updating an archive to the standard output, 
Xin which case the output from @samp{-v} is sent to the standard
Xerror.
X
X@item -version
X
XThis option causes @code{tar} to print out its version number to the
Xstandard error.  In order to avoid being confused with the @samp{-v}
Xoption, @samp{-version} must be given as a separate option,
Xpreceded by a hyphen.
X
X@item -w
XThis option causes @code{tar} to print a message for each action it
Xintends to take, and ask for confirmation on the terminal.  To
Xconfirm, you must type a line of input.  If your input line begins
Xwith @samp{y}, the action is performed, otherwise it is skipped.
X
XThe actions which require confirmation include adding a file to the
Xarchive, extracting a file from the archive, deleting a file from the
Xarchive, and deleting a file from disk.
X
XIf @code{tar} is reading the archive from the standard input,
X@code{tar} will open the file @file{/dev/tty} to ask for
Xconfirmation on.
X
X@item -X @var{file}
XThis option causes @code{tar} to read a list of filenames
X(actually regular expressions) from the file @var{file};
X@code{tar} will ignore files with those names.
XThus if @code{tar} is called as @samp{tar -c -X foo .}
Xand the file @file{foo} contains @samp{*.o} none of the files
Xwhose names end in @file{.o} in the current directory will be added
Xto the archive.  Multiple @code{-X} options may be given.
X
X@item -z
X@itemx -Z
XThe archive should be compressed as it is written, or decompressed
Xas it is read, using the @code{compress} program.  This option works
Xon physical devices (tape drives, etc.) and remote files as well as
Xon normal files; data to or from such devices or remote files is
Xreblocked by another copy of the @code{tar} program to enforce the
Xspecified (or default) block size.  The default compression
Xparameters are used; if you need to override them, avoid the
X@samp{-z} option and run @code{compress} explicitly.
X
XNote that the @samp{-z} option will not work with the @samp{-M} option,
Xor with the @samp{-u}, @samp{-r}, @samp{-A}, or @samp{-D} commands.
X@end table
X
X@node Creation Options, Extraction Options, General Options, Options
X@section Options for Creating Or Updating an Archive
X
XThese options are used to control which files @code{tar} puts in an
Xarchive, or to control the format the archive is written in (@pxref{Format}).
X
XExcept as noted below, these options are useful with the @samp{-c},
X@samp{-r}, @samp{-u}, @samp{-A}, and @samp{-D} commands.
XAlso note that the @samp{-B} option, (@pxref{Extraction Options}),
Xis also useful with the @samp{-r}, @samp{-u}, @samp{-A}, and @samp{-D} commands.
X
X@table @code
X@c this command no longer exists  -D is now the old -J command
X@c @item -D
X@c The @samp{-D} option tells @code{tar} to only store entries for the
X@c directories it encounters, and to not to store the files inside the
X@c directories.  In conjunction with @code{find} this is useful for
X@c creating incremental dumps for archival backups, similar to those
X@c produced by @code{dump}.
X
X@item -G
XThis option should only be used when creating an incremental backup of
Xa filesystem.  When the @samp{-G} option is used, @code{tar} writes, at
Xthe beginning of the archive, an entry for each of the directories that
Xwill be operated on.  The entry for a directory includes a list of all
Xthe files in the directory at the time the dump was done, and a flag
Xfor each file indicating whether the file is going to be put in the
Xarchive.  This information is used when doing a complete incremental
Xrestore.
X
XNote that this option causes @code{tar} to create a non-standard
Xarchive that may not be readable by non-GNU versions of the @code{tar}
Xprogram.
X
X@item -h
XIf @samp{-h} is used, when @code{tar} encounters a symbolic link, it
Xwill archive the linked-to file, instead of simply recording the
Xpresence of a symbolic link.  If the linked-to file is archived
Xagain, an entire second copy of it will be archived, instead of a
Xlink.  This could be considered a bug.
X
X@item -l
XThis option causes @code{tar} to not cross filesystem boundaries
Xwhen archiving parts of a directory tree.  This option only
Xaffects files that are archived because they are in a directory that
Xis archived; files named on the command line are archived
Xregardless, and they can be from various file systems.
X
XThis option is useful for making full or incremental archival backups of
Xa file system, as with the Unix @code{dump} command.
X
XFiles which are skipped due to this option are mentioned on the
Xstandard error.
X
X@item -o
XThis option causes @code{tar} to write an old format archive, which
Xdoes not include information about directories, pipes, fifos,
Xcontiguous files, or device files, and specifies file ownership by
Xnumeric user- and group-ids rather than by user and group names.  In
Xmost cases, a @emph{new} format archive can be read by an @emph{old}
X@code{tar} program without serious trouble, so this option should
Xseldom be needed.  When updating an archive, do not use @samp{-o}
Xunless the archive was created with the @samp{-o} option.
X
X@item -V @var{name}
XThis option causes @code{tar} to write out a @dfn{volume header} at
Xthe beginning of the archive.  If @samp{-M} is used, each volume of
Xthe archive will have a volume header of @samp{@var{name} Volume @var{N}},
Xwhere @var{N} is 1 for the first volume, 2 for the next, and so on.
X
X@item -W
XThis option causes @code{tar} to verify the archive after writing it.
XEach volume is checked after it is written, and any discrepancies are
Xrecorded on the standard error output.
X
XVerification requires that the archive be on a back-space-able medium.
XThis means pipes, some cartridge tape drives, and some other devices
Xcannot be verified.
X@end table
X
X@node Extraction Options, Option Syntax, Creation Options, Options
X@section Options for Listing Or Extracting Files
X
XThe options in this section are meaningful with the @samp{-x} command.
XUnless otherwise stated, they are also meaningful with the @samp{-t}
Xcommand.
X
X@table @code
X@item -B
XIf @samp{-B} is used, @code{tar} will not panic if an attempt to
Xread a block from the archive does not return a full block.  Instead,
X@code{tar} will keep reading until it has obtained a full block.
X
XThis option is turned on by default when @code{tar} is reading an
Xarchive from standard input, or from a remote machine.  This is
Xbecause on BSD Unix systems a read of a pipe will return however much
Xhappens to be in the pipe, even if it is less than @code{tar}
Xrequested.  If this option was not used, @code{tar} would fail
Xas soon as it read an incomplete block from the pipe.
X
XThis option is also useful with the commands for updating an archive.
X
X@item -G
XThe @samp{-G} option means the archive is an incremental backup.
XIts meaning depends on the command that it modifies.
X
XIf the @samp{-G} option is used with @samp{-t}, @code{tar} will list,
Xfor each directory in the archive, the list of files in that
Xdirectory at the time the archive was created.  This information is
Xput out in a format that is not easy for humans to read, but which
Xis unambiguous for a program: each filename is preceded by either a
X@samp{Y} if the file is present in the archive, or an @samp{N} if the
Xfile is a directory, or is not included in the archive.  Each
Xfilename is terminated by a null character.  The last file is
Xfollowed by an additional null and a newline to indicate the end of
Xthe data.
X
XIf the @samp{-G} option is used with @samp{-x}, then when the entry
Xfor a directory is found, all files that currently exist in that directory
Xbut are not listed in the archive @emph{are deleted from the directory}.
X
XThis behavior is convenient when you are restoring a damaged file system
Xfrom a succession of incremental backups: it restores the entire state
Xof the file system to that which obtained when the backup was made.
XIf you don't use @samp{-G}, the file system will probably fill up
Xwith files that shouldn't exist any more.
X
X@item -i
XThe @samp{-i} option causes @code{tar} to ignore blocks of zeros in the
Xarchive.  Normally a block of zeros indicates the end of the
Xarchive, but when reading a damaged archive, or one which was created by
X@code{cat}-ing several archives together, this option allows
X@code{tar} to read the entire archive.  This option is not on by
Xdefault because many versions of @code{tar} write garbage after the
Xzeroed blocks.
X
XNote that this option causes @code{tar} to read to the end of the
Xarchive file, which may sometimes avoid problems when multiple files
Xare stored on a single physical tape.
X
X@item -k
XThe @samp{-k} option prevents @code{tar} from over-writing existing
Xfiles with files with the same name from the archive.
X
XThe @samp{-k} option is meaningless with @samp{-t}.
X
X@item -K @var{filename}
XThe @samp{-K} option causes @code{tar} to begin extracting or listing
Xthe archive with the file @var{filename}, and to consider only the
Xfiles starting at that point in the archive.  This is useful if a
Xprevious attempt to extract files failed when it reached
X@var{filename} due to lack of free space.  (This assumes, of course,
Xthat there is now free space, or that you are now extracting into a
Xdifferent file system.)
X
X@item -m
XWhen this option is used, @code{tar} leaves the modification times of
Xthe files it extracts as the time when the files were extracted,
Xinstead of setting it to the time recorded in the archive.
X
XThe @samp{-m} option is meaningless with @samp{-t}.
X
X@item -O
XWhen this option is used, instead of creating the files
Xspecified, @code{tar} writes the contents of the files
Xextracted to its standard output.  This may be useful if you
Xare only extracting the files in order to send them through a
Xpipeline.
X
XThe @samp{-O} option is meaningless with @samp{-t}.
X
X@item -p
XThis option causes @code{tar} to set the modes (access permissions) of
Xextracted files exactly as recorded in the archive.  If this option is
Xnot used, the current @code{umask} setting limits the permissions on
Xextracted files.
X
XThe @samp{-p} option is meaningless with @samp{-t}.
X
X@item -s
XThe @samp{-s} option tells @code{tar} that the list of filenames to be
Xlisted or extracted is sorted in the same order as the files in the
Xarchive.  This allows a large list of names to be used, even on a
Xsmall machine that would not otherwise be able to hold all the names
Xin memory at the same time.  Such a sorted list can easily be created
Xby running @samp{tar -t} on the archive and editing its output.
X
X@samp{-s} is probably never needed on modern computer systems.
X@end table
X
X@node Option Syntax,, Extraction Options, Options
X@section Old Syntax for Options
X
XFor compatibility with Unix @code{tar}, the first argument can contain
Xoption letters in addition to the command letter; for example, @samp{tar
Xcv} specifies the option @samp{-v} in addition to the command @samp{-c}.
XThe first argument to GNU @code{tar} is always treated as command and
Xoption letters even if it doesn't start with @samp{-}.
X
XSome options need their own arguments; for example, @samp{-f} is followed
Xby the name of the archive file.  When the option is given separately, its
Xargument follows it, as is usual for Unix programs.  For example:
X
X@example
Xtar -c -v -b 20 -f /dev/rmt0
X@end example
X
XWhen options that need arguments are given together with the command, all
Xthe associated arguments follow, in the same order as the options.  Thus,
Xthe example above could also be written in the old style as follows:
X
X@example
Xtar cvbf 20 /dev/rmt0
X@end example
X
X@noindent
XHere @samp{20} is the argument of @samp{-b} and @file{/dev/rmt0} is the
Xargument of @samp{-f}.
X
X@node FullDumps, Extraction Options, IncDumps, Top
X@chapter Using @code{tar} to Perform Full Dumps
XFull dumps should only be made when no other people or programs are
Xmodifying files in the filesystem.  If files are modified while
X@code{tar} is making the backup, they may not be stored properly in
Xthe archive, in which case you won't be able to restore them if you
Xhave to.
X
XYou will want to use the @samp{-V} option to give the archive a
Xvolume label, so you can tell what this archive is even if the label
Xfalls off the tape, or anything like that.
X
XUnless the filesystem you are dumping is guaranteed to fit on one
Xvolume, you will need to use the @samp{-M} option.  Make sure you
Xhave enough tapes on hand to complete the backup.
X
XIf you want to dump each filesystem separately you will need to use
Xthe @samp{-l} option to prevent @code{tar} from crossing filesystem
Xboundaries when storing (sub)directories.
X
XThe @samp{-G} option is not needed, since this is a complete copy of
Xeverything in the filesystem, and a full restore from this backup
Xwould only be done onto a completely empty disk.
X
XUnless you are in a hurry, and trust the @code{tar} program (and
Xyour tapes), it is a good idea to use the @code{-W} (verify) option,
Xto make sure your files really made it onto the dump properly.  This
Xwill also detect cases where the file was modified while (or just
Xafter) it was being archived.
X
X@node IncDumps, FullDumps, Problems, Top
X@chapter Using @code{tar} to Perform Incremental Dumps
XPerforming incremental dumps is similar to performing full dumps,
Xalthough a few more options will usually be needed.
X
XYou will need to use the @samp{-N @var{date}} option to tell @code{tar} to
Xonly store files that have been modified since @var{date}.
X@var{date} should be the date and time of the last full/incremental
Xdump.
X
XA standard scheme is to do a @samp{monthly} (full) dump once a month,
Xa @samp{weekly} dump once a week of everything since the last monthly and
Xa @samp{daily} every day of everything since the last (weekly or monthly)
Xdump.
X
XHere is a copy of the script used to dump the filesystems of the
Xmachines here at the Free Software Foundation.  This script is run
X(semi-)automatically late at night when people are least likely to
Xbe using the machines.  This script dumps several filesystems from
Xseveral machines at once (by using a network-filesystem).  The
Xoperator is responsible for ensuring that all the machines will be
Xup at the time the dump happens.  If a machine is not running, its
Xfiles will not be dumped, and the next day's incremental dump will
X@emph{not} store files that would have gone onto that dump.
X
X@example
X#!/bin/csh
X# Dump thingie
Xset now = `date`
Xset then = `cat date.nfs.dump`
X/u/hack/bin/tar -c -G -v\
X -f /dev/rtu20\
X -b 126\
X -N "$then"\
X -V "Dump from $then to $now"\
X /alpha-bits/gp\
X /gnu/hack\
X /hobbes/u\
X /spiff/u\
X /sugar-bombs/u
Xecho $now > date.nfs.dump
Xmt -f /dev/rtu20 rew
X@end example
X
XOutput from this script is stored in a file, for the operator to
Xread later.
X
XThis script uses the file @file{date.nfs.dump} to store the date/time of
Xthe last dump.
X
XSince this is a streaming tape drive, no attempt to verify the
Xarchive is done.  This is also why the high blocking factor (126) is
Xused.  The tape drive must also be rewound by the @code{mt} command
Xafter the dump is made.
X
X@node Problems, IncDumps, Format, Top
X@chapter Common Problems Using @code{tar}
X
XIn order to update an archive, @code{tar} must be able to backspace
Xthe archive in order to re-read or re-write a block that was just read
X(or written).  This is currently possible only on two kinds of
Xfiles:  normal disk files (or any other file that can be
Xbackspaced with @code{lseek()}), and industry-standard 9-track magnetic
Xtape (or any other kind of tape that can be backspaced with
X@code{ioctl(@dots{},MTIOCTOP,@dots{})}).
X
XThis means that the @samp{-r}, @samp{-u}, @samp{-A}, and @samp{-D}
Xcommands will not work on any other kind of file.  Some media simply
Xcannot be backspaced, which means these commands and options will
Xnever be able to work on them.  These non-backspacing media include
Xpipes and cartridge tape drives.
X
XSome other media can be backspaced, and @code{tar} will work on them
Xonce it is modified to do so.
X
XArchives created with the @samp{-M}, @samp{-V}, and @samp{-G}
Xoptions may not be readable by other version of @code{tar}.  In particular,
Xrestoring a file that was split over a volume boundary will require
Xsome careful work with @code{dd}, if it can be done at all.  Other versions
Xof @code{tar} may also create an empty file whose name is that of
Xthe volume header.  Some versions of @code{tar} may create normal
Xfiles instead of directories archived with the @samp{-G} option.
X
X@node Rem Tape, IncDumps, Format, Top
X@chapter The Remote Tape Server
XIn order to access the tape drive on a remote machine, @code{tar}
Xuses the remote tape server written at the University of California
Xat Berkeley.  The remote tape server must be installed as
X@file{/etc/rmt} on any machine whose tape drive you want to use.
X@code{tar} calls @file{/etc/rmt} by running an @code{rsh} or
X@code{remsh} to the remote machine, optionally using a different
Xlogin name if one is supplied.
X
XA copy of the source for the remote tape server is provided.  It is
XCopyright @copyright 1983 by the Regents of the University of California, but
Xcan be freely distributed.  Instructions for compiling and
Xinstalling it are included in the @file{Makefile}.
X
XThe remote tape server may need to be modified in order to run on a
Xnon-4.3BSD system.
X
X@node Format, Rem Tape, , Top
X@chapter The Format of a @code{tar} Archive
XThis chapter is based heavily on John Gilmore's @i{tar}(5) manual page
Xfor the public domain @code{tar} that GNU @code{tar} is based on.
X
X@section The Standard Format
XA @dfn{tar tape} or file contains a series of records.  Each record
Xcontains @code{RECORDSIZE} bytes.  Although this format may be
Xthought of as being on magnetic tape, other media are often used.
X
XEach file archived is represented by a header record which describes
Xthe file, followed by zero or more records which give the contents
Xof the file.  At the end of the archive file there may be a record
Xfilled with binary zeros as an end-of-file marker.  A reasonable
Xsystem should write a record of zeros at the end, but must not
Xassume that such a record exists when reading an archive.
X
XThe records may be @dfn{blocked} for physical I/O operations.  Each
Xblock of @var{N} records (where @var{N} is set by the @samp{-b}
Xoption to @code{tar}) is written with a single @code{write()}
Xoperation.  On magnetic tapes, the result of such a write is a
Xsingle tape record.  When writing an archive, the last block of
Xrecords should be written at the full size, with records after the
Xzero record containing all zeroes.  When reading an archive, a
Xreasonable system should properly handle an archive whose last block
Xis shorter than the rest, or which contains garbage records after a
Xzero record.
X
XThe header record is defined in C as follows:
X
X@example
X/*
X * Standard Archive Format - Standard TAR - USTAR
X */
X#define  RECORDSIZE  512
X#define  NAMSIZ      100
X#define  TUNMLEN      32
X#define  TGNMLEN      32
X
Xunion record @{
X    char        charptr[RECORDSIZE];
X    struct header @{
X        char    name[NAMSIZ];
X        char    mode[8];
X        char    uid[8];
X        char    gid[8];
X        char    size[12];
X        char    mtime[12];
X        char    chksum[8];
X        char    linkflag;
X        char    linkname[NAMSIZ];
X        char    magic[8];
X        char    uname[TUNMLEN];
X        char    gname[TGNMLEN];
X        char    devmajor[8];
X        char    devminor[8];
X    @} header;
X@};
X
X/* The checksum field is filled with this while the checksum is computed. */
X#define    CHKBLANKS    "        "        /* 8 blanks, no null */
X
X/* The magic field is filled with this if uname and gname are valid. */
X#define    TMAGIC    "ustar  "        /* 7 chars and a null */
X
X/* The magic field is filled with this if this is a GNU format dump entry */
X#define    GNUMAGIC  "GNUtar "        /* 7 chars and a null */
X
X/* The linkflag defines the type of file */
X#define  LF_OLDNORMAL '\0'       /* Normal disk file, Unix compatible */
X#define  LF_NORMAL    '0'        /* Normal disk file */
X#define  LF_LINK      '1'        /* Link to previously dumped file */
X#define  LF_SYMLINK   '2'        /* Symbolic link */
X#define  LF_CHR       '3'        /* Character special file */
X#define  LF_BLK       '4'        /* Block special file */
X#define  LF_DIR       '5'        /* Directory */
X#define  LF_FIFO      '6'        /* FIFO special file */
X#define  LF_CONTIG    '7'        /* Contiguous file */
X
X/* Further link types may be defined later. */
X
X/* Bits used in the mode field - values in octal */
X#define  TSUID    04000        /* Set UID on execution */
X#define  TSGID    02000        /* Set GID on execution */
X#define  TSVTX    01000        /* Save text (sticky bit) */
X
X/* File permissions */
X#define  TUREAD   00400        /* read by owner */
X#define  TUWRITE  00200        /* write by owner */
X#define  TUEXEC   00100        /* execute/search by owner */
X#define  TGREAD   00040        /* read by group */
X#define  TGWRITE  00020        /* write by group */
X#define  TGEXEC   00010        /* execute/search by group */
X#define  TOREAD   00004        /* read by other */
X#define  TOWRITE  00002        /* write by other */
X#define  TOEXEC   00001        /* execute/search by other */
X@end example
X
XAll characters in header records are represented by using 8-bit
Xcharacters in the local variant of ASCII.  Each field within the
Xstructure is contiguous; that is, there is no padding used within
Xthe structure.  Each character on the archive medium is stored
Xcontiguously.
X
XBytes representing the contents of files (after the header record of
Xeach file) are not translated in any way and are not constrained to
Xrepresent characters in any character set.  The @code{tar} format
Xdoes not distinguish text files from binary files, and no
Xtranslation of file contents is performed.
X
XThe @code{name}, @code{linkname}, @code{magic}, @code{uname}, and
X@code{gname} are null-terminated character strings.  All other
Xfileds are zero-filled octal numbers in ASCII.  Each numeric field
Xof width @var{w} contains @var{w}@minus 2 digits, a space, and a null,
Xexcept @code{size}, and @code{mtime}, which do not contain the
Xtrailing null.
X
XThe @code{name} field is the pathname of the file, with directory
Xnames (if any) preceding the file name, separated by slashes.
X
XThe @code{mode} field provides nine bits specifying file permissions
Xand three bits to specify the Set UID, Set GID, and Save Text
X(``stick'') modes.  Values for these bits are defined above.  When
Xspecial permissions are required to create a file with a given mode,
Xand the user restoring files from the archive does not hold such
Xpermissions, the mode bit(s) specifying those special permissions
Xare ignored.  Modes which are not supported by the operating system
Xrestoring files from the archive will be ignored.  Unsupported modes
Xshould be faked up when creating or updating an archive; e.g. the
Xgroup permission could be copied from the @code{other} permission.
X
XThe @code{uid} and @code{gid} fields are the numeric user and group
XID of the file owners, respectively.  If the operating system does
Xnot support numeric user or group IDs, these fields should be
Xignored.
X
XThe @code{size} field is the size of the file in bytes; linked files
Xare archived with this field specified as zero.
X@xref{Extraction Options}; in particular the @samp{-G} option.@refill
X
XThe @code{mtime} field is the modification time of the file at the
Xtime it was archived.  It is the ASCII representation of the octal
Xvalue of the last time the file was modified, represented as an
Xinteger number of seconds since January 1, 1970, 00:00 Coordinated
XUniversal Time.
X
XThe @code{chksum} field is the ASCII representation of the octal
Xvalue of the simple sum of all bytes in the header record.  Each
X8-bit byte in the header is added to an unsigned integer,
Xinitialized to zero, the precision of which shall be no less than
Xseventeen bits.  When calculating the checksum, the @code{chksum}
Xfield is treated as if it were all blanks.
X
XThe @code{typeflag} field specifies the type of file archived.  If a
Xparticular implementation does not recognize or permit the specified
Xtype, the file will be extracted as if it were a regular file.  As
Xthis action occurs, @code{tar} issues a warning to the standard
Xerror.
X
X@table @code
X@item LF_NORMAL
X@itemx LF_OLDNORMAL
XThese represent a regular file.  In order to be compatible with
Xolder versions of @code{tar}, a @code{typeflag} value of
X@code{LF_OLDNORMAL} should be silently recognized as a regular
Xfile.  New archives should be created using @code{LF_NORMAL}.  Also,
Xfor backward compatibility, @code{tar} treats a regular file whose
Xname ends with a slash as a directory.
X
X@item LF_LINK
XThis represents a file linked to another file, of any type,
Xpreviously archived.  Such files are identified in Unix by each file
Xhaving the same device and inode number.  The linked-to
Xname is specified in the @code{linkname} field with a trailing null.
X
X@item LF_SYMLINK
XThis represents a symbolic link to another file.  The linked-to
Xname is specified in the @code{linkname} field with a trailing null.
X
X@item LF_CHR
X@itemx LF_BLK
XThese represent character special files and block special files
Xrespectively.  In this case the @code{devmajor} and @code{devminor}
Xfields will contain the major and minor device numbers
Xrespectively.  Operating systems may map the device specifications
Xto their own local specification, or may ignore the entry.
X
X@item LF_DIR
XThis specifies a directory or sub-directory.  The directory name in
Xthe @code{name} field should end with a slash.  On systems where
Xdisk allocation is performed on a directory basis the @code{size}
Xfield will contain the maximum number of bytes (which may be rounded
Xto the nearest disk block allocation unit) which the directory may
Xhold.  A @code{size} field of zero indicates no such limiting.
XSystems which do not support limiting in this manner should ignore
Xthe @code{size} field.
X
X@item LF_FIFO
XThis specifies a FIFO special file.  Note that the archiving of a
XFIFO file archives the existence of this file and not its contents.
X
X@item LF_CONTIG
XThis specifies a contiguous file, which is the same as a normal
Xfile except that, in operating systems which support it,
Xall its space is allocated contiguously on the disk.  Operating
Xsystems which do not allow contiguous allocation should silently treat
Xthis type as a normal file.
X
X@item 'A' @dots{}
X@itemx 'Z'
XThese are reserved for custom implementations.  Some of these are
Xused in the GNU modified format, as described below.
X@end table
X
XOther values are reserved for specification in future revisions of
Xthe P1003 standard, and should not be used by any @code{tar} program.
X
XThe @code{magic} field indicates that this archive was output in the
XP1003 archive format.  If this field contains @code{TMAGIC}, the
X@code{uname} and @code{gname} fields will contain the ASCII
Xrepresentation of the owner and group of the file respectively.  If
Xfound, the user and group ID represented by these names will be used
Xrather than the values within the @code{uid} and @code{gid} fields.
X
X@section GNU Extensions to the Archive Format
XThe GNU format uses additional file types to describe new types of
Xfiles in an archive.  These are listed below.
X
X@table @code
X@item LF_DUMPDIR
X@itemx 'D'
XThis represents a directory and a list of files created by the
X@samp{-G} option.  The @code{size} field gives the total size of the
Xassociated list of files.  Each filename is preceded by either a @code{'Y'}
X(the file should be in this archive) or an @code{'N'} (The file is a
Xdirectory, or is not stored in the archive).  Each filename is
Xterminated by a null.  There is an additional null after the last
Xfilename.
X
X@item LF_MULTIVOL
X@itemx 'M'
XThis represents a file continued from another volume of a
Xmulti-volume archive created with the @samp{-M} option.  The original
Xtype of the file is not given here.  The @code{size} field gives the
Xmaximum size of this piece of the file (assuming the volume does not
Xend before the file is written out).  The @code{offset} field gives
Xthe offset from the beginning of the file where this part of the
Xfile begins.  Thus @code{size} plus @code{offset} should equal the
Xoriginal size of the file.
X
X@item LF_VOLHDR
X@itemx 'V'
XThis file type is used to mark the volume header that was given with
Xthe @samp{-V} option when the archive was created.  The @code{name}
Xfield contains the @code{name} given after the @samp{-V} option.
XThe @code{size} field is zero.  Only the first file in each volume
Xof an archive should have this type.
X
X@end table
X
XYou may have trouble reading a GNU format archive on a non-GNU system
Xif the options @samp{-G}, @samp{-M} or @samp{-V} were used when writing
Xthe archive.
X@unnumbered Concept Index
X@printindex cp
X@contents
X@bye
SHAR_EOF
echo "File TAR.TEX is complete"
chmod 0644 TAR.TEX || echo "restore of TAR.TEX fails"
echo "x - extracting UPDATE.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > UPDATE.C &&
X/*
X
X	Copyright (C) 1988 Free Software Foundation
X
XGNU tar is distributed in the hope that it will be useful, but WITHOUT ANY
XWARRANTY.  No author or distributor accepts responsibility to anyone
Xfor the consequences of using it or for whether it serves any
Xparticular purpose or works at all, unless he says so in writing.
XRefer to the GNU tar General Public License for full details.
X
XEveryone is granted permission to copy, modify and redistribute GNU tar,
Xbut only under the conditions described in the GNU tar General Public
XLicense.  A copy of this license is supposed to have been given to you
Xalong with GNU tar so you can know your rights and responsibilities.  It
Xshould be in a file named COPYING.  Among other things, the copyright
Xnotice and this notice must be preserved on all copies.
X
XIn other words, go ahead and share GNU tar, but don't try to stop
Xanyone else from sharing it farther.  Help stamp out software hoarding!
X*/
X
X/* JF implement the 'r' 'u' and 'A' options for tar. */
X/* The 'A' option is my own invention:  It means that the file-names are
X   tar files, and they should simply be appended to the end of the archive.
X   No attempt is made to block the reads from the args; if they're on raw
X   tape or something like that, it'll probably lose. . . */
X
X#ifdef atarist
X#include <types.h>
X#include <stat.h>
X#else
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X#include <stdio.h>
X#include <errno.h>
X
X/* JF these includes are copied from create.c  I'm not sure if they're right
X   or not.  */
X#ifndef V7
X#include <fcntl.h>
X#endif
X
X#ifndef	MSDOS
X#include <pwd.h>
X#include <grp.h>
X#endif
X
X#ifdef USG
X#include <sys/sysmacros.h>	/* major() and minor() defined here */
X#endif
X
X/*
X * V7 doesn't have a #define for this.
X */
X#ifndef O_RDONLY
X#define	O_RDONLY	0
X#endif
X
X/*
X * Most people don't have a #define for this.
X */
X#ifndef	O_BINARY
X#define	O_BINARY	0
X#endif
X
X#define STDIN 0
X#define STDOUT 1
X
X#include "tar.h"
X#include "port.h"
X#include "rmt.h"
X
Xint time_to_start_writing = 0;	/* We've hit the end of the old stuff,
X				   and its time to start writing new stuff
X				   to the tape.  This involves seeking
X				   back one block and re-writing the current
X				   block (which has been changed). */
X
Xchar *output_start;		/* Pointer to where we started to write in
X				   the first block we write out.  This is used
X				   if we can't backspace the output and have
X				   to null out the first part of the block */
X
Xextern void skip_file();
X
Xextern union record *head;
Xextern struct stat hstat;
X
Xstruct name *name_scan();
Xchar	*name_from_list();
X
X/* Implement the 'r' (add files to end of archive), and 'u' (add files to
X   end of archive if they arent there, or are more up to date than the
X   version in the archive.) commands.*/
Xvoid
Xupdate_archive()
X{
X	int	found_end = 0;
X	int	status = 3;
X	int	prev_status;
X	char	*p;
X	struct name *name;
X	extern void dump_file();
X
X	name_gather();
X	if(cmd_mode==CMD_UPDATE)
X		name_expand();
X	open_archive(2);	/* Open for updating */
X
X	do {
X		prev_status=status;
X		status=read_header();
X		switch(status) {
X		case EOF:
X			found_end=1;
X			break;
X
X		case 0:		/* A bad record */
X			userec(head);
X			switch(prev_status) {
X			case 3:
X				msg("This doesn't look like a tar archive.\n");
X				/* FALL THROUGH */
X			case 2:
X			case 1:
X				msg("Skipping to next header\n");
X			case 0:
X				break;
X			}
X			break;
X
X			/* A good record */
X		case 1:
X /* printf("File %s\n",head->header.name); */
X			head->header.name[NAMSIZ-1]='\0';
X			if(cmd_mode==CMD_UPDATE && (name=name_scan(head->header.name))) {
X				/* struct stat hstat; */
X				struct stat nstat;
X				int head_standard;
X
X				decode_header(head,&hstat,&head_standard,0);
X				if(stat(head->header.name,&nstat)<0) {
X					msg_perror("can't stat %s:",head->header.name);
X				} else {
X					if(hstat.st_mtime>=nstat.st_mtime)
X						name->found++;
X				}
X			}
X			userec(head);
X			skip_file((long)hstat.st_size);
X			break;
X
X		case 2:
X			ar_record=head;
X			found_end = 1;
X			break;
X		}
X	} while(!found_end);
X
X	time_to_start_writing = 1;
X	output_start=ar_record->charptr;
X
X	while(p=name_from_list()) {
X		if(f_confirm && !confirm("add", p))
X			continue;
X		if(cmd_mode==CMD_CAT)
X			append_file(p);
X		else
X			dump_file(p,-1);
X	}
X
X	write_eot();
X	close_archive();
X	names_notfound();
X}
X
X/* Catenate file p to the archive without creating a header for it.  It had
X   better be a tar file or the archive is screwed */
X
Xappend_file(p)
Xchar *p;
X{
X	int	fd;
X	struct stat statbuf;
X	long	bytes_left;
X	union record *start;
X	long	bufsiz,count;
X
X	if(0 != stat(p,&statbuf) || (fd=open(p,O_RDONLY|O_BINARY))<0) {
X		msg_perror("can't open file %s",p);
X		errors++;
X		return;
X	}
X
X	bytes_left = statbuf.st_size;
X
X	while(bytes_left>0) {
X		start=findrec();
X		bufsiz=endofrecs()->charptr - start->charptr;
X		if(bytes_left < bufsiz) {
X			bufsiz = bytes_left;
X			count = bufsiz % RECORDSIZE;
X			if(count)
X				bzero(start->charptr + bytes_left,(int)(RECORDSIZE-count));
X		}
X		count=read(fd,start->charptr,bufsiz);
X		if(count<0) {
X			msg_perror("read error at byte %ld reading %d bytes in file %s",statbuf.st_size-bytes_left,bufsiz,p);
X			exit(EX_ARGSBAD);		/* FOO */
X		}
X		bytes_left-=count;
X		userec(start+(count-1)/RECORDSIZE);
X		if(count!=bufsiz) {
X			msg("%s: file shrunk by %d bytes, yark!\n",p,bytes_left);
X			abort();
X		}
X	}
X	(void)close(fd);
X}
X
X#ifdef DONTDEF
Xbprint(fp,buf,num)
XFILE *fp;
Xchar *buf;
X{
X	int	c;
X
X	if(num==0 || num==-1)
X		return;
X	fputs(" '",fp);
X	while(num--) {
X		c= *buf++;
X		if(c=='\\') fputs("\\\\",fp);
X		else if(c>=' ' && c<='~')
X			putc(c,fp);
X		else switch(c) {
X		case '\n':
X			fputs("\\n",fp);
X			break;
X		case '\r':
X			fputs("\\r",fp);
X			break;
X		case '\b':
X			fputs("\\b",fp);
X			break;
X		case '\0':
X			/* fputs("\\-",fp); */
X			break;
X		default:
X			fprintf(fp,"\\%03o",c);
X			break;
X		}
X	}
X	fputs("'\n",fp);
X}
X#endif
X
Xint number_of_blocks_read = 0;
X
Xint number_of_new_records = 0;
Xint number_of_records_needed = 0;
X
Xunion record *new_block = 0;
Xunion record *save_block = 0;
X
Xvoid
Xjunk_archive()
X{
X	int	found_stuff = 0;
X	int	status = 3;
X	int	prev_status;
X	struct name *name;
X
X	/* int dummy_head; */
X	int number_of_records_to_skip = 0;
X	int number_of_records_to_keep = 0;
X	int number_of_kept_records_in_block;
X	int sub_status;
X	extern int write_archive_to_stdout;
X
X/* fprintf(stderr,"Junk files\n"); */
X	name_gather();
X	open_archive(2);
X
X	while(!found_stuff) {
X		prev_status=status;
X		status=read_header();
X		switch(status) {
X		case EOF:
X			found_stuff = 1;
X			break;
X
X		case 0:
X			userec(head);
X			switch(prev_status) {
X			case 3:
X				msg("This doesn't look like a tar archive.\n");
X				/* FALL THROUGH */
X			case 2:
X			case 1:
X				msg("Skipping to next header\n");
X				/* FALL THROUGH */
X			case 0:
X				break;
X			}
X			break;
X
X		case 1:
X			head->header.name[NAMSIZ-1] = '\0';
X /* fprintf(stderr,"file %s\n",head->header.name); */
X			if((name=name_scan(head->header.name))==(struct name *)0) {
X				userec(head);
X /* fprintf(stderr,"Skip %ld\n",(long)(hstat.st_size)); */
X				skip_file((long)(hstat.st_size));
X				break;
X			}
X			name->found = 1;
X			found_stuff = 2;
X			break;
X
X		case 2:
X			found_stuff = 1;
X			break;
X		}
X	}
X /* fprintf(stderr,"Out of first loop\n"); */
X
X	if(found_stuff!=2) {
X		write_eot();
X		close_archive();
X		names_notfound();
X		return;
X	}
X
X	if(write_archive_to_stdout)
X		write_archive_to_stdout = 0;
X	new_block = (union record *)malloc(blocksize);
X	if(new_block==0) {
X		fprintf(stderr,"Can't allocate secondary block of %d bytes\n",blocksize);
X		exit(EX_SYSTEM);
X	}
X
X		/* Save away records before this one in this block */
X	number_of_new_records=ar_record-ar_block;
X	number_of_records_needed = blocking - number_of_new_records;
X	if(number_of_new_records)
X		bcopy((void *)ar_block,(void *)new_block,(number_of_new_records)*RECORDSIZE);
X
X /* fprintf(stderr,"Saved %d recs, need %d more\n",number_of_new_records,number_of_records_needed); */
X	userec(head);
X	skip_file((long)(hstat.st_size));
X	found_stuff=0;
X	/* goto flush_file; */
X
X	for(;;) {
X			/* Fill in a block */
X	/* another_file: */
X		if(ar_record==ar_last) {
X /* fprintf(stderr,"New block\n"); */
X			flush_archive();
X			number_of_blocks_read++;
X		}
X		sub_status = read_header();
X /* fprintf(stderr,"Header type %d\n",sub_status); */
X
X		if(sub_status==2 && f_ignorez) {
X			userec(head);
X			continue;
X		}
X		if(sub_status==EOF || sub_status==2) {
X			found_stuff = 1;
X			bzero(new_block[number_of_new_records].charptr,RECORDSIZE*number_of_records_needed);
X			number_of_new_records+=number_of_records_needed;
X			number_of_records_needed = 0;
X			write_block(0);
X			break;
X		}
X
X		if(sub_status==0) {
X			fprintf(stderr,"Deleting non-header from archive.\n");
X			userec(head);
X			continue;
X		}
X
X		/* Found another header.  Yipee! */
X		head->header.name[NAMSIZ-1] = '\0';
X /* fprintf(stderr,"File %s ",head->header.name); */
X		if(name=name_scan(head->header.name)) {
X			name->found = 1;
X /* fprintf(stderr,"Flush it\n"); */
X		/* flush_file: */
X			/* decode_header(head,&hstat,&dummy_head,0); */
X			userec(head);
X			number_of_records_to_skip=(hstat.st_size+RECORDSIZE-1)/RECORDSIZE;
X /* fprintf(stderr,"Flushing %d recs from %s\n",number_of_records_to_skip,head->header.name); */
X
X			while(ar_last-ar_record<=number_of_records_to_skip) {
X
X /* fprintf(stderr,"Block: %d <= %d  ",ar_last-ar_record,number_of_records_to_skip); */
X				number_of_records_to_skip -= (ar_last - ar_record);
X				flush_archive();
X				number_of_blocks_read++;
X /* fprintf(stderr,"Block %d left\n",number_of_records_to_skip); */
X			}
X			ar_record+=number_of_records_to_skip;
X /* fprintf(stderr,"Final %d\n",number_of_records_to_skip); */
X			number_of_records_to_skip = 0;
X			continue;
X		}
X
X	/* copy_header: */
X		new_block[number_of_new_records]= *head;
X		number_of_new_records++;
X		number_of_records_needed--;
X		number_of_records_to_keep=(hstat.st_size+RECORDSIZE-1)/RECORDSIZE;
X		userec(head);
X		if(number_of_records_needed==0)
X			write_block(1);
X	/* copy_data: */
X		number_of_kept_records_in_block = ar_last - ar_record;
X		if(number_of_kept_records_in_block > number_of_records_to_keep)
X			number_of_kept_records_in_block = number_of_records_to_keep;
X
X /* fprintf(stderr,"Need %d kept_in %d keep %d\n",blocking,number_of_kept_records_in_block,number_of_records_to_keep); */
X
X		while(number_of_records_to_keep) {
X			int n;
X
X			if(ar_record==ar_last) {
X /* fprintf(stderr,"Flush. . .\n"); */
X				fl_read();
X				number_of_blocks_read++;
X				ar_record=ar_block;
X				number_of_kept_records_in_block = blocking;
X				if(number_of_kept_records_in_block > number_of_records_to_keep)
SHAR_EOF
echo "End of part 7"
echo "File UPDATE.C is continued in part 8"
echo "8" > s2_seq_.tmp
exit 0