home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 mARCH
/
PCWK3A99.iso
/
Archiwiz
/
Tar320
/
SOURCES.ZIP
/
TAPE.C
< prev
next >
Wrap
Text File
|
1996-05-05
|
17KB
|
674 lines
/* tape.c - handle (tape) archive for the Tar program (see file tar.c)
* Author: T.V.Shaporev
* Creation date: 14 Dec 1990
* Contains both MS-DOS and UNIX specific codes
* Called by many functions - see files tar.c store.c extract.c
*/
#include <stdio.h>
#include <errno.h>
#include "sysup.h"
#include "modern.h"
#include "zippipe.h"
#include "lzwhead.h"
#include "compress.h"
#include "define.h"
#ifdef MODERN
# include <string.h>
# include <stdlib.h>
#else
# ifdef M_XENIX
# include <string.h>
# else
int strlen();
char *strcpy(), *strncpy(), *mktemp();
# endif
#endif
#ifdef MSDOS
# include <io.h>
# ifdef __TURBOC__
# include <dir.h>
# else
# include <direct.h>
# endif
#else
int creat(), open(), read(), write(), close();
long lseek();
#endif
static int n_read, mblock, nblock, rblock, wblock;
static int indread, indwrite;
static char rerror[] = "Tar: tape read error\n";
static int sread __ARGS__((char*, int));
static int swrite __ARGS__((char*, int));
static int sback __ARGS__((int));
#ifdef MSDOS
extern int dread __ARGS__((char*, int));
extern int dwrite __ARGS__((char*, int));
extern int dback __ARGS__((int));
extern int qparse __ARGS__((char*));
extern int qbegin __ARGS__((void));
extern int qread __ARGS__((char*, int));
extern int qwrite __ARGS__((char*, int));
extern int qback __ARGS__((int));
extern int aspiparse __ARGS__((char*));
extern int aspistart __ARGS__((void));
extern int aspiread __ARGS__((char*, int));
extern int aspiwrite __ARGS__((char*, int));
extern int aspiback __ARGS__((int));
#endif
static void talign __ARGS__((long));
void printbs __ARGS__((int));
static void psyserr __ARGS__((void))
{
extern char *sys_errlist[]; extern sys_nerr;
if (errno < sys_nerr) (void)fprintf(myout, "%s\n", sys_errlist[errno]);
else (void)fprintf(myout, "error %d\n", errno);
}
static int sread(buf, n) /* regular file reading */
char *buf; register n;
{
if ((n = read(handle, buf, n)) == -1) {
(void)fprintf(myout, "Tar: archive read error: "); psyserr();
}
return n;
}
static int swrite(buf, n) /* regular file writing */
char *buf; register n;
{
if (write(hwrite, buf, n) != n) {
(void)fprintf(myout, "Tar: archive write error: ");
#ifdef MSDOS
if (n != -1) (void)fprintf(myout,"disk full\n"); else
#endif
psyserr();
n = -1;
}
return n;
}
static int sback(n)
register n;
{
return lseek(handle, (long)-BLKSIZE*n, 1) < 0 ? -1 : n;
}
#ifdef USE_COMPRESS
static int zwrite __ARGS__((char*, int));
static int zwrite(buf, n) /* compressed file writing */
char *buf; register n;
{
cpiece(buf, n); return n;
}
#endif
static int gread __ARGS__((char*, int));
static int gwrite __ARGS__((char*, int));
static int gread(buf, n) /* deflated file reading */
char *buf; register n;
{
if ((n = unzread(buf, n)) == -1) {
(void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
}
return n;
}
static int gwrite(buf, n) /* deflated file reading */
char *buf; register n;
{
if ((n = zipwrite(buf, n)) == -1) {
(void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
}
return n;
}
static int ziperr __ARGS__((void))
{
(void)fprintf(stderr, "Tar: zip error: %s\n", ziperrlist[ziperror]);
return ziperror == ZNOMEM ? ESMALL : ERINIT;
}
#ifndef USE_COMPRESS
static int twofault __ARGS__((char*, int));
/*ARGSUSED2*/ static int twofault(buf, n)
char *buf; register n;
{
#ifdef __TURBOC__
(void)buf; (void)n;
#endif
return -1;
}
#endif
/*ARGSUSED*/ static int onefault(n)
int n;
{
#ifdef __TURBOC__
(void)n;
#endif
return -1;
}
static int (*pread) __ARGS__((char*, int)) = sread;
static int (*pwrite)__ARGS__((char*, int)) = swrite;
static int (*pback) __ARGS__((int)) = sback;
static int (*lread) __ARGS__((char*, int)) = sread;
static int (*lwrite)__ARGS__((char*, int)) = swrite;
static int (*lback) __ARGS__((int)) = sback;
static int (*rcount)__ARGS__((char*, int)) = sread;
static int cntread __ARGS__((char*, int));
static int cntread(buf, n)
char *buf; register n;
{
if ((n = (*rcount)(buf, n)) != -1) {
allblock += (BLKSIZE-1 + (unsigned)n) / BLKSIZE;
}
return n;
}
static void talign(i)
long i;
{
if (i % BLKSIZE) {
(void)fprintf(myout, "Tar: tape blocksize error\n");
if (!i_flag) done(ERREAD);
}
}
void printbs(bs)
int bs;
{
if (v_flag) (void)fprintf(myout, "Tar: blocksize = %d\n", bs);
}
static void wrerror __ARGS__((void))
{
(void)fprintf(myout, "Tar: tape write error\n");
done(EWRITE);
}
static int indget;
static int eof_already = FALSE;
static int got_length;
static int indput;
static int getbyte __ARGS__(( void ))
{
if (eof_already) goto end;
if (indget >= got_length) {
if (pksize == 0) {
if ((got_length = (*lread)(pk_inp, MAXBLOCK*BLKSIZE)) < 0) goto err;
if ((sa.st_mode & S_IFMT) == S_IFCHR) talign((long)got_length);
pksize = got_length;
if (pksize && (pksize % BLKSIZE)==0) printbs(pksize/BLKSIZE);
} else {
if (got_length < pksize || got_length % BLKSIZE) goto end;
if ((got_length = (*lread)(pk_inp, pksize)) < 0) goto err;
}
if (got_length < 1) goto end;
indget = 0;
}
return ((unsigned char *)pk_inp)[indget++];
err:
(void)fprintf(myout, rerror);
done(ERREAD);
end:
eof_already = TRUE;
return EOF;
}
static void pkflush __ARGS__((void))
{
#ifdef MSDOS
if (devtype != DEV_FILE && devtype != DEV_FLOP)
#else
if (!isfile)
#endif
while (indput < pksize) pk_out[indput++] = 0;
if ((*lwrite)(pk_out, indput) < indput) wrerror();
indput = 0;
}
static void putbyte(c)
register c;
{
if (indput >= pksize) {
#ifndef pksize
/* Buffer size must not be less then 512 bytes, so we */
/* can wait for blocksize will be detected by reading */
if (indput < BLKSIZE) goto put;
if (pksize < BLKSIZE) pksize = BLKSIZE;
#endif
pkflush();
}
put:
pk_out[indput++] = c;
}
int initape(name)
char *name;
{
#ifdef UNIX
char tn[10]; register char *n;
#endif
#ifdef MSDOS
register k;
#endif
handle = -1;
pread = lread = sread;
pwrite = lwrite = swrite;
pback = lback = sback;
if (name && name[0]=='-' && name[1]==0) {
if ((a_flag && !c_flag) || d_flag) {
(void)fprintf(stderr, "Tar: can\'t update stdout\n");
return ERRARG;
}
#ifdef myinp
if (j_flag
# ifndef MSDOS
|| w_flag
# endif
) {
(void)fprintf(stderr, "Tar: input must be free\n");
return ERRARG;
}
#endif
handle = a_flag ? /* stdout */ 1 : /* stdin */ 0;
myout = stderr;
} else {
#ifdef UNIX
if (name && name[0]) {
n = name;
} else {
n = strcpy(tn, "/dev/mt0"); tn[7] = (ndrive & 7) | '0';
}
/* Do not create a file unless name specified */
handle = c_flag && n == name ? creat(n, 0666) :
open(n, a_flag && !d_flag ? O_RDWR : O_RDONLY);
if (handle < 0) {
cantopen(n); return ERINIT;
}
#endif
#ifdef MSDOS
if (!name || !name[0]) {
devtype = DEV_FLOP;
inidisk();
} else if ((k=qparse(name)) != FALSE) {
if (k != TRUE) return ERRARG;
pread = lread = qread;
pwrite = lwrite = qwrite;
pback = lback = qback;
devtype = DEV_QIC2;
} else if ((k=aspiparse(name)) != FALSE) {
if (k != TRUE) return ERRARG;
pread = lread = aspiread;
pwrite = lwrite = aspiwrite;
pback = lback = aspiback;
devtype = DEV_ASPI;
} else {
if (!k_flag && defdev(name)==0) k_flag = TRUE;
if (k_flag) {
devtype = DEV_FLOP;
inidisk();
} else {
handle = open(name, !a_flag || d_flag ? O_RDONLY+O_BINARY :
c_flag ? O_CREAT+O_TRUNC+O_WRONLY+O_BINARY :
O_RDWR+O_BINARY,
S_IREAD+S_IWRITE);
if (handle < 0) {
cantopen(name); return ERINIT;
}
devtype = DEV_FILE;
}
}
if (devtype == DEV_FLOP) {
pread = lread = dread;
pwrite = lwrite = dwrite;
pback = lback = dback;
}
#endif
}
if (t_flag) {/* yet another redirection */
rcount = lread; pread = lread = cntread; allblock = 0L;
}
if (handle < 0 || fstat(handle, &sa) != 0) sa.st_mode = S_IFBLK;
hwrite = handle;
n_read = 0;
return CORRECT;
}
static void swapbufs __ARGS__((void))
{
register j; register char *p;
p = pk_inp; pk_inp = io_buf; io_buf = p;
p = pk_out; pk_out = io_2nd; io_2nd = p;
j = pksize;
pksize = BLKSIZE*cblock;
cblock = j/BLKSIZE;
}
int redirect()
{
if (pktype == PKpLZW) {
/* Redirect IO */
pread = dpiece;
#ifdef USE_COMPRESS
pwrite = zwrite;
#else
pwrite = twofault;
#endif
pback = onefault;
swapbufs();
if (x_flag || t_flag || d_flag) {
register j;
indget = 0; got_length = (int)n_read;
if ((j=dbegin(getbyte))!=0) {
if (j < 0) {
outmem(stderr);
return ESMALL;
} else {
(void)fprintf(stderr,
"Tar: archive is not in compressed format\n");
return ERINIT;
}
}
}
if (a_flag || d_flag) {
#ifdef USE_COMPRESS
if (cbegin(lzwbits, putbyte, 0x7fffffffL) != lzwbits) {
outmem(stderr);
return ESMALL;
}
#else
(void)fprintf(stderr,
"Tar: this restricted version does not support LZW compression\n");
return ERRARG;
#endif
}
#ifdef USE_COMPRESS
indput = 0;
#endif
} else if (pktype == PKZIP) {
/* Redirect IO */
pread = gread; pwrite = gwrite; pback = onefault;
swapbufs();
if (x_flag || t_flag || d_flag) {
indget = 0; got_length = (int)n_read;
if (unzopen(getbyte, ZIP_ANY) != 0) return ziperr();
}
indput = 0;
if (a_flag || d_flag) {
if (zipcreat(putbyte, (gnuzip ? ZIP_GNU : ZIP_PKW), ziplevel) != 0)
return ziperr();
}
}
rblock = mblock = cblock;
nblock = 0;
return CORRECT;
}
int runtape()
{
register k;
#ifdef MSDOS
if (devtype == DEV_QIC2) { if (qbegin()) return ERINIT; }
else if (devtype == DEV_ASPI) { if (aspistart()) return ERINIT; }
#endif
if (!cblock && c_flag) printbs(cblock = MAXBLOCK);
if ((k = redirect()) != CORRECT) return k;
if (c_flag && !mblock) printbs(cblock = mblock = MAXBLOCK);
wblock = 0;
return CORRECT;
}
void duptape(n)
char *n;
{
register i;
static char template[] = "XXXXXX";
io_2nd = getbuf(BLKSIZE * (mblock ? mblock : MAXBLOCK));
if (!io_2nd) done(ESMALL);
i=strlen(n);
while (i>0 &&
#ifdef MSDOS
n[i-1]!='\\' && n[i-1]!=':' &&
#endif
n[i-1]!='/') --i;
scratch = salloc((int)(i + sizeof(template)));
(void)strncpy(scratch, n, i);
(void)strcpy (scratch+i, template);
(void)mktemp (scratch);
#ifdef UNIX
hwrite = creat(scratch, 0666);
#endif
#ifdef MSDOS
hwrite = open(scratch, O_CREAT+O_TRUNC+O_RDWR+O_BINARY, S_IREAD+S_IWRITE);
#endif
if (hwrite < 0) {
(void)fprintf(myout, "Tar: can\'t create scratch file\n");
done(EWRITE);
}
}
void backtape()
{
register i;
talign((long)n_read);
if ((i = (int)(n_read / BLKSIZE % mblock)) == 0) i = mblock;
if (!isfile) {
register j;
if ((*pback)(i)!=i) goto fault;
if ((j=(*pread)(io_buf, BLKSIZE*rblock))<BLKSIZE) goto fault;
n_read += j;
}
if ((*pback)(i) != i) goto fault;
wblock = --rblock; indread = indwrite = 0;
return;
fault:
(void)fprintf(myout, "Tar: tape seek fault\n");
done(ERREAD);
}
void endtape()
{
nullblock(steptape());
if (wblock) {
if ((*pwrite)(io_2nd, BLKSIZE*((
#ifdef MSDOS
devtype == DEV_FILE || devtype == DEV_FLOP
#else
isfile
#endif
#ifdef USE_COMPRESS
|| pwrite == zwrite
#endif
|| pwrite == gwrite)
&& wblock < mblock ? wblock : mblock)) < 0) {
wrerror();
}
}
#ifdef USE_COMPRESS
if (pwrite == zwrite) {/* compression on output */
if (cflush() < 0) wrerror();
if (indput > 0) pkflush();
} else
#endif
if (pwrite == gwrite) {/* zip compression */
if (zipclose() == -1L) wrerror();
if (indput > 0) pkflush();
}
if (hwrite >= 0 && close(hwrite)!=0) {
(void)fprintf(myout, "Tar: tape close error\n");
done(EWRITE);
}
}
static int readbuf __ARGS__(( void ))
{
register i;
for (;;) {
if (mblock) {
if ((i=(*pread)(io_buf, BLKSIZE*mblock)) < BLKSIZE || i%BLKSIZE!=0) {
(void)fprintf(myout, rerror);
if (i_flag) return -1;
done(ERREAD);
}
n_read += i;
nblock = i / BLKSIZE;
} else {
if ((i = (*pread)(io_buf, MAXBLOCK*BLKSIZE)) < 1) {
(void)fprintf(myout, rerror);
if (i_flag) return -1;
done(ERREAD);
}
n_read += i;
if (i % BLKSIZE != 0 && pktest((unsigned char*)io_buf) == CORRECT) {
mblock = cblock; n_read = 0; continue;
}
talign((long)i);
mblock = nblock = i / BLKSIZE;
printbs(cblock = mblock);
}
break;
}
rblock = 0;
return 0;
}
header *readtape()
{
if (rblock>=nblock && readbuf()!=0) return NULL;
indread = 0;
return (header *)(io_buf + BLKSIZE * rblock++);
}
int readbyte()
{
register c;
if (indread == 0) ++rblock; /* get 1-st byte - take all the block */
if (rblock>nblock) {
if (readbuf()!=0) return -1;
rblock = 1; /* preserve 1-st block from readtape() */
}
c = ((unsigned char *)(io_buf + BLKSIZE * (rblock-1)))[indread];
indread = (indread+1) & (BLKSIZE-1);
return c;
}
void bacouple()
/* return to the beginning of block after try to uncompress */
{
indread = 0; --rblock;
}
int readarch(h, length)
int h; long length;
{
register i;
while (length > 0) {
if (rblock>=nblock && readbuf()!=0) return -1;
if ((i = (nblock-rblock)*BLKSIZE) > length) i = (int)length;
if (write(h, io_buf + rblock * BLKSIZE, i)!=i)
extwrerr();
rblock += (i + BLKSIZE-1) / BLKSIZE;
length -= i;
}
indread = 0;
return 0;
}
header *steptape()
{
if (!mblock) mblock = 1;
if (wblock >= mblock) {
if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
wblock = 0;
}
indwrite = 0;
return (header *)(io_2nd + BLKSIZE * wblock++);
}
void writebyte(c)
int c;
{
if (indwrite == 0) ++wblock;
if (wblock > mblock) {
if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
wblock = 1;
}
((unsigned char *)(io_2nd + BLKSIZE * (wblock-1)))[indwrite] = c;
indwrite = (indwrite+1) & (BLKSIZE-1);
}
long writearch(h, length, name)
int h; long length; char *name;
{
register i; register j; register k;
register char *p;
register long b;
if (!mblock) mblock = 1;
b = 0;
while (length > 0) {
if (wblock >= mblock) {
if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
wblock = 0;
}
k = BLKSIZE * (mblock-wblock);
i = length < k ? (int)length : k;
p = io_2nd + BLKSIZE * wblock;
if ((j = read(h, p, i)) < 0) {
(void)fprintf(myout, "Tar: error reading \'%s\'\n", name);
done(ERREAD);
}
/* Calculate number of blocks affected */
k = (BLKSIZE-1 + j) / BLKSIZE;
wblock += k;
b += k;
/* Fill the slack area */
for (p+=j, k=BLKSIZE*k-j; k>0; k--) *p++ = '\0';
if (j != i) return b;
length -= i;
}
if (wblock >= mblock) {
if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
wblock = 0;
}
indwrite = 0;
return b;
}