|
|
1.1 ! root 1: #define BITFS(x) (1) ! 2: #ifdef notdef ! 3: #define SMALL 0 /* 1k file systems */ ! 4: #endif ! 5: /* #include <ansi.h> */ ! 6: /* #include <posix.h> */ ! 7: #include <pwd.h> ! 8: #include <stdio.h> ! 9: #include <ctype.h> ! 10: #include <sys/param.h> ! 11: #ifdef SMALL ! 12: #include <sys/fblk.h> ! 13: #endif ! 14: #include <sys/filsys.h> ! 15: #include <sys/dir.h> ! 16: /* #include <sys/dinode.h> */ ! 17: #include <sys/fblk.h> ! 18: #include <sys/ino.h> ! 19: #include <sys/inode.h> ! 20: /* #include <sys/stat.h> */ ! 21: #include <stat.h> ! 22: #include <fstab.h> ! 23: ! 24: #define BIG 64 /* 4k file systems */ ! 25: #define BCOUNT BSIZE(BIG) ! 26: #define BITSPERBLK (BCOUNT*NBBY) ! 27: #define NDIRECT(x) (BSIZE(x)/sizeof(struct direct)) ! 28: #define SPERB(x) (BSIZE(x)/sizeof(short)) ! 29: ! 30: #define NO 0 ! 31: #define YES 1 ! 32: ! 33: #define MAXDUP 10 /* limit on dup blks (per inode) */ ! 34: #define MAXBAD 10 /* limit on bad blks (per inode) */ ! 35: ! 36: #define STEPSIZE 9 /* default step for freelist spacing */ ! 37: #define CYLSIZE 400 /* default cyl size for spacing */ ! 38: #define MAXCYL 1000 /* maximum cylinder size */ ! 39: ! 40: #define BITSPB 8 /* number bits per byte */ ! 41: #define BITSHIFT 3 /* log2(BITSPB) */ ! 42: #define BITMASK 07 /* BITSPB-1 */ ! 43: #define LSTATE 2 /* bits per inode state */ ! 44: #define STATEPB (BITSPB/LSTATE) /* inode states per byte */ ! 45: #define USTATE 0 /* inode not allocated */ ! 46: #define FSTATE 01 /* inode is file */ ! 47: #define DSTATE 02 /* inode is directory */ ! 48: #define CLEAR 03 /* inode is to be cleared */ ! 49: #define SMASK 03 /* mask for inode state */ ! 50: ! 51: typedef struct dinode DINODE; ! 52: typedef struct direct DIRECT; ! 53: ! 54: #define ALLOC ((dp->di_mode & IFMT) != 0) ! 55: #define DIR ((dp->di_mode & IFMT) == IFDIR) ! 56: #define REG ((dp->di_mode & IFMT) == IFREG) ! 57: #define BLK ((dp->di_mode & IFMT) == IFBLK) ! 58: #define CHR ((dp->di_mode & IFMT) == IFCHR) ! 59: #define MPC ((dp->di_mode & IFMT) == IFMPC) ! 60: #define MPB ((dp->di_mode & IFMT) == IFMPB) ! 61: #define LNK ((dp->di_mode & IFMT) == IFLNK) ! 62: #define SPECIAL (BLK || CHR /* || MPC || MPB */ ) ! 63: ! 64: #define NINOBLK 11 /* num blks for raw reading */ ! 65: #define MAXRAW 110 /* largest raw read (in blks) */ ! 66: daddr_t startib; /* blk num of first in raw area */ ! 67: unsigned niblk; /* num of blks in raw area */ ! 68: ! 69: struct bufarea { ! 70: struct bufarea *b_next; /* must be first */ ! 71: daddr_t b_bno; ! 72: union { ! 73: char b_buf[BSIZE(BIG)]; /* buffer space */ ! 74: short b_lnks[SPERB(BIG)]; /* link counts */ ! 75: daddr_t b_indir[NINDIR(BIG)]; /* indirect block */ ! 76: struct filsys b_fs; /* super block */ ! 77: #ifdef SMALL ! 78: struct fblk b_fb; /* free block */ ! 79: #endif ! 80: struct dinode b_dinode[INOPB(BIG)]; /* inode block */ ! 81: DIRECT b_dir[NDIRECT(BIG)]; /* directory */ ! 82: } b_un; ! 83: char b_dirty; ! 84: }; ! 85: ! 86: typedef struct bufarea BUFAREA; ! 87: ! 88: BUFAREA inoblk; /* inode blocks */ ! 89: BUFAREA fileblk; /* other blks in filesys */ ! 90: BUFAREA sblk; /* file system superblock */ ! 91: BUFAREA *poolhead; /* ptr to first buffer in pool */ ! 92: ! 93: #define initbarea(x) (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1 ! 94: #define dirty(x) (x)->b_dirty = 1 ! 95: #define inodirty() inoblk.b_dirty = 1 ! 96: #define fbdirty() fileblk.b_dirty = 1 ! 97: #define sbdirty() sblk.b_dirty = 1 ! 98: ! 99: #define freeblk fileblk.b_un.b_fb ! 100: #define dirblk fileblk.b_un ! 101: #define superblk sblk.b_un.b_fs ! 102: ! 103: struct filecntl { ! 104: int rfdes; ! 105: int wfdes; ! 106: int mod; ! 107: }; ! 108: ! 109: struct filecntl dfile; /* file descriptors for filesys */ ! 110: struct filecntl sfile; /* file descriptors for scratch file */ ! 111: ! 112: typedef unsigned MEMSIZE; ! 113: ! 114: MEMSIZE memsize; /* amt of memory we got */ ! 115: MEMSIZE minsize; ! 116: #ifdef pdp11 ! 117: #define MAXDATA ((MEMSIZE)54*1024) ! 118: #endif ! 119: #ifdef vax ! 120: #define MAXDATA ((MEMSIZE)400*1024) ! 121: #endif ! 122: #ifdef interdata ! 123: #define MAXDATA ((MEMSIZE)400*1024) ! 124: #endif ! 125: #ifdef mips ! 126: #define MAXDATA (0x10000000+(MEMSIZE)400*1024) /* hack */ ! 127: #endif ! 128: #ifndef MAXDATA ! 129: #define MAXDATA ((MEMSIZE)200*1024) ! 130: #endif ! 131: ! 132: #define DUPTBLSIZE 100 /* num of dup blocks to remember */ ! 133: daddr_t duplist[DUPTBLSIZE]; /* dup block table */ ! 134: daddr_t *enddup; /* next entry in dup table */ ! 135: daddr_t *muldup; /* multiple dups part of table */ ! 136: ! 137: #define MAXLNCNT 500 /* num zero link cnts to remember */ ! 138: ino_t badlncnt[MAXLNCNT]; /* table of inos with zero link cnts */ ! 139: ino_t *badlnp; /* next entry in table */ ! 140: ! 141: char sflag; /* salvage free block list */ ! 142: char csflag; /* salvage free block list (conditional) */ ! 143: char nflag; /* assume a no response */ ! 144: char yflag; /* assume a yes response */ ! 145: char tflag; /* scratch file specified */ ! 146: char preen; /* just fix normal inconsistencies */ ! 147: char rplyflag; /* any questions asked? */ ! 148: char hotroot; /* checking root device */ ! 149: char rawflg; /* read raw device */ ! 150: char rmscr; /* remove scratch file when done */ ! 151: char fixfree; /* corrupted free list */ ! 152: char *membase; /* base of memory we get */ ! 153: long *bm_buf; /* ptr to bit map buffer area */ ! 154: char *blkmap; /* ptr to primary blk allocation map */ ! 155: char *freemap; /* ptr to secondary blk allocation map */ ! 156: char *statemap; /* ptr to inode state table */ ! 157: char *pathp; /* pointer to pathname position */ ! 158: char *thisname; /* ptr to current pathname component */ ! 159: char *srchname; /* name being searched for in dir */ ! 160: char pathname[200]; ! 161: char scrfile[80]; ! 162: char *lfname = "lost+found"; ! 163: char *checklist = FSTAB; ! 164: char big; /* it is a 4k file system */ ! 165: ! 166: short *lncntp; /* ptr to link count table */ ! 167: ! 168: int cylsize; /* num blocks per cylinder */ ! 169: int stepsize; /* num blocks for spacing purposes */ ! 170: int badblk; /* num of bad blks seen (per inode) */ ! 171: int dupblk; /* num of dup blks seen (per inode) */ ! 172: int (*pfunc)(); /* function to call to chk blk */ ! 173: int zcleared; /* num of empty, linkless files cleared */ ! 174: ! 175: ino_t inum; /* inode we are currently working on */ ! 176: ino_t imax; /* number of inodes */ ! 177: ino_t parentdir; /* i number of parent directory */ ! 178: ino_t lastino; /* hiwater mark of inodes */ ! 179: ino_t lfdir; /* lost & found directory */ ! 180: ino_t orphan; /* orphaned inode */ ! 181: ! 182: off_t filsize; /* num blks seen in file */ ! 183: off_t maxblk; /* largest logical blk in file */ ! 184: off_t bmapsz; /* num chars in blkmap */ ! 185: ! 186: daddr_t smapblk; /* starting blk of state map */ ! 187: daddr_t lncntblk; /* starting blk of link cnt table */ ! 188: daddr_t fmapblk; /* starting blk of free map */ ! 189: daddr_t n_free; /* number of free blocks */ ! 190: daddr_t n_blks; /* number of blocks used */ ! 191: daddr_t n_files; /* number of files seen */ ! 192: daddr_t fmin; /* block number of the first data block */ ! 193: daddr_t fmax; /* number of blocks in the volume */ ! 194: daddr_t m_blks; /* number of bitmap blocks in the file system */ ! 195: ! 196: #undef howmany ! 197: #undef roundup ! 198: #define howmany(x,y) (((x)+((y)-1))/(y)) ! 199: #define roundup(x,y) ((((x)+((y)-1))/(y))*(y)) ! 200: #define outrange(x) (x < fmin || x >= fmax) ! 201: #define zapino(x) clear((char *)(x),sizeof(DINODE)) ! 202: ! 203: #define setlncnt(x) dolncnt(x,0) ! 204: #define getlncnt() dolncnt(0,1) ! 205: #define declncnt() dolncnt(0,2) ! 206: ! 207: #define setbmap(x) domap(x,0) ! 208: #define getbmap(x) domap(x,1) ! 209: #define clrbmap(x) domap(x,2) ! 210: ! 211: #define setfmap(x) domap(x,0+4) ! 212: #define getfmap(x) domap(x,1+4) ! 213: #define clrfmap(x) domap(x,2+4) ! 214: ! 215: #define setstate(x) dostate(x,0) ! 216: #define getstate() dostate(0,1) ! 217: ! 218: #define DATA 1 ! 219: #define ADDR 0 ! 220: #define ALTERD 010 ! 221: #define KEEPON 04 ! 222: #define SKIP 02 ! 223: #define STOP 01 ! 224: ! 225: DINODE *ginode(); ! 226: BUFAREA *getblk(); ! 227: BUFAREA *search(); ! 228: int dirscan(); ! 229: int findino(); ! 230: void catch(int); ! 231: int mkentry(); ! 232: int chgdd(); ! 233: int pass1(); ! 234: int pass1b(); ! 235: int pass2(); ! 236: int pass3(); ! 237: int pass4(); ! 238: int pass5(); ! 239: void ltol3(char *, long *, int); ! 240: void l3tol(long *, char *, int); ! 241: ! 242: char *devname; ! 243: ! 244: main(argc,argv) ! 245: int argc; ! 246: char *argv[]; ! 247: { ! 248: register FILE *fp; ! 249: register n; ! 250: register char *p; ! 251: char filename[50]; ! 252: char *sbrk(); ! 253: ! 254: setbuf(stdout, NULL); ! 255: sync(); ! 256: while(--argc > 0 && **++argv == '-') { ! 257: switch(*++*argv) { ! 258: case 'p': ! 259: preen++; ! 260: break; ! 261: case 't': ! 262: case 'T': ! 263: tflag++; ! 264: if(**++argv == '-' || --argc <= 0) ! 265: errexit("Bad -t option\n"); ! 266: p = scrfile; ! 267: while(*p++ = **argv) ! 268: (*argv)++; ! 269: break; ! 270: case 's': /* salvage flag */ ! 271: stype(++*argv); ! 272: sflag++; ! 273: break; ! 274: case 'S': /* conditional salvage */ ! 275: stype(++*argv); ! 276: csflag++; ! 277: break; ! 278: case 'n': /* default no answer flag */ ! 279: case 'N': ! 280: nflag++; ! 281: yflag = 0; ! 282: break; ! 283: case 'y': /* default yes answer flag */ ! 284: case 'Y': ! 285: yflag++; ! 286: nflag = 0; ! 287: break; ! 288: default: ! 289: errexit("%c option?\n",**argv); ! 290: } ! 291: } ! 292: if(nflag && (sflag || csflag)) ! 293: errexit("Incompatible options: -n and -%s\n",sflag?"s":"S"); ! 294: if(sflag && csflag) ! 295: sflag = 0; ! 296: memsize = (MEMSIZE)sbrk(0); ! 297: memsize = MAXDATA - memsize - sizeof(int); ! 298: minsize = 2*sizeof(BUFAREA)+BSIZE(BIG); ! 299: while(memsize >= minsize && ! 300: (membase = sbrk(memsize)) == (char *)-1) ! 301: memsize -= 1024; ! 302: if(memsize < minsize) ! 303: errexit("Can't get memory\n"); ! 304: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 305: signal(SIGINT, catch); ! 306: if(argc) { /* arg list has file names */ ! 307: while(argc-- > 0){ ! 308: hotroot = 0; ! 309: check(*argv++); ! 310: } ! 311: } ! 312: else { /* use default checklist */ ! 313: struct fstab *fsp; ! 314: int pid, passno, anygtr, sumstatus = 0; ! 315: passno = 1; ! 316: do { ! 317: anygtr = 0; ! 318: if (setfsent() == 0) ! 319: errexit("Can't open checklist file: %s\n", ! 320: FSTAB); ! 321: while ( (fsp = getfsent()) != 0){ ! 322: if (fsp->fs_ftype != 0) /* regular fs */ ! 323: continue; ! 324: if (preen == 0 || ! 325: passno == 1 && fsp->fs_passno == passno) { ! 326: if (blockcheck(fsp->fs_spec) == NO && ! 327: preen) ! 328: exit(8); ! 329: } else if (fsp->fs_passno > passno) ! 330: anygtr = 1; ! 331: else if (fsp->fs_passno == passno) { ! 332: pid = fork(); ! 333: if (pid < 0) { ! 334: perror("fork"); ! 335: exit(8); ! 336: } ! 337: if (pid == 0) ! 338: if (blockcheck(fsp->fs_spec)==NO) ! 339: exit(8); ! 340: else ! 341: exit(0); ! 342: } ! 343: } ! 344: if (preen) { ! 345: int status; ! 346: while (wait(&status) != -1) ! 347: sumstatus |= status; ! 348: } ! 349: passno++; ! 350: } while (anygtr); ! 351: if (sumstatus) ! 352: exit(8); ! 353: endfsent(); ! 354: } ! 355: exit(0); ! 356: } ! 357: ! 358: /* char *rawname(), *unrawname(); */ ! 359: char *rawname(), *strrchr(), *unrawname(); ! 360: ! 361: blockcheck(name) ! 362: char *name; ! 363: { ! 364: struct stat stat_slash, stat_block, stat_char; ! 365: char *raw; ! 366: int looped = 0; ! 367: ! 368: hotroot = 0; ! 369: if (stat("/", &stat_slash) < 0){ ! 370: error("Can't stat root\n"); ! 371: return(NO); ! 372: } ! 373: retry: ! 374: if (stat(name, &stat_block) < 0){ ! 375: error("Can't stat %s\n", name); ! 376: return(NO); ! 377: } ! 378: big = BIG; /* 1k blocks by default */ ! 379: if (S_ISBLK(stat_block.st_mode)){ ! 380: if(BITFS(stat_block.st_rdev)) ! 381: big = BIG; /* a 4k file system */ ! 382: raw = rawname(name); ! 383: if (stat(raw, &stat_char) < 0){ ! 384: error("Can't stat %s\n", raw); ! 385: return(NO); ! 386: } ! 387: if (S_ISCHR(stat_char.st_mode)){ ! 388: if (stat_slash.st_dev == stat_block.st_rdev) { ! 389: hotroot++; ! 390: raw = unrawname(name); ! 391: } ! 392: check(raw); ! 393: return(YES); ! 394: } else if(big == BIG) { ! 395: check(name); ! 396: return(YES); ! 397: } else { ! 398: error("%s is not a character device\n", raw); ! 399: return(NO); ! 400: } ! 401: } else ! 402: if (S_ISCHR(stat_block.st_mode)){ ! 403: if (looped) { ! 404: error("Can't make sense out of name %s\n", name); ! 405: return(NO); ! 406: } ! 407: name = unrawname(name); ! 408: looped++; ! 409: goto retry; ! 410: } ! 411: error("Can't make sense out of name %s\n", name); ! 412: return(NO); ! 413: } ! 414: ! 415: char * ! 416: unrawname(cp) ! 417: char *cp; ! 418: { ! 419: char *dp = strrchr(cp, '/'); ! 420: struct stat stb; ! 421: if (dp == 0) ! 422: return(cp); ! 423: if (stat(cp, &stb) < 0) ! 424: return(cp); ! 425: if (S_ISCHR(stb.st_mode) == 0) ! 426: return(cp); ! 427: if (*(dp+1) != 'r') ! 428: return(cp); ! 429: strcpy(dp+1, dp+2); ! 430: return(cp); ! 431: } ! 432: ! 433: char * ! 434: rawname(cp) ! 435: char *cp; ! 436: { ! 437: static char rawbuf[32]; ! 438: char *dp = strrchr(cp, '/'); ! 439: ! 440: if (dp == 0) ! 441: return (0); ! 442: if(big == BIG) ! 443: return(cp); ! 444: *dp = 0; ! 445: strcpy(rawbuf, cp); ! 446: *dp = '/'; ! 447: strcat(rawbuf, "/r"); ! 448: strcat(rawbuf, dp+1); ! 449: return (rawbuf); ! 450: } ! 451: ! 452: check(dev) ! 453: char *dev; ! 454: { ! 455: ! 456: devname = dev; ! 457: check1(dev); ! 458: devname = 0; ! 459: } ! 460: ! 461: check1(dev) ! 462: char *dev; ! 463: { ! 464: register DINODE *dp; ! 465: register n; ! 466: register ino_t *blp; ! 467: ino_t savino; ! 468: daddr_t blk; ! 469: BUFAREA *bp1, *bp2; ! 470: ! 471: if(setup(dev) == NO) ! 472: return; ! 473: if (preen==0) { ! 474: printf("** Checking %s\n", dev); ! 475: printf("** Phase 1 - Check Blocks and Sizes\n"); ! 476: } ! 477: pfunc = pass1; ! 478: for(inum = 1; inum <= imax; inum++) { ! 479: if((dp = ginode()) == NULL) ! 480: continue; ! 481: if(ALLOC) { ! 482: lastino = inum; ! 483: if(ftypeok(dp) == NO) { ! 484: pfatal("UNKNOWN FILE TYPE I=%u",inum); ! 485: if(reply("CLEAR") == YES) { ! 486: zapino(dp); ! 487: inodirty(); ! 488: } ! 489: continue; ! 490: } ! 491: n_files++; ! 492: if(setlncnt(dp->di_nlink) <= 0) { ! 493: if(badlnp < &badlncnt[MAXLNCNT]) ! 494: *badlnp++ = inum; ! 495: else { ! 496: pfatal("LINK COUNT TABLE OVERFLOW"); ! 497: if(reply("CONTINUE") == NO) ! 498: errexit(""); ! 499: } ! 500: } ! 501: setstate(DIR ? DSTATE : FSTATE); ! 502: badblk = dupblk = 0; ! 503: filsize = 0; ! 504: maxblk = 0; ! 505: ckinode(dp,ADDR); ! 506: if((n = getstate()) == DSTATE || n == FSTATE) ! 507: sizechk(dp); ! 508: } ! 509: else if(dp->di_mode != 0) { ! 510: pfatal("PARTIALLY ALLOCATED INODE I=%u",inum); ! 511: if(reply("CLEAR") == YES) { ! 512: zapino(dp); ! 513: inodirty(); ! 514: } ! 515: } ! 516: } ! 517: ! 518: ! 519: if(enddup != &duplist[0]) { ! 520: if (preen) ! 521: pfatal("INTERNAL ERROR: dups with -p"); ! 522: printf("** Phase 1b - Rescan For More DUPS\n"); ! 523: pfunc = pass1b; ! 524: for(inum = 1; inum <= lastino; inum++) { ! 525: if(getstate() != USTATE && (dp = ginode()) != NULL) ! 526: if(ckinode(dp,ADDR) & STOP) ! 527: break; ! 528: } ! 529: } ! 530: if(rawflg) { /* shouldn't be set for 4k system */ ! 531: if(inoblk.b_dirty) ! 532: bwrite(&dfile,membase,startib,(int)niblk*BSIZE(big)); ! 533: inoblk.b_dirty = 0; ! 534: if(poolhead) { ! 535: clear(membase,niblk*BSIZE(BIG)); ! 536: for(bp1 = poolhead;bp1->b_next;bp1 = bp1->b_next); ! 537: bp2 = &((BUFAREA *)membase)[(niblk*BSIZE(BIG))/sizeof(BUFAREA)]; ! 538: while(--bp2 >= (BUFAREA *)membase) { ! 539: initbarea(bp2); ! 540: bp2->b_next = bp1->b_next; ! 541: bp1->b_next = bp2; ! 542: } ! 543: } ! 544: rawflg = 0; ! 545: ! 546: } ! 547: ! 548: ! 549: if (preen == 0) ! 550: printf("** Phase 2 - Check Pathnames\n"); ! 551: inum = ROOTINO; ! 552: thisname = pathp = pathname; ! 553: pfunc = pass2; ! 554: switch(getstate()) { ! 555: case USTATE: ! 556: errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); ! 557: case FSTATE: ! 558: pfatal("ROOT INODE NOT DIRECTORY"); ! 559: if(reply("FIX") == NO || (dp = ginode()) == NULL) ! 560: errexit(""); ! 561: dp->di_mode &= ~IFMT; ! 562: dp->di_mode |= IFDIR; ! 563: inodirty(); ! 564: setstate(DSTATE); ! 565: case DSTATE: ! 566: descend(); ! 567: break; ! 568: case CLEAR: ! 569: pfatal("DUPS/BAD IN ROOT INODE"); ! 570: printf("\n"); ! 571: if(reply("CONTINUE") == NO) ! 572: errexit(""); ! 573: setstate(DSTATE); ! 574: descend(); ! 575: } ! 576: ! 577: ! 578: if (preen == 0) ! 579: printf("** Phase 3 - Check Connectivity\n"); ! 580: for(inum = 1; inum <= lastino; inum++) { ! 581: if(getstate() == DSTATE) { ! 582: pfunc = findino; ! 583: srchname = ".."; ! 584: savino = inum; ! 585: do { ! 586: orphan = inum; ! 587: if((dp = ginode()) == NULL) ! 588: break; ! 589: filsize = dp->di_size; ! 590: parentdir = 0; ! 591: ckinode(dp,DATA); ! 592: if((inum = parentdir) == 0) ! 593: break; ! 594: } while(getstate() == DSTATE); ! 595: inum = orphan; ! 596: if(linkup() == YES) { ! 597: thisname = pathp = pathname; ! 598: *pathp++ = '?'; ! 599: pfunc = pass2; ! 600: descend(); ! 601: } ! 602: inum = savino; ! 603: } ! 604: } ! 605: ! 606: ! 607: if (preen == 0) ! 608: printf("** Phase 4 - Check Reference Counts\n"); ! 609: pfunc = pass4; ! 610: zcleared = 0; ! 611: for(inum = 1; inum <= lastino; inum++) { ! 612: switch(getstate()) { ! 613: case FSTATE: ! 614: if(n = getlncnt()) ! 615: adjust((short)n); ! 616: else { ! 617: for(blp = badlncnt;blp < badlnp; blp++) ! 618: if(*blp == inum) { ! 619: clri("UNREF",preen?NO:YES,YES); ! 620: break; ! 621: } ! 622: } ! 623: break; ! 624: case DSTATE: ! 625: clri("UNREF",YES,NO); ! 626: break; ! 627: case CLEAR: ! 628: clri("BAD/DUP",YES,NO); ! 629: } ! 630: } ! 631: if (zcleared) ! 632: pwarn("%u LINKLESS FILES CLEARED\n", zcleared); ! 633: if(imax - n_files != superblk.s_tinode) { ! 634: pwarn("FREE INODE COUNT %u SHOULD BE %u IN SUPERBLK", ! 635: superblk.s_tinode, imax - n_files); ! 636: if (preen) ! 637: printf(" (FIXED)\n"); ! 638: if (preen || reply("FIX") == YES) { ! 639: superblk.s_tinode = imax - n_files; ! 640: sbdirty(); ! 641: } ! 642: } ! 643: flush(&dfile,&fileblk); ! 644: ! 645: if (preen == 0) ! 646: printf("** Phase 5 - Check Free List "); ! 647: if(sflag || (csflag && rplyflag == 0)) { ! 648: if (preen == 0) ! 649: printf("(Ignored)\n"); ! 650: fixfree = 1; ! 651: } ! 652: else { ! 653: if (preen == 0) ! 654: printf("\n"); ! 655: if(freemap) ! 656: copy(blkmap,freemap,(MEMSIZE)bmapsz); ! 657: else { ! 658: for(blk = 0; blk < fmapblk; blk++) { ! 659: bp1 = getblk((BUFAREA *)NULL,blk); ! 660: bp2 = getblk((BUFAREA *)NULL,blk+fmapblk); ! 661: copy(bp1->b_un.b_buf,bp2->b_un.b_buf,BSIZE(big)); ! 662: dirty(bp2); ! 663: } ! 664: } ! 665: badblk = dupblk = 0; ! 666: #ifdef SMALL ! 667: if(big == SMALL) { ! 668: freeblk.df_nfree = superblk.s_nfree; ! 669: for(n = 0; n < NICFREE; n++) ! 670: freeblk.df_free[n] = superblk.s_free[n]; ! 671: } ! 672: #endif ! 673: freechk(); ! 674: if(badblk) { ! 675: pfatal("%d BAD BLKS IN FREE LIST",badblk); ! 676: printf("\n"); ! 677: } ! 678: if(dupblk) ! 679: pwarn("%d DUP BLKS IN FREE LIST\n",dupblk); ! 680: if(fixfree == 0) { ! 681: if((n_blks+n_free) != (fmax-fmin)) { ! 682: pwarn("%ld BLK(S) MISSING\n", ! 683: fmax-fmin-n_blks-n_free); ! 684: fixfree = 1; ! 685: } ! 686: #ifdef SMALL ! 687: else if(big == SMALL && n_free != superblk.s_tfree) { ! 688: pwarn("FREE BLK COUNT WRONG IN SUPERBLK"); ! 689: if (preen) ! 690: printf(" (FIXED)\n"); ! 691: if(preen || reply("FIX") == YES) { ! 692: superblk.s_tfree = n_free; ! 693: sbdirty(); ! 694: } ! 695: } ! 696: #endif ! 697: } ! 698: if(fixfree) { ! 699: pwarn("BAD FREE LIST"); ! 700: if (preen) ! 701: printf(" (SALVAGED)\n"); ! 702: else if(reply("SALVAGE") == NO) ! 703: fixfree = 0; ! 704: } ! 705: } ! 706: ! 707: if(fixfree) { ! 708: if (preen == 0) ! 709: printf("** Phase 6 - Salvage Free List\n"); ! 710: makefree(); ! 711: n_free = superblk.s_tfree; ! 712: } ! 713: ! 714: pwarn("%ld files %ld blocks %ld free\n", n_files,n_blks,n_free); ! 715: if(dfile.mod) { ! 716: time(&superblk.s_time); ! 717: sbdirty(); ! 718: } ! 719: ckfini(); ! 720: sync(); ! 721: if(dfile.mod && hotroot) { ! 722: printf("ROOT MODIFIED\n"); ! 723: } ! 724: if(dfile.mod && preen == 0) ! 725: printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); ! 726: } ! 727: ! 728: /* VARARGS1 */ ! 729: error(s1,s2,s3,s4) ! 730: char *s1; ! 731: { ! 732: printf(s1,s2,s3,s4); ! 733: } ! 734: ! 735: /* VARARGS1 */ ! 736: errexit(s1,s2,s3,s4) ! 737: char *s1; ! 738: { ! 739: error(s1,s2,s3,s4); ! 740: exit(8); ! 741: } ! 742: ! 743: /* ! 744: * Pfatal is called when an inconsistency occurs ! 745: * which should not happen during normal operations. ! 746: * It printfs a message and then dies. ! 747: * When not preening, this is just a printf. ! 748: */ ! 749: pfatal(s,a1,a2,a3) ! 750: char *s; ! 751: { ! 752: ! 753: if (preen) { ! 754: printf("%s: ", devname); ! 755: printf(s, a1, a2, a3); ! 756: printf("\n"); ! 757: preendie(); ! 758: } ! 759: printf(s, a1, a2, a3); ! 760: } ! 761: ! 762: /* ! 763: * Fatal is called to terminate preening ! 764: * due to unexplainable inconsistency. ! 765: */ ! 766: preendie() ! 767: { ! 768: ! 769: printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); ! 770: exit(8); ! 771: } ! 772: ! 773: /* ! 774: * Pwarn is like printf when not preening, ! 775: * or a warning (preceded by filename) when preening. ! 776: */ ! 777: pwarn(s,a1,a2,a3,a4,a5,a6) ! 778: char *s; ! 779: { ! 780: ! 781: if (preen) ! 782: printf("%s: ", devname); ! 783: printf(s, a1, a2, a3, a4, a5, a6); ! 784: } ! 785: ! 786: ckinode(dp,flg) ! 787: DINODE *dp; ! 788: register flg; ! 789: { ! 790: register daddr_t *ap; ! 791: register ret; ! 792: int (*func)(), n; ! 793: daddr_t iaddrs[NADDR]; ! 794: ! 795: if(SPECIAL) ! 796: return(KEEPON); ! 797: l3tol(iaddrs,dp->di_addr,NADDR); ! 798: func = (flg == ADDR) ? pfunc : dirscan; ! 799: for(ap = iaddrs; ap < &iaddrs[NADDR-3]; ap++) { ! 800: if(*ap && (ret = (*func)(*ap)) & STOP) ! 801: return(ret); ! 802: } ! 803: for(n = 1; n < 4; n++) { ! 804: if(*ap && (ret = iblock(*ap,n,flg)) & STOP) ! 805: return(ret); ! 806: ap++; ! 807: } ! 808: return(KEEPON); ! 809: } ! 810: ! 811: ! 812: iblock(blk,ilevel,flg) ! 813: daddr_t blk; ! 814: register ilevel; ! 815: { ! 816: register daddr_t *ap; ! 817: register n; ! 818: int (*func)(); ! 819: BUFAREA ib; ! 820: ! 821: if(flg == ADDR) { ! 822: func = pfunc; ! 823: if(((n = (*func)(blk)) & KEEPON) == 0) ! 824: return(n); ! 825: } ! 826: else ! 827: func = dirscan; ! 828: if(outrange(blk)) /* protect thyself */ ! 829: return(SKIP); ! 830: initbarea(&ib); ! 831: if(getblk(&ib,blk) == NULL) ! 832: return(SKIP); ! 833: ilevel--; ! 834: for(ap = ib.b_un.b_indir; ap < &ib.b_un.b_indir[NINDIR(big)]; ap++) { ! 835: if(*ap) { ! 836: if(ilevel > 0) { ! 837: n = iblock(*ap,ilevel,flg); ! 838: } ! 839: else ! 840: n = (*func)(*ap); ! 841: if(n & STOP) ! 842: return(n); ! 843: } ! 844: } ! 845: return(KEEPON); ! 846: } ! 847: ! 848: ! 849: pass1(blk) ! 850: daddr_t blk; ! 851: { ! 852: register daddr_t *dlp; ! 853: ! 854: if(outrange(blk)) { ! 855: blkerr("BAD",blk); ! 856: if(++badblk >= MAXBAD) { ! 857: printf("EXCESSIVE BAD BLKS I=%u",inum); ! 858: if(reply("CONTINUE") == NO) ! 859: errexit(""); ! 860: return(STOP); ! 861: } ! 862: return(SKIP); ! 863: } ! 864: if(getbmap(blk)) { ! 865: blkerr("DUP",blk); ! 866: if(++dupblk >= MAXDUP) { ! 867: printf("EXCESSIVE DUP BLKS I=%u",inum); ! 868: if(reply("CONTINUE") == NO) ! 869: errexit(""); ! 870: return(STOP); ! 871: } ! 872: if(enddup >= &duplist[DUPTBLSIZE]) { ! 873: printf("DUP TABLE OVERFLOW."); ! 874: if(reply("CONTINUE") == NO) ! 875: errexit(""); ! 876: return(STOP); ! 877: } ! 878: for(dlp = duplist; dlp < muldup; dlp++) { ! 879: if(*dlp == blk) { ! 880: *enddup++ = blk; ! 881: break; ! 882: } ! 883: } ! 884: if(dlp >= muldup) { ! 885: *enddup++ = *muldup; ! 886: *muldup++ = blk; ! 887: } ! 888: } ! 889: else { ! 890: n_blks++; ! 891: setbmap(blk); ! 892: } ! 893: filsize++; ! 894: return(KEEPON); ! 895: } ! 896: ! 897: ! 898: pass1b(blk) ! 899: daddr_t blk; ! 900: { ! 901: register daddr_t *dlp; ! 902: ! 903: if(outrange(blk)) ! 904: return(SKIP); ! 905: for(dlp = duplist; dlp < muldup; dlp++) { ! 906: if(*dlp == blk) { ! 907: blkerr("DUP",blk); ! 908: *dlp = *--muldup; ! 909: *muldup = blk; ! 910: return(muldup == duplist ? STOP : KEEPON); ! 911: } ! 912: } ! 913: return(KEEPON); ! 914: } ! 915: ! 916: ! 917: pass2(dirp) ! 918: register DIRECT *dirp; ! 919: { ! 920: register char *p; ! 921: register n; ! 922: DINODE *dp; ! 923: ! 924: if((inum = dirp->d_ino) == 0) ! 925: return(KEEPON); ! 926: thisname = pathp; ! 927: for(p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; ) ! 928: if((*pathp++ = *p++) == 0) { ! 929: --pathp; ! 930: break; ! 931: } ! 932: *pathp = 0; ! 933: n = NO; ! 934: if(inum > imax || inum <= 0) ! 935: n = direrr("I OUT OF RANGE"); ! 936: else { ! 937: again: ! 938: switch(getstate()) { ! 939: case USTATE: ! 940: n = direrr("UNALLOCATED"); ! 941: break; ! 942: case CLEAR: ! 943: if((n = direrr("DUP/BAD")) == YES) ! 944: break; ! 945: if((dp = ginode()) == NULL) ! 946: break; ! 947: setstate(DIR ? DSTATE : FSTATE); ! 948: goto again; ! 949: case FSTATE: ! 950: declncnt(); ! 951: break; ! 952: case DSTATE: ! 953: declncnt(); ! 954: descend(); ! 955: } ! 956: } ! 957: pathp = thisname; ! 958: if(n == NO) ! 959: return(KEEPON); ! 960: dirp->d_ino = 0; ! 961: return(KEEPON|ALTERD); ! 962: } ! 963: ! 964: ! 965: pass4(blk) ! 966: daddr_t blk; ! 967: { ! 968: register daddr_t *dlp; ! 969: ! 970: if(outrange(blk)) ! 971: return(SKIP); ! 972: if(getbmap(blk)) { ! 973: for(dlp = duplist; dlp < enddup; dlp++) ! 974: if(*dlp == blk) { ! 975: *dlp = *--enddup; ! 976: return(KEEPON); ! 977: } ! 978: clrbmap(blk); ! 979: n_blks--; ! 980: } ! 981: return(KEEPON); ! 982: } ! 983: ! 984: ! 985: pass5(blk) ! 986: daddr_t blk; ! 987: { ! 988: if(outrange(blk)) { ! 989: fixfree = 1; ! 990: if (preen) ! 991: pfatal("BAD BLOCKS IN FREE LIST."); ! 992: if(++badblk >= MAXBAD) { ! 993: printf("EXCESSIVE BAD BLKS IN FREE LIST."); ! 994: if(reply("CONTINUE") == NO) ! 995: errexit(""); ! 996: return(STOP); ! 997: } ! 998: return(SKIP); ! 999: } ! 1000: if(getfmap(blk)) { ! 1001: fixfree = 1; ! 1002: if(++dupblk >= DUPTBLSIZE) { ! 1003: printf("EXCESSIVE DUP BLKS IN FREE LIST."); ! 1004: if(reply("CONTINUE") == NO) ! 1005: errexit(""); ! 1006: return(STOP); ! 1007: } ! 1008: } ! 1009: else { ! 1010: n_free++; ! 1011: setfmap(blk); ! 1012: } ! 1013: return(KEEPON); ! 1014: } ! 1015: ! 1016: ! 1017: blkerr(s,blk) ! 1018: daddr_t blk; ! 1019: char *s; ! 1020: { ! 1021: pfatal("%ld %s I=%u",blk,s,inum); ! 1022: printf("\n"); ! 1023: setstate(CLEAR); /* mark for possible clearing */ ! 1024: } ! 1025: ! 1026: ! 1027: descend() ! 1028: { ! 1029: register DINODE *dp; ! 1030: register char *savname; ! 1031: off_t savsize; ! 1032: ! 1033: setstate(FSTATE); ! 1034: if((dp = ginode()) == NULL) ! 1035: return; ! 1036: savname = thisname; ! 1037: *pathp++ = '/'; ! 1038: savsize = filsize; ! 1039: filsize = dp->di_size; ! 1040: ckinode(dp,DATA); ! 1041: thisname = savname; ! 1042: *--pathp = 0; ! 1043: filsize = savsize; ! 1044: } ! 1045: ! 1046: ! 1047: dirscan(blk) ! 1048: daddr_t blk; ! 1049: { ! 1050: register DIRECT *dirp; ! 1051: register char *p1, *p2; ! 1052: register n; ! 1053: DIRECT direntry; ! 1054: ! 1055: if(outrange(blk)) { ! 1056: filsize -= BSIZE(big); ! 1057: return(SKIP); ! 1058: } ! 1059: for(dirp = dirblk.b_dir; dirp < &dirblk.b_dir[NDIRECT(big)] && ! 1060: filsize > 0; dirp++, filsize -= sizeof(DIRECT)) { ! 1061: if(getblk(&fileblk,blk) == NULL) { ! 1062: filsize -= (&dirblk.b_dir[NDIRECT(big)]-dirp)* ! 1063: sizeof(DIRECT); ! 1064: return(SKIP); ! 1065: } ! 1066: p1 = &dirp->d_name[DIRSIZ]; ! 1067: p2 = &direntry.d_name[DIRSIZ]; ! 1068: while(p1 > (char *)dirp) ! 1069: *--p2 = *--p1; ! 1070: if((n = (*pfunc)(&direntry)) & ALTERD) { ! 1071: if(getblk(&fileblk,blk) != NULL) { ! 1072: p1 = &dirp->d_name[DIRSIZ]; ! 1073: p2 = &direntry.d_name[DIRSIZ]; ! 1074: while(p1 > (char *)dirp) ! 1075: *--p1 = *--p2; ! 1076: fbdirty(); ! 1077: } ! 1078: else ! 1079: n &= ~ALTERD; ! 1080: } ! 1081: if(n & STOP) ! 1082: return(n); ! 1083: } ! 1084: return(filsize > 0 ? KEEPON : STOP); ! 1085: } ! 1086: ! 1087: ! 1088: direrr(s) ! 1089: char *s; ! 1090: { ! 1091: register DINODE *dp; ! 1092: ! 1093: pwarn("%s ",s); ! 1094: pinode(); ! 1095: printf("\n"); ! 1096: if((dp = ginode()) != NULL && ftypeok(dp)) ! 1097: pfatal("%s=%s",DIR?"DIR":"FILE",pathname); ! 1098: else ! 1099: pfatal("NAME=%s",pathname); ! 1100: return(reply("REMOVE")); ! 1101: } ! 1102: ! 1103: ! 1104: adjust(lcnt) ! 1105: register short lcnt; ! 1106: { ! 1107: register DINODE *dp; ! 1108: ! 1109: if((dp = ginode()) == NULL) ! 1110: return; ! 1111: if(dp->di_nlink == lcnt) { ! 1112: if(linkup() == NO) ! 1113: clri("UNREF",NO,NO); ! 1114: } ! 1115: else { ! 1116: pwarn("LINK COUNT %s", ! 1117: (lfdir==inum)?lfname:(DIR?"DIR":"FILE")); ! 1118: pinode(); ! 1119: printf(" COUNT %d SHOULD BE %d", ! 1120: dp->di_nlink,dp->di_nlink-lcnt); ! 1121: if (preen) { ! 1122: if (lcnt < 0) { ! 1123: printf("\n"); ! 1124: preendie(); ! 1125: } ! 1126: printf(" (ADJUSTED)\n"); ! 1127: } ! 1128: if(preen || reply("ADJUST") == YES) { ! 1129: dp->di_nlink -= lcnt; ! 1130: inodirty(); ! 1131: } ! 1132: } ! 1133: } ! 1134: ! 1135: ! 1136: clri(s,flg,jclr) ! 1137: char *s; ! 1138: { ! 1139: register DINODE *dp; ! 1140: ! 1141: if((dp = ginode()) == NULL) ! 1142: return; ! 1143: if(flg == YES) { ! 1144: pwarn("%s %s",s,DIR?"DIR":"FILE"); ! 1145: pinode(); ! 1146: } ! 1147: if(preen || reply("CLEAR") == YES) { ! 1148: if (preen) ! 1149: if (jclr == YES) ! 1150: zcleared++; ! 1151: else ! 1152: printf(" (CLEARED)\n"); ! 1153: n_files--; ! 1154: pfunc = pass4; ! 1155: ckinode(dp,ADDR); ! 1156: zapino(dp); ! 1157: inodirty(); ! 1158: } ! 1159: } ! 1160: ! 1161: ! 1162: setup(dev) ! 1163: char *dev; ! 1164: { ! 1165: register n; ! 1166: register BUFAREA *bp; ! 1167: register MEMSIZE msize; ! 1168: char *mbase; ! 1169: daddr_t bcnt, nscrblk; ! 1170: dev_t rootdev; ! 1171: off_t smapsz, lncntsz, totsz; ! 1172: struct stat statarea; ! 1173: ! 1174: if(stat("/",&statarea) < 0) ! 1175: errexit("Can't stat root\n"); ! 1176: rootdev = statarea.st_dev; ! 1177: if(stat(dev,&statarea) < 0) { ! 1178: error("Can't stat %s\n",dev); ! 1179: return(NO); ! 1180: } ! 1181: rawflg = 0; ! 1182: big = BIG; /* does this undo the work in blockcheck? */ ! 1183: if(S_ISBLK(statarea.st_mode)) { ! 1184: if(BITFS(statarea.st_rdev)) ! 1185: big = BIG; ! 1186: } ! 1187: else if(S_ISCHR(statarea.st_mode)) ! 1188: rawflg++; ! 1189: else { ! 1190: if (reply("file is not a block or character device; OK") == NO) ! 1191: return(NO); ! 1192: big = BIG; ! 1193: } ! 1194: if(rootdev == statarea.st_rdev) ! 1195: hotroot++; ! 1196: if((dfile.rfdes = open(dev,0)) < 0) { ! 1197: error("Can't open %s\n",dev); ! 1198: return(NO); ! 1199: } ! 1200: if (preen == 0) ! 1201: printf("\n%s",dev); ! 1202: if(nflag || (dfile.wfdes = open(dev,1)) < 0) { ! 1203: dfile.wfdes = -1; ! 1204: if (preen) ! 1205: pfatal("NO WRITE ACCESS"); ! 1206: printf(" (NO WRITE)"); ! 1207: } ! 1208: if (preen == 0) ! 1209: printf("\n"); ! 1210: fixfree = 0; ! 1211: dfile.mod = 0; ! 1212: n_files = n_blks = n_free = 0; ! 1213: muldup = enddup = &duplist[0]; ! 1214: badlnp = &badlncnt[0]; ! 1215: lfdir = 0; ! 1216: rplyflag = 0; ! 1217: initbarea(&sblk); ! 1218: initbarea(&fileblk); ! 1219: initbarea(&inoblk); ! 1220: sfile.wfdes = sfile.rfdes = -1; ! 1221: rmscr = 0; ! 1222: if(getblk(&sblk,SUPERB) == NULL) { ! 1223: ckfini(); ! 1224: return(NO); ! 1225: } ! 1226: imax = ((ino_t)superblk.s_isize - (SUPERB+1)) * INOPB(big); ! 1227: fmin = (daddr_t)superblk.s_isize; /* first data blk num */ ! 1228: fmax = superblk.s_fsize; /* first invalid blk num */ ! 1229: m_blks = 0; ! 1230: /* ! 1231: * if this is a big bit mapped file system, ! 1232: * back off fmax by m_blks the number of bitmap blocks. ! 1233: */ ! 1234: if ((big == BIG) && superblk.U.N.S_flag) { ! 1235: m_blks = (superblk.s_fsize+superblk.U.N.S_bsize-1)/superblk.U.N.S_bsize; ! 1236: fmax -= m_blks; ! 1237: } ! 1238: if(fmin >= fmax || ! 1239: (imax/INOPB(big)) != ((ino_t)superblk.s_isize-(SUPERB+1))) { ! 1240: pfatal("Size check: fsize %ld isize %d", ! 1241: superblk.s_fsize,superblk.s_isize); ! 1242: printf("\n"); ! 1243: ckfini(); ! 1244: return(NO); ! 1245: } ! 1246: if (preen == 0) ! 1247: printf("File System: %.12s\n\n", superblk.s_fsmnt); ! 1248: bmapsz = roundup(howmany(fmax,BITSPB),sizeof(*lncntp)); ! 1249: smapsz = roundup(howmany((long)(imax+1),STATEPB),sizeof(*lncntp)); ! 1250: lncntsz = (long)(imax+1) * sizeof(*lncntp); ! 1251: if(bmapsz > smapsz+lncntsz) ! 1252: smapsz = bmapsz-lncntsz; ! 1253: totsz = bmapsz+smapsz+lncntsz; ! 1254: ! 1255: bm_buf = (long *)membase; ! 1256: memsize = memsize-BSIZE(BIG); ! 1257: membase = membase+BSIZE(BIG); ! 1258: ! 1259: msize = memsize; ! 1260: mbase = membase; ! 1261: if(rawflg) { ! 1262: if(msize < (MEMSIZE)(NINOBLK*BSIZE(big)) + 2*sizeof(BUFAREA)) ! 1263: rawflg = 0; ! 1264: else { ! 1265: msize -= (MEMSIZE)NINOBLK*BSIZE(big); ! 1266: mbase += (MEMSIZE)NINOBLK*BSIZE(big); ! 1267: niblk = NINOBLK; ! 1268: startib = fmax; ! 1269: } ! 1270: } ! 1271: clear(mbase,msize); ! 1272: if((off_t)msize < totsz) { ! 1273: bmapsz = roundup(bmapsz,BSIZE(big)); ! 1274: smapsz = roundup(smapsz,BSIZE(big)); ! 1275: lncntsz = roundup(lncntsz,BSIZE(big)); ! 1276: nscrblk = (bmapsz+smapsz+lncntsz)>>BSHIFT(big); ! 1277: if(tflag == 0) { ! 1278: printf("\nNEED SCRATCH FILE (%ld BLKS)\n",nscrblk); ! 1279: do { ! 1280: printf("ENTER FILENAME: "); ! 1281: if((n = getline(stdin,scrfile,sizeof(scrfile))) == EOF) ! 1282: errexit("\n"); ! 1283: } while(n == 0); ! 1284: } ! 1285: if(stat(scrfile,&statarea) < 0 || S_ISREG(statarea.st_mode)) ! 1286: rmscr++; ! 1287: if((sfile.wfdes = creat(scrfile,0666)) < 0 || ! 1288: (sfile.rfdes = open(scrfile,0)) < 0) { ! 1289: error("Can't create %s\n",scrfile); ! 1290: ckfini(); ! 1291: return(NO); ! 1292: } ! 1293: bp = &((BUFAREA *)mbase)[(msize/sizeof(BUFAREA))]; ! 1294: poolhead = NULL; ! 1295: while(--bp >= (BUFAREA *)mbase) { ! 1296: initbarea(bp); ! 1297: bp->b_next = poolhead; ! 1298: poolhead = bp; ! 1299: } ! 1300: bp = poolhead; ! 1301: for(bcnt = 0; bcnt < nscrblk; bcnt++) { ! 1302: bp->b_bno = bcnt; ! 1303: dirty(bp); ! 1304: flush(&sfile,bp); ! 1305: } ! 1306: blkmap = freemap = statemap = (char *) NULL; ! 1307: lncntp = (short *) NULL; ! 1308: smapblk = bmapsz / BSIZE(big); ! 1309: lncntblk = smapblk + smapsz / BSIZE(big); ! 1310: fmapblk = smapblk; ! 1311: } ! 1312: else { ! 1313: if(rawflg && (off_t)msize > totsz+BSIZE(big)) { ! 1314: niblk += (unsigned)((off_t)msize-totsz)>>BSHIFT(big); ! 1315: if(niblk > MAXRAW) ! 1316: niblk = MAXRAW; ! 1317: msize = memsize - (niblk*BSIZE(big)); ! 1318: mbase = membase + (niblk*BSIZE(big)); ! 1319: } ! 1320: poolhead = NULL; ! 1321: blkmap = mbase; ! 1322: statemap = &mbase[(MEMSIZE)bmapsz]; ! 1323: freemap = statemap; ! 1324: lncntp = (short *)&statemap[(MEMSIZE)smapsz]; ! 1325: } ! 1326: return(YES); ! 1327: } ! 1328: ! 1329: ! 1330: DINODE * ! 1331: ginode() ! 1332: { ! 1333: register DINODE *dp; ! 1334: register char *mbase; ! 1335: daddr_t iblk; ! 1336: ! 1337: if(inum > imax) ! 1338: return(NULL); ! 1339: iblk = itod(big, inum); ! 1340: if(rawflg) { ! 1341: mbase = membase; ! 1342: if(iblk < startib || iblk >= startib+niblk) { ! 1343: if(inoblk.b_dirty) ! 1344: bwrite(&dfile,mbase,startib,(int)niblk*BSIZE(big)); ! 1345: inoblk.b_dirty = 0; ! 1346: if(bread(&dfile,mbase,iblk,(int)niblk*BSIZE(big)) == NO) { ! 1347: startib = fmax; ! 1348: return(NULL); ! 1349: } ! 1350: startib = iblk; ! 1351: } ! 1352: dp = (DINODE *)&mbase[(unsigned)((iblk-startib)<<BSHIFT(big))]; ! 1353: } ! 1354: else if(getblk(&inoblk,iblk) != NULL) ! 1355: dp = inoblk.b_un.b_dinode; ! 1356: else ! 1357: return(NULL); ! 1358: return(dp + itoo(big, inum)); ! 1359: } ! 1360: ! 1361: ! 1362: ftypeok(dp) ! 1363: DINODE *dp; ! 1364: { ! 1365: switch(dp->di_mode & IFMT) { ! 1366: case IFDIR: ! 1367: case IFREG: ! 1368: case IFBLK: ! 1369: case IFCHR: ! 1370: /* case IFMPC: */ ! 1371: case IFLNK: ! 1372: /* case IFMPB: */ ! 1373: return(YES); ! 1374: default: ! 1375: return(NO); ! 1376: } ! 1377: } ! 1378: ! 1379: ! 1380: reply(s) ! 1381: char *s; ! 1382: { ! 1383: char line[80]; ! 1384: ! 1385: if (preen) ! 1386: pfatal("INTERNAL ERROR: GOT TO reply()"); ! 1387: rplyflag = 1; ! 1388: printf("\n%s? ",s); ! 1389: if(nflag || csflag || dfile.wfdes < 0) { ! 1390: printf(" no\n\n"); ! 1391: return(NO); ! 1392: } ! 1393: if(yflag) { ! 1394: printf(" yes\n\n"); ! 1395: return(YES); ! 1396: } ! 1397: if(getline(stdin,line,sizeof(line)) == EOF) ! 1398: errexit("\n"); ! 1399: printf("\n"); ! 1400: if(line[0] == 'y' || line[0] == 'Y') ! 1401: return(YES); ! 1402: else ! 1403: return(NO); ! 1404: } ! 1405: ! 1406: ! 1407: getline(fp,loc,maxlen) ! 1408: FILE *fp; ! 1409: char *loc; ! 1410: { ! 1411: register n; ! 1412: register char *p, *lastloc; ! 1413: ! 1414: p = loc; ! 1415: lastloc = &p[maxlen-1]; ! 1416: while((n = getc(fp)) != '\n') { ! 1417: if(n == EOF) ! 1418: return(EOF); ! 1419: if(!isspace(n) && p < lastloc) ! 1420: *p++ = n; ! 1421: } ! 1422: *p = 0; ! 1423: return(p - loc); ! 1424: } ! 1425: ! 1426: ! 1427: stype(p) ! 1428: register char *p; ! 1429: { ! 1430: if(*p == 0) ! 1431: return; ! 1432: cylsize = atoi(p); ! 1433: while(*p && *p != ':') ! 1434: p++; ! 1435: if(*p) ! 1436: p++; ! 1437: stepsize = atoi(p); ! 1438: if(stepsize <= 0 || stepsize > cylsize || ! 1439: cylsize <= 0 || cylsize > MAXCYL) { ! 1440: error("Invalid -s argument, defaults assumed\n"); ! 1441: cylsize = stepsize = 0; ! 1442: } ! 1443: } ! 1444: ! 1445: ! 1446: dostate(s,flg) ! 1447: { ! 1448: register char *p; ! 1449: register unsigned byte, shift; ! 1450: BUFAREA *bp; ! 1451: ! 1452: byte = (inum)/STATEPB; ! 1453: shift = LSTATE * ((inum)%STATEPB); ! 1454: if(statemap != NULL) { ! 1455: bp = NULL; ! 1456: p = &statemap[byte]; ! 1457: } ! 1458: else if((bp = getblk((BUFAREA *)NULL, ! 1459: (daddr_t)(smapblk+(byte/BSIZE(big))))) == NULL) ! 1460: errexit("Fatal I/O error\n"); ! 1461: else ! 1462: p = &bp->b_un.b_buf[byte%BSIZE(big)]; ! 1463: switch(flg) { ! 1464: case 0: ! 1465: *p &= ~(SMASK<<(shift)); ! 1466: *p |= s<<(shift); ! 1467: if(bp != NULL) ! 1468: dirty(bp); ! 1469: return(s); ! 1470: case 1: ! 1471: return((*p>>(shift)) & SMASK); ! 1472: } ! 1473: return(USTATE); ! 1474: } ! 1475: ! 1476: ! 1477: domap(blk,flg) ! 1478: daddr_t blk; ! 1479: { ! 1480: register char *p; ! 1481: register unsigned n; ! 1482: register BUFAREA *bp; ! 1483: off_t byte; ! 1484: ! 1485: byte = blk >> BITSHIFT; ! 1486: n = 1<<((unsigned)(blk & BITMASK)); ! 1487: if(flg & 04) { ! 1488: p = freemap; ! 1489: blk = fmapblk; ! 1490: } ! 1491: else { ! 1492: p = blkmap; ! 1493: blk = 0; ! 1494: } ! 1495: if(p != NULL) { ! 1496: bp = NULL; ! 1497: p += (unsigned)byte; ! 1498: } ! 1499: else if((bp = getblk((BUFAREA *)NULL,blk+(byte>>BSHIFT(big)))) == NULL) ! 1500: errexit("Fatal I/O error\n"); ! 1501: else ! 1502: p = &bp->b_un.b_buf[(unsigned)(byte&BMASK(big))]; ! 1503: switch(flg&03) { ! 1504: case 0: ! 1505: *p |= n; ! 1506: break; ! 1507: case 1: ! 1508: n &= *p; ! 1509: bp = NULL; ! 1510: break; ! 1511: case 2: ! 1512: *p &= ~n; ! 1513: } ! 1514: if(bp != NULL) ! 1515: dirty(bp); ! 1516: return(n); ! 1517: } ! 1518: ! 1519: ! 1520: dobfree(blk,flg) ! 1521: { ! 1522: } ! 1523: ! 1524: ! 1525: dolncnt(val,flg) ! 1526: short val; ! 1527: { ! 1528: register short *sp; ! 1529: register BUFAREA *bp; ! 1530: ! 1531: if(lncntp != NULL) { ! 1532: bp = NULL; ! 1533: sp = &lncntp[inum]; ! 1534: } ! 1535: else if((bp = getblk((BUFAREA *)NULL,(daddr_t)(lncntblk+(inum/SPERB(big))))) == NULL) ! 1536: errexit("Fatal I/O error\n"); ! 1537: else ! 1538: sp = &bp->b_un.b_lnks[inum%SPERB(big)]; ! 1539: switch(flg) { ! 1540: case 0: ! 1541: *sp = val; ! 1542: break; ! 1543: case 1: ! 1544: bp = NULL; ! 1545: break; ! 1546: case 2: ! 1547: (*sp)--; ! 1548: } ! 1549: if(bp != NULL) ! 1550: dirty(bp); ! 1551: return(*sp); ! 1552: } ! 1553: ! 1554: ! 1555: BUFAREA * ! 1556: getblk(bp,blk) ! 1557: daddr_t blk; ! 1558: register BUFAREA *bp; ! 1559: { ! 1560: register struct filecntl *fcp; ! 1561: ! 1562: if(bp == NULL) { ! 1563: bp = search(blk); ! 1564: fcp = &sfile; ! 1565: } ! 1566: else ! 1567: fcp = &dfile; ! 1568: if(bp->b_bno == blk) ! 1569: return(bp); ! 1570: flush(fcp,bp); ! 1571: if(bread(fcp,bp->b_un.b_buf,blk,BSIZE(big)) != NO) { ! 1572: bp->b_bno = blk; ! 1573: return(bp); ! 1574: } ! 1575: bp->b_bno = (daddr_t)-1; ! 1576: return(NULL); ! 1577: } ! 1578: ! 1579: ! 1580: flush(fcp,bp) ! 1581: struct filecntl *fcp; ! 1582: register BUFAREA *bp; ! 1583: { ! 1584: if(bp->b_dirty) { ! 1585: bwrite(fcp,bp->b_un.b_buf,bp->b_bno,BSIZE(big)); ! 1586: } ! 1587: bp->b_dirty = 0; ! 1588: } ! 1589: ! 1590: ! 1591: rwerr(s,blk) ! 1592: char *s; ! 1593: daddr_t blk; ! 1594: { ! 1595: if (preen == 0) ! 1596: printf("\n"); ! 1597: pfatal("CAN NOT %s: BLK %ld",s,blk); ! 1598: if(reply("CONTINUE") == NO) ! 1599: errexit("Program terminated\n"); ! 1600: } ! 1601: ! 1602: ! 1603: sizechk(dp) ! 1604: register DINODE *dp; ! 1605: { ! 1606: /* ! 1607: if (maxblk != howmany(dp->di_size, BSIZE)) ! 1608: printf("POSSIBLE FILE SIZE ERROR I=%u (%ld,%ld)\n\n", ! 1609: inum, maxblk, howmany(dp->di_size,BSIZE)); ! 1610: */ ! 1611: if(DIR && (dp->di_size % sizeof(DIRECT)) != 0) { ! 1612: pwarn("DIRECTORY MISALIGNED I=%u\n",inum); ! 1613: if (preen == 0) ! 1614: printf("\n"); ! 1615: } ! 1616: } ! 1617: ! 1618: ! 1619: ckfini() ! 1620: { ! 1621: flush(&dfile,&fileblk); ! 1622: flush(&dfile,&sblk); ! 1623: flush(&dfile,&inoblk); ! 1624: close(dfile.rfdes); ! 1625: close(dfile.wfdes); ! 1626: close(sfile.rfdes); ! 1627: close(sfile.wfdes); ! 1628: if(rmscr) { ! 1629: unlink(scrfile); ! 1630: } ! 1631: } ! 1632: ! 1633: ! 1634: pinode() ! 1635: { ! 1636: register DINODE *dp; ! 1637: register char *p; ! 1638: struct passwd *passwd; ! 1639: struct passwd *getpwuid(); ! 1640: char *ctime(); ! 1641: ! 1642: printf(" I=%u ",inum); ! 1643: if((dp = ginode()) == NULL) ! 1644: return; ! 1645: printf(" OWNER="); ! 1646: if((passwd = getpwuid((int)dp->di_uid)) != 0) { ! 1647: printf("%s ", passwd->pw_name); ! 1648: } ! 1649: else { ! 1650: printf("%d ",dp->di_uid); ! 1651: } ! 1652: printf("MODE=%o\n",dp->di_mode); ! 1653: if (preen) ! 1654: printf("%s: ", devname); ! 1655: printf("SIZE=%ld ",dp->di_size); ! 1656: p = ctime(&dp->di_mtime); ! 1657: printf("MTIME=%12.12s %4.4s ",p+4,p+20); ! 1658: } ! 1659: ! 1660: ! 1661: copy(fp,tp,size) ! 1662: register char *tp, *fp; ! 1663: MEMSIZE size; ! 1664: { ! 1665: while(size--) ! 1666: *tp++ = *fp++; ! 1667: } ! 1668: ! 1669: ! 1670: freechk() ! 1671: { ! 1672: register daddr_t *ap; ! 1673: daddr_t blkno; ! 1674: daddr_t bm_blk; ! 1675: daddr_t bitno; ! 1676: ! 1677: n_free = 0; ! 1678: if(big == BIG) { ! 1679: if (m_blks) { ! 1680: blkno = bitno = superblk.s_isize; ! 1681: bm_blk = fmax; ! 1682: memset((char *)bm_buf, 0, BSIZE(BIG)); ! 1683: while(blkno < fmax) { ! 1684: if(!getfmap(blkno++)) { ! 1685: BITFREE(bm_buf, bitno); ! 1686: n_free++; ! 1687: } ! 1688: if(++bitno == BITSPERBLK) { ! 1689: bwrite(&dfile, (char *)bm_buf, bm_blk, BSIZE(BIG)); ! 1690: bm_blk++; ! 1691: memset((char *)bm_buf, 0, BSIZE(BIG)); ! 1692: bitno = 0; ! 1693: } ! 1694: ! 1695: } ! 1696: if(bitno) { ! 1697: bwrite(&dfile, (char *)bm_buf, bm_blk, BSIZE(BIG)); ! 1698: } ! 1699: } ! 1700: else { ! 1701: memset((char *)superblk.s_bfree, 0, BITMAP); ! 1702: for(blkno = superblk.s_isize; blkno < fmax; blkno++) { ! 1703: if(!getfmap(blkno)) { ! 1704: BITFREE(superblk.s_bfree, blkno-superblk.s_isize); ! 1705: n_free++; ! 1706: } ! 1707: } ! 1708: } ! 1709: superblk.s_valid = 1; ! 1710: superblk.s_tfree = n_free; ! 1711: sbdirty(); ! 1712: return; ! 1713: } ! 1714: #ifdef SMALL ! 1715: if(freeblk.df_nfree == 0) ! 1716: return; ! 1717: do { ! 1718: if(freeblk.df_nfree <= 0 || freeblk.df_nfree > NICFREE) { ! 1719: pwarn("BAD FREEBLK COUNT"); ! 1720: printf("\n"); ! 1721: fixfree = 1; ! 1722: return; ! 1723: } ! 1724: ap = &freeblk.df_free[freeblk.df_nfree]; ! 1725: while(--ap > &freeblk.df_free[0]) { ! 1726: if(pass5(*ap) == STOP) ! 1727: return; ! 1728: } ! 1729: if(*ap == (daddr_t)0 || pass5(*ap) != KEEPON) ! 1730: return; ! 1731: } while(getblk(&fileblk,*ap) != NULL); ! 1732: #endif ! 1733: } ! 1734: ! 1735: ! 1736: makefree() ! 1737: { ! 1738: register i, cyl, step; ! 1739: int j; ! 1740: char flg[MAXCYL]; ! 1741: short addr[MAXCYL]; ! 1742: daddr_t blk, baseblk; ! 1743: ! 1744: if(big == BIG) ! 1745: return; ! 1746: #ifdef SMALL ! 1747: superblk.s_nfree = 0; ! 1748: superblk.s_flock = 0; ! 1749: superblk.s_fmod = 0; ! 1750: superblk.s_tfree = 0; ! 1751: superblk.s_ninode = 0; ! 1752: superblk.s_ilock = 0; ! 1753: superblk.s_ronly = 0; ! 1754: if(cylsize == 0 || stepsize == 0) { ! 1755: step = superblk.s_dinfo[0]; ! 1756: cyl = superblk.s_dinfo[1]; ! 1757: } ! 1758: else { ! 1759: step = stepsize; ! 1760: cyl = cylsize; ! 1761: } ! 1762: if(step > cyl || step <= 0 || cyl <= 0 || cyl > MAXCYL) { ! 1763: error("Default free list spacing assumed\n"); ! 1764: step = STEPSIZE; ! 1765: cyl = CYLSIZE; ! 1766: } ! 1767: superblk.s_dinfo[0] = step; ! 1768: superblk.s_dinfo[1] = cyl; ! 1769: clear(flg,sizeof(flg)); ! 1770: i = 0; ! 1771: for(j = 0; j < cyl; j++) { ! 1772: while(flg[i]) ! 1773: i = (i + 1) % cyl; ! 1774: addr[j] = i + 1; ! 1775: flg[i]++; ! 1776: i = (i + step) % cyl; ! 1777: } ! 1778: baseblk = (daddr_t)roundup(fmax,cyl); ! 1779: clear((char *)&freeblk,BSIZE(big)); ! 1780: freeblk.df_nfree++; ! 1781: for( ; baseblk > 0; baseblk -= cyl) ! 1782: for(i = 0; i < cyl; i++) { ! 1783: blk = baseblk - addr[i]; ! 1784: if(!outrange(blk) && !getbmap(blk)) { ! 1785: superblk.s_tfree++; ! 1786: if(freeblk.df_nfree >= NICFREE) { ! 1787: fbdirty(); ! 1788: fileblk.b_bno = blk; ! 1789: flush(&dfile,&fileblk); ! 1790: clear((char *)&freeblk,BSIZE(big)); ! 1791: } ! 1792: freeblk.df_free[freeblk.df_nfree] = blk; ! 1793: freeblk.df_nfree++; ! 1794: } ! 1795: } ! 1796: superblk.s_nfree = freeblk.df_nfree; ! 1797: for(i = 0; i < NICFREE; i++) ! 1798: superblk.s_free[i] = freeblk.df_free[i]; ! 1799: sbdirty(); ! 1800: #endif ! 1801: } ! 1802: ! 1803: ! 1804: clear(p,cnt) ! 1805: register char *p; ! 1806: MEMSIZE cnt; ! 1807: { ! 1808: while(cnt--) ! 1809: *p++ = 0; ! 1810: } ! 1811: ! 1812: ! 1813: BUFAREA * ! 1814: search(blk) ! 1815: daddr_t blk; ! 1816: { ! 1817: register BUFAREA *pbp, *bp; ! 1818: ! 1819: for(bp = (BUFAREA *) &poolhead; bp->b_next; ) { ! 1820: pbp = bp; ! 1821: bp = pbp->b_next; ! 1822: if(bp->b_bno == blk) ! 1823: break; ! 1824: } ! 1825: pbp->b_next = bp->b_next; ! 1826: bp->b_next = poolhead; ! 1827: poolhead = bp; ! 1828: return(bp); ! 1829: } ! 1830: ! 1831: ! 1832: findino(dirp) ! 1833: register DIRECT *dirp; ! 1834: { ! 1835: register char *p1, *p2; ! 1836: ! 1837: if(dirp->d_ino == 0) ! 1838: return(KEEPON); ! 1839: for(p1 = dirp->d_name,p2 = srchname;*p2++ == *p1; p1++) { ! 1840: if(*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) { ! 1841: if(dirp->d_ino > 0 && dirp->d_ino <= imax) ! 1842: parentdir = dirp->d_ino; ! 1843: return(STOP); ! 1844: } ! 1845: } ! 1846: return(KEEPON); ! 1847: } ! 1848: ! 1849: ! 1850: mkentry(dirp) ! 1851: register DIRECT *dirp; ! 1852: { ! 1853: register ino_t in; ! 1854: register char *p; ! 1855: ! 1856: if(dirp->d_ino) ! 1857: return(KEEPON); ! 1858: dirp->d_ino = orphan; ! 1859: in = orphan; ! 1860: p = &dirp->d_name[8]; ! 1861: *--p = 0; ! 1862: while(p > dirp->d_name) { ! 1863: *--p = (in % 10) + '0'; ! 1864: in /= 10; ! 1865: } ! 1866: *p = '#'; ! 1867: return(ALTERD|STOP); ! 1868: } ! 1869: ! 1870: ! 1871: chgdd(dirp) ! 1872: register DIRECT *dirp; ! 1873: { ! 1874: if(dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && ! 1875: dirp->d_name[2] == 0) { ! 1876: dirp->d_ino = lfdir; ! 1877: return(ALTERD|STOP); ! 1878: } ! 1879: return(KEEPON); ! 1880: } ! 1881: ! 1882: ! 1883: linkup() ! 1884: { ! 1885: register DINODE *dp; ! 1886: register lostdir; ! 1887: register ino_t pdir; ! 1888: ! 1889: if((dp = ginode()) == NULL) ! 1890: return(NO); ! 1891: lostdir = DIR; ! 1892: pdir = parentdir; ! 1893: if (preen && dp->di_size == 0) ! 1894: return(NO); ! 1895: pwarn("UNREF %s ",lostdir ? "DIR" : "FILE"); ! 1896: pinode(); ! 1897: if (preen) ! 1898: printf(" (RECONNECTED)\n"); ! 1899: else ! 1900: if (reply("RECONNECT") == NO) ! 1901: return(NO); ! 1902: orphan = inum; ! 1903: if(lfdir == 0) { ! 1904: inum = ROOTINO; ! 1905: if((dp = ginode()) == NULL) { ! 1906: inum = orphan; ! 1907: return(NO); ! 1908: } ! 1909: pfunc = findino; ! 1910: srchname = lfname; ! 1911: filsize = dp->di_size; ! 1912: parentdir = 0; ! 1913: ckinode(dp,DATA); ! 1914: inum = orphan; ! 1915: if((lfdir = parentdir) == 0) { ! 1916: pfatal("SORRY. NO lost+found DIRECTORY"); ! 1917: printf("\n\n"); ! 1918: return(NO); ! 1919: } ! 1920: } ! 1921: inum = lfdir; ! 1922: if((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) { ! 1923: inum = orphan; ! 1924: pfatal("SORRY. NO lost+found DIRECTORY"); ! 1925: printf("\n\n"); ! 1926: return(NO); ! 1927: } ! 1928: if(dp->di_size & BMASK(big)) { ! 1929: dp->di_size = roundup(dp->di_size,BSIZE(big)); ! 1930: inodirty(); ! 1931: } ! 1932: filsize = dp->di_size; ! 1933: inum = orphan; ! 1934: pfunc = mkentry; ! 1935: if((ckinode(dp,DATA) & ALTERD) == 0) { ! 1936: pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); ! 1937: printf("\n\n"); ! 1938: return(NO); ! 1939: } ! 1940: declncnt(); ! 1941: if(lostdir) { ! 1942: pfunc = chgdd; ! 1943: dp = ginode(); ! 1944: filsize = dp->di_size; ! 1945: ckinode(dp,DATA); ! 1946: inum = lfdir; ! 1947: if((dp = ginode()) != NULL) { ! 1948: dp->di_nlink++; ! 1949: inodirty(); ! 1950: setlncnt(getlncnt()+1); ! 1951: } ! 1952: inum = orphan; ! 1953: pwarn("DIR I=%u CONNECTED. ",orphan); ! 1954: printf("PARENT WAS I=%u\n",pdir); ! 1955: if (preen == 0) ! 1956: printf("\n"); ! 1957: } ! 1958: return(YES); ! 1959: } ! 1960: ! 1961: ! 1962: bread(fcp,buf,blk,size) ! 1963: daddr_t blk; ! 1964: register struct filecntl *fcp; ! 1965: register size; ! 1966: char *buf; ! 1967: { ! 1968: if(lseek(fcp->rfdes,blk<<BSHIFT(big),0) < 0) ! 1969: rwerr("SEEK",blk); ! 1970: else if(read(fcp->rfdes,buf,size) == size) ! 1971: return(YES); ! 1972: rwerr("READ",blk); ! 1973: return(NO); ! 1974: } ! 1975: ! 1976: ! 1977: bwrite(fcp,buf,blk,size) ! 1978: daddr_t blk; ! 1979: register struct filecntl *fcp; ! 1980: register size; ! 1981: char *buf; ! 1982: { ! 1983: if(fcp->wfdes < 0) ! 1984: return(NO); ! 1985: if(lseek(fcp->wfdes,blk<<BSHIFT(big),0) < 0) ! 1986: rwerr("SEEK",blk); ! 1987: else if(write(fcp->wfdes,buf,size) == size) { ! 1988: fcp->mod = 1; ! 1989: return(YES); ! 1990: } ! 1991: rwerr("WRITE",blk); ! 1992: return(NO); ! 1993: } ! 1994: ! 1995: void ! 1996: catch(int signo) ! 1997: { ! 1998: ckfini(); ! 1999: exit(12); ! 2000: } ! 2001: /* ! 2002: * Convert longs to and from 3-byte disk addresses ! 2003: */ ! 2004: /* ! 2005: void ! 2006: ltol3(char *cp, long *lp, int n) ! 2007: { ! 2008: int i; ! 2009: char *a, *b; ! 2010: ! 2011: a = cp; ! 2012: b = (char *)lp; ! 2013: for (i = 0; i < n; i++) { ! 2014: b++; ! 2015: *a++ = *b++; ! 2016: *a++ = *b++; ! 2017: *a++ = *b++; ! 2018: } ! 2019: } ! 2020: ! 2021: void ! 2022: l3tol(long *lp, char *cp, int n) ! 2023: { ! 2024: int i; ! 2025: char *a, *b; ! 2026: ! 2027: a = (char *)lp; ! 2028: b = cp; ! 2029: for (i = 0; i < n; i++) { ! 2030: *a++ = 0; ! 2031: *a++ = *b++; ! 2032: *a++ = *b++; ! 2033: *a++ = *b++; ! 2034: } ! 2035: } ! 2036: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.