1 static char *sccsid = "@(#)ncheck.c 1.8 (Berkeley) 02/25/82"; 2 /* 3 * ncheck -- obtain file names from reading filesystem 4 */ 5 6 #define NB 500 7 #define HSIZE 2503 8 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 9 10 #include "../h/param.h" 11 #include "../h/inode.h" 12 #include "../h/fs.h" 13 #include <stdio.h> 14 #include <ndir.h> 15 16 struct fs sblock; 17 struct dinode itab[MAXIPG]; 18 struct dinode *gip; 19 ino_t ilist[NB]; 20 struct htab 21 { 22 ino_t h_ino; 23 ino_t h_pino; 24 char *h_name; 25 } htab[HSIZE]; 26 char strngtab[30 * HSIZE]; 27 int strngloc; 28 29 struct dirstuff { 30 int loc; 31 struct dinode *ip; 32 char dbuf[MAXBSIZE]; 33 }; 34 35 int aflg; 36 int sflg; 37 int fi; 38 ino_t ino; 39 int nhent; 40 int nxfile; 41 42 int nerror; 43 daddr_t bmap(); 44 long atol(); 45 struct htab *lookup(); 46 47 main(argc, argv) 48 int argc; 49 char *argv[]; 50 { 51 register i; 52 long n; 53 54 while (--argc) { 55 argv++; 56 if (**argv=='-') 57 switch ((*argv)[1]) { 58 59 case 'a': 60 aflg++; 61 continue; 62 63 case 'i': 64 for(i=0; i<NB; i++) { 65 n = atol(argv[1]); 66 if(n == 0) 67 break; 68 ilist[i] = n; 69 nxfile = i; 70 argv++; 71 argc--; 72 } 73 continue; 74 75 case 's': 76 sflg++; 77 continue; 78 79 default: 80 fprintf(stderr, "ncheck: 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 int i, j, c; 92 int nfiles; 93 94 fi = open(file, 0); 95 if(fi < 0) { 96 fprintf(stderr, "ncheck: cannot open %s\n", file); 97 nerror++; 98 return; 99 } 100 nhent = 0; 101 printf("%s:\n", file); 102 sync(); 103 bread(SBLOCK, (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 nfiles = sblock.fs_ipg * sblock.fs_ncg; 110 if (nfiles > 65535) { 111 printf("%s: %d is a preposterous number of files\n", 112 file, nfiles); 113 nerror++; 114 return; 115 } 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 ilist[nxfile+1] = 0; 126 ino = 0; 127 for (c = 0; c < sblock.fs_ncg; c++) { 128 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 129 sblock.fs_ipg * sizeof (struct dinode)); 130 for(j=0; j<sblock.fs_ipg; j++) { 131 pass2(&itab[j]); 132 ino++; 133 } 134 } 135 ino = 0; 136 for (c = 0; c < sblock.fs_ncg; c++) { 137 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 138 sblock.fs_ipg * sizeof (struct dinode)); 139 for(j=0; j<sblock.fs_ipg; j++) { 140 pass3(&itab[j]); 141 ino++; 142 } 143 } 144 } 145 146 pass1(ip) 147 register struct dinode *ip; 148 { 149 if((ip->di_mode & IFMT) != IFDIR) { 150 if (sflg==0 || nxfile>=NB) 151 return; 152 if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR 153 || ip->di_mode&(ISUID|ISGID)) 154 ilist[nxfile++] = ino; 155 return; 156 } 157 lookup(ino, 1); 158 } 159 160 pass2(ip) 161 register struct dinode *ip; 162 { 163 register struct direct *dp; 164 struct dirstuff dirp; 165 struct htab *hp; 166 167 if((ip->di_mode&IFMT) != IFDIR) 168 return; 169 dirp.loc = 0; 170 dirp.ip = ip; 171 gip = ip; 172 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 173 if(dp->d_ino == 0) 174 continue; 175 hp = lookup(dp->d_ino, 0); 176 if(hp == 0) 177 continue; 178 if(dotname(dp)) 179 continue; 180 hp->h_pino = ino; 181 hp->h_name = &strngtab[strngloc]; 182 strngloc += strlen(dp->d_name) + 1; 183 strcpy(hp->h_name, dp->d_name); 184 } 185 } 186 187 pass3(ip) 188 register struct dinode *ip; 189 { 190 register struct direct *dp; 191 struct dirstuff dirp; 192 int k; 193 194 if((ip->di_mode&IFMT) != IFDIR) 195 return; 196 dirp.loc = 0; 197 dirp.ip = ip; 198 gip = ip; 199 for(dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 200 if(dp->d_ino == 0) 201 continue; 202 if(aflg==0 && dotname(dp)) 203 continue; 204 if(ilist[0] == 0) 205 goto pr; 206 for(k = 0; ilist[k] != 0; k++) 207 if(ilist[k] == dp->d_ino) 208 goto pr; 209 continue; 210 pr: 211 printf("%u ", dp->d_ino); 212 pname(ino, 0); 213 printf("/%s", dp->d_name); 214 if (lookup(dp->d_ino, 0)) 215 printf("/."); 216 printf("\n"); 217 } 218 } 219 220 /* 221 * get next entry in a directory. 222 */ 223 struct direct * 224 readdir(dirp) 225 register struct dirstuff *dirp; 226 { 227 register struct direct *dp; 228 daddr_t lbn, d; 229 230 for(;;) { 231 if (dirp->loc >= dirp->ip->di_size) 232 return NULL; 233 if ((lbn = lblkno(&sblock, dirp->loc)) == 0) { 234 d = bmap(lbn); 235 if(d == 0) 236 return NULL; 237 bread(fsbtodb(&sblock, d), dirp->dbuf, 238 dblksize(&sblock, dirp->ip, lbn)); 239 } 240 dp = (struct direct *) 241 (dirp->dbuf + blkoff(&sblock, dirp->loc)); 242 dirp->loc += dp->d_reclen; 243 if (dp->d_ino == 0) 244 continue; 245 return (dp); 246 } 247 } 248 249 dotname(dp) 250 register struct direct *dp; 251 { 252 253 if (dp->d_name[0]=='.') 254 if (dp->d_name[1]==0 || 255 (dp->d_name[1]=='.' && dp->d_name[2]==0)) 256 return(1); 257 return(0); 258 } 259 260 pname(i, lev) 261 ino_t i; 262 int lev; 263 { 264 register struct htab *hp; 265 266 if (i==ROOTINO) 267 return; 268 if ((hp = lookup(i, 0)) == 0) { 269 printf("???"); 270 return; 271 } 272 if (lev > 10) { 273 printf("..."); 274 return; 275 } 276 pname(hp->h_pino, ++lev); 277 printf("/%s", hp->h_name); 278 } 279 280 struct htab * 281 lookup(i, ef) 282 ino_t i; 283 int ef; 284 { 285 register struct htab *hp; 286 287 for (hp = &htab[i%HSIZE]; hp->h_ino;) { 288 if (hp->h_ino==i) 289 return(hp); 290 if (++hp >= &htab[HSIZE]) 291 hp = htab; 292 } 293 if (ef==0) 294 return(0); 295 if (++nhent >= HSIZE) { 296 fprintf(stderr, "ncheck: out of core-- increase HSIZE\n"); 297 exit(1); 298 } 299 hp->h_ino = i; 300 return(hp); 301 } 302 303 bread(bno, buf, cnt) 304 daddr_t bno; 305 char *buf; 306 int cnt; 307 { 308 register i; 309 310 lseek(fi, bno * DEV_BSIZE, 0); 311 if (read(fi, buf, cnt) != cnt) { 312 fprintf(stderr, "ncheck: read error %d\n", bno); 313 for(i=0; i < cnt; i++) 314 buf[i] = 0; 315 } 316 } 317 318 daddr_t 319 bmap(i) 320 int i; 321 { 322 daddr_t ibuf[MAXNINDIR]; 323 324 if(i < NDADDR) 325 return(gip->di_db[i]); 326 i -= NDADDR; 327 if(i > NINDIR(&sblock)) { 328 fprintf(stderr, "ncheck: %u - huge directory\n", ino); 329 return((daddr_t)0); 330 } 331 bread(fsbtodb(&sblock, gip->di_ib[i]), (char *)ibuf, sizeof(ibuf)); 332 return(ibuf[i]); 333 } 334