|
|
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.