home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 mARCH
/
PCWK3A99.iso
/
Archiwiz
/
Tar320
/
SOURCES.ZIP
/
TAR.C
< prev
next >
Wrap
Text File
|
1996-07-03
|
30KB
|
874 lines
/* tar.c - Tape ARchive utility program (main function)
* Author: T.V.Shaporev
* Creation date: 14 Dec 1990
*
* The program works in a same fashion under UNIX (most clones) and MS-DOS.
* The main idear was to develop a tool for file transferring via diskette
* between different operating systems - such as all UNIX clones, MS-DOS,
* RSX, VAX/VMS - and all others which support tar format on a diskette.
*
* First step on this way (made in 1989) lies in adapting common UNIX tar
* program to MS-DOS.
*
* On the second step
* - some bugs were fixed (especially in DOS-applied codes) and some
* optimization were done;
* - nonstandard (under DOS) diskette formats were added (i.e.
* DEC Rainbow and 80 tracks & 9 sectors format)
* - the possibility for compress encoding were included
* (this compressor has the best ratio among all others which
* I know, but don't ask me about its speed). Compressed-file
* format is compatible with the common versions of tar, so You
* can extract the compressed image from the archive by the
* common program, but I doubt You could uncompress them at last.
*
* On the fird step the program was totally (newly) overwritten to bypass
* any copyright exclamations. In fact, it must be considered new program
* but I prefer to continue version enumeration (I hope, nobody cares).
*
* I think, this program must be called Tar (with capital first letter)
* to distinguish it from regular UNIX tar.
*
* The program's behaviour is analogous to usual tar, and I hope, its
* internal help will be enough to understand the differences.
*
* The program doesn't perform any text file conversion - it passes
* strict binary image of each file. If You has a problems with reading
* DOS text files under UNIX (or UNIX files under DOS) please use my
* dostext program.
*
* The program must be compiled by Turbo C 2.0 compiler (in a compact
* model) under MS-DOS. Please don't replace dynamic arrays back to
* static and automatic - MS-DOS compilers dislike them.
*
* tim tim@ecsc.mipt.su 14 Dec 1990
*/
/* Version 3.01
* Handling of the 'l' option corrected
*/
/* Version 3.02 31 Dec 1990
* - great deal of minor corrections
* - u<pdate> option expanded to extracting
* - j<ournal> option added (comment storying files)
* - wildcards * and ? are now processed in archive; this may be
* suppressed by s<trict> option
* - d<elete> option added to replace previous occurencies of files
* in archive on storying, or deleting files from archive when
* whithout a<dd> parameter - this is for file archives only!
*/
/* Version 3.03 22 Feb 1991
* - an error corrected in mismatch() (file extract.c)
* - decreased stack requirements for tree processing
* (see store() in store.c and putfiles() in tar.c)
* - added codes to prevent archive file self-storying
* (not quite reliable for MS-DOS)
* - bincall() invocations changed by calls to rmdir() and mkdir()
* this is done automatically for 386/ix and may be switched by
* RMKDIR macro
*/
/* Version 3.04 29 Jul 1991
* - a direct intialization of static global variables inserted into
* lzencode() and lzdecode() - see file lzpack.c
*/
/* Version 3.04b 03 Oct 1991
* - a minor correction of bincall()
* - added default block number = sectors on track (MS-DOS)
*/
/* Version 3.05 11 Nov 1991
* - block factor for diskette writing is set to 1 for most BIOS
* compatibility
* - scantape() is slightly optimized
*/
/* Version 3.06 17 Dec 1991
* - n<onest> option applied to all actions (see inarg() in extract.c)
* - command-line-extension-file option (responce file) added
* for vak (vak@kiae.su) request (see append() in tar.c)
* - p<ermission> option added to save directories permissions (UNIX)
*/
/* Version 3.06b 22 Dec 1991
* - UNIX to DOS renaming algorithm (dot elimination) slightly
* changed (see extract.c)
* - most of output redirected to stdout (vs stderr)
*/
/* Version 3.07 28 Dec 1992
* - all unary apostrofs in string constants preserved by backslashes
* - reading file list from stdin allowed (see append() in tar.c)
* - input redirected to /dev/tty under UNIX
* - support for traditional UNIX compression algorithm
* - few changes in converting UNIX names for DOS
*/
/* Version 3.07b 20 Jan 1993
* - gethead() does not return FALSE while errors,
* scantape() looks for tape reading errors
*/
/* Version 3.08 22 Feb 1993
* - method-dependent comression indicator masks (see percent.c)
* - 'z' option applied to catalog printing (see catalog())
* - compatibility corrections in directory structure checking
* - st.st_size == codesize - means file unpacked! (see extract.c)
*/
/* Version 3.09 14 Mar 1993
* - a bug fixed wich prevents archiving unpacked files at all
* (ha-ha!) - see store.c
* - changed header description to support new features
* see define.h
* - support for P1003 and GNU file types - 't' option only! -
* see extract.c
* - small changes in #ifdef-s to distinguish SCO UNIXes from
* XENIXes - see store.c
* - regular file processing extracted into separate source
* files (see savefile.c & restore.c)
* - support for devices and FIFOs added
* - 'l' option added for DOS (copy linked files)
* - support for System V extents - see extract.c and restore.c
* to read archives only, extents may not be unpacked on the
* fly - alas, that's all for now
* - an error corrected in roll.c
*/
/* Version 3.10 28 Jun 1993
* - a bug fixed in old compression code (see lzpack.c)
* - added possibility to run through compress (',' comma option)
* see tar.c, tape.c and compress.c
* - comments will not be printed unless 'j' is given (extract.c)
* - separated compress-related codes
*/
/* Version 3.11 14 Jul 1993
* - support for QIC-02 streamers (first version!)
* devices supported: fastape, everex
*/
/* Version 3.12 29 Sen 1993
* - slack area in archive is filled by nulls to improve compression
* - added support for Wangtek (QIC-02) device
* - a bug fixed in memory release ('pk_out' variable - see _done())
* - program support for QIC-02 drive number and tape format
* selection
* - experimental (!) support for appending QIC-02 tapes
* (see qback() in qicface.c)
* - LZW support splitted into compressor and extractor and
* the letter included in official release (see unlzw.c etc.)
* - get default file name from TAPE environment variable
* - 'o' flag for DOS means prevent file overwriting
*/
/* Version 3.12b 10 Nov 1993
* - an error corrected in QIC device selection (see qicface.c)
* - eliminated idle rewindings around QIC tape initialisation
*/
/* Version 3.13 26 Dec 1993
* - online inflatter (unzip) and corresponding '.' (dot) option
*/
/* Version 3.14 19 Feb 1994
* - online deflatter (zip); compilation model changed to large
*/
/* Version 3.15 - general bugfix 03 Apr 1994
* - strerror() missed in some UNIXes, so psyserr() function added
* into tape.c
* - extended local header signature inserted in deflated output and
* unzclose() changed to uderstand both formats
* (see zipdefs.h, zippipe.c and diszip.c)
* - pkflush() output is aligned to pksize boundary if output is not
* regular file or DOS floppy to avoid block device alignment error
* (see tape.c)
* - "total blocks" number is reported accordingly to real archive
* size (see tape.c, extract.c, tar.c)
*/
/* Version 3.15b - bugfix 15 Jun 1994
* - uname() (see restore.c) bug fixed;
* - bi_reverse() cleaned (__emit__ed code cause BC 3.1 error)
* moved to trees.c and renamed;
* - getlg() changed to look for NEEDBITS buffer;
* - diszip.c cleaned a bit.
*/
/* Version 3.16 ?? Jul 1994
* - got rid of __emit__() - completely;
* - got rid of "#pragma pack()" - see define.h;
* - error corrected in ct_free() (see trees.c);
* - default (-e) compression changed to deflation,
* keep support for old-style decompression;
* - exclude file(s) specification ('#' option) - up to 16 patterns
* (see fmatch.c, store.c, extract.c);
* - autodetection of compressed or (g)zipped archives
* (pktest() from extract.c etc.)
*/
/* Version 3.17 04 Nov 1994
* - changed foloppy calibrating logic (see disk.c), added diskspec()
* function (see pclevel.asm) and support for 2.88M floppies (?);
* - corrected missing IBEGIN updating into diszip.c;
* - added 'drop online' op. into streamer() and qend();
* - restored handling of ':' option in savefile();
* - restored "idle rewindings" while starting tape since
* they arrear to improve reliability;
* - use conditional XOFF flag in ct_iobyte() (see streamer.c);
* - added explicit call to tzset() in tar.c;
* - implemented 'add' and 'skip' device parameters;
* - unzipping stored file (see diszip.c),
* gmtime() changed to localtime() in zippipe.c;
* - GNU-like command line syntax, environment configuration;
* - cascade EOI changed to specific in cthandle.asm.
*/
/* Version 3.18 24 Dec 1994
- ASPI support (first version!);
- bug fixed in blocksize reading (see readblk() in readopt.c);
- bug fixed in pattern comparing (see mismatch() in fmatch.c)
*/
/* Version 3.20g 03 Jul 1996
- fix for 'file changed size'
- attempt to handle EOF inside zip
*/
#include "sysup.h"
#include "modern.h"
#include "zippipe.h"
#include "lzwbits.h"
#include "lzwhead.h"
#include "compress.h"
static char note[] = "\n\
Tape ARchive utility v3.20g (C) 1990-94 Tim V.Shaporev\n";
#ifdef UNIX
static char help[] = "\n\
Usage: tar -<options> [tapefile] [blocksize] [disksize] file ...\n\n\
Options are: s - no wildcards for archive\n\
c - put files to new archive i - ignore read errors\n\
a,r - add files to archive m - forget files origin date/time\n\
y - move files to archive o - forget files owner\n\
x - extract files from archive l - type missed links\n\
t - show archive catalog p - save directories & permissions\n\
d - delete files in archive n - no proceed with dir nesting\n\
u - update files / - omit left \'/\' in file names\n\
v - verbose 0...7 - number of tape device\n\
w - acknowledge operations j - comment storying files\n\
e - compress encode files f - next arg is an archive file\n\
z - old-fashion compression b - next arg is a blocking factor\n\
, - run through compressor @ - next arg is a responce file\n\
. - run through (g)zip # - exclude file(s) specification\n\
";
#endif
#ifdef MSDOS
static char help[] = "\n\
Usage: tar -<options> [tapefile] [blocksize] [disksize] file ...\n\n\
Options are:\n\
c - put files to new archive s - no wildcards for archive\n\
a,r - add files to archive m - forget files date/time\n\
y - move files to archive n - no proceed with dir nesting\n\
x - extract files from archive l - copy linked files\n\
t - show archive catalog o - prevent files overwriting\n\
d - delete files in archive \\ - omit left \'\\\' in file names\n\
u - update files : - omit DOS drive name\n\
v - verbose 0...3 - number of storage device\n\
w - acknowledge operations j - comment storying files\n\
i - ignore read errors f - next arg is an archive file\n\
e - compress encode files b - next arg is a blocking factor\n\
z - old-fashion compression k - next arg is K diskette size\n\
, - run through compressor @ - next arg is a responce file\n\
. - run through (g)zip # - exclude file(s) specification\n\
\n\
Most of options may be combined. Wildcards * and ? are o\'k\n\
";
static char devlist[] = "\n\
The following \"file names\" will be treated as diskette format/size:\n\
\tfd048ss8 - 160K\tfd048ds8 - 320K\tfd135ds9 - 720K\n\
\tfd048ss9 - 180K\tfd048ds9 - 360K\tfd135ds18 - 1.4M\n\
\tfd096ds9 - 720K\tfd096ds15 - 1.2M\trainbow\n\
\n\
Streamer \"file name\" syntax (full form) is:\n\
\t<device>:base:=<base address>h,dma:=<DRQ>[,irq:=<IRQ>][,norewind]\n\
Streamer device clones supported are:\n\
\tarchive,\teverex,\t\twangtek\n\
\n\
The following \"file names\" are aliases for ASPI driven SCSI streamer:\n\
\taspitape,\taspimgr$,\taspi\n\
Full form is:\n\
\taspi[:target:=<n>[,lun:=<n>][,adapter:=<n>][,density:=<x>]]\n\
";
#endif
#include <signal.h>
#include <stdio.h>
#ifdef MSDOS
# include <string.h>
# include <stdlib.h>
# include <time.h>
# include <dos.h>
# include <dir.h>
# include <io.h>
#else
char *strcpy(), *strcat(), *strncpy();
char *getenv(), *malloc(), *realloc();
int open(), read(), close(), link(), unlink(), isatty();
int strlen(), strncmp(), atoi();
void exit(), free();
long lseek();
#endif
#define __ALLOCEXT__
#include "define.h"
#include "lzpack.h"
#include "roll.h"
#ifdef UNIX
# ifdef MAXNAMSIZ
# define MAXPATH MAXNAMSIZ+1
# else
# define MAXPATH 512+1
# endif
#endif
#ifdef UNIX
# ifndef RMKDIR
int bincall(name, args)
char *name, *args;
{
extern int fork(), execl(), wait();
int i; register k;
char b[24];
if (fork() == 0) {
(void)execl(strcat(strcpy(b, "/bin/"), name), name, args, 0);
(void)execl(strcat(strcpy(b, "/usr/bin/"), name), name, args, 0);
k = -1;
} else {
(void)wait(&i); k = i>>8;
}
return k;
}
# endif
#endif
#ifdef MSDOS
void takename(dst, src)
register char *dst, *src;
{
do {
*(dst++) = *src >= 'A' && *src <= 'Z' ? *src + ('z'-'Z') :
*src == '\\' ? '/' : *src;
} while (*(src++));
}
#endif
short headsum(h)
header *h;
{
register short i, j;
for (i=0, j=0; i<BLKSIZE; i++) {
j += i >= MAXTNAME+3*8+2*12 && i < MAXTNAME+3*8+2*12+8 ?
' ' : *((unsigned char *)h + i);
}
#if ~0 != 0177777
return j & 0177777;
#else
return j;
#endif
}
node *finditem(fname, prev, head)
char *fname; node **prev, *head;
{
register node *this;
register i;
*prev = this = head; i = 1;
while (this && i>0) {
if ((i = strcmp(fname, this->name)) > 0) {
*prev = this; this = this->next;
}
}
return i ? NONE : this;
}
node *additem(fname, prev, head)
char *fname; node *prev, **head;
{
register node *this;
register i;
i = sizeof(node) - (MINTNAME-1) + strlen(fname);
if ((this = (node *)malloc(i)) == NULL) return NONE;
(void)strcpy(this->name, fname);
this->prev = prev;
if (prev != NONE) {
if ((this->next = prev->next) != NONE) this->next->prev = this;
prev->next = this;
} else {/* initialise the list */
this->next = NONE;
(*head) = this;
}
return this;
}
void delitem(this, head)
node *this, **head;
{
if (this == *head) {/* head of the list */
if (this->next != NONE) {
this->next->prev = this->prev != this ? this->prev : this->next;
}
this = this->next;
free(*head);
*head = this;
} else {
if (this->next != NONE) this->next->prev = this->prev;
this->prev->next = this->next;
free(this);
}
}
static void _done __ARGS__(( void ))
{
register node *p, *q;
#ifdef MSDOS
extern void qend __ARGS__((void)), aspiend __ARGS__((void));
if (devtype == DEV_QIC2) qend();
else if (devtype == DEV_ASPI) aspiend();
if (archname) free(archname);
#endif
if (responce) free(responce);
if (argvector) free((char*)argvector);
if (tarcmd) free(tarcmd);
p = timehead; while (p) { q = p->next; free(p); p = q; }
#ifdef UNIX
p = linkhead; while (p) { q = p->next; free(p); p = q; }
#endif
if (hwrite >= 0 && hwrite != handle) {
(void)close(hwrite); (void)unlink(scratch);
}
if (io_2nd && io_2nd!=io_buf) free(io_2nd);
if (io_buf) free(io_buf);
if (pk_out && pk_out!=pk_inp) free(pk_out);
if (pk_inp) free(pk_inp);
zipfree();
unzfree();
#ifdef USE_COMPRESS
z_reltab();
#endif
z_relmem();
delroll();
}
void done(n)
int n;
{
_done(); exit(n);
}
void outmem(f)
FILE *f;
{
(void)fprintf(f, "Tar: not enough memory\n");
done(ESMALL);
}
char *salloc(n)
int n;
{
register char *p;
if ((p = malloc(n)) == NULL) outmem(stderr);
return p;
}
int yes_no(d)
char d;
{
register int c;
#ifdef MSDOS
extern int getkey __ARGS__((void));
do {
c = getkey();
} while (c!='y' && c!='Y' && c!='n' && c!='N' && c!='q' && c!='Q' &&
c!='\r' && c!='\n' && c!=27 && c!=3);
if (c == 3) {
cbreak = TRUE;
} else if (c >= ' ') {
(void)fprintf(stderr, "%c", c);
} else if (d) {
(void)fprintf(stderr, "%c", d);
}
(void)fprintf(stderr, "\n");
#else
if ((c = getc(myinp)) == '\n') {
c = d;
} else {
while (getc(myinp) != '\n') ;
}
#endif
if (c == 'q' || c == 'Q') done(EXIT);
return c == 'y' || c == 'Y';
}
void prmode(c, m)
char c; int m;
{
(void)fprintf(myout, "%c%c%c%c%c%c%c%c%c%c", c,
(m & S_IREAD ? 'r' : '-'), (m & S_IWRITE? 'w' : '-'),
(m & S_ISUID ? 's' : m & S_IEXEC ? 'x' : '-'),
(m & 00040 ? 'r' : '-'), (m & 00020 ? 'w' : '-'),
(m & S_ISGID ? 's' : m & 00010 ? 'x' : '-'),
(m & 00004 ? 'r' : '-'), (m & 00002 ? 'w' : '-'),
(m & S_ISVTX ? 't' : m & 00001 ? 'x' : '-'));
}
int okwork(c, p, s, n)
char c, p, *n;
struct stat *s;
{
register m;
(void)fprintf(stderr, "%c ", c);
if (v_flag) {
if (p == ' ' && (m = s->st_mode & S_IFMT) != 0) {
switch (m) {
case S_IFREG: break;
case S_IFDIR: p = 'd'; break;
case S_IFIFO: p = 'p'; break;
case S_IFCHR: p = 'c'; break;
case S_IFBLK: p = 'b'; break;
#ifdef S_IFLNK
case S_IFLNK: p = 'l'; break;
#endif
default: p = '?';
}
}
prmode(p, (int)(s->st_mode));
(void)fprintf(stderr," %3d/%1d %7ld ",s->st_uid,s->st_gid,s->st_size);
}
(void)fprintf(stderr, "%s : ", n);
return YES_NO();
}
void onintr() { (void)signal(SIGINT, SIG_IGN); cbreak = TRUE; }
#ifdef UNIX
void onquit() { (void)signal(SIGQUIT, SIG_IGN); cbreak = TRUE; }
void onhup() { (void)signal(SIGHUP, SIG_IGN); cbreak = TRUE; }
#endif
static void set_sig __ARGS__(( void ))
{
if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void)signal(SIGINT, onintr);
#ifdef UNIX
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) (void)signal(SIGHUP, onhup );
if (signal(SIGQUIT,SIG_IGN) != SIG_IGN) (void)signal(SIGQUIT,onquit);
#endif
}
static void delfile __ARGS__(( void ))
{
if (v_flag)
(void)fprintf(myout, "d %s, %ld bytes, %ld tape blocks\n",
hblock->m.name, st.st_size, (st.st_size + (BLKSIZE-1))/BLKSIZE);
if (usize()) skipfile();
}
static void putfiles __ARGS__(( int, char ** ));
static void putfiles(argc, argv)
int argc; char *argv[];
{
register i;
char fnmbuf[MAXPATH];
for (i=0; i<argc; i++) {
if (strlen(argv[i]) > MAXTNAME) {
(void)fprintf(myout, "Tar: \'%s\' name too long\n", argv[i]);
continue;
}
takename(fnmbuf, argv[i]);
store(fnmbuf);
}
}
static void stdhelp __ARGS__((void))
{
(void)fprintf(stdout, note);
(void)fprintf(stdout, help);
(void)fflush (stdout);
#ifdef MSDOS
if (ioctl(fileno(stdout),0) & 0x80) {/* not a disk file */
(void)fprintf(stderr,"\nDo you want to see device list? ");
(void)fflush (stderr);
if (!YES_NO()) return;
}
(void)fprintf(stdout, devlist);
#endif
}
int pkalloc()
{
register k;
if (pktype == PKpLZW || pktype == PKZIP) {/* Pipe compression */
pksize = BLKSIZE;
k = (d_flag || x_flag || t_flag) && (pk_inp=malloc(pksize))==NULL ||
(d_flag || a_flag) && (pk_out=malloc(pksize))==NULL;
} else {/* Individual file(s) compression */
pksize = PKSIZE;
k = (d_flag || x_flag || (t_flag && pktype == PKfLZW)) &&
(pk_out=malloc(pksize))==NULL ||
(d_flag || a_flag) && (pk_inp=malloc(pksize))==NULL;
}
return k;
}
int main(argc, argv)
int argc; char *argv[];
{
register i, k;
register char *p;
int cenv; char **earg;
if (argc < 2) {
stdhelp(); return ERRARG;
}
#ifdef MSDOS
setdrive = FALSE;
filemask = FA_SYSTEM+FA_HIDDEN+FA_RDONLY+FA_DIREC+FA_ARCH;
#endif
pktype = PKNONE;
pklock = FALSE;
cblock = 0;
tapename = NULL;
myout = stdout;
xcnt = 0;
lzwbits = BITS; ziplevel = 6;
/* Skip the program name */ --argc; ++argv;
appname = NULL;
if ((cenv = envbuild(0, &earg)) > 0) {
i = readopt(&cenv, &earg, OPTFLAG);
if (i < cenv) {
revector(argc, &argv, cenv-i);
/* append new arguments */
while(i<cenv) argv[argc++] = earg[i++];
}
if (appname) argc = argfile(argc, &argv, appname, &responce);
}
i = readopt(&argc, &argv, 0);
pktype &= OPTMASK;
#ifdef MSDOS
if (nonest) filemask = FA_SYSTEM+FA_HIDDEN+FA_RDONLY+FA_ARCH;
#endif
if (
#ifdef MSDOS
!k_flag &&
#endif
!tapename) tapename = getenv("TAPE");
if (!a_flag && !x_flag && !t_flag && !d_flag) {
(void)fprintf(stderr, "Tar: nothing to do\n"); return ERRARG;
}
if (a_flag || d_flag) {
if (i >= argc) {
(void)fprintf(stderr, "Tar: no files specified\n");
return ERRARG;
}
#ifndef USE_COMPRESS
if (pktype == PKfLZW || pktype == PKpLZW) {
(void)fprintf(stderr,
"Tar: this restricted version does not support LZW compression\n");
return ERRARG;
}
#endif
}
if ((k = initape(tapename)) != CORRECT) done(k);
if ((io_buf=getbuf(cblock ? cblock*BLKSIZE : MAXBLOCK*BLKSIZE)) == NULL)
done(ESMALL);
io_2nd = io_buf;
if (pktype != PKNONE) {
if (pkalloc()) {/* Memory lack */
if (!w_flag) {
outmem(stderr);
} else {
(void)fprintf(stderr,
"No memory for [de]compression. Continue? ");
k = YES_NO();
(void)fprintf(stderr, "\n");
if (!k) done(ESMALL);
if (pk_inp) { free(pk_inp); pk_inp = NULL; }
pktype = PKNONE;
}
}
}
cbreak = FALSE;
if ((k = runtape()) != CORRECT) done(k);
#ifdef UNIX
myinp = stdin;
if (!isatty(/* stdin */ 0) && (myinp = fopen("/dev/tty", "r")) == NULL) {
(void)fprintf(myout,
"Tar: warning: can\'t open terminal device, may be problems\n");
myinp = stdin;
}
#endif
#ifdef MSDOS
if (a_flag && isfile) {
p = tapename;
if ((p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z') && p[1]==':') {
k = p[0] < 'a' ? p[0] - ('A'-1) : p[0] - ('a'-1); p += 2;
} else {
k = 0;
}
if (p[0] == '/' || p[0] == '\\') {
takename((archname = salloc(strlen(p) + 1)), p);
} else {
archname = salloc(strlen(p) + MAXPATH);
*(int *)archname = '/';
getcurdir(k, archname+1); takename(archname, archname);
k = strlen(archname);
archname[k++] = '/';
takename(archname+k, p);
}
}
/* Turbo C 2.0 stat() does not call tzset(), so
invoke it explicitly (for non-file archives) */
tzset();
#endif
argc -= i; argv += i;
if (d_flag) {
register header *h; register long l; register m;
if (d_flag && !isfile) {
(void)fprintf(stderr,
"Tar: delete option is for file archives only\n");
return ERRARG;
}
duptape(tapename);
m = FALSE;
do {
if ((k = gethead()) == ERROR) done(ERREAD);
if (!k) continue;
if (a_flag) {
struct stat s;
if (inargs(argc, argv, hblock->m.name)) {
if (u_flag) uplist();
if (stat(hblock->m.name, &s)!=0) {
if (v_flag) {
(void)fprintf(myout, "Tar: can\'t access \'%s\'\n",
hblock->m.name);
}
} else if (!u_flag || s.st_mtime > st.st_mtime) {
delfile(); continue;
}
}
} else {/* pure delete */
if (inargs(argc, argv, hblock->m.name) ||
((hblock->m.filetype==TF_LNK || hblock->m.filetype==TF_SYM) &&
inargs(argc, argv, hblock->m.linkname))) {
m = TRUE; delfile(); continue;
}
}
/* move file to output archive */
for (h=steptape(), i=0; i<BLKSIZE/sizeof(int); i++) {
((int *)h)[i] = ((int *)hblock)[i];
}
if (usize()) {
l = (st.st_size + (BLKSIZE-1)) / BLKSIZE;
while (l-- > 0) {
if ((hblock = readtape()) == NULL) done(ERREAD);
for (h=steptape(), i=0; i<BLKSIZE/sizeof(int); i++) {
((int *)h)[i] = ((int *)hblock)[i];
}
}
}
} while (k);
if (a_flag) {
l = lseek(hwrite, 0L, 1);
putfiles(argc, argv);
m = lseek(hwrite, 0L, 1) > l;
}
if (m) {/* archive was modified */
endtape();
if (unlink(tapename)) {
(void)fprintf(myout, "Tar: can\'t delete \'%s\'\n", tapename);
done(EWRITE);
}
#ifdef UNIX
if (link(scratch, tapename)) {
(void)fprintf(myout,
"Tar: can\'t link \'%s\' - data stay in \'%s\'\n",
tapename, scratch);
done(EWRITE);
}
if (unlink(scratch)) {
(void)fprintf(myout, "Tar: can\'t delete scratch file\n");
}
#endif
#ifdef MSDOS
if (rename(scratch, tapename)) {
(void)fprintf(myout, "Tar: can\'t rename \'%s\' to \'%s\'\n",
scratch, tapename);
done(EWRITE);
}
#endif
#ifdef UNIX
if (a_flag && l_flag) {
register node *this;
for (this=linkhead; this; this=this->next) {
(void)fprintf(myout, "Tar: missed %d link(s) to \'%s\'\n",
this->info.data.count, this->name);
}
}
#endif
} else {
if (v_flag) (void)fprintf(myout, "Tar: archive unchanged\n");
(void)close(hwrite);
if (unlink(scratch)) {
(void)fprintf(myout, "Tar: can\'t delete scratch file\n");
done(EWRITE);
}
}
} else if (a_flag) {
#ifdef MSDOS
if (w_flag && c_flag && devtype == DEV_FLOP) {
fprintf(stderr,
"\007Data on drive %c: would be destroyed. Continue ? ",
ndrive + 'A');
if (!YES_NO()) done(ERRARG);
}
#endif
if (a_flag && !c_flag) {
scantape(argc, argv, acctime); backtape();
}
set_sig();
putfiles(argc, argv);
endtape();
#ifdef UNIX
if (l_flag) {
register node *this;
for (this=linkhead; this; this=this->next) {
(void)fprintf(myout, "Tar: missed %d link(s) to \'%s\'\n",
this->info.data.count, this->name);
}
}
#endif
} else if (x_flag) {
#ifdef UNIX
(void)umask(0);
#endif
scantape(argc, argv, extract);
} else {/* if (t_flag) */
allbytes = 0; allfiles = 0;
scantape(argc, argv, catalog);
if (v_flag) {
(void)fprintf(myout,
"\tTotal %u file(s) for %lu bytes in %lu tape blocks\n",
allfiles, allbytes, allblock);
}
}
_done(); return 0;
}