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