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