| 1 | #define NI 16 |
| 2 | #define NB 10 |
| 3 | #define BITS 8 |
| 4 | #define MAXFN 500 |
| 5 | |
| 6 | #ifndef STANDALONE |
| 7 | #include <stdio.h> |
| 8 | #endif |
| 9 | #include <sys/param.h> |
| 10 | #include <sys/inode.h> |
| 11 | #include <sys/ino.h> |
| 12 | #include <sys/fblk.h> |
| 13 | #include <sys/filsys.h> |
| 14 | |
| 15 | struct filsys sblock; |
| 16 | struct dinode itab[INOPB*NI]; |
| 17 | daddr_t iaddr[NADDR]; |
| 18 | daddr_t blist[NB]; |
| 19 | char *bmap; |
| 20 | |
| 21 | int sflg; |
| 22 | int mflg; |
| 23 | int dflg; |
| 24 | int fi; |
| 25 | ino_t ino; |
| 26 | |
| 27 | ino_t nrfile; |
| 28 | ino_t ndfile; |
| 29 | ino_t nbfile; |
| 30 | ino_t ncfile; |
| 31 | |
| 32 | daddr_t ndirect; |
| 33 | daddr_t nindir; |
| 34 | daddr_t niindir; |
| 35 | daddr_t niiindir; |
| 36 | daddr_t nfree; |
| 37 | daddr_t ndup; |
| 38 | |
| 39 | int nerror; |
| 40 | |
| 41 | long atol(); |
| 42 | daddr_t alloc(); |
| 43 | #ifndef STANDALONE |
| 44 | char *malloc(); |
| 45 | #endif |
| 46 | |
| 47 | main(argc, argv) |
| 48 | char *argv[]; |
| 49 | { |
| 50 | register i; |
| 51 | long n; |
| 52 | |
| 53 | blist[0] = -1; |
| 54 | #ifndef STANDALONE |
| 55 | while (--argc) { |
| 56 | argv++; |
| 57 | if (**argv=='-') |
| 58 | switch ((*argv)[1]) { |
| 59 | case 'd': |
| 60 | dflg++; |
| 61 | continue; |
| 62 | |
| 63 | |
| 64 | case 'm': |
| 65 | mflg++; |
| 66 | continue; |
| 67 | |
| 68 | case 's': |
| 69 | sflg++; |
| 70 | continue; |
| 71 | |
| 72 | case 'b': |
| 73 | for(i=0; i<NB; i++) { |
| 74 | n = atol(argv[1]); |
| 75 | if(n == 0) |
| 76 | break; |
| 77 | blist[i] = n; |
| 78 | argv++; |
| 79 | argc--; |
| 80 | } |
| 81 | blist[i] = -1; |
| 82 | continue; |
| 83 | |
| 84 | default: |
| 85 | printf("Bad flag\n"); |
| 86 | } |
| 87 | check(*argv); |
| 88 | } |
| 89 | #else |
| 90 | { |
| 91 | static char fname[0]; |
| 92 | |
| 93 | printf("File: "); |
| 94 | gets(fname); |
| 95 | check(fname); |
| 96 | } |
| 97 | #endif |
| 98 | return(nerror); |
| 99 | } |
| 100 | |
| 101 | check(file) |
| 102 | char *file; |
| 103 | { |
| 104 | register i, j; |
| 105 | ino_t mino; |
| 106 | daddr_t d; |
| 107 | long n; |
| 108 | |
| 109 | fi = open(file, sflg?2:0); |
| 110 | if (fi < 0) { |
| 111 | printf("cannot open %s\n", file); |
| 112 | nerror |= 04; |
| 113 | return; |
| 114 | } |
| 115 | printf("%s:\n", file); |
| 116 | nrfile = 0; |
| 117 | ndfile = 0; |
| 118 | ncfile = 0; |
| 119 | nbfile = 0; |
| 120 | |
| 121 | ndirect = 0; |
| 122 | nindir = 0; |
| 123 | niindir = 0; |
| 124 | niiindir = 0; |
| 125 | |
| 126 | ndup = 0; |
| 127 | #ifndef STANDALONE |
| 128 | sync(); |
| 129 | #endif |
| 130 | bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); |
| 131 | mino = ((int)sblock.s_isize-2) * INOPB; |
| 132 | ino = 0; |
| 133 | n = (sblock.s_fsize - (int)sblock.s_isize + BITS-1) / BITS; |
| 134 | if (n != (unsigned)n) { |
| 135 | printf("Check fsize and isize: %ld, %u\n", |
| 136 | sblock.s_fsize, (int)sblock.s_isize); |
| 137 | } |
| 138 | #ifdef STANDALONE |
| 139 | bmap = NULL; |
| 140 | #else |
| 141 | bmap = malloc((unsigned)n); |
| 142 | #endif |
| 143 | if (bmap==NULL) { |
| 144 | printf("Not enough core; duplicates unchecked\n"); |
| 145 | dflg++; |
| 146 | sflg = 0; |
| 147 | } |
| 148 | if(!dflg) |
| 149 | for(i=0; i<(unsigned)n; i++) |
| 150 | bmap[i] = 0; |
| 151 | for(i=2;; i+=NI) { |
| 152 | if(ino >= mino) |
| 153 | break; |
| 154 | bread((daddr_t)i, (char *)itab, sizeof(itab)); |
| 155 | for(j=0; j<INOPB*NI; j++) { |
| 156 | if(ino >= mino) |
| 157 | break; |
| 158 | ino++; |
| 159 | pass1(&itab[j]); |
| 160 | } |
| 161 | } |
| 162 | ino = 0; |
| 163 | #ifndef STANDALONE |
| 164 | sync(); |
| 165 | #endif |
| 166 | bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); |
| 167 | if (sflg) { |
| 168 | makefree(); |
| 169 | close(fi); |
| 170 | #ifndef STANDALONE |
| 171 | if (bmap) |
| 172 | free(bmap); |
| 173 | #endif |
| 174 | return; |
| 175 | } |
| 176 | nfree = 0; |
| 177 | while(n = alloc()) { |
| 178 | if (chk(n, "free")) |
| 179 | break; |
| 180 | nfree++; |
| 181 | } |
| 182 | close(fi); |
| 183 | #ifndef STANDALONE |
| 184 | if (bmap) |
| 185 | free(bmap); |
| 186 | #endif |
| 187 | |
| 188 | i = nrfile + ndfile + ncfile + nbfile; |
| 189 | #ifndef STANDALONE |
| 190 | printf("files %6u (r=%u,d=%u,b=%u,c=%u)\n", |
| 191 | i, nrfile, ndfile, nbfile, ncfile); |
| 192 | #else |
| 193 | printf("files %u (r=%u,d=%u,b=%u,c=%u)\n", |
| 194 | i, nrfile, ndfile, nbfile, ncfile); |
| 195 | #endif |
| 196 | n = ndirect + nindir + niindir + niindir; |
| 197 | #ifdef STANDALONE |
| 198 | printf("used %ld (i=%ld,ii=%ld,iii=%ld,d=%ld)\n", |
| 199 | n, nindir, niindir, niiindir, ndirect); |
| 200 | printf("free %ld\n", nfree); |
| 201 | #else |
| 202 | printf("used %7ld (i=%ld,ii=%ld,iii=%ld,d=%ld)\n", |
| 203 | n, nindir, niindir, niiindir, ndirect); |
| 204 | printf("free %7ld\n", nfree); |
| 205 | #endif |
| 206 | if(!dflg) { |
| 207 | n = 0; |
| 208 | for(d=(int)sblock.s_isize; d<sblock.s_fsize; d++) |
| 209 | if(!duped(d)) { |
| 210 | if(mflg) |
| 211 | printf("%ld missing\n", d); |
| 212 | n++; |
| 213 | } |
| 214 | printf("missing%5ld\n", n); |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | pass1(ip) |
| 219 | register struct dinode *ip; |
| 220 | { |
| 221 | daddr_t ind1[NINDIR]; |
| 222 | daddr_t ind2[NINDIR]; |
| 223 | daddr_t ind3[NINDIR]; |
| 224 | register i, j; |
| 225 | int k, l; |
| 226 | |
| 227 | i = ip->di_mode & IFMT; |
| 228 | if(i == 0) { |
| 229 | sblock.s_tinode++; |
| 230 | return; |
| 231 | } |
| 232 | if(i == IFCHR) { |
| 233 | ncfile++; |
| 234 | return; |
| 235 | } |
| 236 | if(i == IFBLK) { |
| 237 | nbfile++; |
| 238 | return; |
| 239 | } |
| 240 | if(i == IFDIR) |
| 241 | ndfile++; else |
| 242 | if(i == IFREG) |
| 243 | nrfile++; |
| 244 | else { |
| 245 | printf("bad mode %u\n", ino); |
| 246 | return; |
| 247 | } |
| 248 | l3tol(iaddr, ip->di_addr, NADDR); |
| 249 | for(i=0; i<NADDR; i++) { |
| 250 | if(iaddr[i] == 0) |
| 251 | continue; |
| 252 | if(i < NADDR-3) { |
| 253 | ndirect++; |
| 254 | chk(iaddr[i], "data (small)"); |
| 255 | continue; |
| 256 | } |
| 257 | nindir++; |
| 258 | if (chk(iaddr[i], "1st indirect")) |
| 259 | continue; |
| 260 | bread(iaddr[i], (char *)ind1, BSIZE); |
| 261 | for(j=0; j<NINDIR; j++) { |
| 262 | if(ind1[j] == 0) |
| 263 | continue; |
| 264 | if(i == NADDR-3) { |
| 265 | ndirect++; |
| 266 | chk(ind1[j], "data (large)"); |
| 267 | continue; |
| 268 | } |
| 269 | niindir++; |
| 270 | if(chk(ind1[j], "2nd indirect")) |
| 271 | continue; |
| 272 | bread(ind1[j], (char *)ind2, BSIZE); |
| 273 | for(k=0; k<NINDIR; k++) { |
| 274 | if(ind2[k] == 0) |
| 275 | continue; |
| 276 | if(i == NADDR-2) { |
| 277 | ndirect++; |
| 278 | chk(ind2[k], "data (huge)"); |
| 279 | continue; |
| 280 | } |
| 281 | niiindir++; |
| 282 | if(chk(ind2[k], "3rd indirect")) |
| 283 | continue; |
| 284 | bread(ind2[k], (char *)ind3, BSIZE); |
| 285 | for(l=0; l<NINDIR; l++) |
| 286 | if(ind3[l]) { |
| 287 | ndirect++; |
| 288 | chk(ind3[l], "data (garg)"); |
| 289 | } |
| 290 | } |
| 291 | } |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | chk(bno, s) |
| 296 | daddr_t bno; |
| 297 | char *s; |
| 298 | { |
| 299 | register n; |
| 300 | |
| 301 | if (bno<(int)sblock.s_isize || bno>=sblock.s_fsize) { |
| 302 | printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); |
| 303 | return(1); |
| 304 | } |
| 305 | if(duped(bno)) { |
| 306 | printf("%ld dup; inode=%u, class=%s\n", bno, ino, s); |
| 307 | ndup++; |
| 308 | } |
| 309 | for (n=0; blist[n] != -1; n++) |
| 310 | if (bno == blist[n]) |
| 311 | printf("%ld arg; inode=%u, class=%s\n", bno, ino, s); |
| 312 | return(0); |
| 313 | } |
| 314 | |
| 315 | duped(bno) |
| 316 | daddr_t bno; |
| 317 | { |
| 318 | daddr_t d; |
| 319 | register m, n; |
| 320 | |
| 321 | if(dflg) |
| 322 | return(0); |
| 323 | d = bno - (int)sblock.s_isize; |
| 324 | m = 1 << (d%BITS); |
| 325 | n = (d/BITS); |
| 326 | if(bmap[n] & m) |
| 327 | return(1); |
| 328 | bmap[n] |= m; |
| 329 | return(0); |
| 330 | } |
| 331 | |
| 332 | daddr_t |
| 333 | alloc() |
| 334 | { |
| 335 | int i; |
| 336 | daddr_t bno; |
| 337 | union { |
| 338 | char data[BSIZE]; |
| 339 | struct fblk fb; |
| 340 | } buf; |
| 341 | |
| 342 | sblock.s_tfree--; |
| 343 | if (sblock.s_nfree<=0) |
| 344 | return(0); |
| 345 | if (sblock.s_nfree>NICFREE) { |
| 346 | printf("Bad free list, s.b. count = %d\n", sblock.s_nfree); |
| 347 | return(0); |
| 348 | } |
| 349 | bno = sblock.s_free[--sblock.s_nfree]; |
| 350 | sblock.s_free[sblock.s_nfree] = (daddr_t)0; |
| 351 | if(bno == 0) |
| 352 | return(bno); |
| 353 | if(sblock.s_nfree <= 0) { |
| 354 | bread(bno, buf.data, BSIZE); |
| 355 | sblock.s_nfree = buf.df_nfree; |
| 356 | if (sblock.s_nfree<0 || sblock.s_nfree>NICFREE) { |
| 357 | printf("Bad free list, entry count of block %ld = %d\n", |
| 358 | bno, sblock.s_nfree); |
| 359 | sblock.s_nfree = 0; |
| 360 | return(0); |
| 361 | } |
| 362 | for(i=0; i<NICFREE; i++) |
| 363 | sblock.s_free[i] = buf.df_free[i]; |
| 364 | } |
| 365 | return(bno); |
| 366 | } |
| 367 | |
| 368 | bfree(bno) |
| 369 | daddr_t bno; |
| 370 | { |
| 371 | union { |
| 372 | char data[BSIZE]; |
| 373 | struct fblk fb; |
| 374 | } buf; |
| 375 | int i; |
| 376 | |
| 377 | sblock.s_tfree++; |
| 378 | if(sblock.s_nfree >= NICFREE) { |
| 379 | for(i=0; i<BSIZE; i++) |
| 380 | buf.data[i] = 0; |
| 381 | buf.df_nfree = sblock.s_nfree; |
| 382 | for(i=0; i<NICFREE; i++) |
| 383 | buf.df_free[i] = sblock.s_free[i]; |
| 384 | bwrite(bno, buf.data); |
| 385 | sblock.s_nfree = 0; |
| 386 | } |
| 387 | sblock.s_free[sblock.s_nfree] = bno; |
| 388 | sblock.s_nfree++; |
| 389 | } |
| 390 | |
| 391 | bread(bno, buf, cnt) |
| 392 | daddr_t bno; |
| 393 | char *buf; |
| 394 | { |
| 395 | register i; |
| 396 | |
| 397 | lseek(fi, bno*BSIZE, 0); |
| 398 | if (read(fi, buf, cnt) != cnt) { |
| 399 | printf("read error %ld\n", bno); |
| 400 | if (sflg) { |
| 401 | printf("No update\n"); |
| 402 | sflg = 0; |
| 403 | } |
| 404 | for(i=0; i<BSIZE; i++) |
| 405 | buf[i] = 0; |
| 406 | } |
| 407 | } |
| 408 | |
| 409 | bwrite(bno, buf) |
| 410 | daddr_t bno; |
| 411 | char *buf; |
| 412 | { |
| 413 | |
| 414 | lseek(fi, bno*BSIZE, 0); |
| 415 | if (write(fi, buf, BSIZE) != BSIZE) |
| 416 | printf("write error %ld\n", bno); |
| 417 | } |
| 418 | |
| 419 | makefree() |
| 420 | { |
| 421 | char flg[MAXFN]; |
| 422 | int adr[MAXFN]; |
| 423 | register i, j; |
| 424 | daddr_t f, d; |
| 425 | int m, n; |
| 426 | |
| 427 | n = sblock.s_n; |
| 428 | if(n <= 0 || n > MAXFN) |
| 429 | n = MAXFN; |
| 430 | sblock.s_n = n; |
| 431 | m = sblock.s_m; |
| 432 | if(m <= 0 || m > sblock.s_n) |
| 433 | m = 3; |
| 434 | sblock.s_m = m; |
| 435 | |
| 436 | for(i=0; i<n; i++) |
| 437 | flg[i] = 0; |
| 438 | i = 0; |
| 439 | for(j=0; j<n; j++) { |
| 440 | while(flg[i]) |
| 441 | i = (i+1)%n; |
| 442 | adr[j] = i+1; |
| 443 | flg[i]++; |
| 444 | i = (i+m)%n; |
| 445 | } |
| 446 | |
| 447 | sblock.s_nfree = 0; |
| 448 | sblock.s_ninode = 0; |
| 449 | sblock.s_flock = 0; |
| 450 | sblock.s_ilock = 0; |
| 451 | sblock.s_fmod = 0; |
| 452 | sblock.s_ronly = 0; |
| 453 | #ifndef STANDALONE |
| 454 | time(&sblock.s_time); |
| 455 | #endif |
| 456 | sblock.s_tfree = 0; |
| 457 | sblock.s_tinode = 0; |
| 458 | |
| 459 | bfree((daddr_t)0); |
| 460 | d = sblock.s_fsize-1; |
| 461 | while(d%sblock.s_n) |
| 462 | d++; |
| 463 | for(; d > 0; d -= sblock.s_n) |
| 464 | for(i=0; i<sblock.s_n; i++) { |
| 465 | f = d - adr[i]; |
| 466 | if(f < sblock.s_fsize && f >= (int)sblock.s_isize) |
| 467 | if(!duped(f)) |
| 468 | bfree(f); |
| 469 | } |
| 470 | bwrite((daddr_t)1, (char *)&sblock); |
| 471 | #ifndef STANDALONE |
| 472 | sync(); |
| 473 | #endif |
| 474 | return; |
| 475 | } |