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