|
|
researchv10 Norman
#define NI 4
#define NB 500
#define BITS 8
#define MAXFN 500
#include <stdio.h>
#include <sys/param.h>
#include <sys/inode.h>
#include <sys/ino.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/stat.h>
#define BITFSBIT 64 /* should be in param.h */
#define BIGINOPB INOPB(BITFSBIT)
#define BIGBSIZE BSIZE(BITFSBIT)
#define BIGNINDIR NINDIR(BITFSBIT)
struct filsys sblock;
struct stat status;
#define dev status.st_rdev
struct dinode itab[BIGINOPB*NI];
daddr_t iaddr[NADDR];
daddr_t blist[NB];
char *bmap;
int sflg;
int mflg;
int dflg;
int eflg;
int fi;
long ino;
int bigflag;
ino_t nrfile;
ino_t ndfile;
ino_t nbfile;
ino_t ncfile;
ino_t nlfile;
daddr_t ndirect;
daddr_t nindir;
daddr_t niindir;
daddr_t niiindir;
daddr_t nfree;
daddr_t ndup;
daddr_t maxblk;
int nerror;
long atol();
daddr_t alloc();
char *malloc();
char *memset();
time_t time();
long lseek();
void sync();
main(argc, argv)
char *argv[];
{
register i;
long n;
setbuf(stdout, (char *)NULL);
blist[0] = -1;
while (--argc) {
argv++;
if (**argv=='-')
switch ((*argv)[1]) {
case 'd':
dflg++;
continue;
case 'e':
eflg++;
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;
case 'B':
bigflag = BITFSBIT;
continue;
default:
fprintf(stderr, "Bad flag\n");
}
check(*argv);
}
return(nerror);
}
check(file)
char *file;
{
register i, j;
long mino;
daddr_t d;
long n;
fi = open(file, sflg?2:0);
if (fi < 0) {
fprintf(stderr, "cannot open %s\n", file);
nerror |= 04;
return;
}
if (fstat(fi, &status) < 0) {
fprintf(stderr, "cannot fstat %s\n", file);
nerror |= 04;
close(fi);
return;
}
if ((status.st_mode & S_IFMT) == S_IFREG)
dev = makedev(0, bigflag);
printf("%s:\n", file);
nrfile = 0;
ndfile = 0;
ncfile = 0;
nbfile = 0;
nlfile = 0;
ndirect = 0;
nindir = 0;
niindir = 0;
niiindir = 0;
ndup = 0;
sync();
bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
mino = ((int)sblock.s_isize-2) * INOPB(dev);
ino = 0;
maxblk = sblock.s_fsize;
/*
* fudge for new bitmapped filesystems
* this should be isolated somewhere
*/
if (BITFS(dev) && sblock.U.N.S_flag) {
n = (sblock.s_fsize+sblock.U.N.S_bsize-1)/sblock.U.N.S_bsize;
maxblk -= n;
}
n = (maxblk - (int)sblock.s_isize + BITS-1) / BITS;
if (n != (unsigned)n) {
fprintf(stderr, "Check fsize and isize: %ld, %u\n",
maxblk, (int)sblock.s_isize);
}
bmap = malloc((unsigned)n);
if (bmap==NULL) {
fprintf(stderr, "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, BSIZE(dev)*NI);
for(j=0; j<INOPB(dev)*NI; j++) {
if(ino >= mino)
break;
ino++;
pass1(&itab[j]);
}
}
ino = 0;
sync();
bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
if (sflg) {
makefree();
close(fi);
if (bmap)
free(bmap);
return;
}
nfree = 0;
while(n = alloc()) {
if (chk(0, n, "free"))
break;
nfree++;
}
close(fi);
i = nrfile + ndfile + ncfile + nbfile + nlfile;
printf("files %6u (r=%u,d=%u,b=%u,c=%u,l=%u)\n",
i, nrfile, ndfile, nbfile, ncfile, nlfile);
n = ndirect + nindir + niindir + niiindir;
printf("used %7ld (i=%ld,ii=%ld,iii=%ld,d=%ld)\n",
n, nindir, niindir, niiindir, ndirect);
printf("free %7ld\n", nfree);
if(!dflg) {
n = 0;
for(d=(int)sblock.s_isize; d<maxblk; d++)
if(!duped(d)) {
if(mflg)
printf("%ld missing\n", d);
n++;
}
printf("missing%5ld\n", n);
}
if (bmap)
free(bmap);
}
pass1(ip)
register struct dinode *ip;
{
daddr_t ind1[BIGNINDIR];
daddr_t ind2[BIGNINDIR];
daddr_t ind3[BIGNINDIR];
register i, j;
int k, l;
int squawked = 0;
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 if(i == IFLNK)
nlfile++;
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(squawked++, iaddr[i], "data (small)");
continue;
}
nindir++;
if (chk(squawked++, iaddr[i], "1st indirect"))
continue;
bread(iaddr[i], (char *)ind1, BSIZE(dev));
for(j=0; j<NINDIR(dev); j++) {
if(ind1[j] == 0)
continue;
if(i == NADDR-3) {
ndirect++;
chk(squawked++, ind1[j], "data (large)");
continue;
}
niindir++;
if(chk(squawked++, ind1[j], "2nd indirect"))
continue;
bread(ind1[j], (char *)ind2, BSIZE(dev));
for(k=0; k<NINDIR(dev); k++) {
if(ind2[k] == 0)
continue;
if(i == NADDR-2) {
ndirect++;
chk(squawked++, ind2[k], "data (huge)");
continue;
}
niiindir++;
if(chk(squawked++, ind2[k], "3rd indirect"))
continue;
bread(ind2[k], (char *)ind3, BSIZE(dev));
for(l=0; l<NINDIR(dev); l++)
if(ind3[l]) {
ndirect++;
chk(squawked++, ind3[l], "data (garg)");
}
}
}
}
}
chk(loud, bno, s)
daddr_t bno;
char *s;
{
register n;
for (n=0; blist[n] != -1; n++)
if (bno == blist[n])
printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
if (bno<(int)sblock.s_isize || bno>=maxblk) {
if (loud == 0 || eflg == 0)
printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
return(1);
}
if(duped(bno)) {
if (loud == 0)
printf("%ld dup; inode=%u, class=%s\n", bno, ino, s);
ndup++;
}
return(0);
}
duped(bno)
daddr_t bno;
{
daddr_t d;
register m, n;
if(dflg)
return(0);
d = bno - (int)sblock.s_isize;
m = 1 << (d%BITS);
n = (d/BITS);
if(bmap[n] & m)
return(1);
bmap[n] |= m;
return(0);
}
daddr_t bitfsalloc(), bigfsalloc();
daddr_t
alloc()
{
daddr_t bno;
union {
char data[BIGBSIZE];
struct fblk fb;
} buf;
register int i;
sblock.s_tfree--;
if (BITFS(dev)) {
if (sblock.U.N.S_flag)
return (bigfsalloc());
return (bitfsalloc());
}
if (sblock.s_nfree<=0)
return(0);
if (sblock.s_nfree>NICFREE) {
fprintf(stderr, "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(dev));
sblock.s_nfree = buf.fb.df_nfree;
if (sblock.s_nfree<0 || sblock.s_nfree>NICFREE) {
fprintf(stderr, "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.fb.df_free[i];
}
return(bno);
}
daddr_t
bitfsalloc()
{
daddr_t bno;
register long *p;
register int i, j;
p = sblock.s_bfree;
for(i = 0; i < BITMAP && *p == 0; i++, p++)
;
if(i >= BITMAP)
return (0);
bno = sblock.s_isize + BITCELL * i;
for(j = 0; j < BITCELL; j++)
if(*p & (1 << j))
break;
if(j >= BITCELL)
return (0);
bno += j;
if(bno >= sblock.s_fsize)
return (0);
*p &= ~(1 << j);
return (bno);
}
daddr_t
bigfsalloc()
{
register long *p;
register int i;
int nblk;
static long *flist, *fend;
daddr_t bno;
if (flist == NULL) {
if (sblock.U.N.S_bsize == 0) /* unlikely */
sblock.U.N.S_bsize = BIGBSIZE*NBBY;
nblk = (sblock.s_fsize+sblock.U.N.S_bsize-1)/sblock.U.N.S_bsize;
if ((flist = (long *)malloc(nblk*BIGBSIZE)) == NULL) {
fprintf(stderr, "no mem for free bitmap\n");
return (0);
}
bno = sblock.s_fsize - nblk;
fend = flist;
for (i = 0; i < nblk; i++, bno++, fend += BIGBSIZE/sizeof(long))
bread(bno, (char *)fend, BIGBSIZE);
}
for (p = flist; p < fend && *p == 0; p++)
;
if (p >= fend)
return (0);
for (i = 0; i < BITCELL; i++)
if (*p & (1<<i))
break;
if (i >= BITCELL)
return (0); /* shouldn't happen */
bno = i + (p - flist)*BITCELL;
if (bno >= maxblk)
return (0);
*p &=~ (1<<i);
return (bno);
}
bread(bno, buf, cnt)
daddr_t bno;
char *buf;
{
register i;
lseek(fi, bno*BSIZE(dev), 0);
if (read(fi, buf, cnt) != cnt) {
fprintf(stderr, "read error %ld\n", bno);
if (sflg) {
fprintf(stderr, "No update\n");
sflg = 0;
}
for(i=0; i<BSIZE(dev); i++)
buf[i] = 0;
}
}
bwrite(bno, buf)
daddr_t bno;
char *buf;
{
lseek(fi, bno*BSIZE(dev), 0);
if (write(fi, buf, BSIZE(dev)) != BSIZE(dev))
fprintf(stderr, "write error %ld\n", bno);
}
makefree()
{
if (!BITFS(dev))
makeoldfree();
else if (sblock.U.N.S_flag == 0)
makesbitfree();
else
makebbitfree();
}
makeoldfree()
{
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;
time(&sblock.s_time);
bfree((daddr_t)0);
sblock.s_tfree = 0;
sblock.s_tinode = 0;
d = maxblk-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 < maxblk && f >= (int)sblock.s_isize)
if(!duped(f))
bfree(f);
}
bwrite((daddr_t)1, (char *)&sblock);
sync();
}
bfree(bno)
daddr_t bno;
{
union {
char data[BIGBSIZE];
struct fblk fb;
} buf;
int i;
sblock.s_tfree++;
if(sblock.s_nfree >= NICFREE) {
for(i=0; i<BSIZE(dev); i++)
buf.data[i] = 0;
buf.fb.df_nfree = sblock.s_nfree;
for(i=0; i<NICFREE; i++)
buf.fb.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++;
}
makesbitfree()
{
register daddr_t bno;
memset((char *)sblock.s_bfree, 0, BITMAP);
sblock.s_tfree = 0;
for (bno = sblock.s_isize; bno < maxblk; bno++)
if (!duped(bno)) {
BITFREE(sblock.s_bfree, bno-sblock.s_isize);
sblock.s_tfree++;
}
sblock.s_valid = 1;
bwrite((daddr_t)1, (char *)&sblock);
}
makebbitfree()
{
register daddr_t bno;
register long *flist;
register int nblk, i;
nblk = (sblock.s_fsize+sblock.U.N.S_bsize-1)/sblock.U.N.S_bsize;
if ((flist = (long *)malloc(nblk*BIGBSIZE)) == NULL) {
fprintf(stderr, "no mem for free bitmap\n");
exit(1); /* eh? */
}
memset((char *)flist, 0, nblk*BIGBSIZE);
sblock.s_tfree = 0;
for (bno = sblock.s_isize; bno < maxblk; bno++)
if (!duped(bno)) {
BITFREE(flist, bno);
sblock.s_tfree++;
}
for (i = 0; i < nblk; i++)
bwrite(sblock.s_fsize - nblk + i, ((char *)flist)+(i*BIGBSIZE));
free((char *)flist);
sblock.s_valid = 1;
bwrite((daddr_t)1, (char *)&sblock);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.