USG_PG3/usr/source/cmd3/ncheck.c
#
#define ERROR 0
#define PAD 10
#define NULL 0
char *dargv[]
{
"/dev/rroot",
"/dev/rrusr",
"/dev/rsrc",
0
};
int pass1();
int pass2();
int pass3();
#define NINODE 16*16
#include "../head/ino.h"
#include "../head/filsys.h"
struct filsys sblock;
struct inode inode[NINODE];
int sflg;
int aflg;
int uflg;
int uid;
int nufile;
#define NI 20
#define NDIRS 787
struct ilist{
int inum;
int size;
};
struct ilist *ilist;
struct ilist *ulist;
struct user{
int id;
char *uname;
};
struct user *user;
int nuser;
int ic;
int nilist;
int nulist;
int fi;
struct htab {
int hino;
int hpino;
char hname[14];
} ;
struct htab *htab;
int hsize;
int nhent PAD;
int (*pass[])() { pass1, pass2, pass3 };
char *lasts;
int ino;
int nerror;
int nffil;
int fout;
int nfiles;
struct dir {
int ino;
char name[14];
};
int ndir;
int try;
int error;
int first;
int ufirst;
int carg;
char cbuf[518];
char pbuf[128];
int ac;
char **av;
int lim;
char *nm;
main(argc, argv)
char **argv;
{
register char **p;
struct user *up,*uup;
int i;
char *q;
register int n;
register struct ilist *lp;
struct ilist *llp;
/*
nffil = dup(1);
*/
carg = argc;
lim = 1;
if(carg == 3)
lim = 0;
ac = argc;
av = argv;
if (ac == 1) {
for (p = dargv; *p;)
check(*p++);
return(nerror);
}
while (--ac) {
av++;
if (**av=='-') switch ((*av)[1]) {
case 's':
sflg++;
continue;
case 'a':
aflg++;
continue;
case 'i':
if(first == 0){
if(carg == 3)
nilist = 512;
else
nilist = ac;
first++;
ilist = alloc(sizeof(ilist[0])*nilist);
llp = &ilist[nilist-1];
nilist = 1;
lp = ilist;
}
av++;
ac--;
while((ac>lim)&&(q = token())&&(lp<llp)){
if(carg != 3){
ac--;
av++;
}
if((n = number(q)) != -1){
lp->inum = n;
lp++;
nilist++;
}else
break;
}
lp->inum = -1;
ac++;
av--;
if(lp == ilist){
printf2("I-node numbers?\n");
exit(1);
}
continue;
case 'u':
uflg++;
if(ufirst == 0){
ufirst++;
user = alloc(129*sizeof(user[0]));
nuser = 1;
up = user;
uup = &user[129];
}
ac--;
av++;
while((ac>lim)&&(q = token())&&(up<uup)){
if(carg != 3){
ac--;
av++;
}
nm = q;
if(((n = number(q)) != -1)||
((n = getpwent(q))!= -1)){
up->id = n;
up->uname = alloc(n = length(nm)+1);
copy(up->uname,nm,n);
nuser++;
up++;
}else{
printf("%s unknown user\n",q);
}
}
up->id = -1;
ac++;
av--;
if(up == user){
printf2("User id's?\n");
exit(1);
}
continue;
default:
printf2("Bad flag\n");
}
if(ilist == NULL){
ilist = alloc(sizeof(ilist[0]));
ilist[0].inum = -1;
}
check(*av);
}
return(nerror);
}
char lbuf[128];
token()
{
register char *p;
register char c;
if(carg != 3){
return(*av);
}
p = lbuf;
while((c = getc(cbuf)) >=0){
switch(c){
case ' ':
case '\t':
case '\n':
goto out;
default:
*p++ = c;
if(p > &lbuf[128]){
printf2("Line buffer exceeded\n");
lbuf[0] = '\0';
goto out;
}
}
}
if(p == lbuf)
return(NULL);
out:
*p = '\0';
return(&lbuf);
}
check(file)
char *file;
{
register i, j;
int pno;
register struct inode *ip;
int k;
int n,s,o;
htab = alloc((NDIRS+PAD)*sizeof(htab[0]));
hsize = NDIRS + PAD;
init();
fi = open(file, 0);
if (fi < 0) {
printf2("cannot open %s\n", file);
return;
}
printf2("%s:\n", file);
sync();
bread(1, &sblock, 512);
nfiles = sblock.s_isize*16;
fout = nffil;
flush();
try = 0;
retry:
nufile = 0;
nhent = PAD;
error = 0;
if((try == 0)&&uflg)
error++;
ndir = 0;
ino = 0;
for(i=0; i<nfiles;i =+ NINODE/16){
bread(i+2, inode, sizeof inode);
for(j=0; j<NINODE && ino<nfiles;j++) {
ino++;
n = pass1(&inode[j]);
if(n == ERROR)
error++;
}
}
if(error){
if(try == 1){
printf2("Error on second try\n");
exit(1);
}
if(nhent >=hsize){
printf2("Rescan necessary: %d. directories\n",ndir);
free(htab);
hsize = PAD + ndir + (ndir/5);
htab = alloc((PAD + ndir + (ndir/5))*sizeof(htab[0]));
init();
}
try++;
goto retry;
}
if(uflg){
ulist = alloc((nufile+15)*sizeof(ulist[0]));
nulist = nufile+2;
}
for (pno=1; pno<3; pno++) {
ino = 0;
for (i=0; ino<nfiles; i =+ NINODE/16) {
bread(i+2, inode, sizeof inode);
for (j=0; j<NINODE && ino<nfiles; j++) {
ino++;
ip = &inode[j];
if((pno == 1)&&uflg){
for(k=0;k<nuser;k++)
if(((ip->i_uid&0377) == user[k].id)&&
((ip->i_mode&IALLOC) != 0)){
ulist[ic].inum = ino;
s = (ip->i_size1 >> 9) & 0177;
s =| (ip->i_size0 << 7) & 077600;
if(ip->i_size1 & 0777)
s++;
if(s > 8) {
o = (s >> 8) & 0377;
if(s & 0377)
o++;
/* huge files
if(o > 7)
o++;
*/
s =+ o;
}
ulist[ic++].size = s;
break;
}
}
(*pass[pno])(ip);
}
}
if(uflg)
ulist[ic].inum = -1;
}
flush();
fout = 1;
}
pass1(ip)
struct inode *ip;
{
register struct user *u;
if ((ip->i_mode&IALLOC)==0)
return(1);
if(uflg){
for(u=user;u<&user[nuser];u++){
if((ip->i_uid&0377) == u->id){
nufile++;
break;
}
}
}
if((ip->i_mode&IFMT)!=IFDIR)
return(1);
ndir++;
return(lookup(ino, 1));
}
pass2(ip)
struct inode *ip;
{
register doff;
register struct htab *hp;
register struct dir *dp;
int i;
if ((ip->i_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR)
return;
doff = 0;
while (dp = dread(ip, doff)) {
doff =+ 16;
if (dp->ino==0)
continue;
if ((hp = lookup(dp->ino, 0)) == 0)
continue;
if (dotname(dp))
continue;
hp->hpino = ino;
for (i=0; i<14; i++)
hp->hname[i] = dp->name[i];
}
}
pass3(ip)
struct inode *ip;
{
int doff;
register struct dir *dp;
register struct ilist *ilp,*ulp;
char b[512];
int o;
int i;
struct inode *p;
struct user *up;
long tell();
if ((ip->i_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR)
return;
doff = 0;
while (dp = dread(ip, doff)) {
doff =+ 16;
if (dp->ino==0)
continue;
if (aflg==0 && dotname(dp))
continue;
for (ilp=ilist; ilp->inum >= 0; ilp++)
if (ilp->inum == dp->ino)
break;
if((ilp->inum == -1)&&(aflg == 0))
goto uf;
printf("%d ", dp->ino);
pname(ino, 0);
printf("/%.14s\n", dp->name);
uf:
if(uflg){
for (ulp=ulist; ulp->inum >= 0; ulp++)
if (ulp->inum == dp->ino)
break;
if(ulp->inum == -1)
continue;
printf("%d\t", dp->ino);
printf("%d\t",ulp->size);
if(nuser>2){
o = dp->ino + 31;
if(seek(fi,o>>4,3)<0)
printf2("Can't seek\n");
read(fi,&b,sizeof(b));
p = &b[(o%16)*32];
for(up=user;up<&user[nuser];up++)
if(up->id == (p->i_uid&0377)){
printf("%-7.7s\t",up->uname);
break;
}
}else
printf("%-7.7s\t",user[0].uname);
pname(ino, 0);
printf("/%.14s\n", dp->name);
}
}
}
dotname(adp)
{
register struct dir *dp;
dp = adp;
if (dp->name[0]=='.')
if (dp->name[1]==0 || dp->name[1]=='.' && dp->name[2]==0)
return(1);
return(0);
}
pname(i, lev)
{
register struct htab *hp;
if (i==1)
return;
if ((hp = lookup(i, 0)) == 0) {
printf("???");
return;
}
if (lev > 10) {
printf("...");
return;
}
pname(hp->hpino, ++lev);
printf("/%.14s", hp->hname);
}
lookup(i, ef)
{
register struct htab *hp;
for (hp = &htab[i%hsize]; hp->hino;) {
if (hp->hino==i)
return(hp);
if (++hp >= &htab[hsize])
hp = htab;
}
if (ef==0)
return(0);
if (++nhent >= hsize) {
return(ERROR);
}
hp->hino = i;
return(hp);
}
dread(aip, aoff)
{
register b, off;
register struct inode *ip;
static ibuf[256];
static char buf[512];
off = aoff;
ip = aip;
if ((off&0777)==0) {
if (off==0177000) {
printf2("Monstrous directory %l\n", ino);
return(0);
}
if ((ip->i_mode&ILARG)==0) {
if (off>=010000 || (b = ip->i_addr[off>>9])==0)
return(0);
bread(b, buf, 512);
} else {
if (off==0) {
if (ip->i_addr[0]==0)
return(0);
bread(ip->i_addr[0], ibuf, 512);
}
if ((b = ibuf[(off>>9)&0177])==0)
return(0);
bread(b, buf, 512);
}
}
return(&buf[off&0777]);
}
bread(bno, buf, cnt)
{
seek(fi, bno, 3);
if (read(fi, buf, cnt) != cnt) {
printf2("read error %d\n", bno);
exit();
}
}
bwrite(bno, buf)
{
seek(fi, bno, 3);
if (write(fi, buf, 512) != 512) {
printf2("write error %d\n", bno);
exit();
}
}
number(as)
char *as;
{
register n, c;
register char *s;
s = as;
n = 0;
while ((c = *s) >= '0' && c <= '9') {
n = n*10+ *s++ -'0';
}
if(s == as)
return(-1);
return(n);
}
printf2(s, a1, a2)
{
extern fout;
flush();
fout = 2;
printf(s, a1, a2);
fout = nffil;
flush();
}
init()
{
register i;
for(i=0;i<hsize;i++)
htab[i].hino = 0;
}
getpwentry(name)
char *name;
{
extern fin;
int r, c;
register char *gnp, *rnp;
char *q;
fi = fin;
r = -1;
if((fin = open("/etc/passwd", 0)) < 0)
goto ret;
loop:
gnp = name;
rnp = pbuf;
while((c=getchar()) != '\n') {
if(c == '\0')
goto ret;
*rnp++ = c;
}
*rnp++ = '\0';
rnp = pbuf;
while (*gnp++ == *rnp++);
if(*--rnp != ':')
goto loop;
q = colon(pbuf);
q = colon(q);
colon(q);
r = number(q);
nm = pbuf;
ret:
close(fin);
fin = 0;
(&fin)[1] = 0;
(&fin)[2] = 0;
return(r);
}
colon(p)
char *p;
{
register char *rp;
rp = p;
while (*rp != ':') {
if (*rp++ == '\0') {
write(1, "Bad /etc/passwd\n", 16);
exit(-1);
}
}
*rp++ = '\0';
return(rp);
}
length(s)
char *s;
{
register i;
i = 0;
while(*s++ != '\0')
i++;
return(i);
}
copy(p,q,c)
char *p,*q;
int c;
{
register i;
for(i=0;i<c;i++){
*p++ = *q++;
}
return(c);
}