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