1 static char *sccsid = "@(#)dcheck.c 1.8 (Berkeley) 02/25/82"; 2 /* 3 * dcheck - check directory consistency 4 */ 5 #define NB 10 6 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 7 8 #include "../h/param.h" 9 #include "../h/inode.h" 10 #include "../h/fs.h" 11 #include <ndir.h> 12 #include <stdio.h> 13 14 union { 15 struct fs fs; 16 char pad[MAXBSIZE]; 17 } fsun; 18 #define sblock fsun.fs 19 20 struct dirstuff { 21 int loc; 22 struct dinode *ip; 23 char dbuf[MAXBSIZE]; 24 }; 25 26 struct dinode itab[MAXIPG]; 27 struct dinode *gip; 28 ino_t ilist[NB]; 29 30 int fi; 31 ino_t ino; 32 ino_t *ecount; 33 int headpr; 34 int nfiles; 35 36 int nerror; 37 daddr_t bmap(); 38 long atol(); 39 char *malloc(); 40 41 main(argc, argv) 42 char *argv[]; 43 { 44 register i; 45 long n; 46 47 while (--argc) { 48 argv++; 49 if (**argv=='-') 50 switch ((*argv)[1]) { 51 52 case 'i': 53 for(i=0; i<NB; i++) { 54 n = atol(argv[1]); 55 if(n == 0) 56 break; 57 ilist[i] = n; 58 argv++; 59 argc--; 60 } 61 ilist[i] = 0; 62 continue; 63 64 default: 65 printf("Bad flag %c\n", (*argv)[1]); 66 nerror++; 67 } 68 check(*argv); 69 } 70 return(nerror); 71 } 72 73 check(file) 74 char *file; 75 { 76 register i, j, c; 77 78 fi = open(file, 0); 79 if(fi < 0) { 80 printf("cannot open %s\n", file); 81 nerror++; 82 return; 83 } 84 headpr = 0; 85 printf("%s:\n", file); 86 sync(); 87 bread(SBLOCK, (char *)&sblock, SBSIZE); 88 if (sblock.fs_magic != FS_MAGIC) { 89 printf("%s: not a file system\n", file); 90 nerror++; 91 return; 92 } 93 nfiles = sblock.fs_ipg * sblock.fs_ncg; 94 if (nfiles > 65535) { 95 printf("%s: preposterous number of files\n", file); 96 nerror++; 97 return; 98 } 99 ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount)); 100 if (ecount == 0) { 101 printf("%s: not enough core for %d files\n", file, nfiles); 102 exit(04); 103 } 104 for (i = 0; i<=nfiles; i++) 105 ecount[i] = 0; 106 ino = 0; 107 for (c = 0; c < sblock.fs_ncg; c++) { 108 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 109 sblock.fs_ipg * sizeof (struct dinode)); 110 for (j = 0; j < sblock.fs_ipg; j++) { 111 pass1(&itab[j]); 112 ino++; 113 } 114 } 115 ino = 0; 116 for (c = 0; c < sblock.fs_ncg; c++) { 117 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 118 sblock.fs_ipg * sizeof (struct dinode)); 119 for (j = 0; j < sblock.fs_ipg; j++) { 120 pass2(&itab[j]); 121 ino++; 122 } 123 } 124 free(ecount); 125 } 126 127 pass1(ip) 128 register struct dinode *ip; 129 { 130 register struct direct *dp; 131 struct dirstuff dirp; 132 int k; 133 134 if((ip->di_mode&IFMT) != IFDIR) 135 return; 136 dirp.loc = 0; 137 dirp.ip = ip; 138 gip = ip; 139 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 140 if(dp->d_ino == 0) 141 continue; 142 if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) { 143 printf("%d bad; %d/%s\n", 144 dp->d_ino, ino, dp->d_name); 145 nerror++; 146 continue; 147 } 148 for (k = 0; ilist[k] != 0; k++) 149 if (ilist[k] == dp->d_ino) { 150 printf("%d arg; %d/%s\n", 151 dp->d_ino, ino, dp->d_name); 152 nerror++; 153 } 154 ecount[dp->d_ino]++; 155 } 156 } 157 158 pass2(ip) 159 register struct dinode *ip; 160 { 161 register i; 162 163 i = ino; 164 if ((ip->di_mode&IFMT)==0 && ecount[i]==0) 165 return; 166 if (ip->di_nlink==ecount[i] && ip->di_nlink!=0) 167 return; 168 if (headpr==0) { 169 printf(" entries link cnt\n"); 170 headpr++; 171 } 172 printf("%u\t%d\t%d\n", ino, 173 ecount[i], ip->di_nlink); 174 } 175 176 /* 177 * get next entry in a directory. 178 */ 179 struct direct * 180 readdir(dirp) 181 register struct dirstuff *dirp; 182 { 183 register struct direct *dp; 184 daddr_t lbn, d; 185 186 for(;;) { 187 if (dirp->loc >= dirp->ip->di_size) 188 return NULL; 189 if ((lbn = lblkno(&sblock, dirp->loc)) == 0) { 190 d = bmap(lbn); 191 if(d == 0) 192 return NULL; 193 bread(fsbtodb(&sblock, d), dirp->dbuf, 194 dblksize(&sblock, dirp->ip, lbn)); 195 } 196 dp = (struct direct *) 197 (dirp->dbuf + blkoff(&sblock, dirp->loc)); 198 dirp->loc += dp->d_reclen; 199 if (dp->d_ino == 0) 200 continue; 201 return (dp); 202 } 203 } 204 205 bread(bno, buf, cnt) 206 daddr_t bno; 207 char *buf; 208 { 209 register i; 210 211 lseek(fi, bno * DEV_BSIZE, 0); 212 if (read(fi, buf, cnt) != cnt) { 213 printf("read error %d\n", bno); 214 for(i=0; i < cnt; i++) 215 buf[i] = 0; 216 } 217 } 218 219 daddr_t 220 bmap(i) 221 { 222 daddr_t ibuf[MAXNINDIR]; 223 224 if(i < NDADDR) 225 return(gip->di_db[i]); 226 i -= NDADDR; 227 if(i > NINDIR(&sblock)) { 228 printf("%u - huge directory\n", ino); 229 return((daddr_t)0); 230 } 231 bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf)); 232 return(ibuf[i]); 233 } 234