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