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