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