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