BSD 4 release
[unix-history] / usr / src / cmd / tp / tp2.c
#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 */
}