Research V7 development
[unix-history] / usr / src / cmd / icheck.c
#define NI 16
#define NB 10
#define BITS 8
#define MAXFN 500
#ifndef STANDALONE
#include <stdio.h>
#endif
#include <sys/param.h>
#include <sys/inode.h>
#include <sys/ino.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
struct filsys sblock;
struct dinode itab[INOPB*NI];
daddr_t iaddr[NADDR];
daddr_t blist[NB];
char *bmap;
int sflg;
int mflg;
int dflg;
int fi;
ino_t ino;
ino_t nrfile;
ino_t ndfile;
ino_t nbfile;
ino_t ncfile;
daddr_t ndirect;
daddr_t nindir;
daddr_t niindir;
daddr_t niiindir;
daddr_t nfree;
daddr_t ndup;
int nerror;
long atol();
daddr_t alloc();
#ifndef STANDALONE
char *malloc();
#endif
main(argc, argv)
char *argv[];
{
register i;
long n;
blist[0] = -1;
#ifndef STANDALONE
while (--argc) {
argv++;
if (**argv=='-')
switch ((*argv)[1]) {
case 'd':
dflg++;
continue;
case 'm':
mflg++;
continue;
case 's':
sflg++;
continue;
case 'b':
for(i=0; i<NB; i++) {
n = atol(argv[1]);
if(n == 0)
break;
blist[i] = n;
argv++;
argc--;
}
blist[i] = -1;
continue;
default:
printf("Bad flag\n");
}
check(*argv);
}
#else
{
static char fname[0];
printf("File: ");
gets(fname);
check(fname);
}
#endif
return(nerror);
}
check(file)
char *file;
{
register i, j;
ino_t mino;
daddr_t d;
long n;
fi = open(file, sflg?2:0);
if (fi < 0) {
printf("cannot open %s\n", file);
nerror |= 04;
return;
}
printf("%s:\n", file);
nrfile = 0;
ndfile = 0;
ncfile = 0;
nbfile = 0;
ndirect = 0;
nindir = 0;
niindir = 0;
niiindir = 0;
ndup = 0;
#ifndef STANDALONE
sync();
#endif
bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
mino = (sblock.s_isize-2) * INOPB;
ino = 0;
n = (sblock.s_fsize - sblock.s_isize + BITS-1) / BITS;
if (n != (unsigned)n) {
printf("Check fsize and isize: %ld, %u\n",
sblock.s_fsize, sblock.s_isize);
}
#ifdef STANDALONE
bmap = NULL;
#else
bmap = malloc((unsigned)n);
#endif
if (bmap==NULL) {
printf("Not enough core; duplicates unchecked\n");
dflg++;
sflg = 0;
}
if(!dflg)
for(i=0; i<(unsigned)n; i++)
bmap[i] = 0;
for(i=2;; i+=NI) {
if(ino >= mino)
break;
bread((daddr_t)i, (char *)itab, sizeof(itab));
for(j=0; j<INOPB*NI; j++) {
if(ino >= mino)
break;
ino++;
pass1(&itab[j]);
}
}
ino = 0;
#ifndef STANDALONE
sync();
#endif
bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
if (sflg) {
makefree();
close(fi);
#ifndef STANDALONE
if (bmap)
free(bmap);
#endif
return;
}
nfree = 0;
while(n = alloc()) {
if (chk(n, "free"))
break;
nfree++;
}
close(fi);
#ifndef STANDALONE
if (bmap)
free(bmap);
#endif
i = nrfile + ndfile + ncfile + nbfile;
#ifndef STANDALONE
printf("files %6u (r=%u,d=%u,b=%u,c=%u)\n",
i, nrfile, ndfile, nbfile, ncfile);
#else
printf("files %u (r=%u,d=%u,b=%u,c=%u)\n",
i, nrfile, ndfile, nbfile, ncfile);
#endif
n = ndirect + nindir + niindir + niindir;
#ifdef STANDALONE
printf("used %ld (i=%ld,ii=%ld,iii=%ld,d=%ld)\n",
n, nindir, niindir, niiindir, ndirect);
printf("free %ld\n", nfree);
#else
printf("used %7ld (i=%ld,ii=%ld,iii=%ld,d=%ld)\n",
n, nindir, niindir, niiindir, ndirect);
printf("free %7ld\n", nfree);
#endif
if(!dflg) {
n = 0;
for(d=sblock.s_isize; d<sblock.s_fsize; d++)
if(!duped(d)) {
if(mflg)
printf("%ld missing\n", d);
n++;
}
printf("missing%5ld\n", n);
}
}
pass1(ip)
register struct dinode *ip;
{
daddr_t ind1[NINDIR];
daddr_t ind2[NINDIR];
daddr_t ind3[NINDIR];
register i, j;
int k, l;
i = ip->di_mode & IFMT;
if(i == 0) {
sblock.s_tinode++;
return;
}
if(i == IFCHR) {
ncfile++;
return;
}
if(i == IFBLK) {
nbfile++;
return;
}
if(i == IFDIR)
ndfile++; else
if(i == IFREG)
nrfile++;
else {
printf("bad mode %u\n", ino);
return;
}
l3tol(iaddr, ip->di_addr, NADDR);
for(i=0; i<NADDR; i++) {
if(iaddr[i] == 0)
continue;
if(i < NADDR-3) {
ndirect++;
chk(iaddr[i], "data (small)");
continue;
}
nindir++;
if (chk(iaddr[i], "1st indirect"))
continue;
bread(iaddr[i], (char *)ind1, BSIZE);
for(j=0; j<NINDIR; j++) {
if(ind1[j] == 0)
continue;
if(i == NADDR-3) {
ndirect++;
chk(ind1[j], "data (large)");
continue;
}
niindir++;
if(chk(ind1[j], "2nd indirect"))
continue;
bread(ind1[j], (char *)ind2, BSIZE);
for(k=0; k<NINDIR; k++) {
if(ind2[k] == 0)
continue;
if(i == NADDR-2) {
ndirect++;
chk(ind2[k], "data (huge)");
continue;
}
niiindir++;
if(chk(ind2[k], "3rd indirect"))
continue;
bread(ind2[k], (char *)ind3, BSIZE);
for(l=0; l<NINDIR; l++)
if(ind3[l]) {
ndirect++;
chk(ind3[l], "data (garg)");
}
}
}
}
}
chk(bno, s)
daddr_t bno;
char *s;
{
register n;
if (bno<sblock.s_isize || bno>=sblock.s_fsize) {
printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
return(1);
}
if(duped(bno)) {
printf("%ld dup; inode=%u, class=%s\n", bno, ino, s);
ndup++;
}
for (n=0; blist[n] != -1; n++)
if (bno == blist[n])
printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
return(0);
}
duped(bno)
daddr_t bno;
{
daddr_t d;
register m, n;
if(dflg)
return(0);
d = bno - sblock.s_isize;
m = 1 << (d%BITS);
n = (d/BITS);
if(bmap[n] & m)
return(1);
bmap[n] |= m;
return(0);
}
daddr_t
alloc()
{
int i;
daddr_t bno;
union {
char data[BSIZE];
struct fblk fb;
} buf;
sblock.s_tfree--;
if (sblock.s_nfree<=0)
return(0);
if (sblock.s_nfree>NICFREE) {
printf("Bad free list, s.b. count = %d\n", sblock.s_nfree);
return(0);
}
bno = sblock.s_free[--sblock.s_nfree];
sblock.s_free[sblock.s_nfree] = (daddr_t)0;
if(bno == 0)
return(bno);
if(sblock.s_nfree <= 0) {
bread(bno, buf.data, BSIZE);
sblock.s_nfree = buf.df_nfree;
if (sblock.s_nfree<0 || sblock.s_nfree>NICFREE) {
printf("Bad free list, entry count of block %ld = %d\n",
bno, sblock.s_nfree);
sblock.s_nfree = 0;
return(0);
}
for(i=0; i<NICFREE; i++)
sblock.s_free[i] = buf.df_free[i];
}
return(bno);
}
bfree(bno)
daddr_t bno;
{
union {
char data[BSIZE];
struct fblk fb;
} buf;
int i;
sblock.s_tfree++;
if(sblock.s_nfree >= NICFREE) {
for(i=0; i<BSIZE; i++)
buf.data[i] = 0;
buf.df_nfree = sblock.s_nfree;
for(i=0; i<NICFREE; i++)
buf.df_free[i] = sblock.s_free[i];
bwrite(bno, buf.data);
sblock.s_nfree = 0;
}
sblock.s_free[sblock.s_nfree] = bno;
sblock.s_nfree++;
}
bread(bno, buf, cnt)
daddr_t bno;
char *buf;
{
register i;
lseek(fi, bno*BSIZE, 0);
if (read(fi, buf, cnt) != cnt) {
printf("read error %ld\n", bno);
if (sflg) {
printf("No update\n");
sflg = 0;
}
for(i=0; i<BSIZE; i++)
buf[i] = 0;
}
}
bwrite(bno, buf)
daddr_t bno;
char *buf;
{
lseek(fi, bno*BSIZE, 0);
if (write(fi, buf, BSIZE) != BSIZE)
printf("write error %ld\n", bno);
}
makefree()
{
char flg[MAXFN];
int adr[MAXFN];
register i, j;
daddr_t f, d;
int m, n;
n = sblock.s_n;
if(n <= 0 || n > MAXFN)
n = MAXFN;
sblock.s_n = n;
m = sblock.s_m;
if(m <= 0 || m > sblock.s_n)
m = 3;
sblock.s_m = m;
for(i=0; i<n; i++)
flg[i] = 0;
i = 0;
for(j=0; j<n; j++) {
while(flg[i])
i = (i+1)%n;
adr[j] = i+1;
flg[i]++;
i = (i+m)%n;
}
sblock.s_nfree = 0;
sblock.s_ninode = 0;
sblock.s_flock = 0;
sblock.s_ilock = 0;
sblock.s_fmod = 0;
sblock.s_ronly = 0;
#ifndef STANDALONE
time(&sblock.s_time);
#endif
sblock.s_tfree = 0;
sblock.s_tinode = 0;
bfree((daddr_t)0);
d = sblock.s_fsize-1;
while(d%sblock.s_n)
d++;
for(; d > 0; d -= sblock.s_n)
for(i=0; i<sblock.s_n; i++) {
f = d - adr[i];
if(f < sblock.s_fsize && f >= sblock.s_isize)
if(!duped(f))
bfree(f);
}
bwrite((daddr_t)1, (char *)&sblock);
#ifndef STANDALONE
sync();
#endif
return;
}