home *** CD-ROM | disk | FTP | other *** search
- /* 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;
- }