Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,613 @@
/*
* flxtp keys [name ...]
* keys are:
* w write to beginning of tape
* a append to end of tape
* r read named files from tape; if no names, extract all
* t table named files; or table all
* also may add:
* v verbose
* i wait for user 'y' before performing function
* u leave extracted filenames in upper case (usually
* filenames are mapped to lower case)
* n don't rewind tape before performing action
* [x,y] specify uic for tape
* pooo use protection ooo on tape
* bddd use blocksize ddd to write on tape
* (tape read automagically determines blksize)
* ddddd use density dddd (800 or 1600)
* o ok to overwrite existing files when extracting
* (default will not overwrite existing files)
* m make a new directory for each uic found on tape and
* put the extracted files in them
*
* name is a unix path name (for writing tapes) or the name of
* a file on the tape. When writing tapes, a name may be a uic
* in the same form as above. This causes all following files
* to be written on the tape in that uic.
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FLXHD 14
#define FLXDATA 512
/*
* len of longest unpacked filename, including the null at end
* and one extra space for version 'number'
*/
#define FLXNM 15
#define MAXBASE (9+1)
#define MAXEXT (3+1)
/* note byte swap for DEC machines */
#define OFFNAME 0
#define OFFEXT 4
#define OFFUIC2 6
#define OFFUIC1 7
#define OFFPROT2 8
#define OFFPROT1 9
#define OFFDATE2 10
#define OFFDATE1 11
#define OFFOVER 12
#define DEFUIC1 '\001'
#define DEFUIC2 '\001'
#define DEFPROT1 '\000'
#define DEFPROT2 '\233'
#define CR '\015'
#define LF '\012'
#define NL '\012'
#define TPWRITE 'w'
#define TPAPPEND 'a'
#define TPREAD 'r'
#define TPTABLE 't'
#define IOPT 'i'
#define VOPT 'v'
#define UOPT 'u'
#define NOPT 'n'
#define POPT 'p'
#define BOPT 'b'
#define DOPT 'd'
#define OOPT 'o'
#define MOPT 'm'
#define NOCMD '\0'
struct parsehdr {
char phname[FLXNM];
char phuic1;
char phuic2;
char phprot1;
char phprot2;
char phdate[11];
};
int verbose, mkdirs, overwrite, inquire, allfiles, uicfiles, upcase, norewind = 0;
int argsleft, filenbr, actnbr = 0;
char tp1600[] = "/dev/nrmt0";
char tp1600rw[] = "/dev/rmt0";
char bsr1600[] = "mt -t /dev/nrmt0 bsr 1";
char tp800[] = "/dev/nrmt0";
char tp800rw[] = "/dev/rmt0";
char bsr800[] = "mt -t /dev/nrmt0 bsr 1";
char *devtp = tp1600;
char *devtprw = tp1600rw;
char *bsrcmd = bsr1600;
int tpfd;
FILE *dfd;
char uic1 = DEFUIC1;
char uic2 = DEFUIC2;
char prot1 = DEFPROT1;
char prot2 = DEFPROT2;
char date1 = '\000';
char date2 = '\000';
#define BIGBLK 32768
unsigned tpblksiz = FLXDATA;
char *tpbuf, *malloc();
char cmd = NOCMD;
/*
* flxtp - read or write flx format tape
*/
main (argc, argv)
int argc;
char **argv;
{
int k;
int density;
char c = '\0';
if (argc < 2) usage();
if (argc == 2) allfiles++;
else argsleft = argc - 2;
argv++; /* skip over command name */
k=0;
while ( (c=(*argv)[k++]) != '\0') {
switch (c) {
case TPAPPEND:
#ifndef PICKLE
error ("append function not implemented");
#endif
/* fall thru to write */
case TPWRITE:
if (cmd != NOCMD) error ("Only one of rwat may be selected");
if (allfiles) error ("Name(s) must be given for w or a");
cmd = c;
break;
case TPREAD:
/* fall thru */
case TPTABLE:
if (cmd != NOCMD) error ("Only one of rwat may be selected");
cmd = c;
break;
case MOPT: mkdirs++; break;
case OOPT: overwrite++; break;
case NOPT: norewind++; break;
case IOPT: inquire++; break;
case VOPT: verbose++; break;
case UOPT: upcase++; break;
case '[':
if(sscanf(&(*argv)[k],"%3o,%3o]",&uic1,&uic2)==2 ) {
while ( (*argv)[k++] != ']');
}
else error ("Uic must be given as [xxx,yyy]");
uicfiles++;
break;
case POPT:
if(sscanf(&(*argv)[k],"%3o",&prot2) == 1 ) {
while ( isdigit ( (*argv)[k]) )
k++;
}
else error ("Protection must be given as pooo");
break;
case BOPT:
if (sscanf(&(*argv)[k],"%d",&tpblksiz) == 1) {
while ( isdigit ( (*argv)[k] ) )
k++;
}
else error ("Tape blocksize must be given as bddd");
break;
case DOPT:
if (sscanf(&(*argv)[k],"%d",&density) == 1) {
while ( isdigit ( (*argv)[k] ) )
k++;
if (density==1600) {/* already set */}
else if (density==800) {
devtp=tp800;
devtprw=tp800rw;
bsrcmd=bsr800;
}
else error ("Density must be given as d800 or d1600");
}
else error ("Density must be given as d800 or d1600");
break;
case '-': /* ignore */ break;
default:
usage();
} /* switch */
} /* while */
if (cmd == TPREAD | cmd == TPTABLE) tpblksiz = BIGBLK;
if ( (tpbuf=malloc(tpblksiz)) == (char *) 0)
error ("Sorry, can't get buffer for your blocksize");
argv++; /* skip over keys */
if ( !norewind) {
if((tpfd=open(devtprw,0)) == -1)
error ("Can't access tape");
close(tpfd);
}
switch (cmd) {
case TPAPPEND:
seekeot();
/* fall thru to put files */
case TPWRITE:
putfiles (argv);
break;
case TPREAD:
getfiles (argv);
break;
case TPTABLE:
tblfiles (argv);
break;
default:
error ("Pgm error; see sys msg");
} /* switch */
exit (0);
} /* flxtp */
error (msg)
char *msg;
{
fprintf (stderr,"%s\n",msg);
exit (-1);
} /* error */
usage ()
{
fprintf (stderr,"Usage: flxtp (rwat)[vilnupOOObDDDdDDDD] [name ...]\nwhere u = [x,y]\n");
exit (-1);
} /* usage */
int tblfiles (list)
char **list;
{
char hdr[FLXHD];
struct parsehdr phdr;
int nr, nbrblk, totblks = 0;
if ( (tpfd=open(devtp,0)) == -1) error ("Can't open tape");
while (allfiles | argsleft) {
if ((nr=read(tpfd,hdr,FLXHD)) == 0) break;
expandhdr (hdr, &phdr);
filenbr++;
if (amatch (&phdr, list)) {
nbrblk = gobblefile();
totblks += nbrblk;
fprintf(stdout,"File %4d: %-13s %5d <%3o> [%3o,%3o]\n",
filenbr, phdr.phname, nbrblk,
phdr.phprot2&0xff, phdr.phuic1&0xff, phdr.phuic2&0xff);
actnbr++;
if (!allfiles) argsleft--;
}
else nbrblk = gobblefile();
}
if(allfiles) fprintf (stdout,"Total %d data blocks in %d files listed\n",
totblks,actnbr);
if (!allfiles & argsleft) fprintf (stderr,"Other files not found\n");
close (tpfd);
} /* tblfiles */
int gobblefile ()
{
int nr, nbrblk = 0;
while ((nr=read(tpfd,tpbuf,tpblksiz)) > 0)
nbrblk++;
return (nbrblk);
} /* gobblefile */
int getfiles (list)
char **list;
{
char wuic1, wuic2 = 0;
char hdr[FLXHD], reply[2], *pfull, *p, *q, *v, *fname, overname[FLXNM];
static char versions[] = "!@#$%^&*()";
static char mkdircmd [] = "mkdir 000,000.dir";
static char *pathname = &mkdircmd[6];
static char fullname[27];
struct parsehdr phdr;
int nr, ip, jp, nbrblk = 0;
if ( (tpfd=open(devtp,0)) == -1) error ("Can't open tape");
while (allfiles | argsleft) {
if ((nr=read(tpfd,hdr,FLXHD)) == 0)
break;
expandhdr ( hdr, &phdr);
filenbr++;
if (amatch (&phdr, list) ) {
if (!allfiles) argsleft--;
if (inquire) {
fprintf (stdout,"Extract %s? (y/n) ",phdr.phname);
fread(reply,1, 2, stdin);
if (*reply != 'y') goto skip;
}
if (mkdirs) {
if (phdr.phuic1 != wuic1 | phdr.phuic2 != wuic2) {
wuic1=phdr.phuic1;
wuic2=phdr.phuic2;
sprintf(pathname,
"%03o,%03o.dir",
wuic1&0xff, wuic2&0xff);
if (access(pathname,0) != 0) {
if (system(mkdircmd) != 0)
error ("Can't make directory");
}
}
pfull = fullname;
p = pathname;
while ( *pfull++ = *p++ );
pfull[-1] = '/';
p = phdr.phname;
while ( *pfull++ = *p++);
fname = fullname;
}
else fname = phdr.phname;
if (verbose) fprintf (stdout,
"get [%3o,%3o] %s file # %d\n",
phdr.phuic1&0xff, phdr.phuic2&0xff, fname, filenbr);
if (!overwrite && (access(fname,0 /* exists */) == 0)) {
/* try adding 'version' char at end of name */
v=versions;
p=fname; q=overname;
while (*p) *q++ = *p++;
*(q+1) = '\0';
while (*v) {
*q = *v;
if (access(overname,0)) break;
v++; /* try next 'version' nbr */
}
if (*v == 0) { /*already 10 versions */
printf("Can't overwrite %s\n",
overname);
goto skip;
}
printf("Duplicate filename; %s used\n",
overname);
fname = overname;
}
if ( (dfd=fopen(fname, "w")) == NULL)
error ("Can't open disk file");
while ( (nr=read(tpfd, tpbuf, tpblksiz)) > 0){
ip = jp = 0;
while (ip<nr) {
tpbuf[jp] = tpbuf[ip];
if (tpbuf[jp] == CR
|| tpbuf[jp] == '\0')
jp--;
ip++; jp++;
} /* while */
if (fwrite(tpbuf, 1, jp, dfd) != jp)
error ("Disk write error");
} /* while */
if (nr == -1) error ("Tape read error");
fclose(dfd);
actnbr++;
continue;
}
skip: nbrblk=gobblefile();
}
if (allfiles | verbose) fprintf (stdout,"Total %d files extracted\n",actnbr);
if ((!allfiles) & argsleft) fprintf (stderr,"%d files not found\n",argsleft);
close (tpfd);
} /* getfiles */
seekeot () {
int nr, stat;
if ( (tpfd=open(devtp,0)) == -1) error ("Can't open tape");
if (verbose) fprintf (stdout,"Seeking to end of tape\n");
while (1) {
stat = read(tpfd,tpbuf,tpblksiz);
if(stat <= 0) break;
nr = gobblefile ();
filenbr++;
}
if (stat == -1) error ("Can't find end of tape");
close (tpfd);
/* back up before second eot mark */
if (system(bsrcmd)) error ("Can't find end of tape");
} /* seekeot */
putfiles (list)
char **list;
{
int n, nbrblk = 0;
char reply[2];
struct stat sbuf;
while ( *list != NULL) {
actnbr++;
filenbr++;
if (**list == '[') {
/* set new uic for writing */
if (sscanf(*list, "[%3o,%3o]", &uic1, &uic2) != 2)
error ("Uic must be given as [xxx,yyy]");
list++;
actnbr--;
filenbr--;
continue;
}
if ( (stat(*list,&sbuf) == 0) &&
(sbuf.st_mode & S_IFDIR) ) {
printf("Directory %s ignored\n", *list);
list++;
actnbr--;
filenbr--;
continue;
}
if (inquire) {
fprintf (stdout, "%c File # %d %s? (y/n) ",cmd, actnbr, *list);
fread (reply, 1, 2, stdin);
if (*reply != 'y') continue;
actnbr--;
filenbr--;
}
if (verbose)
fprintf (stdout,"%c File #%4d [%3o,%3o] %s ",
cmd, filenbr, uic1&0xff, uic2&0xff, *list);
if ( (dfd=fopen(*list, "r")) != NULL) {
if ( (tpfd=open(devtp,2)) == -1)
error ("Can't open tape");
if (puthdr(*list)) error ("Can't write tape");
nbrblk=0;
while ( n=buildbuf()) {
if (write(tpfd,tpbuf,n) != n)
error ("Tape write error");
nbrblk++;
}
close(tpfd);
fclose(dfd);
if (verbose) fprintf (stdout,"%d data blocks\n",nbrblk);
}
else fprintf (stderr,"Can't open diskfile %s\n", *list);
list++;
} /* while */
if (verbose) fprintf (stdout, "Total %d files written to tape\n",actnbr);
} /* putfiles */
int puthdr (name)
char *name;
{
char buf[FLXHD], base[MAXBASE], ext[MAXEXT], *nend;
int i;
/* get parts of filename */
fnparts(name,base,MAXBASE,ext,MAXEXT);
/* pad both parts with blanks */
nend=base;
i=0;
while (*nend) {nend++; i++;}
while ( i < MAXBASE ) base[i++] = ' ';
nend=ext;
i=0;
while (*nend) {nend++; i++;}
while ( i < MAXEXT ) ext[i++] = ' ';
/* convert both parts to rad50 */
ator50 (base, 6, &buf[OFFNAME]);
ator50 (&base[6], 3, &buf[OFFOVER]);
ator50 (ext, 3, &buf[OFFEXT]);
buf[OFFUIC1] = uic1;
buf[OFFUIC2] = uic2;
buf[OFFPROT1] = prot1;
buf[OFFPROT2] = prot2;
buf[OFFDATE1] = date1;
buf[OFFDATE2] = date2;
if (write(tpfd,buf,FLXHD) != FLXHD) return (-1);
return (0);
} /* puthdr */
int buildbuf ()
{
static int crlf, deof = 0;
int n, c;
n = 0;
if (crlf) {
tpbuf[n++] = LF;
crlf = 0;
}
if (deof) {deof=0; return(0);}
while (n <tpblksiz) {
c=getc(dfd);
if (c == EOF) {deof++; break;}
if (c == NL) {
tpbuf[n++] = CR;
if (n<tpblksiz) tpbuf[n++] = LF;
else {crlf++; break;}
}
else tpbuf[n++] = c;
}
if (n%2 != 0) tpbuf[n++] = '\0';
return (n);
} /* buildbuf */
char unmap (n)
unsigned n;
{
static char rm[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.!0123456789";
static char rml[]= " abcdefghijklmnopqrstuvwxyz$.!0123456789";
if (n<40) {
if (upcase) return (rm[n]);
else return (rml[n]);
}
return ('!'); /* error */
} /* unmap */
r50toa (s, slen, d)
char *s, *d;
int slen;
{
unsigned word;
int i, j, i2;
for (i=j=0; i<slen; i++) {
i2= i*2;
/* note byte swap for DEC machines */
word = ( (s[i2+1]<<8) | (s[i2]&0xff) ) & 0xffff;
d[j++]=unmap(word/1600);
d[j++]=unmap((word%1600)/40);
d[j++]=unmap((word%1600)%40);
} /* for */
d[j++]='\0';
} /* r50toa */
ator50 (s, slen, d)
char *s, *d;
int slen;
{
int i, word;
for (i=0; i<slen; i+=3) {
word = radmap(s[i])*1600 + radmap(s[i+1])*40 + radmap(s[i+2]);
/* note byte swap for DEC machine */
*d++ = word;
*d++ = word>>8;
} /* for */
} /* ator50 */
int radmap (c)
char c;
{
if (islower(c)) return (c-96);
if (isupper(c)) return (c-64);
if (isdigit(c)) return (c-18);
if (c==' ') return (0);
if (c=='$') return (27);
if (c=='.') return (28);
return (29);
} /* radmap */
#define MATCH 1
#define NOMATCH 0
int amatch (ph, list)
struct parsehdr *ph;
char **list;
{
if (allfiles) {
if (uicfiles) {
if (ph->phuic1 == uic1 & ph->phuic2 == uic2)
return (MATCH);
else return (NOMATCH);
}
else return (MATCH);
}
if (uicfiles)
if (ph->phuic1 != uic1 | ph->phuic2 != uic2) return (NOMATCH);
while (*list) {
if (strncmp (ph->phname, *list, FLXNM) == 0)
return (MATCH);
list++;
} /* while */
return (NOMATCH);
} /* amatch */
expandhdr (hdr, ph)
char *hdr;
struct parsehdr *ph;
{
char *nm;
nm = ph->phname;
r50toa(&hdr[OFFNAME], 2 /* words */, nm);
while (*nm > ' ') nm++;
r50toa(&hdr[OFFOVER], 1 /* word */, nm);
while (*nm > ' ') nm++;
*nm++ = '.';
r50toa (&hdr[OFFEXT], 1 /* word */, nm);
while (*nm > ' ') nm++;
/* if filename ends in '.', just drop it */
if ( *(nm - 1) == '.') nm--;
*nm = '\0';
ph->phuic1 = hdr[OFFUIC1];
ph->phuic2 = hdr[OFFUIC2];
ph->phprot1 = hdr[OFFPROT1];
ph->phprot2 = hdr[OFFPROT2];
ph->phdate[0] = '\0'; /* don't yet know how to parse date */
} /* expandhdr */

View File

@@ -0,0 +1,58 @@
#include <stdio.h>
#include <ctype.h>
#define PERIOD '.'
#define SLASH '/'
fnparts (origfn, base, maxbase, suffix, maxsuffix)
char *origfn, *base, *suffix;
int maxbase, maxsuffix;
{
char *end, *bp, *sp, *endbase;
int i;
/* point past last char of orignal filename */
end = origfn;
while (*end++);
/* find suffix by scanning backwards for '.'
* but don't backup before a pathname
*/
sp = end;
while ( *sp != PERIOD & *sp != SLASH & sp != origfn) sp--;
if ( *sp != PERIOD ) { /* no suffix found */
endbase = end;
*suffix = '\0';
}
else {
endbase = sp++; /* and skip the '.' */
i=0;
while ( i< (maxsuffix-1)) {
if (islower(*sp) | isdigit(*sp) | isupper(*sp) )
*suffix++ = *sp++;
else sp++; /* ignore other chars */
if ( *sp == '\0' ) break;
} /* while */
*suffix = '\0'; /* terminate with null */
} /* end of getting the suffix */
/* find base by scanning backwards from suffix */
bp=endbase;
while ( *bp != SLASH & bp != origfn ) bp--;
if ( *bp == SLASH ) bp++; /* skip slash, if found */
i=0;
while ( i < (maxbase-1) ) { /* save the base */
if (islower(*bp) | isdigit(*bp) | isupper(*bp))
*base++ = *bp++;
else bp++; /* ignore other chars */
if ( bp == endbase ) break;
} /* save the base */
*base = '\0'; /* terminate with null */
} /* fnparts */

View File

@@ -0,0 +1,6 @@
flxtp: flxtp.c /usr/carol/mylibc/mylib.a
cc -DPICKLE flxtp.c /usr/carol/mylibc/mylib.a -o flxtp
install:
mv /usr/tandy/flxtp /usr/tandy/old/
mv flxtp /usr/tandy

View File

@@ -0,0 +1,14 @@
CFLAGS=-O
h = tp.h tp_defs.h
o = tp0.o tp1.o tp2.o tp3.o
tp : $o
$(CC) -o tp $o
$o : $h
install : tp
install -s tp ${DESTDIR}/bin
clean :
rm -f *.o

View File

@@ -0,0 +1,958 @@
static char *sccsid = "@(#)tar.c 4.5 (Berkeley) 81/04/02";
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <sys/mtio.h>
#include <signal.h>
char *sprintf();
char *strcat();
daddr_t bsrch();
#define TBLOCK 512
#define NBLOCK 20
#define NAMSIZ 100
union hblock {
char dummy[TBLOCK];
struct header {
char name[NAMSIZ];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[NAMSIZ];
} dbuf;
} dblock, tbuf[NBLOCK];
struct linkbuf {
ino_t inum;
dev_t devnum;
int count;
char pathname[NAMSIZ];
struct linkbuf *nextp;
} *ihead;
struct stat stbuf;
int rflag, xflag, vflag, tflag, mt, cflag, mflag, fflag, oflag, pflag;
int term, chksum, wflag, recno, first, linkerrok;
int freemem = 1;
int nblock = NBLOCK;
daddr_t low;
daddr_t high;
FILE *tfile;
char tname[] = "/tmp/tarXXXXXX";
char *usefile;
char magtape[] = "/dev/rmt8";
char *malloc();
main(argc, argv)
int argc;
char *argv[];
{
char *cp;
int onintr(), onquit(), onhup(), onterm();
if (argc < 2)
usage();
tfile = NULL;
usefile = magtape;
argv[argc] = 0;
argv++;
for (cp = *argv++; *cp; cp++)
switch(*cp) {
case 'f':
usefile = *argv++;
fflag++;
break;
case 'c':
cflag++;
rflag++;
break;
case 'o':
oflag++;
break;
case 'p':
pflag++;
break;
case 'u':
mktemp(tname);
if ((tfile = fopen(tname, "w")) == NULL) {
fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname);
done(1);
}
fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n");
/* FALL THROUGH */
case 'r':
rflag++;
break;
case 'v':
vflag++;
break;
case 'w':
wflag++;
break;
case 'x':
xflag++;
break;
case 't':
tflag++;
break;
case 'm':
mflag++;
break;
case '-':
break;
case '0':
case '1':
case '4':
case '5':
case '7':
case '8':
magtape[8] = *cp;
usefile = magtape;
break;
case 'b':
nblock = atoi(*argv++);
if (nblock > NBLOCK || nblock <= 0) {
fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK);
done(1);
}
break;
case 'l':
linkerrok++;
break;
default:
fprintf(stderr, "tar: %c: unknown option\n", *cp);
usage();
}
if (rflag) {
if (cflag && tfile != NULL) {
usage();
done(1);
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, onintr);
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, onhup);
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
signal(SIGQUIT, onquit);
/*
if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
signal(SIGTERM, onterm);
*/
if (strcmp(usefile, "-") == 0) {
if (cflag == 0) {
fprintf(stderr, "Can only create standard output archives\n");
done(1);
}
mt = dup(1);
nblock = 1;
}
else if ((mt = open(usefile, 2)) < 0) {
if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) {
fprintf(stderr, "tar: cannot open %s\n", usefile);
done(1);
}
}
dorep(argv);
}
else if (xflag) {
if (strcmp(usefile, "-") == 0) {
mt = dup(0);
nblock = 1;
}
else if ((mt = open(usefile, 0)) < 0) {
fprintf(stderr, "tar: cannot open %s\n", usefile);
done(1);
}
doxtract(argv);
}
else if (tflag) {
if (strcmp(usefile, "-") == 0) {
mt = dup(0);
nblock = 1;
}
else if ((mt = open(usefile, 0)) < 0) {
fprintf(stderr, "tar: cannot open %s\n", usefile);
done(1);
}
dotable();
}
else
usage();
done(0);
}
usage()
{
fprintf(stderr, "tar: usage tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n");
done(1);
}
dorep(argv)
char *argv[];
{
register char *cp, *cp2;
char wdir[60];
if (!cflag) {
getdir();
do {
passtape();
if (term)
done(0);
getdir();
} while (!endtape());
if (tfile != NULL) {
char buf[200];
sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s",
tname, tname, tname, tname, tname, tname);
fflush(tfile);
system(buf);
freopen(tname, "r", tfile);
fstat(fileno(tfile), &stbuf);
high = stbuf.st_size;
}
}
getwdir(wdir);
while (*argv && ! term) {
cp2 = *argv;
if (!strcmp(cp2, "-C") && argv[1]) {
argv++;
if (chdir(*argv) < 0)
perror(*argv);
else
getwdir(wdir);
argv++;
continue;
}
for (cp = *argv; *cp; cp++)
if (*cp == '/')
cp2 = cp;
if (cp2 != *argv) {
*cp2 = '\0';
chdir(*argv);
*cp2 = '/';
cp2++;
}
putfile(*argv++, cp2);
chdir(wdir);
}
putempty();
putempty();
flushtape();
if (linkerrok == 1)
for (; ihead != NULL; ihead = ihead->nextp)
if (ihead->count != 0)
fprintf(stderr, "Missing links to %s\n", ihead->pathname);
}
endtape()
{
if (dblock.dbuf.name[0] == '\0') {
backtape();
return(1);
}
else
return(0);
}
getdir()
{
register struct stat *sp;
int i;
readtape( (char *) &dblock);
if (dblock.dbuf.name[0] == '\0')
return;
sp = &stbuf;
sscanf(dblock.dbuf.mode, "%o", &i);
sp->st_mode = i;
sscanf(dblock.dbuf.uid, "%o", &i);
sp->st_uid = i;
sscanf(dblock.dbuf.gid, "%o", &i);
sp->st_gid = i;
sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
sscanf(dblock.dbuf.chksum, "%o", &chksum);
if (chksum != checksum()) {
fprintf(stderr, "directory checksum error\n");
done(2);
}
if (tfile != NULL)
fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);
}
passtape()
{
long blocks;
char buf[TBLOCK];
if (dblock.dbuf.linkflag == '1')
return;
blocks = stbuf.st_size;
blocks += TBLOCK-1;
blocks /= TBLOCK;
while (blocks-- > 0)
readtape(buf);
}
putfile(longname, shortname)
char *longname;
char *shortname;
{
int infile;
long blocks;
char buf[TBLOCK];
register char *cp, *cp2;
struct direct dbuf;
int i, j;
infile = open(shortname, 0);
if (infile < 0) {
fprintf(stderr, "tar: %s: cannot open file\n", longname);
return;
}
fstat(infile, &stbuf);
if (tfile != NULL && checkupdate(longname) == 0) {
close(infile);
return;
}
if (checkw('r', longname) == 0) {
close(infile);
return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
for (i = 0, cp = buf; *cp++ = longname[i++];);
*--cp = '/';
*++cp = 0 ;
i = 0;
if (!oflag) {
if( (cp - buf) >= NAMSIZ) {
fprintf(stderr, "%s: file name too long\n", longname);
close(infile);
return;
}
stbuf.st_size = 0;
tomodes(&stbuf);
strcpy(dblock.dbuf.name,buf);
sprintf(dblock.dbuf.chksum, "%6o", checksum());
writetape( (char *) &dblock);
}
chdir(shortname);
while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) {
if (dbuf.d_ino == 0) {
i++;
continue;
}
if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) {
i++;
continue;
}
cp2 = cp;
for (j=0; j < DIRSIZ; j++)
*cp2++ = dbuf.d_name[j];
*cp2 = '\0';
close(infile);
putfile(buf, cp);
infile = open(".", 0);
i++;
lseek(infile, (long) (sizeof(dbuf) * i), 0);
}
close(infile);
chdir("..");
return;
}
if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname);
return;
}
tomodes(&stbuf);
cp2 = longname;
for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
if (i >= NAMSIZ) {
fprintf(stderr, "%s: file name too long\n", longname);
close(infile);
return;
}
if (stbuf.st_nlink > 1) {
struct linkbuf *lp;
int found = 0;
for (lp = ihead; lp != NULL; lp = lp->nextp) {
if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) {
found++;
break;
}
}
if (found) {
strcpy(dblock.dbuf.linkname, lp->pathname);
dblock.dbuf.linkflag = '1';
sprintf(dblock.dbuf.chksum, "%6o", checksum());
writetape( (char *) &dblock);
if (vflag) {
fprintf(stderr, "a %s ", longname);
fprintf(stderr, "link to %s\n", lp->pathname);
}
lp->count--;
close(infile);
return;
}
else {
lp = (struct linkbuf *) malloc(sizeof(*lp));
if (lp == NULL) {
if (freemem) {
fprintf(stderr, "Out of memory. Link information lost\n");
freemem = 0;
}
}
else {
lp->nextp = ihead;
ihead = lp;
lp->inum = stbuf.st_ino;
lp->devnum = stbuf.st_dev;
lp->count = stbuf.st_nlink - 1;
strcpy(lp->pathname, longname);
}
}
}
blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK;
if (vflag) {
fprintf(stderr, "a %s ", longname);
fprintf(stderr, "%ld blocks\n", blocks);
}
sprintf(dblock.dbuf.chksum, "%6o", checksum());
writetape( (char *) &dblock);
while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
writetape(buf);
blocks--;
}
close(infile);
if (blocks != 0 || i != 0)
fprintf(stderr, "%s: file changed size\n", longname);
while (blocks-- > 0)
putempty();
}
doxtract(argv)
char *argv[];
{
long blocks, bytes;
char buf[TBLOCK];
char **cp;
int ofile;
for (;;) {
getdir();
if (endtape())
break;
if (*argv == 0)
goto gotit;
for (cp = argv; *cp; cp++)
if (prefix(*cp, dblock.dbuf.name))
goto gotit;
passtape();
continue;
gotit:
if (checkw('x', dblock.dbuf.name) == 0) {
passtape();
continue;
}
if(checkdir(dblock.dbuf.name))
continue;
if (dblock.dbuf.linkflag == '1') {
unlink(dblock.dbuf.name);
if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name);
continue;
}
if (vflag)
fprintf(stderr, "%s linked to %s\n",
dblock.dbuf.name, dblock.dbuf.linkname);
continue;
}
if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) {
fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name);
passtape();
continue;
}
chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
if (vflag)
fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n",
dblock.dbuf.name, bytes, blocks);
while (blocks-- > 0) {
readtape(buf);
if (bytes > TBLOCK) {
if (write(ofile, buf, TBLOCK) < 0) {
fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
done(2);
}
} else
if (write(ofile, buf, (int) bytes) < 0) {
fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
done(2);
}
bytes -= TBLOCK;
}
close(ofile);
if (mflag == 0) {
time_t timep[2];
timep[0] = time(NULL);
timep[1] = stbuf.st_mtime;
utime(dblock.dbuf.name, timep);
}
if (pflag)
chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
}
}
dotable()
{
for (;;) {
getdir();
if (endtape())
break;
if (vflag)
longt(&stbuf);
printf("%s", dblock.dbuf.name);
if (dblock.dbuf.linkflag == '1')
printf(" linked to %s", dblock.dbuf.linkname);
printf("\n");
passtape();
}
}
putempty()
{
char buf[TBLOCK];
char *cp;
for (cp = buf; cp < &buf[TBLOCK]; )
*cp++ = '\0';
writetape(buf);
}
longt(st)
register struct stat *st;
{
register char *cp;
char *ctime();
pmode(st);
printf("%3d/%1d", st->st_uid, st->st_gid);
printf("%7D", st->st_size);
cp = ctime(&st->st_mtime);
printf(" %-12.12s %-4.4s ", cp+4, cp+20);
}
#define SUID 04000
#define SGID 02000
#define ROWN 0400
#define WOWN 0200
#define XOWN 0100
#define RGRP 040
#define WGRP 020
#define XGRP 010
#define ROTH 04
#define WOTH 02
#define XOTH 01
#define STXT 01000
int m1[] = { 1, ROWN, 'r', '-' };
int m2[] = { 1, WOWN, 'w', '-' };
int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
int m4[] = { 1, RGRP, 'r', '-' };
int m5[] = { 1, WGRP, 'w', '-' };
int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
int m7[] = { 1, ROTH, 'r', '-' };
int m8[] = { 1, WOTH, 'w', '-' };
int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
pmode(st)
register struct stat *st;
{
register int **mp;
for (mp = &m[0]; mp < &m[9];)
select(*mp++, st);
}
select(pairp, st)
int *pairp;
struct stat *st;
{
register int n, *ap;
ap = pairp;
n = *ap++;
while (--n>=0 && (st->st_mode&*ap++)==0)
ap++;
printf("%c", *ap);
}
checkdir(name)
register char *name;
{
register char *cp;
int i;
for (cp = name; *cp; cp++) {
if (*cp == '/') {
*cp = '\0';
if (access(name, 01) < 0) {
register int pid, rp;
if ((pid = fork()) == 0) {
execl("/bin/mkdir", "mkdir", name, 0);
execl("/usr/bin/mkdir", "mkdir", name, 0);
fprintf(stderr, "tar: cannot find mkdir!\n");
done(0);
}
while ((rp = wait(&i)) >= 0 && rp != pid)
;
chown(name, stbuf.st_uid, stbuf.st_gid);
if (pflag)
chmod(dblock.dbuf.name,
stbuf.st_mode & 0777);
}
*cp = '/';
}
}
return(cp[-1]=='/');
}
onintr()
{
signal(SIGINT, SIG_IGN);
term++;
}
onquit()
{
signal(SIGQUIT, SIG_IGN);
term++;
}
onhup()
{
signal(SIGHUP, SIG_IGN);
term++;
}
onterm()
{
signal(SIGTERM, SIG_IGN);
term++;
}
tomodes(sp)
register struct stat *sp;
{
register char *cp;
for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
*cp = '\0';
sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777);
sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid);
sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
}
checksum()
{
register i;
register char *cp;
for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
*cp = ' ';
i = 0;
for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
i += *cp;
return(i);
}
checkw(c, name)
char *name;
{
if (wflag) {
printf("%c ", c);
if (vflag)
longt(&stbuf);
printf("%s: ", name);
if (response() == 'y'){
return(1);
}
return(0);
}
return(1);
}
response()
{
char c;
c = getchar();
if (c != '\n')
while (getchar() != '\n');
else c = 'n';
return(c);
}
checkupdate(arg)
char *arg;
{
char name[100];
long mtime;
daddr_t seekp;
daddr_t lookup();
rewind(tfile);
for (;;) {
if ((seekp = lookup(arg)) < 0)
return(1);
fseek(tfile, seekp, 0);
fscanf(tfile, "%s %lo", name, &mtime);
if (stbuf.st_mtime > mtime)
return(1);
else
return(0);
}
}
done(n)
{
unlink(tname);
exit(n);
}
prefix(s1, s2)
register char *s1, *s2;
{
while (*s1)
if (*s1++ != *s2++)
return(0);
if (*s2)
return(*s2 == '/');
return(1);
}
getwdir(s)
char *s;
{
int i;
int pipdes[2];
pipe(pipdes);
if ((i = fork()) == 0) {
close(1);
dup(pipdes[1]);
execl("/bin/pwd", "pwd", 0);
execl("/usr/bin/pwd", "pwd", 0);
fprintf(stderr, "pwd failed!\n");
printf("/\n");
exit(1);
}
while (wait((int *)NULL) != -1)
;
read(pipdes[0], s, 50);
while(*s != '\n')
s++;
*s = '\0';
close(pipdes[0]);
close(pipdes[1]);
}
#define N 200
int njab;
daddr_t
lookup(s)
char *s;
{
register i;
daddr_t a;
for(i=0; s[i]; i++)
if(s[i] == ' ')
break;
a = bsrch(s, i, low, high);
return(a);
}
daddr_t
bsrch(s, n, l, h)
daddr_t l, h;
char *s;
{
register i, j;
char b[N];
daddr_t m, m1;
njab = 0;
loop:
if(l >= h)
return(-1L);
m = l + (h-l)/2 - N/2;
if(m < l)
m = l;
fseek(tfile, m, 0);
fread(b, 1, N, tfile);
njab++;
for(i=0; i<N; i++) {
if(b[i] == '\n')
break;
m++;
}
if(m >= h)
return(-1L);
m1 = m;
j = i;
for(i++; i<N; i++) {
m1++;
if(b[i] == '\n')
break;
}
i = cmp(b+j, s, n);
if(i < 0) {
h = m;
goto loop;
}
if(i > 0) {
l = m1;
goto loop;
}
return(m);
}
cmp(b, s, n)
char *b, *s;
{
register i;
if(b[0] != '\n')
exit(2);
for(i=0; i<n; i++) {
if(b[i+1] > s[i])
return(-1);
if(b[i+1] < s[i])
return(1);
}
return(b[i+1] == ' '? 0 : -1);
}
readtape(buffer)
char *buffer;
{
register int i;
if (recno >= nblock || first == 0) {
if ((i = read(mt, tbuf, TBLOCK*nblock)) < 0) {
fprintf(stderr, "Tar: tape read error\n");
done(3);
}
if (first == 0) {
if ((i % TBLOCK) != 0) {
fprintf(stderr, "Tar: tape blocksize error\n");
done(3);
}
i /= TBLOCK;
if (i != nblock) {
fprintf(stderr, "Tar: blocksize = %d\n", i);
nblock = i;
}
}
recno = 0;
}
first = 1;
copy(buffer, &tbuf[recno++]);
return(TBLOCK);
}
writetape(buffer)
char *buffer;
{
first = 1;
if (recno >= nblock) {
if (write(mt, tbuf, TBLOCK*nblock) < 0) {
fprintf(stderr, "Tar: tape write error\n");
done(2);
}
recno = 0;
}
copy(&tbuf[recno++], buffer);
if (recno >= nblock) {
if (write(mt, tbuf, TBLOCK*nblock) < 0) {
fprintf(stderr, "Tar: tape write error\n");
done(2);
}
recno = 0;
}
return(TBLOCK);
}
backtape()
{
static int mtdev = 1;
static struct mtop mtop = {MTBSR, 1};
struct mtget mtget;
if (mtdev == 1)
mtdev = ioctl(mt, MTIOCGET, &mtget);
if (mtdev == 0) {
if (ioctl(mt, MTIOCTOP, &mtop) < 0) {
fprintf(stderr, "Tar: tape backspace error\n");
done(4);
}
} else
lseek(mt, (long) -TBLOCK*nblock, 1);
recno--;
}
flushtape()
{
write(mt, tbuf, TBLOCK*nblock);
}
copy(to, from)
register char *to, *from;
{
register i;
i = TBLOCK;
do {
*to++ = *from++;
} while (--i);
}

View File

@@ -0,0 +1,85 @@
/* c-version of tp?.s
*
* M. Ferentz
* August 1976
*
* revised July 1977 BTL
*/
#define MDIRENT 496 /* must be zero mod 8 */
#define DIRSZ sizeof(struct dent)
#define MAPSIZE 4096
#define MAPMASK 07777
#define NAMELEN 32
#define BSIZE 512
#define TCSIZ 578
#define TCDIRS 192
#define MTSIZ 32767
#define TPB (BSIZE/sizeof(struct tent))
#define OK 0100000
#define BRKINCR 512
#define tapeblk &tpentry[0]
#define tapeb &tpentry[0]
struct tent { /* Structure of a tape directory block */
char pathnam[NAMELEN];
short mode;
char uid;
char gid;
char spare;
char size0;
unsigned short size1;
long time;
unsigned short tapea; /* tape address */
short unused[8];
short cksum;
} tpentry[TPB];
struct dent { /* in core version of tent with "unused" removed
* and pathname replaced by pointer to same in a
* packed area (nameblock).
*/
char *d_namep;
int d_mode;
int d_uid;
int d_gid;
long d_size;
long d_time;
int d_tapea;
} dir[MDIRENT];
char map[MAPSIZE];
char name[NAMELEN];
char name1[NAMELEN];
extern char mt[];
extern char tc[];
char *tname;
extern char mheader[];
extern char theader[];
int narg, rnarg;
char **parg;
int wseeka,rseeka;
int tapsiz;
int fio;
short ndirent, ndentb;
struct dent *edir;
struct dent *lastd; /* for improvement */
char *sbrk();
char *strcpy();
long lseek();
int (*command)();
char *nameblk;
char *top;
char *nptr;
extern int flags;
#define flc 0001
#define fli 0004
#define flm 0010
#define flu 0020
#define flv 0040
#define flw 0100
#define fls 0200

View File

@@ -0,0 +1,2 @@
#include "tp.h"
#include "tp_defs.h"

View File

@@ -0,0 +1,197 @@
#include "tp.h"
main(argc,argv)
char **argv;
{
register char c,*ptr;
extern cmd(), cmr(),cmx(), cmt();
tname = tc;
command = cmr;
if ((narg = rnarg = argc) < 2) narg = 2;
else {
ptr = argv[1]; /* get first argument */
parg = &argv[2]; /* pointer to second argument */
while (c = *ptr++) switch(c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
tc[8] = c;
mt[8] = c;
continue;
case 'f':
tname = *parg++;
flags |= flm;
narg--; rnarg--;
continue;
case 'c':
flags |= flc; continue;
case 'd':
setcom(cmd); continue;
case 'i':
flags |= fli; continue;
case 'm':
tname = mt;
flags |= flm;
continue;
case 'r':
flags &= ~flu; setcom(cmr); continue;
case 's':
flags |= fls; continue;
case 't':
setcom(cmt); continue;
case 'u':
flags |= flu; setcom(cmr); continue;
case 'v':
flags |= flv; continue;
case 'w':
flags |= flw; continue;
case 'x':
setcom(cmx); continue;
default:
useerr();
}
}
optap();
top = nptr = nameblk = sbrk(0);
(*command)();
}
optap()
{
extern cmr();
if ((flags & flm) == 0) { /* DECTAPE */
tapsiz = TCSIZ;
ndirent = TCDIRS;
fio =open(tc,2);
} else { /* MAGTAPE */
tapsiz = MTSIZ;
ndirent = MDIRENT;
if(command == cmr) {
fio = open(tname,1);
if (fio < 0) fio = creat(tname,0666);
} else
fio = open(tname,0);
}
if (fio < 0) {
printf("Tape open error\n");
done();
}
ndentb = ndirent/TPB;
edir = &dir[ndirent];
}
setcom(newcom)
int (*newcom)();
{
extern cmr();
if (command != cmr) useerr();
command = newcom;
}
useerr()
{
printf("Bad usage\n");
done();
}
/* /* COMMANDS */
cmd()
{
extern delete();
if (flags & (flm|flc)) useerr();
if (narg <= 2) useerr();
rddir();
gettape(delete);
wrdir();
check();
}
cmr()
{
if (flags & (flc|flm)) clrdir();
else rddir();
getfiles();
update();
check();
}
cmt()
{
extern taboc();
if (flags & (flc|flw)) useerr();
rddir();
if (flags & flv)
printf(" mode uid gid tapa size date time name\n");
gettape(taboc);
check();
}
cmx()
{
extern extract();
if (flags & (flc)) useerr();
rddir();
gettape(extract);
done();
}
check()
{
usage();
done();
}
done()
{
printf("End\n");
exit(0);
}
encode(pname,dptr) /* pname points to the pathname
* nptr points to next location in nameblk
* dptr points to the dir entry */
char *pname;
struct dent *dptr;
{
register char *np;
register n;
dptr->d_namep = np = nptr;
if (np > top - NAMELEN) {
if(sbrk(BRKINCR) == (char *)-1) {
printf("Out of core\n");
done();
} else
top += BRKINCR;
}
if((n=strlen(pname)) > NAMELEN) {
printf("Pathname too long - %s\nFile ignored\n",pname);
clrent(dptr);
}
else {
nptr += n+1;
strcpy(np, pname);
}
}
decode(pname,dptr) /* dptr points to the dir entry
* name is placed in pname[] */
char *pname;
struct dent *dptr;
{
strcpy(pname, dptr->d_namep);
}

View File

@@ -0,0 +1,348 @@
#include "tp.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
struct direct direct;
struct stat statb;
clrdir()
{
register j, *p;
j = ndirent * (DIRSZ/sizeof(int));
p = (int *)dir;
do (*p++ = 0); while (--j);
lastd = 0;
}
clrent(ptr)
struct dent *ptr;
{
register *p, j;
p = (int *)ptr;
j = DIRSZ/sizeof(int);
do *p++ = 0;
while (--j);
if (++ptr == lastd) do {
if (--lastd < dir) {
lastd = 0;
return;
}
} while (lastd->d_namep == 0);
}
rddir()
{
register struct tent *tp;
register struct dent *p1;
struct dent *dptr;
struct tent *tptr;
int count, i, sum;
short reg, *sp;
sum = 0;
clrdir();
rseek(0);
tread(); /* Read the bootstrap block */
if ((tpentry[TPB-1].cksum != 0) && (flags & flm)) {
ndirent = tpentry[TPB-1].cksum;
if(flags & fls) swab((char *)&ndirent, (char *)&ndirent, sizeof(ndirent));
if(ndirent < 0 || ndirent > MDIRENT) ndirent = MDIRENT;
ndentb = ndirent/TPB;
}
dptr = &dir[0];
count = ndirent;
do {
if ((count % TPB) == 0) { /* next block */
tread();
tptr = &tpentry[0];
}
if(flags & fls)
swab((char *)tptr, (char *)tptr, sizeof(*tptr));
sp = (short *)tptr;
reg = 0;
for(i=0;i<sizeof(struct tent)/sizeof(short);i++)
reg += *sp++;
if(flags & fls) {
swab((char *)tptr, (char *)tptr, sizeof(*tptr));
swabdir(tptr);
}
sum |= reg;
p1 = dptr;
if (reg == 0) {
tp = tptr;
if(tp->pathnam[0] != '\0') {
lastd = p1;
encode(tp->pathnam,p1);
p1->d_mode = tp->mode;
p1->d_uid = tp->uid;
p1->d_gid = tp->gid;
p1->d_size = (((long)tp->size0&0377L)<<16)+(tp->size1&0177777L);
p1->d_time = tp->time;
p1->d_tapea = tp->tapea;
}
}
++tptr; /* bump to next tent */
(dptr++)->d_mode &= ~OK;
} while (--count);
if(sum != 0)
if(flags & (fls|fli)) {
printf("Directory checksum\n");
if ((flags & fli) == 0) done();
} else {
flags |= fls;
rddir();
printf("Warning: swabbing required\n");
return;
}
bitmap();
}
wrdir()
{
register struct tent *tp;
register struct dent *dp;
struct dent *dptr;
int count, i;
short reg, *sp;
wseek(0);
if (flags & flm)
reg = open(mheader,0);
else reg = open(theader,0);
if (reg >= 0) {
read(reg,(char *)tapeb,BSIZE);
close(reg);
if(flags & fls)
swab((char *)&ndirent, (char *)&tpentry[TPB-1].cksum, sizeof(ndirent));
else
tpentry[TPB-1].cksum = ndirent;
} else
printf("\7\7\7Warning: cannot read prototype boot block.\n");
dptr = &dir[0];
count = ndirent;
for (;;) {
twrite();
if (count == 0) return;
tp = &tpentry[0];
do {
dp = dptr++; /* dptr set to next entry */
if (dp->d_namep) {
decode(tp->pathnam,dp);
tp->mode = dp->d_mode;
tp->uid = dp->d_uid;
tp->gid = dp->d_gid;
tp->time = dp->d_time;
tp->size0 = dp->d_size >> 16;
tp->size1 = dp->d_size;
tp->tapea = dp->d_tapea;
if(flags & fls) {
swabdir(tp);
swab((char *)tp, (char *)tp, sizeof(*tp));
}
reg = 0;
sp = (short *)tp;
for(i=0;i<sizeof(struct tent)/sizeof(short)-1;i++)
reg -= *sp++;
*sp = reg;
if(flags & fls)
swab((char *)tp, (char *)tp, sizeof(*tp));
} else {
sp = (short *)tp;
for(i=0;i<sizeof(struct tent)/sizeof(short);i++)
*sp++ = 0;
}
tp++;
} while (--count % TPB);
}
}
tread()
{
register j, *ptr;
if (read(fio,(char *)tapeb,BSIZE) != BSIZE) {
printf("Tape read error\n");
if ((flags & fli) == 0) done();
ptr = (int *)tapeb;
j = BSIZE/sizeof(int);
while(j--) *ptr++ = 0;
}
rseeka++;
}
twrite()
{
if (write(fio, (char *)tapeb,BSIZE) != BSIZE) {
printf("Tape write error\n");
done();
}
++wseeka;
}
rseek(blk)
{
rseeka = blk;
if (lseek(fio,(long)blk*BSIZE,0) < 0) seekerr();
}
wseek(blk)
{
register amt, b;
amt = b = blk;
if ((amt -= wseeka) < 0) amt = -amt;
if (amt > 25 && b) {
lseek(fio, (long)(b-1)*BSIZE, 0); /* seek previous block */
read(fio, (char *)&wseeka, 1); /* read next block */
}
wseeka = b;
if (lseek(fio, (long)b*BSIZE, 0) < 0) seekerr();
}
seekerr()
{
printf("Tape seek error\n");
done();
}
verify(key)
{
register c;
if ((flags & (flw | flv)) == 0)
return(0);
repeat: printf("%c %s ", key, name);
if ((flags & flw) == 0) {
printf("\n");
return(0);
}
c = getchar();
if (c == 'n' && getchar() == '\n')
done();
if (c == '\n')
return(-1);
if (c == 'y' && getchar() == '\n')
return(0);
while (getchar() != '\n');
goto repeat;
}
getfiles()
{
if ((narg -= 2) == 0) {
strcpy(name, ".");
callout();
} else while (--narg >= 0) {
strcpy(name, *parg++);
callout();
}
}
expand()
{
register char *p0, *save0;
int n, fid;
if ((fid = open(name,0)) < 0) fserr();
for (;;) {
if ((n = read(fid, (char *)&direct, sizeof(direct))) != sizeof(direct)) {
if (n == 0) {
close(fid);
return;
}
fserr();
}
if (direct.d_ino == 0) /* null entry */
continue;
p0 = name;
if (direct.d_name[0] == '.') /* don't save .xxxx */
continue;
while (*p0++);
save0 = --p0; /* save loc of \0 */
if (p0[-1] != '/')
*p0++ = '/';
strcpy(p0, direct.d_name);
callout();
*save0 = 0; /* restore */
}
}
fserr()
{
printf("%s -- Cannot open file\n", name);
done();
}
callout()
{
register struct dent *d;
register char *ptr1, *ptr0;
struct dent *empty;
int mode;
if (stat(name,&statb) < 0) fserr();
mode = statb.st_mode;
if ((mode &= S_IFMT) != 0) {
if (mode == S_IFDIR) /* directory */
expand();
if(mode != S_IFREG) return;
}
/* when we reach here we have recursed until we found
* an ordinary file. Now we look for it in "dir".
*/
empty = 0;
d = &dir[0];
do {
if (d->d_namep == 0) { /* empty directory slot */
if (empty == 0) /* remember the first one */
empty = d;
continue;
}
decode(name1,d);
ptr0 = name;
ptr1 = name1;
do if (*ptr0++ != *ptr1) goto cont;
while (*ptr1++);
/* veritably the same name */
if (flags & flu) { /* check the times */
if (d->d_time >= statb.st_mtime)
return;
}
if (verify('r') < 0) return;
goto copydir;
cont: continue;
} while (++d <= lastd);
/* name not found in directory */
if ((d = empty) == 0) {
d = lastd +1;
if (d >= edir) {
printf("Directory overflow\n");
done();
}
}
if (verify('a') < 0) return;
if (d > lastd) lastd = d;
encode(name,d);
copydir:
d->d_mode = statb.st_mode | OK;
d->d_uid = statb.st_uid;
d->d_gid = statb.st_gid;
d->d_size = statb.st_size;
d->d_time = statb.st_mtime;
}
swabdir(tp)
register struct tent *tp;
{
swab((char *)tp, (char *)tp, sizeof(*tp));
swab(tp->pathnam, tp->pathnam, NAMELEN);
swab((char *)&tp->uid, (char *)&tp->uid, 4); /* uid,gid,spare,size0 */
}

View File

@@ -0,0 +1,248 @@
#include "tp.h"
gettape(how)
int (*how)();
{
register char *ptr0, *ptr1;
register struct dent *d;
int count;
do {
d = &dir[0];
count = 0;
do {
if (d->d_namep == 0) continue;
decode(name,d);
if (rnarg > 2) {
ptr0 = name;
ptr1 = *parg;
while (*ptr1)
if (*ptr0++ != *ptr1++) goto cont;
if (*ptr0 && *ptr0 != '/') goto cont;
}
(*how)(d); /* delete, extract, or taboc */
++count;
cont: continue;
} while (++d <= lastd);
if (count == 0 && rnarg > 2)
printf("%s not found\n", *parg);
++parg;
} while (--narg > 2);
}
delete(dd)
struct dent *dd;
{
if (verify('d') >= 0)
clrent(dd);
}
update()
{
register struct dent *d;
register b, last;
int first, size;
bitmap();
d = &dir[0];
do {
if(d->d_namep == 0 || (d->d_mode&OK) == 0) continue;
if (d->d_size == 0) continue;
/* find a place on the tape for this file */
size = (d->d_size+BSIZE-1)/BSIZE;
first = ndentb;
toosmall: ++first;
if ((last = first + size) >= tapsiz) maperr();
for (b = first; b < last; ++b)
if (map[(b>>3) & MAPMASK] & (1<<(b&7))) {
first = b;
goto toosmall;
};
d->d_tapea = first;
setmap(d);
} while (++d <= lastd);
wrdir();
update1();
}
update1()
{
register struct dent *d, *id;
register index;
int f;
for (;;) {
d = &dir[0];
index = MTSIZ;
id = 0;
do { /* find new dent with lowest tape address */
if(d->d_namep == 0 || (d->d_mode&OK) == 0) continue;
if (d->d_tapea < index) {
index = d->d_tapea;
id = d;
}
} while (++d <= lastd);
if ((d = id) == 0) return;
d->d_mode &= ~OK; /* change from new to old */
if (d->d_size == 0) continue;
decode(name,d);
wseek(index);
if ((f = open(name,0)) < 0) {
printf("Can't open %s\n", name);
continue;
}
for (index = d->d_size/BSIZE; index != 0; --index) {
if (read(f,(char *)tapeb,BSIZE) != BSIZE) phserr();
twrite();
}
if (index = d->d_size % BSIZE) {
if (read(f,(char *)tapeb,index) != index) phserr();
twrite();
}
if (read(f,(char *)tapeb,1) != 0) phserr();
close(f);
}
}
phserr()
{ printf("%s -- Phase error \n", name); }
bitmap() /* place old files in the map */
{
register char *m;
register count;
register struct dent *d;
for(m=map;m<&map[MAPSIZE];) *m++ = 0;
count = ndirent;
d = dir;
do {
if(d->d_namep != 0 && (d->d_mode&OK) == 0
&& d->d_size != 0) setmap(d);
d++;
} while (--count);
}
setmap(d)
register struct dent *d;
{
unsigned c, block;
char bit;
int i;
c = d->d_size/BSIZE;
if (d->d_size % BSIZE) c++;
block = d->d_tapea;
if ((c += block) >= tapsiz) maperr();
do {
bit = 1 << (block & 7);
i = (block>>3) & MAPMASK;
if (bit & map[i]) maperr();
map[i] |= bit;
} while (++block < c);
}
maperr()
{
printf("Tape overflow\n");
done();
}
usage()
{
register reg,count;
int nused, nentr, nfree;
static lused;
bitmap();
for(count=0,nentr=0;count<ndirent;count++)
if(dir[count].d_namep != 0) nentr++;
nused = nfree = 0;
reg = ndentb;
++reg; /* address of first non-directory tape block */
count = tapsiz - reg;
do {
if (reg >= tapsiz) {
printf("Tape overflow\n");
done();
}
if (map[(reg>>3) & MAPMASK] & (1 << (reg&7))) {
nused++;
lused = reg;
} else {
if (flags & flm) break;
nfree++;
}
reg++;
} while (--count);
printf("%4d entries\n%4d used\n", nentr, nused);
if ((flags & flm)==0)
printf("%4d free\n", nfree);
printf("%4d last\n", lused);
}
taboc(dd)
struct dent *dd;
{
register mode;
register *m;
register char *s;
int count, *localtime();
char work[20];
if (flags & flv) {
mode = dd->d_mode;
s = &work[19];
*s = 0;
for (count = 3; count; --count) {
if (mode&1) *--s = 'x';
else *--s = '-';
if (mode&2) *--s = 'w';
else *--s = '-';
if (mode&4) *--s = 'r';
else *--s = '-';
mode >>= 3;
}
if (mode&4) s[2] = 's';
if (mode&2) s[5] = 's';
printf("%s%4d%4d%5d%9D ",s,dd->d_uid, dd->d_gid,dd->d_tapea,dd->d_size);
m = localtime(&dd->d_time);
printf("%2d/%2d/%2d %2d:%2d ",m[5],m[4]+1,m[3],m[2],m[1]);
}
printf("%s\n", name);
}
extract(d)
register struct dent *d;
{
register count, id;
if (d->d_size==0) return;
if (verify('x') < 0) return;
rseek(d->d_tapea);
unlink(name);
if ((id = creat(name,d->d_mode)) < 0)
printf("%s -- create error\n", name);
count = d->d_size/BSIZE;
while (count--) {
tread();
if (write(id, (char *)tapeb, BSIZE) != BSIZE) goto ng;
}
if (count = d->d_size % BSIZE) {
tread();
if (write(id, (char *)tapeb, count) != count) {
ng: printf("%s -- write error\n", name);
close(id);
return;
}
}
close(id);
chown(name,d->d_uid & 0377, d->d_gid&0377);
}

View File

@@ -0,0 +1,5 @@
char mt[] = "/dev/rmt0";
char tc[] = "/dev/tapx";
int flags = flu;
char mheader[] = "/usr/mdec/mboot";
char theader[] = "/usr/mdec/tboot";