MiniUnix/usr/sys/source/check.c
#
#define NBTMPB 2
char *dargv[]
{
0,
"/dev/rk0",
"/dev/rk1",
0
};
int bufa;
int sflg;
char lfile[] "/tmp/ktmp";
int lflg;
int uflg;
int lfdes;
int lfptr;
struct inode
{
int i_mode;
char i_nlink;
char i_uid;
char i_gid;
char i_size0;
char *i_size1;
int i_addr[8];
int i_atime[2];
int i_mtime[2];
};
/* modes */
#define IALLOC 0100000
#define IFMT 060000
#define IFDIR 040000
#define IFCHR 020000
#define IFBLK 060000
#define ILARG 010000
struct
{
char *s_isize;
char *s_fsize;
int s_nfree;
int s_free[100];
int s_ninode;
int s_inode[100];
char s_flock;
char s_ilock;
char s_fmod;
int time[2];
int pad[50];
} sblock;
char bitcnt[]
{
4,3,3,2,3,2,2,1,
3,2,2,1,2,1,1,0,
};
int ndlist;
int dlist[100];
char *great;
int nblist;
int blist[100];
char *bmap -1;
int fi;
int nfile;
int nspcl;
int nlarg;
int nvlarg;
int nindir;
int nvindir;
int ndir;
int nused;
int hiwat;
int nfree;
int ino;
int ndup;
int nnf 100;
struct
{
char icnt[2];
} *icnt;
char *ucnt;
struct fname
{
int inum;
int nptr;
int pnum;
} *dn, *edn;
int ldivr;
int fout;
main(argc, argv)
char **argv;
{
char *arg;
register *p;
argv[argc] = 0;
if(argc == 1) {
argv = dargv;
for(argc = 1; dargv[argc]; argc++);
}
if(argc>1 && *argv[1] == '-') {
argc--;
argv++;
arg = *argv;
while(*arg)
switch(*arg++) {
case 'u':
uflg++;
case 'l':
lflg++;
continue;
case 's':
sflg++;
continue;
case 'i':
dlist[ndlist++] = number(argv[1]);
argc--;
argv++;
continue;
case 'b':
blist[nblist++] = number(argv[1]);
argc--;
argv++;
continue;
case 'g':
great = number(argv[1]);
argc--;
argv++;
continue;
}
}
if (lflg)
sflg = 0;
fout = dup(1);
argc--;
argv++;
fprintf("%s:\n", argv[0]);
check(argv[0]);
flush();
close(fout);
fout = 1;
if(argc > 1)
execv("/bin/check", argv);
}
check(file)
char *file;
{
struct inode buf[16];
register i, j;
int compar(), cintr();
struct fname *dnp;
fi = open(file, 0);
if(fi < 0) {
fprintf("cannot open %s\n", file);
return;
}
sync();
bread(1, &sblock);
if (lflg) {
if(uflg) {
ucnt = sbrk(sblock.s_isize*2);
if(bad(ucnt))
return;
} else {
lfdes = creat(lfile, 0666);
if ((signal(2, 1) & 01) == 0)
signal(2, cintr);
}
dn = edn = sbrk(101*6);
if(bad(dn))
return;
} else {
bmap = sbrk(NBTMPB*512);
icnt = sbrk(sblock.s_isize*16);
if(bad(bmap) || bad(icnt))
return;
}
for(i=0; i<sblock.s_isize; i++) {
bread(i+2, buf);
for(j=0; j<16; j++) {
ino++;
pass1(&buf[j]);
}
}
if(uflg) {
for(ino=2; ino<sblock.s_isize*16; ino++) {
i = ldiv(0, ino, 8);
if(ucnt[i] & (1<<ldivr))
if(trace(ino, 0) == 0)
fprintf("%l\n", ino);
}
return;
}
ino = 0;
if (lflg) {
close(lfdes);
lfdes = open(lfile, 0);
qsort(dn, edn-dn, 6, compar);
i = -1;
j = 0;
for (dnp=dn; dnp<edn; dnp++) {
if(dnp->pnum == 0) {
if(dnp->inum != 1)
j = 1;
continue;
}
printf("%4l", dnp->inum);
if (dnp->inum == i)
putchar('l'); else
putchar(' ');
i = dnp->inum;
putchar(' ');
if(lflg > 1)
pstat(i, buf);
pfilename(dnp, 0);
if(j) {
j = 0;
printf("/.");
}
putchar('\n');
}
close(lfdes);
unlink(lfile);
return;
}
sync();
bread(1, &sblock);
if(sflg) {
close(fi);
fi = open(file, 2);
if(fi < 0) {
fprintf("cannot write %s\n", file);
return;
}
sblock.s_nfree = 0;
sblock.s_ninode = 0;
sblock.s_flock = 0;
sblock.s_ilock = 0;
sblock.s_fmod = 0;
free(0);
for(i=sblock.s_fsize-1; i>=sblock.s_isize+2; i--) {
ndup = 0;
chk(i, "URK", 0);
if(ndup == 0)
free(i);
}
inodlist();
bwrite(1, &sblock);
close(fi);
sync();
return;
}
while(i = alloc()) {
if(chk(i, "free", 0))
break;
nfree++;
}
if(ndup)
printf("%l dups in free\n", ndup);
ndup = sblock.s_fsize - sblock.s_isize - 2 - NBTMPB*4096;
for(i=0; i<NBTMPB*512; i++) {
j = bmap[i];
ndup =+ bitcnt[j&017];
ndup =+ bitcnt[(j>>4)&017];
}
if(ndup)
printf("%l missing\n", ndup);
for(i=0; i<sblock.s_isize*16; i++) {
j = icnt->icnt[i] & 0377;
if(j!=0 && j!=0200)
printf("%6l %3o\n", i+1, j);
}
printf("spcl %6l\n", nspcl);
printf("files %6l\n", nfile);
printf("large %6l\n", nlarg);
printf("vlarg %6l\n", nvlarg);
printf("direc %6l\n", ndir);
printf("indir %6l\n", nindir);
printf("vindr %6l\n", nvindir);
printf("used %6l\n", nused);
printf("last %6l\n", hiwat);
printf("free %6l\n", nfree);
close(fi);
}
cintr()
{
unlink(lfile);
exit();
}
compar(p1, p2)
struct fname *p1, *p2;
{
int i;
i = p1->inum - p2->inum;
if(i)
return(i);
return(p1->pnum - p2->pnum);
}
pass1(ip)
struct inode *ip;
{
int buf[256], vbuf[256];
register i, j, df;
int k;
if((ip->i_mode&IALLOC) == 0)
return;
if(uflg) {
i = ldiv(0, ino, 8);
ucnt[i] =| 1<<ldivr;
}
if (!lflg) {
icnt->icnt[ino-1] =+ 0100;
if(ip->i_nlink)
icnt->icnt[ino-1] =+ 0100 + ip->i_nlink;
}
if((ip->i_mode&IFCHR&IFBLK) != 0) {
nspcl++;
return;
}
df = 0;
if((ip->i_mode&IFMT) == IFDIR) {
df = ldiv(ip->i_size0, ip->i_size1, 16);
if(lflg && !uflg) {
if(--nnf<0) {
nnf = 100;
edn = sbrk(6*101);
if(bad(edn))
lflg = 0;
}
edn->pnum = 0;
edn->inum = ino;
edn++;
}
ndir++;
} else if (lflg)
return;
nfile++;
if((ip->i_mode&ILARG) != 0) {
nlarg++;
for(i=0; i<7; i++)
if(ip->i_addr[i] != 0) {
nindir++;
if(chk(ip->i_addr[i], "idir", 0))
continue;
bread(ip->i_addr[i], buf);
for(j=0; j<256; j++)
if(buf[j] != 0)
chk(buf[j], "ldir", df);
df =- 32;
}
if(ip->i_addr[7]) {
nvlarg++;
if(chk(ip->i_addr[7], "viin", 0))
return;
bread(ip->i_addr[7], buf);
for(j=0; j<256; j++)
if(buf[j] != 0) {
nvindir++;
if(chk(buf[j], "vind", 0))
continue;
bread(buf[j], vbuf);
for(k=0; k<256; k++)
if(vbuf[k])
chk(vbuf[k], "vdir", df);
}
}
return;
}
for(i=0; i<8; i++) {
if(ip->i_addr[i] != 0)
chk(ip->i_addr[i], "sdir", df);
df =- 32;
}
}
chk(ii, s, df)
char *ii;
{
register char *i;
register n, j;
int b;
int buf[256];
struct {
int ino;
char name[14];
};
i = ii;
for(j=0; j<nblist; j++)
if(i == blist[j])
fprintf("%l blk; i=%l(%s)\n", i, ino, s);
if(great && i >= great && i)
fprintf("%l geq; i=%l(%s)\n", i, ino, s);
if(ino) {
nused++;
if(i > hiwat)
hiwat = i;
}
if(i<sblock.s_isize+2 || i>=sblock.s_fsize) {
fprintf("%l bad; i=%l(%s)\n", i, ino, s);
return(1);
}
n = ldiv(0, i, 8);
if (lflg==0) {
j = (1<<ldivr);
if(bmap[n] & j) {
if(ino == 0) {
ndup++;
return(0);
}
fprintf("%l dup; i=%l(%s)\n", i, ino, s);
return(1);
}
bmap[n] =| j;
}
if(df>0) {
bread(i, buf);
for(n=0; n<256; n=+8) {
if(df <= 0)
break;
df--;
if((b=buf[n]) == 0)
continue;
if (lflg)
if(!(buf[n].name[0]=='.' &&
(buf[n].name[1]=='\0' ||
(buf[n].name[1]=='.' && buf[n].name[2]=='\0')))) {
if (--nnf<0) {
nnf = 100;
edn = sbrk(6*101);
if(bad(edn))
lflg = 0;
}
edn->pnum = ino;
edn->inum = buf[n];
edn->nptr = lfptr;
for (j=0; j<14; j++)
if(buf[n].name[j] == '\0')
break;
j++;
if(!uflg)
write(lfdes, buf[n].name, j);
lfptr =+ j;
edn++;
}
for(j=0; j<ndlist; j++)
if(b == dlist[j])
fprintf("%l ino; i=%l(%s) \"%.16s\"\n",
b, ino, s, buf+n+1);
if(b<1 || b>16*sblock.s_isize) {
fprintf("%l din; i=%l(%s)\n", i, ino, s);
continue;
}
if (!lflg)
icnt->icnt[b-1]--;
}
}
return(0);
}
pfilename(dp, recur)
struct fname *dp;
{
register struct fname *p;
char name[14];
if (++recur > 10) {
putchar('.');
putchar('.');
putchar('.');
} else
if (dp->pnum != 1) {
for (p = dn; p<edn; p++) {
if (p->inum==dp->pnum && p->pnum!=0) {
pfilename(p, recur);
goto yes;
}
}
putchar('?');
putchar('?');
putchar('?');
yes:
putchar('/');
}
seek(lfdes, dp->nptr, 0);
read(lfdes, name, 14);
printf("%.14s", name);
}
pstat(i, buf)
{
register n, *p;
n = ldiv(0, i+31, 16);
if(n != bufa) {
bufa = n;
bread(n, buf);
}
p = buf + ldivr*32;
printf("%4o ", p->i_mode&07777);
pdate(p->i_atime);
pdate(p->i_mtime);
}
pdate(t)
int *t;
{
register *p;
p = localtime(t);
p2dig(p[5], '/');
p2dig(p[4]+1, '/');
p2dig(p[3], ' ');
p2dig(p[2], ':');
p2dig(p[1], ' ');
}
p2dig(n, c)
{
putchar(n/10 + '0');
putchar(n%10 + '0');
putchar(c);
}
alloc()
{
register b, i;
int buf[256];
i = --sblock.s_nfree;
if(i<0 || i>=100) {
fprintf("bad freeblock\n");
return(0);
}
b = sblock.s_free[i];
if(b == 0)
return(0);
if(sblock.s_nfree <= 0) {
bread(b, buf);
sblock.s_nfree = buf[0];
for(i=0; i<100; i++)
sblock.s_free[i] = buf[i+1];
}
return(b);
}
bread(bno, buf)
{
seek(fi, bno, 3);
if(read(fi, buf, 512) != 512) {
fprintf("read error %d\n", bno);
exit();
}
}
free(in)
{
int i;
int buf[256];
if(sblock.s_nfree >= 100) {
buf[0] = sblock.s_nfree;
for(i=0; i<100; i++)
buf[i+1] = sblock.s_free[i];
sblock.s_nfree = 0;
bwrite(in, buf);
}
sblock.s_free[sblock.s_nfree++] = in;
}
bwrite(bno, buf)
{
seek(fi, bno, 3);
if(write(fi, buf, 512) != 512) {
fprintf("write error %d\n", bno);
exit();
}
}
number(s)
char *s;
{
int n, c;
n = 0;
while(c = *s++) {
if(c<'0' || c>'9')
continue;
n = n*10+c-'0';
}
return(n);
}
fprintf(a, b, c, d, e)
{
printf(a, b, c, d, e);
flush();
}
bad(f)
{
if(f == -1) {
fprintf("out of memory\n");
return(1);
}
return(0);
}
trace(ii, r)
{
register struct fname *p;
register i, j;
i = ii;
r++;
if(r > 10)
return(0);
for(p=dn; p<edn; p++)
if(p->inum == i) {
j = p->pnum;
if(j == 0 || j == 1)
return(j);
if(trace(j, r) == 1) {
setpn(j, 1);
return(1);
}
}
setpn(i, 0);
return(0);
}
setpn(pn, n)
{
register struct fname *p;
register i, j;
i = pn;
j = n;
for(p=dn; p<edn; p++)
if(p->pnum == i)
p->pnum = j;
}
inodlist()
{
register struct inode *ip;
register i, bn;
int buf[256];
ino = 0;
for(bn = 2; bn < 2+sblock.s_isize; bn++) {
bread(bn, buf);
ip = buf;
for(i = 0; i < 16; i++) {
ino++;
if(ip->i_mode == 0) {
sblock.s_inode[sblock.s_ninode++] = ino;
if(sblock.s_ninode >= 100)
return;
}
ip++;
}
}
}