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