USG_PG3/usr/source/cmd2/icheck.c
#
#define CLEAR 021
#define DSTATE 020
#define FSTATE 001
#define ALLINUM inum=1;inum<=imax;inum++
#define ALLAP ap= &inode->addr[0];ap<&inode->addr[8];ap++) if (*ap
#define ALLOC (inode->flags&0100000)
#define LARGE (inode->flags&010000)
#define DIR ((inode->flags&060000)==040000)
#define NOTSPL ((inode->flags&020000)==0)
#define MAXDUP 100
struct SB {
int isize;
int fsize;
int nfree;
int free[100];
int ninode;
int finode[100];
char flock;
char ilock;
char fmod;
int time[2];
int fill[50];
} sb;
struct INODE {
int flags;
char nlinks;
char uid;
char gid;
char size0;
int size1;
int addr[8];
int actime[2];
int modtime[2];
} *inode;
struct DE {
int dnum;
char dname[14];
};
struct {int INT;};
char
*bbit,
*fbit,
*state,
*lc,
pathname[200],
*pp,
*name,
*fmin,
*fmax,
sflag,
nflag,
yflag,
*dev,
;
int
n_free,
n_blks,
n_files,
inum,
diskr,
diskw,
cc,
dups[MAXDUP],
*dc,
*el,
imax,
imod,
mod,
dmod,
buf[256],
ttyargs[3],
;
main(argn,argv)
int argn;
char *argv[];
{
char c,lsflag,lnflag,lyflag;
int i;
gtty(0,ttyargs);
lyflag = lnflag = lsflag = 0;
chdir("/dev");
sync();
if(argn==1) {
check(dev="rootdev");
goto fin;
}
for(i=1;i<argn;i++)
if(*argv[i] == '-') {
while(c = *++argv[i])
switch(c) {
case 's':
case 'S':
lsflag = 1;
continue;
case 'n':
case 'N':
lnflag = 1;
continue;
case 'y':
case 'Y':
lyflag = 1;
continue;
default:
printf("%c option?\n",c);
goto fin;
}
} else {
sflag = lsflag;
nflag = lnflag;
yflag = lyflag;
dev = argv[i];
check();
}
fin:
if(mod) {
printf("\n*****BOOT UNIX(NO SYNC!)*****\n");
for(;;) i = 0;
}
}
check()
{
register int *ap,*bp;
register char *blk;
int a,b,*cp;
/* Initialization */
if((diskr = open(dev,0)) == -1) {
printf("CAN NOT OPEN %s\n",dev);
return;
}
printf("\n%25s",dev);
if((diskw = open(dev,1)) == -1) {
nflag = 1;
printf("(NO WRITE)");
}
printf("\n");
if(seek(diskr,1,3) < 0) rwerr("SEEK",1);
if(read(diskr,&sb,512)<0) rwerr("READ",1);
imax = 16 * sb.isize;
fmin = 2+sb.isize;
fmax = sb.fsize;
bbit = sbrk(((fmax>>3)&017777)+1);
fbit = state = sbrk(imax/4+1);
lc = sbrk(imax+1);
el = dc = dups;
n_files = n_blks = n_free = *dc = 0;
pp = pathname;
pathname[0] = '/';
pathname[1] = 0;
/* Phase 1 */
printf("Phase 1 - Check Blocks\n");
for(ALLINUM) {
stat();
if(ALLOC) {
n_files++;
if(DIR) set(DSTATE); else set(FSTATE);
if((lc[inum]=inode->nlinks)==0)
set(CLEAR);
if(NOTSPL)for(ALLAP)
if(pass1(*ap) && LARGE)
iblock(*ap,&pass1);
}
}
/* Phase 2 */
setexit();
if(dc==dups) goto phase3;
printf("Phase 2 - Rescan for more DUPS\n");
for(ALLINUM)
if(get()) {
stat();
if(NOTSPL)for(ALLAP)
if(pass2(*ap) && LARGE)
iblock(*ap,&pass2);
}
/* Phase 3 */
phase3:
printf("Phase 3 - Check Pathnames\n");
inum = 1;
lc[1]++;
descend();
/* Phase 4 */
printf("Phase 4 - Check Reference Counts\n");
for(ALLINUM)
switch(get()) {
case FSTATE:
if(lc[inum]) adj();
continue;
case DSTATE:
case CLEAR:
clri();
}
stat(imax+1);
/* Phase 5 */
if (sflag) goto salvage;
printf("Phase 5 - Check Free List\n");
brk(cp=fbit+(((fmax>>3)&017777)+1));
bp = bbit;
for(ap=fbit;ap<cp;) *ap++ = *bp++;
if(sb.nfree<=0 || sb.nfree>100) goto bad;
while(blk = sb.free[--sb.nfree]) {
if(sb.nfree==0) {
if(seek(diskr,blk,3) < 0) rwerr("SEEK",blk);
if(read(diskr,&sb.nfree,202)<0) rwerr("READ",blk);
}
if(sb.nfree<=0 || sb.nfree>100) goto bad;
if(blk<fmin || blk>=fmax
|| (fbit[a=((blk>>3)&017777)]&(b=1<<(blk&07)))) {
bad:
printf("%15s %-15s\tSALVAGE?","","BAD FREE LIST");
sflag = reply();
goto salvage;
}
fbit[a] =| b;
n_free++;
}
if((n_blks+n_free)!=(fmax-fmin)) {
printf("%15l %-15s\tSALVAGE?",fmax-fmin-n_blks-n_free,
"MISSING");
sflag = reply();
}
/* Phase 6 */
salvage:
if(sflag==0) goto statistic;
printf("Phase 6 - Salvage Free List\n");
n_free = sb.ninode = sb.nfree = 0;
sb.free[sb.nfree++] = 0;
for(blk=fmax-1;blk>=fmin;--blk)
if((bbit[(blk.INT>>3)&017777]&(1<<(blk&07)))==0) {
if(sb.nfree==100) {
if(nflag==0) {
if(seek(diskw,blk,3)<0) rwerr("SEEK",blk);
if(write(diskw,&sb.nfree,512)<0)
rwerr("WRITE",blk);
}
sb.nfree = 0;
}
sb.free[sb.nfree++] = blk;
n_free++;
}
if(nflag==0) {
if(seek(diskw,1,3)<0) rwerr("SEEK",1);
if(write(diskw,&sb,512)<0) rwerr("WRITE",1);
mod = 1;
}
statistic:
printf("%5l files %5l blocks %5l free\n",
n_files,n_blks,n_free);
close(diskr);
close(diskw);
}
pass1(blk)
char *blk;
{
register int a,b,*ip;
if(blk<fmin || blk>=fmax) {
blkerr("BAD",blk);
return(0);
}
if(bbit[a=((blk>>3)&017777)]&(b=(1<<(blk&07)))) {
blkerr("DUP",blk);
if(el > &dups[MAXDUP]) {
printf("\tEXCESSIVE DUPS EXIT?");
if(reply()) exit(); else goto ret;
}
ip = dups;
while(ip<dc)
if(*ip++ == blk) {
*el++ = blk;
goto ret;
}
*el++ = *dc;
*dc++ = blk;
} else {
bbit[a] =| b;
n_blks++;
}
ret:
return(1);
}
pass2(blk)
char *blk;
{
register int *ip;
if(blk<fmin || blk>=fmax) return(0);
ip = dups;
while(ip<dc)
if(*ip++ == blk) {
blkerr("DUP",blk);
*--ip = *--dc;
*dc = blk;
if(dc==dups) reset(); else break;
}
return(1);
}
stat()
{
static struct INODE ibuf[16];
static int cib;
register int ib;
if((ib=2+(inum-1)/16)!=cib) {
if(imod && (nflag==0)) {
if(seek(diskw,cib,3)<0) rwerr("SEEK",cib);
if(write(diskw,ibuf,512)<0) rwerr("WRITE",cib);
imod = 0;
mod = 1;
}
if(seek(diskr,cib=ib,3) < 0) rwerr("SEEK",cib);
if(read(diskr,ibuf,512)<0) rwerr("READ",cib);
}
return(inode = &ibuf[(inum-1)%16]);
}
iblock(blk,func)
char *blk,(*func)();
{
register int *ap;
ap = buf;
do {
getblk(blk);
if(*ap)
(*func)(*ap);
} while(++ap<&buf[256]);
}
blkerr(s,blk)
char *blk;
char *s;
{
printf("%15l %-15s I = %l\n",blk,s,inum);
set(CLEAR);
}
clri()
{
register int *ap;
stat();
printf("%15s %-15sI = %5l\tCLEAR?",
((inode->nlinks==0)||(get()!=CLEAR))?"UNREFERENCED":"BAD/DUP",
DIR?"DIRECTORY":"FILE",inum);
if(reply()) {
n_files--;
if(NOTSPL)for(ALLAP)
if(pass4(*ap) && LARGE)
iblock(*ap,&pass4);
for(ap=inode;ap<&inode[1];*ap++ = 0);
imod = 1;
}
}
pass4(blk)
char *blk;
{
register int a,b,*ip;
if(blk<fmin || blk>=fmax) return(0);
if(bbit[a=((blk>>3)&017777)]&(b=1<<(blk&07))) {
ip = dups;
while(ip<el)
if(*ip++ == blk) {
*--ip = *--el;
goto ret;
}
bbit[a] =& ~ b;
n_blks--;
}
ret:
return(1);
}
adj()
{
stat();
if(inode->nlinks==lc[inum])
clri();
else {
printf("%15s %-15sI = %5l\tADJUST?",
"LINK COUNT",DIR?"DIRECTORY":"FILE",inum);
if(reply()) {
inode->nlinks =- lc[inum];
imod = 1;
}
}
}
descend()
{
register int *ip,*ap;
int a[8];
extern int pass3();
char *lname;
if(inum>imax)
return(direrr("I OUT OF RANGE"));
again:
switch(get()) {
case DSTATE:
set(FSTATE);
lc[inum]--;
ip = &stat()->addr[0];
for(ap=a;ap<&a[8];) *ap++ = *ip++;
*pp++ = '/';
lname = name;
name = pp;
if(LARGE) {
for(ap=a;ap<&a[8];ap++)
if(*ap) iblock(*ap,&pass3);
} else {
for(ap=a;ap<&a[8];ap++)
if(*ap) pass3(*ap);
}
name = lname;
*--pp = 0;
return(0);
case FSTATE:
lc[inum]--;
return(0);
case 0:
return(direrr("UNALLOCATED"));
case CLEAR:
if(direrr("DUP/BAD")) return(1);
stat();
if(DIR) set(DSTATE); else set(FSTATE);
goto again;
}
}
pass3(blk)
char *blk;
{
register struct DE *dp;
register char *c;
dp = buf;
do {
getblk(blk);
if(inum = dp->dnum) {
c = &dp->dname[0];
while((*pp = *c++) && pp++ && c<&dp->dname[14]);
*pp = 0;
if(descend()) {
getblk(blk);
dmod = 1;
dp->dnum = 0;
}
pp = name;
}
} while(++dp<&buf[256]);
}
direrr(s)
char *s;
{
printf("%15s I = %-5l%s\tREMOVE?",s,inum,pathname);
return(reply());
}
reply()
{
register char c;
if(nflag) {
printf(" no\n");
return(0);
}
if(yflag) {
printf(" yes\n");
return(1);
}
do
c = getchar();
while(c == ' ' || c == '\t');
stty(0,ttyargs);
printf("\n");
if(c == 'y')
return(1);
else
return(0);
}
putchar(c)
char c;
{
if(c) write(1,&c,1);
}
getchar()
{
char c;
read(0,&c,1);
return(c);
}
rwerr(s,b)
char *s,*b;
{
printf("\nCAN NOT %s: %s\tBLOCK %5l\tEXIT?",s,dev,b);
if(nflag || reply()) {
printf("\n\n");
exit();
}
}
getblk(blk)
char *blk;
{
static char *cb;
if(blk==cb) return;
if(dmod && (nflag==0)) {
if(seek(diskw,cb,3)<0) rwerr("SEEK",cb);
if(write(diskw,buf,512)<0) rwerr("WRITE",cb);
dmod = 0;
}
if(seek(diskr,cb=blk,3)<0) rwerr("SEEK",blk);
if(read(diskr,buf,512)<0) rwerr("READ",blk);
}