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