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