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